зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1694537 - support reference types in wasm exceptions r=rhunt
This patch adds support for using reference types in wasm exception types and allows exceptions including such values to be thrown and caught. Differential Revision: https://phabricator.services.mozilla.com/D106850
This commit is contained in:
Родитель
637bff54ac
Коммит
681a9661aa
|
@ -0,0 +1,143 @@
|
|||
// |jit-test| skip-if: !wasmReftypesEnabled()
|
||||
//
|
||||
// Exception tests that use reference types.
|
||||
|
||||
load(libdir + "eqArrayHelper.js");
|
||||
|
||||
assertEq(
|
||||
wasmEvalText(
|
||||
`(module
|
||||
(event $exn (param externref))
|
||||
(func (export "f") (result externref)
|
||||
try (result externref)
|
||||
ref.null extern
|
||||
throw $exn
|
||||
catch $exn
|
||||
end))`
|
||||
).exports.f(),
|
||||
null
|
||||
);
|
||||
|
||||
{
|
||||
let f = wasmEvalText(
|
||||
`(module
|
||||
(event $exn (param funcref))
|
||||
(func $f (export "f") (result funcref)
|
||||
try (result funcref)
|
||||
ref.func $f
|
||||
throw $exn
|
||||
catch $exn
|
||||
end))`
|
||||
).exports.f;
|
||||
assertEq(f(), f);
|
||||
}
|
||||
|
||||
{
|
||||
let f = wasmEvalText(
|
||||
`(module
|
||||
(event $exn (param externref))
|
||||
(func (export "f") (param externref) (result externref)
|
||||
try (result externref)
|
||||
local.get 0
|
||||
throw $exn
|
||||
catch $exn
|
||||
end))`
|
||||
).exports.f;
|
||||
|
||||
for (v of WasmExternrefValues) {
|
||||
assertEq(f(v), v);
|
||||
}
|
||||
}
|
||||
|
||||
assertEqArray(
|
||||
wasmEvalText(
|
||||
`(module
|
||||
(event $exn (param externref externref))
|
||||
(func (export "f") (param externref externref)
|
||||
(result externref externref)
|
||||
try (result externref externref)
|
||||
local.get 0
|
||||
local.get 1
|
||||
throw $exn
|
||||
catch $exn
|
||||
end))`
|
||||
).exports.f("foo", "bar"),
|
||||
["foo", "bar"]
|
||||
);
|
||||
|
||||
assertEqArray(
|
||||
wasmEvalText(
|
||||
`(module
|
||||
(event $exn (param i32 i32 externref f32))
|
||||
(func (export "f") (param externref)
|
||||
(result i32 i32 externref f32)
|
||||
try (result i32 i32 externref f32)
|
||||
i32.const 0
|
||||
i32.const 1
|
||||
local.get 0
|
||||
f32.const 2.0
|
||||
throw $exn
|
||||
catch $exn
|
||||
end))`
|
||||
).exports.f("foo"),
|
||||
[0, 1, "foo", 2.0]
|
||||
);
|
||||
|
||||
assertEqArray(
|
||||
wasmEvalText(
|
||||
`(module
|
||||
(event $exn (param i32 i32 externref f32 externref f64))
|
||||
(func (export "f") (param externref externref)
|
||||
(result i32 i32 externref f32 externref f64)
|
||||
try (result i32 i32 externref f32 externref f64)
|
||||
i32.const 0
|
||||
i32.const 1
|
||||
local.get 0
|
||||
f32.const 2.0
|
||||
local.get 1
|
||||
f64.const 3.0
|
||||
throw $exn
|
||||
catch $exn
|
||||
end))`
|
||||
).exports.f("foo", "bar"),
|
||||
[0, 1, "foo", 2.0, "bar", 3.0]
|
||||
);
|
||||
|
||||
// Test to ensure that reference typed values are tracked correctly by
|
||||
// the GC within exception objects.
|
||||
{
|
||||
gczeal(2, 1); // Collect on every allocation.
|
||||
|
||||
var thrower;
|
||||
let exports = wasmEvalText(
|
||||
`(module
|
||||
(event $exn (param externref))
|
||||
(import "m" "f" (func $f (result externref)))
|
||||
(func (export "thrower") (param externref)
|
||||
(local.get 0)
|
||||
(throw $exn))
|
||||
(func (export "catcher") (result externref)
|
||||
try (result externref)
|
||||
(call $f)
|
||||
catch $exn
|
||||
end))`,
|
||||
{
|
||||
m: {
|
||||
f: () => {
|
||||
// The purpose of this intermediate try-catch in JS is to force
|
||||
// some allocation to occur after Wasm's `throw`, triggering GC, and
|
||||
// then rethrow back to Wasm to observe any errors.
|
||||
try {
|
||||
thrower("foo");
|
||||
} catch (e) {
|
||||
let v = { x: 5 };
|
||||
throw e;
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
).exports;
|
||||
|
||||
thrower = exports.thrower;
|
||||
assertEq(exports.catcher(), "foo");
|
||||
}
|
|
@ -337,37 +337,8 @@ function testValidateExnPayload() {
|
|||
wasmInvalid(invalid1, /event index out of range/);
|
||||
}
|
||||
|
||||
// Exception types with reference types are not supported yet.
|
||||
function testValidateExnWithRef() {
|
||||
invalid0 = `(module
|
||||
(event $exn (param externref))
|
||||
(func try nop catch $exn drop end))`;
|
||||
error0 = /exception with reference types not supported/;
|
||||
|
||||
invalid1 = `(module
|
||||
(event $exn (param externref))
|
||||
(func (param externref) (local.get 0) (throw $exn)))`;
|
||||
error1 = /exception with reference types not supported/;
|
||||
|
||||
invalid2 = `(module
|
||||
(event $exn (param funcref))
|
||||
(func try nop catch $exn drop end))`;
|
||||
error2 = /exception with reference types not supported/;
|
||||
|
||||
invalid3 = `(module
|
||||
(event $exn (param funcref))
|
||||
(func (param funcref) (local.get 0) (throw $exn)))`;
|
||||
error3 = /exception with reference types not supported/;
|
||||
|
||||
wasmFailValidateText(invalid0, error0);
|
||||
wasmFailValidateText(invalid1, error1);
|
||||
wasmFailValidateText(invalid2, error2);
|
||||
wasmFailValidateText(invalid3, error3);
|
||||
}
|
||||
|
||||
testValidateDecode();
|
||||
testValidateThrow();
|
||||
testValidateTryCatch();
|
||||
testValidateCatch();
|
||||
testValidateExnPayload();
|
||||
testValidateExnWithRef();
|
||||
|
|
|
@ -10632,6 +10632,13 @@ bool BaseCompiler::emitCatch() {
|
|||
// Extract the arguments in the exception package and push them.
|
||||
const ResultType params = moduleEnv_.events[eventIndex].resultType();
|
||||
|
||||
uint32_t refCount = 0;
|
||||
for (uint32_t i = 0; i < params.length(); i++) {
|
||||
if (params[i].isReference()) {
|
||||
refCount++;
|
||||
}
|
||||
}
|
||||
|
||||
const uint32_t dataOffset =
|
||||
NativeObject::getFixedSlotOffset(ArrayBufferObject::DATA_SLOT);
|
||||
|
||||
|
@ -10639,57 +10646,92 @@ bool BaseCompiler::emitCatch() {
|
|||
// is live in this register.
|
||||
RegRef exn = RegRef(WasmExceptionReg);
|
||||
needRef(exn);
|
||||
RegRef scratch = needRef();
|
||||
RegRef values = needRef();
|
||||
RegRef refs = needRef();
|
||||
|
||||
masm.unboxObject(Address(exn, WasmRuntimeExceptionObject::offsetOfValues()),
|
||||
scratch);
|
||||
values);
|
||||
masm.unboxObject(Address(exn, WasmRuntimeExceptionObject::offsetOfRefs()),
|
||||
refs);
|
||||
|
||||
# ifdef DEBUG
|
||||
Label ok;
|
||||
RegI32 scratch = needI32();
|
||||
masm.load32(Address(refs, NativeObject::offsetOfFixedElements() +
|
||||
ObjectElements::offsetOfLength()),
|
||||
scratch);
|
||||
masm.branch32(Assembler::Equal, scratch, Imm32(refCount), &ok);
|
||||
masm.assumeUnreachable("Array length should be equal to exn ref count.");
|
||||
masm.bind(&ok);
|
||||
freeI32(scratch);
|
||||
# endif
|
||||
masm.loadPtr(Address(refs, NativeObject::offsetOfElements()), refs);
|
||||
|
||||
freeRef(exn);
|
||||
|
||||
masm.loadPtr(Address(scratch, dataOffset), scratch);
|
||||
masm.loadPtr(Address(values, dataOffset), values);
|
||||
size_t argOffset = 0;
|
||||
// The ref values have been pushed into the ArrayObject in a stacklike
|
||||
// fashion so we need to load them starting from the last element.
|
||||
int32_t refIndex = refCount - 1;
|
||||
for (uint32_t i = 0; i < params.length(); i++) {
|
||||
switch (params[i].kind()) {
|
||||
case ValType::I32: {
|
||||
RegI32 reg = needI32();
|
||||
masm.load32(Address(scratch, argOffset), reg);
|
||||
masm.load32(Address(values, argOffset), reg);
|
||||
pushI32(reg);
|
||||
break;
|
||||
}
|
||||
case ValType::I64: {
|
||||
RegI64 reg = needI64();
|
||||
masm.load64(Address(scratch, argOffset), reg);
|
||||
masm.load64(Address(values, argOffset), reg);
|
||||
pushI64(reg);
|
||||
break;
|
||||
}
|
||||
case ValType::F32: {
|
||||
RegF32 reg = needF32();
|
||||
masm.loadFloat32(Address(scratch, argOffset), reg);
|
||||
masm.loadFloat32(Address(values, argOffset), reg);
|
||||
pushF32(reg);
|
||||
break;
|
||||
}
|
||||
case ValType::F64: {
|
||||
RegF64 reg = needF64();
|
||||
masm.loadDouble(Address(scratch, argOffset), reg);
|
||||
masm.loadDouble(Address(values, argOffset), reg);
|
||||
pushF64(reg);
|
||||
break;
|
||||
}
|
||||
case ValType::V128: {
|
||||
# ifdef ENABLE_WASM_SIMD
|
||||
RegV128 reg = needV128();
|
||||
masm.loadUnalignedSimd128(Address(scratch, argOffset), reg);
|
||||
masm.loadUnalignedSimd128(Address(values, argOffset), reg);
|
||||
pushV128(reg);
|
||||
break;
|
||||
# else
|
||||
MOZ_CRASH("No SIMD support");
|
||||
# endif
|
||||
}
|
||||
case ValType::Ref:
|
||||
case ValType::Rtt:
|
||||
MOZ_CRASH("NYI - no reftype support");
|
||||
case ValType::Ref: {
|
||||
// TODO/AnyRef-boxing: With boxed immediates and strings, this may need
|
||||
// to handle other kinds of values.
|
||||
ASSERT_ANYREF_IS_JSOBJECT;
|
||||
|
||||
RegRef reg = needRef();
|
||||
NativeObject::elementsSizeMustNotOverflow();
|
||||
uint32_t offset = refIndex * sizeof(Value);
|
||||
masm.unboxObjectOrNull(Address(refs, offset), reg);
|
||||
pushRef(reg);
|
||||
refIndex--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!params[i].isReference()) {
|
||||
argOffset += SizeOf(params[i]);
|
||||
}
|
||||
argOffset += SizeOf(params[i]);
|
||||
}
|
||||
freeRef(scratch);
|
||||
MOZ_ASSERT(refIndex == -1);
|
||||
freeRef(values);
|
||||
freeRef(refs);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -10805,7 +10847,9 @@ bool BaseCompiler::emitThrow() {
|
|||
// Measure space we need for all the args to put in the exception.
|
||||
uint32_t exnBytes = 0;
|
||||
for (size_t i = 0; i < params.length(); i++) {
|
||||
exnBytes += SizeOf(params[i]);
|
||||
if (!params[i].isReference()) {
|
||||
exnBytes += SizeOf(params[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// Create the new exception object that we will throw.
|
||||
|
@ -10821,13 +10865,15 @@ bool BaseCompiler::emitThrow() {
|
|||
const uint32_t dataOffset =
|
||||
NativeObject::getFixedSlotOffset(ArrayBufferObject::DATA_SLOT);
|
||||
|
||||
masm.unboxObject(Address(exn, WasmRuntimeExceptionObject::offsetOfValues()),
|
||||
scratch);
|
||||
Address exnValuesAddress(exn, WasmRuntimeExceptionObject::offsetOfValues());
|
||||
masm.unboxObject(exnValuesAddress, scratch);
|
||||
masm.loadPtr(Address(scratch, dataOffset), scratch);
|
||||
|
||||
size_t argOffset = exnBytes;
|
||||
for (int32_t i = params.length() - 1; i >= 0; i--) {
|
||||
argOffset -= SizeOf(params[i]);
|
||||
if (!params[i].isReference()) {
|
||||
argOffset -= SizeOf(params[i]);
|
||||
}
|
||||
switch (params[i].kind()) {
|
||||
case ValType::I32: {
|
||||
RegI32 reg = popI32();
|
||||
|
@ -10863,11 +10909,37 @@ bool BaseCompiler::emitThrow() {
|
|||
MOZ_CRASH("No SIMD support");
|
||||
# endif
|
||||
}
|
||||
case ValType::Ref:
|
||||
case ValType::Rtt:
|
||||
MOZ_CRASH("NYI - no reftype support");
|
||||
case ValType::Ref: {
|
||||
RegRef refArg = popRef();
|
||||
|
||||
// Keep exn on the stack to preserve it across the call.
|
||||
RegRef tmp = needRef();
|
||||
moveRef(exn, tmp);
|
||||
pushRef(tmp);
|
||||
|
||||
// Arguments to the instance call start here.
|
||||
pushRef(exn);
|
||||
pushRef(refArg);
|
||||
|
||||
if (!emitInstanceCall(lineOrBytecode, SASigPushRefIntoExn)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// The call result is checked by the instance call failure handling,
|
||||
// so we do not need to use the result here.
|
||||
freeI32(popI32());
|
||||
|
||||
exn = popRef();
|
||||
|
||||
// Restore scratch register contents that got clobbered.
|
||||
masm.unboxObject(exnValuesAddress, scratch);
|
||||
masm.loadPtr(Address(scratch, dataOffset), scratch);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
MOZ_ASSERT(argOffset == 0);
|
||||
freeRef(scratch);
|
||||
|
||||
return throwFrom(exn, lineOrBytecode);
|
||||
|
|
|
@ -236,6 +236,12 @@ const SymbolicAddressSignature SASigGetLocalExceptionIndex = {
|
|||
_Infallible,
|
||||
2,
|
||||
{_PTR, _RoN, _END}};
|
||||
const SymbolicAddressSignature SASigPushRefIntoExn = {
|
||||
SymbolicAddress::PushRefIntoExn,
|
||||
_I32,
|
||||
_FailOnNegI32,
|
||||
3,
|
||||
{_PTR, _RoN, _RoN, _END}};
|
||||
#endif
|
||||
const SymbolicAddressSignature SASigArrayNew = {SymbolicAddress::ArrayNew,
|
||||
_RoN,
|
||||
|
@ -1231,6 +1237,11 @@ void* wasm::AddressOf(SymbolicAddress imm, ABIFunctionType* abiType) {
|
|||
{ArgType_General, ArgType_General});
|
||||
MOZ_ASSERT(*abiType == ToABIType(SASigGetLocalExceptionIndex));
|
||||
return FuncCast(Instance::getLocalExceptionIndex, *abiType);
|
||||
case SymbolicAddress::PushRefIntoExn:
|
||||
*abiType = MakeABIFunctionType(
|
||||
ArgType_Int32, {ArgType_General, ArgType_General, ArgType_General});
|
||||
MOZ_ASSERT(*abiType == ToABIType(SASigPushRefIntoExn));
|
||||
return FuncCast(Instance::pushRefIntoExn, *abiType);
|
||||
#endif
|
||||
|
||||
#if defined(JS_CODEGEN_MIPS32)
|
||||
|
@ -1352,6 +1363,7 @@ bool wasm::NeedsBuiltinThunk(SymbolicAddress sym) {
|
|||
case SymbolicAddress::ExceptionNew:
|
||||
case SymbolicAddress::ThrowException:
|
||||
case SymbolicAddress::GetLocalExceptionIndex:
|
||||
case SymbolicAddress::PushRefIntoExn:
|
||||
#endif
|
||||
case SymbolicAddress::ArrayNew:
|
||||
case SymbolicAddress::RefTest:
|
||||
|
|
|
@ -78,6 +78,7 @@ extern const SymbolicAddressSignature SASigStructNew;
|
|||
extern const SymbolicAddressSignature SASigExceptionNew;
|
||||
extern const SymbolicAddressSignature SASigThrowException;
|
||||
extern const SymbolicAddressSignature SASigGetLocalExceptionIndex;
|
||||
extern const SymbolicAddressSignature SASigPushRefIntoExn;
|
||||
#endif
|
||||
extern const SymbolicAddressSignature SASigArrayNew;
|
||||
extern const SymbolicAddressSignature SASigRefTest;
|
||||
|
|
|
@ -1453,6 +1453,8 @@ static const char* ThunkedNativeToDescription(SymbolicAddress func) {
|
|||
return "call to native throw exception (in wasm)";
|
||||
case SymbolicAddress::GetLocalExceptionIndex:
|
||||
return "call to native get the local index of an exn's tag (in wasm)";
|
||||
case SymbolicAddress::PushRefIntoExn:
|
||||
return "call to native that pushes a ref value into an exn (in wasm)";
|
||||
#endif
|
||||
case SymbolicAddress::ArrayNew:
|
||||
return "call to native array.new (in wasm)";
|
||||
|
|
|
@ -1004,7 +1004,14 @@ bool Instance::initElems(uint32_t tableIndex, const ElemSegment& seg,
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
return AnyRef::fromJSObject(WasmRuntimeExceptionObject::create(cx, tag, buf))
|
||||
RootedArrayObject refs(cx, NewDenseEmptyArray(cx));
|
||||
|
||||
if (!refs) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return AnyRef::fromJSObject(
|
||||
WasmRuntimeExceptionObject::create(cx, tag, buf, refs))
|
||||
.forCompiledCode();
|
||||
}
|
||||
|
||||
|
@ -1046,6 +1053,30 @@ bool Instance::initElems(uint32_t tableIndex, const ElemSegment& seg,
|
|||
// JS value.
|
||||
return UINT32_MAX;
|
||||
}
|
||||
|
||||
/* static */ int32_t Instance::pushRefIntoExn(Instance* instance, JSObject* exn,
|
||||
JSObject* ref) {
|
||||
MOZ_ASSERT(SASigPushRefIntoExn.failureMode == FailureMode::FailOnNegI32);
|
||||
|
||||
JSContext* cx = TlsContext.get();
|
||||
|
||||
MOZ_ASSERT(exn->is<WasmRuntimeExceptionObject>());
|
||||
RootedWasmRuntimeExceptionObject exnObj(
|
||||
cx, &exn->as<WasmRuntimeExceptionObject>());
|
||||
|
||||
// TODO/AnyRef-boxing: With boxed immediates and strings, this may need to
|
||||
// handle other kinds of values.
|
||||
ASSERT_ANYREF_IS_JSOBJECT;
|
||||
|
||||
RootedValue refVal(cx, ObjectOrNullValue(ref));
|
||||
RootedArrayObject arr(cx, &exnObj->refs());
|
||||
|
||||
if (!NewbornArrayPush(cx, arr, refVal)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* static */ int32_t Instance::refTest(Instance* instance, void* refPtr,
|
||||
|
|
|
@ -225,6 +225,8 @@ class Instance {
|
|||
uint32_t nbytes);
|
||||
static void* throwException(Instance* instance, JSObject* exn);
|
||||
static uint32_t getLocalExceptionIndex(Instance* instance, JSObject* exn);
|
||||
static int32_t pushRefIntoExn(Instance* instance, JSObject* exn,
|
||||
JSObject* ref);
|
||||
#endif
|
||||
static void* arrayNew(Instance* instance, uint32_t length, void* arrayDescr);
|
||||
static int32_t refTest(Instance* instance, void* refPtr, void* rttPtr);
|
||||
|
|
|
@ -3815,8 +3815,8 @@ bool WasmRuntimeExceptionObject::construct(JSContext* cx, unsigned argc,
|
|||
|
||||
/* static */
|
||||
WasmRuntimeExceptionObject* WasmRuntimeExceptionObject::create(
|
||||
JSContext* cx, wasm::SharedExceptionTag tag,
|
||||
HandleArrayBufferObject values) {
|
||||
JSContext* cx, wasm::SharedExceptionTag tag, HandleArrayBufferObject values,
|
||||
HandleArrayObject refs) {
|
||||
RootedObject proto(
|
||||
cx, &cx->global()->getPrototype(JSProto_WasmRuntimeException).toObject());
|
||||
|
||||
|
@ -3832,6 +3832,7 @@ WasmRuntimeExceptionObject* WasmRuntimeExceptionObject::create(
|
|||
MemoryUse::WasmRuntimeExceptionTag);
|
||||
|
||||
obj->initFixedSlot(VALUES_SLOT, ObjectValue(*values));
|
||||
obj->initFixedSlot(REFS_SLOT, ObjectValue(*refs));
|
||||
|
||||
MOZ_ASSERT(!obj->isNewborn());
|
||||
|
||||
|
@ -3840,7 +3841,7 @@ WasmRuntimeExceptionObject* WasmRuntimeExceptionObject::create(
|
|||
|
||||
bool WasmRuntimeExceptionObject::isNewborn() const {
|
||||
MOZ_ASSERT(is<WasmRuntimeExceptionObject>());
|
||||
return getReservedSlot(VALUES_SLOT).isUndefined();
|
||||
return getReservedSlot(REFS_SLOT).isUndefined();
|
||||
}
|
||||
|
||||
const JSPropertySpec WasmRuntimeExceptionObject::properties[] = {
|
||||
|
@ -3856,6 +3857,10 @@ ExceptionTag& WasmRuntimeExceptionObject::tag() const {
|
|||
return *(ExceptionTag*)getReservedSlot(TAG_SLOT).toPrivate();
|
||||
}
|
||||
|
||||
ArrayObject& WasmRuntimeExceptionObject::refs() const {
|
||||
return getReservedSlot(REFS_SLOT).toObject().as<ArrayObject>();
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// WebAssembly class and static methods
|
||||
|
||||
|
|
|
@ -518,6 +518,7 @@ class WasmExceptionObject : public NativeObject {
|
|||
class WasmRuntimeExceptionObject : public NativeObject {
|
||||
static const unsigned TAG_SLOT = 0;
|
||||
static const unsigned VALUES_SLOT = 1;
|
||||
static const unsigned REFS_SLOT = 2;
|
||||
|
||||
static const JSClassOps classOps_;
|
||||
static const ClassSpec classSpec_;
|
||||
|
@ -525,7 +526,7 @@ class WasmRuntimeExceptionObject : public NativeObject {
|
|||
static void trace(JSTracer* trc, JSObject* obj);
|
||||
|
||||
public:
|
||||
static const unsigned RESERVED_SLOTS = 2;
|
||||
static const unsigned RESERVED_SLOTS = 3;
|
||||
static const JSClass class_;
|
||||
static const JSClass& protoClass_;
|
||||
static const JSPropertySpec properties[];
|
||||
|
@ -535,14 +536,20 @@ class WasmRuntimeExceptionObject : public NativeObject {
|
|||
|
||||
static WasmRuntimeExceptionObject* create(JSContext* cx,
|
||||
wasm::SharedExceptionTag tag,
|
||||
Handle<ArrayBufferObject*> values);
|
||||
Handle<ArrayBufferObject*> values,
|
||||
HandleArrayObject refs);
|
||||
bool isNewborn() const;
|
||||
|
||||
wasm::ExceptionTag& tag() const;
|
||||
ArrayObject& refs() const;
|
||||
|
||||
static size_t offsetOfValues() {
|
||||
return NativeObject::getFixedSlotOffset(VALUES_SLOT);
|
||||
}
|
||||
|
||||
static size_t offsetOfRefs() {
|
||||
return NativeObject::getFixedSlotOffset(REFS_SLOT);
|
||||
}
|
||||
};
|
||||
|
||||
// The class of the WebAssembly global namespace object.
|
||||
|
|
|
@ -393,10 +393,6 @@ class MOZ_STACK_CLASS OpIter : private Policy {
|
|||
inline bool checkIsSubtypeOf(ValType lhs, ValType rhs);
|
||||
inline bool checkIsSubtypeOf(ResultType params, ResultType results);
|
||||
|
||||
#ifdef ENABLE_WASM_EXCEPTIONS
|
||||
[[nodiscard]] bool exceptionTypeHasRef(ResultType type);
|
||||
#endif
|
||||
|
||||
public:
|
||||
#ifdef DEBUG
|
||||
explicit OpIter(const ModuleEnvironment& env, Decoder& decoder)
|
||||
|
@ -1387,17 +1383,6 @@ inline bool OpIter<Policy>::readBrTable(Uint32Vector* depths,
|
|||
#undef UNKNOWN_ARITY
|
||||
|
||||
#ifdef ENABLE_WASM_EXCEPTIONS
|
||||
template <typename Policy>
|
||||
inline bool OpIter<Policy>::exceptionTypeHasRef(ResultType type) {
|
||||
for (size_t i = 0; i < type.length(); i++) {
|
||||
if (type[i].isReference()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename Policy>
|
||||
inline bool OpIter<Policy>::readTry(ResultType* paramType) {
|
||||
MOZ_ASSERT(Classify(op_) == OpKind::Try);
|
||||
|
@ -1424,9 +1409,6 @@ inline bool OpIter<Policy>::readCatch(LabelKind* kind, uint32_t* eventIndex,
|
|||
if (*eventIndex >= env_.events.length()) {
|
||||
return fail("event index out of range");
|
||||
}
|
||||
if (exceptionTypeHasRef(env_.events[*eventIndex].resultType())) {
|
||||
return fail("exception with reference types not supported");
|
||||
}
|
||||
|
||||
Control& block = controlStack_.back();
|
||||
if (block.kind() != LabelKind::Try && block.kind() != LabelKind::Catch) {
|
||||
|
@ -1458,9 +1440,6 @@ inline bool OpIter<Policy>::readThrow(uint32_t* eventIndex,
|
|||
if (*eventIndex >= env_.events.length()) {
|
||||
return fail("event index out of range");
|
||||
}
|
||||
if (exceptionTypeHasRef(env_.events[*eventIndex].resultType())) {
|
||||
return fail("exception with reference types not supported.");
|
||||
}
|
||||
|
||||
if (!popWithType(env_.events[*eventIndex].resultType(), argValues)) {
|
||||
return false;
|
||||
|
|
|
@ -3615,6 +3615,7 @@ enum class SymbolicAddress {
|
|||
ExceptionNew,
|
||||
ThrowException,
|
||||
GetLocalExceptionIndex,
|
||||
PushRefIntoExn,
|
||||
#endif
|
||||
ArrayNew,
|
||||
InlineTypedObjectClass,
|
||||
|
|
Загрузка…
Ссылка в новой задаче