2 +----------------------------------------------------------------------+
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010-2014 Facebook, Inc. (http://www.facebook.com) |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 3.01 of the PHP license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | http://www.php.net/license/3_01.txt |
11 | If you did not receive a copy of the PHP license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@php.net so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
16 #ifndef incl_HPHP_TRACELET_H_
17 #define incl_HPHP_TRACELET_H_
19 #include <boost/ptr_container/ptr_vector.hpp>
22 #include "hphp/runtime/vm/jit/runtime-type.h"
27 struct NormalizedInstruction
;
30 * A tracelet is a unit of input to the back-end. It is a partially typed,
31 * non-maximal basic block, representing the next slice of the program to
33 * It is a consecutive set of instructions, only the last of which may be a
34 * transfer of control, annotated types and locations for each opcode's input
37 typedef hphp_hash_map
<Location
, DynLocation
*, Location
> ChangeMap
;
38 typedef ChangeMap DepMap
;
41 InstrStream() : first(nullptr), last(nullptr) {}
42 void append(NormalizedInstruction
* ni
);
43 void remove(NormalizedInstruction
* ni
);
44 NormalizedInstruction
* first
;
45 NormalizedInstruction
* last
;
50 std::vector
<bool> m_mask
;
51 std::vector
<bool> m_vals
;
53 std::string
pretty() const {
54 std::ostringstream out
;
56 for (size_t i
= 0; i
< m_mask
.size(); ++i
) {
57 out
<< (m_mask
[i
] ? "1" : "0");
60 for (size_t i
= 0; i
< m_vals
.size(); ++i
) {
61 out
<< (m_vals
[i
] ? "1" : "0");
66 typedef hphp_hash_map
<int64_t, Record
, int64_hash
> ArMap
;
71 void addDep(int entryArDelta
, unsigned argNum
, bool isRef
) {
72 if (m_arMap
.find(entryArDelta
) == m_arMap
.end()) {
73 m_arMap
[entryArDelta
] = Record();
75 Record
& r
= m_arMap
[entryArDelta
];
76 if (argNum
>= r
.m_mask
.size()) {
77 assert(argNum
>= r
.m_vals
.size());
78 r
.m_mask
.resize(argNum
+ 1);
79 r
.m_vals
.resize(argNum
+ 1);
81 r
.m_mask
[argNum
] = true;
82 r
.m_vals
[argNum
] = isRef
;
86 return m_arMap
.size();
91 // State for tracking function param reffiness. m_topFunc is the function
92 // for the activation record that is closest to the top of the stack, or
93 // NULL if it is currently unknown. A tracelet can be in one of three
94 // epistemological states: GUESSABLE, KNOWN, and UNKNOWABLE. We start out in
95 // GUESSABLE, with m_topFunc == NULL (not yet guessed); when it's time to
96 // guess, we will use the ActRec seen on the top of stack at compilation
97 // time as a hint for refs going forward.
99 // The KNOWN state is a very strong guarantee. It means that no matter when
100 // this tracelet is executed, no matter what else has happened, the ActRec
101 // closest to the top of the stack WILL contain m_topFunc. This means: if that
102 // function is defined conditionally, or defined in some other module, you
103 // cannot correctly make that assertion. KNOWN indicates absolute certainty
104 // about all possible futures.
106 // This strange "not-guessed-yet-but-could" state is required by our
107 // VM design; at present, the ActRec is not easily recoverable from an
108 // arbitrary instruction boundary. However, it can be recovered from the
109 // instructions that need to do so.
110 static const int InvalidEntryArDelta
= INT_MAX
;
113 GUESSABLE
, KNOWN
, UNKNOWABLE
118 const Func
* m_topFunc
;
119 int m_entryArDelta
; // delta at BB entry to guessed ActRec.
122 std::vector
<Record
> m_arStack
;
125 void pushFunc(const NormalizedInstruction
& ni
);
126 void pushFuncD(const Func
* func
);
129 bool checkByRef(int argNum
, int stackOffset
, RefDeps
* outRefDeps
);
130 const Func
* knownFunc();
131 State
currentState();
134 struct Tracelet
: private boost::noncopyable
{
136 DepMap m_dependencies
;
137 DepMap m_resolvedDeps
; // dependencies resolved by static analysis
138 InstrStream m_instrStream
;
141 // SrcKey for the start of the Tracelet. This will be the same as
142 // m_instrStream.first->source.
145 // numOpcodes is the number of raw opcode instructions, before optimization.
146 // The immediates optimization may both:
148 // 1. remove the first opcode, thus making
149 // sk.instr != instrs.first->source.instr
150 // 2. remove no longer needed instructions
153 // Assumptions about entering actRec's reffiness.
154 ActRecState m_arState
;
158 * If we were unable to make sense of the instruction stream (e.g., it
159 * used instructions that the translator does not understand), then this
160 * tracelet is useful only for defining the boundaries of a basic block.
161 * The low-level translator can handle this by backing off to the
162 * bytecode interpreter.
164 bool m_analysisFailed
;
167 * If IR inlining failed we may still need access to the trace for profiling
168 * purposes if stats are enabled so maintain this to verify that we should use
169 * this Tracelet for inlining purposes.
171 bool m_inliningFailed
;
173 // Track which NormalizedInstructions and DynLocations are owned by this
174 // Tracelet; used for cleanup purposes
175 boost::ptr_vector
<NormalizedInstruction
> m_instrs
;
176 boost::ptr_vector
<DynLocation
> m_dynlocs
;
181 NormalizedInstruction
* newNormalizedInstruction();
182 DynLocation
* newDynLocation(Location l
, DataType t
);
183 DynLocation
* newDynLocation(Location l
, RuntimeType t
);
184 DynLocation
* newDynLocation();
186 /* These aren't merged into a single method with a default argument
187 * to make gdb happy. */
189 void print(std::ostream
& out
) const;
190 std::string
toString() const;
192 SrcKey
nextSk() const;
193 const Func
* func() const;