/* * 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 = tx->uniqueStubs.resumeHelper; } tl_regState = VMRegState::DIRTY; return tca; }
/* * 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) { assert_native_stack_aligned(); 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; }
/* * This is used to generate an entry point for the entry to a function, after * the prologue has run. */ TCA funcBodyHelper(ActRec* fp) { assert_native_stack_aligned(); void* const sp = reinterpret_cast<Cell*>(fp) - fp->func()->numSlotsInFrame(); setupAfterPrologue(fp, sp); tl_regState = VMRegState::CLEAN; auto const func = const_cast<Func*>(fp->m_func); auto tca = mcg->getFuncBody(func); if (!tca) { tca = mcg->tx().uniqueStubs.resumeHelper; } tl_regState = VMRegState::DIRTY; return tca; }
TCA fcallHelper(ActRec* ar, void* sp) { try { 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); uint64_t rip = ar->m_savedRip; if (g_context->doFCall(ar, g_context->m_pc)) { ar->m_savedRip = rip; return 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)-rip; } setupAfterPrologue(ar, sp); assert(ar == g_context->m_fp); return 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; } }