Rename RefcountProfile to IncRefProfile
[hiphop-php.git] / hphp / runtime / vm / jit / vasm-unit.h
blob02cc6a837f5f9d576bdf322211b0f341e493a5a4
1 /*
2 +----------------------------------------------------------------------+
3 | HipHop for PHP |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010-present 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 +----------------------------------------------------------------------+
17 #ifndef incl_HPHP_JIT_VASM_UNIT_H_
18 #define incl_HPHP_JIT_VASM_UNIT_H_
20 #include "hphp/runtime/base/datatype.h"
22 #include "hphp/runtime/vm/jit/types.h"
23 #include "hphp/runtime/vm/jit/containers.h"
24 #include "hphp/runtime/vm/jit/vasm.h"
25 #include "hphp/runtime/vm/jit/vasm-data.h"
26 #include "hphp/runtime/vm/jit/vasm-instr.h"
27 #include "hphp/runtime/vm/jit/vasm-reg.h"
29 #include "hphp/util/data-block.h"
30 #include "hphp/util/immed.h"
32 #include <functional>
33 #include <type_traits>
35 namespace HPHP { namespace jit {
36 ///////////////////////////////////////////////////////////////////////////////
39 * Block of Vinstrs, managed by Vunit.
41 * A Vblock, in addition to containing a Vinstr stream, also specifies where it
42 * should be emitted to.
44 struct Vblock {
45 explicit Vblock(AreaIndex area_idx, uint64_t w)
46 : area_idx(area_idx)
47 , weight(w) {}
49 AreaIndex area_idx;
50 int frame{-1};
51 int pending_frames{-1};
52 uint64_t weight;
53 jit::vector<Vinstr> code;
57 * Source operands for vcall/vinvoke instructions, packed into a struct for
58 * convenience and to keep the instructions compact.
60 struct VcallArgs {
61 VregList args;
62 VregList simdArgs;
63 VregList stkArgs;
64 VregList indRetArgs;
67 ///////////////////////////////////////////////////////////////////////////////
70 * Vasm constant.
72 * Either a 1, 4, or 8 byte unsigned value, 8 byte double, or the disp32 part
73 * of a thread-local address of an immutable constant that varies by thread.
74 * Constants may also represent an undefined value, indicated by the isUndef
75 * member.
77 * Also contains convenience constructors for various pointer and enum types.
79 struct Vconst {
80 enum Kind { Quad, Long, Byte, Double };
82 using ullong = unsigned long long;
83 using ulong = unsigned long;
85 Vconst() : kind(Quad), val(0) {}
86 explicit Vconst(Kind k) : kind(k), isUndef(true), val(0) {}
87 explicit Vconst(bool b) : kind(Byte), val(b) {}
88 explicit Vconst(uint8_t b) : kind(Byte), val(b) {}
89 explicit Vconst(int8_t b) : Vconst(uint8_t(b)) {}
90 explicit Vconst(uint32_t i) : kind(Long), val(i) {}
91 // For historical reasons Vconst(int) produces an 8-byte constant.
92 explicit Vconst(int32_t i) : Vconst(int64_t(i)) {}
93 explicit Vconst(uint16_t) = delete;
94 explicit Vconst(int16_t) = delete;
95 explicit Vconst(ullong i) : kind(Quad), val(i) {}
96 explicit Vconst(long long i) : Vconst(ullong(i)) {}
97 explicit Vconst(ulong i) : Vconst(ullong(i)) {}
98 explicit Vconst(long i) : Vconst(ullong(i)) {}
99 explicit Vconst(const void* p) : Vconst(uintptr_t(p)) {}
100 explicit Vconst(double d) : kind(Double), doubleVal(d) {}
102 template<
103 class E,
104 class Enable = typename std::enable_if<std::is_enum<E>::value>::type
106 explicit Vconst(E e) : Vconst(typename std::underlying_type<E>::type(e)) {}
108 template<class R, class... Args>
109 explicit Vconst(R (*fn)(Args...)) : Vconst(uintptr_t(fn)) {}
111 bool operator==(Vconst other) const {
112 return kind == other.kind &&
113 ((isUndef && other.isUndef) || val == other.val);
116 struct Hash {
117 size_t operator()(Vconst c) const {
118 return
119 std::hash<uint64_t>()(c.val) ^ std::hash<int>()(c.kind) ^ c.isUndef;
123 /////////////////////////////////////////////////////////////////////////////
124 // Data members.
126 Kind kind;
127 bool isUndef{false};
128 union {
129 uint64_t val;
130 double doubleVal;
134 struct Vframe {
135 Vframe(
136 const Func* func,
137 int32_t soff,
138 int parent,
139 int cost,
140 uint64_t entry_weight
141 ) : func(func)
142 , soff(soff)
143 , parent(parent)
144 , entry_weight(entry_weight)
145 , inclusive_cost(cost)
146 , exclusive_cost(cost)
149 struct Section {
150 size_t inclusive{0};
151 size_t exclusive{0};
154 static constexpr int Top = -1;
156 LowPtr<const Func> func;
157 int32_t soff{-1};
158 int parent;
160 uint64_t entry_weight;
161 int inclusive_cost;
162 int exclusive_cost;
164 int num_inner_frames{0};
166 jit::array<Section, kNumAreas> sections;
169 ///////////////////////////////////////////////////////////////////////////////
172 * A Vunit contains all the assets that make up a vasm compilation unit. It is
173 * responsible for allocating new blocks, Vregs, and tuples.
175 struct Vunit {
177 * Create a new block in the given area and weight, returning its id.
179 Vlabel makeBlock(AreaIndex area, uint64_t weight);
182 * Create a block intended to be used temporarily, as part of modifying
183 * existing code.
185 * Although not necessary for correctness, the block may be freed with
186 * freeScratchBlock when finished.
188 Vlabel makeScratchBlock();
191 * Free a scratch block when finished with it. There must be no references
192 * to this block in reachable code.
194 void freeScratchBlock(Vlabel);
196 /////////////////////////////////////////////////////////////////////////////
199 * Make various Vunit-managed vasm structures.
201 Vreg makeReg() { return Vreg{next_vr++}; }
202 Vtuple makeTuple(VregList&& regs);
203 Vtuple makeTuple(const VregList& regs);
204 VcallArgsId makeVcallArgs(VcallArgs&& args);
207 * Create or return a register representing the given constant value.
209 Vreg makeConst(Vconst);
210 template<typename T> Vreg makeConst(T v) { return makeConst(Vconst{v}); }
213 * Allocate a block of data to hold n objects of type T.
215 * Any instructions with VdataPtr members that point inside the buffer
216 * returned by allocData() will automatically be fixed up during a relocation
217 * pass immediately before final code emission.
219 template<typename T>
220 T* allocData(size_t n = 1) {
221 auto const size = sizeof(T) * n;
222 dataBlocks.emplace_back();
224 auto& block = dataBlocks.back();
225 block.data.reset(new uint8_t[size]);
226 block.size = size;
227 block.align = alignof(T);
228 return (T*)block.data.get();
231 /////////////////////////////////////////////////////////////////////////////
234 * Return true iff this Vunit needs register allocation before it can be
235 * emitted, either because it uses virtual registers or contains instructions
236 * that must be lowered by xls.
238 bool needsRegAlloc() const;
240 /////////////////////////////////////////////////////////////////////////////
241 // Data members.
243 unsigned next_vr{Vreg::V0};
244 Vlabel entry;
245 jit::vector<Vframe> frames;
246 jit::vector<Vblock> blocks;
247 jit::hash_map<Vconst,Vreg,Vconst::Hash> constToReg;
248 jit::hash_map<size_t,Vconst> regToConst;
249 jit::vector<VregList> tuples;
250 jit::vector<VcallArgs> vcallArgs;
251 jit::vector<VdataBlock> dataBlocks;
252 uint16_t cur_voff{0}; // current instruction index managed by Vout
253 bool padding{false};
254 bool profiling{false};
255 folly::Optional<TransContext> context;
256 StructuredLogEntry* log_entry{nullptr};
259 ///////////////////////////////////////////////////////////////////////////////
262 #endif