From 04f64983e29920a67f52379c57140ab45c248d1b Mon Sep 17 00:00:00 2001 From: Asumu Takikawa Date: Wed, 21 Jul 2021 19:17:51 +0000 Subject: [PATCH] Bug 1717118 - Part 1, rename JS API classes for exceptions r=rhunt The Wasm exception handling spec has changed to rename "events" to "tags". As a result, `WebAssembly.Exception` gets renamed to `WebAssembly.Tag` and `WebAssembly.RuntimeException` becomes `WebAssembly.Exception`. Differential Revision: https://phabricator.services.mozilla.com/D118281 --- js/public/ProtoKey.h | 2 +- js/public/friend/ErrorNumbers.msg | 2 +- js/src/gc/GCEnum.h | 4 +- .../tests/wasm/exceptions/import-export.js | 26 +- .../tests/wasm/exceptions/throw-to-js.js | 2 +- js/src/vm/GlobalObject.cpp | 2 +- js/src/wasm/WasmBaselineCompile.cpp | 8 +- js/src/wasm/WasmBuiltins.cpp | 3 +- js/src/wasm/WasmInstance.cpp | 12 +- js/src/wasm/WasmJS.cpp | 282 +++++++++--------- js/src/wasm/WasmJS.h | 21 +- js/src/wasm/WasmModule.cpp | 90 +++--- js/src/wasm/WasmModule.h | 23 +- js/src/wasm/WasmTypeDecls.h | 11 +- js/src/wasm/WasmTypes.h | 14 +- 15 files changed, 244 insertions(+), 258 deletions(-) diff --git a/js/public/ProtoKey.h b/js/public/ProtoKey.h index 8a86cbfdef21..e0ad2a23d915 100644 --- a/js/public/ProtoKey.h +++ b/js/public/ProtoKey.h @@ -121,8 +121,8 @@ REAL(WasmMemory, OCLASP(WasmMemory)) \ REAL(WasmTable, OCLASP(WasmTable)) \ REAL(WasmGlobal, OCLASP(WasmGlobal)) \ + REAL(WasmTag, OCLASP(WasmTag)) \ REAL(WasmException, OCLASP(WasmException)) \ - REAL(WasmRuntimeException, OCLASP(WasmRuntimeException)) \ REAL(FinalizationRegistry, OCLASP(FinalizationRegistry)) \ REAL(WeakRef, OCLASP(WeakRef)) \ REAL(Iterator, OCLASP(Iterator)) \ diff --git a/js/public/friend/ErrorNumbers.msg b/js/public/friend/ErrorNumbers.msg index eff07932e237..074deca492fc 100644 --- a/js/public/friend/ErrorNumbers.msg +++ b/js/public/friend/ErrorNumbers.msg @@ -422,7 +422,7 @@ MSG_DEF(JSMSG_WASM_COMPILE_ERROR, 1, JSEXN_WASMCOMPILEERROR, "{0}") MSG_DEF(JSMSG_WASM_NO_SHMEM_COMPILE, 0, JSEXN_WASMCOMPILEERROR, "shared memory is disabled") MSG_DEF(JSMSG_WASM_BAD_IMPORT_TYPE, 2, JSEXN_WASMLINKERROR, "import object field '{0}' is not a {1}") MSG_DEF(JSMSG_WASM_BAD_IMPORT_SIG, 2, JSEXN_WASMLINKERROR, "imported function '{0}.{1}' signature mismatch") -MSG_DEF(JSMSG_WASM_BAD_EXN_SIG, 2, JSEXN_WASMLINKERROR, "imported exception '{0}.{1}' signature mismatch") +MSG_DEF(JSMSG_WASM_BAD_TAG_SIG, 2, JSEXN_WASMLINKERROR, "imported tag '{0}.{1}' signature mismatch") MSG_DEF(JSMSG_WASM_BAD_IMP_INDEX, 1, JSEXN_WASMLINKERROR, "imported {0} with incompatible index type") MSG_DEF(JSMSG_WASM_BAD_IMP_SIZE, 1, JSEXN_WASMLINKERROR, "imported {0} with incompatible size") MSG_DEF(JSMSG_WASM_BAD_IMP_MAX, 1, JSEXN_WASMLINKERROR, "imported {0} with incompatible maximum size") diff --git a/js/src/gc/GCEnum.h b/js/src/gc/GCEnum.h index c18308f7f890..d88aba22731d 100644 --- a/js/src/gc/GCEnum.h +++ b/js/src/gc/GCEnum.h @@ -127,9 +127,9 @@ enum class GCAbortReason { _(WasmResolveResponseClosure) \ _(WasmModule) \ _(WasmTableTable) \ + _(WasmTagTag) \ + _(WasmTagType) \ _(WasmExceptionTag) \ - _(WasmExceptionType) \ - _(WasmRuntimeExceptionTag) \ _(WasmRttValueChildren) \ _(FileObjectFile) \ _(Debugger) \ diff --git a/js/src/jit-test/tests/wasm/exceptions/import-export.js b/js/src/jit-test/tests/wasm/exceptions/import-export.js index cf0b7bae579a..06a571d14fe7 100644 --- a/js/src/jit-test/tests/wasm/exceptions/import-export.js +++ b/js/src/jit-test/tests/wasm/exceptions/import-export.js @@ -1,19 +1,19 @@ // Tests for Wasm exception import and export. -// The WebAssembly.Exception constructor cannot be called for now until the -// JS API specifies the behavior. Same with WebAssembly.RuntimeException. +// The WebAssembly.Tag constructor cannot be called for now until the +// JS API specifies the behavior. Same with WebAssembly.Exception. function testException() { + assertErrorMessage( + () => new WebAssembly.Tag(), + WebAssembly.RuntimeError, + /cannot call WebAssembly.Tag/ + ); + assertErrorMessage( () => new WebAssembly.Exception(), WebAssembly.RuntimeError, /cannot call WebAssembly.Exception/ ); - - assertErrorMessage( - () => new WebAssembly.RuntimeException(), - WebAssembly.RuntimeError, - /cannot call WebAssembly.RuntimeException/ - ); } function testImports() { @@ -24,9 +24,9 @@ function testImports() { `; assertErrorMessage( - () => wasmEvalText(mod, { m: { exn: "not an exception" } }), + () => wasmEvalText(mod, { m: { exn: "not a tag" } }), WebAssembly.LinkError, - /import object field 'exn' is not a Exception/ + /import object field 'exn' is not a Tag/ ); } @@ -36,7 +36,7 @@ function testExports() { `).exports; assertEq(typeof exports1.exn, "object"); - assertEq(exports1.exn instanceof WebAssembly.Exception, true); + assertEq(exports1.exn instanceof WebAssembly.Tag, true); var exports2 = wasmEvalText(` (module @@ -45,7 +45,7 @@ function testExports() { `).exports; assertEq(typeof exports2.exn, "object"); - assertEq(exports2.exn instanceof WebAssembly.Exception, true); + assertEq(exports2.exn instanceof WebAssembly.Tag, true); } function testImportExport() { @@ -76,7 +76,7 @@ function testImportExport() { ); }, WebAssembly.LinkError, - /imported exception 'm.exn' signature mismatch/ + /imported tag 'm.exn' signature mismatch/ ); } diff --git a/js/src/jit-test/tests/wasm/exceptions/throw-to-js.js b/js/src/jit-test/tests/wasm/exceptions/throw-to-js.js index daed7d3905ab..da979d5ce270 100644 --- a/js/src/jit-test/tests/wasm/exceptions/throw-to-js.js +++ b/js/src/jit-test/tests/wasm/exceptions/throw-to-js.js @@ -7,7 +7,7 @@ function assertWasmThrowsExn(thunk) { thunk(); } catch (exn) { thrown = true; - assertEq(exn instanceof WebAssembly.RuntimeException, true); + assertEq(exn instanceof WebAssembly.Exception, true); } assertEq(thrown, true, "missing exception"); diff --git a/js/src/vm/GlobalObject.cpp b/js/src/vm/GlobalObject.cpp index e4527f77f731..3959fba59d46 100644 --- a/js/src/vm/GlobalObject.cpp +++ b/js/src/vm/GlobalObject.cpp @@ -158,8 +158,8 @@ bool GlobalObject::skipDeselectedConstructor(JSContext* cx, JSProtoKey key) { case JSProto_WasmMemory: case JSProto_WasmTable: case JSProto_WasmGlobal: + case JSProto_WasmTag: case JSProto_WasmException: - case JSProto_WasmRuntimeException: return false; #ifdef JS_HAS_INTL_API diff --git a/js/src/wasm/WasmBaselineCompile.cpp b/js/src/wasm/WasmBaselineCompile.cpp index c8edbf24b168..3254ad2821e5 100644 --- a/js/src/wasm/WasmBaselineCompile.cpp +++ b/js/src/wasm/WasmBaselineCompile.cpp @@ -10602,10 +10602,8 @@ bool BaseCompiler::emitCatch() { RegRef values = needRef(); RegRef refs = needRef(); - masm.unboxObject(Address(exn, WasmRuntimeExceptionObject::offsetOfValues()), - values); - masm.unboxObject(Address(exn, WasmRuntimeExceptionObject::offsetOfRefs()), - refs); + masm.unboxObject(Address(exn, WasmExceptionObject::offsetOfValues()), values); + masm.unboxObject(Address(exn, WasmExceptionObject::offsetOfRefs()), refs); # ifdef DEBUG Label ok; @@ -10964,7 +10962,7 @@ bool BaseCompiler::emitThrow() { const uint32_t dataOffset = NativeObject::getFixedSlotOffset(ArrayBufferObject::DATA_SLOT); - Address exnValuesAddress(exn, WasmRuntimeExceptionObject::offsetOfValues()); + Address exnValuesAddress(exn, WasmExceptionObject::offsetOfValues()); masm.unboxObject(exnValuesAddress, scratch); masm.loadPtr(Address(scratch, dataOffset), scratch); diff --git a/js/src/wasm/WasmBuiltins.cpp b/js/src/wasm/WasmBuiltins.cpp index edc93cd101c8..b80039f39d8c 100644 --- a/js/src/wasm/WasmBuiltins.cpp +++ b/js/src/wasm/WasmBuiltins.cpp @@ -505,8 +505,7 @@ bool wasm::HandleThrow(JSContext* cx, WasmFrameIter& iter, if (tryNote) { cx->clearPendingException(); - if (!exn.isObject() || - !exn.toObject().is()) { + if (!exn.isObject() || !exn.toObject().is()) { RootedObject obj(cx, WasmJSExceptionObject::create(cx, &exn)); if (!obj) { MOZ_ASSERT(cx->isThrowingOutOfMemory()); diff --git a/js/src/wasm/WasmInstance.cpp b/js/src/wasm/WasmInstance.cpp index 68e03079c7ca..4e54e5c19f48 100644 --- a/js/src/wasm/WasmInstance.cpp +++ b/js/src/wasm/WasmInstance.cpp @@ -1003,8 +1003,7 @@ bool Instance::initElems(uint32_t tableIndex, const ElemSegment& seg, return nullptr; } - return AnyRef::fromJSObject( - WasmRuntimeExceptionObject::create(cx, tag, buf, refs)) + return AnyRef::fromJSObject(WasmExceptionObject::create(cx, tag, buf, refs)) .forCompiledCode(); } @@ -1032,8 +1031,8 @@ bool Instance::initElems(uint32_t tableIndex, const ElemSegment& seg, MOZ_ASSERT(SASigGetLocalExceptionIndex.failureMode == FailureMode::Infallible); - if (exn->is()) { - ExceptionTag& exnTag = exn->as().tag(); + if (exn->is()) { + ExceptionTag& exnTag = exn->as().tag(); for (size_t i = 0; i < instance->exceptionTags().length(); i++) { ExceptionTag& tag = *instance->exceptionTags()[i]; if (&tag == &exnTag) { @@ -1053,9 +1052,8 @@ bool Instance::initElems(uint32_t tableIndex, const ElemSegment& seg, JSContext* cx = TlsContext.get(); - MOZ_ASSERT(exn->is()); - RootedWasmRuntimeExceptionObject exnObj( - cx, &exn->as()); + MOZ_ASSERT(exn->is()); + RootedWasmExceptionObject exnObj(cx, &exn->as()); // TODO/AnyRef-boxing: With boxed immediates and strings, this may need to // handle other kinds of values. diff --git a/js/src/wasm/WasmJS.cpp b/js/src/wasm/WasmJS.cpp index c36ae2dec218..f6298cad29e5 100644 --- a/js/src/wasm/WasmJS.cpp +++ b/js/src/wasm/WasmJS.cpp @@ -555,23 +555,22 @@ bool js::wasm::GetImports(JSContext* cx, const Module& module, #ifdef ENABLE_WASM_EXCEPTIONS case DefinitionKind::Event: { const uint32_t index = eventIndex++; - if (!v.isObject() || !v.toObject().is()) { - return ThrowBadImportType(cx, import.field.get(), "Exception"); + if (!v.isObject() || !v.toObject().is()) { + return ThrowBadImportType(cx, import.field.get(), "Tag"); } - RootedWasmExceptionObject obj(cx, - &v.toObject().as()); + RootedWasmTagObject obj(cx, &v.toObject().as()); // Checks whether the signature of the imported exception object matches // the signature declared in the exception import's EventDesc. if (obj->resultType() != events[index].resultType()) { JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, - JSMSG_WASM_BAD_EXN_SIG, import.module.get(), + JSMSG_WASM_BAD_TAG_SIG, import.module.get(), import.field.get()); return false; } - if (!imports->exceptionObjs.append(obj)) { + if (!imports->tagObjs.append(obj)) { ReportOutOfMemory(cx); return false; } @@ -3539,6 +3538,126 @@ bool WasmGlobalObject::type(JSContext* cx, unsigned argc, Value* vp) { } #endif +// ============================================================================ +// WebAssembly.Tag class and methods + +const JSClassOps WasmTagObject::classOps_ = { + nullptr, // addProperty + nullptr, // delProperty + nullptr, // enumerate + nullptr, // newEnumerate + nullptr, // resolve + nullptr, // mayResolve + WasmTagObject::finalize, // finalize + nullptr, // call + nullptr, // hasInstance + nullptr, // construct + nullptr, // trace +}; + +const JSClass WasmTagObject::class_ = { + "WebAssembly.Tag", + JSCLASS_HAS_RESERVED_SLOTS(WasmTagObject::RESERVED_SLOTS) | + JSCLASS_FOREGROUND_FINALIZE, + &WasmTagObject::classOps_, &WasmTagObject::classSpec_}; + +const JSClass& WasmTagObject::protoClass_ = PlainObject::class_; + +static constexpr char WasmTagName[] = "Tag"; + +const ClassSpec WasmTagObject::classSpec_ = { + CreateWasmConstructor, + GenericCreatePrototype, + WasmTagObject::static_methods, + nullptr, + WasmTagObject::methods, + WasmTagObject::properties, + nullptr, + ClassSpec::DontDefineConstructor}; + +/* static */ +void WasmTagObject::finalize(JSFreeOp* fop, JSObject* obj) { + WasmTagObject& exnObj = obj->as(); + if (!exnObj.isNewborn()) { + fop->release(obj, &exnObj.tag(), MemoryUse::WasmTagTag); + fop->delete_(obj, &exnObj.valueTypes(), MemoryUse::WasmTagType); + } +} + +bool WasmTagObject::construct(JSContext* cx, unsigned argc, Value* vp) { + CallArgs args = CallArgsFromVp(argc, vp); + + if (!ThrowIfNotConstructing(cx, args, "Tag")) { + return false; + } + + // FIXME: The JS API is not finalized and may specify a different behavior + // here. + // For now, we implement the same behavior as V8 and error when called. + JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, + JSMSG_WASM_EXN_CONSTRUCTOR, "WebAssembly.Tag"); + + return false; +} + +/* static */ +WasmTagObject* WasmTagObject::create(JSContext* cx, const ValTypeVector& type, + HandleObject proto) { + AutoSetNewObjectMetadata metadata(cx); + RootedWasmTagObject obj(cx, + NewObjectWithGivenProto(cx, proto)); + if (!obj) { + return nullptr; + } + + MOZ_ASSERT(obj->isNewborn()); + + SharedExceptionTag tag = SharedExceptionTag(cx->new_()); + if (!tag) { + ReportOutOfMemory(cx); + return nullptr; + } + + InitReservedSlot(obj, TAG_SLOT, tag.forget().take(), MemoryUse::WasmTagTag); + + wasm::ValTypeVector* newValueTypes = js_new(); + for (auto t : type) { + if (!newValueTypes->append(t)) { + return nullptr; + } + } + InitReservedSlot(obj, TYPE_SLOT, newValueTypes, MemoryUse::WasmTagType); + + MOZ_ASSERT(!obj->isNewborn()); + + return obj; +} + +bool WasmTagObject::isNewborn() const { + MOZ_ASSERT(is()); + return getReservedSlot(TYPE_SLOT).isUndefined(); +} + +const JSPropertySpec WasmTagObject::properties[] = { + JS_STRING_SYM_PS(toStringTag, "WebAssembly.Tag", JSPROP_READONLY), + JS_PS_END}; + +const JSFunctionSpec WasmTagObject::methods[] = {JS_FS_END}; + +const JSFunctionSpec WasmTagObject::static_methods[] = {JS_FS_END}; + +wasm::ValTypeVector& WasmTagObject::valueTypes() const { + return *(ValTypeVector*)getFixedSlot(TYPE_SLOT).toPrivate(); +}; + +wasm::ResultType WasmTagObject::resultType() const { + return wasm::ResultType::Vector(valueTypes()); +} + +ExceptionTag& WasmTagObject::tag() const { + return *(ExceptionTag*)getReservedSlot(TAG_SLOT).toPrivate(); +} + // ============================================================================ // WebAssembly.Exception class and methods @@ -3581,7 +3700,6 @@ void WasmExceptionObject::finalize(JSFreeOp* fop, JSObject* obj) { WasmExceptionObject& exnObj = obj->as(); if (!exnObj.isNewborn()) { fop->release(obj, &exnObj.tag(), MemoryUse::WasmExceptionTag); - fop->delete_(obj, &exnObj.valueTypes(), MemoryUse::WasmExceptionType); } } @@ -3592,9 +3710,8 @@ bool WasmExceptionObject::construct(JSContext* cx, unsigned argc, Value* vp) { return false; } - // FIXME: The JS API is not finalized and may specify a different behavior - // here. - // For now, we implement the same behavior as V8 and error when called. + // FIXME: When the JS API is finalized, it may be possible to construct + // WebAssembly.Exception instances from JS, but not for now. JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, JSMSG_WASM_EXN_CONSTRUCTOR, "WebAssembly.Exception"); @@ -3603,8 +3720,12 @@ bool WasmExceptionObject::construct(JSContext* cx, unsigned argc, Value* vp) { /* static */ WasmExceptionObject* WasmExceptionObject::create(JSContext* cx, - const ValTypeVector& type, - HandleObject proto) { + wasm::SharedExceptionTag tag, + HandleArrayBufferObject values, + HandleArrayObject refs) { + RootedObject proto( + cx, &cx->global()->getPrototype(JSProto_WasmException).toObject()); + AutoSetNewObjectMetadata metadata(cx); RootedWasmExceptionObject obj( cx, NewObjectWithGivenProto(cx, proto)); @@ -3613,23 +3734,11 @@ WasmExceptionObject* WasmExceptionObject::create(JSContext* cx, } MOZ_ASSERT(obj->isNewborn()); - - SharedExceptionTag tag = SharedExceptionTag(cx->new_()); - if (!tag) { - ReportOutOfMemory(cx); - return nullptr; - } - InitReservedSlot(obj, TAG_SLOT, tag.forget().take(), MemoryUse::WasmExceptionTag); - wasm::ValTypeVector* newValueTypes = js_new(); - for (auto t : type) { - if (!newValueTypes->append(t)) { - return nullptr; - } - } - InitReservedSlot(obj, TYPE_SLOT, newValueTypes, MemoryUse::WasmExceptionType); + obj->initFixedSlot(VALUES_SLOT, ObjectValue(*values)); + obj->initFixedSlot(REFS_SLOT, ObjectValue(*refs)); MOZ_ASSERT(!obj->isNewborn()); @@ -3638,7 +3747,7 @@ WasmExceptionObject* WasmExceptionObject::create(JSContext* cx, bool WasmExceptionObject::isNewborn() const { MOZ_ASSERT(is()); - return getReservedSlot(TYPE_SLOT).isUndefined(); + return getReservedSlot(REFS_SLOT).isUndefined(); } const JSPropertySpec WasmExceptionObject::properties[] = { @@ -3649,126 +3758,11 @@ const JSFunctionSpec WasmExceptionObject::methods[] = {JS_FS_END}; const JSFunctionSpec WasmExceptionObject::static_methods[] = {JS_FS_END}; -wasm::ValTypeVector& WasmExceptionObject::valueTypes() const { - return *(ValTypeVector*)getFixedSlot(TYPE_SLOT).toPrivate(); -}; - -wasm::ResultType WasmExceptionObject::resultType() const { - return wasm::ResultType::Vector(valueTypes()); -} - ExceptionTag& WasmExceptionObject::tag() const { return *(ExceptionTag*)getReservedSlot(TAG_SLOT).toPrivate(); } -// ============================================================================ -// WebAssembly.RuntimeException class and methods - -const JSClassOps WasmRuntimeExceptionObject::classOps_ = { - nullptr, // addProperty - nullptr, // delProperty - nullptr, // enumerate - nullptr, // newEnumerate - nullptr, // resolve - nullptr, // mayResolve - WasmRuntimeExceptionObject::finalize, // finalize - nullptr, // call - nullptr, // hasInstance - nullptr, // construct - nullptr, // trace -}; - -const JSClass WasmRuntimeExceptionObject::class_ = { - "WebAssembly.RuntimeException", - JSCLASS_HAS_RESERVED_SLOTS(WasmRuntimeExceptionObject::RESERVED_SLOTS) | - JSCLASS_FOREGROUND_FINALIZE, - &WasmRuntimeExceptionObject::classOps_, - &WasmRuntimeExceptionObject::classSpec_}; - -const JSClass& WasmRuntimeExceptionObject::protoClass_ = PlainObject::class_; - -static constexpr char WasmRuntimeExceptionName[] = "RuntimeException"; - -const ClassSpec WasmRuntimeExceptionObject::classSpec_ = { - CreateWasmConstructor, - GenericCreatePrototype, - WasmRuntimeExceptionObject::static_methods, - nullptr, - WasmRuntimeExceptionObject::methods, - WasmRuntimeExceptionObject::properties, - nullptr, - ClassSpec::DontDefineConstructor}; - -/* static */ -void WasmRuntimeExceptionObject::finalize(JSFreeOp* fop, JSObject* obj) { - WasmRuntimeExceptionObject& exnObj = obj->as(); - if (!exnObj.isNewborn()) { - fop->release(obj, &exnObj.tag(), MemoryUse::WasmRuntimeExceptionTag); - } -} - -bool WasmRuntimeExceptionObject::construct(JSContext* cx, unsigned argc, - Value* vp) { - CallArgs args = CallArgsFromVp(argc, vp); - - if (!ThrowIfNotConstructing(cx, args, "RuntimeException")) { - return false; - } - - // FIXME: When the JS API is finalized, it may be possible to construct - // WebAssembly.RuntimeException instances from JS, but not for now. - JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, - JSMSG_WASM_EXN_CONSTRUCTOR, - "WebAssembly.RuntimeException"); - - return false; -} - -/* static */ -WasmRuntimeExceptionObject* WasmRuntimeExceptionObject::create( - JSContext* cx, wasm::SharedExceptionTag tag, HandleArrayBufferObject values, - HandleArrayObject refs) { - RootedObject proto( - cx, &cx->global()->getPrototype(JSProto_WasmRuntimeException).toObject()); - - AutoSetNewObjectMetadata metadata(cx); - RootedWasmRuntimeExceptionObject obj( - cx, NewObjectWithGivenProto(cx, proto)); - if (!obj) { - return nullptr; - } - - MOZ_ASSERT(obj->isNewborn()); - InitReservedSlot(obj, TAG_SLOT, tag.forget().take(), - MemoryUse::WasmRuntimeExceptionTag); - - obj->initFixedSlot(VALUES_SLOT, ObjectValue(*values)); - obj->initFixedSlot(REFS_SLOT, ObjectValue(*refs)); - - MOZ_ASSERT(!obj->isNewborn()); - - return obj; -} - -bool WasmRuntimeExceptionObject::isNewborn() const { - MOZ_ASSERT(is()); - return getReservedSlot(REFS_SLOT).isUndefined(); -} - -const JSPropertySpec WasmRuntimeExceptionObject::properties[] = { - JS_STRING_SYM_PS(toStringTag, "WebAssembly.RuntimeException", - JSPROP_READONLY), - JS_PS_END}; - -const JSFunctionSpec WasmRuntimeExceptionObject::methods[] = {JS_FS_END}; - -const JSFunctionSpec WasmRuntimeExceptionObject::static_methods[] = {JS_FS_END}; - -ExceptionTag& WasmRuntimeExceptionObject::tag() const { - return *(ExceptionTag*)getReservedSlot(TAG_SLOT).toPrivate(); -} - -ArrayObject& WasmRuntimeExceptionObject::refs() const { +ArrayObject& WasmExceptionObject::refs() const { return getReservedSlot(REFS_SLOT).toObject().as(); } @@ -4749,8 +4743,8 @@ static bool WebAssemblyClassFinish(JSContext* cx, HandleObject object, {"Table", JSProto_WasmTable}, {"Global", JSProto_WasmGlobal}, #ifdef ENABLE_WASM_EXCEPTIONS + {"Tag", JSProto_WasmTag}, {"Exception", JSProto_WasmException}, - {"RuntimeException", JSProto_WasmRuntimeException}, #endif {"CompileError", GetExceptionProtoKey(JSEXN_WASMCOMPILEERROR)}, {"LinkError", GetExceptionProtoKey(JSEXN_WASMLINKERROR)}, diff --git a/js/src/wasm/WasmJS.h b/js/src/wasm/WasmJS.h index 7c4618071289..433df888ca07 100644 --- a/js/src/wasm/WasmJS.h +++ b/js/src/wasm/WasmJS.h @@ -488,10 +488,10 @@ class WasmTableObject : public NativeObject { #endif }; -// The class of WebAssembly.Exception. This class is used to track exception +// The class of WebAssembly.Tag. This class is used to track exception tag // types for exports and imports. -class WasmExceptionObject : public NativeObject { +class WasmTagObject : public NativeObject { static const unsigned TAG_SLOT = 0; static const unsigned TYPE_SLOT = 1; @@ -509,9 +509,8 @@ class WasmExceptionObject : public NativeObject { static const JSFunctionSpec static_methods[]; static bool construct(JSContext*, unsigned, Value*); - static WasmExceptionObject* create(JSContext* cx, - const wasm::ValTypeVector& type, - HandleObject proto); + static WasmTagObject* create(JSContext* cx, const wasm::ValTypeVector& type, + HandleObject proto); bool isNewborn() const; wasm::ValTypeVector& valueTypes() const; @@ -519,11 +518,11 @@ class WasmExceptionObject : public NativeObject { wasm::ExceptionTag& tag() const; }; -// The class of WebAssembly.RuntimeException. This class is used for +// The class of WebAssembly.Exception. This class is used for // representing exceptions thrown from Wasm in JS. (it is also used as // the internal representation for exceptions in Wasm) -class WasmRuntimeExceptionObject : public NativeObject { +class WasmExceptionObject : public NativeObject { static const unsigned TAG_SLOT = 0; static const unsigned VALUES_SLOT = 1; static const unsigned REFS_SLOT = 2; @@ -542,10 +541,10 @@ class WasmRuntimeExceptionObject : public NativeObject { static const JSFunctionSpec static_methods[]; static bool construct(JSContext*, unsigned, Value*); - static WasmRuntimeExceptionObject* create(JSContext* cx, - wasm::SharedExceptionTag tag, - Handle values, - HandleArrayObject refs); + static WasmExceptionObject* create(JSContext* cx, + wasm::SharedExceptionTag tag, + Handle values, + HandleArrayObject refs); bool isNewborn() const; wasm::ExceptionTag& tag() const; diff --git a/js/src/wasm/WasmModule.cpp b/js/src/wasm/WasmModule.cpp index 807e22633d02..722bb8a93cb6 100644 --- a/js/src/wasm/WasmModule.cpp +++ b/js/src/wasm/WasmModule.cpp @@ -755,15 +755,16 @@ bool Module::instantiateMemory(JSContext* cx, } #ifdef ENABLE_WASM_EXCEPTIONS -bool Module::instantiateImportedException( - JSContext* cx, Handle exnObj, - WasmExceptionObjectVector& exnObjs, SharedExceptionTagVector* tags) const { - MOZ_ASSERT(exnObj); - // The check whether the EventDesc signature matches the exnObj value types +bool Module::instantiateImportedTag(JSContext* cx, + Handle tagObj, + WasmTagObjectVector& tagObjs, + SharedExceptionTagVector* tags) const { + MOZ_ASSERT(tagObj); + // The check whether the EventDesc signature matches the tagObj value types // is done by js::wasm::GetImports(). - // Collects the exception tag from the imported exception. - ExceptionTag& tag = exnObj->tag(); + // Collects the exception tag from the imported tag. + ExceptionTag& tag = tagObj->tag(); if (!tags->append(&tag)) { ReportOutOfMemory(cx); @@ -773,40 +774,39 @@ bool Module::instantiateImportedException( return true; } -bool Module::instantiateLocalException(JSContext* cx, const EventDesc& ed, - WasmExceptionObjectVector& exnObjs, - SharedExceptionTagVector* tags, - uint32_t exnIndex) const { +bool Module::instantiateLocalTag(JSContext* cx, const EventDesc& ed, + WasmTagObjectVector& tagObjs, + SharedExceptionTagVector* tags, + uint32_t tagIndex) const { SharedExceptionTag tag; - // Extend exnObjs in anticipation of an exported exception object. - if (exnObjs.length() <= exnIndex && !exnObjs.resize(exnIndex + 1)) { + // Extend tagObjs in anticipation of an exported tag object. + if (tagObjs.length() <= tagIndex && !tagObjs.resize(tagIndex + 1)) { ReportOutOfMemory(cx); return false; } if (ed.isExport) { - // If the exception description is exported, create an export exception + // If the tag description is exported, create an export tag // object for it. - RootedObject proto( - cx, &cx->global()->getPrototype(JSProto_WasmException).toObject()); - RootedWasmExceptionObject exnObj( - cx, WasmExceptionObject::create(cx, ed.type, proto)); - if (!exnObj) { + RootedObject proto(cx, + &cx->global()->getPrototype(JSProto_WasmTag).toObject()); + RootedWasmTagObject tagObj(cx, WasmTagObject::create(cx, ed.type, proto)); + if (!tagObj) { return false; } - // Take the exception tag that was created inside the WasmExceptionObject. - tag = &exnObj->tag(); - // Save the new export exception object. - exnObjs[exnIndex] = exnObj; + // Take the exception tag that was created inside the WasmTagObject. + tag = &tagObj->tag(); + // Save the new export tag object. + tagObjs[tagIndex] = tagObj; } else { - // Create a new tag for every non exported exception. + // Create a new exception tag for every non exported tag. tag = SharedExceptionTag(cx->new_()); if (!tag) { return false; } - // The exnObj is null if the exception is neither exported nor imported. + // The tagObj is null if the tag is neither exported nor imported. } - // Collect a tag for every exception. + // Collect an exception tag for every tag. if (!tags->emplaceBack(tag)) { ReportOutOfMemory(cx); return false; @@ -815,22 +815,21 @@ bool Module::instantiateLocalException(JSContext* cx, const EventDesc& ed, return true; } -bool Module::instantiateExceptions(JSContext* cx, - WasmExceptionObjectVector& exnObjs, - SharedExceptionTagVector* tags) const { - uint32_t exnIndex = 0; +bool Module::instantiateTags(JSContext* cx, WasmTagObjectVector& tagObjs, + SharedExceptionTagVector* tags) const { + uint32_t tagIndex = 0; for (const EventDesc& ed : metadata().events) { - if (exnIndex < exnObjs.length()) { - Rooted exnObj(cx, exnObjs[exnIndex]); - if (!instantiateImportedException(cx, exnObj, exnObjs, tags)) { + if (tagIndex < tagObjs.length()) { + Rooted tagObj(cx, tagObjs[tagIndex]); + if (!instantiateImportedTag(cx, tagObj, tagObjs, tags)) { return false; } } else { - if (!instantiateLocalException(cx, ed, exnObjs, tags, exnIndex)) { + if (!instantiateLocalTag(cx, ed, tagObjs, tags, tagIndex)) { return false; } } - exnIndex++; + tagIndex++; } return true; } @@ -1111,15 +1110,12 @@ static bool GetGlobalExport(JSContext* cx, HandleWasmInstanceObject instanceObj, return true; } -static bool CreateExportObject(JSContext* cx, - HandleWasmInstanceObject instanceObj, - const JSFunctionVector& funcImports, - const WasmTableObjectVector& tableObjs, - HandleWasmMemoryObject memoryObj, - const WasmExceptionObjectVector& exceptionObjs, - const ValVector& globalImportValues, - const WasmGlobalObjectVector& globalObjs, - const ExportVector& exports) { +static bool CreateExportObject( + JSContext* cx, HandleWasmInstanceObject instanceObj, + const JSFunctionVector& funcImports, const WasmTableObjectVector& tableObjs, + HandleWasmMemoryObject memoryObj, const WasmTagObjectVector& tagObjs, + const ValVector& globalImportValues, + const WasmGlobalObjectVector& globalObjs, const ExportVector& exports) { const Instance& instance = instanceObj->instance(); const Metadata& metadata = instance.metadata(); const GlobalDescVector& globals = metadata.globals; @@ -1186,7 +1182,7 @@ static bool CreateExportObject(JSContext* cx, } #ifdef ENABLE_WASM_EXCEPTIONS case DefinitionKind::Event: { - val = ObjectValue(*exceptionObjs[exp.eventIndex()]); + val = ObjectValue(*tagObjs[exp.eventIndex()]); break; } #endif @@ -1230,7 +1226,7 @@ bool Module::instantiate(JSContext* cx, ImportValues& imports, SharedExceptionTagVector tags; #ifdef ENABLE_WASM_EXCEPTIONS - if (!instantiateExceptions(cx, imports.exceptionObjs, &tags)) { + if (!instantiateTags(cx, imports.tagObjs, &tags)) { return false; } #endif @@ -1281,7 +1277,7 @@ bool Module::instantiate(JSContext* cx, ImportValues& imports, } if (!CreateExportObject(cx, instance, imports.funcs, tableObjs.get(), memory, - imports.exceptionObjs, imports.globalValues, + imports.tagObjs, imports.globalValues, imports.globalObjs, exports_)) { return false; } diff --git a/js/src/wasm/WasmModule.h b/js/src/wasm/WasmModule.h index abc4c33f4df0..a7ce692b655b 100644 --- a/js/src/wasm/WasmModule.h +++ b/js/src/wasm/WasmModule.h @@ -45,7 +45,7 @@ struct ImportValues { JSFunctionVector funcs; WasmTableObjectVector tables; WasmMemoryObject* memory; - WasmExceptionObjectVector exceptionObjs; + WasmTagObjectVector tagObjs; WasmGlobalObjectVector globalObjs; ValVector globalValues; @@ -57,7 +57,7 @@ struct ImportValues { if (memory) { TraceRoot(trc, &memory, "import values memory"); } - exceptionObjs.trace(trc); + tagObjs.trace(trc); globalObjs.trace(trc); globalValues.trace(trc); } @@ -124,16 +124,15 @@ class Module : public JS::WasmModule { bool instantiateMemory(JSContext* cx, MutableHandleWasmMemoryObject memory) const; #ifdef ENABLE_WASM_EXCEPTIONS - bool instantiateImportedException(JSContext* cx, - Handle exnObj, - WasmExceptionObjectVector& exnObjs, - SharedExceptionTagVector* tags) const; - bool instantiateLocalException(JSContext* cx, const EventDesc& ed, - WasmExceptionObjectVector& exnObjs, - SharedExceptionTagVector* tags, - uint32_t exnIndex) const; - bool instantiateExceptions(JSContext* cx, WasmExceptionObjectVector& exnObjs, - SharedExceptionTagVector* tags) const; + bool instantiateImportedTag(JSContext* cx, Handle tagObj, + WasmTagObjectVector& tagObjs, + SharedExceptionTagVector* tags) const; + bool instantiateLocalTag(JSContext* cx, const EventDesc& ed, + WasmTagObjectVector& tagObjs, + SharedExceptionTagVector* tags, + uint32_t tagIndex) const; + bool instantiateTags(JSContext* cx, WasmTagObjectVector& tagObjs, + SharedExceptionTagVector* tags) const; #endif bool instantiateImportedTable(JSContext* cx, const TableDesc& td, Handle table, diff --git a/js/src/wasm/WasmTypeDecls.h b/js/src/wasm/WasmTypeDecls.h index 1f2775ef8581..36f61ff9b695 100644 --- a/js/src/wasm/WasmTypeDecls.h +++ b/js/src/wasm/WasmTypeDecls.h @@ -60,13 +60,12 @@ using WasmGlobalObjectVector = GCVector; using RootedWasmGlobalObject = Rooted; -class WasmExceptionObject; -using WasmExceptionObjectVector = - GCVector; -using RootedWasmExceptionObject = Rooted; +class WasmTagObject; +using WasmTagObjectVector = GCVector; +using RootedWasmTagObject = Rooted; -class WasmRuntimeExceptionObject; -using RootedWasmRuntimeExceptionObject = Rooted; +class WasmExceptionObject; +using RootedWasmExceptionObject = Rooted; namespace wasm { diff --git a/js/src/wasm/WasmTypes.h b/js/src/wasm/WasmTypes.h index f619a914f87d..53803f64b0c4 100644 --- a/js/src/wasm/WasmTypes.h +++ b/js/src/wasm/WasmTypes.h @@ -81,12 +81,16 @@ class Instance; class Table; // Exception tags are used to uniquely identify exceptions. They are stored -// in a vector in Instances and used by both WebAssembly.Exception for import -// and export, and by the representation of thrown exceptions. +// in a vector in Instances and used by both WebAssembly.Tag for import +// and export, and by WebAssembly.Exception for thrown exceptions. // // Since an exception tag is a (trivial) substructure of AtomicRefCounted, the -// RefPtr SharedExceptionTag can have many instances/modules referencing a -// single constant exception tag. +// RefPtr SharedTag can have many instances/modules referencing a single +// constant exception tag. +// +// It is possible that other proposals will start using tags as well, in which +// case it may be worth generalizing this representation for other kinds of +// tags. struct ExceptionTag : AtomicRefCounted { ExceptionTag() = default; @@ -97,7 +101,7 @@ using SharedExceptionTagVector = // WasmJSExceptionObject wraps a JS Value in order to provide a uniform // method of handling JS thrown exceptions. Exceptions originating in Wasm -// are WebAssemby.RuntimeException objects, whereas exceptions from JS are +// are WebAssemby.Exception objects, whereas exceptions from JS are // wrapped as WasmJSExceptionObject objects. class WasmJSExceptionObject : public NativeObject { static const unsigned VALUE_SLOT = 0;