Changeset 270855 in webkit
- Timestamp:
- Dec 15, 2020 11:15:33 AM (19 months ago)
- Location:
- trunk
- Files:
-
- 2 added
- 19 edited
-
JSTests/ChangeLog (modified) (1 diff)
-
JSTests/wasm.yaml (modified) (1 diff)
-
JSTests/wasm/references-spec-tests/memory_fill.wast.js (added)
-
JSTests/wasm/references/memory_fill_shared.js (added)
-
JSTests/wasm/references/table_instructions_parse_unreachable.js (modified) (2 diffs)
-
JSTests/wasm/wasm.json (modified) (1 diff)
-
Source/JavaScriptCore/ChangeLog (modified) (1 diff)
-
Source/JavaScriptCore/bytecode/BytecodeList.rb (modified) (1 diff)
-
Source/JavaScriptCore/interpreter/Register.h (modified) (2 diffs)
-
Source/JavaScriptCore/llint/WebAssembly.asm (modified) (1 diff)
-
Source/JavaScriptCore/wasm/WasmAirIRGenerator.cpp (modified) (2 diffs)
-
Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp (modified) (2 diffs)
-
Source/JavaScriptCore/wasm/WasmFunctionParser.h (modified) (4 diffs)
-
Source/JavaScriptCore/wasm/WasmLLIntGenerator.cpp (modified) (2 diffs)
-
Source/JavaScriptCore/wasm/WasmMemory.cpp (modified) (2 diffs)
-
Source/JavaScriptCore/wasm/WasmMemory.h (modified) (1 diff)
-
Source/JavaScriptCore/wasm/WasmOperations.cpp (modified) (1 diff)
-
Source/JavaScriptCore/wasm/WasmOperations.h (modified) (1 diff)
-
Source/JavaScriptCore/wasm/WasmSlowPaths.cpp (modified) (1 diff)
-
Source/JavaScriptCore/wasm/WasmSlowPaths.h (modified) (1 diff)
-
Source/JavaScriptCore/wasm/wasm.json (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
trunk/JSTests/ChangeLog
r270827 r270855 1 2020-12-15 Dmitry Bezhetskov <dbezhetskov@igalia.com> 2 3 [WASM-References] Add support for memory.fill 4 https://bugs.webkit.org/show_bug.cgi?id=219848 5 6 Reviewed by Yusuke Suzuki. 7 8 Added spec tests and unreachable tests for memory.fill. 9 10 * wasm.yaml: 11 * wasm/references-spec-tests/memory_fill.wast.js: Added. 12 * wasm/references/memory_fill_shared.js: Added. 13 (async test): 14 * wasm/references/table_instructions_parse_unreachable.js: 15 (invalidMemoryFillUnreachable): 16 * wasm/wasm.json: 17 1 18 2020-12-15 Dmitry Bezhetskov <dbezhetskov@igalia.com> 2 19 -
trunk/JSTests/wasm.yaml
r270827 r270855 57 57 - path: wasm/references-spec-tests/select.wast.js 58 58 cmd: runWebAssemblyReferenceSpecTest :normal 59 - path: wasm/references-spec-tests/memory_fill.wast.js 60 cmd: runWebAssemblyReferenceSpecTest :normal 59 61 60 62 - path: wasm/multi-value-spec-tests/block.wast.js -
trunk/JSTests/wasm/references/table_instructions_parse_unreachable.js
r270827 r270855 254 254 } 255 255 256 function validMemoryFillUnreachable() { 257 /* 258 (module 259 (memory $mem0 1) 260 (func (export "run") 261 (return) 262 (memory.fill (i32.const 0) (i32.const 11) (i32.const 3)) 263 ) 264 ) 265 */ 266 let instance = new WebAssembly.Instance(module("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x04\x01\x60\x00\x00\x03\x02\x01\x00\x05\x03\x01\x00\x01\x07\x07\x01\x03\x72\x75\x6e\x00\x00\x0a\x0e\x01\x0c\x00\x0f\x41\x00\x41\x0b\x41\x03\xfc\x0b\x00\x0b")); 267 instance.exports.run(); 268 } 269 270 function invalidMemoryFillUnreachable() { 271 /* 272 (module 273 (memory $mem0 1) 274 (func (export "run") 275 (return) 276 (memory.fill (unused = 1) (i32.const 0) (i32.const 11) (i32.const 3)) 277 ) 278 ) 279 */ 280 assert.throws(() => module("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x04\x01\x60\x00\x00\x03\x02\x01\x00\x05\x03\x01\x00\x01\x07\x07\x01\x03\x72\x75\x6e\x00\x00\x0a\x0e\x01\x0c\x00\x0f\x41\x00\x41\x0b\x41\x03\xfc\x0b\x01\x0b"), 281 WebAssembly.CompileError, 282 "WebAssembly.Module doesn't parse at byte 11: auxiliary byte for memory.fill should be zero, but got 1, in function at index 0 (evaluating 'new WebAssembly.Module(buffer)')"); 283 } 284 256 285 validTableInitUnreachable(); 257 286 invalidTableInitUnreachable(); … … 274 303 validAnnotatedSelectUnreachable(); 275 304 invalidAnnotatedSelectUnreachable(); 305 306 validMemoryFillUnreachable(); 307 invalidMemoryFillUnreachable(); -
trunk/JSTests/wasm/wasm.json
r270827 r270855 79 79 "table.fill": { "category": "exttable", "value": 252, "return": [], "parameter": ["i32", "externref", "i32"], "immediate": [{"name": "table_index", "type": "varuint32"}], "description": "fill entries [i,i+n) with the given value", "extendedOp": 17 }, 80 80 "table.copy": { "category": "exttable", "value": 252, "return": [], "parameter": ["i32", "i32", "i32"], "immediate": [{"name": "dst_index", "type": "varuint32"}, {"name": "src_index", "type": "varuint32"}],"description": "copy table elements from dst_table[dstOffset, dstOffset + length] to src_table[srcOffset, srcOffset + length]", "extendedOp": 14 }, 81 "memory.fill": { "category": "exttable", "value": 252, "return": [], "parameter": ["i32", "i32", "i32"], "immediate": [{"name": "unused", "type": "uint8"}], "description": "sets all values in a region to a given byte", "extendedOp": 11 }, 81 82 "call": { "category": "call", "value": 16, "return": ["call"], "parameter": ["call"], "immediate": [{"name": "function_index", "type": "varuint32"}], "description": "call a function by its index" }, 82 83 "call_indirect": { "category": "call", "value": 17, "return": ["call"], "parameter": ["call"], "immediate": [{"name": "type_index", "type": "varuint32"}, {"name": "table_index","type": "varuint32"}],"description": "call a function indirect with an expected signature" }, -
trunk/Source/JavaScriptCore/ChangeLog
r270827 r270855 1 2020-12-15 Dmitry Bezhetskov <dbezhetskov@igalia.com> 2 3 [WASM-References] Add support for memory.fill 4 https://bugs.webkit.org/show_bug.cgi?id=219848 5 6 Reviewed by Yusuke Suzuki. 7 8 Add support for memory.fill from ref-types spec. 9 memory.fill sets all bytes in a memory region to a given byte: 10 https://webassembly.github.io/reference-types/core/syntax/instructions.html#memory-instructions. 11 12 * bytecode/BytecodeList.rb: 13 * llint/WebAssembly.asm: 14 * wasm/WasmAirIRGenerator.cpp: 15 (JSC::Wasm::AirIRGenerator::addMemoryFill): 16 * wasm/WasmB3IRGenerator.cpp: 17 (JSC::Wasm::B3IRGenerator::addMemoryFill): 18 * wasm/WasmFunctionParser.h: 19 (JSC::Wasm::FunctionParser<Context>::parseMemoryFillImmediate): 20 (JSC::Wasm::FunctionParser<Context>::parseExpression): 21 (JSC::Wasm::FunctionParser<Context>::parseUnreachableExpression): 22 * wasm/WasmLLIntGenerator.cpp: 23 (JSC::Wasm::LLIntGenerator::addMemoryFill): 24 * wasm/WasmMemory.cpp: 25 (JSC::Wasm::Memory::fill): 26 (JSC::Wasm::Memory::doMemoryFill): 27 * wasm/WasmMemory.h: 28 * wasm/WasmOperations.cpp: 29 (JSC::Wasm::JSC_DEFINE_JIT_OPERATION): 30 * wasm/WasmOperations.h: 31 * wasm/WasmSlowPaths.cpp: 32 (JSC::LLInt::WASM_SLOW_PATH_DECL): 33 * wasm/WasmSlowPaths.h: 34 * wasm/wasm.json: 35 1 36 2020-12-15 Dmitry Bezhetskov <dbezhetskov@igalia.com> 2 37 -
trunk/Source/JavaScriptCore/bytecode/BytecodeList.rb
r270689 r270855 1676 1676 } 1677 1677 1678 op :memory_fill, 1679 args: { 1680 dstAddress: VirtualRegister, 1681 targetValue: VirtualRegister, 1682 count: VirtualRegister, 1683 } 1684 1678 1685 op :select, 1679 1686 args: { -
trunk/Source/JavaScriptCore/interpreter/Register.h
r270208 r270855 64 64 ALWAYS_INLINE JSScope* scope() const; 65 65 int32_t unboxedInt32() const; 66 uint32_t unboxedUInt32() const; 66 67 int32_t asanUnsafeUnboxedInt32() const; 67 68 int64_t unboxedInt52() const; … … 143 144 } 144 145 146 ALWAYS_INLINE uint32_t Register::unboxedUInt32() const 147 { 148 return static_cast<uint32_t>(unboxedInt32()); 149 } 150 145 151 SUPPRESS_ASAN ALWAYS_INLINE int32_t Register::asanUnsafeUnboxedInt32() const 146 152 { -
trunk/Source/JavaScriptCore/llint/WebAssembly.asm
r270689 r270855 568 568 slowWasmOp(table_copy) 569 569 slowWasmOp(table_grow) 570 slowWasmOp(memory_fill) 570 571 slowWasmOp(set_global_ref) 571 572 slowWasmOp(set_global_ref_portable_binding) -
trunk/Source/JavaScriptCore/wasm/WasmAirIRGenerator.cpp
r270689 r270855 281 281 PartialResult WARN_UNUSED_RETURN addGrowMemory(ExpressionType delta, ExpressionType& result); 282 282 PartialResult WARN_UNUSED_RETURN addCurrentMemory(ExpressionType& result); 283 PartialResult WARN_UNUSED_RETURN addMemoryFill(ExpressionType dstAddress, ExpressionType targetValue, ExpressionType count); 283 284 284 285 // Atomics … … 1271 1272 addShift(Type::I32, Urshift64, temp1, temp2, result); 1272 1273 append(Move32, result, result); 1274 1275 return { }; 1276 } 1277 1278 auto AirIRGenerator::addMemoryFill(ExpressionType dstAddress, ExpressionType targetValue, ExpressionType count) -> PartialResult 1279 { 1280 ASSERT(dstAddress.tmp()); 1281 ASSERT(dstAddress.type() == Type::I32); 1282 1283 ASSERT(targetValue.tmp()); 1284 ASSERT(targetValue.type() == Type::I32); 1285 1286 ASSERT(count.tmp()); 1287 ASSERT(count.type() == Type::I32); 1288 1289 auto result = tmpForType(Type::I32); 1290 emitCCall( 1291 &operationWasmMemoryFill, result, instanceValue(), 1292 dstAddress, targetValue, count); 1293 1294 emitCheck([&] { 1295 return Inst(BranchTest32, nullptr, Arg::resCond(MacroAssembler::Zero), result, result); 1296 }, [=] (CCallHelpers& jit, const B3::StackmapGenerationParams&) { 1297 this->emitThrowException(jit, ExceptionType::OutOfBoundsTableAccess); 1298 }); 1273 1299 1274 1300 return { }; -
trunk/Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp
r270689 r270855 236 236 PartialResult WARN_UNUSED_RETURN addGrowMemory(ExpressionType delta, ExpressionType& result); 237 237 PartialResult WARN_UNUSED_RETURN addCurrentMemory(ExpressionType& result); 238 PartialResult WARN_UNUSED_RETURN addMemoryFill(ExpressionType dstAddress, ExpressionType targetValue, ExpressionType count); 238 239 239 240 // Atomics … … 880 881 881 882 result = m_currentBlock->appendNew<Value>(m_proc, Trunc, origin(), numPages); 883 884 return { }; 885 } 886 887 auto B3IRGenerator::addMemoryFill(ExpressionType dstAddress, ExpressionType targetValue, ExpressionType count) -> PartialResult 888 { 889 auto result = m_currentBlock->appendNew<CCallValue>( 890 m_proc, toB3Type(I32), origin(), 891 m_currentBlock->appendNew<ConstPtrValue>(m_proc, origin(), tagCFunction<OperationPtrTag>(operationWasmMemoryFill)), 892 instanceValue(), 893 dstAddress, targetValue, count); 894 895 { 896 CheckValue* check = m_currentBlock->appendNew<CheckValue>(m_proc, Check, origin(), 897 m_currentBlock->appendNew<Value>(m_proc, Equal, origin(), result, m_currentBlock->appendNew<Const32Value>(m_proc, origin(), 0))); 898 899 check->setGenerator([=] (CCallHelpers& jit, const B3::StackmapGenerationParams&) { 900 this->emitExceptionCheck(jit, ExceptionType::OutOfBoundsTableAccess); 901 }); 902 } 882 903 883 904 return { }; -
trunk/Source/JavaScriptCore/wasm/WasmFunctionParser.h
r270827 r270855 157 157 PartialResult WARN_UNUSED_RETURN parseAnnotatedSelectImmediates(AnnotatedSelectImmediates&); 158 158 159 PartialResult WARN_UNUSED_RETURN parseMemoryFillImmediate(); 160 159 161 #define WASM_TRY_ADD_TO_CONTEXT(add_expression) WASM_FAIL_IF_HELPER_FAILS(m_context.add_expression) 160 162 … … 565 567 result.sizeOfAnnotationVector = sizeOfAnnotationVector; 566 568 result.targetType = targetType; 567 569 return { }; 570 } 571 572 template<typename Context> 573 auto FunctionParser<Context>::parseMemoryFillImmediate() -> PartialResult 574 { 575 uint8_t auxiliaryByte; 576 WASM_PARSER_FAIL_IF(!parseUInt8(auxiliaryByte), "can't parse auxiliary byte"); 577 WASM_PARSER_FAIL_IF(!!auxiliaryByte, "auxiliary byte for memory.fill should be zero, but got ", auxiliaryByte); 568 578 return { }; 569 579 } … … 816 826 817 827 WASM_TRY_ADD_TO_CONTEXT(addTableCopy(immediates.dstTableIndex, immediates.srcTableIndex, dstOffset, srcOffset, length)); 828 break; 829 } 830 case ExtTableOpType::MemoryFill: { 831 WASM_FAIL_IF_HELPER_FAILS(parseMemoryFillImmediate()); 832 833 WASM_VALIDATOR_FAIL_IF(!m_info.memoryCount(), "memory must be present"); 834 835 TypedExpression dstAddress; 836 TypedExpression targetValue; 837 TypedExpression count; 838 839 WASM_TRY_POP_EXPRESSION_STACK_INTO(count, "memory.fill"); 840 WASM_TRY_POP_EXPRESSION_STACK_INTO(targetValue, "memory.fill"); 841 WASM_TRY_POP_EXPRESSION_STACK_INTO(dstAddress, "memory.fill"); 842 843 WASM_VALIDATOR_FAIL_IF(I32 != dstAddress.type(), "memory.fill dstAddress to type ", dstAddress.type(), " expected ", I32); 844 WASM_VALIDATOR_FAIL_IF(I32 != targetValue.type(), "memory.fill targetValue to type ", targetValue.type(), " expected ", I32); 845 WASM_VALIDATOR_FAIL_IF(I32 != count.type(), "memory.fill size to type ", count.type(), " expected ", I32); 846 847 WASM_TRY_ADD_TO_CONTEXT(addMemoryFill(dstAddress, targetValue, count)); 818 848 break; 819 849 } … … 1386 1416 return { }; 1387 1417 } 1418 case ExtTableOpType::MemoryFill: { 1419 WASM_FAIL_IF_HELPER_FAILS(parseMemoryFillImmediate()); 1420 return { }; 1421 } 1388 1422 default: 1389 1423 WASM_PARSER_FAIL_IF(true, "invalid extended table op ", extOp); -
trunk/Source/JavaScriptCore/wasm/WasmLLIntGenerator.cpp
r270689 r270855 212 212 PartialResult WARN_UNUSED_RETURN addGrowMemory(ExpressionType delta, ExpressionType& result); 213 213 PartialResult WARN_UNUSED_RETURN addCurrentMemory(ExpressionType& result); 214 PartialResult WARN_UNUSED_RETURN addMemoryFill(ExpressionType dstAddress, ExpressionType targetValue, ExpressionType count); 214 215 215 216 // Atomics … … 1188 1189 } 1189 1190 1191 auto LLIntGenerator::addMemoryFill(ExpressionType dstAddress, ExpressionType targetValue, ExpressionType count) -> PartialResult 1192 { 1193 WasmMemoryFill::emit(this, dstAddress, targetValue, count); 1194 return { }; 1195 } 1196 1190 1197 auto LLIntGenerator::addSelect(ExpressionType condition, ExpressionType nonZero, ExpressionType zero, ExpressionType& result) -> PartialResult 1191 1198 { -
trunk/Source/JavaScriptCore/wasm/WasmMemory.cpp
r269974 r270855 31 31 32 32 #include "Options.h" 33 #include <wtf/CheckedArithmetic.h> 33 34 #include <wtf/DataLog.h> 34 35 #include <wtf/Gigacage.h> … … 618 619 } 619 620 621 bool Memory::fill(uint32_t offset, uint8_t targetValue, uint32_t count) 622 { 623 if (sumOverflows<uint32_t>(offset, count)) 624 return false; 625 626 if (offset + count > m_handle->size()) 627 return false; 628 629 memset(reinterpret_cast<uint8_t*>(memory()) + offset, targetValue, count); 630 return true; 631 } 632 620 633 void Memory::registerInstance(Instance* instance) 621 634 { -
trunk/Source/JavaScriptCore/wasm/WasmMemory.h
r270208 r270855 133 133 }; 134 134 Expected<PageCount, GrowFailReason> grow(PageCount); 135 bool fill(uint32_t, uint8_t, uint32_t); 135 136 void registerInstance(Instance*); 136 137 -
trunk/Source/JavaScriptCore/wasm/WasmOperations.cpp
r270689 r270855 639 639 } 640 640 641 JSC_DEFINE_JIT_OPERATION(operationWasmMemoryFill, bool, (Instance* instance, uint32_t dstAddress, uint32_t targetValue, uint32_t count)) 642 { 643 return instance->memory()->fill(dstAddress, static_cast<uint8_t>(targetValue), count); 644 } 645 641 646 JSC_DEFINE_JIT_OPERATION(operationGetWasmTableElement, EncodedJSValue, (Instance* instance, unsigned tableIndex, int32_t signedIndex)) 642 647 { -
trunk/Source/JavaScriptCore/wasm/WasmOperations.h
r270689 r270855 62 62 JSC_DECLARE_JIT_OPERATION(operationPopcount64, uint64_t, (int64_t)); 63 63 JSC_DECLARE_JIT_OPERATION(operationGrowMemory, int32_t, (void*, Instance*, int32_t)); 64 JSC_DECLARE_JIT_OPERATION(operationWasmMemoryFill, bool, (Instance*, uint32_t dstAddress, uint32_t targetValue, uint32_t count)); 64 65 65 66 JSC_DECLARE_JIT_OPERATION(operationGetWasmTableElement, EncodedJSValue, (Instance*, unsigned, int32_t)); -
trunk/Source/JavaScriptCore/wasm/WasmSlowPaths.cpp
r270689 r270855 380 380 } 381 381 382 WASM_SLOW_PATH_DECL(memory_fill) 383 { 384 auto instruction = pc->as<WasmMemoryFill, WasmOpcodeTraits>(); 385 uint32_t dstAddress = READ(instruction.m_dstAddress).unboxedUInt32(); 386 uint32_t targetValue = READ(instruction.m_targetValue).unboxedUInt32(); 387 uint32_t count = READ(instruction.m_count).unboxedUInt32(); 388 if (!Wasm::operationWasmMemoryFill(instance, dstAddress, targetValue, count)) 389 WASM_THROW(Wasm::ExceptionType::OutOfBoundsTableAccess); 390 WASM_END(); 391 } 392 382 393 inline SlowPathReturnType doWasmCall(Wasm::Instance* instance, unsigned functionIndex) 383 394 { -
trunk/Source/JavaScriptCore/wasm/WasmSlowPaths.h
r270689 r270855 67 67 WASM_SLOW_PATH_HIDDEN_DECL(table_grow); 68 68 WASM_SLOW_PATH_HIDDEN_DECL(grow_memory); 69 WASM_SLOW_PATH_HIDDEN_DECL(memory_fill); 69 70 WASM_SLOW_PATH_HIDDEN_DECL(call); 70 71 WASM_SLOW_PATH_HIDDEN_DECL(call_no_tls); -
trunk/Source/JavaScriptCore/wasm/wasm.json
r270827 r270855 79 79 "table.fill": { "category": "exttable", "value": 252, "return": [], "parameter": ["i32", "externref", "i32"], "immediate": [{"name": "table_index", "type": "varuint32"}], "description": "fill entries [i,i+n) with the given value", "extendedOp": 17 }, 80 80 "table.copy": { "category": "exttable", "value": 252, "return": [], "parameter": ["i32", "i32", "i32"], "immediate": [{"name": "dst_index", "type": "varuint32"}, {"name": "src_index", "type": "varuint32"}],"description": "copy table elements from dst_table[dstOffset, dstOffset + length] to src_table[srcOffset, srcOffset + length]", "extendedOp": 14 }, 81 "memory.fill": { "category": "exttable", "value": 252, "return": [], "parameter": ["i32", "i32", "i32"], "immediate": [{"name": "unused", "type": "uint8"}], "description": "sets all values in a region to a given byte", "extendedOp": 11 }, 81 82 "call": { "category": "call", "value": 16, "return": ["call"], "parameter": ["call"], "immediate": [{"name": "function_index", "type": "varuint32"}], "description": "call a function by its index" }, 82 83 "call_indirect": { "category": "call", "value": 17, "return": ["call"], "parameter": ["call"], "immediate": [{"name": "type_index", "type": "varuint32"}, {"name": "table_index","type": "varuint32"}],"description": "call a function indirect with an expected signature" },
Note: See TracChangeset
for help on using the changeset viewer.