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 +----------------------------------------------------------------------+
19 #include "hphp/runtime/vm/jit/cg-meta.h"
20 #include "hphp/runtime/vm/jit/containers.h"
21 #include "hphp/runtime/vm/jit/types.h"
22 #include "hphp/runtime/vm/jit/vasm-text.h"
23 #include "hphp/runtime/vm/jit/vasm-unit.h"
24 #include "hphp/runtime/vm/jit/vasm.h"
26 #include "hphp/util/data-block.h"
28 #include <boost/type_traits.hpp>
31 ///////////////////////////////////////////////////////////////////////////////
37 ///////////////////////////////////////////////////////////////////////////////
40 * Writer stream for adding instructions to a Vblock.
43 Vout(Vunit
& u
, Vlabel b
,
44 Optional
<Vinstr::ir_context
> irctx
= std::nullopt
)
47 , m_irctx ( irctx
? *irctx
48 : Vinstr::ir_context
{ nullptr, Vinstr::kInvalidVoff
} )
51 Vout(Vout
&&) = default;
52 Vout(const Vout
&) = delete;
54 Vout
& operator=(const Vout
&);
55 Vout
& operator=(Vlabel
);
58 * Implicit cast to label for initializing branch instructions.
60 /* implicit */ operator Vlabel() const;
63 * Instruction emitter.
65 Vout
& operator<<(const Vinstr
& inst
);
68 * Create a stream connected to a new empty block.
72 /////////////////////////////////////////////////////////////////////////////
75 * Whether the stream is empty or terminated (because a block-terminating
76 * instruction has been emitted).
82 * Return the managed Vunit.
84 Vunit
& unit() { return m_unit
; }
87 * Return the code area of the currently-managed block.
89 AreaIndex
area() const;
92 * Set the current block and Vinstr origin.
94 void use(Vlabel b
) { m_block
= b
; }
95 void setOrigin(const IRInstruction
* i
) { m_irctx
.origin
= i
; }
97 const IRInstruction
* getOrigin() const { return m_irctx
.origin
; }
100 * Add a scaling factor. The weight of the current block and all
101 * future blocks created from this Vout will be multiplied by the
102 * total scaling factor.
104 void addWeightScale(uint64_t);
111 Vtuple
makeTuple(const VregList
& regs
) const;
112 Vtuple
makeTuple(VregList
&& regs
) const;
113 VcallArgsId
makeVcallArgs(VcallArgs
&& args
) const;
114 template<class T
> Vreg
cns(T v
);
115 template<class T
, class... Args
> T
* allocData(Args
&&... args
);
118 Vout(Vunit
& u
, Vlabel b
, Vinstr::ir_context irctx
, uint64_t scale
)
122 , m_weight_scale
{scale
} {}
126 Vinstr::ir_context m_irctx
;
127 uint64_t m_weight_scale
= 1;
130 ///////////////////////////////////////////////////////////////////////////////
135 * A Vasm manages Vout streams for a Vunit.
138 explicit Vasm(Vunit
& unit
) : m_unit(unit
) { m_outs
.reserve(kNumAreas
); }
141 * Obtain the managed Vunit.
143 Vunit
& unit() { return m_unit
; }
146 * Get or create the stream for the corresponding Varea.
148 Vout
& main() { return out(AreaIndex::Main
); }
149 Vout
& cold() { return out(AreaIndex::Cold
); }
150 Vout
& frozen() { return out(AreaIndex::Frozen
); }
153 Vout
& out(AreaIndex i
);
157 jit::vector
<Vout
> m_outs
; // one for each AreaIndex
160 ///////////////////////////////////////////////////////////////////////////////
163 * Helper for emitting small amounts of machine code using vasm.
165 * Vauto manages a Vunit with a single area. When the Vauto goes out of scope,
166 * it will finalize and emit any code it contains.
169 explicit Vauto(CodeBlock
& main
, CodeBlock
& cold
, DataBlock
& data
,
170 CGMeta
& fixups
, CodeKind kind
= CodeKind::Helper
,
171 const char* name
= nullptr,
172 bool relocate
= false, bool* wasFull
= nullptr)
173 : m_text
{main
, cold
, data
}
175 , m_main
{m_unit
, m_unit
.makeBlock(AreaIndex::Main
)}
176 , m_cold
{m_unit
, m_unit
.makeBlock(AreaIndex::Cold
)}
178 , m_relocate
{relocate
}
181 m_unit
.entry
= Vlabel(this->main());
185 Vunit
& unit() { return m_unit
; }
186 Vout
& main() { return m_main
; }
187 Vout
& cold() { return m_cold
; }
203 template<class GenFunc
>
204 TCA
vwrap_impl(CodeBlock
& main
, CodeBlock
& cold
, DataBlock
& data
,
205 CGMeta
* meta
, GenFunc gen
,
207 CodeKind kind
= CodeKind::CrossTrace
,
208 bool relocate
= true,
209 bool nullOnFull
= false);
213 * Convenience wrappers around Vauto for cross-trace or helper code.
215 * The relocate parameter attempts to generate code into a temporary
216 * buffer allocated from cb, and then relocate it to the start of cb -
217 * which can reduce the code size. If there isn't enough room in cb,
218 * the parameter will be ignored.
220 template<class GenFunc
>
221 TCA
vwrap(CodeBlock
& cb
, DataBlock
& data
, CGMeta
& meta
, GenFunc gen
,
222 const char* name
= nullptr,
223 CodeKind kind
= CodeKind::CrossTrace
, bool relocate
= true) {
224 return detail::vwrap_impl(cb
, cb
, data
, &meta
,
225 [&] (Vout
& v
, Vout
&) { gen(v
); }, name
,
228 template<class GenFunc
>
229 TCA
vwrap(CodeBlock
& cb
, DataBlock
& data
, GenFunc gen
,
230 const char* name
= nullptr,
231 bool relocate
= true, bool nullOnFull
= false) {
232 return detail::vwrap_impl(cb
, cb
, data
, nullptr,
233 [&] (Vout
& v
, Vout
&) { gen(v
); },
234 name
, CodeKind::CrossTrace
, relocate
, nullOnFull
);
236 template<class GenFunc
>
237 TCA
vwrap2(CodeBlock
& main
, CodeBlock
& cold
, DataBlock
& data
,
238 CGMeta
& meta
, GenFunc gen
, const char* name
= nullptr) {
239 return detail::vwrap_impl(main
, cold
, data
, &meta
, gen
, name
);
241 template<class GenFunc
>
242 TCA
vwrap2(CodeBlock
& main
, CodeBlock
& cold
, DataBlock
& data
, GenFunc gen
,
243 const char* name
= nullptr) {
244 return detail::vwrap_impl(main
, cold
, data
, nullptr, gen
, name
);
248 * Multiplying factors used to compute the block weights for each code area.
249 * We multiply the corresponding IR block's profile counter by the following
250 * factors, depending on the code area the block is assigned to.
252 uint64_t areaWeightFactor(AreaIndex area
);
254 ///////////////////////////////////////////////////////////////////////////////
257 #include "hphp/runtime/vm/jit/vasm-gen-inl.h"