bool isVMFrame(const ActRec* ar) { assert(ar); // Determine whether the frame pointer is outside the native stack, cleverly // using a single unsigned comparison to do both halves of the bounds check. bool ret = uintptr_t(ar) - s_stackLimit >= s_stackSize; assert(!ret || isValidVMStackAddress(ar) || (ar->m_func->validate(), ar->resumed())); return ret; }
void FixupMap::fixupWorkSimulated(ExecutionContext* ec) const { TRACE(1, "fixup(begin):\n"); auto isVMFrame = [] (ActRec* ar, const vixl::Simulator* sim) { // If this assert is failing, you may have forgotten a sync point somewhere assertx(ar); bool ret = uintptr_t(ar) - s_stackLimit >= s_stackSize && !sim->is_on_stack(ar); assertx(!ret || isValidVMStackAddress(ar) || ar->resumed()); return ret; }; // For each nested simulator (corresponding to nested VM invocations), look at // its PC to find a potential fixup key. // // Callstack walking is necessary, because we may get called from a // uniqueStub. for (int i = ec->m_activeSims.size() - 1; i >= 0; --i) { auto const* sim = ec->m_activeSims[i]; auto const fp = arm::x2a(arm::rvmfp()); auto* rbp = reinterpret_cast<ActRec*>(sim->xreg(fp.code())); auto tca = reinterpret_cast<TCA>(sim->pc()); TRACE(2, "considering frame %p, %p\n", rbp, tca); while (rbp && !isVMFrame(rbp, sim)) { tca = reinterpret_cast<TCA>(rbp->m_savedRip); rbp = rbp->m_sfp; } if (!rbp) continue; auto* ent = m_fixups.find(tca); if (!ent) { continue; } if (ent->isIndirect()) { not_implemented(); } VMRegs regs; regsFromActRec(tca, rbp, ent->fixup, ®s); TRACE(2, "fixup(end): func %s fp %p sp %p pc %p\b", regs.fp->m_func->name()->data(), regs.fp, regs.sp, regs.pc); auto& vmRegs = vmRegsUnsafe(); vmRegs.fp = const_cast<ActRec*>(regs.fp); vmRegs.pc = reinterpret_cast<PC>(regs.pc); vmRegs.stack.top() = regs.sp; return; } // This shouldn't be reached. always_assert(false); }
void enterTC(TCA start, ActRec* stashedAR) { if (debug) { fflush(stdout); fflush(stderr); } assertx(tc::isValidCodeAddress(start)); assertx(((uintptr_t)vmsp() & (sizeof(Cell) - 1)) == 0); assertx(((uintptr_t)vmfp() & (sizeof(Cell) - 1)) == 0); INC_TPC(enter_tc); if (Trace::moduleEnabled(Trace::ringbuffer, 1)) { auto skData = SrcKey{liveFunc(), vmpc(), liveResumed()}.toAtomicInt(); Trace::ringbufferEntry(Trace::RBTypeEnterTC, skData, (uint64_t)start); } tl_regState = VMRegState::DIRTY; enterTCImpl(start, stashedAR); tl_regState = VMRegState::CLEAN; assertx(isValidVMStackAddress(vmsp())); vmfp() = nullptr; }