зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1471169 - Implement realm switching for Wasm calls. r=luke
This commit is contained in:
Родитель
e62f5044db
Коммит
62bb224959
|
@ -726,3 +726,44 @@ assertEq(e.call(), 1090);
|
|||
// Test the error path in the arguments rectifier.
|
||||
assertErrorMessage(() => i.missTwo(1337), Error, "a FFI to believe in");
|
||||
})();
|
||||
|
||||
(function testCrossRealmImport() {
|
||||
var g = newGlobal({sameCompartmentAs: this});
|
||||
g.evaluate("function f1() { assertCorrectRealm(); return 123; }");
|
||||
g.mem = new Memory({initial:8});
|
||||
|
||||
// The current_memory builtin asserts cx->realm matches instance->realm so
|
||||
// we call it here.
|
||||
var i1 = new Instance(new Module(wasmTextToBinary(`
|
||||
(module
|
||||
(import $imp1 "a" "f1" (result i32))
|
||||
(import $imp2 "a" "f2" (result i32))
|
||||
(import "a" "m" (memory 1))
|
||||
(func $test (result i32)
|
||||
(i32.add
|
||||
(i32.add
|
||||
(i32.add (current_memory) (call $imp1))
|
||||
(current_memory))
|
||||
(call $imp2)))
|
||||
(export "impstub" $imp1)
|
||||
(export "test" $test))
|
||||
`)), {a:{m:g.mem, f1:g.f1, f2:g.Math.abs}});
|
||||
|
||||
for (var i = 0; i < 20; i++) {
|
||||
assertEq(i1.exports.impstub(), 123);
|
||||
assertEq(i1.exports.test(), 139);
|
||||
}
|
||||
|
||||
// Inter-module/inter-realm wasm => wasm calls.
|
||||
var src = `
|
||||
(module
|
||||
(import $imp "a" "othertest" (result i32))
|
||||
(import "a" "m" (memory 1))
|
||||
(func (result i32) (i32.add (call $imp) (current_memory)))
|
||||
(export "test" 1))
|
||||
`;
|
||||
g.i1 = i1;
|
||||
g.evaluate("i2 = new WebAssembly.Instance(new WebAssembly.Module(wasmTextToBinary(`" + src + "`)), {a:{m:mem,othertest:i1.exports.test}})");
|
||||
for (var i = 0; i < 20; i++)
|
||||
assertEq(g.i2.exports.test(), 147);
|
||||
})();
|
||||
|
|
|
@ -201,3 +201,32 @@ var tbl = wasmEvalText(`(module (table (export "tbl") anyfunc (elem $f)) (func $
|
|||
tbl.get(0).foo = 42;
|
||||
gc();
|
||||
assertEq(tbl.get(0).foo, 42);
|
||||
|
||||
(function testCrossRealmCall() {
|
||||
var g = newGlobal({sameCompartmentAs: this});
|
||||
|
||||
// The current_memory builtin asserts cx->realm matches instance->realm so
|
||||
// we call it here.
|
||||
var src = `
|
||||
(module
|
||||
(import "a" "t" (table 3 anyfunc))
|
||||
(import "a" "m" (memory 1))
|
||||
(func $f (result i32) (i32.add (i32.const 3) (current_memory)))
|
||||
(elem (i32.const 0) $f))
|
||||
`;
|
||||
g.mem = new Memory({initial:4});
|
||||
g.tbl = new Table({initial:3, element:"anyfunc"});
|
||||
var i1 = g.evaluate("new WebAssembly.Instance(new WebAssembly.Module(wasmTextToBinary(`" + src + "`)), {a:{t:tbl,m:mem}})");
|
||||
|
||||
var call = new Instance(new Module(wasmTextToBinary(`
|
||||
(module
|
||||
(import "a" "t" (table 3 anyfunc))
|
||||
(import "a" "m" (memory 1))
|
||||
(type $v2i (func (result i32)))
|
||||
(func $call (param $i i32) (result i32) (i32.add (call_indirect $v2i (get_local $i)) (current_memory)))
|
||||
(export "call" $call))
|
||||
`)), {a:{t:g.tbl,m:g.mem}}).exports.call;
|
||||
|
||||
for (var i = 0; i < 10; i++)
|
||||
assertEq(call(0), 11);
|
||||
})();
|
||||
|
|
|
@ -7123,6 +7123,7 @@ CodeGenerator::emitWasmCallBase(MWasmCall* mir, bool needsBoundsCheck)
|
|||
// TLS and pinned regs. The only case where where we don't have to reload
|
||||
// the TLS and pinned regs is when the callee preserves them.
|
||||
bool reloadRegs = true;
|
||||
bool switchRealm = true;
|
||||
|
||||
const wasm::CallSiteDesc& desc = mir->desc();
|
||||
const wasm::CalleeDesc& callee = mir->callee();
|
||||
|
@ -7130,6 +7131,7 @@ CodeGenerator::emitWasmCallBase(MWasmCall* mir, bool needsBoundsCheck)
|
|||
case wasm::CalleeDesc::Func:
|
||||
masm.call(desc, callee.funcIndex());
|
||||
reloadRegs = false;
|
||||
switchRealm = false;
|
||||
break;
|
||||
case wasm::CalleeDesc::Import:
|
||||
masm.wasmCallImport(desc, callee);
|
||||
|
@ -7137,22 +7139,30 @@ CodeGenerator::emitWasmCallBase(MWasmCall* mir, bool needsBoundsCheck)
|
|||
case wasm::CalleeDesc::AsmJSTable:
|
||||
case wasm::CalleeDesc::WasmTable:
|
||||
masm.wasmCallIndirect(desc, callee, needsBoundsCheck);
|
||||
reloadRegs = callee.which() == wasm::CalleeDesc::WasmTable && callee.wasmTableIsExternal();
|
||||
reloadRegs = switchRealm =
|
||||
(callee.which() == wasm::CalleeDesc::WasmTable && callee.wasmTableIsExternal());
|
||||
break;
|
||||
case wasm::CalleeDesc::Builtin:
|
||||
masm.call(desc, callee.builtin());
|
||||
reloadRegs = false;
|
||||
switchRealm = false;
|
||||
break;
|
||||
case wasm::CalleeDesc::BuiltinInstanceMethod:
|
||||
masm.wasmCallBuiltinInstanceMethod(desc, mir->instanceArg(), callee.builtin());
|
||||
switchRealm = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (reloadRegs) {
|
||||
masm.loadWasmTlsRegFromFrame();
|
||||
masm.loadWasmPinnedRegsFromTls();
|
||||
if (switchRealm)
|
||||
masm.switchToWasmTlsRealm(ABINonArgReturnReg0, ABINonArgReturnReg1);
|
||||
} else {
|
||||
MOZ_ASSERT(!switchRealm);
|
||||
}
|
||||
|
||||
|
||||
if (mir->spIncrement())
|
||||
masm.reserveStack(mir->spIncrement());
|
||||
}
|
||||
|
|
|
@ -1825,6 +1825,14 @@ MacroAssembler::switchToBaselineFrameRealm(Register scratch)
|
|||
switchToObjectRealm(scratch, scratch);
|
||||
}
|
||||
|
||||
void
|
||||
MacroAssembler::switchToWasmTlsRealm(Register scratch1, Register scratch2)
|
||||
{
|
||||
loadPtr(Address(WasmTlsReg, offsetof(wasm::TlsData, cx)), scratch1);
|
||||
loadPtr(Address(WasmTlsReg, offsetof(wasm::TlsData, realm)), scratch2);
|
||||
storePtr(scratch2, Address(scratch1, JSContext::offsetOfRealm()));
|
||||
}
|
||||
|
||||
void
|
||||
MacroAssembler::debugAssertContextRealm(const void* realm, Register scratch)
|
||||
{
|
||||
|
@ -3530,6 +3538,11 @@ MacroAssembler::wasmCallImport(const wasm::CallSiteDesc& desc, const wasm::Calle
|
|||
static_assert(ABINonArgReg0 != WasmTlsReg, "by constraint");
|
||||
#endif
|
||||
|
||||
// Switch to the callee's realm.
|
||||
loadWasmGlobalPtr(globalDataOffset + offsetof(wasm::FuncImportTls, realm), ABINonArgReg1);
|
||||
loadPtr(Address(WasmTlsReg, offsetof(wasm::TlsData, cx)), ABINonArgReg2);
|
||||
storePtr(ABINonArgReg1, Address(ABINonArgReg2, JSContext::offsetOfRealm()));
|
||||
|
||||
// Switch to the callee's TLS and pinned registers and make the call.
|
||||
loadWasmGlobalPtr(globalDataOffset + offsetof(wasm::FuncImportTls, tls), WasmTlsReg);
|
||||
loadWasmPinnedRegsFromTls();
|
||||
|
@ -3562,7 +3575,7 @@ void
|
|||
MacroAssembler::wasmCallIndirect(const wasm::CallSiteDesc& desc, const wasm::CalleeDesc& callee,
|
||||
bool needsBoundsCheck)
|
||||
{
|
||||
Register scratch = WasmTableCallScratchReg;
|
||||
Register scratch = WasmTableCallScratchReg0;
|
||||
Register index = WasmTableCallIndexReg;
|
||||
|
||||
if (callee.which() == wasm::CalleeDesc::AsmJSTable) {
|
||||
|
@ -3623,6 +3636,7 @@ MacroAssembler::wasmCallIndirect(const wasm::CallSiteDesc& desc, const wasm::Cal
|
|||
bind(&nonNull);
|
||||
|
||||
loadWasmPinnedRegsFromTls();
|
||||
switchToWasmTlsRealm(index, WasmTableCallScratchReg1);
|
||||
|
||||
loadPtr(Address(scratch, offsetof(wasm::ExternalTableElem, code)), scratch);
|
||||
} else {
|
||||
|
|
|
@ -2017,6 +2017,7 @@ class MacroAssembler : public MacroAssemblerSpecific
|
|||
void switchToRealm(const void* realm, Register scratch);
|
||||
void switchToObjectRealm(Register obj, Register scratch);
|
||||
void switchToBaselineFrameRealm(Register scratch);
|
||||
void switchToWasmTlsRealm(Register scratch1, Register scratch2);
|
||||
void debugAssertContextRealm(const void* realm, Register scratch);
|
||||
|
||||
void loadJitActivation(Register dest) {
|
||||
|
|
|
@ -119,6 +119,7 @@ bool IsUnaligned(const wasm::MemoryAccessDesc& access);
|
|||
static constexpr Register ABINonArgReg0 = r4;
|
||||
static constexpr Register ABINonArgReg1 = r5;
|
||||
static constexpr Register ABINonArgReg2 = r6;
|
||||
static constexpr Register ABINonArgReg3 = r7;
|
||||
|
||||
// This register may be volatile or nonvolatile. Avoid d15 which is the
|
||||
// ScratchDoubleReg.
|
||||
|
@ -142,9 +143,10 @@ static constexpr Register WasmTlsReg = r9;
|
|||
|
||||
// Registers used for wasm table calls. These registers must be disjoint
|
||||
// from the ABI argument registers, WasmTlsReg and each other.
|
||||
static constexpr Register WasmTableCallScratchReg = ABINonArgReg0;
|
||||
static constexpr Register WasmTableCallSigReg = ABINonArgReg1;
|
||||
static constexpr Register WasmTableCallIndexReg = ABINonArgReg2;
|
||||
static constexpr Register WasmTableCallScratchReg0 = ABINonArgReg0;
|
||||
static constexpr Register WasmTableCallScratchReg1 = ABINonArgReg1;
|
||||
static constexpr Register WasmTableCallSigReg = ABINonArgReg2;
|
||||
static constexpr Register WasmTableCallIndexReg = ABINonArgReg3;
|
||||
|
||||
static constexpr Register PreBarrierReg = r1;
|
||||
|
||||
|
|
|
@ -438,6 +438,7 @@ class ABIArgGenerator
|
|||
static constexpr Register ABINonArgReg0 = r8;
|
||||
static constexpr Register ABINonArgReg1 = r9;
|
||||
static constexpr Register ABINonArgReg2 = r10;
|
||||
static constexpr Register ABINonArgReg3 = r11;
|
||||
|
||||
// This register may be volatile or nonvolatile. Avoid d31 which is the
|
||||
// ScratchDoubleReg.
|
||||
|
@ -461,9 +462,10 @@ static constexpr Register WasmTlsReg { Registers::x23 };
|
|||
|
||||
// Registers used for wasm table calls. These registers must be disjoint
|
||||
// from the ABI argument registers, WasmTlsReg and each other.
|
||||
static constexpr Register WasmTableCallScratchReg = ABINonArgReg0;
|
||||
static constexpr Register WasmTableCallSigReg = ABINonArgReg1;
|
||||
static constexpr Register WasmTableCallIndexReg = ABINonArgReg2;
|
||||
static constexpr Register WasmTableCallScratchReg0 = ABINonArgReg0;
|
||||
static constexpr Register WasmTableCallScratchReg1 = ABINonArgReg1;
|
||||
static constexpr Register WasmTableCallSigReg = ABINonArgReg2;
|
||||
static constexpr Register WasmTableCallIndexReg = ABINonArgReg3;
|
||||
|
||||
static inline bool
|
||||
GetIntArgReg(uint32_t usedIntArgs, uint32_t usedFloatArgs, Register* out)
|
||||
|
|
|
@ -68,6 +68,7 @@ static constexpr Register64 ReturnReg64(InvalidReg);
|
|||
static constexpr Register ABINonArgReg0 { Registers::invalid_reg };
|
||||
static constexpr Register ABINonArgReg1 { Registers::invalid_reg };
|
||||
static constexpr Register ABINonArgReg2 { Registers::invalid_reg };
|
||||
static constexpr Register ABINonArgReg3 { Registers::invalid_reg };
|
||||
static constexpr Register ABINonArgReturnReg0 { Registers::invalid_reg };
|
||||
static constexpr Register ABINonArgReturnReg1 { Registers::invalid_reg };
|
||||
static constexpr Register ABINonVolatileReg { Registers::invalid_reg };
|
||||
|
@ -75,7 +76,8 @@ static constexpr Register ABINonArgReturnVolatileReg { Registers::invalid_reg };
|
|||
|
||||
static constexpr FloatRegister ABINonArgDoubleReg = { FloatRegisters::invalid_reg };
|
||||
|
||||
static constexpr Register WasmTableCallScratchReg { Registers::invalid_reg };
|
||||
static constexpr Register WasmTableCallScratchReg0 { Registers::invalid_reg };
|
||||
static constexpr Register WasmTableCallScratchReg1 { Registers::invalid_reg };
|
||||
static constexpr Register WasmTableCallSigReg { Registers::invalid_reg };
|
||||
static constexpr Register WasmTableCallIndexReg { Registers::invalid_reg };
|
||||
static constexpr Register WasmTlsReg { Registers::invalid_reg };
|
||||
|
|
|
@ -181,6 +181,7 @@ class ABIArgGenerator
|
|||
static constexpr Register ABINonArgReg0 = rax;
|
||||
static constexpr Register ABINonArgReg1 = rbx;
|
||||
static constexpr Register ABINonArgReg2 = r10;
|
||||
static constexpr Register ABINonArgReg3 = r12;
|
||||
|
||||
// This register may be volatile or nonvolatile. Avoid xmm15 which is the
|
||||
// ScratchDoubleReg.
|
||||
|
@ -204,9 +205,10 @@ static constexpr Register WasmTlsReg = r14;
|
|||
|
||||
// Registers used for asm.js/wasm table calls. These registers must be disjoint
|
||||
// from the ABI argument registers, WasmTlsReg and each other.
|
||||
static constexpr Register WasmTableCallScratchReg = ABINonArgReg0;
|
||||
static constexpr Register WasmTableCallSigReg = ABINonArgReg1;
|
||||
static constexpr Register WasmTableCallIndexReg = ABINonArgReg2;
|
||||
static constexpr Register WasmTableCallScratchReg0 = ABINonArgReg0;
|
||||
static constexpr Register WasmTableCallScratchReg1 = ABINonArgReg1;
|
||||
static constexpr Register WasmTableCallSigReg = ABINonArgReg2;
|
||||
static constexpr Register WasmTableCallIndexReg = ABINonArgReg3;
|
||||
|
||||
static constexpr Register OsrFrameReg = IntArgReg3;
|
||||
|
||||
|
|
|
@ -83,6 +83,7 @@ class ABIArgGenerator
|
|||
static constexpr Register ABINonArgReg0 = eax;
|
||||
static constexpr Register ABINonArgReg1 = ebx;
|
||||
static constexpr Register ABINonArgReg2 = ecx;
|
||||
static constexpr Register ABINonArgReg3 = edx;
|
||||
|
||||
// This register may be volatile or nonvolatile. Avoid xmm7 which is the
|
||||
// ScratchDoubleReg.
|
||||
|
@ -106,9 +107,10 @@ static constexpr Register WasmTlsReg = esi;
|
|||
|
||||
// Registers used for asm.js/wasm table calls. These registers must be disjoint
|
||||
// from the ABI argument registers, WasmTlsReg and each other.
|
||||
static constexpr Register WasmTableCallScratchReg = ABINonArgReg0;
|
||||
static constexpr Register WasmTableCallSigReg = ABINonArgReg1;
|
||||
static constexpr Register WasmTableCallIndexReg = ABINonArgReg2;
|
||||
static constexpr Register WasmTableCallScratchReg0 = ABINonArgReg0;
|
||||
static constexpr Register WasmTableCallScratchReg1 = ABINonArgReg1;
|
||||
static constexpr Register WasmTableCallSigReg = ABINonArgReg2;
|
||||
static constexpr Register WasmTableCallIndexReg = ABINonArgReg3;
|
||||
|
||||
static constexpr Register OsrFrameReg = edx;
|
||||
static constexpr Register PreBarrierReg = edx;
|
||||
|
|
|
@ -3522,7 +3522,7 @@ class BaseCompiler final : public BaseCompilerInterface
|
|||
{
|
||||
explicit FunctionCall(uint32_t lineOrBytecode)
|
||||
: lineOrBytecode(lineOrBytecode),
|
||||
reloadMachineStateAfter(false),
|
||||
isInterModule(false),
|
||||
usesSystemAbi(false),
|
||||
#ifdef JS_CODEGEN_ARM
|
||||
hardFP(true),
|
||||
|
@ -3533,7 +3533,7 @@ class BaseCompiler final : public BaseCompilerInterface
|
|||
|
||||
uint32_t lineOrBytecode;
|
||||
ABIArgGenerator abi;
|
||||
bool reloadMachineStateAfter;
|
||||
bool isInterModule;
|
||||
bool usesSystemAbi;
|
||||
#ifdef JS_CODEGEN_ARM
|
||||
bool hardFP;
|
||||
|
@ -3544,7 +3544,7 @@ class BaseCompiler final : public BaseCompilerInterface
|
|||
|
||||
void beginCall(FunctionCall& call, UseABI useABI, InterModule interModule)
|
||||
{
|
||||
call.reloadMachineStateAfter = interModule == InterModule::True || useABI == UseABI::System;
|
||||
call.isInterModule = interModule == InterModule::True;
|
||||
call.usesSystemAbi = useABI == UseABI::System;
|
||||
|
||||
if (call.usesSystemAbi) {
|
||||
|
@ -3575,7 +3575,11 @@ class BaseCompiler final : public BaseCompilerInterface
|
|||
size_t adjustment = call.stackArgAreaSize + call.frameAlignAdjustment;
|
||||
fr.freeArgAreaAndPopBytes(adjustment, stackSpace);
|
||||
|
||||
if (call.reloadMachineStateAfter) {
|
||||
if (call.isInterModule) {
|
||||
masm.loadWasmTlsRegFromFrame();
|
||||
masm.loadWasmPinnedRegsFromTls();
|
||||
masm.switchToWasmTlsRealm(ABINonArgReturnReg0, ABINonArgReturnReg1);
|
||||
} else if (call.usesSystemAbi) {
|
||||
// On x86 there are no pinned registers, so don't waste time
|
||||
// reloading the Tls.
|
||||
#ifndef JS_CODEGEN_X86
|
||||
|
|
|
@ -530,7 +530,7 @@ wasm::GenerateFunctionPrologue(MacroAssembler& masm, const FuncTypeIdDesc& funcT
|
|||
offsets->begin = masm.currentOffset();
|
||||
switch (funcTypeId.kind()) {
|
||||
case FuncTypeIdDesc::Kind::Global: {
|
||||
Register scratch = WasmTableCallScratchReg;
|
||||
Register scratch = WasmTableCallScratchReg0;
|
||||
masm.loadWasmGlobalPtr(funcTypeId.globalDataOffset(), scratch);
|
||||
masm.branchPtr(Assembler::Condition::Equal, WasmTableCallSigReg, scratch,
|
||||
&normalEntry);
|
||||
|
|
|
@ -108,6 +108,8 @@ bool
|
|||
Instance::callImport(JSContext* cx, uint32_t funcImportIndex, unsigned argc, const uint64_t* argv,
|
||||
MutableHandleValue rval)
|
||||
{
|
||||
AssertRealmUnchanged aru(cx);
|
||||
|
||||
Tier tier = code().bestTier();
|
||||
|
||||
const FuncImport& fi = metadata(tier).funcImports[funcImportIndex];
|
||||
|
@ -151,6 +153,8 @@ Instance::callImport(JSContext* cx, uint32_t funcImportIndex, unsigned argc, con
|
|||
|
||||
FuncImportTls& import = funcImportTls(fi);
|
||||
RootedFunction importFun(cx, &import.obj->as<JSFunction>());
|
||||
MOZ_ASSERT(cx->realm() == importFun->realm());
|
||||
|
||||
RootedValue fval(cx, ObjectValue(*import.obj));
|
||||
RootedValue thisv(cx, UndefinedValue());
|
||||
if (!Call(cx, fval, thisv, args, rval))
|
||||
|
@ -319,6 +323,10 @@ Instance::growMemory_i32(Instance* instance, uint32_t delta)
|
|||
/* static */ uint32_t
|
||||
Instance::currentMemory_i32(Instance* instance)
|
||||
{
|
||||
// This invariant must hold when running Wasm code. Assert it here so we can
|
||||
// write tests for cross-realm calls.
|
||||
MOZ_ASSERT(TlsContext.get()->realm() == instance->realm());
|
||||
|
||||
uint32_t byteLength = instance->memory()->volatileMemoryLength();
|
||||
MOZ_ASSERT(byteLength % wasm::PageSize == 0);
|
||||
return byteLength / wasm::PageSize;
|
||||
|
@ -504,6 +512,7 @@ Instance::Instance(JSContext* cx,
|
|||
tlsData()->boundsCheckLimit = memory ? memory->buffer().wasmBoundsCheckLimit() : 0;
|
||||
#endif
|
||||
tlsData()->instance = this;
|
||||
tlsData()->realm = realm_;
|
||||
tlsData()->cx = cx;
|
||||
tlsData()->resetInterrupt(cx);
|
||||
tlsData()->jumpTable = code_->tieringJumpTable();
|
||||
|
@ -520,16 +529,19 @@ Instance::Instance(JSContext* cx,
|
|||
Tier calleeTier = calleeInstance.code().bestTier();
|
||||
const CodeRange& codeRange = calleeInstanceObj->getExportedFunctionCodeRange(f, calleeTier);
|
||||
import.tls = calleeInstance.tlsData();
|
||||
import.realm = f->realm();
|
||||
import.code = calleeInstance.codeBase(calleeTier) + codeRange.funcNormalEntry();
|
||||
import.baselineScript = nullptr;
|
||||
import.obj = calleeInstanceObj;
|
||||
} else if (void* thunk = MaybeGetBuiltinThunk(f, fi.funcType())) {
|
||||
import.tls = tlsData();
|
||||
import.realm = f->realm();
|
||||
import.code = thunk;
|
||||
import.baselineScript = nullptr;
|
||||
import.obj = f;
|
||||
} else {
|
||||
import.tls = tlsData();
|
||||
import.realm = f->realm();
|
||||
import.code = codeBase(callerTier) + fi.interpExitCodeOffset();
|
||||
import.baselineScript = nullptr;
|
||||
import.obj = f;
|
||||
|
|
|
@ -1069,6 +1069,9 @@ GenerateImportFunction(jit::MacroAssembler& masm, const FuncImport& fi, FuncType
|
|||
masm.loadWasmTlsRegFromFrame();
|
||||
masm.loadWasmPinnedRegsFromTls();
|
||||
|
||||
// Restore cx->realm.
|
||||
masm.switchToWasmTlsRealm(ABINonArgReturnReg0, ABINonArgReturnReg1);
|
||||
|
||||
GenerateFunctionEpilogue(masm, framePushed, offsets);
|
||||
return FinishOffsets(masm, offsets);
|
||||
}
|
||||
|
|
|
@ -1858,6 +1858,9 @@ struct TlsData
|
|||
// Pointer to the Instance that contains this TLS data.
|
||||
Instance* instance;
|
||||
|
||||
// Equal to instance->realm_.
|
||||
JS::Realm* realm;
|
||||
|
||||
// The containing JSContext.
|
||||
JSContext* cx;
|
||||
|
||||
|
@ -1927,6 +1930,9 @@ struct FuncImportTls
|
|||
// with any pinned registers) before calling 'code'.
|
||||
TlsData* tls;
|
||||
|
||||
// The callee function's realm.
|
||||
JS::Realm* realm;
|
||||
|
||||
// If 'code' points into a JIT code thunk, the BaselineScript of the callee,
|
||||
// for bidirectional registration purposes.
|
||||
jit::BaselineScript* baselineScript;
|
||||
|
|
Загрузка…
Ссылка в новой задаче