2 +----------------------------------------------------------------------+
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"
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.
45 explicit Vblock(AreaIndex area_idx
, uint64_t w
)
51 int pending_frames
{-1};
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.
67 ///////////////////////////////////////////////////////////////////////////////
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
77 * Also contains convenience constructors for various pointer and enum types.
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
) {}
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
);
117 size_t operator()(Vconst c
) const {
119 std::hash
<uint64_t>()(c
.val
) ^ std::hash
<int>()(c
.kind
) ^ c
.isUndef
;
123 /////////////////////////////////////////////////////////////////////////////
140 uint64_t entry_weight
144 , entry_weight(entry_weight
)
145 , inclusive_cost(cost
)
146 , exclusive_cost(cost
)
154 static constexpr int Top
= -1;
156 LowPtr
<const Func
> func
;
160 uint64_t entry_weight
;
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.
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
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.
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
]);
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 /////////////////////////////////////////////////////////////////////////////
243 unsigned next_vr
{Vreg::V0
};
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
254 bool profiling
{false};
255 folly::Optional
<TransContext
> context
;
256 StructuredLogEntry
* log_entry
{nullptr};
259 ///////////////////////////////////////////////////////////////////////////////