зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1732782 - Fix Wasm exceptions JS API for layout changes. r=rhunt
Fixes how exception payloads are written to and read from exception objects using the JS API, which was broken when the Wasm instructions transitioned to using an alignment-aware tag type to find the offsets into the payload. Differential Revision: https://phabricator.services.mozilla.com/D126853
This commit is contained in:
Родитель
8e59b5f49b
Коммит
b0627b0ec2
|
@ -96,7 +96,7 @@ assertErrorMessage(
|
||||||
/first argument must be a WebAssembly.Tag/
|
/first argument must be a WebAssembly.Tag/
|
||||||
);
|
);
|
||||||
|
|
||||||
const { tag1, tag2, tag3, tag4, tag5, tag6, tag7 } = wasmEvalText(
|
const { tag1, tag2, tag3, tag4, tag5, tag6, tag7, tag8, tag9 } = wasmEvalText(
|
||||||
`(module
|
`(module
|
||||||
(tag (export "tag1") (param))
|
(tag (export "tag1") (param))
|
||||||
(tag (export "tag2") (param i32))
|
(tag (export "tag2") (param i32))
|
||||||
|
@ -104,7 +104,9 @@ const { tag1, tag2, tag3, tag4, tag5, tag6, tag7 } = wasmEvalText(
|
||||||
(tag (export "tag4") (param i32 externref i32))
|
(tag (export "tag4") (param i32 externref i32))
|
||||||
(tag (export "tag5") (param i32 externref i32 externref))
|
(tag (export "tag5") (param i32 externref i32 externref))
|
||||||
(tag (export "tag6") (param funcref))
|
(tag (export "tag6") (param funcref))
|
||||||
(tag (export "tag7") (param i64)))`
|
(tag (export "tag7") (param i64))
|
||||||
|
(tag (export "tag8") (param i32 f64))
|
||||||
|
(tag (export "tag9") (param externref funcref)))`
|
||||||
).exports;
|
).exports;
|
||||||
|
|
||||||
new WebAssembly.Exception(tag1, []);
|
new WebAssembly.Exception(tag1, []);
|
||||||
|
@ -168,25 +170,23 @@ assertErrorMessage(
|
||||||
const exn2 = new WebAssembly.Exception(tag2, [3]);
|
const exn2 = new WebAssembly.Exception(tag2, [3]);
|
||||||
assertEq(exn2.getArg(tag2, 0), 3);
|
assertEq(exn2.getArg(tag2, 0), 3);
|
||||||
|
|
||||||
assertEq(
|
assertEq(new WebAssembly.Exception(tag2, [undefined]).getArg(tag2, 0), 0);
|
||||||
new WebAssembly.Exception(tag2, [undefined]).getArg(tag2, 0),
|
|
||||||
0
|
|
||||||
);
|
|
||||||
|
|
||||||
const exn4 = new WebAssembly.Exception(tag4, [3, "foo", 4]);
|
const exn4 = new WebAssembly.Exception(tag4, [3, "foo", 4]);
|
||||||
assertEq(exn4.getArg(tag4, 0), 3);
|
assertEq(exn4.getArg(tag4, 0), 3);
|
||||||
assertEq(exn4.getArg(tag4, 1), "foo");
|
assertEq(exn4.getArg(tag4, 1), "foo");
|
||||||
assertEq(exn4.getArg(tag4, 2), 4);
|
assertEq(exn4.getArg(tag4, 2), 4);
|
||||||
|
|
||||||
const exn5 = new WebAssembly.Exception(
|
const exn5 = new WebAssembly.Exception(tag5, [3, "foo", 4, "bar"]);
|
||||||
tag5,
|
|
||||||
[3,
|
|
||||||
"foo",
|
|
||||||
4,
|
|
||||||
"bar"]
|
|
||||||
);
|
|
||||||
assertEq(exn5.getArg(tag5, 3), "bar");
|
assertEq(exn5.getArg(tag5, 3), "bar");
|
||||||
|
|
||||||
|
const { funcref } = wasmEvalText(
|
||||||
|
`(module (func (export "funcref")))`
|
||||||
|
).exports;
|
||||||
|
const exn9 = new WebAssembly.Exception(tag9, ["foo", funcref]);
|
||||||
|
assertEq(exn9.getArg(tag9, 0), "foo");
|
||||||
|
assertEq(exn9.getArg(tag9, 1), funcref);
|
||||||
|
|
||||||
assertErrorMessage(
|
assertErrorMessage(
|
||||||
() => exn2.getArg(),
|
() => exn2.getArg(),
|
||||||
TypeError,
|
TypeError,
|
||||||
|
@ -257,6 +257,30 @@ assertEqArray(
|
||||||
[42, 5.5]
|
[42, 5.5]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
assertEqArray(
|
||||||
|
wasmEvalText(
|
||||||
|
`(module
|
||||||
|
(import "m" "exn" (tag $exn (param i32 f64)))
|
||||||
|
(import "m" "f" (func $f))
|
||||||
|
(func (export "f") (result i32 f64)
|
||||||
|
try (result i32 f64)
|
||||||
|
call $f
|
||||||
|
(i32.const 0)
|
||||||
|
(f64.const 0)
|
||||||
|
catch $exn
|
||||||
|
end))`,
|
||||||
|
{
|
||||||
|
m: {
|
||||||
|
exn: tag8,
|
||||||
|
f: () => {
|
||||||
|
throw new WebAssembly.Exception(tag8, [9999, 9999]);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
).exports.f(),
|
||||||
|
[9999, 9999]
|
||||||
|
);
|
||||||
|
|
||||||
assertEqArray(
|
assertEqArray(
|
||||||
wasmEvalText(
|
wasmEvalText(
|
||||||
`(module
|
`(module
|
||||||
|
@ -282,6 +306,61 @@ assertEqArray(
|
||||||
[42, "foo", 42]
|
[42, "foo", 42]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
assertEqArray(
|
||||||
|
wasmEvalText(
|
||||||
|
`(module
|
||||||
|
(import "m" "exn" (tag $exn (param i32 externref i32 externref)))
|
||||||
|
(import "m" "f" (func $f))
|
||||||
|
(func (export "f") (result i32 externref i32 externref)
|
||||||
|
try (result i32 externref i32 externref)
|
||||||
|
call $f
|
||||||
|
(i32.const 0)
|
||||||
|
(ref.null extern)
|
||||||
|
(i32.const 0)
|
||||||
|
(ref.null extern)
|
||||||
|
catch $exn
|
||||||
|
end))`,
|
||||||
|
{
|
||||||
|
m: {
|
||||||
|
exn: tag5,
|
||||||
|
f: () => {
|
||||||
|
throw new WebAssembly.Exception(tag5, [42, "foo", 42, "bar"]);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
).exports.f(),
|
||||||
|
[42, "foo", 42, "bar"]
|
||||||
|
);
|
||||||
|
|
||||||
|
{
|
||||||
|
const { funcref } = wasmEvalText(
|
||||||
|
`(module (func (export "funcref")))`
|
||||||
|
).exports;
|
||||||
|
assertEqArray(
|
||||||
|
wasmEvalText(
|
||||||
|
`(module
|
||||||
|
(import "m" "exn" (tag $exn (param externref funcref)))
|
||||||
|
(import "m" "f" (func $f))
|
||||||
|
(func (export "f") (result externref funcref)
|
||||||
|
try (result externref funcref)
|
||||||
|
call $f
|
||||||
|
(ref.null extern)
|
||||||
|
(ref.null func)
|
||||||
|
catch $exn
|
||||||
|
end))`,
|
||||||
|
{
|
||||||
|
m: {
|
||||||
|
exn: tag9,
|
||||||
|
f: () => {
|
||||||
|
throw new WebAssembly.Exception(tag9, ["foo", funcref]);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
).exports.f(),
|
||||||
|
["foo", funcref]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
assertEq(
|
assertEq(
|
||||||
wasmEvalText(
|
wasmEvalText(
|
||||||
`(module
|
`(module
|
||||||
|
@ -323,7 +402,7 @@ assertEq(
|
||||||
end))`,
|
end))`,
|
||||||
{
|
{
|
||||||
m: {
|
m: {
|
||||||
exn: exn,
|
exn,
|
||||||
f: () => {
|
f: () => {
|
||||||
throw new WebAssembly.Exception(exn, [42]);
|
throw new WebAssembly.Exception(exn, [42]);
|
||||||
},
|
},
|
||||||
|
@ -362,3 +441,49 @@ assertEq(
|
||||||
1
|
1
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test `getArg` on a Wasm-thrown exception.
|
||||||
|
assertEq(
|
||||||
|
(() => {
|
||||||
|
try {
|
||||||
|
wasmEvalText(
|
||||||
|
`(module
|
||||||
|
(import "m" "exn" (tag $exn (param i32 f64)))
|
||||||
|
(func (export "f")
|
||||||
|
(i32.const 9999)
|
||||||
|
(f64.const 9999)
|
||||||
|
throw $exn))`,
|
||||||
|
{ m: { exn: tag8 } }
|
||||||
|
).exports.f();
|
||||||
|
} catch (exn) {
|
||||||
|
return exn.getArg(tag8, 1);
|
||||||
|
}
|
||||||
|
})(),
|
||||||
|
9999
|
||||||
|
);
|
||||||
|
|
||||||
|
assertEqArray(
|
||||||
|
(() => {
|
||||||
|
try {
|
||||||
|
wasmEvalText(
|
||||||
|
`(module
|
||||||
|
(import "m" "exn" (tag $exn (param i32 externref i32 externref)))
|
||||||
|
(func (export "f") (param externref externref)
|
||||||
|
(i32.const 1)
|
||||||
|
(local.get 0)
|
||||||
|
(i32.const 2)
|
||||||
|
(local.get 1)
|
||||||
|
throw $exn))`,
|
||||||
|
{ m: { exn: tag5 } }
|
||||||
|
).exports.f("foo", "bar");
|
||||||
|
} catch (exn) {
|
||||||
|
return [
|
||||||
|
exn.getArg(tag5, 0),
|
||||||
|
exn.getArg(tag5, 1),
|
||||||
|
exn.getArg(tag5, 2),
|
||||||
|
exn.getArg(tag5, 3),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
})(),
|
||||||
|
[1, "foo", 2, "bar"]
|
||||||
|
);
|
||||||
|
|
|
@ -3574,9 +3574,9 @@ bool BaseCompiler::emitCatch() {
|
||||||
masm.bind(&tryCatch.catchInfos.back().label);
|
masm.bind(&tryCatch.catchInfos.back().label);
|
||||||
|
|
||||||
// Extract the arguments in the exception package and push them.
|
// Extract the arguments in the exception package and push them.
|
||||||
const TagDesc& tagDesc = moduleEnv_.tags[tagIndex];
|
const TagType& tagType = moduleEnv_.tags[tagIndex].type;
|
||||||
const ValTypeVector& params = tagDesc.argTypes;
|
const ValTypeVector& params = tagType.argTypes;
|
||||||
const TagOffsetVector& offsets = tagDesc.argOffsets;
|
const TagOffsetVector& offsets = tagType.argOffsets;
|
||||||
|
|
||||||
const uint32_t dataOffset =
|
const uint32_t dataOffset =
|
||||||
NativeObject::getFixedSlotOffset(ArrayBufferObject::DATA_SLOT);
|
NativeObject::getFixedSlotOffset(ArrayBufferObject::DATA_SLOT);
|
||||||
|
@ -3601,7 +3601,7 @@ bool BaseCompiler::emitCatch() {
|
||||||
masm.load32(Address(refs, NativeObject::offsetOfFixedElements() +
|
masm.load32(Address(refs, NativeObject::offsetOfFixedElements() +
|
||||||
ObjectElements::offsetOfLength()),
|
ObjectElements::offsetOfLength()),
|
||||||
scratch);
|
scratch);
|
||||||
masm.branch32(Assembler::Equal, scratch, Imm32(tagDesc.refCount), &ok);
|
masm.branch32(Assembler::Equal, scratch, Imm32(tagType.refCount), &ok);
|
||||||
masm.assumeUnreachable("Array length should be equal to exn ref count.");
|
masm.assumeUnreachable("Array length should be equal to exn ref count.");
|
||||||
masm.bind(&ok);
|
masm.bind(&ok);
|
||||||
freeI32(scratch);
|
freeI32(scratch);
|
||||||
|
@ -3955,11 +3955,11 @@ bool BaseCompiler::emitThrow() {
|
||||||
|
|
||||||
const TagDesc& tagDesc = moduleEnv_.tags[exnIndex];
|
const TagDesc& tagDesc = moduleEnv_.tags[exnIndex];
|
||||||
const ResultType& params = tagDesc.resultType();
|
const ResultType& params = tagDesc.resultType();
|
||||||
const TagOffsetVector& offsets = tagDesc.argOffsets;
|
const TagOffsetVector& offsets = tagDesc.type.argOffsets;
|
||||||
|
|
||||||
// Create the new exception object that we will throw.
|
// Create the new exception object that we will throw.
|
||||||
pushI32(exnIndex);
|
pushI32(exnIndex);
|
||||||
pushI32(tagDesc.bufferSize);
|
pushI32(tagDesc.type.bufferSize);
|
||||||
if (!emitInstanceCall(lineOrBytecode, SASigExceptionNew)) {
|
if (!emitInstanceCall(lineOrBytecode, SASigExceptionNew)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1463,7 +1463,7 @@ bool WasmModuleObject::imports(JSContext* cx, unsigned argc, Value* vp) {
|
||||||
case DefinitionKind::Tag: {
|
case DefinitionKind::Tag: {
|
||||||
size_t tagIndex = numTagImport++;
|
size_t tagIndex = numTagImport++;
|
||||||
const TagDesc& tag = metadata.tags[tagIndex];
|
const TagDesc& tag = metadata.tags[tagIndex];
|
||||||
typeObj = TagTypeToObject(cx, tag.argTypes);
|
typeObj = TagTypeToObject(cx, tag.type.argTypes);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
# endif // ENABLE_WASM_EXCEPTIONS
|
# endif // ENABLE_WASM_EXCEPTIONS
|
||||||
|
@ -1568,7 +1568,7 @@ bool WasmModuleObject::exports(JSContext* cx, unsigned argc, Value* vp) {
|
||||||
# ifdef ENABLE_WASM_EXCEPTIONS
|
# ifdef ENABLE_WASM_EXCEPTIONS
|
||||||
case DefinitionKind::Tag: {
|
case DefinitionKind::Tag: {
|
||||||
const TagDesc& tag = metadata.tags[exp.tagIndex()];
|
const TagDesc& tag = metadata.tags[exp.tagIndex()];
|
||||||
typeObj = TagTypeToObject(cx, tag.argTypes);
|
typeObj = TagTypeToObject(cx, tag.type.argTypes);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
# endif // ENABLE_WASM_EXCEPTIONS
|
# endif // ENABLE_WASM_EXCEPTIONS
|
||||||
|
@ -3710,7 +3710,7 @@ void WasmTagObject::finalize(JSFreeOp* fop, JSObject* obj) {
|
||||||
WasmTagObject& exnObj = obj->as<WasmTagObject>();
|
WasmTagObject& exnObj = obj->as<WasmTagObject>();
|
||||||
if (!exnObj.isNewborn()) {
|
if (!exnObj.isNewborn()) {
|
||||||
fop->release(obj, &exnObj.tag(), MemoryUse::WasmTagTag);
|
fop->release(obj, &exnObj.tag(), MemoryUse::WasmTagTag);
|
||||||
fop->delete_(obj, &exnObj.valueTypes(), MemoryUse::WasmTagType);
|
fop->delete_(obj, &exnObj.tagType(), MemoryUse::WasmTagType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3745,6 +3745,15 @@ bool WasmTagObject::construct(JSContext* cx, unsigned argc, Value* vp) {
|
||||||
if (!ParseValTypes(cx, paramsVal, params)) {
|
if (!ParseValTypes(cx, paramsVal, params)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
TagOffsetVector offsets;
|
||||||
|
if (!offsets.resize(params.length())) {
|
||||||
|
ReportOutOfMemory(cx);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
TagType tagType = TagType(std::move(params), std::move(offsets));
|
||||||
|
if (!tagType.computeLayout()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
RootedObject proto(cx);
|
RootedObject proto(cx);
|
||||||
if (!GetPrototypeFromBuiltinConstructor(cx, args, JSProto_WasmTag, &proto)) {
|
if (!GetPrototypeFromBuiltinConstructor(cx, args, JSProto_WasmTag, &proto)) {
|
||||||
|
@ -3754,7 +3763,7 @@ bool WasmTagObject::construct(JSContext* cx, unsigned argc, Value* vp) {
|
||||||
proto = GlobalObject::getOrCreatePrototype(cx, JSProto_WasmTag);
|
proto = GlobalObject::getOrCreatePrototype(cx, JSProto_WasmTag);
|
||||||
}
|
}
|
||||||
|
|
||||||
RootedWasmTagObject tagObj(cx, WasmTagObject::create(cx, params, proto));
|
RootedWasmTagObject tagObj(cx, WasmTagObject::create(cx, tagType, proto));
|
||||||
if (!tagObj) {
|
if (!tagObj) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -3764,7 +3773,8 @@ bool WasmTagObject::construct(JSContext* cx, unsigned argc, Value* vp) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */
|
/* static */
|
||||||
WasmTagObject* WasmTagObject::create(JSContext* cx, const ValTypeVector& type,
|
WasmTagObject* WasmTagObject::create(JSContext* cx,
|
||||||
|
const wasm::TagType& tagType,
|
||||||
HandleObject proto) {
|
HandleObject proto) {
|
||||||
AutoSetNewObjectMetadata metadata(cx);
|
AutoSetNewObjectMetadata metadata(cx);
|
||||||
RootedWasmTagObject obj(cx,
|
RootedWasmTagObject obj(cx,
|
||||||
|
@ -3783,13 +3793,12 @@ WasmTagObject* WasmTagObject::create(JSContext* cx, const ValTypeVector& type,
|
||||||
|
|
||||||
InitReservedSlot(obj, TAG_SLOT, tag.forget().take(), MemoryUse::WasmTagTag);
|
InitReservedSlot(obj, TAG_SLOT, tag.forget().take(), MemoryUse::WasmTagTag);
|
||||||
|
|
||||||
wasm::ValTypeVector* newValueTypes = js_new<ValTypeVector>();
|
TagType* newType = js_new<TagType>();
|
||||||
for (auto t : type) {
|
if (!newType || !newType->clone(tagType)) {
|
||||||
if (!newValueTypes->append(t)) {
|
ReportOutOfMemory(cx);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
InitReservedSlot(obj, TYPE_SLOT, newValueTypes, MemoryUse::WasmTagType);
|
InitReservedSlot(obj, TYPE_SLOT, newType, MemoryUse::WasmTagType);
|
||||||
|
|
||||||
MOZ_ASSERT(!obj->isNewborn());
|
MOZ_ASSERT(!obj->isNewborn());
|
||||||
|
|
||||||
|
@ -3832,8 +3841,12 @@ const JSFunctionSpec WasmTagObject::methods[] = {
|
||||||
|
|
||||||
const JSFunctionSpec WasmTagObject::static_methods[] = {JS_FS_END};
|
const JSFunctionSpec WasmTagObject::static_methods[] = {JS_FS_END};
|
||||||
|
|
||||||
|
TagType& WasmTagObject::tagType() const {
|
||||||
|
return *(TagType*)getFixedSlot(TYPE_SLOT).toPrivate();
|
||||||
|
};
|
||||||
|
|
||||||
wasm::ValTypeVector& WasmTagObject::valueTypes() const {
|
wasm::ValTypeVector& WasmTagObject::valueTypes() const {
|
||||||
return *(ValTypeVector*)getFixedSlot(TYPE_SLOT).toPrivate();
|
return tagType().argTypes;
|
||||||
};
|
};
|
||||||
|
|
||||||
wasm::ResultType WasmTagObject::resultType() const {
|
wasm::ResultType WasmTagObject::resultType() const {
|
||||||
|
@ -3923,25 +3936,24 @@ bool WasmExceptionObject::construct(JSContext* cx, unsigned argc, Value* vp) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
wasm::ValTypeVector& params = exnTag->valueTypes();
|
const wasm::TagType& tagType = exnTag->tagType();
|
||||||
|
const wasm::ValTypeVector& params = tagType.argTypes;
|
||||||
|
const wasm::TagOffsetVector& offsets = tagType.argOffsets;
|
||||||
|
|
||||||
// This is pre-sizing the data buffer for the exception object.
|
RootedArrayBufferObject buf(
|
||||||
size_t nbytes = 0;
|
cx, ArrayBufferObject::createZeroed(cx, tagType.bufferSize));
|
||||||
for (const ValType param : params) {
|
|
||||||
if (!param.isReference()) {
|
|
||||||
nbytes += SizeOf(param);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
RootedArrayBufferObject buf(cx, ArrayBufferObject::createZeroed(cx, nbytes));
|
|
||||||
if (!buf) {
|
if (!buf) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
RootedArrayObject refs(cx, NewDenseEmptyArray(cx));
|
RootedArrayObject refs(cx, NewDenseFullyAllocatedArray(cx, tagType.refCount));
|
||||||
if (!refs) {
|
if (!refs) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
refs->setDenseInitializedLength(tagType.refCount);
|
||||||
|
for (int i = 0; i < tagType.refCount; i++) {
|
||||||
|
refs->initDenseElement(i, UndefinedValue());
|
||||||
|
}
|
||||||
|
|
||||||
uint8_t* bufPtr = buf->dataPointer();
|
uint8_t* bufPtr = buf->dataPointer();
|
||||||
RootedValue nextArg(cx);
|
RootedValue nextArg(cx);
|
||||||
|
@ -3961,18 +3973,19 @@ bool WasmExceptionObject::construct(JSContext* cx, unsigned argc, Value* vp) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (params[i].isReference()) {
|
if (params[i].isReference()) {
|
||||||
RootedObject objPtr(cx);
|
ASSERT_ANYREF_IS_JSOBJECT;
|
||||||
if (!ToWebAssemblyValue(cx, nextArg, params[i], objPtr.address(), true)) {
|
RootedAnyRef anyref(cx, AnyRef::null());
|
||||||
return false;
|
if (!ToWebAssemblyValue(cx, nextArg, params[i],
|
||||||
}
|
anyref.get().asJSObjectAddress(), true)) {
|
||||||
if (!NewbornArrayPush(cx, refs, ObjectValue(*objPtr))) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
refs->setDenseElement(offsets[i] / sizeof(Value),
|
||||||
|
ObjectValue(*anyref.get().asJSObject()));
|
||||||
} else {
|
} else {
|
||||||
if (!ToWebAssemblyValue(cx, nextArg, params[i], bufPtr, true)) {
|
if (!ToWebAssemblyValue(cx, nextArg, params[i], bufPtr + offsets[i],
|
||||||
|
true)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
bufPtr += SizeOf(params[i]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4080,25 +4093,17 @@ bool WasmExceptionObject::getArgImpl(JSContext* cx, const CallArgs& args) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t offset = exnTag->tagType().argOffsets[index];
|
||||||
RootedValue result(cx);
|
RootedValue result(cx);
|
||||||
if (params[index].isReference()) {
|
if (params[index].isReference()) {
|
||||||
uint32_t refIndex = 0;
|
ASSERT_ANYREF_IS_JSOBJECT;
|
||||||
for (size_t i = 0; i < index; i++) {
|
RootedValue val(cx, exnObj->refs().getDenseElement(offset / sizeof(Value)));
|
||||||
if (params[i].isReference()) {
|
RootedAnyRef anyref(cx, AnyRef::fromJSObject(val.toObjectOrNull()));
|
||||||
refIndex++;
|
if (!ToJSValue(cx, anyref.get().asJSObjectAddress(), params[index],
|
||||||
}
|
&result)) {
|
||||||
}
|
|
||||||
JSObject* ref = &exnObj->refs().getDenseElement(refIndex).toObject();
|
|
||||||
if (!ToJSValue(cx, &ref, params[index], &result)) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
uint32_t offset = 0;
|
|
||||||
for (size_t i = 0; i < index; i++) {
|
|
||||||
if (!params[i].isReference()) {
|
|
||||||
offset += SizeOf(params[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!ToJSValue(cx, exnObj->values().dataPointer() + offset, params[index],
|
if (!ToJSValue(cx, exnObj->values().dataPointer() + offset, params[index],
|
||||||
&result)) {
|
&result)) {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -506,10 +506,11 @@ class WasmTagObject : public NativeObject {
|
||||||
static const JSFunctionSpec static_methods[];
|
static const JSFunctionSpec static_methods[];
|
||||||
static bool construct(JSContext*, unsigned, Value*);
|
static bool construct(JSContext*, unsigned, Value*);
|
||||||
|
|
||||||
static WasmTagObject* create(JSContext* cx, const wasm::ValTypeVector& type,
|
static WasmTagObject* create(JSContext* cx, const wasm::TagType& tagType,
|
||||||
HandleObject proto);
|
HandleObject proto);
|
||||||
bool isNewborn() const;
|
bool isNewborn() const;
|
||||||
|
|
||||||
|
wasm::TagType& tagType() const;
|
||||||
wasm::ValTypeVector& valueTypes() const;
|
wasm::ValTypeVector& valueTypes() const;
|
||||||
wasm::ResultType resultType() const;
|
wasm::ResultType resultType() const;
|
||||||
wasm::ExceptionTag& tag() const;
|
wasm::ExceptionTag& tag() const;
|
||||||
|
|
|
@ -840,8 +840,7 @@ bool Module::instantiateLocalTag(JSContext* cx, const TagDesc& ed,
|
||||||
// If the tag description is exported, create an export tag
|
// If the tag description is exported, create an export tag
|
||||||
// object for it.
|
// object for it.
|
||||||
RootedObject proto(cx, &cx->global()->getPrototype(JSProto_WasmTag));
|
RootedObject proto(cx, &cx->global()->getPrototype(JSProto_WasmTag));
|
||||||
RootedWasmTagObject tagObj(cx,
|
RootedWasmTagObject tagObj(cx, WasmTagObject::create(cx, ed.type, proto));
|
||||||
WasmTagObject::create(cx, ed.argTypes, proto));
|
|
||||||
if (!tagObj) {
|
if (!tagObj) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -181,7 +181,7 @@ size_t GlobalDesc::sizeOfExcludingThis(MallocSizeOf mallocSizeOf) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ENABLE_WASM_EXCEPTIONS
|
#ifdef ENABLE_WASM_EXCEPTIONS
|
||||||
bool TagDesc::computeLayout() {
|
bool TagType::computeLayout() {
|
||||||
StructLayout layout;
|
StructLayout layout;
|
||||||
int32_t refCount = 0;
|
int32_t refCount = 0;
|
||||||
for (const ValType argType : argTypes) {
|
for (const ValType argType : argTypes) {
|
||||||
|
|
|
@ -286,25 +286,43 @@ using GlobalDescVector = Vector<GlobalDesc, 0, SystemAllocPolicy>;
|
||||||
// offset in the elements of the exception's ArrayObject.
|
// offset in the elements of the exception's ArrayObject.
|
||||||
using TagOffsetVector = Vector<int32_t, 0, SystemAllocPolicy>;
|
using TagOffsetVector = Vector<int32_t, 0, SystemAllocPolicy>;
|
||||||
|
|
||||||
struct TagDesc {
|
struct TagType {
|
||||||
TagKind kind;
|
|
||||||
ValTypeVector argTypes;
|
ValTypeVector argTypes;
|
||||||
TagOffsetVector argOffsets;
|
TagOffsetVector argOffsets;
|
||||||
int32_t bufferSize;
|
int32_t bufferSize;
|
||||||
int32_t refCount;
|
int32_t refCount;
|
||||||
bool isExport;
|
|
||||||
|
|
||||||
TagDesc(TagKind kind, ValTypeVector&& argTypes, TagOffsetVector&& argOffsets,
|
TagType() : argTypes(), argOffsets(), bufferSize(0), refCount(0) {}
|
||||||
bool isExport = false)
|
TagType(ValTypeVector&& argTypes, TagOffsetVector&& argOffsets)
|
||||||
: kind(kind),
|
: argTypes(std::move(argTypes)),
|
||||||
argTypes(std::move(argTypes)),
|
|
||||||
argOffsets(std::move(argOffsets)),
|
argOffsets(std::move(argOffsets)),
|
||||||
bufferSize(0),
|
bufferSize(0),
|
||||||
refCount(0),
|
refCount(0) {}
|
||||||
isExport(isExport) {}
|
|
||||||
|
|
||||||
[[nodiscard]] bool computeLayout();
|
[[nodiscard]] bool computeLayout();
|
||||||
ResultType resultType() const { return ResultType::Vector(argTypes); }
|
|
||||||
|
[[nodiscard]] bool clone(const TagType& src) {
|
||||||
|
MOZ_ASSERT(argTypes.empty());
|
||||||
|
MOZ_ASSERT(argOffsets.empty());
|
||||||
|
if (!argTypes.appendAll(src.argTypes) ||
|
||||||
|
!argOffsets.appendAll(src.argOffsets)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bufferSize = src.bufferSize;
|
||||||
|
refCount = src.refCount;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct TagDesc {
|
||||||
|
TagKind kind;
|
||||||
|
TagType type;
|
||||||
|
bool isExport;
|
||||||
|
|
||||||
|
TagDesc(TagKind kind, TagType&& type, bool isExport = false)
|
||||||
|
: kind(kind), type(std::move(type)), isExport(isExport) {}
|
||||||
|
|
||||||
|
ResultType resultType() const { return ResultType::Vector(type.argTypes); }
|
||||||
};
|
};
|
||||||
|
|
||||||
using TagDescVector = Vector<TagDesc, 0, SystemAllocPolicy>;
|
using TagDescVector = Vector<TagDesc, 0, SystemAllocPolicy>;
|
||||||
|
|
|
@ -2055,14 +2055,14 @@ static bool DecodeImport(Decoder& d, ModuleEnvironment* env) {
|
||||||
if (!offsets.resize(tagArgs.length())) {
|
if (!offsets.resize(tagArgs.length())) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!env->tags.emplaceBack(tagKind, std::move(tagArgs),
|
TagType type = TagType(std::move(tagArgs), std::move(offsets));
|
||||||
std::move(offsets))) {
|
if (!env->tags.emplaceBack(tagKind, std::move(type))) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (env->tags.length() > MaxTags) {
|
if (env->tags.length() > MaxTags) {
|
||||||
return d.fail("too many tags");
|
return d.fail("too many tags");
|
||||||
}
|
}
|
||||||
if (!env->tags.back().computeLayout()) {
|
if (!env->tags.back().type.computeLayout()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -2286,9 +2286,9 @@ static bool DecodeTagSection(Decoder& d, ModuleEnvironment* env) {
|
||||||
if (!offsets.resize(tagArgs.length())) {
|
if (!offsets.resize(tagArgs.length())) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
env->tags.infallibleEmplaceBack(tagKind, std::move(tagArgs),
|
TagType type = TagType(std::move(tagArgs), std::move(offsets));
|
||||||
std::move(offsets));
|
env->tags.infallibleEmplaceBack(tagKind, std::move(type));
|
||||||
if (!env->tags.back().computeLayout()) {
|
if (!env->tags.back().type.computeLayout()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2409,7 +2409,7 @@ static bool DecodeExport(Decoder& d, ModuleEnvironment* env,
|
||||||
}
|
}
|
||||||
|
|
||||||
# ifdef WASM_PRIVATE_REFTYPES
|
# ifdef WASM_PRIVATE_REFTYPES
|
||||||
if (!TagIsJSCompatible(d, env->tags[tagIndex].argTypes)) {
|
if (!TagIsJSCompatible(d, env->tags[tagIndex].type.argTypes)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
# endif
|
# endif
|
||||||
|
|
Загрузка…
Ссылка в новой задаче