@@ -114,7 +114,9 @@ void Func::setFullName() {
|
||||
}
|
||||
|
||||
void Func::initPrologues(int numParams, bool isGenerator) {
|
||||
m_funcBody = (TCA)HPHP::VM::Transl::funcBodyHelperThunk;
|
||||
m_funcBody = (isGenerator ?
|
||||
(TCA)HPHP::VM::Transl::contEnterHelperThunk :
|
||||
(TCA)HPHP::VM::Transl::funcBodyHelperThunk);
|
||||
|
||||
int maxNumPrologues = Func::getMaxNumPrologues(numParams);
|
||||
int numPrologues =
|
||||
|
||||
@@ -702,7 +702,7 @@ void HhbcTranslator::emitContEnter(int32_t returnBcOffset) {
|
||||
SSATmp* contAR = m_tb->genLdRaw(cont, RawMemSlot::ContARPtr, Type::StkPtr);
|
||||
|
||||
SSATmp* func = m_tb->genLdARFuncPtr(contAR, m_tb->genDefConst<int64_t>(0));
|
||||
SSATmp* funcBody = m_tb->genLdRaw(func, RawMemSlot::ContEntry, Type::TCA);
|
||||
SSATmp* funcBody = m_tb->genLdRaw(func, RawMemSlot::FuncBody, Type::TCA);
|
||||
|
||||
m_tb->genContEnter(contAR, funcBody, returnBcOffset);
|
||||
|
||||
|
||||
@@ -1393,7 +1393,7 @@ class RawMemSlot {
|
||||
|
||||
enum Kind {
|
||||
ContLabel, ContDone, ContShouldThrow, ContRunning, ContARPtr,
|
||||
StrLen, FuncNumParams, FuncRefBitVec, ContEntry, MisBaseStrOff,
|
||||
StrLen, FuncNumParams, FuncRefBitVec, FuncBody, MisBaseStrOff,
|
||||
MisCtx,
|
||||
MaxKind
|
||||
};
|
||||
@@ -1408,7 +1408,7 @@ class RawMemSlot {
|
||||
case StrLen: return GetStrLen();
|
||||
case FuncNumParams: return GetFuncNumParams();
|
||||
case FuncRefBitVec: return GetFuncRefBitVec();
|
||||
case ContEntry: return GetContEntry();
|
||||
case FuncBody: return GetFuncBody();
|
||||
case MisBaseStrOff: return GetMisBaseStrOff();
|
||||
case MisCtx: return GetMisCtx();
|
||||
default: not_reached();
|
||||
@@ -1456,10 +1456,8 @@ class RawMemSlot {
|
||||
static RawMemSlot m(Func::refBitVecOff(), sz::qword, Type::Int);
|
||||
return m;
|
||||
}
|
||||
static RawMemSlot& GetContEntry() {
|
||||
static RawMemSlot m(
|
||||
Func::prologueTableOff() + sizeof(HPHP::VM::Transl::TCA),
|
||||
sz::qword, Type::TCA);
|
||||
static RawMemSlot& GetFuncBody() {
|
||||
static RawMemSlot m(Func::funcBodyOff(), sz::qword, Type::TCA);
|
||||
return m;
|
||||
}
|
||||
static RawMemSlot& GetMisBaseStrOff() {
|
||||
|
||||
@@ -187,9 +187,35 @@ asm (
|
||||
#endif
|
||||
);
|
||||
|
||||
asm (
|
||||
".byte 0\n"
|
||||
".align 16\n"
|
||||
".globl __contEnterHelperThunk\n"
|
||||
"__contEnterHelperThunk:\n"
|
||||
#if defined(__x86_64__)
|
||||
// The generator body's AR is in rStashedAR. rVmFp still points to the frame
|
||||
// above the generator. The prologue is responsible for setting rVmFp. Even
|
||||
// if we can't get a prologue, funcBodyHelper syncs the new FP, and the
|
||||
// "resume helper" sets the hardware FP from that.
|
||||
// This helper is called from the tc - so we need to maintain stack parity,
|
||||
// hence the pop/push
|
||||
"pop 0x8(%r15)\n"
|
||||
"mov %r15, %rdi\n"
|
||||
"call funcBodyHelper\n"
|
||||
"push 0x8(%r15)\n"
|
||||
"jmp *%rax\n"
|
||||
"ud2\n"
|
||||
#elif defined(__AARCH64EL__)
|
||||
"brk 0\n"
|
||||
#else
|
||||
# error You sure have your work cut out for you
|
||||
#endif
|
||||
);
|
||||
|
||||
/*
|
||||
* This is used to generate an entry point for the entry
|
||||
* to a function, after the prologue has run.
|
||||
* Two different "function"-entry paths come through here: entering functions
|
||||
* via FCallArray, and entering generator bodies. The common element is that
|
||||
* neither requires different entry points for different callsite arities.
|
||||
*/
|
||||
TCA funcBodyHelper(ActRec* fp) {
|
||||
g_vmContext->m_fp = fp;
|
||||
@@ -216,12 +242,22 @@ TCA funcBodyHelper(ActRec* fp) {
|
||||
Func* func = const_cast<Func*>(fp->m_func);
|
||||
SrcKey sk(func, func->base());
|
||||
|
||||
TCA tca = tx64->getCallArrayProlog(func);
|
||||
TCA tca;
|
||||
if (func->isGenerator()) {
|
||||
assert(nargs == 1);
|
||||
tca = tx64->funcPrologue(func, nargs);
|
||||
} else {
|
||||
tca = tx64->getCallArrayProlog(func);
|
||||
}
|
||||
|
||||
if (tca) {
|
||||
func->setFuncBody(tca);
|
||||
} else {
|
||||
tca = Translator::Get()->getResumeHelper();
|
||||
if (func->isGenerator()) {
|
||||
tca = Translator::Get()->getResumeHelperRet();
|
||||
} else {
|
||||
tca = Translator::Get()->getResumeHelper();
|
||||
}
|
||||
}
|
||||
tl_regState = REGSTATE_DIRTY;
|
||||
return tca;
|
||||
|
||||
@@ -7566,7 +7566,7 @@ void TranslatorX64::translateContEnter(const Tracelet& t,
|
||||
|
||||
// We're between tracelets; hardcode the register
|
||||
a. loadq (rStashedAR[AROFF(m_func)], rax);
|
||||
a. loadq (rax[Func::prologueTableOff() + sizeof(TCA)], rax);
|
||||
a. loadq (rax[Func::funcBodyOff()], rax);
|
||||
|
||||
a. call (rax);
|
||||
}
|
||||
|
||||
@@ -1121,6 +1121,7 @@ const size_t kMaxNumTrampolines = kTrampolinesBlockSize /
|
||||
|
||||
void fcallHelperThunk() asm ("__fcallHelperThunk");
|
||||
void funcBodyHelperThunk() asm ("__funcBodyHelperThunk");
|
||||
void contEnterHelperThunk() asm ("__contEnterHelperThunk");
|
||||
|
||||
// These could be static but are used in hopt/codegen.cpp
|
||||
void raiseUndefVariable(StringData* nm);
|
||||
|
||||
Referência em uma Nova Issue
Bloquear um usuário