Diff
Modified: trunk/JSTests/ChangeLog (285064 => 285065)
--- trunk/JSTests/ChangeLog 2021-10-30 00:35:14 UTC (rev 285064)
+++ trunk/JSTests/ChangeLog 2021-10-30 00:46:27 UTC (rev 285065)
@@ -1,3 +1,16 @@
+2021-10-29 Dmitry Bezhetskov <[email protected]>
+
+ [WASM-Function-References] Add support for (ref.null heaptype)
+ https://bugs.webkit.org/show_bug.cgi?id=229707
+
+ Reviewed by Yusuke Suzuki.
+
+ Added spec tests for (ref.null $t) : https://github.com/WebAssembly/function-references/blob/master/test/core/ref_null.wast.
+
+ * wasm.yaml:
+ * wasm/function-references-spec-tests/call_ref.wast.js:
+ * wasm/function-references-spec-tests/ref_null.wast.js: Added.
+
2021-10-27 Dmitry Bezhetskov <[email protected]>
[WASM-Function-References] Add call_ref spec tests
Modified: trunk/JSTests/wasm/function-references-spec-tests/call_ref.wast.js (285064 => 285065)
--- trunk/JSTests/wasm/function-references-spec-tests/call_ref.wast.js 2021-10-30 00:35:14 UTC (rev 285064)
+++ trunk/JSTests/wasm/function-references-spec-tests/call_ref.wast.js 2021-10-30 00:46:27 UTC (rev 285065)
@@ -1,11 +1,13 @@
-let $1 = instance("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x18\x04\x60\x01\x7f\x01\x7f\x60\x01\x7e\x01\x7e\x60\x02\x7e\x7e\x01\x7e\x60\x02\x6b\x00\x7f\x01\x7f\x03\x0a\x09\x03\x00\x00\x00\x01\x02\x01\x01\x01\x06\x1f\x05\x6b\x01\x00\xd2\x04\x0b\x6b\x02\x00\xd2\x05\x0b\x6b\x01\x00\xd2\x06\x0b\x6b\x01\x00\xd2\x07\x0b\x6b\x01\x00\xd2\x08\x0b\x07\x2a\x06\x03\x72\x75\x6e\x00\x03\x03\x66\x61\x63\x00\x04\x07\x66\x61\x63\x2d\x61\x63\x63\x00\x05\x03\x66\x69\x62\x00\x06\x04\x65\x76\x65\x6e\x00\x07\x03\x6f\x64\x64\x00\x08\x09\x17\x05\x03\x00\x02\x01\x02\x03\x00\x01\x04\x03\x00\x01\x05\x03\x00\x01\x06\x03\x00\x02\x07\x08\x0a\xa7\x01\x09\x07\x00\x20\x01\x20\x00\x14\x0b\x07\x00\x20\x00\x20\x00\x6c\x0b\x07\x00\x41\x00\x20\x00\x6b\x0b\x15\x01\x02\x6c\x00\xd2\x01\x21\x01\xd2\x02\x21\x02\x20\x00\x20\x01\x14\x20\x02\x14\x0b\x16\x00\x20\x00\x50\x04\x7e\x42\x01\x05\x20\x00\x20\x00\x42\x01\x7d\x23\x00\x14\x7e\x0b\x0b\x18\x00\x20\x00\x50\x04\x7e\x20\x01\x05\x20\x00\x42\x01\x7d\x20\x00\x20\x01\
x7e\x23\x01\x14\x0b\x0b\x1e\x00\x20\x00\x42\x01\x58\x04\x7e\x42\x01\x05\x20\x00\x42\x02\x7d\x23\x02\x14\x20\x00\x42\x01\x7d\x23\x02\x14\x7c\x0b\x0b\x13\x00\x20\x00\x50\x04\x7e\x42\x2c\x05\x20\x00\x42\x01\x7d\x23\x04\x14\x0b\x0b\x14\x00\x20\x00\x50\x04\x7e\x42\xe3\x00\x05\x20\x00\x42\x01\x7d\x23\x03\x14\x0b\x0b");
+let $1 = instance("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x1c\x05\x60\x01\x7f\x01\x7f\x60\x01\x7e\x01\x7e\x60\x02\x6b\x00\x7f\x01\x7f\x60\x00\x01\x7f\x60\x02\x7e\x7e\x01\x7e\x03\x0b\x0a\x02\x00\x00\x00\x03\x01\x04\x01\x01\x01\x06\x1f\x05\x6b\x01\x00\xd2\x05\x0b\x6b\x04\x00\xd2\x06\x0b\x6b\x01\x00\xd2\x07\x0b\x6b\x01\x00\xd2\x08\x0b\x6b\x01\x00\xd2\x09\x0b\x07\x31\x07\x03\x72\x75\x6e\x00\x03\x04\x6e\x75\x6c\x6c\x00\x04\x03\x66\x61\x63\x00\x05\x07\x66\x61\x63\x2d\x61\x63\x63\x00\x06\x03\x66\x69\x62\x00\x07\x04\x65\x76\x65\x6e\x00\x08\x03\x6f\x64\x64\x00\x09\x09\x06\x01\x03\x00\x02\x01\x02\x0a\xaf\x01\x0a\x07\x00\x20\x01\x20\x00\x14\x0b\x07\x00\x20\x00\x20\x00\x6c\x0b\x07\x00\x41\x00\x20\x00\x6b\x0b\x15\x01\x02\x6c\x00\xd2\x01\x21\x01\xd2\x02\x21\x02\x20\x00\x20\x01\x14\x20\x02\x14\x0b\x07\x00\x41\x01\xd0\x00\x14\x0b\x16\x00\x20\x00\x50\x04\x7e\x42\x01\x05\x20\x00\x20\x00\x42\x01\x7d\x23\x00\x14\x7e\x0b\x0b\x18\x00\x20\x00\x50\x04\x7e\x20\x01\x05\x20\x00\x42\x01\x7d\x20\x
00\x20\x01\x7e\x23\x01\x14\x0b\x0b\x1e\x00\x20\x00\x42\x01\x58\x04\x7e\x42\x01\x05\x20\x00\x42\x02\x7d\x23\x02\x14\x20\x00\x42\x01\x7d\x23\x02\x14\x7c\x0b\x0b\x13\x00\x20\x00\x50\x04\x7e\x42\x2c\x05\x20\x00\x42\x01\x7d\x23\x04\x14\x0b\x0b\x14\x00\x20\x00\x50\x04\x7e\x42\xe3\x00\x05\x20\x00\x42\x01\x7d\x23\x03\x14\x0b\x0b");
+// call_ref.wast:94
assert_return(() => call($1, "run", [0]), 0);
+
+// call_ref.wast:95
assert_return(() => call($1, "run", [3]), -9);
-// call_ref.wast:99
-// FIXME: add support for (ref.null <heaptype>): https://bugs.webkit.org/show_bug.cgi?id=229707.
-// (assert_trap (invoke "null") "null function")
+// call_ref.wast:97
+assert_trap(() => call($1, "null", []));
// call_ref.wast:99
run(() => call(instance("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x09\x02\x60\x00\x00\x60\x01\x7e\x01\x7e\x02\x0a\x01\x02\x24\x31\x03\x66\x61\x63\x00\x01\x03\x02\x01\x00\x07\x07\x01\x03\x72\x75\x6e\x00\x01\x0a\x15\x01\x13\x00\x02\x40\x42\x00\x10\x00\x01\x42\x01\x01\x51\x45\x0d\x00\x0f\x0b\x00\x0b", exports("$1", $1)), "run", [])); // (assert_return (invoke "fac" (i64.const 0)) (i64.const 1))
Added: trunk/JSTests/wasm/function-references-spec-tests/ref_null.wast.js (0 => 285065)
--- trunk/JSTests/wasm/function-references-spec-tests/ref_null.wast.js (rev 0)
+++ trunk/JSTests/wasm/function-references-spec-tests/ref_null.wast.js 2021-10-30 00:46:27 UTC (rev 285065)
@@ -0,0 +1,24 @@
+/*
+ (module
+ (type $t (func))
+ (func (export "externref") (result externref) (ref.null extern))
+ (func (export "funcref") (result funcref) (ref.null func))
+ (func (export "ref") (result (ref null $t)) (ref.null $t))
+
+ (global externref (ref.null extern))
+ (global funcref (ref.null func))
+ (global (ref null $t) (ref.null $t))
+ )
+*/
+
+let $1 = instance("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x11\x04\x60\x00\x00\x60\x00\x01\x6f\x60\x00\x01\x70\x60\x00\x01\x6c\x00\x03\x04\x03\x01\x02\x03\x06\x11\x03\x6f\x00\xd0\x6f\x0b\x70\x00\xd0\x70\x0b\x6c\x00\x00\xd0\x00\x0b\x07\x1d\x03\x09\x65\x78\x74\x65\x72\x6e\x72\x65\x66\x00\x00\x07\x66\x75\x6e\x63\x72\x65\x66\x00\x01\x03\x72\x65\x66\x00\x02\x0a\x10\x03\x04\x00\xd0\x6f\x0b\x04\x00\xd0\x70\x0b\x04\x00\xd0\x00\x0b");
+
+// ref_null.wast:12
+assert_return(() => call($1, "externref", []), null);
+
+// ref_null.wast:13
+assert_return(() => call($1, "funcref", []), null);
+
+// ref_null.wast:14
+// FIXME: https://bugs.webkit.org/show_bug.cgi?id=231222
+// assert_return(() => call($1, "ref", []), null);
Modified: trunk/JSTests/wasm.yaml (285064 => 285065)
--- trunk/JSTests/wasm.yaml 2021-10-30 00:35:14 UTC (rev 285064)
+++ trunk/JSTests/wasm.yaml 2021-10-30 00:46:27 UTC (rev 285065)
@@ -139,6 +139,8 @@
- path: wasm/function-references-spec-tests/call_ref.wast.js
cmd: runWebAssemblyFunctionReferenceSpecTest :normal
+- path: wasm/function-references-spec-tests/ref_null.wast.js
+ cmd: runWebAssemblyFunctionReferenceSpecTest :normal
- path: wasm/spec-tests/address.wast.js
cmd: runWebAssemblySpecTest :normal
Modified: trunk/Source/_javascript_Core/ChangeLog (285064 => 285065)
--- trunk/Source/_javascript_Core/ChangeLog 2021-10-30 00:35:14 UTC (rev 285064)
+++ trunk/Source/_javascript_Core/ChangeLog 2021-10-30 00:46:27 UTC (rev 285065)
@@ -1,3 +1,34 @@
+2021-10-29 Dmitry Bezhetskov <[email protected]>
+
+ [WASM-Function-References] Add support for (ref.null heaptype)
+ https://bugs.webkit.org/show_bug.cgi?id=229707
+
+ Reviewed by Yusuke Suzuki.
+
+ Added support for (ref.null $t) from the typed function references proposal:
+ https://github.com/WebAssembly/function-references/blob/master/proposals/function-references/Overview.md#optional-references.
+ Since now we can have null references I've also updated call_ref implementation to check the target reference for null.
+ According to the spec (https://github.com/WebAssembly/function-references/blob/master/proposals/function-references/Overview.md#functions)
+ we must trap on null.
+
+ * wasm/WasmAirIRGenerator.cpp:
+ (JSC::Wasm::AirIRGenerator::addCallRef):
+ * wasm/WasmB3IRGenerator.cpp:
+ (JSC::Wasm::B3IRGenerator::addCallRef):
+ * wasm/WasmExceptionType.h:
+ * wasm/WasmFormat.h:
+ (JSC::Wasm::isTypeIndexHeapType):
+ * wasm/WasmFunctionParser.h:
+ (JSC::Wasm::FunctionParser<Context>::parseExpression):
+ * wasm/WasmParser.h:
+ (JSC::Wasm::Parser<SuccessType>::parseHeapType):
+ (JSC::Wasm::Parser<SuccessType>::parseValueType):
+ * wasm/WasmSectionParser.cpp:
+ (JSC::Wasm::SectionParser::parseInitExpr):
+ * wasm/WasmSlowPaths.cpp:
+ (JSC::LLInt::doWasmCallRef):
+
+
2021-10-28 Saam Barati <[email protected]>
Don't call type() on Structure, instead call type() on its typeInfo()
Modified: trunk/Source/_javascript_Core/wasm/WasmAirIRGenerator.cpp (285064 => 285065)
--- trunk/Source/_javascript_Core/wasm/WasmAirIRGenerator.cpp 2021-10-30 00:35:14 UTC (rev 285064)
+++ trunk/Source/_javascript_Core/wasm/WasmAirIRGenerator.cpp 2021-10-30 00:46:27 UTC (rev 285065)
@@ -3444,6 +3444,15 @@
ExpressionType calleeFunction = args.takeLast();
m_maxNumJSCallArguments = std::max(m_maxNumJSCallArguments, static_cast<uint32_t>(args.size()));
+ // Check the target reference for null.
+ auto tmpForNull = g64();
+ append(Move, Arg::bigImm(JSValue::encode(jsNull())), tmpForNull);
+ emitCheck([&] {
+ return Inst(Branch64, nullptr, Arg::relCond(MacroAssembler::Equal), calleeFunction, tmpForNull);
+ }, [=] (CCallHelpers& jit, const B3::StackmapGenerationParams&) {
+ this->emitThrowException(jit, ExceptionType::NullReference);
+ });
+
ExpressionType calleeCode = g64();
append(Move, Arg::addr(calleeFunction, WebAssemblyFunctionBase::offsetOfEntrypointLoadLocation()), calleeCode); // Pointer to callee code.
Modified: trunk/Source/_javascript_Core/wasm/WasmB3IRGenerator.cpp (285064 => 285065)
--- trunk/Source/_javascript_Core/wasm/WasmB3IRGenerator.cpp 2021-10-30 00:35:14 UTC (rev 285064)
+++ trunk/Source/_javascript_Core/wasm/WasmB3IRGenerator.cpp 2021-10-30 00:46:27 UTC (rev 285065)
@@ -3161,6 +3161,15 @@
Value* calleeInstance = m_currentBlock->appendNew<MemoryValue>(m_proc, Load, pointerType(), origin(),
m_currentBlock->appendNew<Value>(m_proc, Add, origin(), jsCalleeInstance, instanceOffset));
+ // Check the target reference for null.
+ {
+ CheckValue* check = m_currentBlock->appendNew<CheckValue>(m_proc, Check, origin(),
+ m_currentBlock->appendNew<Value>(m_proc, Equal, origin(), callee, m_currentBlock->appendNew<Const64Value>(m_proc, origin(), JSValue::encode(jsNull()))));
+ check->setGenerator([=] (CCallHelpers& jit, const B3::StackmapGenerationParams&) {
+ this->emitExceptionCheck(jit, ExceptionType::NullReference);
+ });
+ }
+
Value* calleeCode = m_currentBlock->appendNew<MemoryValue>(m_proc, Load, pointerType(), origin(),
m_currentBlock->appendNew<MemoryValue>(m_proc, Load, pointerType(), origin(), callee,
safeCast<int32_t>(WebAssemblyFunctionBase::offsetOfEntrypointLoadLocation())));
Modified: trunk/Source/_javascript_Core/wasm/WasmExceptionType.h (285064 => 285065)
--- trunk/Source/_javascript_Core/wasm/WasmExceptionType.h 2021-10-30 00:35:14 UTC (rev 285064)
+++ trunk/Source/_javascript_Core/wasm/WasmExceptionType.h 2021-10-30 00:46:27 UTC (rev 285065)
@@ -36,6 +36,7 @@
macro(OutOfBoundsTableAccess, "Out of bounds table access") \
macro(OutOfBoundsCallIndirect, "Out of bounds call_indirect") \
macro(NullTableEntry, "call_indirect to a null table entry") \
+ macro(NullReference, "call_ref to a null reference") \
macro(BadSignature, "call_indirect to a signature that does not match") \
macro(OutOfBoundsTrunc, "Out of bounds Trunc operation") \
macro(Unreachable, "Unreachable code should not be executed") \
Modified: trunk/Source/_javascript_Core/wasm/WasmFormat.h (285064 => 285065)
--- trunk/Source/_javascript_Core/wasm/WasmFormat.h 2021-10-30 00:35:14 UTC (rev 285064)
+++ trunk/Source/_javascript_Core/wasm/WasmFormat.h 2021-10-30 00:46:27 UTC (rev 285065)
@@ -138,6 +138,14 @@
return isRefType(type) && !isExternref(type) && !isFuncref(type);
}
+inline bool isTypeIndexHeapType(int32_t heapType)
+{
+ if (!Options::useWebAssemblyTypedFunctionReferences())
+ return false;
+
+ return heapType >= 0;
+}
+
inline bool isSubtype(Type sub, Type parent)
{
if (sub.isNullable() && !parent.isNullable())
Modified: trunk/Source/_javascript_Core/wasm/WasmFunctionParser.h (285064 => 285065)
--- trunk/Source/_javascript_Core/wasm/WasmFunctionParser.h 2021-10-30 00:35:14 UTC (rev 285064)
+++ trunk/Source/_javascript_Core/wasm/WasmFunctionParser.h 2021-10-30 00:46:27 UTC (rev 285065)
@@ -1078,7 +1078,16 @@
case RefNull: {
Type typeOfNull;
- WASM_PARSER_FAIL_IF(!parseRefType(m_info, typeOfNull), "ref.null type must be a reference type");
+ if (Options::useWebAssemblyTypedFunctionReferences()) {
+ int32_t heapType;
+ WASM_PARSER_FAIL_IF(!parseHeapType(m_info, heapType), "ref.null heaptype must be funcref, externref or type_idx");
+ if (isTypeIndexHeapType(heapType)) {
+ SignatureIndex signatureIndex = SignatureInformation::get(m_info.usedSignatures[heapType].get());
+ typeOfNull = Type { TypeKind::RefNull, Nullable::Yes, signatureIndex };
+ } else
+ typeOfNull = Type { TypeKind::RefNull, Nullable::Yes, static_cast<SignatureIndex>(heapType) };
+ } else
+ WASM_PARSER_FAIL_IF(!parseRefType(m_info, typeOfNull), "ref.null type must be a reference type");
m_expressionStack.constructAndAppend(typeOfNull, m_context.addConstant(typeOfNull, JSValue::encode(jsNull())));
return { };
}
Modified: trunk/Source/_javascript_Core/wasm/WasmParser.h (285064 => 285065)
--- trunk/Source/_javascript_Core/wasm/WasmParser.h 2021-10-30 00:35:14 UTC (rev 285064)
+++ trunk/Source/_javascript_Core/wasm/WasmParser.h 2021-10-30 00:46:27 UTC (rev 285065)
@@ -87,6 +87,7 @@
bool WARN_UNUSED_RETURN parseValueType(const ModuleInformation&, Type&);
bool WARN_UNUSED_RETURN parseRefType(const ModuleInformation&, Type&);
bool WARN_UNUSED_RETURN parseExternalKind(ExternalKind&);
+ bool WARN_UNUSED_RETURN parseHeapType(const ModuleInformation&, int32_t&);
size_t m_offset = 0;
@@ -294,6 +295,31 @@
}
template<typename SuccessType>
+ALWAYS_INLINE bool Parser<SuccessType>::parseHeapType(const ModuleInformation& info, int32_t& result)
+{
+ if (!Options::useWebAssemblyTypedFunctionReferences())
+ return false;
+
+ int32_t heapType;
+ if (!parseVarInt32(heapType))
+ return false;
+
+ if (heapType < 0) {
+ if (isValidHeapTypeKind(static_cast<TypeKind>(heapType))) {
+ result = heapType;
+ return true;
+ }
+ return false;
+ }
+
+ if (static_cast<size_t>(heapType) >= info.usedSignatures.size())
+ return false;
+
+ result = heapType;
+ return true;
+}
+
+template<typename SuccessType>
ALWAYS_INLINE bool Parser<SuccessType>::parseValueType(const ModuleInformation& info, Type& result)
{
int8_t kind;
@@ -310,24 +336,11 @@
sigIndex = static_cast<SignatureIndex>(typeKind);
typeKind = TypeKind::RefNull;
} else if (typeKind == TypeKind::Ref || typeKind == TypeKind::RefNull) {
- if (!Options::useWebAssemblyTypedFunctionReferences())
- return false;
-
+ isNullable = typeKind == TypeKind::RefNull;
int32_t heapType;
- isNullable = typeKind == TypeKind::RefNull;
-
- if (!parseVarInt32(heapType))
+ if (!parseHeapType(info, heapType))
return false;
- if (heapType < 0) {
- TypeKind heapKind = static_cast<TypeKind>(heapType);
- if (!isValidHeapTypeKind(heapKind))
- return false;
- sigIndex = static_cast<SignatureIndex>(heapKind);
- } else {
- if (static_cast<size_t>(heapType) >= info.usedSignatures.size())
- return false;
- sigIndex = SignatureInformation::get(info.usedSignatures[heapType].get());
- }
+ sigIndex = heapType < 0 ? static_cast<SignatureIndex>(heapType) : SignatureInformation::get(info.usedSignatures[heapType].get());
}
Type type = { typeKind, static_cast<Nullable>(isNullable), sigIndex };
Modified: trunk/Source/_javascript_Core/wasm/WasmSectionParser.cpp (285064 => 285065)
--- trunk/Source/_javascript_Core/wasm/WasmSectionParser.cpp 2021-10-30 00:35:14 UTC (rev 285064)
+++ trunk/Source/_javascript_Core/wasm/WasmSectionParser.cpp 2021-10-30 00:46:27 UTC (rev 285065)
@@ -618,7 +618,17 @@
case RefNull: {
Type typeOfNull;
- WASM_PARSER_FAIL_IF(!parseRefType(m_info, typeOfNull), "ref.null type must be a reference type");
+ if (Options::useWebAssemblyTypedFunctionReferences()) {
+ int32_t heapType;
+ WASM_PARSER_FAIL_IF(!parseHeapType(m_info, heapType), "ref.null heaptype must be funcref, externref or type_idx");
+ if (isTypeIndexHeapType(heapType)) {
+ SignatureIndex signatureIndex = SignatureInformation::get(m_info->usedSignatures[heapType].get());
+ typeOfNull = Type { TypeKind::RefNull, Nullable::Yes, signatureIndex };
+ } else
+ typeOfNull = Type { TypeKind::RefNull, Nullable::Yes, static_cast<SignatureIndex>(heapType) };
+ } else
+ WASM_PARSER_FAIL_IF(!parseRefType(m_info, typeOfNull), "ref.null type must be a reference type");
+
resultType = typeOfNull;
bitsOrImportNumber = JSValue::encode(jsNull());
break;
Modified: trunk/Source/_javascript_Core/wasm/WasmSlowPaths.cpp (285064 => 285065)
--- trunk/Source/_javascript_Core/wasm/WasmSlowPaths.cpp 2021-10-30 00:35:14 UTC (rev 285064)
+++ trunk/Source/_javascript_Core/wasm/WasmSlowPaths.cpp 2021-10-30 00:46:27 UTC (rev 285065)
@@ -506,6 +506,9 @@
{
UNUSED_PARAM(callFrame);
+ if (targetReference.isNull())
+ WASM_THROW(Wasm::ExceptionType::NullReference);
+
ASSERT(targetReference.isObject());
JSObject* referenceAsObject = jsCast<JSObject*>(targetReference);