TCA emitEndCatchHelper(CodeBlock& cb, UniqueStubs& us) { Asm a { cb }; alignJmpTarget(cb); Label debuggerReturn; Label resumeCppUnwind; auto const start = a.frontier(); a. cmpq (0, rvmtl()[unwinderDebuggerReturnSPOff()]); a. jne8 (debuggerReturn); // Normal endCatch situation: call back to tc_unwind_resume, which returns // the catch trace (or null) in rax and the new vmfp in rdx. a. movq (rvmfp(), rarg(0)); a. call (TCA(tc_unwind_resume)); a. movq (rdx, rvmfp()); a. testq(rax, rax); a. jz8 (resumeCppUnwind); a. jmp (rax); // rdx is still live if we're going to code from llvm asm_label(a, resumeCppUnwind); static_assert(sizeof(tl_regState) == 1, "The following store must match the size of tl_regState"); auto vptr = emitTLSAddr(a, tl_regState, rax); Vasm::prefix(a, vptr). storeb(static_cast<int32_t>(VMRegState::CLEAN), vptr.mr()); a. loadq(rvmtl()[unwinderExnOff()], rarg(0)); emitCall(a, TCA(_Unwind_Resume), arg_regs(1)); us.endCatchHelperPast = a.frontier(); a. ud2(); asm_label(a, debuggerReturn); a. loadq (rvmtl()[unwinderDebuggerReturnSPOff()], rvmsp()); a. storeq(0, rvmtl()[unwinderDebuggerReturnSPOff()]); svcreq::emit_persistent(a.code(), folly::none, REQ_POST_DEBUGGER_RET); return start; }
void emitTransCounterInc(Asm& a) { emitTransCounterInc(Vauto(a.code()).main()); }
void emitCall(Asm& a, CppCall call, RegSet args) { emitCall(Vauto(a.code()).main(), call, args); }