remove operator-> from String
[hiphop-php.git] / hphp / runtime / vm / jit / tracelet.h
blob8ecdcdc3477f21e45989e67081f3ea6f06ca34e7
1 /*
2 +----------------------------------------------------------------------+
3 | HipHop for PHP |
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>
20 #include <vector>
22 #include "hphp/runtime/vm/jit/runtime-type.h"
24 namespace HPHP {
25 namespace JIT {
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
32 * be executed.
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
35 * and output.
37 typedef hphp_hash_map<Location, DynLocation*, Location> ChangeMap;
38 typedef ChangeMap DepMap;
40 struct InstrStream {
41 InstrStream() : first(nullptr), last(nullptr) {}
42 void append(NormalizedInstruction* ni);
43 void remove(NormalizedInstruction* ni);
44 NormalizedInstruction* first;
45 NormalizedInstruction* last;
48 struct RefDeps {
49 struct Record {
50 std::vector<bool> m_mask;
51 std::vector<bool> m_vals;
53 std::string pretty() const {
54 std::ostringstream out;
55 out << "mask=";
56 for (size_t i = 0; i < m_mask.size(); ++i) {
57 out << (m_mask[i] ? "1" : "0");
59 out << " vals=";
60 for (size_t i = 0; i < m_vals.size(); ++i) {
61 out << (m_vals[i] ? "1" : "0");
63 return out.str();
66 typedef hphp_hash_map<int64_t, Record, int64_hash> ArMap;
67 ArMap m_arMap;
69 RefDeps() {}
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;
85 size_t size() const {
86 return m_arMap.size();
90 struct ActRecState {
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;
112 enum class State {
113 GUESSABLE, KNOWN, UNKNOWABLE
116 struct Record {
117 State m_state;
118 const Func* m_topFunc;
119 int m_entryArDelta; // delta at BB entry to guessed ActRec.
122 std::vector<Record> m_arStack;
124 ActRecState() {}
125 void pushFunc(const NormalizedInstruction& ni);
126 void pushFuncD(const Func* func);
127 void pushDynFunc();
128 void pop();
129 bool checkByRef(int argNum, int stackOffset, RefDeps* outRefDeps);
130 const Func* knownFunc();
131 State currentState();
134 struct Tracelet : private boost::noncopyable {
135 ChangeMap m_changes;
136 DepMap m_dependencies;
137 DepMap m_resolvedDeps; // dependencies resolved by static analysis
138 InstrStream m_instrStream;
139 int m_stackChange;
141 // SrcKey for the start of the Tracelet. This will be the same as
142 // m_instrStream.first->source.
143 SrcKey m_sk;
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
151 int m_numOpcodes;
153 // Assumptions about entering actRec's reffiness.
154 ActRecState m_arState;
155 RefDeps m_refDeps;
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;
178 Tracelet();
179 ~Tracelet();
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. */
188 void print() const;
189 void print(std::ostream& out) const;
190 std::string toString() const;
192 SrcKey nextSk() const;
193 const Func* func() const;
196 } } // HPHP::JIT
197 #endif