зеркало из https://github.com/mozilla/gecko-dev.git
Backed out changeset a95360977f76 (bug 1428453) for arm build bustage
This commit is contained in:
Родитель
c921526073
Коммит
c241a94698
|
@ -3292,8 +3292,20 @@ MacroAssembler::wasmEmitOldTrapOutOfLineCode()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MOZ_ASSERT(site.trap != wasm::Trap::IndirectCallBadSig);
|
if (site.trap == wasm::Trap::IndirectCallBadSig) {
|
||||||
|
// The indirect call bad-signature trap is a special case for two
|
||||||
|
// reasons:
|
||||||
|
// - the check happens in the very first instructions of the
|
||||||
|
// prologue, before the stack frame has been set up which messes
|
||||||
|
// up everything (stack depth computations, unwinding)
|
||||||
|
// - the check happens in the callee while the trap should be
|
||||||
|
// reported at the caller's call_indirect
|
||||||
|
// To solve both problems at once, the out-of-line path (far) jumps
|
||||||
|
// directly to the trap exit stub. This takes advantage of the fact
|
||||||
|
// that there is already a CallSite for call_indirect and the
|
||||||
|
// current pre-prologue stack/register state.
|
||||||
|
append(wasm::OldTrapFarJump(site.trap, farJumpWithPatch()));
|
||||||
|
} else {
|
||||||
// Inherit the frame depth of the trap site. This value is captured
|
// Inherit the frame depth of the trap site. This value is captured
|
||||||
// by the wasm::CallSite to allow unwinding this frame.
|
// by the wasm::CallSite to allow unwinding this frame.
|
||||||
setFramePushed(site.framePushed);
|
setFramePushed(site.framePushed);
|
||||||
|
@ -3320,6 +3332,7 @@ MacroAssembler::wasmEmitOldTrapOutOfLineCode()
|
||||||
// the trapping instruction.
|
// the trapping instruction.
|
||||||
wasm::CallSiteDesc desc(site.offset, wasm::CallSiteDesc::OldTrapExit);
|
wasm::CallSiteDesc desc(site.offset, wasm::CallSiteDesc::OldTrapExit);
|
||||||
call(desc, site.trap);
|
call(desc, site.trap);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
// Traps do not return, so no need to freeStack().
|
// Traps do not return, so no need to freeStack().
|
||||||
|
|
|
@ -1646,12 +1646,7 @@ Simulator::handleWasmSegFault(int32_t addr, unsigned numBytes)
|
||||||
const wasm::ModuleSegment* moduleSegment = segment->asModule();
|
const wasm::ModuleSegment* moduleSegment = segment->asModule();
|
||||||
|
|
||||||
wasm::Instance* instance = wasm::LookupFaultingInstance(*moduleSegment, pc, fp);
|
wasm::Instance* instance = wasm::LookupFaultingInstance(*moduleSegment, pc, fp);
|
||||||
if (!instance)
|
if (!instance || !instance->memoryAccessInGuardRegion((uint8_t*)addr, numBytes))
|
||||||
return false;
|
|
||||||
|
|
||||||
MOZ_RELEASE_ASSERT(&instance->code() == &codeSegment.code());
|
|
||||||
|
|
||||||
if (!instance->memoryAccessInGuardRegion((uint8_t*)addr, numBytes))
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
const wasm::MemoryAccess* memoryAccess = instance->code().lookupMemoryAccess(pc);
|
const wasm::MemoryAccess* memoryAccess = instance->code().lookupMemoryAccess(pc);
|
||||||
|
|
|
@ -1823,27 +1823,13 @@ jit::JitActivation::wasmInterruptResumePC() const
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
jit::JitActivation::startWasmTrap(wasm::Trap trap, uint32_t bytecodeOffset,
|
jit::JitActivation::startWasmTrap(wasm::Trap trap, uint32_t bytecodeOffset, void* pc, void* fp)
|
||||||
const wasm::RegisterState& state)
|
|
||||||
{
|
{
|
||||||
bool unwound;
|
MOZ_ASSERT(pc);
|
||||||
wasm::UnwindState unwindState;
|
MOZ_ASSERT(fp);
|
||||||
MOZ_ALWAYS_TRUE(wasm::StartUnwinding(state, &unwindState, &unwound));
|
|
||||||
MOZ_ASSERT(unwound == (trap == wasm::Trap::IndirectCallBadSig));
|
|
||||||
|
|
||||||
void* pc = unwindState.pc;
|
|
||||||
wasm::Frame* fp = unwindState.fp;
|
|
||||||
|
|
||||||
const wasm::Code& code = fp->tls->instance->code();
|
|
||||||
MOZ_RELEASE_ASSERT(&code == wasm::LookupCode(pc));
|
|
||||||
|
|
||||||
// If the frame was unwound, the bytecodeOffset must be recovered from the
|
|
||||||
// callsite so that it is accurate.
|
|
||||||
if (unwound)
|
|
||||||
bytecodeOffset = code.lookupCallSite(pc)->lineOrBytecode();
|
|
||||||
|
|
||||||
cx_->runtime()->wasmUnwindData.ref().construct<wasm::TrapData>(pc, trap, bytecodeOffset);
|
cx_->runtime()->wasmUnwindData.ref().construct<wasm::TrapData>(pc, trap, bytecodeOffset);
|
||||||
setWasmExitFP(fp);
|
setWasmExitFP((wasm::Frame*)fp);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -1667,13 +1667,13 @@ class JitActivation : public Activation
|
||||||
// when the interrupt is handled.
|
// when the interrupt is handled.
|
||||||
|
|
||||||
// Returns true iff we've entered interrupted state.
|
// Returns true iff we've entered interrupted state.
|
||||||
bool startWasmInterrupt(const wasm::RegisterState& state);
|
bool startWasmInterrupt(const JS::ProfilingFrameIterator::RegisterState& state);
|
||||||
void finishWasmInterrupt();
|
void finishWasmInterrupt();
|
||||||
bool isWasmInterrupted() const;
|
bool isWasmInterrupted() const;
|
||||||
void* wasmInterruptUnwindPC() const;
|
void* wasmInterruptUnwindPC() const;
|
||||||
void* wasmInterruptResumePC() const;
|
void* wasmInterruptResumePC() const;
|
||||||
|
|
||||||
void startWasmTrap(wasm::Trap trap, uint32_t bytecodeOffset, const wasm::RegisterState& state);
|
void startWasmTrap(wasm::Trap trap, uint32_t bytecodeOffset, void* pc, void* fp);
|
||||||
void finishWasmTrap();
|
void finishWasmTrap();
|
||||||
bool isWasmTrapping() const;
|
bool isWasmTrapping() const;
|
||||||
void* wasmTrapPC() const;
|
void* wasmTrapPC() const;
|
||||||
|
|
|
@ -459,26 +459,18 @@ wasm::GenerateFunctionPrologue(MacroAssembler& masm, uint32_t framePushed, IsLea
|
||||||
masm.flushBuffer();
|
masm.flushBuffer();
|
||||||
masm.haltingAlign(CodeAlignment);
|
masm.haltingAlign(CodeAlignment);
|
||||||
|
|
||||||
// The table entry falls through into the normal entry after it has checked
|
// Generate table entry:
|
||||||
// the signature.
|
|
||||||
Label normalEntry;
|
|
||||||
|
|
||||||
// Generate table entry. The BytecodeOffset of the trap is fixed up to be
|
|
||||||
// the bytecode offset of the callsite by JitActivation::startWasmTrap.
|
|
||||||
offsets->begin = masm.currentOffset();
|
offsets->begin = masm.currentOffset();
|
||||||
|
OldTrapDesc trap(trapOffset, Trap::IndirectCallBadSig, 0);
|
||||||
switch (sigId.kind()) {
|
switch (sigId.kind()) {
|
||||||
case SigIdDesc::Kind::Global: {
|
case SigIdDesc::Kind::Global: {
|
||||||
Register scratch = WasmTableCallScratchReg;
|
Register scratch = WasmTableCallScratchReg;
|
||||||
masm.loadWasmGlobalPtr(sigId.globalDataOffset(), scratch);
|
masm.loadWasmGlobalPtr(sigId.globalDataOffset(), scratch);
|
||||||
masm.branchPtr(Assembler::Condition::Equal, WasmTableCallSigReg, scratch,
|
masm.branchPtr(Assembler::Condition::NotEqual, WasmTableCallSigReg, scratch, trap);
|
||||||
&normalEntry);
|
|
||||||
masm.wasmTrap(Trap::IndirectCallBadSig, BytecodeOffset(0));
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SigIdDesc::Kind::Immediate: {
|
case SigIdDesc::Kind::Immediate: {
|
||||||
masm.branch32(Assembler::Condition::Equal, WasmTableCallSigReg, Imm32(sigId.immediate()),
|
masm.branch32(Assembler::Condition::NotEqual, WasmTableCallSigReg, Imm32(sigId.immediate()), trap);
|
||||||
&normalEntry);
|
|
||||||
masm.wasmTrap(Trap::IndirectCallBadSig, BytecodeOffset(0));
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SigIdDesc::Kind::None:
|
case SigIdDesc::Kind::None:
|
||||||
|
@ -491,7 +483,6 @@ wasm::GenerateFunctionPrologue(MacroAssembler& masm, uint32_t framePushed, IsLea
|
||||||
|
|
||||||
// Generate normal entry:
|
// Generate normal entry:
|
||||||
masm.nopAlign(CodeAlignment);
|
masm.nopAlign(CodeAlignment);
|
||||||
masm.bind(&normalEntry);
|
|
||||||
GenerateCallablePrologue(masm, &offsets->normalEntry);
|
GenerateCallablePrologue(masm, &offsets->normalEntry);
|
||||||
|
|
||||||
// Tiering works as follows. The Code owns a jumpTable, which has one
|
// Tiering works as follows. The Code owns a jumpTable, which has one
|
||||||
|
@ -1281,21 +1272,20 @@ wasm::LookupFaultingInstance(const ModuleSegment& codeSegment, void* pc, void* f
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
size_t offsetInModule = ((uint8_t*)pc) - codeSegment.base();
|
size_t offsetInModule = ((uint8_t*)pc) - codeSegment.base();
|
||||||
if ((offsetInModule >= codeRange->funcNormalEntry() &&
|
if (offsetInModule < codeRange->funcNormalEntry() + SetFP)
|
||||||
offsetInModule < codeRange->funcNormalEntry() + SetFP) ||
|
return nullptr;
|
||||||
(offsetInModule >= codeRange->ret() - PoppedFP &&
|
if (offsetInModule >= codeRange->ret() - PoppedFP && offsetInModule <= codeRange->ret())
|
||||||
offsetInModule <= codeRange->ret()))
|
|
||||||
{
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
|
||||||
|
|
||||||
Instance* instance = reinterpret_cast<Frame*>(fp)->tls->instance;
|
Instance* instance = reinterpret_cast<Frame*>(fp)->tls->instance;
|
||||||
|
|
||||||
// TODO: In the special case of a cross-instance indirect call bad-signature
|
// TODO: when Trap::IndirectCallBadSig is converted away from being an
|
||||||
// fault, fp can point to the caller frame which is in a different
|
// OldTrap, this could become a release assert again. The reason for the
|
||||||
// instance/module than pc. This special case should go away when old-style
|
// check is the out-of-line trap stub for the table entry's signature check,
|
||||||
// traps go away and signal handling is reworked.
|
// which executes before fp has been updated.
|
||||||
//MOZ_RELEASE_ASSERT(&instance->code() == &codeSegment.code());
|
//MOZ_RELEASE_ASSERT(&instance->code() == &codeSegment.code());
|
||||||
|
if (&instance->code() != &codeSegment.code())
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1039,13 +1039,11 @@ HandleFault(PEXCEPTION_POINTERS exception)
|
||||||
if (!moduleSegment->code().lookupTrap(pc, &trap, &bytecode))
|
if (!moduleSegment->code().lookupTrap(pc, &trap, &bytecode))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
activation->startWasmTrap(trap, bytecode.offset, ToRegisterState(context));
|
activation->startWasmTrap(trap, bytecode.offset, pc, ContextToFP(context));
|
||||||
*ppc = moduleSegment->trapCode();
|
*ppc = moduleSegment->trapCode();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
MOZ_RELEASE_ASSERT(&instance->code() == &moduleSegment->code());
|
|
||||||
|
|
||||||
if (record->NumberParameters < 2)
|
if (record->NumberParameters < 2)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -1172,11 +1170,9 @@ HandleMachException(JSContext* cx, const ExceptionRequest& request)
|
||||||
if (!moduleSegment->code().lookupTrap(pc, &trap, &bytecode))
|
if (!moduleSegment->code().lookupTrap(pc, &trap, &bytecode))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
activation->startWasmTrap(trap, bytecode.offset, ToRegisterState(&context));
|
activation->startWasmTrap(trap, bytecode.offset, pc, ContextToFP(&context));
|
||||||
*ppc = moduleSegment->trapCode();
|
*ppc = moduleSegment->trapCode();
|
||||||
} else {
|
} else {
|
||||||
MOZ_RELEASE_ASSERT(&instance->code() == &moduleSegment->code());
|
|
||||||
|
|
||||||
MOZ_ASSERT(request.body.exception == EXC_BAD_ACCESS);
|
MOZ_ASSERT(request.body.exception == EXC_BAD_ACCESS);
|
||||||
if (request.body.codeCnt != 2)
|
if (request.body.codeCnt != 2)
|
||||||
return false;
|
return false;
|
||||||
|
@ -1398,13 +1394,11 @@ HandleFault(int signum, siginfo_t* info, void* ctx)
|
||||||
if (!moduleSegment->code().lookupTrap(pc, &trap, &bytecode))
|
if (!moduleSegment->code().lookupTrap(pc, &trap, &bytecode))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
activation->startWasmTrap(trap, bytecode.offset, ToRegisterState(context));
|
activation->startWasmTrap(trap, bytecode.offset, pc, ContextToFP(context));
|
||||||
*ppc = moduleSegment->trapCode();
|
*ppc = moduleSegment->trapCode();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
MOZ_RELEASE_ASSERT(&instance->code() == &moduleSegment->code());
|
|
||||||
|
|
||||||
uint8_t* faultingAddress = reinterpret_cast<uint8_t*>(info->si_addr);
|
uint8_t* faultingAddress = reinterpret_cast<uint8_t*>(info->si_addr);
|
||||||
|
|
||||||
// Although it's not strictly necessary, to make sure we're not covering up
|
// Although it's not strictly necessary, to make sure we're not covering up
|
||||||
|
|
|
@ -1730,14 +1730,14 @@ wasm::GenerateStubs(const ModuleEnvironment& env, const FuncImportVector& import
|
||||||
case Trap::InvalidConversionToInteger:
|
case Trap::InvalidConversionToInteger:
|
||||||
case Trap::IntegerDivideByZero:
|
case Trap::IntegerDivideByZero:
|
||||||
case Trap::IndirectCallToNull:
|
case Trap::IndirectCallToNull:
|
||||||
case Trap::IndirectCallBadSig:
|
|
||||||
case Trap::ImpreciseSimdConversion:
|
case Trap::ImpreciseSimdConversion:
|
||||||
case Trap::StackOverflow:
|
case Trap::StackOverflow:
|
||||||
case Trap::ThrowReported:
|
case Trap::ThrowReported:
|
||||||
break;
|
break;
|
||||||
// The TODO list of "old" traps to convert to new traps:
|
// The TODO list of "old" traps to convert to new traps:
|
||||||
case Trap::OutOfBounds:
|
case Trap::OutOfBounds:
|
||||||
case Trap::UnalignedAccess: {
|
case Trap::UnalignedAccess:
|
||||||
|
case Trap::IndirectCallBadSig: {
|
||||||
CallableOffsets offsets;
|
CallableOffsets offsets;
|
||||||
if (!GenerateOldTrapExit(masm, trap, &throwLabel, &offsets))
|
if (!GenerateOldTrapExit(masm, trap, &throwLabel, &offsets))
|
||||||
return false;
|
return false;
|
||||||
|
|
Загрузка…
Ссылка в новой задаче