diff --git a/hphp/runtime/vm/func.cpp b/hphp/runtime/vm/func.cpp index 174a9aebc..fc70bf167 100644 --- a/hphp/runtime/vm/func.cpp +++ b/hphp/runtime/vm/func.cpp @@ -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 = diff --git a/hphp/runtime/vm/translator/hopt/hhbctranslator.cpp b/hphp/runtime/vm/translator/hopt/hhbctranslator.cpp index e8bb31338..0974c2aa3 100644 --- a/hphp/runtime/vm/translator/hopt/hhbctranslator.cpp +++ b/hphp/runtime/vm/translator/hopt/hhbctranslator.cpp @@ -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(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); diff --git a/hphp/runtime/vm/translator/hopt/ir.h b/hphp/runtime/vm/translator/hopt/ir.h index 893a471b0..935f4fc0a 100644 --- a/hphp/runtime/vm/translator/hopt/ir.h +++ b/hphp/runtime/vm/translator/hopt/ir.h @@ -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() { diff --git a/hphp/runtime/vm/translator/translator-x64-helpers.cpp b/hphp/runtime/vm/translator/translator-x64-helpers.cpp index f916867a4..5ce68b7cd 100644 --- a/hphp/runtime/vm/translator/translator-x64-helpers.cpp +++ b/hphp/runtime/vm/translator/translator-x64-helpers.cpp @@ -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(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; diff --git a/hphp/runtime/vm/translator/translator-x64.cpp b/hphp/runtime/vm/translator/translator-x64.cpp index 3b25beabd..4c4c9cd99 100644 --- a/hphp/runtime/vm/translator/translator-x64.cpp +++ b/hphp/runtime/vm/translator/translator-x64.cpp @@ -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); } diff --git a/hphp/runtime/vm/translator/translator-x64.h b/hphp/runtime/vm/translator/translator-x64.h index 8de4fec49..522988dd5 100644 --- a/hphp/runtime/vm/translator/translator-x64.h +++ b/hphp/runtime/vm/translator/translator-x64.h @@ -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);