diff --git a/js/src/jit/CodeGenerator.cpp b/js/src/jit/CodeGenerator.cpp index f8210c69f30a..f5814101fb07 100644 --- a/js/src/jit/CodeGenerator.cpp +++ b/js/src/jit/CodeGenerator.cpp @@ -9571,12 +9571,8 @@ CodeGenerator::generateWasm(wasm::SigIdDesc sigId, wasm::BytecodeOffset trapOffs // functions with small framePushed). Perform overflow-checking after // pushing framePushed to catch cases with really large frames. Label onOverflow; - if (!omitOverRecursedCheck()) { - masm.branchPtr(Assembler::AboveOrEqual, - Address(WasmTlsReg, offsetof(wasm::TlsData, stackLimit)), - masm.getStackPointer(), - &onOverflow); - } + if (!omitOverRecursedCheck()) + masm.wasmEmitStackCheck(masm.getStackPointer(), ABINonArgReg0, &onOverflow); if (!generateBody()) return false; diff --git a/js/src/jit/MacroAssembler.cpp b/js/src/jit/MacroAssembler.cpp index 40cd2dec2448..8fea6a88f0ee 100644 --- a/js/src/jit/MacroAssembler.cpp +++ b/js/src/jit/MacroAssembler.cpp @@ -3090,6 +3090,17 @@ MacroAssembler::wasmAssertNonExitInvariants(Register activation) #endif } +void +MacroAssembler::wasmEmitStackCheck(Register sp, Register scratch, Label* onOverflow) +{ + loadPtr(Address(WasmTlsReg, offsetof(wasm::TlsData, addressOfContext)), scratch); + loadPtr(Address(scratch, 0), scratch); + branchPtr(Assembler::AboveOrEqual, + Address(scratch, offsetof(JSContext, jitStackLimitNoInterrupt)), + sp, + onOverflow); +} + //}}} check_macroassembler_style void diff --git a/js/src/jit/MacroAssembler.h b/js/src/jit/MacroAssembler.h index bb7b0079e309..26b9a4e9ce7e 100644 --- a/js/src/jit/MacroAssembler.h +++ b/js/src/jit/MacroAssembler.h @@ -1479,6 +1479,9 @@ class MacroAssembler : public MacroAssemblerSpecific // Assert invariants that should be true within any non-exit-stub wasm code. void wasmAssertNonExitInvariants(Register activation); + // Perform a stack-overflow test, branching to the given Label on overflow. + void wasmEmitStackCheck(Register sp, Register scratch, Label* onOverflow); + public: // ======================================================================== // Clamping functions. diff --git a/js/src/vm/Debugger.cpp b/js/src/vm/Debugger.cpp index 5c1e3be152de..6595bad2d04d 100644 --- a/js/src/vm/Debugger.cpp +++ b/js/src/vm/Debugger.cpp @@ -8057,7 +8057,8 @@ DebuggerFrame::setOnStepHandler(JSContext* cx, HandleDebuggerFrame frame, OnStep return false; } else if (!handler && prior) { // Single stepping toggled on->off. - if (!instance->debug().decrementStepModeCount(cx, wasmFrame->funcIndex())) + FreeOp* fop = cx->runtime()->defaultFreeOp(); + if (!instance->debug().decrementStepModeCount(fop, wasmFrame->funcIndex())) return false; } } else { @@ -8391,8 +8392,7 @@ DebuggerFrame_maybeDecrementFrameScriptStepModeCount(FreeOp* fop, AbstractFrameP return; if (frame.isWasmDebugFrame()) { wasm::Instance* instance = frame.wasmInstance(); - instance->debug().decrementStepModeCount(instance->cx(), - frame.asWasmDebugFrame()->funcIndex()); + instance->debug().decrementStepModeCount(fop, frame.asWasmDebugFrame()->funcIndex()); } else { frame.script()->decrementStepModeCount(fop); } diff --git a/js/src/vm/Stack.cpp b/js/src/vm/Stack.cpp index 93b10c5c4493..2a2a9ae82b1a 100644 --- a/js/src/vm/Stack.cpp +++ b/js/src/vm/Stack.cpp @@ -1684,9 +1684,7 @@ WasmActivation::startInterrupt(void* pc, uint8_t* fp) cx_->runtime()->setWasmResumePC(pc); exitFP_ = reinterpret_cast(fp); - MOZ_ASSERT(cx() == exitFP_->tls->cx); MOZ_ASSERT(compartment() == exitFP_->tls->instance->compartment()); - MOZ_ASSERT(interrupted()); } diff --git a/js/src/wasm/WasmBaselineCompile.cpp b/js/src/wasm/WasmBaselineCompile.cpp index 583a7f9931dd..d8eda0f9a629 100644 --- a/js/src/wasm/WasmBaselineCompile.cpp +++ b/js/src/wasm/WasmBaselineCompile.cpp @@ -2225,14 +2225,11 @@ class BaseCompiler // be (we may need arbitrary spill slots and outgoing param slots) so // emit a patchable add that is patched in endFunction(). // - // ScratchReg may be used by branchPtr(), so use ABINonArgReg0 for the - // effective address. + // ScratchReg may be used by branchPtr(), so use ABINonArgReg0/1 for + // temporaries. stackAddOffset_ = masm.add32ToPtrWithPatch(StackPointer, ABINonArgReg0); - masm.branchPtr(Assembler::AboveOrEqual, - Address(WasmTlsReg, offsetof(TlsData, stackLimit)), - ABINonArgReg0, - &stackOverflowLabel_); + masm.wasmEmitStackCheck(ABINonArgReg0, ABINonArgReg1, &stackOverflowLabel_); // Copy arguments from registers to stack. diff --git a/js/src/wasm/WasmDebug.cpp b/js/src/wasm/WasmDebug.cpp index afc8d1eb781c..87c853c382ed 100644 --- a/js/src/wasm/WasmDebug.cpp +++ b/js/src/wasm/WasmDebug.cpp @@ -345,7 +345,7 @@ DebugState::incrementStepModeCount(JSContext* cx, uint32_t funcIndex) } bool -DebugState::decrementStepModeCount(JSContext* cx, uint32_t funcIndex) +DebugState::decrementStepModeCount(FreeOp* fop, uint32_t funcIndex) { MOZ_ASSERT(debugEnabled()); const CodeRange& codeRange = codeRanges(Tier::Debug)[debugFuncToCodeRangeIndex(funcIndex)]; @@ -359,7 +359,7 @@ DebugState::decrementStepModeCount(JSContext* cx, uint32_t funcIndex) stepModeCounters_.remove(p); - AutoWritableJitCode awjc(cx->runtime(), code_->segment(Tier::Debug).base() + codeRange.begin(), + AutoWritableJitCode awjc(fop->runtime(), code_->segment(Tier::Debug).base() + codeRange.begin(), codeRange.end() - codeRange.begin()); AutoFlushICache afc("Code::decrementStepModeCount"); diff --git a/js/src/wasm/WasmDebug.h b/js/src/wasm/WasmDebug.h index 94fec7a3857a..52a268e51dd8 100644 --- a/js/src/wasm/WasmDebug.h +++ b/js/src/wasm/WasmDebug.h @@ -137,7 +137,7 @@ class DebugState bool stepModeEnabled(uint32_t funcIndex) const; bool incrementStepModeCount(JSContext* cx, uint32_t funcIndex); - bool decrementStepModeCount(JSContext* cx, uint32_t funcIndex); + bool decrementStepModeCount(FreeOp* fop, uint32_t funcIndex); // Stack inspection helpers. diff --git a/js/src/wasm/WasmFrameIterator.cpp b/js/src/wasm/WasmFrameIterator.cpp index 13ebff0d5367..3e40e431e33b 100644 --- a/js/src/wasm/WasmFrameIterator.cpp +++ b/js/src/wasm/WasmFrameIterator.cpp @@ -309,7 +309,8 @@ LoadActivation(MacroAssembler& masm, Register dest) { // WasmCall pushes a WasmActivation and an inactive JitActivation. The // JitActivation only becomes active when calling into JS from wasm. - masm.loadPtr(Address(WasmTlsReg, offsetof(wasm::TlsData, cx)), dest); + masm.loadPtr(Address(WasmTlsReg, offsetof(wasm::TlsData, addressOfContext)), dest); + masm.loadPtr(Address(dest, 0), dest); masm.loadPtr(Address(dest, JSContext::offsetOfActivation()), dest); masm.loadPtr(Address(dest, Activation::offsetOfPrev()), dest); } diff --git a/js/src/wasm/WasmInstance.cpp b/js/src/wasm/WasmInstance.cpp index 6e1297948663..951b829b8850 100644 --- a/js/src/wasm/WasmInstance.cpp +++ b/js/src/wasm/WasmInstance.cpp @@ -256,7 +256,7 @@ Instance::callImport(JSContext* cx, uint32_t funcImportIndex, unsigned argc, con /* static */ int32_t Instance::callImport_void(Instance* instance, int32_t funcImportIndex, int32_t argc, uint64_t* argv) { - JSContext* cx = instance->cx(); + JSContext* cx = TlsContext.get(); RootedValue rval(cx); return instance->callImport(cx, funcImportIndex, argc, argv, &rval); } @@ -264,7 +264,7 @@ Instance::callImport_void(Instance* instance, int32_t funcImportIndex, int32_t a /* static */ int32_t Instance::callImport_i32(Instance* instance, int32_t funcImportIndex, int32_t argc, uint64_t* argv) { - JSContext* cx = instance->cx(); + JSContext* cx = TlsContext.get(); RootedValue rval(cx); if (!instance->callImport(cx, funcImportIndex, argc, argv, &rval)) return false; @@ -275,7 +275,7 @@ Instance::callImport_i32(Instance* instance, int32_t funcImportIndex, int32_t ar /* static */ int32_t Instance::callImport_i64(Instance* instance, int32_t funcImportIndex, int32_t argc, uint64_t* argv) { - JSContext* cx = instance->cx(); + JSContext* cx = TlsContext.get(); RootedValue rval(cx); if (!instance->callImport(cx, funcImportIndex, argc, argv, &rval)) return false; @@ -286,7 +286,7 @@ Instance::callImport_i64(Instance* instance, int32_t funcImportIndex, int32_t ar /* static */ int32_t Instance::callImport_f64(Instance* instance, int32_t funcImportIndex, int32_t argc, uint64_t* argv) { - JSContext* cx = instance->cx(); + JSContext* cx = TlsContext.get(); RootedValue rval(cx); if (!instance->callImport(cx, funcImportIndex, argc, argv, &rval)) return false; @@ -299,7 +299,7 @@ Instance::growMemory_i32(Instance* instance, uint32_t delta) { MOZ_ASSERT(!instance->isAsmJS()); - JSContext* cx = instance->cx(); + JSContext* cx = TlsContext.get(); RootedWasmMemoryObject memory(cx, instance->memory_); uint32_t ret = WasmMemoryObject::grow(memory, delta, cx); @@ -343,14 +343,13 @@ Instance::Instance(JSContext* cx, #endif MOZ_ASSERT(tables_.length() == metadata().tables.length()); - tlsData()->cx = cx; - tlsData()->instance = this; - tlsData()->globalData = globals_->globalData(); tlsData()->memoryBase = memory ? memory->buffer().dataPointerEither().unwrap() : nullptr; #ifndef WASM_HUGE_MEMORY tlsData()->boundsCheckLimit = memory ? memory->buffer().wasmBoundsCheckLimit() : 0; #endif - tlsData()->stackLimit = *(void**)cx->stackLimitAddressForJitCode(JS::StackForUntrustedScript); + tlsData()->globalData = globals_->globalData(); + tlsData()->instance = this; + tlsData()->addressOfContext = (JSContext**)object->zone()->group()->addressOfOwnerContext(); Tier callerTier = Tier::TBD; Tier calleeTier = Tier::TBD; diff --git a/js/src/wasm/WasmInstance.h b/js/src/wasm/WasmInstance.h index 9207af777594..38493942531b 100644 --- a/js/src/wasm/WasmInstance.h +++ b/js/src/wasm/WasmInstance.h @@ -104,7 +104,6 @@ class Instance bool init(JSContext* cx); void trace(JSTracer* trc); - JSContext* cx() const { return tlsData()->cx; } JSCompartment* compartment() const { return compartment_; } const Code& code() const { return *code_; } DebugState& debug() { return *debug_; } diff --git a/js/src/wasm/WasmStubs.cpp b/js/src/wasm/WasmStubs.cpp index 4ef101ae562f..daf84ae20551 100644 --- a/js/src/wasm/WasmStubs.cpp +++ b/js/src/wasm/WasmStubs.cpp @@ -736,7 +736,8 @@ wasm::GenerateImportJitExit(MacroAssembler& masm, const FuncImport& fi, Label* t Register act = WasmIonExitRegE1; // JitActivation* act = cx->activation(); - masm.loadPtr(Address(WasmTlsReg, offsetof(TlsData, cx)), cx); + masm.loadPtr(Address(WasmTlsReg, offsetof(TlsData, addressOfContext)), cx); + masm.loadPtr(Address(cx, 0), cx); masm.loadPtr(Address(cx, JSContext::offsetOfActivation()), act); // act.active_ = true; @@ -772,7 +773,8 @@ wasm::GenerateImportJitExit(MacroAssembler& masm, const FuncImport& fi, Label* t Register tmp = WasmIonExitRegD2; // JitActivation* act = cx->activation(); - masm.loadPtr(Address(WasmTlsReg, offsetof(TlsData, cx)), cx); + masm.loadPtr(Address(WasmTlsReg, offsetof(TlsData, addressOfContext)), cx); + masm.loadPtr(Address(cx, 0), cx); masm.loadPtr(Address(cx, JSContext::offsetOfActivation()), act); // cx->jitTop = act->prevJitTop_; diff --git a/js/src/wasm/WasmTypes.h b/js/src/wasm/WasmTypes.h index f8fe543546ea..ad166e930a29 100644 --- a/js/src/wasm/WasmTypes.h +++ b/js/src/wasm/WasmTypes.h @@ -1287,15 +1287,6 @@ struct ExportArg struct TlsData { - // Pointer to the JSContext that contains this TLS data. - JSContext* cx; - - // Pointer to the Instance that contains this TLS data. - Instance* instance; - - // Pointer to the global data for this Instance. - uint8_t* globalData; - // Pointer to the base of the default memory (or null if there is none). uint8_t* memoryBase; @@ -1304,10 +1295,14 @@ struct TlsData uint32_t boundsCheckLimit; #endif - // Stack limit for the current thread. This limit is checked against the - // stack pointer in the prologue of functions that allocate stack space. See - // `CodeGenerator::generateWasm`. - void* stackLimit; + // Pointer to the global data for this Instance. + uint8_t* globalData; + + // Pointer to the Instance that contains this TLS data. + Instance* instance; + + // Shortcut to instance->zone->group->addressOfOwnerContext + JSContext** addressOfContext; // The globalArea must be the last field. Globals for the module start here // and are inline in this structure. 16-byte alignment is required for SIMD