зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1370696: Use register state unwinding when interrupting within wasm; r=luke
MozReview-Commit-ID: 76RM1Gf0eAo --HG-- extra : rebase_source : 60b3d43ebe5af0c88ae14e2f685f761012672110 extra : histedit_source : 882ad83e6b5033a08b1045892ab3f3b13b38c5b1
This commit is contained in:
Родитель
99a29014d5
Коммит
771e53e98e
|
@ -1547,6 +1547,17 @@ Simulator::exclusiveMonitorClear()
|
|||
exclusiveMonitorHeld_ = false;
|
||||
}
|
||||
|
||||
void
|
||||
Simulator::startInterrupt(WasmActivation* activation)
|
||||
{
|
||||
JS::ProfilingFrameIterator::RegisterState state;
|
||||
state.pc = (void*) get_pc();
|
||||
state.fp = (void*) get_register(fp);
|
||||
state.sp = (void*) get_register(sp);
|
||||
state.lr = (void*) get_register(lr);
|
||||
activation->startInterrupt(state);
|
||||
}
|
||||
|
||||
// The signal handler only redirects the PC to the interrupt stub when the PC is
|
||||
// in function code. However, this guard is racy for the ARM simulator since the
|
||||
// signal handler samples PC in the middle of simulating an instruction and thus
|
||||
|
@ -1568,7 +1579,7 @@ Simulator::handleWasmInterrupt()
|
|||
if (!fp)
|
||||
return;
|
||||
|
||||
activation->startInterrupt(pc, fp);
|
||||
startInterrupt(activation);
|
||||
set_pc(int32_t(segment->interruptCode()));
|
||||
}
|
||||
|
||||
|
@ -1594,7 +1605,7 @@ Simulator::handleWasmFault(int32_t addr, unsigned numBytes)
|
|||
const wasm::CodeSegment* segment;
|
||||
const wasm::MemoryAccess* memoryAccess = instance->code().lookupMemoryAccess(pc, &segment);
|
||||
if (!memoryAccess) {
|
||||
act->startInterrupt(pc, fp);
|
||||
startInterrupt(act);
|
||||
if (!instance->code().containsCodePC(pc, &segment))
|
||||
MOZ_CRASH("Cannot map PC to trap handler");
|
||||
set_pc(int32_t(segment->outOfBoundsCode()));
|
||||
|
|
|
@ -40,6 +40,9 @@
|
|||
#include "vm/MutexIDs.h"
|
||||
|
||||
namespace js {
|
||||
|
||||
class WasmActivation;
|
||||
|
||||
namespace jit {
|
||||
|
||||
class Simulator;
|
||||
|
@ -289,6 +292,7 @@ class Simulator
|
|||
|
||||
// Handle a wasm interrupt triggered by an async signal handler.
|
||||
void handleWasmInterrupt();
|
||||
void startInterrupt(WasmActivation* act);
|
||||
|
||||
// Handle any wasm faults, returning true if the fault was handled.
|
||||
bool handleWasmFault(int32_t addr, unsigned numBytes);
|
||||
|
|
|
@ -249,7 +249,13 @@ void Simulator::handle_wasm_interrupt() {
|
|||
if (!code || !segment->containsFunctionPC(pc))
|
||||
return;
|
||||
|
||||
activation->startInterrupt(pc, fp);
|
||||
JS::ProfilingFrameIterator::RegisterState state;
|
||||
state.pc = pc;
|
||||
state.fp = fp;
|
||||
state.lr = (uint8_t*) xreg(30);
|
||||
state.sp = (uint8_t*) xreg(31);
|
||||
activation->startInterrupt(state);
|
||||
|
||||
set_pc((Instruction*)segment->interruptCode());
|
||||
}
|
||||
|
||||
|
|
|
@ -1089,13 +1089,26 @@ struct JSRuntime : public js::MallocProvider<JSRuntime>
|
|||
// resume PC at a time.
|
||||
js::ActiveThreadData<void*> wasmResumePC_;
|
||||
|
||||
// To ensure a consistent state of fp/pc, the unwound pc might be
|
||||
// different from the resumePC, especially at call boundaries.
|
||||
js::ActiveThreadData<void*> wasmUnwindPC_;
|
||||
|
||||
public:
|
||||
void startWasmInterrupt(void* resumePC, void* unwindPC) {
|
||||
MOZ_ASSERT(resumePC && unwindPC);
|
||||
wasmResumePC_ = resumePC;
|
||||
wasmUnwindPC_ = unwindPC;
|
||||
}
|
||||
void finishWasmInterrupt() {
|
||||
MOZ_ASSERT(wasmResumePC_ && wasmUnwindPC_);
|
||||
wasmResumePC_ = nullptr;
|
||||
wasmUnwindPC_ = nullptr;
|
||||
}
|
||||
void* wasmResumePC() const {
|
||||
return wasmResumePC_;
|
||||
}
|
||||
void setWasmResumePC(void* resumePC) {
|
||||
MOZ_ASSERT(!!resumePC == !wasmResumePC_);
|
||||
wasmResumePC_ = resumePC;
|
||||
void* wasmUnwindPC() const {
|
||||
return wasmUnwindPC_;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -1652,19 +1652,25 @@ WasmActivation::unwindExitFP(wasm::Frame* exitFP)
|
|||
}
|
||||
|
||||
void
|
||||
WasmActivation::startInterrupt(void* pc, uint8_t* fp)
|
||||
WasmActivation::startInterrupt(const JS::ProfilingFrameIterator::RegisterState& state)
|
||||
{
|
||||
MOZ_ASSERT(pc);
|
||||
MOZ_ASSERT(fp);
|
||||
MOZ_ASSERT(state.pc);
|
||||
MOZ_ASSERT(state.fp);
|
||||
|
||||
// Execution can only be interrupted in function code. Afterwards, control
|
||||
// flow does not reenter function code and thus there should be no
|
||||
// interrupt-during-interrupt.
|
||||
MOZ_ASSERT(!interrupted());
|
||||
MOZ_ASSERT(compartment()->wasm.lookupCode(pc)->lookupRange(pc)->isFunction());
|
||||
|
||||
cx_->runtime()->setWasmResumePC(pc);
|
||||
exitFP_ = reinterpret_cast<wasm::Frame*>(fp);
|
||||
bool ignoredUnwound;
|
||||
wasm::UnwindState unwindState;
|
||||
MOZ_ALWAYS_TRUE(wasm::StartUnwinding(*this, state, &unwindState, &ignoredUnwound));
|
||||
|
||||
void* unwindPC = unwindState.pc;
|
||||
MOZ_ASSERT(compartment()->wasm.lookupCode(unwindPC)->lookupRange(unwindPC)->isFunction());
|
||||
|
||||
cx_->runtime()->startWasmInterrupt(state.pc, unwindPC);
|
||||
exitFP_ = reinterpret_cast<wasm::Frame*>(unwindState.fp);
|
||||
|
||||
MOZ_ASSERT(compartment() == exitFP_->tls->instance->compartment());
|
||||
MOZ_ASSERT(interrupted());
|
||||
|
@ -1676,14 +1682,14 @@ WasmActivation::finishInterrupt()
|
|||
MOZ_ASSERT(interrupted());
|
||||
MOZ_ASSERT(exitFP_);
|
||||
|
||||
cx_->runtime()->setWasmResumePC(nullptr);
|
||||
cx_->runtime()->finishWasmInterrupt();
|
||||
exitFP_ = nullptr;
|
||||
}
|
||||
|
||||
bool
|
||||
WasmActivation::interrupted() const
|
||||
{
|
||||
void* pc = cx_->runtime()->wasmResumePC();
|
||||
void* pc = cx_->runtime()->wasmUnwindPC();
|
||||
if (!pc)
|
||||
return false;
|
||||
|
||||
|
@ -1699,6 +1705,13 @@ WasmActivation::interrupted() const
|
|||
return true;
|
||||
}
|
||||
|
||||
void*
|
||||
WasmActivation::unwindPC() const
|
||||
{
|
||||
MOZ_ASSERT(interrupted());
|
||||
return cx_->runtime()->wasmUnwindPC();
|
||||
}
|
||||
|
||||
void*
|
||||
WasmActivation::resumePC() const
|
||||
{
|
||||
|
|
|
@ -1760,9 +1760,10 @@ class WasmActivation : public Activation
|
|||
// Interrupts are started from the interrupt signal handler (or the ARM
|
||||
// simulator) and cleared by WasmHandleExecutionInterrupt or WasmHandleThrow
|
||||
// when the interrupt is handled.
|
||||
void startInterrupt(void* pc, uint8_t* fp);
|
||||
void startInterrupt(const JS::ProfilingFrameIterator::RegisterState& state);
|
||||
void finishInterrupt();
|
||||
bool interrupted() const;
|
||||
void* unwindPC() const;
|
||||
void* resumePC() const;
|
||||
|
||||
// Used by wasm::FrameIterator during stack unwinding.
|
||||
|
|
|
@ -72,11 +72,11 @@ FrameIterator::FrameIterator(WasmActivation* activation, Unwind unwind)
|
|||
// but this is fine because CallSite is only used for line number for which
|
||||
// we can use the beginning of the function from the CodeRange instead.
|
||||
|
||||
code_ = activation_->compartment()->wasm.lookupCode(activation->resumePC());
|
||||
code_ = activation_->compartment()->wasm.lookupCode(activation->unwindPC());
|
||||
MOZ_ASSERT(code_);
|
||||
MOZ_ASSERT(&fp_->tls->instance->code() == code_);
|
||||
|
||||
codeRange_ = code_->lookupRange(activation->resumePC());
|
||||
codeRange_ = code_->lookupRange(activation->unwindPC());
|
||||
MOZ_ASSERT(codeRange_->kind() == CodeRange::Function);
|
||||
|
||||
MOZ_ASSERT(!done());
|
||||
|
|
|
@ -71,6 +71,7 @@ class AutoSetHandlingSegFault
|
|||
# define XMM_sig(p,i) ((p)->Xmm##i)
|
||||
# define EIP_sig(p) ((p)->Eip)
|
||||
# define EBP_sig(p) ((p)->Ebp)
|
||||
# define ESP_sig(p) ((p)->Esp)
|
||||
# define RIP_sig(p) ((p)->Rip)
|
||||
# define RAX_sig(p) ((p)->Rax)
|
||||
# define RCX_sig(p) ((p)->Rcx)
|
||||
|
@ -92,6 +93,7 @@ class AutoSetHandlingSegFault
|
|||
# define XMM_sig(p,i) ((p)->sc_fpstate->fx_xmm[i])
|
||||
# define EIP_sig(p) ((p)->sc_eip)
|
||||
# define EBP_sig(p) ((p)->sc_ebp)
|
||||
# define ESP_sig(p) ((p)->sc_esp)
|
||||
# define RIP_sig(p) ((p)->sc_rip)
|
||||
# define RAX_sig(p) ((p)->sc_rax)
|
||||
# define RCX_sig(p) ((p)->sc_rcx)
|
||||
|
@ -116,6 +118,7 @@ class AutoSetHandlingSegFault
|
|||
# if defined(__aarch64__)
|
||||
# define EPC_sig(p) ((p)->sc_elr)
|
||||
# define RFP_sig(p) ((p)->sc_x[29])
|
||||
# define RLR_sig(p) ((p)->sc_x[30])
|
||||
# endif
|
||||
# if defined(__mips__)
|
||||
# define EPC_sig(p) ((p)->sc_pc)
|
||||
|
@ -126,10 +129,12 @@ class AutoSetHandlingSegFault
|
|||
# define XMM_sig(p,i) ((p)->uc_mcontext.fpregs->_xmm[i])
|
||||
# define EIP_sig(p) ((p)->uc_mcontext.gregs[REG_EIP])
|
||||
# define EBP_sig(p) ((p)->uc_mcontext.gregs[REG_EBP])
|
||||
# define ESP_sig(p) ((p)->uc_mcontext.gregs[REG_ESP])
|
||||
# else
|
||||
# define XMM_sig(p,i) ((p)->uc_mcontext.fpregs.fp_reg_set.fpchip_state.xmm[i])
|
||||
# define EIP_sig(p) ((p)->uc_mcontext.gregs[REG_PC])
|
||||
# define EBP_sig(p) ((p)->uc_mcontext.gregs[REG_EBP])
|
||||
# define ESP_sig(p) ((p)->uc_mcontext.gregs[REG_ESP])
|
||||
# endif
|
||||
# define RIP_sig(p) ((p)->uc_mcontext.gregs[REG_RIP])
|
||||
# define RAX_sig(p) ((p)->uc_mcontext.gregs[REG_RAX])
|
||||
|
@ -144,28 +149,31 @@ class AutoSetHandlingSegFault
|
|||
# define R9_sig(p) ((p)->uc_mcontext.gregs[REG_R9])
|
||||
# define R10_sig(p) ((p)->uc_mcontext.gregs[REG_R10])
|
||||
# define R12_sig(p) ((p)->uc_mcontext.gregs[REG_R12])
|
||||
# define R13_sig(p) ((p)->uc_mcontext.gregs[REG_R13])
|
||||
# define R14_sig(p) ((p)->uc_mcontext.gregs[REG_R14])
|
||||
# if defined(__linux__) && defined(__arm__)
|
||||
# define R11_sig(p) ((p)->uc_mcontext.arm_fp)
|
||||
# define R13_sig(p) ((p)->uc_mcontext.arm_sp)
|
||||
# define R14_sig(p) ((p)->uc_mcontext.arm_lr)
|
||||
# define R15_sig(p) ((p)->uc_mcontext.arm_pc)
|
||||
# else
|
||||
# define R11_sig(p) ((p)->uc_mcontext.gregs[REG_R11])
|
||||
# define R13_sig(p) ((p)->uc_mcontext.gregs[REG_R13])
|
||||
# define R14_sig(p) ((p)->uc_mcontext.gregs[REG_R14])
|
||||
# define R15_sig(p) ((p)->uc_mcontext.gregs[REG_R15])
|
||||
# endif
|
||||
# if defined(__linux__) && defined(__aarch64__)
|
||||
# define EPC_sig(p) ((p)->uc_mcontext.pc)
|
||||
# define RFP_sig(p) ((p)->uc_mcontext.regs[29])
|
||||
# define RLR_sig(p) ((p)->uc_mcontext.regs[30])
|
||||
# endif
|
||||
# if defined(__linux__) && defined(__mips__)
|
||||
# define EPC_sig(p) ((p)->uc_mcontext.pc)
|
||||
# define RSP_sig(p) ((p)->uc_mcontext.gregs[29])
|
||||
# define RFP_sig(p) ((p)->uc_mcontext.gregs[30])
|
||||
# endif
|
||||
#elif defined(__NetBSD__)
|
||||
# define XMM_sig(p,i) (((struct fxsave64*)(p)->uc_mcontext.__fpregs)->fx_xmm[i])
|
||||
# define EIP_sig(p) ((p)->uc_mcontext.__gregs[_REG_EIP])
|
||||
# define EBP_sig(p) ((p)->uc_mcontext.__gregs[_REG_EBP])
|
||||
# define ESP_sig(p) ((p)->uc_mcontext.__gregs[_REG_ESP])
|
||||
# define RIP_sig(p) ((p)->uc_mcontext.__gregs[_REG_RIP])
|
||||
# define RAX_sig(p) ((p)->uc_mcontext.__gregs[_REG_RAX])
|
||||
# define RCX_sig(p) ((p)->uc_mcontext.__gregs[_REG_RCX])
|
||||
|
@ -186,6 +194,8 @@ class AutoSetHandlingSegFault
|
|||
# if defined(__aarch64__)
|
||||
# define EPC_sig(p) ((p)->uc_mcontext.__gregs[_REG_PC])
|
||||
# define RFP_sig(p) ((p)->uc_mcontext.__gregs[_REG_X29])
|
||||
# define RLR_sig(p) ((p)->uc_mcontext.__gregs[_REG_X30])
|
||||
# define RSP_sig(p) ((p)->uc_mcontext.__gregs[_REG_X31])
|
||||
# endif
|
||||
# if defined(__mips__)
|
||||
# define EPC_sig(p) ((p)->uc_mcontext.__gregs[_REG_EPC])
|
||||
|
@ -199,6 +209,7 @@ class AutoSetHandlingSegFault
|
|||
# endif
|
||||
# define EIP_sig(p) ((p)->uc_mcontext.mc_eip)
|
||||
# define EBP_sig(p) ((p)->uc_mcontext.mc_ebp)
|
||||
# define ESP_sig(p) ((p)->uc_mcontext.mc_esp)
|
||||
# define RIP_sig(p) ((p)->uc_mcontext.mc_rip)
|
||||
# define RAX_sig(p) ((p)->uc_mcontext.mc_rax)
|
||||
# define RCX_sig(p) ((p)->uc_mcontext.mc_rcx)
|
||||
|
@ -223,6 +234,7 @@ class AutoSetHandlingSegFault
|
|||
# if defined(__FreeBSD__) && defined(__aarch64__)
|
||||
# define EPC_sig(p) ((p)->uc_mcontext.mc_gpregs.gp_elr)
|
||||
# define RFP_sig(p) ((p)->uc_mcontext.mc_gpregs.gp_x[29])
|
||||
# define RLR_sig(p) ((p)->uc_mcontext.mc_gpregs.gp_x[30])
|
||||
# endif
|
||||
# if defined(__FreeBSD__) && defined(__mips__)
|
||||
# define EPC_sig(p) ((p)->uc_mcontext.mc_pc)
|
||||
|
@ -231,8 +243,10 @@ class AutoSetHandlingSegFault
|
|||
#elif defined(XP_DARWIN)
|
||||
# define EIP_sig(p) ((p)->uc_mcontext->__ss.__eip)
|
||||
# define EBP_sig(p) ((p)->uc_mcontext->__ss.__ebp)
|
||||
# define ESP_sig(p) ((p)->uc_mcontext->__ss.__esp)
|
||||
# define RIP_sig(p) ((p)->uc_mcontext->__ss.__rip)
|
||||
# define RBP_sig(p) ((p)->uc_mcontext->__ss.__rbp)
|
||||
# define RSP_sig(p) ((p)->uc_mcontext->__ss.__rsp)
|
||||
# define R15_sig(p) ((p)->uc_mcontext->__ss.__pc)
|
||||
#else
|
||||
# error "Don't know how to read/write to the thread state via the mcontext_t."
|
||||
|
@ -375,15 +389,21 @@ struct macos_arm_context {
|
|||
#if defined(_M_X64) || defined(__x86_64__)
|
||||
# define PC_sig(p) RIP_sig(p)
|
||||
# define FP_sig(p) RBP_sig(p)
|
||||
# define SP_sig(p) RSP_sig(p)
|
||||
#elif defined(_M_IX86) || defined(__i386__)
|
||||
# define PC_sig(p) EIP_sig(p)
|
||||
# define FP_sig(p) EBP_sig(p)
|
||||
# define SP_sig(p) ESP_sig(p)
|
||||
#elif defined(__arm__)
|
||||
# define PC_sig(p) R15_sig(p)
|
||||
# define FP_sig(p) R11_sig(p)
|
||||
# define SP_sig(p) R13_sig(p)
|
||||
# define LR_sig(p) R14_sig(p)
|
||||
# define PC_sig(p) R15_sig(p)
|
||||
#elif defined(__aarch64__)
|
||||
# define PC_sig(p) EPC_sig(p)
|
||||
# define FP_sig(p) RFP_sig(p)
|
||||
# define SP_sig(p) RSP_sig(p)
|
||||
# define LR_sig(p) RLR_sig(p)
|
||||
#elif defined(__mips__)
|
||||
# define PC_sig(p) EPC_sig(p)
|
||||
# define FP_sig(p) RFP_sig(p)
|
||||
|
@ -409,7 +429,46 @@ ContextToFP(CONTEXT* context)
|
|||
#endif
|
||||
}
|
||||
|
||||
static uint8_t*
|
||||
ContextToSP(CONTEXT* context)
|
||||
{
|
||||
#ifdef JS_CODEGEN_NONE
|
||||
MOZ_CRASH();
|
||||
#else
|
||||
return reinterpret_cast<uint8_t*>(SP_sig(context));
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(__arm__) || defined(__aarch64__)
|
||||
static uint8_t*
|
||||
ContextToLR(CONTEXT* context)
|
||||
{
|
||||
return reinterpret_cast<uint8_t*>(LR_sig(context));
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(XP_DARWIN)
|
||||
|
||||
static uint8_t**
|
||||
ContextToPC(EMULATOR_CONTEXT* context)
|
||||
{
|
||||
# if defined(__x86_64__)
|
||||
static_assert(sizeof(context->thread.__rip) == sizeof(void*),
|
||||
"stored IP should be compile-time pointer-sized");
|
||||
return reinterpret_cast<uint8_t**>(&context->thread.__rip);
|
||||
# elif defined(__i386__)
|
||||
static_assert(sizeof(context->thread.uts.ts32.__eip) == sizeof(void*),
|
||||
"stored IP should be compile-time pointer-sized");
|
||||
return reinterpret_cast<uint8_t**>(&context->thread.uts.ts32.__eip);
|
||||
# elif defined(__arm__)
|
||||
static_assert(sizeof(context->thread.__pc) == sizeof(void*),
|
||||
"stored IP should be compile-time pointer-sized");
|
||||
return reinterpret_cast<uint8_t**>(&context->thread.__pc);
|
||||
# else
|
||||
# error Unsupported architecture
|
||||
# endif
|
||||
}
|
||||
|
||||
static uint8_t*
|
||||
ContextToFP(EMULATOR_CONTEXT* context)
|
||||
{
|
||||
|
@ -423,7 +482,49 @@ ContextToFP(EMULATOR_CONTEXT* context)
|
|||
# error Unsupported architecture
|
||||
# endif
|
||||
}
|
||||
#endif // XP_DARWIN
|
||||
|
||||
static uint8_t*
|
||||
ContextToSP(EMULATOR_CONTEXT* context)
|
||||
{
|
||||
# if defined(__x86_64__)
|
||||
return (uint8_t*)context->thread.__rsp;
|
||||
# elif defined(__i386__)
|
||||
return (uint8_t*)context->thread.uts.ts32.__esp;
|
||||
# elif defined(__arm__)
|
||||
return (uint8_t*)context->thread.__sp;
|
||||
# else
|
||||
# error Unsupported architecture
|
||||
# endif
|
||||
}
|
||||
|
||||
static JS::ProfilingFrameIterator::RegisterState
|
||||
ToRegisterState(EMULATOR_CONTEXT* context)
|
||||
{
|
||||
JS::ProfilingFrameIterator::RegisterState state;
|
||||
state.fp = ContextToFP(context);
|
||||
state.pc = *ContextToPC(context);
|
||||
state.sp = ContextToSP(context);
|
||||
// no ARM on Darwin => don't fill state.lr.
|
||||
return state;
|
||||
}
|
||||
#endif // XP_DARWIN
|
||||
|
||||
static JS::ProfilingFrameIterator::RegisterState
|
||||
ToRegisterState(CONTEXT* context)
|
||||
{
|
||||
#ifdef JS_CODEGEN_NONE
|
||||
MOZ_CRASH();
|
||||
#else
|
||||
JS::ProfilingFrameIterator::RegisterState state;
|
||||
state.fp = ContextToFP(context);
|
||||
state.pc = *ContextToPC(context);
|
||||
state.sp = ContextToSP(context);
|
||||
# if defined(__arm__) || defined(__aarch64__)
|
||||
state.lr = ContextToLR(context);
|
||||
# endif
|
||||
return state;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(WASM_HUGE_MEMORY)
|
||||
MOZ_COLD static void
|
||||
|
@ -672,7 +773,7 @@ HandleMemoryAccess(EMULATOR_CONTEXT* context, uint8_t* pc, uint8_t* faultingAddr
|
|||
// experimental SIMD.js or Atomics. When these are converted to
|
||||
// non-experimental wasm features, this case, as well as outOfBoundsCode,
|
||||
// can be removed.
|
||||
activation->startInterrupt(pc, ContextToFP(context));
|
||||
activation->startInterrupt(ToRegisterState(context));
|
||||
if (!instance.code().containsCodePC(pc, &segment))
|
||||
MOZ_CRASH("Cannot map PC to trap handler");
|
||||
*ppc = segment->outOfBoundsCode();
|
||||
|
@ -818,7 +919,7 @@ HandleMemoryAccess(EMULATOR_CONTEXT* context, uint8_t* pc, uint8_t* faultingAddr
|
|||
const MemoryAccess* memoryAccess = instance.code().lookupMemoryAccess(pc, &segment);
|
||||
if (!memoryAccess) {
|
||||
// See explanation in the WASM_HUGE_MEMORY HandleMemoryAccess.
|
||||
activation->startInterrupt(pc, ContextToFP(context));
|
||||
activation->startInterrupt(ToRegisterState(context));
|
||||
if (!instance.code().containsCodePC(pc, &segment))
|
||||
MOZ_CRASH("Cannot map PC to trap handler");
|
||||
*ppc = segment->outOfBoundsCode();
|
||||
|
@ -935,26 +1036,6 @@ WasmFaultHandler(LPEXCEPTION_POINTERS exception)
|
|||
#elif defined(XP_DARWIN)
|
||||
# include <mach/exc.h>
|
||||
|
||||
static uint8_t**
|
||||
ContextToPC(EMULATOR_CONTEXT* context)
|
||||
{
|
||||
# if defined(__x86_64__)
|
||||
static_assert(sizeof(context->thread.__rip) == sizeof(void*),
|
||||
"stored IP should be compile-time pointer-sized");
|
||||
return reinterpret_cast<uint8_t**>(&context->thread.__rip);
|
||||
# elif defined(__i386__)
|
||||
static_assert(sizeof(context->thread.uts.ts32.__eip) == sizeof(void*),
|
||||
"stored IP should be compile-time pointer-sized");
|
||||
return reinterpret_cast<uint8_t**>(&context->thread.uts.ts32.__eip);
|
||||
# elif defined(__arm__)
|
||||
static_assert(sizeof(context->thread.__pc) == sizeof(void*),
|
||||
"stored IP should be compile-time pointer-sized");
|
||||
return reinterpret_cast<uint8_t**>(&context->thread.__pc);
|
||||
# else
|
||||
# error Unsupported architecture
|
||||
# endif
|
||||
}
|
||||
|
||||
// This definition was generated by mig (the Mach Interface Generator) for the
|
||||
// routine 'exception_raise' (exc.defs).
|
||||
#pragma pack(4)
|
||||
|
@ -1273,7 +1354,7 @@ HandleFault(int signum, siginfo_t* info, void* ctx)
|
|||
// partly overlaps the end of the heap. In this case, it is an out-of-bounds
|
||||
// error and we should signal that properly, but to do so we must inspect
|
||||
// the operand of the failed access.
|
||||
activation->startInterrupt(pc, ContextToFP(context));
|
||||
activation->startInterrupt(ToRegisterState(context));
|
||||
*ppc = segment->unalignedAccessCode();
|
||||
return true;
|
||||
}
|
||||
|
@ -1397,7 +1478,7 @@ RedirectJitCodeToInterruptCheck(JSContext* cx, CONTEXT* context)
|
|||
if (activation->interrupted())
|
||||
return false;
|
||||
|
||||
activation->startInterrupt(pc, fp);
|
||||
activation->startInterrupt(ToRegisterState(context));
|
||||
*ContextToPC(context) = codeSegment->interruptCode();
|
||||
#endif
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче