void addDbgGuardImpl(SrcKey sk, SrcRec* sr) { TCA realCode = sr->getTopTranslation(); if (!realCode) return; // No translations, nothing to do. auto& cb = mcg->code.main(); auto const dbgGuard = vwrap(cb, [&] (Vout& v) { if (!sk.resumed()) { auto const off = sr->nonResumedSPOff(); v << lea{rvmfp()[-cellsToBytes(off.offset)], rvmsp()}; } auto const tinfo = v.makeReg(); auto const attached = v.makeReg(); auto const sf = v.makeReg(); auto const done = v.makeBlock(); constexpr size_t dbgOff = offsetof(ThreadInfo, m_reqInjectionData) + RequestInjectionData::debuggerReadOnlyOffset(); v << ldimmq{reinterpret_cast<uintptr_t>(sk.pc()), rarg(0)}; emitTLSLoad(v, tls_datum(ThreadInfo::s_threadInfo), tinfo); v << loadb{tinfo[dbgOff], attached}; v << testbi{static_cast<int8_t>(0xffu), attached, sf}; v << jcci{CC_NZ, sf, done, mcg->ustubs().interpHelper}; v = done; v << fallthru{}; }, CodeKind::Helper); // Emit a jump to the actual code. auto const dbgBranchGuardSrc = emitSmashableJmp(cb, realCode); // Add the guard to the SrcRec. sr->addDebuggerGuard(dbgGuard, dbgBranchGuardSrc); }
bool emit(Venv& env, const fallback& i) { auto const jmp = emitSmashableJmp(*env.cb, env.meta, env.cb->frontier()); env.stubs.push_back({jmp, nullptr, i}); registerFallbackJump(env, jmp, CC_None); return true; }
bool emit(Venv& env, const bindjmp& i) { auto const jmp = emitSmashableJmp(*env.cb, env.meta, env.cb->frontier()); env.stubs.push_back({jmp, nullptr, i}); setJmpTransID(env, jmp); return true; }
bool emit(Venv& env, const fallback& i) { auto const jmp = emitSmashableJmp(*env.cb, env.meta, env.cb->frontier()); env.stubs.push_back({jmp, nullptr, i}); mcg->tx().getSrcRec(i.target)->registerFallbackJump(jmp, CC_None, env.meta); return true; }
void Vgen::emit(jmp i) { if (next == i.target) return; jmps.push_back({a->frontier(), i.target}); // B range is +/- 128MB but this uses BR emitSmashableJmp(*codeBlock, env.meta, kEndOfTargetChain); }