TCA fcallHelper(ActRec* ar) { assert_native_stack_aligned(); assertx(!ar->resumed()); if (LIKELY(!RuntimeOption::EvalFailJitPrologs)) { auto const tca = mcg->getFuncPrologue( const_cast<Func*>(ar->m_func), ar->numArgs(), ar ); if (tca) return tca; } // Check for stack overflow in the same place func prologues make their // StackCheck::Early check (see irgen-func-prologue.cpp). This handler also // cleans and syncs vmRegs for us. if (checkCalleeStackOverflow(ar)) handleStackOverflow(ar); try { VMRegAnchor _(ar); if (doFCall(ar, vmpc())) { return mcg->tx().uniqueStubs.resumeHelperRet; } // We've been asked to skip the function body (fb_intercept). The vmregs // have already been fixed; indicate this with a nullptr return. return nullptr; } catch (...) { // The VMRegAnchor above took care of us, but we need to tell the unwinder // (since ~VMRegAnchor() will have reset tl_regState). tl_regState = VMRegState::CLEAN; throw; } }
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 (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; } }