Bug 1738637 - wasm: Emit 'funcref' instead of 'anyfunc' for .type() accessors. r=yury

The specification for js-types now [1] defines the canonical type used
for .type() accessors to be 'funcref' instead of 'anyfunc'. The implementation
and WPTs are updated accordingly. 'anyfunc' is still accepted as an alias of
'funcref' for constructors, but this is already implemented and requires no
changes.

[1] https://github.com/WebAssembly/js-types/pull/34/files
[2] https://github.com/WebAssembly/js-types/blob/main/proposals/js-types/Overview.md

Differential Revision: https://phabricator.services.mozilla.com/D149169
This commit is contained in:
Ryan Hunt 2022-06-16 12:17:21 +00:00
Родитель 5e74be0d5b
Коммит b0e653be71
5 изменённых файлов: 49 добавлений и 69 удалений

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

@ -1133,7 +1133,7 @@ static JSString* UTF8CharsToString(JSContext* cx, const char* chars) {
const ValTypeVector& valTypes) {
Rooted<ArrayObject*> arrayObj(cx, NewDenseEmptyArray(cx));
for (ValType valType : valTypes) {
RootedString type(cx, UTF8CharsToString(cx, ToJSAPIString(valType).get()));
RootedString type(cx, UTF8CharsToString(cx, ToString(valType).get()));
if (!type) {
return nullptr;
}
@ -1170,8 +1170,7 @@ static JSObject* TableTypeToObject(JSContext* cx, RefType type,
uint32_t initial, Maybe<uint32_t> maximum) {
Rooted<IdValueVector> props(cx, IdValueVector(cx));
RootedString elementType(cx,
UTF8CharsToString(cx, ToJSAPIString(type).get()));
RootedString elementType(cx, UTF8CharsToString(cx, ToString(type).get()));
if (!elementType || !props.append(IdValuePair(NameToId(cx->names().element),
StringValue(elementType)))) {
ReportOutOfMemory(cx);
@ -1258,7 +1257,7 @@ static JSObject* GlobalTypeToObject(JSContext* cx, ValType type,
return nullptr;
}
RootedString valueType(cx, UTF8CharsToString(cx, ToJSAPIString(type).get()));
RootedString valueType(cx, UTF8CharsToString(cx, ToString(type).get()));
if (!valueType || !props.append(IdValuePair(NameToId(cx->names().value),
StringValue(valueType)))) {
ReportOutOfMemory(cx);

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

@ -86,20 +86,44 @@ bool wasm::ToRefType(JSContext* cx, JSLinearString* typeLinearStr,
return true;
}
#ifdef ENABLE_WASM_TYPE_REFLECTIONS
UniqueChars wasm::ToJSAPIString(RefType type) {
return ToJSAPIString(ValType(type));
}
UniqueChars wasm::ToJSAPIString(ValType type) {
if (type.kind() == ValType::Ref && type.refTypeKind() == RefType::Func) {
return JS_smprintf("anyfunc");
UniqueChars wasm::ToString(RefType type) {
// Try to emit a shorthand version first
if (type.isNullable() && !type.isTypeIndex()) {
const char* literal = nullptr;
switch (type.kind()) {
case RefType::Func:
literal = "funcref";
break;
case RefType::Extern:
literal = "externref";
break;
case RefType::Eq:
literal = "eqref";
break;
case RefType::TypeIndex:
MOZ_ASSERT_UNREACHABLE();
}
return DuplicateString(literal);
}
return ToString(type);
}
#endif
// Emit the full reference type with heap type
const char* heapType = nullptr;
switch (type.kind()) {
case RefType::Func:
heapType = "func";
break;
case RefType::Extern:
heapType = "extern";
break;
case RefType::Eq:
heapType = "eq";
break;
case RefType::TypeIndex:
return JS_smprintf("(ref %s%d)", type.isNullable() ? "null " : "",
type.typeIndex());
}
return JS_smprintf("(ref %s%s)", type.isNullable() ? "null " : "", heapType);
}
UniqueChars wasm::ToString(ValType type) {
const char* literal = nullptr;
@ -120,47 +144,14 @@ UniqueChars wasm::ToString(ValType type) {
literal = "f64";
break;
case ValType::Ref:
if (type.isNullable() && !type.isTypeIndex()) {
switch (type.refTypeKind()) {
case RefType::Func:
literal = "funcref";
break;
case RefType::Extern:
literal = "externref";
break;
case RefType::Eq:
literal = "eqref";
break;
case RefType::TypeIndex:
MOZ_ASSERT_UNREACHABLE();
}
} else {
const char* heapType = nullptr;
switch (type.refTypeKind()) {
case RefType::Func:
heapType = "func";
break;
case RefType::Extern:
heapType = "extern";
break;
case RefType::Eq:
heapType = "eq";
break;
case RefType::TypeIndex:
return JS_smprintf("(ref %s%d)", type.isNullable() ? "null " : "",
type.refType().typeIndex());
}
return JS_smprintf("(ref %s%s)", type.isNullable() ? "null " : "",
heapType);
}
break;
return ToString(type.refType());
case ValType::Rtt:
if (!type.hasRttDepth()) {
return JS_smprintf("(rtt %d)", type.typeIndex());
}
return JS_smprintf("(rtt %d %d)", type.rttDepth(), type.typeIndex());
}
return JS_smprintf("%s", literal);
return DuplicateString(literal);
}
UniqueChars wasm::ToString(const Maybe<ValType>& type) {

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

@ -748,16 +748,6 @@ extern UniqueChars ToString(ValType type);
extern UniqueChars ToString(const Maybe<ValType>& type);
#ifdef ENABLE_WASM_TYPE_REFLECTIONS
// The JS API sometimes uses different names ("anyfunc" rather than "funcref").
extern UniqueChars ToJSAPIString(RefType type);
extern UniqueChars ToJSAPIString(ValType type);
#endif
} // namespace wasm
} // namespace js

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

@ -50,12 +50,12 @@ test(() => {
}, "externref, immutable")
test(() => {
assert_type({"value": "anyfunc", "mutable": true})
}, "anyfunc, mutable")
assert_type({"value": "funcref", "mutable": true})
}, "funcref, mutable")
test(() => {
assert_type({"value": "anyfunc", "mutable": false})
}, "anyfunc, immutable")
assert_type({"value": "funcref", "mutable": false})
}, "funcref, immutable")
test(() => {
const myglobal = new WebAssembly.Global({"value": "i32", "mutable": true});

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

@ -10,17 +10,17 @@ function assert_type(argument) {
}
test(() => {
assert_type({ "minimum": 0, "element": "anyfunc"});
assert_type({ "minimum": 0, "element": "funcref"});
}, "Zero initial, no maximum");
test(() => {
assert_type({ "minimum": 5, "element": "anyfunc" });
assert_type({ "minimum": 5, "element": "funcref" });
}, "Non-zero initial, no maximum");
test(() => {
assert_type({ "minimum": 0, "maximum": 0, "element": "anyfunc" });
assert_type({ "minimum": 0, "maximum": 0, "element": "funcref" });
}, "Zero maximum");
test(() => {
assert_type({ "minimum": 0, "maximum": 5, "element": "anyfunc" });
assert_type({ "minimum": 0, "maximum": 5, "element": "funcref" });
}, "Non-zero maximum");