Changeset 246504 in webkit
- Timestamp:
- Jun 17, 2019 11:44:18 AM (5 years ago)
- Location:
- trunk
- Files:
-
- 1 added
- 28 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JSTests/ChangeLog
r246499 r246504 1 2019-06-17 Justin Michaud <justin_michaud@apple.com> 2 3 [WASM-References] Add support for Funcref in parameters and return types 4 https://bugs.webkit.org/show_bug.cgi?id=198157 5 6 Reviewed by Yusuke Suzuki. 7 8 * wasm/Builder.js: 9 (export.default.Builder.prototype._registerSectionBuilders.const.section.in.WASM.description.section.switch.section.case.string_appeared_here.this.section): 10 * wasm/references/anyref_globals.js: 11 * wasm/references/func_ref.js: Added. 12 (fullGC.gc.makeExportedFunction): 13 (makeExportedIdent): 14 (makeAnyfuncIdent): 15 (fun): 16 (assert.eq.instance.exports.fix.fun): 17 (assert.eq.instance.exports.fix): 18 (string_appeared_here.End.End.Function.End.Code.End.WebAssembly.imp.ref): 19 (string_appeared_here.End.End.Function.End.Code.End.WebAssembly): 20 (GetLocal.0.I32Const.0.TableSet.End.End.WebAssembly.fun): 21 (GetLocal.0.I32Const.0.TableSet.End.End.WebAssembly.assert.throws): 22 (GetLocal.0.I32Const.0.TableSet.End.End.WebAssembly): 23 (assert.throws): 24 (assert.throws.doTest): 25 (let.importedFun.of): 26 (makeAnyfuncIdent.fun): 27 * wasm/references/validation.js: 28 (assert.throws): 29 * wasm/wasm.json: 30 1 31 2019-06-17 Ross Kirsling <ross.kirsling@sony.com> 2 32 -
trunk/JSTests/wasm/Builder.js
r245765 r246504 535 535 GetGlobal: (type, initValue, mutability) => { 536 536 s.data.push({ type, op: "get_global", mutability: _normalizeMutability(mutability), initValue }); 537 return _errorHandlingProxyFor(globalBuilder); 538 }, 539 RefFunc: (type, initValue, mutability) => { 540 s.data.push({ type, op: "ref.func", mutability: _normalizeMutability(mutability), initValue }); 537 541 return _errorHandlingProxyFor(globalBuilder); 538 542 }, -
trunk/JSTests/wasm/references/anyref_globals.js
r245765 r246504 57 57 const obj = { test: "hi" } 58 58 59 $1.exports.set_glob(obj); assert.eq($1.exports.get_glob(), obj); 59 assert.throws(() => $1.exports.expglob2 = null, TypeError, "Attempted to assign to readonly property.") 60 61 $1.exports.set_glob(obj); assert.eq($1.exports.get_glob(), obj); assert.eq($1.exports.expglob2, "hi") 60 62 $1.exports.set_glob(5); assert.eq($1.exports.get_glob(), 5) 61 63 $1.exports.set_glob(null); assert.eq($1.exports.get_glob(), null) -
trunk/JSTests/wasm/references/validation.js
r246139 r246504 64 64 bin.trim(); 65 65 66 assert.throws(() => new WebAssembly.Module(bin.get()), WebAssembly.CompileError, "WebAssembly.Module doesn't validate: table.set expects the table to have type Anyref, in function at index 0 (evaluating 'new WebAssembly.Module(bin.get())')");66 assert.throws(() => new WebAssembly.Module(bin.get()), WebAssembly.CompileError, "WebAssembly.Module doesn't validate: table.set value to type Anyref expected Anyfunc, in function at index 0 (evaluating 'new WebAssembly.Module(bin.get())')"); 67 67 } 68 68 … … 87 87 bin.trim(); 88 88 89 assert.throws(() => new WebAssembly.Module(bin.get()), WebAssembly.CompileError, "WebAssembly.Module doesn't validate: table.get expects the table to have type Anyref, in function at index 0 (evaluating 'new WebAssembly.Module(bin.get())')");89 assert.throws(() => new WebAssembly.Module(bin.get()), WebAssembly.CompileError, "WebAssembly.Module doesn't validate: control flow returns with unexpected type, in function at index 0 (evaluating 'new WebAssembly.Module(bin.get())')"); 90 90 } 91 91 -
trunk/JSTests/wasm/wasm.json
r246139 r246504 12 12 "f32": { "type": "varint7", "value": -3, "b3type": "B3::Float" }, 13 13 "f64": { "type": "varint7", "value": -4, "b3type": "B3::Double" }, 14 "anyfunc": { "type": "varint7", "value": -16, "b3type": "B3:: Void" },14 "anyfunc": { "type": "varint7", "value": -16, "b3type": "B3::Int64" }, 15 15 "anyref": { "type": "varint7", "value": -17, "b3type": "B3::Int64" }, 16 16 "func": { "type": "varint7", "value": -32, "b3type": "B3::Void" }, 17 17 "void": { "type": "varint7", "value": -64, "b3type": "B3::Void" } 18 18 }, 19 "value_type": ["i32", "i64", "f32", "f64", "anyref" ],20 "block_type": ["i32", "i64", "f32", "f64", "void", "anyref" ],19 "value_type": ["i32", "i64", "f32", "f64", "anyref", "anyfunc"], 20 "block_type": ["i32", "i64", "f32", "f64", "void", "anyref", "anyfunc"], 21 21 "elem_type": ["anyfunc","anyref"], 22 22 "external_kind": { … … 60 60 "f64.const": { "category": "special", "value": 68, "return": ["f64"], "parameter": [], "immediate": [{"name": "value", "type": "double"}], "description": "a constant value interpreted as f64" }, 61 61 "f32.const": { "category": "special", "value": 67, "return": ["f32"], "parameter": [], "immediate": [{"name": "value", "type": "float"}], "description": "a constant value interpreted as f32" }, 62 "ref.null": { "category": "special", "value": 208, "return": ["any ref"],"parameter": [], "immediate": [], "description": "a constant null reference" },62 "ref.null": { "category": "special", "value": 208, "return": ["anyfunc"], "parameter": [], "immediate": [], "description": "a constant null reference" }, 63 63 "ref.is_null": { "category": "special", "value": 209, "return": ["i32"], "parameter": ["anyref"], "immediate": [], "description": "determine if a reference is null" }, 64 "ref.func": { "category": "special", "value": 210, "return": ["anyfunc"], "parameter": [], "immediate": [{"name": "function_index", "type": "varuint32"}], "description": "return a reference to the function at the given index" }, 64 65 "get_local": { "category": "special", "value": 32, "return": ["any"], "parameter": [], "immediate": [{"name": "local_index", "type": "varuint32"}], "description": "read a local variable or parameter" }, 65 66 "set_local": { "category": "special", "value": 33, "return": [], "parameter": ["any"], "immediate": [{"name": "local_index", "type": "varuint32"}], "description": "write a local variable or parameter" }, -
trunk/Source/JavaScriptCore/ChangeLog
r246490 r246504 1 2019-06-17 Justin Michaud <justin_michaud@apple.com> 2 3 [WASM-References] Add support for Funcref in parameters and return types 4 https://bugs.webkit.org/show_bug.cgi?id=198157 5 6 Reviewed by Yusuke Suzuki. 7 8 Add support for funcref in parameters, globals, and in table.get/set. When converting a JSValue to 9 a funcref (nee anyfunc), we first make sure it is an exported wasm function or null. 10 11 We also add support for Ref.func. Anywhere a Ref.func is used, (statically) we construct a JS wrapper 12 for it so that we never need to construct JSValues when handling references. This should make threads 13 easier to implement. 14 15 Finally, we add some missing bounds checks for table.get/set. 16 17 * wasm/WasmAirIRGenerator.cpp: 18 (JSC::Wasm::AirIRGenerator::tmpForType): 19 (JSC::Wasm::AirIRGenerator::moveOpForValueType): 20 (JSC::Wasm::AirIRGenerator::AirIRGenerator): 21 (JSC::Wasm::AirIRGenerator::addLocal): 22 (JSC::Wasm::AirIRGenerator::addConstant): 23 (JSC::Wasm::AirIRGenerator::addRefFunc): 24 (JSC::Wasm::AirIRGenerator::addTableSet): 25 (JSC::Wasm::AirIRGenerator::setGlobal): 26 (JSC::Wasm::AirIRGenerator::addReturn): 27 * wasm/WasmB3IRGenerator.cpp: 28 (JSC::Wasm::B3IRGenerator::addLocal): 29 (JSC::Wasm::B3IRGenerator::addTableSet): 30 (JSC::Wasm::B3IRGenerator::addRefFunc): 31 (JSC::Wasm::B3IRGenerator::setGlobal): 32 * wasm/WasmBBQPlan.cpp: 33 (JSC::Wasm::BBQPlan::compileFunctions): 34 * wasm/WasmCallingConvention.h: 35 (JSC::Wasm::CallingConventionAir::marshallArgument const): 36 (JSC::Wasm::CallingConventionAir::setupCall const): 37 * wasm/WasmExceptionType.h: 38 * wasm/WasmFormat.h: 39 (JSC::Wasm::isValueType): 40 (JSC::Wasm::isSubtype): 41 * wasm/WasmFunctionParser.h: 42 (JSC::Wasm::FunctionParser<Context>::parseExpression): 43 (JSC::Wasm::FunctionParser<Context>::parseUnreachableExpression): 44 * wasm/WasmInstance.cpp: 45 (JSC::Wasm::Instance::Instance): 46 (JSC::Wasm::Instance::getFunctionWrapper const): 47 (JSC::Wasm::Instance::setFunctionWrapper): 48 * wasm/WasmInstance.h: 49 * wasm/WasmModuleInformation.h: 50 (JSC::Wasm::ModuleInformation::referencedFunctions const): 51 (JSC::Wasm::ModuleInformation::addReferencedFunction const): 52 * wasm/WasmSectionParser.cpp: 53 (JSC::Wasm::SectionParser::parseGlobal): 54 (JSC::Wasm::SectionParser::parseInitExpr): 55 * wasm/WasmValidate.cpp: 56 (JSC::Wasm::Validate::addTableGet): 57 (JSC::Wasm::Validate::addTableSet): 58 (JSC::Wasm::Validate::addRefIsNull): 59 (JSC::Wasm::Validate::addRefFunc): 60 (JSC::Wasm::Validate::setLocal): 61 (JSC::Wasm::Validate::addCall): 62 (JSC::Wasm::Validate::addCallIndirect): 63 * wasm/js/JSToWasm.cpp: 64 (JSC::Wasm::createJSToWasmWrapper): 65 * wasm/js/JSWebAssemblyHelpers.h: 66 (JSC::isWebAssemblyHostFunction): 67 * wasm/js/JSWebAssemblyInstance.cpp: 68 (JSC::JSWebAssemblyInstance::visitChildren): 69 * wasm/js/JSWebAssemblyRuntimeError.cpp: 70 (JSC::createJSWebAssemblyRuntimeError): 71 * wasm/js/JSWebAssemblyRuntimeError.h: 72 * wasm/js/WasmToJS.cpp: 73 (JSC::Wasm::handleBadI64Use): 74 (JSC::Wasm::wasmToJS): 75 (JSC::Wasm::emitWasmToJSException): 76 * wasm/js/WasmToJS.h: 77 * wasm/js/WebAssemblyFunction.cpp: 78 (JSC::callWebAssemblyFunction): 79 (JSC::WebAssemblyFunction::jsCallEntrypointSlow): 80 * wasm/js/WebAssemblyModuleRecord.cpp: 81 (JSC::WebAssemblyModuleRecord::link): 82 * wasm/wasm.json: 83 1 84 2019-06-16 Darin Adler <darin@apple.com> 2 85 -
trunk/Source/JavaScriptCore/wasm/WasmAirIRGenerator.cpp
r246451 r246504 235 235 // References 236 236 PartialResult WARN_UNUSED_RETURN addRefIsNull(ExpressionType& value, ExpressionType& result); 237 PartialResult WARN_UNUSED_RETURN addRefFunc(uint32_t index, ExpressionType& result); 237 238 238 239 // Tables 239 PartialResult WARN_UNUSED_RETURN addTableGet(ExpressionType& i dx, ExpressionType& result);240 PartialResult WARN_UNUSED_RETURN addTableSet(ExpressionType& i dx, ExpressionType& value);240 PartialResult WARN_UNUSED_RETURN addTableGet(ExpressionType& index, ExpressionType& result); 241 PartialResult WARN_UNUSED_RETURN addTableSet(ExpressionType& index, ExpressionType& value); 241 242 242 243 // Locals … … 371 372 case Type::I64: 372 373 case Type::Anyref: 374 case Type::Anyfunc: 373 375 return g64(); 374 376 case Type::F32: … … 555 557 case Type::I64: 556 558 case Type::Anyref: 559 case Type::Anyfunc: 557 560 return Move; 558 561 case Type::F32: … … 800 803 case Type::I64: 801 804 case Type::Anyref: 805 case Type::Anyfunc: 802 806 append(Move, arg, m_locals[i]); 803 807 break; … … 885 889 switch (type) { 886 890 case Type::Anyref: 891 case Type::Anyfunc: 887 892 append(Move, Arg::imm(JSValue::encode(jsNull())), local); 888 893 break; … … 919 924 case Type::I64: 920 925 case Type::Anyref: 926 case Type::Anyfunc: 921 927 append(block, Move, Arg::bigImm(value), result); 922 928 break; … … 954 960 } 955 961 956 auto AirIRGenerator::add TableGet(ExpressionType& idx, ExpressionType& result) -> PartialResult962 auto AirIRGenerator::addRefFunc(uint32_t index, ExpressionType& result) -> PartialResult 957 963 { 958 964 // FIXME: Emit this inline <https://bugs.webkit.org/show_bug.cgi?id=198506>. 959 ASSERT(idx.tmp()); 960 ASSERT(idx.type() == Type::I32); 965 result = tmpForType(Type::Anyfunc); 966 emitCCall(&doWasmRefFunc, result, instanceValue(), addConstant(Type::I32, index)); 967 968 return { }; 969 } 970 971 auto AirIRGenerator::addTableGet(ExpressionType& index, ExpressionType& result) -> PartialResult 972 { 973 // FIXME: Emit this inline <https://bugs.webkit.org/show_bug.cgi?id=198506>. 974 ASSERT(index.tmp()); 975 ASSERT(index.type() == Type::I32); 961 976 result = tmpForType(Type::Anyref); 962 977 963 uint64_t (*doGet)(Instance*, int32_t) = [] (Instance* instance, int32_t idx) -> uint64_t { 964 return JSValue::encode(instance->table()->get(idx)); 965 }; 966 967 emitCCall(doGet, result, instanceValue(), idx); 968 969 return { }; 970 } 971 972 auto AirIRGenerator::addTableSet(ExpressionType& idx, ExpressionType& value) -> PartialResult 978 emitCCall(&getWasmTableElement, result, instanceValue(), index); 979 emitCheck([&] { 980 return Inst(BranchTest32, nullptr, Arg::resCond(MacroAssembler::Zero), result, result); 981 }, [=] (CCallHelpers& jit, const B3::StackmapGenerationParams&) { 982 this->emitThrowException(jit, ExceptionType::OutOfBoundsTableAccess); 983 }); 984 985 return { }; 986 } 987 988 auto AirIRGenerator::addTableSet(ExpressionType& index, ExpressionType& value) -> PartialResult 973 989 { 974 990 // FIXME: Emit this inline <https://bugs.webkit.org/show_bug.cgi?id=198506>. 975 ASSERT(i dx.tmp());976 ASSERT(i dx.type() == Type::I32);991 ASSERT(index.tmp()); 992 ASSERT(index.type() == Type::I32); 977 993 ASSERT(value.tmp()); 978 994 979 void (*doSet)(Instance*, int32_t, uint64_t value) = [] (Instance* instance, int32_t idx, uint64_t value) -> void { 980 // FIXME: We need to box wasm Funcrefs once they are supported here. 981 // <https://bugs.webkit.org/show_bug.cgi?id=198157> 982 instance->table()->set(idx, JSValue::decode(value)); 983 }; 984 985 emitCCall(doSet, TypedTmp(), instanceValue(), idx, value); 995 auto shouldThrow = g32(); 996 emitCCall(&setWasmTableElement, shouldThrow, instanceValue(), index, value); 997 998 emitCheck([&] { 999 return Inst(BranchTest32, nullptr, Arg::resCond(MacroAssembler::Zero), shouldThrow, shouldThrow); 1000 }, [=] (CCallHelpers& jit, const B3::StackmapGenerationParams&) { 1001 this->emitThrowException(jit, ExceptionType::OutOfBoundsTableAccess); 1002 }); 986 1003 987 1004 return { }; … … 1104 1121 } 1105 1122 1106 if ( type == Anyref)1123 if (isSubtype(type, Anyref)) 1107 1124 emitWriteBarrierForJSWrapper(); 1108 1125 … … 1624 1641 case Type::I64: 1625 1642 case Type::Anyref: 1643 case Type::Anyfunc: 1626 1644 append(Move, returnValues[0], returnValueGPR); 1627 1645 append(Ret64, returnValueGPR); -
trunk/Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp
r246451 r246504 188 188 // References 189 189 PartialResult WARN_UNUSED_RETURN addRefIsNull(ExpressionType& value, ExpressionType& result); 190 PartialResult WARN_UNUSED_RETURN addRefFunc(uint32_t index, ExpressionType& result); 190 191 191 192 // Tables 192 PartialResult WARN_UNUSED_RETURN addTableGet(ExpressionType& i dx, ExpressionType& result);193 PartialResult WARN_UNUSED_RETURN addTableSet(ExpressionType& i dx, ExpressionType& value);193 PartialResult WARN_UNUSED_RETURN addTableGet(ExpressionType& index, ExpressionType& result); 194 PartialResult WARN_UNUSED_RETURN addTableSet(ExpressionType& index, ExpressionType& value); 194 195 195 196 // Locals … … 539 540 Variable* local = m_proc.addVariable(toB3Type(type)); 540 541 m_locals.uncheckedAppend(local); 541 auto val = type == Anyref? JSValue::encode(jsNull()) : 0;542 auto val = isSubtype(type, Anyref) ? JSValue::encode(jsNull()) : 0; 542 543 m_currentBlock->appendNew<VariableValue>(m_proc, Set, Origin(), local, constant(toB3Type(type), val, Origin())); 543 544 } … … 566 567 } 567 568 568 auto B3IRGenerator::addTableGet(ExpressionType& i dx, ExpressionType& result) -> PartialResult569 auto B3IRGenerator::addTableGet(ExpressionType& index, ExpressionType& result) -> PartialResult 569 570 { 570 571 // FIXME: Emit this inline <https://bugs.webkit.org/show_bug.cgi?id=198506>. 571 uint64_t (*doGet)(Instance*, int32_t) = [] (Instance* instance, int32_t idx) -> uint64_t {572 return JSValue::encode(instance->table()->get(idx));573 };574 575 572 result = m_currentBlock->appendNew<CCallValue>(m_proc, toB3Type(Anyref), origin(), 576 m_currentBlock->appendNew<ConstPtrValue>(m_proc, origin(), tagCFunctionPtr<void*>(doGet, B3CCallPtrTag)), 577 instanceValue(), idx); 578 579 return { }; 580 } 581 582 auto B3IRGenerator::addTableSet(ExpressionType& idx, ExpressionType& value) -> PartialResult 573 m_currentBlock->appendNew<ConstPtrValue>(m_proc, origin(), tagCFunctionPtr<void*>(&getWasmTableElement, B3CCallPtrTag)), 574 instanceValue(), index); 575 576 { 577 CheckValue* check = m_currentBlock->appendNew<CheckValue>(m_proc, Check, origin(), 578 m_currentBlock->appendNew<Value>(m_proc, Equal, origin(), result, m_currentBlock->appendNew<Const64Value>(m_proc, origin(), 0))); 579 580 check->setGenerator([=] (CCallHelpers& jit, const B3::StackmapGenerationParams&) { 581 this->emitExceptionCheck(jit, ExceptionType::OutOfBoundsTableAccess); 582 }); 583 } 584 585 return { }; 586 } 587 588 auto B3IRGenerator::addTableSet(ExpressionType& index, ExpressionType& value) -> PartialResult 583 589 { 584 590 // FIXME: Emit this inline <https://bugs.webkit.org/show_bug.cgi?id=198506>. 585 void (*doSet)(Instance*, int32_t, uint64_t value) = [] (Instance* instance, int32_t idx, uint64_t value) -> void { 586 // FIXME: We need to box wasm Funcrefs once they are supported here. 587 // <https://bugs.webkit.org/show_bug.cgi?id=198157> 588 instance->table()->set(idx, JSValue::decode(value)); 589 }; 590 591 m_currentBlock->appendNew<CCallValue>(m_proc, B3::Void, origin(), 592 m_currentBlock->appendNew<ConstPtrValue>(m_proc, origin(), tagCFunctionPtr<void*>(doSet, B3CCallPtrTag)), 593 instanceValue(), idx, value); 591 auto shouldThrow = m_currentBlock->appendNew<CCallValue>(m_proc, B3::Int32, origin(), 592 m_currentBlock->appendNew<ConstPtrValue>(m_proc, origin(), tagCFunctionPtr<void*>(&setWasmTableElement, B3CCallPtrTag)), 593 instanceValue(), index, value); 594 595 { 596 CheckValue* check = m_currentBlock->appendNew<CheckValue>(m_proc, Check, origin(), 597 m_currentBlock->appendNew<Value>(m_proc, Equal, origin(), shouldThrow, m_currentBlock->appendNew<Const32Value>(m_proc, origin(), 0))); 598 599 check->setGenerator([=] (CCallHelpers& jit, const B3::StackmapGenerationParams&) { 600 this->emitExceptionCheck(jit, ExceptionType::OutOfBoundsTableAccess); 601 }); 602 } 603 604 return { }; 605 } 606 607 auto B3IRGenerator::addRefFunc(uint32_t index, ExpressionType& result) -> PartialResult 608 { 609 // FIXME: Emit this inline <https://bugs.webkit.org/show_bug.cgi?id=198506>. 610 611 result = m_currentBlock->appendNew<CCallValue>(m_proc, B3::Int64, origin(), 612 m_currentBlock->appendNew<ConstPtrValue>(m_proc, origin(), tagCFunctionPtr<void*>(&doWasmRefFunc, B3CCallPtrTag)), 613 instanceValue(), addConstant(Type::I32, index)); 594 614 595 615 return { }; … … 680 700 m_currentBlock->appendNew<MemoryValue>(m_proc, Store, origin(), value, globalsArray, safeCast<int32_t>(index * sizeof(Register))); 681 701 682 if ( m_info.globals[index].type == Anyref)702 if (isSubtype(m_info.globals[index].type, Anyref)) 683 703 emitWriteBarrierForJSWrapper(); 684 704 -
trunk/Source/JavaScriptCore/wasm/WasmBBQPlan.cpp
r246368 r246504 287 287 m_wasmInternalFunctions[functionIndex] = WTFMove(*parseAndCompileResult); 288 288 289 if (m_exportedFunctionIndices.contains(functionIndex) ) {289 if (m_exportedFunctionIndices.contains(functionIndex) || m_moduleInformation->referencedFunctions().contains(functionIndex)) { 290 290 auto locker = holdLock(m_lock); 291 291 auto result = m_embedderToWasmInternalFunctions.add(functionIndex, m_createEmbedderWrapper(m_compilationContexts[functionIndex], signature, &m_unlinkedWasmToWasmCalls[functionIndex], m_moduleInformation.get(), m_mode, functionIndex)); -
trunk/Source/JavaScriptCore/wasm/WasmCallingConvention.h
r245496 r246504 237 237 case Type::I64: 238 238 case Type::Anyref: 239 case Wasm::Anyfunc: 239 240 marshallArgumentImpl(m_gprArgs, gpArgumentCount, stackOffset, regFunc, stackFunc); 240 241 break; … … 302 303 case Type::I64: 303 304 case Type::Anyref: 305 case Wasm::Anyfunc: 304 306 patchpoint->resultConstraint = B3::ValueRep::reg(GPRInfo::returnValueGPR); 305 307 break; -
trunk/Source/JavaScriptCore/wasm/WasmExceptionType.h
r238376 r246504 34 34 #define FOR_EACH_EXCEPTION(macro) \ 35 35 macro(OutOfBoundsMemoryAccess, "Out of bounds memory access") \ 36 macro(OutOfBoundsTableAccess, "Out of bounds table access") \ 36 37 macro(OutOfBoundsCallIndirect, "Out of bounds call_indirect") \ 37 38 macro(NullTableEntry, "call_indirect to a null table entry") \ … … 43 44 macro(StackOverflow, "Stack overflow") \ 44 45 macro(I64ArgumentType, "WebAssembly function with an i64 argument can't be called from JavaScript") \ 45 macro(I64ReturnType, "WebAssembly function that returns i64 can't be called from JavaScript") 46 macro(I64ReturnType, "WebAssembly function that returns i64 can't be called from JavaScript") \ 47 macro(FuncrefNotWasm, "Anyfunc must be an exported wasm function") 46 48 47 49 enum class ExceptionType : uint32_t { -
trunk/Source/JavaScriptCore/wasm/WasmFormat.h
r246139 r246504 69 69 return true; 70 70 case Anyref: 71 case Anyfunc: 71 72 return Options::useWebAssemblyReferences(); 72 73 default: … … 74 75 } 75 76 return false; 77 } 78 79 inline bool isSubtype(Type sub, Type parent) 80 { 81 if (sub == parent) 82 return true; 83 return sub == Anyfunc && parent == Anyref; 76 84 } 77 85 … … 139 147 IsImport, 140 148 FromGlobalImport, 149 FromRefFunc, 141 150 FromExpression 142 151 }; … … 235 244 Optional<uint32_t> maximum() const { return m_maximum; } 236 245 TableElementType type() const { return m_type; } 246 Wasm::Type wasmType() const { return m_type == TableElementType::Funcref ? Type::Anyfunc : Type::Anyref; } 237 247 238 248 private: -
trunk/Source/JavaScriptCore/wasm/WasmFunctionParser.h
r246139 r246504 284 284 case TableGet: { 285 285 WASM_PARSER_FAIL_IF(!Options::useWebAssemblyReferences(), "references are not enabled"); 286 ExpressionType result, i dx;287 WASM_TRY_POP_EXPRESSION_STACK_INTO(i dx, "table.get");288 WASM_TRY_ADD_TO_CONTEXT(addTableGet(i dx, result));286 ExpressionType result, index; 287 WASM_TRY_POP_EXPRESSION_STACK_INTO(index, "table.get"); 288 WASM_TRY_ADD_TO_CONTEXT(addTableGet(index, result)); 289 289 m_expressionStack.append(result); 290 290 return { }; … … 293 293 case TableSet: { 294 294 WASM_PARSER_FAIL_IF(!Options::useWebAssemblyReferences(), "references are not enabled"); 295 ExpressionType val, i dx;295 ExpressionType val, index; 296 296 WASM_TRY_POP_EXPRESSION_STACK_INTO(val, "table.set"); 297 WASM_TRY_POP_EXPRESSION_STACK_INTO(i dx, "table.set");298 WASM_TRY_ADD_TO_CONTEXT(addTableSet(i dx, val));297 WASM_TRY_POP_EXPRESSION_STACK_INTO(index, "table.set"); 298 WASM_TRY_ADD_TO_CONTEXT(addTableSet(index, val)); 299 299 return { }; 300 300 } … … 302 302 case RefNull: { 303 303 WASM_PARSER_FAIL_IF(!Options::useWebAssemblyReferences(), "references are not enabled"); 304 m_expressionStack.append(m_context.addConstant(Any ref, JSValue::encode(jsNull())));304 m_expressionStack.append(m_context.addConstant(Anyfunc, JSValue::encode(jsNull()))); 305 305 return { }; 306 306 } … … 311 311 WASM_TRY_POP_EXPRESSION_STACK_INTO(value, "ref.is_null"); 312 312 WASM_TRY_ADD_TO_CONTEXT(addRefIsNull(value, result)); 313 m_expressionStack.append(result); 314 return { }; 315 } 316 317 case RefFunc: { 318 uint32_t index; 319 ExpressionType result; 320 WASM_PARSER_FAIL_IF(!Options::useWebAssemblyReferences(), "references are not enabled"); 321 WASM_PARSER_FAIL_IF(!parseVarUInt32(index), "can't get index for ref.func"); 322 323 WASM_TRY_ADD_TO_CONTEXT(addRefFunc(index, result)); 313 324 m_expressionStack.append(result); 314 325 return { }; … … 682 693 } 683 694 695 case RefFunc: { 696 uint32_t unused; 697 WASM_PARSER_FAIL_IF(!parseVarUInt32(unused), "can't get immediate for ", m_currentOpcode, " in unreachable context"); 698 WASM_PARSER_FAIL_IF(!Options::useWebAssemblyReferences(), "references are not enabled"); 699 return { }; 700 } 701 684 702 case GrowMemory: 685 703 case CurrentMemory: { -
trunk/Source/JavaScriptCore/wasm/WasmInstance.cpp
r246095 r246504 30 30 31 31 #include "JSCInlines.h" 32 #include "JSWebAssemblyHelpers.h" 32 33 #include "JSWebAssemblyInstance.h" 33 34 #include "Register.h" … … 58 59 memset(static_cast<void*>(m_globals.get()), 0, globalMemoryByteSize(m_module.get())); 59 60 for (unsigned i = 0; i < m_module->moduleInformation().globals.size(); ++i) { 60 if ( m_module.get().moduleInformation().globals[i].type == Anyref)61 if (isSubtype(m_module.get().moduleInformation().globals[i].type, Anyref)) 61 62 m_globalsToMark.set(i); 62 63 } … … 81 82 } 82 83 84 JSValue Instance::getFunctionWrapper(unsigned i) const 85 { 86 JSValue value = m_functionWrappers.get(i).get(); 87 if (value.isEmpty()) 88 return jsNull(); 89 return value; 90 } 91 92 void Instance::setFunctionWrapper(unsigned i, JSValue value) 93 { 94 ASSERT(m_owner); 95 ASSERT(value.isFunction(*owner<JSWebAssemblyInstance>()->vm())); 96 ASSERT(!m_functionWrappers.contains(i)); 97 auto locker = holdLock(owner<JSWebAssemblyInstance>()->cellLock()); 98 m_functionWrappers.set(i, WriteBarrier<Unknown>(*owner<JSWebAssemblyInstance>()->vm(), owner<JSWebAssemblyInstance>(), value)); 99 ASSERT(getFunctionWrapper(i) == value); 100 } 101 102 EncodedJSValue getWasmTableElement(Instance* instance, int32_t signedIndex) 103 { 104 if (signedIndex < 0) 105 return 0; 106 107 uint32_t index = signedIndex; 108 if (index >= instance->table()->length()) 109 return 0; 110 111 return JSValue::encode(instance->table()->get(index)); 112 } 113 114 bool setWasmTableElement(Instance* instance, int32_t signedIndex, EncodedJSValue encValue) 115 { 116 if (signedIndex < 0) 117 return false; 118 119 uint32_t index = signedIndex; 120 if (index >= instance->table()->length()) 121 return false; 122 123 JSValue value = JSValue::decode(encValue); 124 if (instance->table()->type() == Wasm::TableElementType::Anyref) 125 instance->table()->set(index, value); 126 else if (instance->table()->type() == Wasm::TableElementType::Funcref) { 127 WebAssemblyFunction* wasmFunction; 128 WebAssemblyWrapperFunction* wasmWrapperFunction; 129 130 if (isWebAssemblyHostFunction(*instance->owner<JSObject>()->vm(), value, wasmFunction, wasmWrapperFunction)) { 131 ASSERT(!!wasmFunction || !!wasmWrapperFunction); 132 if (wasmFunction) 133 instance->table()->asFuncrefTable()->setFunction(index, jsCast<JSObject*>(value), wasmFunction->importableFunction(), &wasmFunction->instance()->instance()); 134 else 135 instance->table()->asFuncrefTable()->setFunction(index, jsCast<JSObject*>(value), wasmWrapperFunction->importableFunction(), &wasmWrapperFunction->instance()->instance()); 136 } else if (value.isNull()) 137 instance->table()->clear(index); 138 else 139 ASSERT_NOT_REACHED(); 140 } else 141 ASSERT_NOT_REACHED(); 142 143 return true; 144 } 145 146 EncodedJSValue doWasmRefFunc(Instance* instance, uint32_t index) 147 { 148 JSValue value = instance->getFunctionWrapper(index); 149 ASSERT(value.isFunction(*instance->owner<JSObject>()->vm())); 150 return JSValue::encode(value); 151 } 152 83 153 } } // namespace JSC::Wasm 84 154 -
trunk/Source/JavaScriptCore/wasm/WasmInstance.h
r246368 r246504 40 40 41 41 struct Context; 42 class Instance; 43 44 EncodedJSValue getWasmTableElement(Instance*, int32_t); 45 bool setWasmTableElement(Instance*, int32_t, EncodedJSValue encValue); 46 EncodedJSValue doWasmRefFunc(Instance*, uint32_t); 42 47 43 48 class Instance : public ThreadSafeRefCounted<Instance>, public CanMakeWeakPtr<Instance> { 44 49 public: 45 50 using StoreTopCallFrameCallback = WTF::Function<void(void*)>; 51 using FunctionWrapperMap = HashMap<uint32_t, WriteBarrier<Unknown>, IntHash<uint32_t>, WTF::UnsignedWithZeroKeyHashTraits<uint32_t>>; 46 52 47 53 static Ref<Instance> create(Context*, Ref<Module>&&, EntryFrame** pointerToTopEntryFrame, void** pointerToActualStackLimit, StoreTopCallFrameCallback&&); … … 92 98 void setGlobal(unsigned, JSValue); 93 99 const BitVector& globalsToMark() { return m_globalsToMark; } 100 JSValue getFunctionWrapper(unsigned) const; 101 typename FunctionWrapperMap::ValuesConstIteratorRange functionWrappers() const { return m_functionWrappers.values(); } 102 void setFunctionWrapper(unsigned, JSValue); 94 103 95 104 static ptrdiff_t offsetOfMemory() { return OBJECT_OFFSETOF(Instance, m_memory); } … … 160 169 }; 161 170 MallocPtr<GlobalValue> m_globals; 171 FunctionWrapperMap m_functionWrappers; 162 172 BitVector m_globalsToMark; 163 173 EntryFrame** m_pointerToTopEntryFrame { nullptr }; -
trunk/Source/JavaScriptCore/wasm/WasmModuleInformation.h
r239427 r246504 30 30 #include "WasmFormat.h" 31 31 32 #include <wtf/BitVector.h> 32 33 #include <wtf/Optional.h> 33 34 … … 67 68 uint32_t tableCount() const { return tableInformation ? 1 : 0; } 68 69 70 const BitVector& referencedFunctions() const { return m_referencedFunctions; } 71 void addReferencedFunction(unsigned index) const { m_referencedFunctions.set(index); } 72 69 73 Vector<Import> imports; 70 74 Vector<SignatureIndex> importFunctionSignatureIndices; … … 85 89 Vector<CustomSection> customSections; 86 90 Ref<NameSection> nameSection; 91 92 mutable BitVector m_referencedFunctions; 87 93 }; 88 94 -
trunk/Source/JavaScriptCore/wasm/WasmSectionParser.cpp
r246266 r246504 292 292 if (initOpcode == GetGlobal) 293 293 global.initializationType = Global::FromGlobalImport; 294 else if (initOpcode == RefFunc) 295 global.initializationType = Global::FromRefFunc; 294 296 else 295 297 global.initializationType = Global::FromExpression; 296 WASM_PARSER_FAIL_IF( typeForInitOpcode != global.type, "Global init_expr opcode of type ", typeForInitOpcode, " doesn't match global's type ", global.type);298 WASM_PARSER_FAIL_IF(!isSubtype(typeForInitOpcode, global.type), "Global init_expr opcode of type ", typeForInitOpcode, " doesn't match global's type ", global.type); 297 299 298 300 m_info->globals.uncheckedAppend(WTFMove(global)); … … 480 482 481 483 case RefNull: { 482 resultType = Any ref;484 resultType = Anyfunc; 483 485 bitsOrImportNumber = JSValue::encode(jsNull()); 486 break; 487 } 488 489 case RefFunc: { 490 uint32_t index; 491 WASM_PARSER_FAIL_IF(!parseVarUInt32(index), "can't get ref.func index"); 492 WASM_PARSER_FAIL_IF(index >= m_info->functions.size(), "ref.func index", index, " exceeds the number of functions ", m_info->functions.size()); 493 494 resultType = Anyfunc; 495 bitsOrImportNumber = index; 484 496 break; 485 497 } -
trunk/Source/JavaScriptCore/wasm/WasmValidate.cpp
r246266 r246504 104 104 // References 105 105 Result WARN_UNUSED_RETURN addRefIsNull(ExpressionType& value, ExpressionType& result); 106 Result WARN_UNUSED_RETURN addRefFunc(uint32_t index, ExpressionType& result); 106 107 107 108 // Tables 108 Result WARN_UNUSED_RETURN addTableGet(ExpressionType& i dx, ExpressionType& result);109 Result WARN_UNUSED_RETURN addTableSet(ExpressionType& i dx, ExpressionType& value);109 Result WARN_UNUSED_RETURN addTableGet(ExpressionType& index, ExpressionType& result); 110 Result WARN_UNUSED_RETURN addTableSet(ExpressionType& index, ExpressionType& value); 110 111 111 112 // Locals … … 178 179 } 179 180 180 auto Validate::addTableGet(ExpressionType& idx, ExpressionType& result) -> Result 181 { 182 result = Type::Anyref; 183 WASM_VALIDATOR_FAIL_IF(Type::I32 != idx, "table.get index to type ", idx, " expected ", Type::I32); 184 WASM_VALIDATOR_FAIL_IF(TableElementType::Anyref != m_module.tableInformation.type(), "table.get expects the table to have type ", Type::Anyref); 185 186 return { }; 187 } 188 189 auto Validate::addTableSet(ExpressionType& idx, ExpressionType& value) -> Result 190 { 191 WASM_VALIDATOR_FAIL_IF(Type::I32 != idx, "table.set index to type ", idx, " expected ", Type::I32); 192 WASM_VALIDATOR_FAIL_IF(Type::Anyref != value, "table.set value to type ", value, " expected ", Type::Anyref); 193 WASM_VALIDATOR_FAIL_IF(TableElementType::Anyref != m_module.tableInformation.type(), "table.set expects the table to have type ", Type::Anyref); 181 auto Validate::addTableGet(ExpressionType& index, ExpressionType& result) -> Result 182 { 183 result = m_module.tableInformation.wasmType(); 184 WASM_VALIDATOR_FAIL_IF(Type::I32 != index, "table.get index to type ", index, " expected ", Type::I32); 185 186 return { }; 187 } 188 189 auto Validate::addTableSet(ExpressionType& index, ExpressionType& value) -> Result 190 { 191 auto type = m_module.tableInformation.wasmType(); 192 WASM_VALIDATOR_FAIL_IF(Type::I32 != index, "table.set index to type ", index, " expected ", Type::I32); 193 WASM_VALIDATOR_FAIL_IF(!isSubtype(value, type), "table.set value to type ", value, " expected ", type); 194 WASM_VALIDATOR_FAIL_IF(m_module.tableInformation.type() != TableElementType::Anyref 195 && m_module.tableInformation.type() != TableElementType::Funcref, "table.set expects the table to have type anyref or anyfunc"); 194 196 195 197 return { }; … … 199 201 { 200 202 result = Type::I32; 201 WASM_VALIDATOR_FAIL_IF(Type::Anyref != value, "ref.is_null to type ", value, " expected ", Type::Anyref); 203 WASM_VALIDATOR_FAIL_IF(!isSubtype(value, Type::Anyref), "ref.is_null to type ", value, " expected ", Type::Anyref); 204 205 return { }; 206 } 207 208 auto Validate::addRefFunc(uint32_t index, ExpressionType& result) -> Result 209 { 210 result = Type::Anyfunc; 211 WASM_VALIDATOR_FAIL_IF(index >= m_module.functionIndexSpaceSize(), "ref.func index ", index, " is too large, max is ", m_module.functionIndexSpaceSize()); 212 m_module.addReferencedFunction(index); 202 213 203 214 return { }; … … 225 236 ExpressionType localType; 226 237 WASM_FAIL_IF_HELPER_FAILS(getLocal(index, localType)); 227 WASM_VALIDATOR_FAIL_IF( localType != value, "set_local to type ", value, " expected ", localType);238 WASM_VALIDATOR_FAIL_IF(!isSubtype(value, localType), "set_local to type ", value, " expected ", localType); 228 239 return { }; 229 240 } … … 363 374 364 375 for (unsigned i = 0; i < args.size(); ++i) 365 WASM_VALIDATOR_FAIL_IF( args[i] != signature.argument(i), "argument type mismatch in call, got ", args[i], ", expected ", signature.argument(i));376 WASM_VALIDATOR_FAIL_IF(!isSubtype(args[i], signature.argument(i)), "argument type mismatch in call, got ", args[i], ", expected ", signature.argument(i)); 366 377 367 378 result = signature.returnType(); … … 376 387 377 388 for (unsigned i = 0; i < argumentCount; ++i) 378 WASM_VALIDATOR_FAIL_IF( args[i] != signature.argument(i), "argument type mismatch in call_indirect, got ", args[i], ", expected ", signature.argument(i));389 WASM_VALIDATOR_FAIL_IF(!isSubtype(args[i], signature.argument(i)), "argument type mismatch in call_indirect, got ", args[i], ", expected ", signature.argument(i)); 379 390 380 391 WASM_VALIDATOR_FAIL_IF(args.last() != I32, "non-i32 call_indirect index ", args.last()); -
trunk/Source/JavaScriptCore/wasm/js/JSToWasm.cpp
r246451 r246504 32 32 #include "DisallowMacroScratchRegisterUsage.h" 33 33 #include "JSCInlines.h" 34 #include "JSWebAssemblyHelpers.h" 34 35 #include "JSWebAssemblyInstance.h" 35 36 #include "JSWebAssemblyRuntimeError.h" … … 84 85 case Wasm::I32: 85 86 case Wasm::Anyref: 87 case Wasm::Anyfunc: 86 88 if (numGPRs >= wasmCallingConvention().m_gprArgs.size()) 87 89 totalFrameSize += sizeof(void*); … … 123 125 } 124 126 125 jit.loadPtr(CCallHelpers::Address(GPRInfo::argumentGPR2, Instance::offsetOfPointerToTopEntryFrame()), GPRInfo::argumentGPR0); 126 jit.loadPtr(CCallHelpers::Address(GPRInfo::argumentGPR0), GPRInfo::argumentGPR0); 127 jit.copyCalleeSavesToEntryFrameCalleeSavesBuffer(GPRInfo::argumentGPR0); 128 jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0); 129 jit.move(CCallHelpers::TrustedImm32(static_cast<int32_t>(argumentsIncludeI64 ? ExceptionType::I64ArgumentType : ExceptionType::I64ReturnType)), GPRInfo::argumentGPR1); 130 131 CCallHelpers::Call call = jit.call(OperationPtrTag); 132 133 jit.jump(GPRInfo::returnValueGPR, ExceptionHandlerPtrTag); 134 jit.breakpoint(); // We should not reach this. 135 136 jit.addLinkTask([=] (LinkBuffer& linkBuffer) { 137 linkBuffer.link(call, FunctionPtr<OperationPtrTag>(wasmToJSException)); 138 }); 127 emitThrowWasmToJSException(jit, GPRInfo::argumentGPR2, argumentsIncludeI64 ? ExceptionType::I64ArgumentType : ExceptionType::I64ReturnType); 139 128 return result; 140 129 } … … 166 155 case Wasm::I32: 167 156 case Wasm::I64: 157 case Wasm::Anyfunc: 168 158 case Wasm::Anyref: 169 159 if (numGPRs >= wasmCallingConvention().m_gprArgs.size()) { … … 251 241 break; 252 242 case Wasm::Anyref: 253 // FIXME: We need to box wasm Funcrefs once they are supported here.243 case Wasm::Anyfunc: 254 244 break; 255 245 case Wasm::I32: … … 269 259 case Wasm::I64: 270 260 case Wasm::Func: 271 case Wasm::Anyfunc:272 261 jit.breakpoint(); 273 262 break; -
trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyHelpers.h
r233122 r246504 123 123 124 124 125 ALWAYS_INLINE bool isWebAssemblyHostFunction(VM& vm, JS Object*object)125 ALWAYS_INLINE bool isWebAssemblyHostFunction(VM& vm, JSValue object) 126 126 { 127 127 WebAssemblyFunction* unused; -
trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyInstance.cpp
r245765 r246504 92 92 visitor.append(*thisObject->instance().importFunction<WriteBarrier<JSObject>>(i)); // This also keeps the functions' JSWebAssemblyInstance alive. 93 93 94 for (size_t i : thisObject->instance().globalsToMark()) { 95 // FIXME: We need to box wasm Funcrefs once they are supported here. 96 // <https://bugs.webkit.org/show_bug.cgi?id=198157> 94 for (size_t i : thisObject->instance().globalsToMark()) 97 95 visitor.appendUnbarriered(JSValue::decode(thisObject->instance().loadI64Global(i))); 98 } 96 97 auto locker = holdLock(cell->cellLock()); 98 for (auto& wrapper : thisObject->instance().functionWrappers()) 99 visitor.appendUnbarriered(wrapper.get()); 99 100 } 100 101 -
trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyRuntimeError.cpp
r217108 r246504 49 49 const ClassInfo JSWebAssemblyRuntimeError::s_info = { "WebAssembly.RuntimeError", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSWebAssemblyRuntimeError) }; 50 50 51 JSObject* createJSWebAssemblyRuntimeError(ExecState* exec, VM& vm, const String& message) 52 { 53 ASSERT(!message.isEmpty()); 54 JSGlobalObject* globalObject = exec->lexicalGlobalObject(); 55 return JSWebAssemblyRuntimeError::create(exec, vm, globalObject->webAssemblyRuntimeErrorStructure(), message); 56 } 51 57 52 58 } // namespace JSC -
trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyRuntimeError.h
r244040 r246504 44 44 }; 45 45 46 JSObject* createJSWebAssemblyRuntimeError(ExecState*, VM&, const String&); 47 46 48 } // namespace JSC 47 49 -
trunk/Source/JavaScriptCore/wasm/js/WasmToJS.cpp
r245496 r246504 33 33 #include "JITExceptions.h" 34 34 #include "JSCInlines.h" 35 #include "JSWebAssemblyHelpers.h" 35 36 #include "JSWebAssemblyInstance.h" 36 37 #include "JSWebAssemblyRuntimeError.h" … … 66 67 case Void: 67 68 case Func: 68 case Anyfunc:69 69 RELEASE_ASSERT_NOT_REACHED(); 70 70 … … 163 163 case Void: 164 164 case Func: 165 case Anyfunc:166 165 case I64: 167 166 RELEASE_ASSERT_NOT_REACHED(); 168 167 case Anyref: 168 case Anyfunc: 169 169 case I32: { 170 170 GPRReg gprReg; … … 238 238 case Void: 239 239 case Func: 240 case Anyfunc:241 240 case I64: 242 241 RELEASE_ASSERT_NOT_REACHED(); … … 244 243 arg = jsNumber(static_cast<int32_t>(buffer[argNum])); 245 244 break; 245 case Anyfunc: { 246 arg = JSValue::decode(buffer[argNum]); 247 ASSERT(isWebAssemblyHostFunction(*vm, arg) || arg.isNull()); 248 break; 249 } 246 250 case Anyref: 247 // FIXME: We need to box wasm Funcrefs once they are supported here.248 251 arg = JSValue::decode(buffer[argNum]); 249 252 break; … … 269 272 switch (signature.returnType()) { 270 273 case Func: 271 case Anyfunc:272 274 case I64: 273 275 RELEASE_ASSERT_NOT_REACHED(); … … 277 279 case I32: { 278 280 realResult = static_cast<uint64_t>(static_cast<uint32_t>(result.toInt32(exec))); 281 break; 282 } 283 case Anyfunc: { 284 realResult = JSValue::encode(result); 285 ASSERT(result.isFunction(*vm) || result.isNull()); 279 286 break; 280 287 } … … 372 379 case Void: 373 380 case Func: 374 case Anyfunc:375 381 case I64: 376 382 RELEASE_ASSERT_NOT_REACHED(); // Handled above. 377 383 case Anyref: 384 case Anyfunc: 378 385 case I32: { 379 386 GPRReg gprReg; … … 391 398 jit.boxInt32(gprReg, JSValueRegs(gprReg), DoNotHaveTagRegisters); 392 399 } 393 // FIXME: We need to box wasm Funcrefs once they are supported here.394 400 jit.store64(gprReg, calleeFrame.withOffset(calleeFrameOffset)); 395 401 calleeFrameOffset += sizeof(Register); … … 442 448 case Void: 443 449 case Func: 444 case Anyfunc:445 450 case I64: 446 451 RELEASE_ASSERT_NOT_REACHED(); // Handled above. 447 452 case Anyref: 453 case Anyfunc: 448 454 case I32: 449 455 // Skipped: handled above. … … 520 526 break; 521 527 case Func: 522 case Anyfunc:523 528 // For the JavaScript embedding, imports with these types in their signature return are a WebAssembly.Module validation error. 524 529 RELEASE_ASSERT_NOT_REACHED(); … … 554 559 break; 555 560 } 561 case Anyfunc: 556 562 case Anyref: 557 563 break; … … 696 702 } 697 703 704 void emitThrowWasmToJSException(CCallHelpers& jit, GPRReg wasmInstance, Wasm::ExceptionType type) 705 { 706 ASSERT(wasmInstance != GPRInfo::argumentGPR0); 707 jit.loadPtr(CCallHelpers::Address(wasmInstance, Wasm::Instance::offsetOfPointerToTopEntryFrame()), GPRInfo::argumentGPR0); 708 jit.loadPtr(CCallHelpers::Address(GPRInfo::argumentGPR0), GPRInfo::argumentGPR0); 709 jit.copyCalleeSavesToEntryFrameCalleeSavesBuffer(GPRInfo::argumentGPR0); 710 jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0); 711 jit.move(CCallHelpers::TrustedImm32(static_cast<int32_t>(type)), GPRInfo::argumentGPR1); 712 713 CCallHelpers::Call call = jit.call(OperationPtrTag); 714 715 jit.jump(GPRInfo::returnValueGPR, ExceptionHandlerPtrTag); 716 jit.breakpoint(); // We should not reach this. 717 718 jit.addLinkTask([=] (LinkBuffer& linkBuffer) { 719 linkBuffer.link(call, FunctionPtr<OperationPtrTag>(Wasm::wasmToJSException)); 720 }); 721 } 722 698 723 } } // namespace JSC::Wasm 699 724 -
trunk/Source/JavaScriptCore/wasm/js/WasmToJS.h
r230748 r246504 46 46 47 47 void* wasmToJSException(ExecState*, Wasm::ExceptionType, Instance*); 48 void emitThrowWasmToJSException(CCallHelpers&, GPRReg wasmInstance, Wasm::ExceptionType); 48 49 49 50 } } // namespace JSC::Wasm -
trunk/Source/JavaScriptCore/wasm/js/WebAssemblyFunction.cpp
r246451 r246504 85 85 arg = JSValue::decode(arg.toInt32(exec)); 86 86 break; 87 case Wasm::Anyfunc: { 88 if (!isWebAssemblyHostFunction(vm, arg) && !arg.isNull()) 89 return JSValue::encode(throwException(exec, scope, createJSWebAssemblyRuntimeError(exec, vm, "Anyfunc must be an exported wasm function"))); 90 break; 91 } 87 92 case Wasm::Anyref: 88 93 break; … … 98 103 case Wasm::Void: 99 104 case Wasm::Func: 100 case Wasm::Anyfunc:101 105 RELEASE_ASSERT_NOT_REACHED(); 102 106 } … … 229 233 break; 230 234 case Wasm::Anyref: 235 case Wasm::Anyfunc: 231 236 case Wasm::I32: 232 237 if (numGPRs >= Wasm::wasmCallingConvention().m_gprArgs.size()) … … 304 309 } 305 310 break; 311 case Wasm::Anyfunc: { 312 // FIXME: Emit this inline <https://bugs.webkit.org/show_bug.cgi?id=198506>. 313 bool (*shouldThrow)(Wasm::Instance*, JSValue) = [] (Wasm::Instance* wasmInstance, JSValue arg) -> bool { 314 JSWebAssemblyInstance* instance = wasmInstance->owner<JSWebAssemblyInstance>(); 315 JSGlobalObject* globalObject = instance->globalObject(); 316 VM& vm = globalObject->vm(); 317 return !isWebAssemblyHostFunction(vm, arg) && !arg.isNull(); 318 }; 319 jit.move(CCallHelpers::TrustedImmPtr(&instance()->instance()), GPRInfo::argumentGPR0); 320 jit.load64(CCallHelpers::Address(GPRInfo::callFrameRegister, jsOffset), GPRInfo::argumentGPR1); 321 jit.setupArguments<decltype(shouldThrow)>(GPRInfo::argumentGPR0, GPRInfo::argumentGPR1); 322 auto call = jit.call(OperationPtrTag); 323 324 jit.addLinkTask([=] (LinkBuffer& linkBuffer) { 325 linkBuffer.link(call, FunctionPtr<OperationPtrTag>(shouldThrow)); 326 }); 327 328 slowPath.append(jit.branchTest32(CCallHelpers::NonZero, GPRInfo::returnValueGPR)); 329 330 FALLTHROUGH; 331 } 306 332 case Wasm::Anyref: { 307 333 jit.load64(CCallHelpers::Address(GPRInfo::callFrameRegister, jsOffset), scratchGPR); … … 467 493 break; 468 494 } 469 case Wasm::Any ref: {470 // FIXME: We need to box wasm Funcrefs once they are supported here.495 case Wasm::Anyfunc: 496 case Wasm::Anyref: 471 497 break; 472 }473 498 case Wasm::I64: 474 499 case Wasm::Func: 475 case Wasm::Anyfunc:476 500 return nullptr; 477 501 default: -
trunk/Source/JavaScriptCore/wasm/js/WebAssemblyModuleRecord.cpp
r246139 r246504 236 236 if (moduleInformation.globals[import.kindIndex].type == Wasm::I64) 237 237 return exception(createJSWebAssemblyLinkError(exec, vm, importFailMessage(import, "imported global", "cannot be an i64"))); 238 if ( moduleInformation.globals[import.kindIndex].type != Wasm::Anyref&& !value.isNumber())238 if (!isSubtype(moduleInformation.globals[import.kindIndex].type, Wasm::Anyref) && !value.isNumber()) 239 239 return exception(createJSWebAssemblyLinkError(exec, vm, importFailMessage(import, "imported global", "must be a number"))); 240 240 // iii. Append ToWebAssemblyValue(v) to imports. 241 241 switch (moduleInformation.globals[import.kindIndex].type) { 242 case Wasm::Anyfunc: 243 if (!isWebAssemblyHostFunction(vm, value) && !value.isNull()) 244 return exception(createJSWebAssemblyLinkError(exec, vm, importFailMessage(import, "imported global", "must be a wasm exported function or null"))); 245 m_instance->instance().setGlobal(import.kindIndex, value); 246 break; 242 247 case Wasm::Anyref: 243 248 m_instance->instance().setGlobal(import.kindIndex, value); … … 320 325 } 321 326 327 unsigned functionImportCount = codeBlock->functionImportCount(); 328 auto makeFunctionWrapper = [&] (const String& field, uint32_t index) -> JSValue { 329 // If we already made a wrapper, do not make a new one. 330 JSValue wrapper = m_instance->instance().getFunctionWrapper(index); 331 332 if (!wrapper.isNull()) 333 return wrapper; 334 335 // 1. If e is a closure c: 336 // i. If there is an Exported Function Exotic Object func in funcs whose func.[[Closure]] equals c, then return func. 337 // ii. (Note: At most one wrapper is created for any closure, so func is unique, even if there are multiple occurrances in the list. Moreover, if the item was an import that is already an Exported Function Exotic Object, then the original function object will be found. For imports that are regular JS functions, a new wrapper will be created.) 338 if (index < functionImportCount) { 339 JSObject* functionImport = m_instance->instance().importFunction<WriteBarrier<JSObject>>(index)->get(); 340 if (isWebAssemblyHostFunction(vm, functionImport)) 341 wrapper = functionImport; 342 else { 343 Wasm::SignatureIndex signatureIndex = module->signatureIndexFromFunctionIndexSpace(index); 344 wrapper = WebAssemblyWrapperFunction::create(vm, globalObject, globalObject->webAssemblyWrapperFunctionStructure(), functionImport, index, m_instance.get(), signatureIndex); 345 } 346 } else { 347 // iii. Otherwise: 348 // a. Let func be an Exported Function Exotic Object created from c. 349 // b. Append func to funcs. 350 // c. Return func. 351 Wasm::Callee& embedderEntrypointCallee = codeBlock->embedderEntrypointCalleeFromFunctionIndexSpace(index); 352 Wasm::WasmToWasmImportableFunction::LoadLocation entrypointLoadLocation = codeBlock->entrypointLoadLocationFromFunctionIndexSpace(index); 353 Wasm::SignatureIndex signatureIndex = module->signatureIndexFromFunctionIndexSpace(index); 354 const Wasm::Signature& signature = Wasm::SignatureInformation::get(signatureIndex); 355 WebAssemblyFunction* function = WebAssemblyFunction::create(vm, globalObject, globalObject->webAssemblyFunctionStructure(), signature.argumentCount(), field, m_instance.get(), embedderEntrypointCallee, entrypointLoadLocation, signatureIndex); 356 wrapper = function; 357 } 358 359 ASSERT(wrapper.isFunction(vm)); 360 m_instance->instance().setFunctionWrapper(index, wrapper); 361 362 return wrapper; 363 }; 364 365 for (auto index : moduleInformation.referencedFunctions()) 366 makeFunctionWrapper("Referenced function", index); 367 322 368 // Globals 323 369 { … … 328 374 ASSERT(global.initialBitsOrImportNumber < moduleInformation.firstInternalGlobal); 329 375 m_instance->instance().setGlobal(globalIndex, m_instance->instance().loadI64Global(global.initialBitsOrImportNumber)); 376 } else if (global.initializationType == Wasm::Global::FromRefFunc) { 377 ASSERT(global.initialBitsOrImportNumber < moduleInformation.functionIndexSpaceSize()); 378 ASSERT(makeFunctionWrapper("Global init expr", global.initialBitsOrImportNumber).isFunction(vm)); 379 m_instance->instance().setGlobal(globalIndex, JSValue::encode(makeFunctionWrapper("Global init expr", global.initialBitsOrImportNumber))); 330 380 } else 331 381 m_instance->instance().setGlobal(globalIndex, global.initialBitsOrImportNumber); … … 334 384 335 385 SymbolTable* exportSymbolTable = module->exportSymbolTable(); 336 unsigned functionImportCount = codeBlock->functionImportCount();337 386 338 387 // Let exports be a list of (string, JS value) pairs that is mapped from each external value e in instance.exports as follows: … … 342 391 switch (exp.kind) { 343 392 case Wasm::ExternalKind::Function: { 344 // 1. If e is a closure c: 345 // i. If there is an Exported Function Exotic Object func in funcs whose func.[[Closure]] equals c, then return func. 346 // ii. (Note: At most one wrapper is created for any closure, so func is unique, even if there are multiple occurrances in the list. Moreover, if the item was an import that is already an Exported Function Exotic Object, then the original function object will be found. For imports that are regular JS functions, a new wrapper will be created.) 347 if (exp.kindIndex < functionImportCount) { 348 unsigned functionIndex = exp.kindIndex; 349 JSObject* functionImport = m_instance->instance().importFunction<WriteBarrier<JSObject>>(functionIndex)->get(); 350 if (isWebAssemblyHostFunction(vm, functionImport)) 351 exportedValue = functionImport; 352 else { 353 Wasm::SignatureIndex signatureIndex = module->signatureIndexFromFunctionIndexSpace(functionIndex); 354 exportedValue = WebAssemblyWrapperFunction::create(vm, globalObject, globalObject->webAssemblyWrapperFunctionStructure(), functionImport, functionIndex, m_instance.get(), signatureIndex); 355 } 356 } else { 357 // iii. Otherwise: 358 // a. Let func be an Exported Function Exotic Object created from c. 359 // b. Append func to funcs. 360 // c. Return func. 361 Wasm::Callee& embedderEntrypointCallee = codeBlock->embedderEntrypointCalleeFromFunctionIndexSpace(exp.kindIndex); 362 Wasm::WasmToWasmImportableFunction::LoadLocation entrypointLoadLocation = codeBlock->entrypointLoadLocationFromFunctionIndexSpace(exp.kindIndex); 363 Wasm::SignatureIndex signatureIndex = module->signatureIndexFromFunctionIndexSpace(exp.kindIndex); 364 const Wasm::Signature& signature = Wasm::SignatureInformation::get(signatureIndex); 365 WebAssemblyFunction* function = WebAssemblyFunction::create(vm, globalObject, globalObject->webAssemblyFunctionStructure(), signature.argumentCount(), String::fromUTF8(exp.field), m_instance.get(), embedderEntrypointCallee, entrypointLoadLocation, signatureIndex); 366 exportedValue = function; 367 } 393 exportedValue = makeFunctionWrapper(String::fromUTF8(exp.field), exp.kindIndex); 394 ASSERT(exportedValue.isFunction(vm)); 395 ASSERT(makeFunctionWrapper(String::fromUTF8(exp.field), exp.kindIndex) == exportedValue); 368 396 break; 369 397 } … … 389 417 switch (global.type) { 390 418 case Wasm::Anyref: 391 // FIXME: We need to box wasm Funcrefs once they are supported here. 392 // <https://bugs.webkit.org/show_bug.cgi?id=198157> 419 case Wasm::Anyfunc: 393 420 exportedValue = JSValue::decode(m_instance->instance().loadI64Global(exp.kindIndex)); 394 421 break; -
trunk/Source/JavaScriptCore/wasm/wasm.json
r246139 r246504 12 12 "f32": { "type": "varint7", "value": -3, "b3type": "B3::Float" }, 13 13 "f64": { "type": "varint7", "value": -4, "b3type": "B3::Double" }, 14 "anyfunc": { "type": "varint7", "value": -16, "b3type": "B3:: Void" },14 "anyfunc": { "type": "varint7", "value": -16, "b3type": "B3::Int64" }, 15 15 "anyref": { "type": "varint7", "value": -17, "b3type": "B3::Int64" }, 16 16 "func": { "type": "varint7", "value": -32, "b3type": "B3::Void" }, 17 17 "void": { "type": "varint7", "value": -64, "b3type": "B3::Void" } 18 18 }, 19 "value_type": ["i32", "i64", "f32", "f64", "anyref" ],20 "block_type": ["i32", "i64", "f32", "f64", "void", "anyref" ],19 "value_type": ["i32", "i64", "f32", "f64", "anyref", "anyfunc"], 20 "block_type": ["i32", "i64", "f32", "f64", "void", "anyref", "anyfunc"], 21 21 "elem_type": ["anyfunc","anyref"], 22 22 "external_kind": { … … 60 60 "f64.const": { "category": "special", "value": 68, "return": ["f64"], "parameter": [], "immediate": [{"name": "value", "type": "double"}], "description": "a constant value interpreted as f64" }, 61 61 "f32.const": { "category": "special", "value": 67, "return": ["f32"], "parameter": [], "immediate": [{"name": "value", "type": "float"}], "description": "a constant value interpreted as f32" }, 62 "ref.null": { "category": "special", "value": 208, "return": ["any ref"],"parameter": [], "immediate": [], "description": "a constant null reference" },62 "ref.null": { "category": "special", "value": 208, "return": ["anyfunc"], "parameter": [], "immediate": [], "description": "a constant null reference" }, 63 63 "ref.is_null": { "category": "special", "value": 209, "return": ["i32"], "parameter": ["anyref"], "immediate": [], "description": "determine if a reference is null" }, 64 "ref.func": { "category": "special", "value": 210, "return": ["anyfunc"], "parameter": [], "immediate": [{"name": "function_index", "type": "varuint32"}], "description": "return a reference to the function at the given index" }, 64 65 "get_local": { "category": "special", "value": 32, "return": ["any"], "parameter": [], "immediate": [{"name": "local_index", "type": "varuint32"}], "description": "read a local variable or parameter" }, 65 66 "set_local": { "category": "special", "value": 33, "return": [], "parameter": ["any"], "immediate": [{"name": "local_index", "type": "varuint32"}], "description": "write a local variable or parameter" },
Note: See TracChangeset
for help on using the changeset viewer.