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 +----------------------------------------------------------------------+
17 #ifndef incl_HPHP_TRANSLATOR_INLINE_H_
18 #define incl_HPHP_TRANSLATOR_INLINE_H_
20 #include "hphp/runtime/vm/jit/translator.h"
21 #include "hphp/runtime/vm/jit/translator-helpers.h"
22 #include <boost/noncopyable.hpp>
23 #include "hphp/runtime/base/execution-context.h"
25 #define TVOFF(nm) offsetof(TypedValue, nm)
26 #define AROFF(nm) offsetof(ActRec, nm)
29 * Because of a circular dependence with ExecutionContext, these
30 * translation-related helpers cannot live in translator.h.
35 * Accessors for the virtual machine registers, both rvalues and
38 * Note that these do not assert anything about tl_regState; use
41 inline Cell
*& vmsp() { return (Cell
*&)g_context
->m_stack
.top(); }
42 inline Cell
*& vmfp() { return (Cell
*&)g_context
->m_fp
; }
43 inline const unsigned char*& vmpc() { return g_context
->m_pc
; }
44 inline ActRec
*& vmFirstAR() { return g_context
->m_firstAR
; }
46 inline ActRec
* liveFrame() { return (ActRec
*)vmfp(); }
47 inline const Func
* liveFunc() { return liveFrame()->m_func
; }
48 inline const Unit
* liveUnit() { return liveFunc()->unit(); }
49 inline Class
* liveClass() { return liveFunc()->cls(); }
51 inline Offset
liveSpOff() {
53 if (liveFrame()->inGenerator()) {
54 fp
= (Cell
*)Stack::generatorStackBase((ActRec
*)fp
);
61 inline bool isNativeImplCall(const Func
* funcd
, int numArgs
) {
62 return funcd
&& funcd
->methInfo() && numArgs
== funcd
->numParams();
65 inline ptrdiff_t cellsToBytes(int nCells
) {
66 return nCells
* sizeof(Cell
);
69 inline int64_t localOffset(int64_t locId
) {
70 return -cellsToBytes(locId
+ 1);
73 inline void assert_native_stack_aligned() {
75 assert(reinterpret_cast<uintptr_t>(__builtin_frame_address(0)) % 16 == 0);
79 struct VMRegAnchor
: private boost::noncopyable
{
82 assert_native_stack_aligned();
86 explicit VMRegAnchor(ActRec
* ar
) {
87 // Some C++ entry points have an ActRec prepared from after a call
88 // instruction. This syncs us to right after the call instruction.
89 assert(tl_regState
== VMRegState::DIRTY
);
90 m_old
= VMRegState::DIRTY
;
91 tl_regState
= VMRegState::CLEAN
;
93 auto prevAr
= g_context
->getOuterVMFrame(ar
);
94 const Func
* prevF
= prevAr
->m_func
;
95 vmsp() = ar
->inGenerator() ?
96 Stack::generatorStackBase(ar
) - 1 :
97 (TypedValue
*)ar
- ar
->numArgs();
98 assert(g_context
->m_stack
.isValidAddress((uintptr_t)vmsp()));
99 vmpc() = prevF
->unit()->at(prevF
->base() + ar
->m_soff
);
100 vmfp() = (TypedValue
*)prevAr
;
107 struct EagerVMRegAnchor
{
111 DEBUG_ONLY
const Cell
* fp
= vmfp();
112 DEBUG_ONLY
const Cell
* sp
= vmsp();
113 DEBUG_ONLY
const auto* pc
= vmpc();
115 assert(vmfp() == fp
&& vmsp() == sp
&& vmpc() == pc
);
118 tl_regState
= VMRegState::CLEAN
;
120 ~EagerVMRegAnchor() {
125 inline ActRec
* regAnchorFP(Offset
* pc
= nullptr) {
126 // In builtins, m_fp points to the caller's frame if called
127 // through FCallBuiltin, else it points to the builtin's frame,
128 // in which case, getPrevVMState() gets the caller's frame.
129 // In addition, we need to skip over php-defined builtin functions
130 // in order to find the true context.
131 auto const context
= g_context
.getNoCheck();
132 auto cur
= context
->getFP();
133 if (pc
) *pc
= cur
->m_func
->unit()->offsetOf(context
->getPC());
134 while (cur
&& cur
->skipFrame()) {
135 cur
= context
->getPrevVMState(cur
, pc
);
140 inline ActRec
* regAnchorFPForArgs() {
141 // Like regAnchorFP, but only account for FCallBuiltin
142 auto const context
= g_context
.getNoCheck();
143 ActRec
* cur
= context
->getFP();
144 if (cur
&& cur
->m_func
->isCPPBuiltin()) {
145 cur
= context
->getPrevVMState(cur
);
150 struct EagerCallerFrame
: public EagerVMRegAnchor
{
151 ActRec
* operator()() {
152 return regAnchorFP();
154 ActRec
* actRecForArgs() { return regAnchorFPForArgs(); }
158 // VM helper to retrieve the frame pointer from the TC. This is
159 // a common need for extensions.
160 struct CallerFrame
: public VMRegAnchor
{
161 template<class... Args
>
162 ActRec
* operator()(Args
&&... args
) {
163 return regAnchorFP(std::forward
<Args
>(args
)...);
165 ActRec
* actRecForArgs() { return regAnchorFPForArgs(); }
168 #define SYNC_VM_REGS_SCOPED() \
169 HPHP::JIT::VMRegAnchor _anchorUnused