WebKit Bugzilla
Attachment 370159 Details for
Bug 197969
: [WASM-References] Add support for Anyref in parameters and return types, Ref.null and Ref.is_null for Anyref values.
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch
bug-197969-20190517151643.patch (text/plain), 40.22 KB, created by
Justin Michaud
on 2019-05-17 15:16:44 PDT
(
hide
)
Description:
Patch
Filename:
MIME Type:
Creator:
Justin Michaud
Created:
2019-05-17 15:16:44 PDT
Size:
40.22 KB
patch
obsolete
>Subversion Revision: 245483 >diff --git a/Source/JavaScriptCore/ChangeLog b/Source/JavaScriptCore/ChangeLog >index 82d5cfe1649d48ad4137e843432cf12c91cf4514..0709475387e37b848410f5ac446550fe4656da99 100644 >--- a/Source/JavaScriptCore/ChangeLog >+++ b/Source/JavaScriptCore/ChangeLog >@@ -1,3 +1,47 @@ >+2019-05-17 Justin Michaud <justin_michaud@apple.com> >+ >+ [WASM-References] Add support for Anyref in parameters and return types, Ref.null and Ref.is_null for Anyref values. >+ https://bugs.webkit.org/show_bug.cgi?id=197969 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ Add a new runtime option for wasm references. >+ Add support for Anyref as a value type. >+ Add support for Anyref in parameters and return types of Wasm functions. JSValues are marshalled into/out of wasm Anyrefs >+ as a black box, except null which becomes a Nullref value. Nullref is not expressible in the bytecode or in the js API. >+ Add Ref.null and Ref.is_null for Anyref values. Support for these functions with funcrefs is out of scope. >+ >+ * runtime/Options.h: >+ * wasm/WasmAirIRGenerator.cpp: >+ (JSC::Wasm::AirIRGenerator::tmpForType): >+ (JSC::Wasm::AirIRGenerator::AirIRGenerator): >+ (JSC::Wasm::AirIRGenerator::addConstant): >+ (JSC::Wasm::AirIRGenerator::addRefIsNull): >+ (JSC::Wasm::AirIRGenerator::addReturn): >+ * wasm/WasmB3IRGenerator.cpp: >+ (JSC::Wasm::B3IRGenerator::addRefIsNull): >+ * wasm/WasmCallingConvention.h: >+ (JSC::Wasm::CallingConventionAir::marshallArgument const): >+ (JSC::Wasm::CallingConventionAir::setupCall const): >+ * wasm/WasmFormat.h: >+ (JSC::Wasm::isValueType): >+ * wasm/WasmFunctionParser.h: >+ (JSC::Wasm::FunctionParser<Context>::FunctionParser): >+ (JSC::Wasm::FunctionParser<Context>::parseExpression): >+ (JSC::Wasm::FunctionParser<Context>::parseUnreachableExpression): >+ * wasm/WasmValidate.cpp: >+ (JSC::Wasm::Validate::addRefIsNull): >+ * wasm/generateWasmOpsHeader.py: >+ (bitSet): >+ * wasm/js/JSToWasm.cpp: >+ (JSC::Wasm::createJSToWasmWrapper): >+ * wasm/js/WasmToJS.cpp: >+ (JSC::Wasm::wasmToJS): >+ * wasm/js/WebAssemblyFunction.cpp: >+ (JSC::callWebAssemblyFunction): >+ (JSC::WebAssemblyFunction::jsCallEntrypointSlow): >+ * wasm/wasm.json: >+ > 2019-05-17 Keith Rollin <krollin@apple.com> > > Re-enable generate-xcfilelists >diff --git a/Source/JavaScriptCore/runtime/Options.h b/Source/JavaScriptCore/runtime/Options.h >index 6bc150021a3a5003e8bb14a482ce1930562fc5d8..f32fa6ea8e8b0e5ffd1d092953cd9f6d5ebc84b7 100644 >--- a/Source/JavaScriptCore/runtime/Options.h >+++ b/Source/JavaScriptCore/runtime/Options.h >@@ -502,6 +502,7 @@ constexpr bool enableWebAssemblyStreamingApi = false; > v(bool, useWebAssemblyStreamingApi, enableWebAssemblyStreamingApi, Normal, "Allow to run WebAssembly's Streaming API") \ > v(bool, useCallICsForWebAssemblyToJSCalls, true, Normal, "If true, we will use CallLinkInfo to inline cache Wasm to JS calls.") \ > v(bool, useEagerWebAssemblyModuleHashing, false, Normal, "Unnamed WebAssembly modules are identified in backtraces through their hash, if available.") \ >+ v(bool, useWebAssemblyReferences, true, Normal, "Allow types from the wasm references spec.") \ > v(bool, useBigInt, false, Normal, "If true, we will enable BigInt support.") \ > v(bool, useIntlNumberFormatToParts, enableIntlNumberFormatToParts, Normal, "If true, we will enable Intl.NumberFormat.prototype.formatToParts") \ > v(bool, useIntlPluralRules, enableIntlPluralRules, Normal, "If true, we will enable Intl.PluralRules.") \ >diff --git a/Source/JavaScriptCore/wasm/WasmAirIRGenerator.cpp b/Source/JavaScriptCore/wasm/WasmAirIRGenerator.cpp >index 475e9268849e82b50ec42653698a0482bd6fe921..f7960731806ab7c6939f753075b7062c43cf68cf 100644 >--- a/Source/JavaScriptCore/wasm/WasmAirIRGenerator.cpp >+++ b/Source/JavaScriptCore/wasm/WasmAirIRGenerator.cpp >@@ -41,6 +41,7 @@ > #include "B3ProcedureInlines.h" > #include "BinarySwitch.h" > #include "DisallowMacroScratchRegisterUsage.h" >+#include "JSCInlines.h" > #include "ScratchRegisterAllocator.h" > #include "VirtualRegister.h" > #include "WasmCallingConvention.h" >@@ -230,6 +231,8 @@ public: > ExpressionType addConstant(Type, uint64_t); > ExpressionType addConstant(BasicBlock*, Type, uint64_t); > >+ PartialResult WARN_UNUSED_RETURN addRefIsNull(ExpressionType& value, ExpressionType& result); >+ > // Locals > PartialResult WARN_UNUSED_RETURN getLocal(uint32_t index, ExpressionType& result); > PartialResult WARN_UNUSED_RETURN setLocal(uint32_t index, ExpressionType value); >@@ -360,6 +363,7 @@ private: > case Type::I32: > return g32(); > case Type::I64: >+ case Type::Anyref: > return g64(); > case Type::F32: > return f32(); >@@ -786,6 +790,7 @@ AirIRGenerator::AirIRGenerator(const ModuleInformation& info, B3::Procedure& pro > append(Move32, arg, m_locals[i]); > break; > case Type::I64: >+ case Type::Anyref: > append(Move, arg, m_locals[i]); > break; > case Type::F32: >@@ -902,6 +907,7 @@ auto AirIRGenerator::addConstant(BasicBlock* block, Type type, uint64_t value) - > switch (type) { > case Type::I32: > case Type::I64: >+ case Type::Anyref: > append(block, Move, Arg::bigImm(value), result); > break; > case Type::F32: >@@ -925,6 +931,18 @@ auto AirIRGenerator::addArguments(const Signature& signature) -> PartialResult > return { }; > } > >+auto AirIRGenerator::addRefIsNull(ExpressionType& value, ExpressionType& result) -> PartialResult >+{ >+ ASSERT(value.tmp()); >+ result = tmpForType(Type::I32); >+ auto tmp = g64(); >+ >+ append(Move, Arg::bigImm(JSValue::encode(jsNull())), tmp); >+ append(Compare64, Arg::relCond(MacroAssembler::Equal), value, tmp, result); >+ >+ return { }; >+} >+ > auto AirIRGenerator::getLocal(uint32_t index, ExpressionType& result) -> PartialResult > { > ASSERT(m_locals[index].tmp()); >@@ -1509,6 +1527,7 @@ auto AirIRGenerator::addReturn(const ControlData& data, const ExpressionList& re > append(Ret32, returnValueGPR); > break; > case Type::I64: >+ case Type::Anyref: > append(Move, returnValues[0], returnValueGPR); > append(Ret64, returnValueGPR); > break; >diff --git a/Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp b/Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp >index 15f464f02ce369f35e4ccb15e1be25e0db0e703c..bb2471f8da7603808b564203f0078ba3c6681f7c 100644 >--- a/Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp >+++ b/Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp >@@ -184,6 +184,8 @@ public: > PartialResult WARN_UNUSED_RETURN addLocal(Type, uint32_t); > ExpressionType addConstant(Type, uint64_t); > >+ PartialResult WARN_UNUSED_RETURN addRefIsNull(ExpressionType& value, ExpressionType& result); >+ > // Locals > PartialResult WARN_UNUSED_RETURN getLocal(uint32_t index, ExpressionType& result); > PartialResult WARN_UNUSED_RETURN setLocal(uint32_t index, ExpressionType value); >@@ -550,6 +552,12 @@ auto B3IRGenerator::addArguments(const Signature& signature) -> PartialResult > return { }; > } > >+auto B3IRGenerator::addRefIsNull(ExpressionType& value, ExpressionType& result) -> PartialResult >+{ >+ result = m_currentBlock->appendNew<Value>(m_proc, B3::Equal, origin(), value, m_currentBlock->appendNew<Const64Value>(m_proc, origin(), JSValue::encode(jsNull()))); >+ return { }; >+} >+ > auto B3IRGenerator::getLocal(uint32_t index, ExpressionType& result) -> PartialResult > { > ASSERT(m_locals[index]); >diff --git a/Source/JavaScriptCore/wasm/WasmCallingConvention.h b/Source/JavaScriptCore/wasm/WasmCallingConvention.h >index 31866c20dcbfd09faddcf9872893798e599e0273..10eb8cd4e7336e0ef24dc9be504b7507ce83c752 100644 >--- a/Source/JavaScriptCore/wasm/WasmCallingConvention.h >+++ b/Source/JavaScriptCore/wasm/WasmCallingConvention.h >@@ -235,6 +235,7 @@ private: > switch (type) { > case Type::I32: > case Type::I64: >+ case Type::Anyref: > marshallArgumentImpl(m_gprArgs, gpArgumentCount, stackOffset, regFunc, stackFunc); > break; > case Type::F32: >@@ -299,6 +300,7 @@ public: > break; > case Type::I32: > case Type::I64: >+ case Type::Anyref: > patchpoint->resultConstraint = B3::ValueRep::reg(GPRInfo::returnValueGPR); > break; > default: >diff --git a/Source/JavaScriptCore/wasm/WasmFormat.h b/Source/JavaScriptCore/wasm/WasmFormat.h >index fc69ee5c58a4fac31ac97b4e16ac604f2a14ae8d..b7622644163bf78f5ed380519d43836b51483e15 100644 >--- a/Source/JavaScriptCore/wasm/WasmFormat.h >+++ b/Source/JavaScriptCore/wasm/WasmFormat.h >@@ -62,6 +62,8 @@ inline bool isValueType(Type type) > case F32: > case F64: > return true; >+ case Anyref: >+ return Options::useWebAssemblyReferences(); > default: > break; > } >diff --git a/Source/JavaScriptCore/wasm/WasmFunctionParser.h b/Source/JavaScriptCore/wasm/WasmFunctionParser.h >index 2e028e36662653ecec39e02edb8a20bfd44cda91..175056b58e721f7442d48c73966de3301195807b 100644 >--- a/Source/JavaScriptCore/wasm/WasmFunctionParser.h >+++ b/Source/JavaScriptCore/wasm/WasmFunctionParser.h >@@ -105,7 +105,7 @@ FunctionParser<Context>::FunctionParser(Context& context, const uint8_t* functio > , m_info(info) > { > if (verbose) >- dataLogLn("Parsing function starting at: ", (uintptr_t)functionStart, " of length: ", functionLength); >+ dataLogLn("Parsing function starting at: ", (uintptr_t)functionStart, " of length: ", functionLength, " with signature: ", signature); > m_context.setParser(this); > } > >@@ -281,6 +281,21 @@ auto FunctionParser<Context>::parseExpression() -> PartialResult > return { }; > } > >+ case RefNull: { >+ WASM_PARSER_FAIL_IF(!Options::useWebAssemblyReferences(), "references are not enabled"); >+ m_expressionStack.append(m_context.addConstant(Anyref, JSValue::encode(jsNull()))); >+ return { }; >+ } >+ >+ case RefIsNull: { >+ WASM_PARSER_FAIL_IF(!Options::useWebAssemblyReferences(), "references are not enabled"); >+ ExpressionType result, value; >+ WASM_TRY_POP_EXPRESSION_STACK_INTO(value, "ref.is_null"); >+ WASM_TRY_ADD_TO_CONTEXT(addRefIsNull(value, result)); >+ m_expressionStack.append(result); >+ return { }; >+ } >+ > case GetLocal: { > uint32_t index; > ExpressionType result; >@@ -639,6 +654,16 @@ auto FunctionParser<Context>::parseUnreachableExpression() -> PartialResult > return { }; > } > >+ case RefNull: { >+ WASM_PARSER_FAIL_IF(!Options::useWebAssemblyReferences(), "references are not enabled"); >+ return { }; >+ } >+ >+ case RefIsNull: { >+ WASM_PARSER_FAIL_IF(!Options::useWebAssemblyReferences(), "references are not enabled"); >+ return { }; >+ } >+ > case GrowMemory: > case CurrentMemory: { > uint8_t reserved; >diff --git a/Source/JavaScriptCore/wasm/WasmValidate.cpp b/Source/JavaScriptCore/wasm/WasmValidate.cpp >index bcd477bc20ef7c8aa73beb1a86a3aab91d0bf08a..fd54162008409da36f9694d38912c8efc91428b5 100644 >--- a/Source/JavaScriptCore/wasm/WasmValidate.cpp >+++ b/Source/JavaScriptCore/wasm/WasmValidate.cpp >@@ -100,6 +100,8 @@ public: > Result WARN_UNUSED_RETURN addLocal(Type, uint32_t); > ExpressionType addConstant(Type type, uint64_t) { return type; } > >+ Result WARN_UNUSED_RETURN addRefIsNull(ExpressionType& value, ExpressionType& result); >+ > // Locals > Result WARN_UNUSED_RETURN getLocal(uint32_t index, ExpressionType& result); > Result WARN_UNUSED_RETURN setLocal(uint32_t index, ExpressionType value); >@@ -169,6 +171,14 @@ auto Validate::addArguments(const Signature& signature) -> Result > return { }; > } > >+auto Validate::addRefIsNull(ExpressionType& value, ExpressionType& result) -> Result >+{ >+ result = Type::I32; >+ WASM_VALIDATOR_FAIL_IF(Type::Anyref != value, "ref.is_null to type ", value, " expected ", Type::Anyref); >+ >+ return { }; >+} >+ > auto Validate::addLocal(Type type, uint32_t count) -> Result > { > size_t size = m_locals.size() + count; >diff --git a/Source/JavaScriptCore/wasm/generateWasmOpsHeader.py b/Source/JavaScriptCore/wasm/generateWasmOpsHeader.py >index 0b8d7b0264480af32d9b81c0e2222db7e07b8715..4e9a6656631979d2c9378b637e1b88f0692b751c 100755 >--- a/Source/JavaScriptCore/wasm/generateWasmOpsHeader.py >+++ b/Source/JavaScriptCore/wasm/generateWasmOpsHeader.py >@@ -95,7 +95,7 @@ def ceilDiv(a, b): > > def bitSet(): > v = "" >- for i in range(ceilDiv(maxOpValue, 8)): >+ for i in range(ceilDiv(maxOpValue + 1, 8)): > entry = 0 > for j in range(8): > if i * 8 + j in opValueSet: >diff --git a/Source/JavaScriptCore/wasm/js/JSToWasm.cpp b/Source/JavaScriptCore/wasm/js/JSToWasm.cpp >index 774bce0d73863270d29cd787de5535e67e0b544a..657da57aeb7ce3daeaf3c25747818b620dce1492 100644 >--- a/Source/JavaScriptCore/wasm/js/JSToWasm.cpp >+++ b/Source/JavaScriptCore/wasm/js/JSToWasm.cpp >@@ -82,6 +82,7 @@ std::unique_ptr<InternalFunction> createJSToWasmWrapper(CompilationContext& comp > argumentsIncludeI64 = true; > FALLTHROUGH; > case Wasm::I32: >+ case Wasm::Anyref: > if (numGPRs >= wasmCallingConvention().m_gprArgs.size()) > totalFrameSize += sizeof(void*); > ++numGPRs; >@@ -164,6 +165,7 @@ std::unique_ptr<InternalFunction> createJSToWasmWrapper(CompilationContext& comp > switch (signature.argument(i)) { > case Wasm::I32: > case Wasm::I64: >+ case Wasm::Anyref: > if (numGPRs >= wasmCallingConvention().m_gprArgs.size()) { > if (signature.argument(i) == Wasm::I32) { > jit.load32(CCallHelpers::Address(GPRInfo::callFrameRegister, jsOffset), scratchReg); >@@ -247,6 +249,9 @@ std::unique_ptr<InternalFunction> createJSToWasmWrapper(CompilationContext& comp > case Wasm::Void: > jit.moveTrustedValue(jsUndefined(), JSValueRegs { GPRInfo::returnValueGPR }); > break; >+ case Wasm::Anyref: >+ // FIXME: We need to box wasm Funcrefs once they are supported here. >+ break; > case Wasm::I32: > jit.zeroExtend32ToPtr(GPRInfo::returnValueGPR, GPRInfo::returnValueGPR); > jit.boxInt32(GPRInfo::returnValueGPR, JSValueRegs { GPRInfo::returnValueGPR }, DoNotHaveTagRegisters); >diff --git a/Source/JavaScriptCore/wasm/js/WasmToJS.cpp b/Source/JavaScriptCore/wasm/js/WasmToJS.cpp >index 572b0307d032c40b592353e6b6d423bd6fcdbb3c..5bff9cc6d0441f0efcf21b9dcf988107fb5688bb 100644 >--- a/Source/JavaScriptCore/wasm/js/WasmToJS.cpp >+++ b/Source/JavaScriptCore/wasm/js/WasmToJS.cpp >@@ -165,6 +165,7 @@ Expected<MacroAssemblerCodeRef<WasmEntryPtrTag>, BindingFailure> wasmToJS(VM* vm > case Anyfunc: > case I64: > RELEASE_ASSERT_NOT_REACHED(); >+ case Anyref: > case I32: { > GPRReg gprReg; > if (marshalledGPRs < wasmCC.m_gprArgs.size()) >@@ -175,7 +176,8 @@ Expected<MacroAssemblerCodeRef<WasmEntryPtrTag>, BindingFailure> wasmToJS(VM* vm > jit.load64(JIT::Address(GPRInfo::callFrameRegister, frOffset), gprReg); > frOffset += sizeof(Register); > } >- jit.zeroExtend32ToPtr(gprReg, gprReg); >+ if (argType == I32) >+ jit.zeroExtend32ToPtr(gprReg, gprReg); > jit.store64(gprReg, buffer + bufferOffset); > ++marshalledGPRs; > break; >@@ -241,6 +243,10 @@ Expected<MacroAssemblerCodeRef<WasmEntryPtrTag>, BindingFailure> wasmToJS(VM* vm > case I32: > arg = jsNumber(static_cast<int32_t>(buffer[argNum])); > break; >+ case Anyref: >+ // FIXME: We need to box wasm Funcrefs once they are supported here. >+ arg = JSValue::decode(buffer[argNum]); >+ break; > case F32: > case F64: > arg = jsNumber(purifyNaN(bitwise_cast<double>(buffer[argNum]))); >@@ -272,6 +278,10 @@ Expected<MacroAssemblerCodeRef<WasmEntryPtrTag>, BindingFailure> wasmToJS(VM* vm > realResult = static_cast<uint64_t>(static_cast<uint32_t>(result.toInt32(exec))); > break; > } >+ case Anyref: { >+ realResult = JSValue::encode(result); >+ break; >+ } > case F64: > case F32: { > realResult = bitwise_cast<uint64_t>(result.toNumber(exec)); >@@ -364,6 +374,7 @@ Expected<MacroAssemblerCodeRef<WasmEntryPtrTag>, BindingFailure> wasmToJS(VM* vm > case Anyfunc: > case I64: > RELEASE_ASSERT_NOT_REACHED(); // Handled above. >+ case Anyref: > case I32: { > GPRReg gprReg; > if (marshalledGPRs < wasmCC.m_gprArgs.size()) >@@ -375,8 +386,11 @@ Expected<MacroAssemblerCodeRef<WasmEntryPtrTag>, BindingFailure> wasmToJS(VM* vm > frOffset += sizeof(Register); > } > ++marshalledGPRs; >- jit.zeroExtend32ToPtr(gprReg, gprReg); // Clear non-int32 and non-tag bits. >- jit.boxInt32(gprReg, JSValueRegs(gprReg), DoNotHaveTagRegisters); >+ if (argType == I32) { >+ jit.zeroExtend32ToPtr(gprReg, gprReg); // Clear non-int32 and non-tag bits. >+ jit.boxInt32(gprReg, JSValueRegs(gprReg), DoNotHaveTagRegisters); >+ } >+ // FIXME: We need to box wasm Funcrefs once they are supported here. > jit.store64(gprReg, calleeFrame.withOffset(calleeFrameOffset)); > calleeFrameOffset += sizeof(Register); > break; >@@ -430,6 +444,7 @@ Expected<MacroAssemblerCodeRef<WasmEntryPtrTag>, BindingFailure> wasmToJS(VM* vm > case Anyfunc: > case I64: > RELEASE_ASSERT_NOT_REACHED(); // Handled above. >+ case Anyref: > case I32: > // Skipped: handled above. > if (marshalledGPRs >= wasmCC.m_gprArgs.size()) >@@ -538,6 +553,8 @@ Expected<MacroAssemblerCodeRef<WasmEntryPtrTag>, BindingFailure> wasmToJS(VM* vm > done.link(&jit); > break; > } >+ case Anyref: >+ break; > case F32: { > CCallHelpers::JumpList done; > >diff --git a/Source/JavaScriptCore/wasm/js/WebAssemblyFunction.cpp b/Source/JavaScriptCore/wasm/js/WebAssemblyFunction.cpp >index 6dcec80dd84e14c02acb587f7c099d0228e16379..2ff0e78e582f6561a28f3c59537821c03980b890 100644 >--- a/Source/JavaScriptCore/wasm/js/WebAssemblyFunction.cpp >+++ b/Source/JavaScriptCore/wasm/js/WebAssemblyFunction.cpp >@@ -84,6 +84,8 @@ static EncodedJSValue JSC_HOST_CALL callWebAssemblyFunction(ExecState* exec) > case Wasm::I32: > arg = JSValue::decode(arg.toInt32(exec)); > break; >+ case Wasm::Anyref: >+ break; > case Wasm::I64: > arg = JSValue(); > break; >@@ -225,6 +227,7 @@ MacroAssemblerCodePtr<JSEntryPtrTag> WebAssemblyFunction::jsCallEntrypointSlow() > case Wasm::I64: > argumentsIncludeI64 = true; > break; >+ case Wasm::Anyref: > case Wasm::I32: > if (numGPRs >= Wasm::wasmCallingConvention().m_gprArgs.size()) > totalFrameSize += sizeof(CPURegister); >@@ -300,6 +303,18 @@ MacroAssemblerCodePtr<JSEntryPtrTag> WebAssemblyFunction::jsCallEntrypointSlow() > ++numGPRs; > } > break; >+ case Wasm::Anyref: { >+ jit.load64(CCallHelpers::Address(GPRInfo::callFrameRegister, jsOffset), scratchGPR); >+ >+ if (numGPRs >= Wasm::wasmCallingConvention().m_gprArgs.size()) { >+ jit.store64(scratchGPR, calleeFrame.withOffset(wasmOffset)); >+ wasmOffset += sizeof(CPURegister); >+ } else { >+ jit.move(scratchGPR, Wasm::wasmCallingConvention().m_gprArgs[numGPRs].gpr()); >+ ++numGPRs; >+ } >+ break; >+ } > case Wasm::F32: > case Wasm::F64: > if (numFPRs >= Wasm::wasmCallingConvention().m_fprArgs.size()) { >@@ -451,6 +466,10 @@ MacroAssemblerCodePtr<JSEntryPtrTag> WebAssemblyFunction::jsCallEntrypointSlow() > isNaN.link(&jit); > break; > } >+ case Wasm::Anyref: { >+ // FIXME: We need to box wasm Funcrefs once they are supported here. >+ break; >+ } > case Wasm::I64: > case Wasm::Func: > case Wasm::Anyfunc: >diff --git a/Source/JavaScriptCore/wasm/wasm.json b/Source/JavaScriptCore/wasm/wasm.json >index 31d103f9c8a2022a7144032686e760c40caf3a45..e61aa74c338660e4b5f16a354d52d151060092b0 100644 >--- a/Source/JavaScriptCore/wasm/wasm.json >+++ b/Source/JavaScriptCore/wasm/wasm.json >@@ -12,11 +12,12 @@ > "f32": { "type": "varint7", "value": -3, "b3type": "B3::Float" }, > "f64": { "type": "varint7", "value": -4, "b3type": "B3::Double" }, > "anyfunc": { "type": "varint7", "value": -16, "b3type": "B3::Void" }, >+ "anyref": { "type": "varint7", "value": -17, "b3type": "B3::Int64" }, > "func": { "type": "varint7", "value": -32, "b3type": "B3::Void" }, > "void": { "type": "varint7", "value": -64, "b3type": "B3::Void" } > }, >- "value_type": ["i32", "i64", "f32", "f64"], >- "block_type": ["i32", "i64", "f32", "f64", "void"], >+ "value_type": ["i32", "i64", "f32", "f64", "anyref"], >+ "block_type": ["i32", "i64", "f32", "f64", "void", "anyref"], > "elem_type": ["anyfunc"], > "external_kind": { > "Function": { "type": "uint8", "value": 0 }, >@@ -58,6 +59,8 @@ > "i64.const": { "category": "special", "value": 66, "return": ["i64"], "parameter": [], "immediate": [{"name": "value", "type": "varint64"}], "description": "a constant value interpreted as i64" }, > "f64.const": { "category": "special", "value": 68, "return": ["f64"], "parameter": [], "immediate": [{"name": "value", "type": "double"}], "description": "a constant value interpreted as f64" }, > "f32.const": { "category": "special", "value": 67, "return": ["f32"], "parameter": [], "immediate": [{"name": "value", "type": "float"}], "description": "a constant value interpreted as f32" }, >+ "ref.null": { "category": "special", "value": 208, "return": ["anyref"], "parameter": [], "immediate": [], "description": "a constant null reference" }, >+ "ref.is_null": { "category": "special", "value": 209, "return": ["i32"], "parameter": ["anyref"], "immediate": [], "description": "determine if a reference is null" }, > "get_local": { "category": "special", "value": 32, "return": ["any"], "parameter": [], "immediate": [{"name": "local_index", "type": "varuint32"}], "description": "read a local variable or parameter" }, > "set_local": { "category": "special", "value": 33, "return": [], "parameter": ["any"], "immediate": [{"name": "local_index", "type": "varuint32"}], "description": "write a local variable or parameter" }, > "tee_local": { "category": "special", "value": 34, "return": ["any"], "parameter": ["any"], "immediate": [{"name": "local_index", "type": "varuint32"}], "description": "write a local variable or parameter and return the same value" }, >diff --git a/Tools/ChangeLog b/Tools/ChangeLog >index 8f32ef9a20a1a6e6225a1222254193c42986cfa4..f7afbe7c83fd16907b7f6a22d7751b1763295c8e 100644 >--- a/Tools/ChangeLog >+++ b/Tools/ChangeLog >@@ -1,3 +1,14 @@ >+2019-05-17 Justin Michaud <justin_michaud@apple.com> >+ >+ [WASM-References] Add support for Anyref in parameters and return types, Ref.null and Ref.is_null for Anyref values. >+ https://bugs.webkit.org/show_bug.cgi?id=197969 >+ >+ Run wasm tests additionally with wasmBBQUsesAir=0. >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ * Scripts/run-jsc-stress-tests: >+ > 2019-05-17 Alex Christensen <achristensen@webkit.org> > > Add SPI to set a list of hosts to which to send custom header fields cross-origin >diff --git a/Tools/Scripts/run-jsc-stress-tests b/Tools/Scripts/run-jsc-stress-tests >index a7be368588a5df26ddefe2a555412659e9fbeeec..2703c4053a23aa3dcce1ab03172d8c6d2a211861 100755 >--- a/Tools/Scripts/run-jsc-stress-tests >+++ b/Tools/Scripts/run-jsc-stress-tests >@@ -1080,6 +1080,7 @@ def runWebAssembly > run("wasm-no-call-ic", "-m", "--useCallICsForWebAssemblyToJSCalls=false", *FTL_OPTIONS) > run("wasm-no-tls-context", "-m", "--useFastTLSForWasmContext=false", *FTL_OPTIONS) > run("wasm-slow-memory", "-m", "--useWebAssemblyFastMemory=false", *FTL_OPTIONS) >+ run("wasm-no-air", "-m", "--wasmBBQUsesAir=false", *FTL_OPTIONS) > end > end > >@@ -1096,6 +1097,7 @@ def runWebAssemblySuite > run("wasm-no-call-ic", "-m", "--useCallICsForWebAssemblyToJSCalls=false", *FTL_OPTIONS) > run("wasm-no-tls-context", "-m", "--useFastTLSForWasmContext=false", *FTL_OPTIONS) > run("wasm-slow-memory", "-m", "--useWebAssemblyFastMemory=false", *FTL_OPTIONS) >+ run("wasm-no-air", "-m", "--wasmBBQUsesAir=false", *FTL_OPTIONS) > end > end > >@@ -1114,6 +1116,7 @@ def runWebAssemblyEmscripten(mode) > run("wasm-eager-jettison", "--forceCodeBlockToJettisonDueToOldAge=true", *FTL_OPTIONS) > run("wasm-no-call-ic", "--useCallICsForWebAssemblyToJSCalls=false", *FTL_OPTIONS) > run("wasm-no-tls-context", "--useFastTLSForWasmContext=false", *FTL_OPTIONS) >+ run("wasm-no-air", "--wasmBBQUsesAir=false", *FTL_OPTIONS) > end > end > >@@ -1138,6 +1141,7 @@ def runWebAssemblySpecTest(mode) > runWithOutputHandler("wasm-eager-jettison", noisyOutputHandler, "../spec-harness.js", "--forceCodeBlockToJettisonDueToOldAge=true", *FTL_OPTIONS) > runWithOutputHandler("wasm-no-call-ic", noisyOutputHandler, "../spec-harness.js", "--useCallICsForWebAssemblyToJSCalls=false", *FTL_OPTIONS) > runWithOutputHandler("wasm-no-tls-context", noisyOutputHandler, "../spec-harness.js", "--useFastTLSForWasmContext=false", *FTL_OPTIONS) >+ runWithOutputHandler("wasm-no-air", noisyOutputHandler, "../spec-harness.js", "--wasmBBQUsesAir=false", *FTL_OPTIONS) > end > end > >diff --git a/JSTests/ChangeLog b/JSTests/ChangeLog >index e68c82672e523e8e249a022e8bf601b122c3fa31..1afcfe7a75cd343af99c51014094dafd5cca38e2 100644 >--- a/JSTests/ChangeLog >+++ b/JSTests/ChangeLog >@@ -1,3 +1,26 @@ >+2019-05-17 Justin Michaud <justin_michaud@apple.com> >+ >+ [WASM-References] Add support for Anyref in parameters and return types, Ref.null and Ref.is_null for Anyref values. >+ https://bugs.webkit.org/show_bug.cgi?id=197969 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ Support the anyref type in Builder.js, plus add some extra error logging. >+ Add new folder for wasm references tests. >+ >+ * wasm.yaml: >+ * wasm/Builder.js: >+ (const._isValidValue): >+ * wasm/references/anyref_modules.js: Added. >+ (Call.3.RefIsNull.End.End.WebAssembly.js.ident): >+ (Call.3.RefIsNull.End.End.WebAssembly.js.make_null): >+ (Call.3.RefIsNull.End.End.WebAssembly): >+ (undefined): >+ * wasm/references/is_null.js: Added. >+ * wasm/references/is_null_error.js: Added. >+ * wasm/spec-harness/index.js: >+ * wasm/wasm.json: >+ > 2019-05-16 Ross Kirsling <ross.kirsling@sony.com> > > [JSC] Invalid AssignmentTargetType should be an early error. >diff --git a/JSTests/wasm.yaml b/JSTests/wasm.yaml >index 3c1a5fcf1fd8ba194f786eea243e6f5ca41bf23f..45dbd1acb7093df26704129c6b42f4cac39d63e5 100644 >--- a/JSTests/wasm.yaml >+++ b/JSTests/wasm.yaml >@@ -29,6 +29,8 @@ > cmd: runNoJIT unless parseRunCommands > - path: wasm/function-tests > cmd: runWebAssemblySuite unless parseRunCommands >+- path: wasm/references >+ cmd: runWebAssemblySuite unless parseRunCommands > - path: wasm/fuzz > cmd: runWebAssemblySuite unless parseRunCommands > - path: wasm/stress >diff --git a/JSTests/wasm/Builder.js b/JSTests/wasm/Builder.js >index e94f0a31a416f8631793551dc11603de6dc4d13c..f22de1b81c8409da044bb05112a45cd29fd72896 100644 >--- a/JSTests/wasm/Builder.js >+++ b/JSTests/wasm/Builder.js >@@ -33,6 +33,7 @@ const _isValidValue = (value, type) => { > switch (type) { > // We allow both signed and unsigned numbers. > case "i32": return Math.round(value) === value && LLB.varint32Min <= value && value <= LLB.varuint32Max; >+ case "anyref": return true; > case "i64": return true; // FIXME https://bugs.webkit.org/show_bug.cgi?id=163420 64-bit values > case "f32": return typeof(value) === "number" && isFinite(value); > case "f64": return typeof(value) === "number" && isFinite(value); >diff --git a/JSTests/wasm/references/anyref_modules.js b/JSTests/wasm/references/anyref_modules.js >new file mode 100644 >index 0000000000000000000000000000000000000000..ed10096d7b5ce6a1c6ea98653c58fd2504223fc3 >--- /dev/null >+++ b/JSTests/wasm/references/anyref_modules.js >@@ -0,0 +1,132 @@ >+import * as assert from '../assert.js'; >+import Builder from '../Builder.js'; >+ >+const $1 = new WebAssembly.Instance(new WebAssembly.Module((new Builder()) >+ .Type().End() >+ .Function().End() >+ .Export() >+ .Function("h") >+ .Function("i") >+ .Function("j") >+ .Function("k") >+ .End() >+ .Code() >+ .Function("h", { params: ["anyref"], ret: "anyref" }) >+ .GetLocal(0) >+ .End() >+ >+ .Function("i", { params: [], ret: "anyref" }) >+ .RefNull() >+ .Call(0) >+ .End() >+ >+ .Function("j", { params: ["anyref"], ret: "i32" }) >+ .GetLocal(0) >+ .RefIsNull() >+ .End() >+ >+ .Function("k", { params: [], ret: "i32" }) >+ .RefNull() >+ .RefIsNull() >+ .End() >+ .End().WebAssembly().get())); >+ >+const $2 = new WebAssembly.Instance(new WebAssembly.Module((new Builder()) >+ .Type().End() >+ .Import() >+ .Function("m1", "h", { params: ["anyref"], ret: "anyref" }) >+ .Function("m1", "j", { params: ["anyref"], ret: "i32" }) >+ .Function("js", "ident", { params: ["anyref"], ret: "anyref" }) >+ .Function("js", "make_null", { params: [], ret: "anyref" }) >+ .End() >+ .Function().End() >+ .Export() >+ .Function("call_h") >+ .Function("call_j") >+ .Function("call_h_null") >+ .Function("call_j_null") >+ .Function("call_ident") >+ .Function("call_ident_null") >+ .Function("is_makenull_null") >+ .End() >+ .Code() >+ .Function("call_h", { params: ["anyref"], ret: "anyref" }) >+ .GetLocal(0) >+ .Call(0) >+ .End() >+ >+ .Function("call_j", { params: ["anyref"], ret: "i32" }) >+ .GetLocal(0) >+ .Call(1) >+ .End() >+ >+ .Function("call_h_null", { params: [], ret: "anyref" }) >+ .RefNull() >+ .Call(0) >+ .End() >+ >+ .Function("call_j_null", { params: [], ret: "i32" }) >+ .RefNull() >+ .Call(1) >+ .End() >+ >+ .Function("call_ident", { params: ["anyref"], ret: "anyref" }) >+ .I32Const(1) >+ .If("anyref") >+ .Block("anyref", (b) => >+ b.GetLocal(0) >+ ) >+ .Else() >+ .Block("anyref", (b) => >+ b.GetLocal(0) >+ ) >+ .End() >+ .Call(2) >+ .End() >+ >+ .Function("call_ident_null", { params: [], ret: "anyref" }) >+ .RefNull() >+ .Call(2) >+ .End() >+ >+ .Function("is_makenull_null", { params: [], ret: "i32" }) >+ .Call(3) >+ .RefIsNull() >+ .End() >+ .End().WebAssembly().get()), { m1: $1.exports, js: { >+ ident: function(x) { return x; }, >+ make_null: function() { return null; }, >+ } }); >+ >+assert.eq($2.exports.call_h(null), null) >+ >+const obj = { test: "hi" } >+assert.eq($2.exports.call_h(obj), obj) >+assert.eq($2.exports.call_h(5), 5) >+assert.eq($2.exports.call_h("hi"), "hi") >+assert.eq($2.exports.call_h(undefined), undefined) >+ >+assert.eq($2.exports.call_j(obj), 0) >+assert.eq($2.exports.call_j(5), 0) >+assert.eq($2.exports.call_j("hi"), 0) >+assert.eq($2.exports.call_j(null), 1) >+assert.eq($2.exports.call_j(undefined), 0) >+ >+assert.eq($2.exports.call_h_null(), null) >+assert.eq($2.exports.call_j_null(), 1) >+ >+assert.eq($2.exports.call_ident(null), null) >+assert.eq($2.exports.call_ident(obj), obj) >+assert.eq($2.exports.call_ident(5), 5) >+assert.eq($2.exports.call_ident("hi"), "hi") >+assert.eq($2.exports.call_ident(undefined), undefined) >+ >+for (let i=0; i<1000; ++i) { >+ // Trigger the ic path >+ assert.eq($2.exports.call_ident(null), null) >+ assert.eq($2.exports.call_ident(7), 7) >+ assert.eq($2.exports.call_ident("bye"), "bye") >+} >+ >+assert.eq($2.exports.call_ident_null(), null) >+assert.eq($2.exports.is_makenull_null(), 1) >diff --git a/JSTests/wasm/references/is_null.js b/JSTests/wasm/references/is_null.js >new file mode 100644 >index 0000000000000000000000000000000000000000..52bcbf36a78259e1ba8fe4b50b18ce88c3024dfb >--- /dev/null >+++ b/JSTests/wasm/references/is_null.js >@@ -0,0 +1,60 @@ >+import * as assert from '../assert.js'; >+import Builder from '../Builder.js'; >+ >+const builder = (new Builder()) >+ .Type().End() >+ .Function().End() >+ .Export() >+ .Function("h") >+ .Function("i") >+ .Function("j") >+ .Function("k") >+ .End() >+ .Code() >+ .Function("h", { params: ["anyref"], ret: "anyref" }) >+ .GetLocal(0) >+ .End() >+ >+ .Function("i", { params: [], ret: "anyref" }) >+ .RefNull() >+ .Call(0) >+ .End() >+ >+ .Function("j", { params: ["anyref"], ret: "i32" }) >+ .GetLocal(0) >+ .RefIsNull() >+ .End() >+ >+ .Function("k", { params: [], ret: "i32" }) >+ .RefNull() >+ .RefIsNull() >+ .End() >+ .End(); >+ >+const bin = builder.WebAssembly().get(); >+const module = new WebAssembly.Module(bin); >+const instance = new WebAssembly.Instance(module); >+assert.eq(instance.exports.h(null), null) >+ >+const obj = { test: "hi" } >+assert.eq(instance.exports.h(obj), obj) >+assert.eq(instance.exports.h(5), 5) >+assert.eq(instance.exports.h("hi"), "hi") >+assert.eq(instance.exports.h(undefined), undefined) >+ >+assert.eq(instance.exports.i(), null) >+ >+assert.eq(instance.exports.j(obj), 0) >+assert.eq(instance.exports.j(5), 0) >+assert.eq(instance.exports.j("hi"), 0) >+assert.eq(instance.exports.j(null), 1) >+assert.eq(instance.exports.j(undefined), 0) >+ >+assert.eq(instance.exports.k(), 1) >+ >+assert.eq(obj.test, "hi") >+const obj2 = instance.exports.h(obj) >+obj2.test = "bye" >+assert.eq(obj.test, "bye") >+ >+for (let i=0; i<1000; ++i) assert.eq(instance.exports.h(null), null) >diff --git a/JSTests/wasm/references/is_null_error.js b/JSTests/wasm/references/is_null_error.js >new file mode 100644 >index 0000000000000000000000000000000000000000..915b36ad99614f0f0f5b87c94235724d16955c8b >--- /dev/null >+++ b/JSTests/wasm/references/is_null_error.js >@@ -0,0 +1,22 @@ >+import * as assert from '../assert.js'; >+import Builder from '../Builder.js'; >+ >+{ >+ const builder = (new Builder()) >+ .Type().End() >+ .Function().End() >+ .Export() >+ .Function("j") >+ .End() >+ .Code() >+ .Function("j", { params: [], ret: "i32" }) >+ .I32Const(0) >+ .RefIsNull() >+ .End() >+ .End(); >+ >+ const bin = builder.WebAssembly(); >+ bin.trim(); >+ >+ assert.throws(() => new WebAssembly.Module(bin.get()), WebAssembly.CompileError, "WebAssembly.Module doesn't validate: ref.is_null to type I32 expected Anyref, in function at index 0 (evaluating 'new WebAssembly.Module(bin.get())')"); >+} >diff --git a/JSTests/wasm/spec-harness/index.js b/JSTests/wasm/spec-harness/index.js >index bc298d200a07b1d569708adf80e04b3ab96a14cc..eb00c6d878fc90d511f606b4b434845686735ae4 100644 >--- a/JSTests/wasm/spec-harness/index.js >+++ b/JSTests/wasm/spec-harness/index.js >@@ -190,6 +190,7 @@ function instance(bytes, imports = registry, valid = true) { > if (valid) { > uniqueTest(() => { > let instantiated = err === null; >+ if (!instantiated) print(err); > assert_true(instantiated, err); > }, "module successfully instantiated"); > } >diff --git a/JSTests/wasm/wasm.json b/JSTests/wasm/wasm.json >index 31d103f9c8a2022a7144032686e760c40caf3a45..e61aa74c338660e4b5f16a354d52d151060092b0 100644 >--- a/JSTests/wasm/wasm.json >+++ b/JSTests/wasm/wasm.json >@@ -12,11 +12,12 @@ > "f32": { "type": "varint7", "value": -3, "b3type": "B3::Float" }, > "f64": { "type": "varint7", "value": -4, "b3type": "B3::Double" }, > "anyfunc": { "type": "varint7", "value": -16, "b3type": "B3::Void" }, >+ "anyref": { "type": "varint7", "value": -17, "b3type": "B3::Int64" }, > "func": { "type": "varint7", "value": -32, "b3type": "B3::Void" }, > "void": { "type": "varint7", "value": -64, "b3type": "B3::Void" } > }, >- "value_type": ["i32", "i64", "f32", "f64"], >- "block_type": ["i32", "i64", "f32", "f64", "void"], >+ "value_type": ["i32", "i64", "f32", "f64", "anyref"], >+ "block_type": ["i32", "i64", "f32", "f64", "void", "anyref"], > "elem_type": ["anyfunc"], > "external_kind": { > "Function": { "type": "uint8", "value": 0 }, >@@ -58,6 +59,8 @@ > "i64.const": { "category": "special", "value": 66, "return": ["i64"], "parameter": [], "immediate": [{"name": "value", "type": "varint64"}], "description": "a constant value interpreted as i64" }, > "f64.const": { "category": "special", "value": 68, "return": ["f64"], "parameter": [], "immediate": [{"name": "value", "type": "double"}], "description": "a constant value interpreted as f64" }, > "f32.const": { "category": "special", "value": 67, "return": ["f32"], "parameter": [], "immediate": [{"name": "value", "type": "float"}], "description": "a constant value interpreted as f32" }, >+ "ref.null": { "category": "special", "value": 208, "return": ["anyref"], "parameter": [], "immediate": [], "description": "a constant null reference" }, >+ "ref.is_null": { "category": "special", "value": 209, "return": ["i32"], "parameter": ["anyref"], "immediate": [], "description": "determine if a reference is null" }, > "get_local": { "category": "special", "value": 32, "return": ["any"], "parameter": [], "immediate": [{"name": "local_index", "type": "varuint32"}], "description": "read a local variable or parameter" }, > "set_local": { "category": "special", "value": 33, "return": [], "parameter": ["any"], "immediate": [{"name": "local_index", "type": "varuint32"}], "description": "write a local variable or parameter" }, > "tee_local": { "category": "special", "value": 34, "return": ["any"], "parameter": ["any"], "immediate": [{"name": "local_index", "type": "varuint32"}], "description": "write a local variable or parameter and return the same value" },
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 197969
:
370091
|
370157
| 370159