forked from facebook/hhvm
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfunction-entry-helpers-x64.cpp
144 lines (132 loc) · 4.62 KB
/
function-entry-helpers-x64.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
/*
+----------------------------------------------------------------------+
| HipHop for PHP |
+----------------------------------------------------------------------+
| Copyright (c) 2010-2014 Facebook, Inc. (http://www.facebook.com) |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| [email protected] so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
*/
#include "hphp/runtime/vm/jit/translator-inline.h"
#include "hphp/runtime/vm/jit/mc-generator.h"
#include "hphp/runtime/vm/event-hook.h"
#include "hphp/runtime/base/builtin-functions.h"
#include "hphp/vixl/a64/simulator-a64.h"
namespace HPHP {
namespace jit {
static void setupAfterPrologue(ActRec* fp, void* sp) {
auto& regs = vmRegsUnsafe();
regs.fp = fp;
regs.stack.top() = (Cell*)sp;
int nargs = fp->numArgs();
int nparams = fp->m_func->numNonVariadicParams();
Offset firstDVInitializer = InvalidAbsoluteOffset;
if (nargs < nparams) {
const Func::ParamInfoVec& paramInfo = fp->m_func->params();
for (int i = nargs; i < nparams; ++i) {
Offset dvInitializer = paramInfo[i].funcletOff;
if (dvInitializer != InvalidAbsoluteOffset) {
firstDVInitializer = dvInitializer;
break;
}
}
}
if (firstDVInitializer != InvalidAbsoluteOffset) {
regs.pc = fp->m_func->unit()->entry() + firstDVInitializer;
} else {
regs.pc = fp->m_func->getEntry();
}
}
TCA fcallHelper(ActRec* ar, void* sp) {
try {
assert(!ar->resumed());
TCA tca =
mcg->getFuncPrologue((Func*)ar->m_func, ar->numArgs(), ar);
if (tca) {
return tca;
}
if (!ar->m_func->isClonedClosure()) {
/*
* If the func is a cloned closure, then the original
* closure has already run the prologue, and the prologues
* array is just being used as entry points for the
* dv funclets. Dont run the prologue again.
*/
VMRegAnchor _(ar);
if (g_context->doFCall(ar, vmpc())) {
return mcg->tx().uniqueStubs.resumeHelperRet;
}
// We've been asked to skip the function body
// (fb_intercept). frame, stack and pc have
// already been fixed - flag that with a negative
// return address.
return (TCA)-ar->m_savedRip;
}
setupAfterPrologue(ar, sp);
assert(ar == vmRegsUnsafe().fp);
return mcg->tx().uniqueStubs.resumeHelper;
} catch (...) {
/*
The return address is set to __fcallHelperThunk,
which has no unwind information. Its "logically"
part of the tc, but the c++ unwinder wont know
that. So point our return address at the called
function's return address (which will be in the
tc).
Note that the registers really are clean - we
cleaned them in the try above - so we just
have to tell the unwinder that.
*/
DECLARE_FRAME_POINTER(framePtr);
tl_regState = VMRegState::CLEAN;
framePtr->m_savedRip = ar->m_savedRip;
throw;
}
}
/*
* This is used to generate an entry point for the entry
* to a function, after the prologue has run.
*/
TCA funcBodyHelper(ActRec* fp, void* sp) {
setupAfterPrologue(fp, sp);
tl_regState = VMRegState::CLEAN;
Func* func = const_cast<Func*>(fp->m_func);
TCA tca = mcg->getCallArrayPrologue(func);
if (!tca) {
tca = mcg->tx().uniqueStubs.resumeHelper;
}
tl_regState = VMRegState::DIRTY;
return tca;
}
int64_t decodeCufIterHelper(Iter* it, TypedValue func) {
DECLARE_FRAME_POINTER(framePtr);
ObjectData* obj = nullptr;
HPHP::Class* cls = nullptr;
StringData* invName = nullptr;
auto ar = framePtr->m_sfp;
if (LIKELY(ar->m_func->isBuiltin())) {
ar = g_context->getOuterVMFrame(ar);
}
const Func* f = vm_decode_function(tvAsVariant(&func),
ar, false,
obj, cls, invName,
false);
if (UNLIKELY(!f)) return false;
CufIter &cit = it->cuf();
cit.setFunc(f);
if (obj) {
cit.setCtx(obj);
obj->incRefCount();
} else {
cit.setCtx(cls);
}
cit.setName(invName);
return true;
}
} } // HPHP::jit