remove operator-> from String
[hiphop-php.git] / hphp / runtime / vm / jit / translator-inline.h
blobf7f182737d9938626b468260e161cf439ba865f5
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"
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.
32 namespace HPHP {
35 * Accessors for the virtual machine registers, both rvalues and
36 * lvalues.
38 * Note that these do not assert anything about tl_regState; use
39 * carefully.
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() {
52 Cell* fp = vmfp();
53 if (liveFrame()->inGenerator()) {
54 fp = (Cell*)Stack::generatorStackBase((ActRec*)fp);
56 return fp - vmsp();
59 namespace JIT {
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() {
74 #ifndef NDEBUG
75 assert(reinterpret_cast<uintptr_t>(__builtin_frame_address(0)) % 16 == 0);
76 #endif
79 struct VMRegAnchor : private boost::noncopyable {
80 VMRegState m_old;
81 VMRegAnchor() {
82 assert_native_stack_aligned();
83 m_old = tl_regState;
84 translatorSync();
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;
102 ~VMRegAnchor() {
103 tl_regState = m_old;
107 struct EagerVMRegAnchor {
108 VMRegState m_old;
109 EagerVMRegAnchor() {
110 if (debug) {
111 DEBUG_ONLY const Cell* fp = vmfp();
112 DEBUG_ONLY const Cell* sp = vmsp();
113 DEBUG_ONLY const auto* pc = vmpc();
114 VMRegAnchor _;
115 assert(vmfp() == fp && vmsp() == sp && vmpc() == pc);
117 m_old = tl_regState;
118 tl_regState = VMRegState::CLEAN;
120 ~EagerVMRegAnchor() {
121 tl_regState = m_old;
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);
137 return cur;
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);
147 return 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
171 } } // HPHP::JIT
173 #endif