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
This commit is contained in:
Asumu Takikawa 2021-07-21 19:17:51 +00:00
Родитель fb077089e7
Коммит 04f64983e2
15 изменённых файлов: 244 добавлений и 258 удалений

Просмотреть файл

@ -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)) \

Просмотреть файл

@ -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")

Просмотреть файл

@ -127,9 +127,9 @@ enum class GCAbortReason {
_(WasmResolveResponseClosure) \
_(WasmModule) \
_(WasmTableTable) \
_(WasmTagTag) \
_(WasmTagType) \
_(WasmExceptionTag) \
_(WasmExceptionType) \
_(WasmRuntimeExceptionTag) \
_(WasmRttValueChildren) \
_(FileObjectFile) \
_(Debugger) \

Просмотреть файл

@ -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/
);
}

Просмотреть файл

@ -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");

Просмотреть файл

@ -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

Просмотреть файл

@ -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);

Просмотреть файл

@ -505,8 +505,7 @@ bool wasm::HandleThrow(JSContext* cx, WasmFrameIter& iter,
if (tryNote) {
cx->clearPendingException();
if (!exn.isObject() ||
!exn.toObject().is<WasmRuntimeExceptionObject>()) {
if (!exn.isObject() || !exn.toObject().is<WasmExceptionObject>()) {
RootedObject obj(cx, WasmJSExceptionObject::create(cx, &exn));
if (!obj) {
MOZ_ASSERT(cx->isThrowingOutOfMemory());

Просмотреть файл

@ -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<WasmRuntimeExceptionObject>()) {
ExceptionTag& exnTag = exn->as<WasmRuntimeExceptionObject>().tag();
if (exn->is<WasmExceptionObject>()) {
ExceptionTag& exnTag = exn->as<WasmExceptionObject>().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<WasmRuntimeExceptionObject>());
RootedWasmRuntimeExceptionObject exnObj(
cx, &exn->as<WasmRuntimeExceptionObject>());
MOZ_ASSERT(exn->is<WasmExceptionObject>());
RootedWasmExceptionObject exnObj(cx, &exn->as<WasmExceptionObject>());
// TODO/AnyRef-boxing: With boxed immediates and strings, this may need to
// handle other kinds of values.

Просмотреть файл

@ -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<WasmExceptionObject>()) {
return ThrowBadImportType(cx, import.field.get(), "Exception");
if (!v.isObject() || !v.toObject().is<WasmTagObject>()) {
return ThrowBadImportType(cx, import.field.get(), "Tag");
}
RootedWasmExceptionObject obj(cx,
&v.toObject().as<WasmExceptionObject>());
RootedWasmTagObject obj(cx, &v.toObject().as<WasmTagObject>());
// 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<WasmTagObject, WasmTagName>,
GenericCreatePrototype<WasmTagObject>,
WasmTagObject::static_methods,
nullptr,
WasmTagObject::methods,
WasmTagObject::properties,
nullptr,
ClassSpec::DontDefineConstructor};
/* static */
void WasmTagObject::finalize(JSFreeOp* fop, JSObject* obj) {
WasmTagObject& exnObj = obj->as<WasmTagObject>();
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<WasmTagObject>(cx, proto));
if (!obj) {
return nullptr;
}
MOZ_ASSERT(obj->isNewborn());
SharedExceptionTag tag = SharedExceptionTag(cx->new_<ExceptionTag>());
if (!tag) {
ReportOutOfMemory(cx);
return nullptr;
}
InitReservedSlot(obj, TAG_SLOT, tag.forget().take(), MemoryUse::WasmTagTag);
wasm::ValTypeVector* newValueTypes = js_new<ValTypeVector>();
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<WasmTagObject>());
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<WasmExceptionObject>();
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<WasmExceptionObject>(cx, proto));
@ -3613,23 +3734,11 @@ WasmExceptionObject* WasmExceptionObject::create(JSContext* cx,
}
MOZ_ASSERT(obj->isNewborn());
SharedExceptionTag tag = SharedExceptionTag(cx->new_<ExceptionTag>());
if (!tag) {
ReportOutOfMemory(cx);
return nullptr;
}
InitReservedSlot(obj, TAG_SLOT, tag.forget().take(),
MemoryUse::WasmExceptionTag);
wasm::ValTypeVector* newValueTypes = js_new<ValTypeVector>();
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<WasmExceptionObject>());
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<WasmRuntimeExceptionObject, WasmRuntimeExceptionName>,
GenericCreatePrototype<WasmRuntimeExceptionObject>,
WasmRuntimeExceptionObject::static_methods,
nullptr,
WasmRuntimeExceptionObject::methods,
WasmRuntimeExceptionObject::properties,
nullptr,
ClassSpec::DontDefineConstructor};
/* static */
void WasmRuntimeExceptionObject::finalize(JSFreeOp* fop, JSObject* obj) {
WasmRuntimeExceptionObject& exnObj = obj->as<WasmRuntimeExceptionObject>();
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<WasmRuntimeExceptionObject>(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<WasmRuntimeExceptionObject>());
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<ArrayObject>();
}
@ -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)},

