Remove VariantStrongBind and CVarStrongBind
[hiphop-php.git] / hphp / runtime / vm / jit / translator-inline.h
blobae21c3fdccb410d3f5b0e7756d404f327366b042
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 +----------------------------------------------------------------------+
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"
26 * Because of a circular dependence with ExecutionContext, these
27 * translation-related helpers cannot live in translator.h.
29 namespace HPHP {
32 * Accessors for the virtual machine registers, both rvalues and
33 * lvalues.
35 * Note that these do not assert anything about tl_regState; use
36 * carefully.
38 inline Cell*& vmsp() { return (Cell*&)g_context->m_stack.top(); }
39 inline Cell*& vmfp() { return (Cell*&)g_context->m_fp; }
40 inline const unsigned char*& vmpc() { return g_context->m_pc; }
41 inline ActRec*& vmFirstAR() { return g_context->m_firstAR; }
43 inline ActRec* liveFrame() { return (ActRec*)vmfp(); }
44 inline const Func* liveFunc() { return liveFrame()->m_func; }
45 inline const Unit* liveUnit() { return liveFunc()->unit(); }
46 inline Class* liveClass() { return liveFunc()->cls(); }
47 inline bool liveResumed() { return liveFrame()->resumed(); }
49 inline Offset liveSpOff() {
50 Cell* fp = vmfp();
51 if (liveFrame()->resumed()) {
52 fp = (Cell*)Stack::resumableStackBase((ActRec*)fp);
54 return fp - vmsp();
57 namespace JIT {
59 inline int cellsToBytes(int nCells) {
60 return safe_cast<int32_t>(nCells * ssize_t(sizeof(Cell)));
63 inline int localOffset(int locId) {
64 return -cellsToBytes(locId + 1);
67 inline void assert_native_stack_aligned() {
68 #ifndef NDEBUG
69 assert(reinterpret_cast<uintptr_t>(__builtin_frame_address(0)) % 16 == 0);
70 #endif
73 /**
74 * This class is used as a scoped guard around code that is called from the JIT
75 * which needs the VM to be in a consistent state. JIT helpers use it to guard
76 * calls into HHVM's runtime. It is used like this:
78 * void helperFunction() {
79 * JIT::VMRegAnchor _;
80 * runtimeCall();
81 * }
83 * VMRegAnchor should also be used before entering a C library compiled with
84 * -fomit-frame-pointer which will call back into HHVM. If VMRegAnchor is not
85 * used, HHVM's runtime will attempt to traverse the native stack, and will
86 * assert or crash if it attempts to parse a part of the stack with no frame
87 * pointers. VMRegAnchor forces the stack traversal to be done when it is
88 * constructed.
90 struct VMRegAnchor : private boost::noncopyable {
91 VMRegState m_old;
92 VMRegAnchor() {
93 assert_native_stack_aligned();
94 m_old = tl_regState;
95 translatorSync();
97 explicit VMRegAnchor(ActRec* ar) {
98 // Some C++ entry points have an ActRec prepared from after a call
99 // instruction. This syncs us to right after the call instruction.
100 assert(tl_regState == VMRegState::DIRTY);
101 m_old = VMRegState::DIRTY;
102 tl_regState = VMRegState::CLEAN;
104 auto prevAr = g_context->getOuterVMFrame(ar);
105 const Func* prevF = prevAr->m_func;
106 assert(!ar->resumed());
107 vmsp() = (TypedValue*)ar - ar->numArgs();
108 assert(g_context->m_stack.isValidAddress((uintptr_t)vmsp()));
109 vmpc() = prevF->unit()->at(prevF->base() + ar->m_soff);
110 vmfp() = (TypedValue*)prevAr;
112 ~VMRegAnchor() {
113 tl_regState = m_old;
118 * This class is used as an invocation guard equivalent to VMRegAnchor, except
119 * the sync is assumed to have already been done. This was part of a
120 * project aimed at improving performance by doing the fixup in advance, i.e.
121 * eagerly -- the benefits turned out to be marginal or negative in most cases.
123 struct EagerVMRegAnchor {
124 VMRegState m_old;
125 EagerVMRegAnchor() {
126 if (debug) {
127 DEBUG_ONLY const Cell* fp = vmfp();
128 DEBUG_ONLY const Cell* sp = vmsp();
129 DEBUG_ONLY const auto* pc = vmpc();
130 VMRegAnchor _;
131 assert(vmfp() == fp);
132 assert(vmsp() == sp);
133 assert(vmpc() == pc);
135 m_old = tl_regState;
136 tl_regState = VMRegState::CLEAN;
138 ~EagerVMRegAnchor() {
139 tl_regState = m_old;
143 inline ActRec* regAnchorFP(Offset* pc = nullptr) {
144 // In builtins, m_fp points to the caller's frame if called
145 // through FCallBuiltin, else it points to the builtin's frame,
146 // in which case, getPrevVMState() gets the caller's frame.
147 // In addition, we need to skip over php-defined builtin functions
148 // in order to find the true context.
149 auto const context = g_context.getNoCheck();
150 auto cur = context->getFP();
151 if (pc) *pc = cur->m_func->unit()->offsetOf(context->getPC());
152 while (cur && cur->skipFrame()) {
153 cur = context->getPrevVMState(cur, pc);
155 return cur;
158 inline ActRec* regAnchorFPForArgs() {
159 // Like regAnchorFP, but only account for FCallBuiltin
160 auto const context = g_context.getNoCheck();
161 ActRec* cur = context->getFP();
162 if (cur && cur->m_func->isCPPBuiltin()) {
163 cur = context->getPrevVMState(cur);
165 return cur;
168 struct EagerCallerFrame : public EagerVMRegAnchor {
169 ActRec* operator()() {
170 return regAnchorFP();
172 ActRec* actRecForArgs() { return regAnchorFPForArgs(); }
176 // VM helper to retrieve the frame pointer from the TC. This is
177 // a common need for extensions.
178 struct CallerFrame : public VMRegAnchor {
179 template<class... Args>
180 ActRec* operator()(Args&&... args) {
181 return regAnchorFP(std::forward<Args>(args)...);
183 ActRec* actRecForArgs() { return regAnchorFPForArgs(); }
186 #define SYNC_VM_REGS_SCOPED() \
187 HPHP::JIT::VMRegAnchor _anchorUnused
189 } } // HPHP::JIT
191 #endif