Просмотреть файл

@ -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,8 +509,7 @@ class WasmExceptionObject : public NativeObject {
static const JSFunctionSpec static_methods[];
static bool construct(JSContext*, unsigned, Value*);
static WasmExceptionObject* create(JSContext* cx,
const wasm::ValTypeVector& type,
static WasmTagObject* create(JSContext* cx, const wasm::ValTypeVector& type,
HandleObject proto);
bool isNewborn() 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,7 +541,7 @@ class WasmRuntimeExceptionObject : public NativeObject {
static const JSFunctionSpec static_methods[];
static bool construct(JSContext*, unsigned, Value*);
static WasmRuntimeExceptionObject* create(JSContext* cx,
static WasmExceptionObject* create(JSContext* cx,
wasm::SharedExceptionTag tag,
Handle<ArrayBufferObject*> values,
HandleArrayObject refs);

Просмотреть файл

@ -755,15 +755,16 @@ bool Module::instantiateMemory(JSContext* cx,
}
#ifdef ENABLE_WASM_EXCEPTIONS
bool Module::instantiateImportedException(
JSContext* cx, Handle<WasmExceptionObject*> 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<WasmTagObject*> 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,
bool Module::instantiateLocalTag(JSContext* cx, const EventDesc& ed,
WasmTagObjectVector& tagObjs,
SharedExceptionTagVector* tags,
uint32_t exnIndex) const {
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_<ExceptionTag>());
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,
bool Module::instantiateTags(JSContext* cx, WasmTagObjectVector& tagObjs,
SharedExceptionTagVector* tags) const {
uint32_t exnIndex = 0;
uint32_t tagIndex = 0;
for (const EventDesc& ed : metadata().events) {
if (exnIndex < exnObjs.length()) {
Rooted<WasmExceptionObject*> exnObj(cx, exnObjs[exnIndex]);
if (!instantiateImportedException(cx, exnObj, exnObjs, tags)) {
if (tagIndex < tagObjs.length()) {
Rooted<WasmTagObject*> 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,
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 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;
}

Просмотреть файл

@ -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,15 +124,14 @@ class Module : public JS::WasmModule {
bool instantiateMemory(JSContext* cx,
MutableHandleWasmMemoryObject memory) const;
#ifdef ENABLE_WASM_EXCEPTIONS
bool instantiateImportedException(JSContext* cx,
Handle<WasmExceptionObject*> exnObj,
WasmExceptionObjectVector& exnObjs,
bool instantiateImportedTag(JSContext* cx, Handle<WasmTagObject*> tagObj,
WasmTagObjectVector& tagObjs,
SharedExceptionTagVector* tags) const;
bool instantiateLocalException(JSContext* cx, const EventDesc& ed,
WasmExceptionObjectVector& exnObjs,
bool instantiateLocalTag(JSContext* cx, const EventDesc& ed,
WasmTagObjectVector& tagObjs,
SharedExceptionTagVector* tags,
uint32_t exnIndex) const;
bool instantiateExceptions(JSContext* cx, WasmExceptionObjectVector& exnObjs,
uint32_t tagIndex) const;
bool instantiateTags(JSContext* cx, WasmTagObjectVector& tagObjs,
SharedExceptionTagVector* tags) const;
#endif
bool instantiateImportedTable(JSContext* cx, const TableDesc& td,

Просмотреть файл

@ -60,13 +60,12 @@ using WasmGlobalObjectVector =
GCVector<WasmGlobalObject*, 0, SystemAllocPolicy>;
using RootedWasmGlobalObject = Rooted<WasmGlobalObject*>;
class WasmExceptionObject;
using WasmExceptionObjectVector =
GCVector<WasmExceptionObject*, 0, SystemAllocPolicy>;
using RootedWasmExceptionObject = Rooted<WasmExceptionObject*>;
class WasmTagObject;
using WasmTagObjectVector = GCVector<WasmTagObject*, 0, SystemAllocPolicy>;
using RootedWasmTagObject = Rooted<WasmTagObject*>;
class WasmRuntimeExceptionObject;
using RootedWasmRuntimeExceptionObject = Rooted<WasmRuntimeExceptionObject*>;
class WasmExceptionObject;
using RootedWasmExceptionObject = Rooted<WasmExceptionObject*>;
namespace wasm {

Просмотреть файл

@ -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> {
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;