Changeset 207453 in webkit
- Timestamp:
- Oct 17, 2016 7:02:48 PM (8 years ago)
- Location:
- trunk
- Files:
-
- 2 added
- 18 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JSTests/ChangeLog
r207433 r207453 1 2016-10-17 Keith Miller <keith_miller@apple.com> 2 3 Add support for WASM Memory. 4 https://bugs.webkit.org/show_bug.cgi?id=161710 5 6 Reviewed by Geoffrey Garen. 7 8 Add store and load opcodes to wasm.json. Additionally, add new 9 enums for those opcodes in the generator. 10 11 * stress/wasm/generate-wasmops-header.js: 12 (const.template.pragma.once.ENABLE.WEBASSEMBLY.include.cstdint.namespace.JSC.namespace.WASM.enum.LoadOpType): 13 (const.template.pragma.once.ENABLE.WEBASSEMBLY.include.cstdint.namespace.JSC.namespace.WASM.enum.StoreOpType): 14 1 15 2016-10-17 Saam Barati <sbarati@apple.com> 2 16 -
trunk/JSTests/wasm/generate-wasmops-header.js
r207363 r207453 37 37 "\n\n#define FOR_EACH_WASM_BINARY_OP(macro)", 38 38 ...opcodeMacroizer(op => (op.category === "arithmetic" || op.category === "comparison") && op.parameter.length === 2), 39 "\n\n#define FOR_EACH_WASM_MEMORY_LOAD_OP(macro)", 40 ...opcodeMacroizer(op => (op.category === "memory" && op.return.length === 1)), 41 "\n\n#define FOR_EACH_WASM_MEMORY_STORE_OP(macro)", 42 ...opcodeMacroizer(op => (op.category === "memory" && op.return.length === 0)), 39 43 "\n\n"].join(""); 40 44 … … 95 99 FOR_EACH_WASM_CONTROL_FLOW_OP(macro) \\ 96 100 FOR_EACH_WASM_UNARY_OP(macro) \\ 97 FOR_EACH_WASM_BINARY_OP(macro) 101 FOR_EACH_WASM_BINARY_OP(macro) \\ 102 FOR_EACH_WASM_MEMORY_LOAD_OP(macro) \\ 103 FOR_EACH_WASM_MEMORY_STORE_OP(macro) 98 104 99 105 #define CREATE_ENUM_VALUE(name, id, b3op) name = id, … … 119 125 }; 120 126 127 enum class LoadOpType : uint8_t { 128 FOR_EACH_WASM_MEMORY_LOAD_OP(CREATE_ENUM_VALUE) 129 }; 130 131 enum class StoreOpType : uint8_t { 132 FOR_EACH_WASM_MEMORY_STORE_OP(CREATE_ENUM_VALUE) 133 }; 134 121 135 #undef CREATE_ENUM_VALUE 122 136 -
trunk/Source/JavaScriptCore/CMakeLists.txt
r207434 r207453 864 864 wasm/WASMB3IRGenerator.cpp 865 865 wasm/WASMCallingConvention.cpp 866 wasm/WASMMemory.cpp 866 867 wasm/WASMModuleParser.cpp 867 868 wasm/WASMPlan.cpp -
trunk/Source/JavaScriptCore/ChangeLog
r207444 r207453 1 2016-10-17 Keith Miller <keith_miller@apple.com> 2 3 Add support for WASM Memory. 4 https://bugs.webkit.org/show_bug.cgi?id=161710 5 6 Reviewed by Geoffrey Garen. 7 8 This patch add initial support for WASM memory operations. First, 9 it adds the concept of a WASM Module memory management object. 10 This object currently mmaps a 32-bit address space for WASM use, 11 although it marks all the memory outside the current breakpoint as 12 PROT_NONE. For now, we do a range check on each store and load. In 13 the future, we should change this to be an signal handler that 14 checks what module the program trapped in. 15 16 Additionally, this patch changes the way that our temporary tests 17 call into WASM code. There is now a true "thunk" that relocates 18 arguments and calls into WASM. This thunk does not tail call 19 because we use pinned values to memory base-pointer and 20 size. We use the new B3 pinned register api to pin the values. 21 22 * CMakeLists.txt: 23 * Configurations/ToolExecutable.xcconfig: 24 * JavaScriptCore.xcodeproj/project.pbxproj: 25 * testWASM.cpp: 26 (runWASMTests): 27 (main): 28 * wasm/WASMB3IRGenerator.cpp: 29 (JSC::WASM::createJSWrapper): 30 (JSC::WASM::parseAndCompile): 31 * wasm/WASMB3IRGenerator.h: 32 * wasm/WASMCallingConvention.h: 33 (JSC::WASM::CallingConvention::iterate): 34 (JSC::WASM::CallingConvention::setupCall): 35 (JSC::WASM::nextJSCOffset): 36 * wasm/WASMFormat.h: 37 * wasm/WASMFunctionParser.h: 38 (JSC::WASM::FunctionParser<Context>::parseExpression): 39 * wasm/WASMMemory.cpp: Copied from Source/JavaScriptCore/wasm/WASMPlan.cpp. 40 (JSC::WASM::Memory::Memory): 41 * wasm/WASMMemory.h: Copied from Source/JavaScriptCore/wasm/WASMModuleParser.h. 42 (JSC::WASM::Memory::~Memory): 43 (JSC::WASM::Memory::memory): 44 (JSC::WASM::Memory::size): 45 (JSC::WASM::Memory::pinnedRegisters): 46 (JSC::WASM::Memory::mode): 47 (JSC::WASM::Memory::growMemory): 48 (JSC::WASM::Memory::offsetOfSize): 49 * wasm/WASMModuleParser.cpp: 50 (JSC::WASM::ModuleParser::parse): 51 (JSC::WASM::ModuleParser::parseMemory): 52 * wasm/WASMModuleParser.h: 53 (JSC::WASM::ModuleParser::functionInformation): 54 (JSC::WASM::ModuleParser::memory): 55 * wasm/WASMOps.h: 56 * wasm/WASMPlan.cpp: 57 (JSC::WASM::Plan::Plan): 58 * wasm/WASMPlan.h: 59 * wasm/WASMSections.h: 60 1 61 2016-10-17 Joseph Pecoraro <pecoraro@apple.com> 2 62 -
trunk/Source/JavaScriptCore/Configurations/ToolExecutable.xcconfig
r202287 r207453 32 32 CODE_SIGN_ENTITLEMENTS_ios_testapi = entitlements.plist; 33 33 CODE_SIGN_ENTITLEMENTS_ios_testb3 = entitlements.plist; 34 CODE_SIGN_ENTITLEMENTS_ios_testWASM = entitlements.plist; 34 35 CODE_SIGN_ENTITLEMENTS_ios_testRegExp = entitlements.plist; 35 36 -
trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
r207434 r207453 1217 1217 534C457E1BC72549007476A7 /* JSTypedArrayViewConstructor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 534C457D1BC72549007476A7 /* JSTypedArrayViewConstructor.cpp */; }; 1218 1218 53529A4C1C457B75000B49C6 /* APIUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = 53529A4B1C457B75000B49C6 /* APIUtils.h */; }; 1219 535557141D9D9EA5006D583B /* WASMMemory.h in Headers */ = {isa = PBXBuildFile; fileRef = 535557131D9D9EA5006D583B /* WASMMemory.h */; }; 1220 535557161D9DFA32006D583B /* WASMMemory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 535557151D9DFA32006D583B /* WASMMemory.cpp */; }; 1219 1221 5370B4F51BF26202005C40FC /* AdaptiveInferredPropertyValueWatchpointBase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5370B4F31BF25EA2005C40FC /* AdaptiveInferredPropertyValueWatchpointBase.cpp */; }; 1220 1222 5370B4F61BF26205005C40FC /* AdaptiveInferredPropertyValueWatchpointBase.h in Headers */ = {isa = PBXBuildFile; fileRef = 5370B4F41BF25EA2005C40FC /* AdaptiveInferredPropertyValueWatchpointBase.h */; }; … … 3464 3466 534C457D1BC72549007476A7 /* JSTypedArrayViewConstructor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSTypedArrayViewConstructor.cpp; sourceTree = "<group>"; }; 3465 3467 53529A4B1C457B75000B49C6 /* APIUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = APIUtils.h; sourceTree = "<group>"; }; 3468 535557131D9D9EA5006D583B /* WASMMemory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WASMMemory.h; sourceTree = "<group>"; }; 3469 535557151D9DFA32006D583B /* WASMMemory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WASMMemory.cpp; sourceTree = "<group>"; }; 3466 3470 5370B4F31BF25EA2005C40FC /* AdaptiveInferredPropertyValueWatchpointBase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AdaptiveInferredPropertyValueWatchpointBase.cpp; sourceTree = "<group>"; }; 3467 3471 5370B4F41BF25EA2005C40FC /* AdaptiveInferredPropertyValueWatchpointBase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AdaptiveInferredPropertyValueWatchpointBase.h; sourceTree = "<group>"; }; … … 5700 5704 7BC547D21B69599B00959B58 /* WASMFormat.h */, 5701 5705 53F40E8A1D5901BB0099A1B6 /* WASMFunctionParser.h */, 5706 535557151D9DFA32006D583B /* WASMMemory.cpp */, 5707 535557131D9D9EA5006D583B /* WASMMemory.h */, 5702 5708 53F40E961D5A7BEC0099A1B6 /* WASMModuleParser.cpp */, 5703 5709 53F40E941D5A7AEF0099A1B6 /* WASMModuleParser.h */, … … 7872 7878 1478297B1379E8A800A7C2A3 /* HandleTypes.h in Headers */, 7873 7879 0F10F1A31C420BF0001C07D2 /* AirCustom.h in Headers */, 7880 535557141D9D9EA5006D583B /* WASMMemory.h in Headers */, 7874 7881 14BA7A9813AADFF8005B7C2C /* Heap.h in Headers */, 7875 7882 0F32BD111BB34F190093A57F /* HeapHelperPool.h in Headers */, … … 9214 9221 0FD3C82614115D4000FD81CB /* DFGDriver.cpp in Sources */, 9215 9222 0FF0F19E16B72A0B005DF95B /* DFGEdge.cpp in Sources */, 9223 535557161D9DFA32006D583B /* WASMMemory.cpp in Sources */, 9216 9224 0F8F14331ADF090100ED792C /* DFGEpoch.cpp in Sources */, 9217 9225 0FBC0AE71496C7C400D4FBDD /* DFGExitProfile.cpp in Sources */, -
trunk/Source/JavaScriptCore/testWASM.cpp
r206110 r207453 33 33 #include "ProtoCallFrame.h" 34 34 #include "VM.h" 35 #include "WASMMemory.h" 35 36 #include "WASMPlan.h" 37 36 38 #include <wtf/DataLog.h> 37 39 #include <wtf/LEBDecoder.h> … … 243 245 { 244 246 // Generated from: 245 // (module 246 // (func (export "dumb-eq") (param $x i32) (param $y i32) (result i32) 247 // (module 248 // (memory 1) 249 // (func (export "i32_load8_s") (param $i i32) (param $ptr i32) (result i32) 250 // (i64.store (get_local $ptr) (get_local $i)) 251 // (return (i64.load (get_local $ptr))) 252 // ) 253 // ) 254 Vector<uint8_t> vector = { 255 0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x87, 0x80, 0x80, 0x80, 0x00, 0x01, 0x40, 256 0x02, 0x02, 0x01, 0x01, 0x02, 0x03, 0x82, 0x80, 0x80, 0x80, 0x00, 0x01, 0x00, 0x05, 0x83, 0x80, 257 0x80, 0x80, 0x00, 0x01, 0x01, 0x01, 0x07, 0x8f, 0x80, 0x80, 0x80, 0x00, 0x01, 0x0b, 0x69, 0x33, 258 0x32, 0x5f, 0x6c, 0x6f, 0x61, 0x64, 0x38, 0x5f, 0x73, 0x00, 0x00, 0x0a, 0x95, 0x80, 0x80, 0x80, 259 0x00, 0x01, 0x8f, 0x80, 0x80, 0x80, 0x00, 0x00, 0x14, 0x01, 0x14, 0x00, 0x34, 0x03, 0x00, 0x14, 260 0x01, 0x2b, 0x03, 0x00, 0x09, 0x0f 261 }; 262 263 Plan plan(*vm, vector); 264 if (plan.result.size() != 1 || !plan.result[0]) { 265 dataLogLn("Module failed to compile correctly."); 266 CRASH(); 267 } 268 269 // Test this doesn't crash. 270 CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(0), box(10) }), 0); 271 CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(100), box(2) }), 100); 272 CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(1), box(100) }), 1); 273 } 274 275 { 276 // Generated from: 277 // (module 278 // (memory 1) 279 // (func (export "i32_load8_s") (param $i i32) (param $ptr i32) (result i32) 280 // (i32.store (get_local $ptr) (get_local $i)) 281 // (return (i32.load (get_local $ptr))) 282 // ) 283 // ) 284 Vector<uint8_t> vector = { 285 0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x87, 0x80, 0x80, 0x80, 0x00, 0x01, 0x40, 286 0x02, 0x01, 0x01, 0x01, 0x01, 0x03, 0x82, 0x80, 0x80, 0x80, 0x00, 0x01, 0x00, 0x05, 0x83, 0x80, 287 0x80, 0x80, 0x00, 0x01, 0x01, 0x01, 0x07, 0x8f, 0x80, 0x80, 0x80, 0x00, 0x01, 0x0b, 0x69, 0x33, 288 0x32, 0x5f, 0x6c, 0x6f, 0x61, 0x64, 0x38, 0x5f, 0x73, 0x00, 0x00, 0x0a, 0x95, 0x80, 0x80, 0x80, 289 0x00, 0x01, 0x8f, 0x80, 0x80, 0x80, 0x00, 0x00, 0x14, 0x01, 0x14, 0x00, 0x33, 0x02, 0x00, 0x14, 290 0x01, 0x2a, 0x02, 0x00, 0x09, 0x0f 291 }; 292 293 Plan plan(*vm, vector); 294 if (plan.result.size() != 1 || !plan.result[0]) { 295 dataLogLn("Module failed to compile correctly."); 296 CRASH(); 297 } 298 299 // Test this doesn't crash. 300 CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(0), box(10) }), 0); 301 CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(100), box(2) }), 100); 302 CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(1), box(100) }), 1); 303 } 304 305 { 306 // Generated from: 307 // (module 308 // (memory 1) 309 // (func (export "write_array") (param $x i32) (param $p i32) (param $length i32) (local $i i32) 310 // (set_local $i (i32.const 0)) 311 // (block 312 // (loop 313 // (br_if 1 (i32.ge_u (get_local $i) (get_local $length))) 314 // (i32.store (i32.add (get_local $p) (i32.mul (get_local $i) (i32.const 4))) (get_local $x)) 315 // (set_local $i (i32.add (i32.const 1) (get_local $i))) 316 // (br 0) 317 // ) 318 // ) 319 // (return) 320 // ) 321 // ) 322 Vector<uint8_t> vector = { 323 0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x87, 0x80, 0x80, 0x80, 0x00, 0x01, 0x40, 324 0x03, 0x01, 0x01, 0x01, 0x00, 0x03, 0x82, 0x80, 0x80, 0x80, 0x00, 0x01, 0x00, 0x05, 0x83, 0x80, 325 0x80, 0x80, 0x00, 0x01, 0x01, 0x01, 0x07, 0x8f, 0x80, 0x80, 0x80, 0x00, 0x01, 0x0b, 0x77, 0x72, 326 0x69, 0x74, 0x65, 0x5f, 0x61, 0x72, 0x72, 0x61, 0x79, 0x00, 0x00, 0x0a, 0xb2, 0x80, 0x80, 0x80, 327 0x00, 0x01, 0xac, 0x80, 0x80, 0x80, 0x00, 0x01, 0x01, 0x01, 0x10, 0x00, 0x15, 0x03, 0x01, 0x00, 328 0x02, 0x00, 0x14, 0x03, 0x14, 0x02, 0x56, 0x07, 0x01, 0x14, 0x01, 0x14, 0x03, 0x10, 0x04, 0x42, 329 0x40, 0x14, 0x00, 0x33, 0x02, 0x00, 0x10, 0x01, 0x14, 0x03, 0x40, 0x15, 0x03, 0x06, 0x00, 0x0f, 330 0x0f, 0x09, 0x0f 331 }; 332 333 Plan plan(*vm, vector); 334 if (plan.result.size() != 1 || !plan.result[0]) { 335 dataLogLn("Module failed to compile correctly."); 336 CRASH(); 337 } 338 ASSERT(plan.memory->size()); 339 340 // Test this doesn't crash. 341 unsigned length = 5; 342 unsigned offset = sizeof(uint32_t); 343 uint32_t* memory = static_cast<uint32_t*>(plan.memory->memory()); 344 invoke<void>(*plan.result[0]->jsEntryPoint, { box(100), box(offset), box(length) }); 345 offset /= sizeof(uint32_t); 346 CHECK_EQ(memory[offset - 1], 0u); 347 CHECK_EQ(memory[offset + length], 0u); 348 for (unsigned i = 0; i < length; ++i) 349 CHECK_EQ(memory[i + offset], 100u); 350 351 length = 10; 352 offset = 5 * sizeof(uint32_t); 353 invoke<void>(*plan.result[0]->jsEntryPoint, { box(5), box(offset), box(length) }); 354 offset /= sizeof(uint32_t); 355 CHECK_EQ(memory[offset - 1], 100u); 356 CHECK_EQ(memory[offset + length], 0u); 357 for (unsigned i = 0; i < length; ++i) 358 CHECK_EQ(memory[i + offset], 5u); 359 } 360 361 { 362 // Generated from: 363 // (module 364 // (memory 1) 365 // (func (export "write_array") (param $x i32) (param $p i32) (param $length i32) (local $i i32) 366 // (set_local $i (i32.const 0)) 367 // (block 368 // (loop 369 // (br_if 1 (i32.ge_u (get_local $i) (get_local $length))) 370 // (i32.store8 (i32.add (get_local $p) (get_local $i)) (get_local $x)) 371 // (set_local $i (i32.add (i32.const 1) (get_local $i))) 372 // (br 0) 373 // ) 374 // ) 375 // (return) 376 // ) 377 // ) 378 Vector<uint8_t> vector = { 379 0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x87, 0x80, 0x80, 0x80, 0x00, 0x01, 0x40, 380 0x03, 0x01, 0x01, 0x01, 0x00, 0x03, 0x82, 0x80, 0x80, 0x80, 0x00, 0x01, 0x00, 0x05, 0x83, 0x80, 381 0x80, 0x80, 0x00, 0x01, 0x01, 0x01, 0x07, 0x8f, 0x80, 0x80, 0x80, 0x00, 0x01, 0x0b, 0x77, 0x72, 382 0x69, 0x74, 0x65, 0x5f, 0x61, 0x72, 0x72, 0x61, 0x79, 0x00, 0x00, 0x0a, 0xaf, 0x80, 0x80, 0x80, 383 0x00, 0x01, 0xa9, 0x80, 0x80, 0x80, 0x00, 0x01, 0x01, 0x01, 0x10, 0x00, 0x15, 0x03, 0x01, 0x00, 384 0x02, 0x00, 0x14, 0x03, 0x14, 0x02, 0x56, 0x07, 0x01, 0x14, 0x01, 0x14, 0x03, 0x40, 0x14, 0x00, 385 0x2e, 0x00, 0x00, 0x10, 0x01, 0x14, 0x03, 0x40, 0x15, 0x03, 0x06, 0x00, 0x0f, 0x0f, 0x09, 0x0f 386 }; 387 388 Plan plan(*vm, vector); 389 if (plan.result.size() != 1 || !plan.result[0]) { 390 dataLogLn("Module failed to compile correctly."); 391 CRASH(); 392 } 393 ASSERT(plan.memory->size()); 394 395 // Test this doesn't crash. 396 unsigned length = 5; 397 unsigned offset = 1; 398 uint8_t* memory = static_cast<uint8_t*>(plan.memory->memory()); 399 invoke<void>(*plan.result[0]->jsEntryPoint, { box(100), box(offset), box(length) }); 400 CHECK_EQ(memory[offset - 1], 0u); 401 CHECK_EQ(memory[offset + length], 0u); 402 for (unsigned i = 0; i < length; ++i) 403 CHECK_EQ(memory[i + offset], 100u); 404 405 length = 10; 406 offset = 5; 407 invoke<void>(*plan.result[0]->jsEntryPoint, { box(5), box(offset), box(length) }); 408 CHECK_EQ(memory[offset - 1], 100u); 409 CHECK_EQ(memory[offset + length], 0u); 410 for (unsigned i = 0; i < length; ++i) 411 CHECK_EQ(memory[i + offset], 5u); 412 } 413 414 { 415 // Generated from: 416 // (module 417 // (memory 1) 418 // (func (export "i32_load8_s") (param $i i32) (param $ptr i32) (result i32) 419 // (i32.store8 (get_local $ptr) (get_local $i)) 420 // (return (i32.load8_s (get_local $ptr))) 421 // ) 422 // ) 423 Vector<uint8_t> vector = { 424 0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x87, 0x80, 0x80, 0x80, 0x00, 0x01, 0x40, 425 0x02, 0x01, 0x01, 0x01, 0x01, 0x03, 0x82, 0x80, 0x80, 0x80, 0x00, 0x01, 0x00, 0x05, 0x83, 0x80, 426 0x80, 0x80, 0x00, 0x01, 0x01, 0x01, 0x07, 0x8f, 0x80, 0x80, 0x80, 0x00, 0x01, 0x0b, 0x69, 0x33, 427 0x32, 0x5f, 0x6c, 0x6f, 0x61, 0x64, 0x38, 0x5f, 0x73, 0x00, 0x00, 0x0a, 0x95, 0x80, 0x80, 0x80, 428 0x00, 0x01, 0x8f, 0x80, 0x80, 0x80, 0x00, 0x00, 0x14, 0x01, 0x14, 0x00, 0x2e, 0x00, 0x00, 0x14, 429 0x01, 0x20, 0x00, 0x00, 0x09, 0x0f 430 }; 431 432 Plan plan(*vm, vector); 433 if (plan.result.size() != 1 || !plan.result[0]) { 434 dataLogLn("Module failed to compile correctly."); 435 CRASH(); 436 } 437 ASSERT(plan.memory->size()); 438 439 // Test this doesn't crash. 440 CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(0), box(10) }), 0); 441 CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(100), box(2) }), 100); 442 CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(1), box(100) }), 1); 443 } 444 445 { 446 // Generated from: 447 // (module 448 // (memory 1) 449 // (func (export "i32_load8_s") (param $i i32) (result i32) 450 // (i32.store8 (i32.const 8) (get_local $i)) 451 // (return (i32.load8_s (i32.const 8))) 452 // ) 453 // ) 454 Vector<uint8_t> vector = { 455 0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x86, 0x80, 0x80, 0x80, 0x00, 0x01, 0x40, 456 0x01, 0x01, 0x01, 0x01, 0x03, 0x82, 0x80, 0x80, 0x80, 0x00, 0x01, 0x00, 0x05, 0x83, 0x80, 0x80, 457 0x80, 0x00, 0x01, 0x01, 0x01, 0x07, 0x8f, 0x80, 0x80, 0x80, 0x00, 0x01, 0x0b, 0x69, 0x33, 0x32, 458 0x5f, 0x6c, 0x6f, 0x61, 0x64, 0x38, 0x5f, 0x73, 0x00, 0x00, 0x0a, 0x95, 0x80, 0x80, 0x80, 0x00, 459 0x01, 0x8f, 0x80, 0x80, 0x80, 0x00, 0x00, 0x10, 0x08, 0x14, 0x00, 0x2e, 0x00, 0x00, 0x10, 0x08, 460 0x20, 0x00, 0x00, 0x09, 0x0f 461 }; 462 463 Plan plan(*vm, vector); 464 if (plan.result.size() != 1 || !plan.result[0]) { 465 dataLogLn("Module failed to compile correctly."); 466 CRASH(); 467 } 468 469 // Test this doesn't crash. 470 CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(0) }), 0); 471 CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(100) }), 100); 472 CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(1) }), 1); 473 } 474 475 { 476 // Generated from: 477 // (module 478 // (memory 1) 479 // (func (export "i32_load8_s") (param $i i32) (param $ptr i32) (result i32) 480 // (i32.store (get_local $ptr) (get_local $i)) 481 // (return (i32.load (get_local $ptr))) 482 // ) 483 // ) 484 Vector<uint8_t> vector = { 485 0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x87, 0x80, 0x80, 0x80, 0x00, 0x01, 0x40, 486 0x02, 0x02, 0x01, 0x01, 0x02, 0x03, 0x82, 0x80, 0x80, 0x80, 0x00, 0x01, 0x00, 0x05, 0x83, 0x80, 487 0x80, 0x80, 0x00, 0x01, 0x01, 0x01, 0x07, 0x8f, 0x80, 0x80, 0x80, 0x00, 0x01, 0x0b, 0x69, 0x33, 488 0x32, 0x5f, 0x6c, 0x6f, 0x61, 0x64, 0x38, 0x5f, 0x73, 0x00, 0x00, 0x0a, 0x95, 0x80, 0x80, 0x80, 489 0x00, 0x01, 0x8f, 0x80, 0x80, 0x80, 0x00, 0x00, 0x14, 0x01, 0x14, 0x00, 0x34, 0x03, 0x00, 0x14, 490 0x01, 0x2b, 0x03, 0x00, 0x09, 0x0f 491 }; 492 493 Plan plan(*vm, vector); 494 if (plan.result.size() != 1 || !plan.result[0]) { 495 dataLogLn("Module failed to compile correctly."); 496 CRASH(); 497 } 498 499 // Test this doesn't crash. 500 CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(0), box(10) }), 0); 501 CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(100), box(2) }), 100); 502 CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(1), box(100) }), 1); 503 CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(-12), box(plan.memory->size() - sizeof(uint64_t)) }), -12); 504 } 505 506 { 507 // Generated from: 508 // (module 509 // (memory 1) 510 // (func (export "i32_load8_s") (param $i i32) (param $ptr i32) (result i32) 511 // (i32.store (get_local $ptr) (get_local $i)) 512 // (return (i32.load (get_local $ptr))) 513 // ) 514 // ) 515 Vector<uint8_t> vector = { 516 0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x87, 0x80, 0x80, 0x80, 0x00, 0x01, 0x40, 517 0x02, 0x01, 0x01, 0x01, 0x01, 0x03, 0x82, 0x80, 0x80, 0x80, 0x00, 0x01, 0x00, 0x05, 0x83, 0x80, 518 0x80, 0x80, 0x00, 0x01, 0x01, 0x01, 0x07, 0x8f, 0x80, 0x80, 0x80, 0x00, 0x01, 0x0b, 0x69, 0x33, 519 0x32, 0x5f, 0x6c, 0x6f, 0x61, 0x64, 0x38, 0x5f, 0x73, 0x00, 0x00, 0x0a, 0x95, 0x80, 0x80, 0x80, 520 0x00, 0x01, 0x8f, 0x80, 0x80, 0x80, 0x00, 0x00, 0x14, 0x01, 0x14, 0x00, 0x33, 0x02, 0x00, 0x14, 521 0x01, 0x2a, 0x02, 0x00, 0x09, 0x0f 522 }; 523 524 Plan plan(*vm, vector); 525 if (plan.result.size() != 1 || !plan.result[0]) { 526 dataLogLn("Module failed to compile correctly."); 527 CRASH(); 528 } 529 530 // Test this doesn't crash. 531 CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(0), box(10) }), 0); 532 CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(100), box(2) }), 100); 533 CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(1), box(100) }), 1); 534 } 535 536 { 537 // Generated from: 538 // (module 539 // (memory 1) 540 // (func (export "write_array") (param $x i32) (param $p i32) (param $length i32) (local $i i32) 541 // (set_local $i (i32.const 0)) 542 // (block 543 // (loop 544 // (br_if 1 (i32.ge_u (get_local $i) (get_local $length))) 545 // (i32.store (i32.add (get_local $p) (i32.mul (get_local $i) (i32.const 4))) (get_local $x)) 546 // (set_local $i (i32.add (i32.const 1) (get_local $i))) 547 // (br 0) 548 // ) 549 // ) 550 // (return) 551 // ) 552 // ) 553 Vector<uint8_t> vector = { 554 0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x87, 0x80, 0x80, 0x80, 0x00, 0x01, 0x40, 555 0x03, 0x01, 0x01, 0x01, 0x00, 0x03, 0x82, 0x80, 0x80, 0x80, 0x00, 0x01, 0x00, 0x05, 0x83, 0x80, 556 0x80, 0x80, 0x00, 0x01, 0x01, 0x01, 0x07, 0x8f, 0x80, 0x80, 0x80, 0x00, 0x01, 0x0b, 0x77, 0x72, 557 0x69, 0x74, 0x65, 0x5f, 0x61, 0x72, 0x72, 0x61, 0x79, 0x00, 0x00, 0x0a, 0xb2, 0x80, 0x80, 0x80, 558 0x00, 0x01, 0xac, 0x80, 0x80, 0x80, 0x00, 0x01, 0x01, 0x01, 0x10, 0x00, 0x15, 0x03, 0x01, 0x00, 559 0x02, 0x00, 0x14, 0x03, 0x14, 0x02, 0x56, 0x07, 0x01, 0x14, 0x01, 0x14, 0x03, 0x10, 0x04, 0x42, 560 0x40, 0x14, 0x00, 0x33, 0x02, 0x00, 0x10, 0x01, 0x14, 0x03, 0x40, 0x15, 0x03, 0x06, 0x00, 0x0f, 561 0x0f, 0x09, 0x0f 562 }; 563 564 Plan plan(*vm, vector); 565 if (plan.result.size() != 1 || !plan.result[0]) { 566 dataLogLn("Module failed to compile correctly."); 567 CRASH(); 568 } 569 ASSERT(plan.memory->size()); 570 571 // Test this doesn't crash. 572 unsigned length = 5; 573 unsigned offset = sizeof(uint32_t); 574 uint32_t* memory = static_cast<uint32_t*>(plan.memory->memory()); 575 invoke<void>(*plan.result[0]->jsEntryPoint, { box(100), box(offset), box(length) }); 576 offset /= sizeof(uint32_t); 577 CHECK_EQ(memory[offset - 1], 0u); 578 CHECK_EQ(memory[offset + length], 0u); 579 for (unsigned i = 0; i < length; ++i) 580 CHECK_EQ(memory[i + offset], 100u); 581 582 length = 10; 583 offset = 5 * sizeof(uint32_t); 584 invoke<void>(*plan.result[0]->jsEntryPoint, { box(5), box(offset), box(length) }); 585 offset /= sizeof(uint32_t); 586 CHECK_EQ(memory[offset - 1], 100u); 587 CHECK_EQ(memory[offset + length], 0u); 588 for (unsigned i = 0; i < length; ++i) 589 CHECK_EQ(memory[i + offset], 5u); 590 } 591 592 { 593 // Generated from: 594 // (module 595 // (memory 1) 596 // (func (export "write_array") (param $x i32) (param $p i32) (param $length i32) (local $i i32) 597 // (set_local $i (i32.const 0)) 598 // (block 599 // (loop 600 // (br_if 1 (i32.ge_u (get_local $i) (get_local $length))) 601 // (i32.store8 (i32.add (get_local $p) (get_local $i)) (get_local $x)) 602 // (set_local $i (i32.add (i32.const 1) (get_local $i))) 603 // (br 0) 604 // ) 605 // ) 606 // (return) 607 // ) 608 // ) 609 Vector<uint8_t> vector = { 610 0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x87, 0x80, 0x80, 0x80, 0x00, 0x01, 0x40, 611 0x03, 0x01, 0x01, 0x01, 0x00, 0x03, 0x82, 0x80, 0x80, 0x80, 0x00, 0x01, 0x00, 0x05, 0x83, 0x80, 612 0x80, 0x80, 0x00, 0x01, 0x01, 0x01, 0x07, 0x8f, 0x80, 0x80, 0x80, 0x00, 0x01, 0x0b, 0x77, 0x72, 613 0x69, 0x74, 0x65, 0x5f, 0x61, 0x72, 0x72, 0x61, 0x79, 0x00, 0x00, 0x0a, 0xaf, 0x80, 0x80, 0x80, 614 0x00, 0x01, 0xa9, 0x80, 0x80, 0x80, 0x00, 0x01, 0x01, 0x01, 0x10, 0x00, 0x15, 0x03, 0x01, 0x00, 615 0x02, 0x00, 0x14, 0x03, 0x14, 0x02, 0x56, 0x07, 0x01, 0x14, 0x01, 0x14, 0x03, 0x40, 0x14, 0x00, 616 0x2e, 0x00, 0x00, 0x10, 0x01, 0x14, 0x03, 0x40, 0x15, 0x03, 0x06, 0x00, 0x0f, 0x0f, 0x09, 0x0f 617 }; 618 619 Plan plan(*vm, vector); 620 if (plan.result.size() != 1 || !plan.result[0]) { 621 dataLogLn("Module failed to compile correctly."); 622 CRASH(); 623 } 624 ASSERT(plan.memory->size()); 625 626 // Test this doesn't crash. 627 unsigned length = 5; 628 unsigned offset = 1; 629 uint8_t* memory = static_cast<uint8_t*>(plan.memory->memory()); 630 invoke<void>(*plan.result[0]->jsEntryPoint, { box(100), box(offset), box(length) }); 631 CHECK_EQ(memory[offset - 1], 0u); 632 CHECK_EQ(memory[offset + length], 0u); 633 for (unsigned i = 0; i < length; ++i) 634 CHECK_EQ(memory[i + offset], 100u); 635 636 length = 10; 637 offset = 5; 638 invoke<void>(*plan.result[0]->jsEntryPoint, { box(5), box(offset), box(length) }); 639 CHECK_EQ(memory[offset - 1], 100u); 640 CHECK_EQ(memory[offset + length], 0u); 641 for (unsigned i = 0; i < length; ++i) 642 CHECK_EQ(memory[i + offset], 5u); 643 } 644 645 { 646 // Generated from: 647 // (module 648 // (memory 1) 649 // (func (export "i32_load8_s") (param $i i32) (param $ptr i32) (result i32) 650 // (i32.store8 (get_local $ptr) (get_local $i)) 651 // (return (i32.load8_s (get_local $ptr))) 652 // ) 653 // ) 654 Vector<uint8_t> vector = { 655 0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x87, 0x80, 0x80, 0x80, 0x00, 0x01, 0x40, 656 0x02, 0x01, 0x01, 0x01, 0x01, 0x03, 0x82, 0x80, 0x80, 0x80, 0x00, 0x01, 0x00, 0x05, 0x83, 0x80, 657 0x80, 0x80, 0x00, 0x01, 0x01, 0x01, 0x07, 0x8f, 0x80, 0x80, 0x80, 0x00, 0x01, 0x0b, 0x69, 0x33, 658 0x32, 0x5f, 0x6c, 0x6f, 0x61, 0x64, 0x38, 0x5f, 0x73, 0x00, 0x00, 0x0a, 0x95, 0x80, 0x80, 0x80, 659 0x00, 0x01, 0x8f, 0x80, 0x80, 0x80, 0x00, 0x00, 0x14, 0x01, 0x14, 0x00, 0x2e, 0x00, 0x00, 0x14, 660 0x01, 0x20, 0x00, 0x00, 0x09, 0x0f 661 }; 662 663 Plan plan(*vm, vector); 664 if (plan.result.size() != 1 || !plan.result[0]) { 665 dataLogLn("Module failed to compile correctly."); 666 CRASH(); 667 } 668 ASSERT(plan.memory->size()); 669 670 // Test this doesn't crash. 671 CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(0), box(10) }), 0); 672 CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(100), box(2) }), 100); 673 CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(1), box(100) }), 1); 674 } 675 676 { 677 // Generated from: 678 // (module 679 // (memory 1) 680 // (func (export "i32_load8_s") (param $i i32) (result i32) 681 // (i32.store8 (i32.const 8) (get_local $i)) 682 // (return (i32.load8_s (i32.const 8))) 683 // ) 684 // ) 685 Vector<uint8_t> vector = { 686 0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x86, 0x80, 0x80, 0x80, 0x00, 0x01, 0x40, 687 0x01, 0x01, 0x01, 0x01, 0x03, 0x82, 0x80, 0x80, 0x80, 0x00, 0x01, 0x00, 0x05, 0x83, 0x80, 0x80, 688 0x80, 0x00, 0x01, 0x01, 0x01, 0x07, 0x8f, 0x80, 0x80, 0x80, 0x00, 0x01, 0x0b, 0x69, 0x33, 0x32, 689 0x5f, 0x6c, 0x6f, 0x61, 0x64, 0x38, 0x5f, 0x73, 0x00, 0x00, 0x0a, 0x95, 0x80, 0x80, 0x80, 0x00, 690 0x01, 0x8f, 0x80, 0x80, 0x80, 0x00, 0x00, 0x10, 0x08, 0x14, 0x00, 0x2e, 0x00, 0x00, 0x10, 0x08, 691 0x20, 0x00, 0x00, 0x09, 0x0f 692 }; 693 694 Plan plan(*vm, vector); 695 if (plan.result.size() != 1 || !plan.result[0]) { 696 dataLogLn("Module failed to compile correctly."); 697 CRASH(); 698 } 699 700 // Test this doesn't crash. 701 CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(0) }), 0); 702 CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(100) }), 100); 703 CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(1) }), 1); 704 } 705 706 { 707 // Generated from: 708 // (module 709 // (func "dumb-eq" (param $x i32) (param $y i32) (result i32) 247 710 // (if (i32.eq (get_local $x) (get_local $y)) 248 711 // (then (br 0)) … … 266 729 267 730 // Test this doesn't crash. 268 CHECK_EQ(invoke<int>(*plan.result[0] , { box(0), box(1) }), 1);269 CHECK_EQ(invoke<int>(*plan.result[0] , { box(1), box(0) }), 1);270 CHECK_EQ(invoke<int>(*plan.result[0] , { box(2), box(1) }), 1);271 CHECK_EQ(invoke<int>(*plan.result[0] , { box(1), box(2) }), 1);272 CHECK_EQ(invoke<int>(*plan.result[0] , { box(2), box(2) }), 0);273 CHECK_EQ(invoke<int>(*plan.result[0] , { box(1), box(1) }), 0);274 CHECK_EQ(invoke<int>(*plan.result[0] , { box(2), box(6) }), 1);275 CHECK_EQ(invoke<int>(*plan.result[0] , { box(100), box(6) }), 1);731 CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(0), box(1) }), 1); 732 CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(1), box(0) }), 1); 733 CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(2), box(1) }), 1); 734 CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(1), box(2) }), 1); 735 CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(2), box(2) }), 0); 736 CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(1), box(1) }), 0); 737 CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(2), box(6) }), 1); 738 CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(100), box(6) }), 1); 276 739 } 277 740 … … 307 770 308 771 // Test this doesn't crash. 309 CHECK_EQ(invoke<int>(*plan.result[0] , { box(0), box(1) }), 1);310 CHECK_EQ(invoke<int>(*plan.result[0] , { box(1), box(0) }), 0);311 CHECK_EQ(invoke<int>(*plan.result[0] , { box(2), box(1) }), 0);312 CHECK_EQ(invoke<int>(*plan.result[0] , { box(1), box(2) }), 1);313 CHECK_EQ(invoke<int>(*plan.result[0] , { box(2), box(2) }), 0);314 CHECK_EQ(invoke<int>(*plan.result[0] , { box(1), box(1) }), 0);315 CHECK_EQ(invoke<int>(*plan.result[0] , { box(2), box(6) }), 1);316 CHECK_EQ(invoke<int>(*plan.result[0] , { box(100), box(6) }), 0);772 CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(0), box(1) }), 1); 773 CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(1), box(0) }), 0); 774 CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(2), box(1) }), 0); 775 CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(1), box(2) }), 1); 776 CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(2), box(2) }), 0); 777 CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(1), box(1) }), 0); 778 CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(2), box(6) }), 1); 779 CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(100), box(6) }), 0); 317 780 } 318 781 … … 334 797 335 798 // Test this doesn't crash. 336 CHECK_EQ(invoke<int>(*plan.result[0] , { }), 5);799 CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { }), 5); 337 800 } 338 801 … … 355 818 356 819 // Test this doesn't crash. 357 CHECK_EQ(invoke<int>(*plan.result[0] , { }), 11);820 CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { }), 11); 358 821 } 359 822 … … 375 838 376 839 // Test this doesn't crash. 377 CHECK_EQ(invoke<int>(*plan.result[0] , { }), 11);840 CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { }), 11); 378 841 } 379 842 … … 395 858 396 859 // Test this doesn't crash. 397 CHECK_EQ(invoke<int>(*plan.result[0] , { }), 11);860 CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { }), 11); 398 861 } 399 862 … … 414 877 415 878 // Test this doesn't crash. 416 CHECK_EQ(invoke<int>(*plan.result[0] , { box(0), box(1) }), 1);417 CHECK_EQ(invoke<int>(*plan.result[0] , { box(100), box(1) }), 101);418 CHECK_EQ(invoke<int>(*plan.result[0] , { box(-1), box(1)}), 0);419 CHECK_EQ(invoke<int>(*plan.result[0] , { box(std::numeric_limits<int>::max()), box(1) }), std::numeric_limits<int>::min());879 CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(0), box(1) }), 1); 880 CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(100), box(1) }), 101); 881 CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(-1), box(1)}), 0); 882 CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(std::numeric_limits<int>::max()), box(1) }), std::numeric_limits<int>::min()); 420 883 } 421 884 … … 443 906 444 907 // Test this doesn't crash. 445 CHECK_EQ(invoke<int>(*plan.result[0] , { box(0) }), 0);446 CHECK_EQ(invoke<int>(*plan.result[0] , { box(10) }), 10);908 CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(0) }), 0); 909 CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(10) }), 10); 447 910 } 448 911 … … 479 942 480 943 // Test this doesn't crash. 481 CHECK_EQ(invoke<int>(*plan.result[0] , { box(0) }), 0);482 CHECK_EQ(invoke<int>(*plan.result[0] , { box(1) }), 1);483 CHECK_EQ(invoke<int>(*plan.result[0] , { box(2)}), 3);484 CHECK_EQ(invoke<int>(*plan.result[0] , { box(100) }), 5050);944 CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(0) }), 0); 945 CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(1) }), 1); 946 CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(2)}), 3); 947 CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(100) }), 5050); 485 948 } 486 949 … … 523 986 524 987 // Test this doesn't crash. 525 CHECK_EQ(invoke<int>(*plan.result[0] , { box(0), box(1) }), 0);526 CHECK_EQ(invoke<int>(*plan.result[0] , { box(1), box(0) }), 0);527 CHECK_EQ(invoke<int>(*plan.result[0] , { box(2), box(1) }), 2);528 CHECK_EQ(invoke<int>(*plan.result[0] , { box(1), box(2) }), 2);529 CHECK_EQ(invoke<int>(*plan.result[0] , { box(2), box(2) }), 4);530 CHECK_EQ(invoke<int>(*plan.result[0] , { box(2), box(6) }), 12);531 CHECK_EQ(invoke<int>(*plan.result[0] , { box(100), box(6) }), 600);532 CHECK_EQ(invoke<int>(*plan.result[0] , { box(100), box(100) }), 10000);988 CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(0), box(1) }), 0); 989 CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(1), box(0) }), 0); 990 CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(2), box(1) }), 2); 991 CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(1), box(2) }), 2); 992 CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(2), box(2) }), 4); 993 CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(2), box(6) }), 12); 994 CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(100), box(6) }), 600); 995 CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(100), box(100) }), 10000); 533 996 } 534 997 … … 576 1039 577 1040 // Test this doesn't crash. 578 CHECK_EQ(invoke<int>(*plan.result[0] , { box(0), box(1) }), 1);579 CHECK_EQ(invoke<int>(*plan.result[0] , { box(1), box(0) }), 0);580 CHECK_EQ(invoke<int>(*plan.result[0] , { box(2), box(1) }), 0);581 CHECK_EQ(invoke<int>(*plan.result[0] , { box(1), box(2) }), 1);582 CHECK_EQ(invoke<int>(*plan.result[0] , { box(2), box(2) }), 0);583 CHECK_EQ(invoke<int>(*plan.result[0] , { box(1), box(1) }), 0);584 CHECK_EQ(invoke<int>(*plan.result[0] , { box(2), box(6) }), 1);585 CHECK_EQ(invoke<int>(*plan.result[0] , { box(100), box(6) }), 0);1041 CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(0), box(1) }), 1); 1042 CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(1), box(0) }), 0); 1043 CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(2), box(1) }), 0); 1044 CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(1), box(2) }), 1); 1045 CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(2), box(2) }), 0); 1046 CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(1), box(1) }), 0); 1047 CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(2), box(6) }), 1); 1048 CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(100), box(6) }), 0); 586 1049 } 587 1050 … … 596 1059 if (options.m_runLEBTests) 597 1060 runLEBTests(); 598 599 1061 600 1062 if (options.m_runWASMTests) { -
trunk/Source/JavaScriptCore/wasm/WASMB3IRGenerator.cpp
r206110 r207453 30 30 31 31 #include "B3BasicBlockInlines.h" 32 #include "B3ConstPtrValue.h" 32 33 #include "B3FixSSA.h" 34 #include "B3StackmapGenerationParams.h" 33 35 #include "B3Validate.h" 34 36 #include "B3ValueInlines.h" 35 37 #include "B3Variable.h" 36 38 #include "B3VariableValue.h" 39 #include "B3WasmAddressValue.h" 40 #include "B3WasmBoundsCheckValue.h" 37 41 #include "VirtualRegister.h" 38 42 #include "WASMCallingConvention.h" 39 43 #include "WASMFunctionParser.h" 44 #include "WASMMemory.h" 40 45 #include <wtf/Optional.h> 41 46 … … 166 171 static constexpr ExpressionType emptyExpression = nullptr; 167 172 168 B3IRGenerator( Procedure&);173 B3IRGenerator(Memory*, Procedure&); 169 174 170 175 void addArguments(const Vector<Type>&); … … 172 177 ExpressionType addConstant(Type, uint64_t); 173 178 179 // Locals 174 180 bool WARN_UNUSED_RETURN getLocal(uint32_t index, ExpressionType& result); 175 181 bool WARN_UNUSED_RETURN setLocal(uint32_t index, ExpressionType value); 176 182 183 // Memory 184 bool WARN_UNUSED_RETURN load(LoadOpType, ExpressionType pointer, ExpressionType& result, uint32_t offset); 185 bool WARN_UNUSED_RETURN store(StoreOpType, ExpressionType pointer, ExpressionType value, uint32_t offset); 186 187 // Basic operators 177 188 bool WARN_UNUSED_RETURN binaryOp(BinaryOpType, ExpressionType left, ExpressionType right, ExpressionType& result); 178 189 bool WARN_UNUSED_RETURN unaryOp(UnaryOpType, ExpressionType arg, ExpressionType& result); 179 190 191 // Control flow 180 192 ControlData WARN_UNUSED_RETURN addBlock(Type signature); 181 193 ControlData WARN_UNUSED_RETURN addLoop(Type signature); … … 192 204 193 205 private: 206 ExpressionType emitCheckAndPreparePointer(ExpressionType pointer, uint32_t offset, uint32_t sizeOfOp); 207 ExpressionType emitLoadOp(LoadOpType, Origin, ExpressionType pointer, uint32_t offset); 208 void emitStoreOp(StoreOpType, Origin, ExpressionType pointer, ExpressionType value, uint32_t offset); 209 194 210 void unify(Variable* target, const ExpressionType source); 195 211 void unifyValuesWithBlock(const ExpressionList& resultStack, ResultList& stack); 196 212 213 Memory* m_memory; 197 214 Procedure& m_proc; 198 215 BasicBlock* m_currentBlock; 199 216 Vector<Variable*> m_locals; 217 GPRReg m_memoryBaseGPR; 218 GPRReg m_memorySizeGPR; 200 219 }; 201 220 202 B3IRGenerator::B3IRGenerator(Procedure& procedure) 203 : m_proc(procedure) 221 B3IRGenerator::B3IRGenerator(Memory* memory, Procedure& procedure) 222 : m_memory(memory) 223 , m_proc(procedure) 204 224 { 205 225 m_currentBlock = m_proc.addBlock(); 226 227 if (m_memory) { 228 m_memoryBaseGPR = m_memory->pinnedRegisters().baseMemoryPointer; 229 m_proc.pinRegister(m_memoryBaseGPR); 230 ASSERT(!m_memory->pinnedRegisters().sizeRegisters[0].sizeOffset); 231 m_memorySizeGPR = m_memory->pinnedRegisters().sizeRegisters[0].sizeRegister; 232 for (const PinnedSizeRegisterInfo& info : m_memory->pinnedRegisters().sizeRegisters) 233 m_proc.pinRegister(info.sizeRegister); 234 } 235 236 m_proc.setWasmBoundsCheckGenerator([=] (CCallHelpers& jit, GPRReg pinnedGPR, unsigned) { 237 ASSERT_UNUSED(pinnedGPR, m_memorySizeGPR == pinnedGPR); 238 // FIXME: This should unwind the stack and throw a JS exception. See: https://bugs.webkit.org/show_bug.cgi?id=163351 239 jit.breakpoint(); 240 }); 206 241 } 207 242 … … 225 260 } 226 261 227 bool WARN_UNUSED_RETURNB3IRGenerator::getLocal(uint32_t index, ExpressionType& result)262 bool B3IRGenerator::getLocal(uint32_t index, ExpressionType& result) 228 263 { 229 264 ASSERT(m_locals[index]); … … 232 267 } 233 268 234 bool WARN_UNUSED_RETURNB3IRGenerator::setLocal(uint32_t index, ExpressionType value)269 bool B3IRGenerator::setLocal(uint32_t index, ExpressionType value) 235 270 { 236 271 ASSERT(m_locals[index]); 237 272 m_currentBlock->appendNew<VariableValue>(m_proc, B3::Set, Origin(), m_locals[index], value); 273 return true; 274 } 275 276 inline Value* B3IRGenerator::emitCheckAndPreparePointer(ExpressionType pointer, uint32_t offset, uint32_t sizeOfOperation) 277 { 278 ASSERT(m_memoryBaseGPR && m_memorySizeGPR); 279 ASSERT(sizeOfOperation + offset > offset); 280 m_currentBlock->appendNew<WasmBoundsCheckValue>(m_proc, Origin(), pointer, m_memorySizeGPR, sizeOfOperation + offset - 1); 281 pointer = m_currentBlock->appendNew<Value>(m_proc, ZExt32, Origin(), pointer); 282 return m_currentBlock->appendNew<WasmAddressValue>(m_proc, Origin(), pointer, m_memoryBaseGPR); 283 } 284 285 inline uint32_t sizeOfLoadOp(LoadOpType op) 286 { 287 switch (op) { 288 case LoadOpType::I32Load8S: 289 case LoadOpType::I32Load8U: 290 case LoadOpType::I64Load8S: 291 case LoadOpType::I64Load8U: 292 return 1; 293 case LoadOpType::I32Load16S: 294 case LoadOpType::I64Load16S: 295 return 2; 296 case LoadOpType::I32Load: 297 case LoadOpType::I64Load32S: 298 case LoadOpType::I64Load32U: 299 return 4; 300 case LoadOpType::I64Load: 301 return 8; 302 case LoadOpType::I32Load16U: 303 case LoadOpType::I64Load16U: 304 case LoadOpType::F32Load: 305 case LoadOpType::F64Load: 306 break; 307 } 308 RELEASE_ASSERT_NOT_REACHED(); 309 } 310 311 inline Value* B3IRGenerator::emitLoadOp(LoadOpType op, Origin origin, ExpressionType pointer, uint32_t offset) 312 { 313 switch (op) { 314 case LoadOpType::I32Load8S: { 315 return m_currentBlock->appendNew<MemoryValue>(m_proc, Load8S, origin, pointer, offset); 316 } 317 318 case LoadOpType::I64Load8S: { 319 Value* value = m_currentBlock->appendNew<MemoryValue>(m_proc, Load8S, origin, pointer, offset); 320 return m_currentBlock->appendNew<Value>(m_proc, SExt32, origin, value); 321 } 322 323 case LoadOpType::I32Load8U: { 324 return m_currentBlock->appendNew<MemoryValue>(m_proc, Load8Z, origin, pointer, offset); 325 } 326 327 case LoadOpType::I64Load8U: { 328 Value* value = m_currentBlock->appendNew<MemoryValue>(m_proc, Load8Z, origin, pointer, offset); 329 return m_currentBlock->appendNew<Value>(m_proc, ZExt32, origin, value); 330 } 331 332 case LoadOpType::I32Load16S: { 333 return m_currentBlock->appendNew<MemoryValue>(m_proc, Load16S, origin, pointer, offset); 334 } 335 case LoadOpType::I64Load16S: { 336 Value* value = m_currentBlock->appendNew<MemoryValue>(m_proc, Load16S, origin, pointer, offset); 337 return m_currentBlock->appendNew<Value>(m_proc, SExt32, origin, value); 338 } 339 340 case LoadOpType::I32Load: { 341 return m_currentBlock->appendNew<MemoryValue>(m_proc, Load, Int32, origin, pointer); 342 } 343 344 case LoadOpType::I64Load32U: { 345 Value* value = m_currentBlock->appendNew<MemoryValue>(m_proc, Load, Int32, origin, pointer); 346 return m_currentBlock->appendNew<Value>(m_proc, ZExt32, origin, value); 347 } 348 349 case LoadOpType::I64Load32S: { 350 Value* value = m_currentBlock->appendNew<MemoryValue>(m_proc, Load, Int32, origin, pointer); 351 return m_currentBlock->appendNew<Value>(m_proc, SExt32, origin, value); 352 } 353 354 case LoadOpType::I64Load: { 355 return m_currentBlock->appendNew<MemoryValue>(m_proc, Load, Int64, origin, pointer); 356 } 357 358 case LoadOpType::F32Load: { 359 return m_currentBlock->appendNew<MemoryValue>(m_proc, Load, Float, origin, pointer); 360 } 361 362 case LoadOpType::F64Load: { 363 return m_currentBlock->appendNew<MemoryValue>(m_proc, Load, Double, origin, pointer); 364 } 365 366 // B3 doesn't support Load16Z yet. 367 case LoadOpType::I32Load16U: 368 case LoadOpType::I64Load16U: 369 break; 370 } 371 RELEASE_ASSERT_NOT_REACHED(); 372 } 373 374 bool B3IRGenerator::load(LoadOpType op, ExpressionType pointer, ExpressionType& result, uint32_t offset) 375 { 376 ASSERT(pointer->type() == Int32); 377 378 result = emitLoadOp(op, Origin(), emitCheckAndPreparePointer(pointer, offset, sizeOfLoadOp(op)), offset); 379 return true; 380 } 381 382 inline uint32_t sizeOfStoreOp(StoreOpType op) 383 { 384 switch (op) { 385 case StoreOpType::I32Store8: 386 case StoreOpType::I64Store8: 387 return 1; 388 case StoreOpType::I32Store16: 389 case StoreOpType::I64Store16: 390 return 2; 391 case StoreOpType::I32Store: 392 case StoreOpType::I64Store32: 393 case StoreOpType::F32Store: 394 return 4; 395 case StoreOpType::I64Store: 396 case StoreOpType::F64Store: 397 return 8; 398 } 399 RELEASE_ASSERT_NOT_REACHED(); 400 } 401 402 403 inline void B3IRGenerator::emitStoreOp(StoreOpType op, Origin origin, ExpressionType pointer, ExpressionType value, uint32_t offset) 404 { 405 switch (op) { 406 case StoreOpType::I64Store8: 407 value = m_currentBlock->appendNew<Value>(m_proc, Trunc, origin, value); 408 FALLTHROUGH; 409 410 case StoreOpType::I32Store8: 411 m_currentBlock->appendNew<MemoryValue>(m_proc, Store8, origin, value, pointer, offset); 412 return; 413 414 case StoreOpType::I64Store16: 415 value = m_currentBlock->appendNew<Value>(m_proc, Trunc, origin, value); 416 FALLTHROUGH; 417 418 case StoreOpType::I32Store16: 419 m_currentBlock->appendNew<MemoryValue>(m_proc, Store16, origin, value, pointer, offset); 420 return; 421 422 case StoreOpType::I64Store32: 423 value = m_currentBlock->appendNew<Value>(m_proc, Trunc, origin, value); 424 FALLTHROUGH; 425 426 case StoreOpType::I64Store: 427 case StoreOpType::I32Store: 428 case StoreOpType::F32Store: 429 case StoreOpType::F64Store: 430 m_currentBlock->appendNew<MemoryValue>(m_proc, Store, origin, value, pointer, offset); 431 return; 432 } 433 RELEASE_ASSERT_NOT_REACHED(); 434 } 435 436 bool B3IRGenerator::store(StoreOpType op, ExpressionType pointer, ExpressionType value, uint32_t offset) 437 { 438 ASSERT(pointer->type() == Int32); 439 440 emitStoreOp(op, Origin(), emitCheckAndPreparePointer(pointer, offset, sizeOfStoreOp(op)), value, offset); 238 441 return true; 239 442 } … … 404 607 } // anonymous namespace 405 608 406 std::unique_ptr<Compilation> parseAndCompile(VM& vm, Vector<uint8_t>& source, FunctionInformation info, unsigned optLevel) 609 610 static std::unique_ptr<Compilation> createJSWrapper(VM& vm, const Signature* signature, MacroAssemblerCodePtr mainFunction, Memory* memory) 611 { 612 Procedure proc; 613 BasicBlock* block = proc.addBlock(); 614 615 // Check argument count is sane. 616 Value* framePointer = block->appendNew<B3::Value>(proc, B3::FramePointer, Origin()); 617 Value* offSetOfArgumentCount = block->appendNew<Const64Value>(proc, Origin(), CallFrameSlot::argumentCount * sizeof(Register)); 618 Value* argumentCount = block->appendNew<MemoryValue>(proc, Load, Int32, Origin(), 619 block->appendNew<Value>(proc, Add, Origin(), framePointer, offSetOfArgumentCount)); 620 621 Value* expectedArgumentCount = block->appendNew<Const32Value>(proc, Origin(), signature->arguments.size()); 622 623 CheckValue* argumentCountCheck = block->appendNew<CheckValue>(proc, Check, Origin(), 624 block->appendNew<Value>(proc, Above, Origin(), expectedArgumentCount, argumentCount)); 625 argumentCountCheck->setGenerator([] (CCallHelpers& jit, const StackmapGenerationParams&) { 626 jit.breakpoint(); 627 }); 628 629 // Move memory values to the approriate places, if needed. 630 Value* baseMemory = nullptr; 631 Vector<Value*> sizes; 632 if (memory) { 633 baseMemory = block->appendNew<ConstPtrValue>(proc, Origin(), memory->memory()); 634 Value* size = block->appendNew<MemoryValue>(proc, Load, Int32, Origin(), 635 block->appendNew<ConstPtrValue>(proc, Origin(), bitwise_cast<char*>(memory) + Memory::offsetOfSize())); 636 sizes.reserveCapacity(memory->pinnedRegisters().sizeRegisters.size()); 637 for (auto info : memory->pinnedRegisters().sizeRegisters) { 638 sizes.append(block->appendNew<Value>(proc, Sub, Origin(), size, 639 block->appendNew<Const32Value>(proc, Origin(), info.sizeOffset))); 640 } 641 } 642 643 // Get our arguments. 644 Vector<Value*> arguments; 645 jscCallingConvention().iterate(signature->arguments, proc, block, Origin(), [&] (Value* argument, unsigned) { 646 arguments.append(argument); 647 }); 648 649 // Move the arguments into place. 650 Value* result = jscCallingConvention().setupCall(proc, block, Origin(), mainFunction, arguments, toB3Type(signature->returnType), [&] (PatchpointValue* patchpoint) { 651 if (memory) { 652 ASSERT(sizes.size() == memory->pinnedRegisters().sizeRegisters.size()); 653 patchpoint->append(ConstrainedValue(baseMemory, ValueRep::reg(memory->pinnedRegisters().baseMemoryPointer))); 654 for (unsigned i = 0; i < sizes.size(); ++i) 655 patchpoint->append(ConstrainedValue(sizes[i], ValueRep::reg(memory->pinnedRegisters().sizeRegisters[i].sizeRegister))); 656 } 657 }); 658 659 // Return the result, if needed. 660 if (signature->returnType != Void) 661 block->appendNewControlValue(proc, B3::Return, Origin(), result); 662 else 663 block->appendNewControlValue(proc, B3::Return, Origin()); 664 665 return std::make_unique<Compilation>(vm, proc); 666 } 667 668 std::unique_ptr<FunctionCompilation> parseAndCompile(VM& vm, Vector<uint8_t>& source, Memory* memory, FunctionInformation info, unsigned optLevel) 407 669 { 408 670 Procedure procedure; 409 B3IRGenerator context( procedure);671 B3IRGenerator context(memory, procedure); 410 672 FunctionParser<B3IRGenerator> parser(context, source, info); 411 673 if (!parser.parse()) … … 418 680 if (verbose) 419 681 dataLog("Post SSA: ", procedure); 420 return std::make_unique<Compilation>(vm, procedure, optLevel); 682 auto result = std::make_unique<FunctionCompilation>(); 683 684 result->code = std::make_unique<Compilation>(vm, procedure, optLevel); 685 result->jsEntryPoint = createJSWrapper(vm, info.signature, result->code->code(), memory); 686 return result; 421 687 } 422 688 -
trunk/Source/JavaScriptCore/wasm/WASMB3IRGenerator.h
r205769 r207453 36 36 namespace JSC { namespace WASM { 37 37 38 std::unique_ptr<B3::Compilation> parseAndCompile(VM&, Vector<uint8_t>&, FunctionInformation, unsigned optLevel = 1); 38 class Memory; 39 40 std::unique_ptr<FunctionCompilation> parseAndCompile(VM&, Vector<uint8_t>&, Memory*, FunctionInformation, unsigned optLevel = 1); 39 41 40 42 } } // namespace JSC::WASM -
trunk/Source/JavaScriptCore/wasm/WASMCallingConvention.h
r205552 r207453 28 28 #if ENABLE(WEBASSEMBLY) 29 29 30 #include "AllowMacroScratchRegisterUsage.h" 30 31 #include "B3ArgumentRegValue.h" 31 32 #include "B3BasicBlock.h" 32 33 #include "B3Const64Value.h" 34 #include "B3ConstrainedValue.h" 33 35 #include "B3MemoryValue.h" 36 #include "B3PatchpointValue.h" 37 #include "B3Procedure.h" 38 #include "B3StackmapGenerationParams.h" 34 39 #include "CallFrame.h" 40 #include "LinkBuffer.h" 35 41 #include "RegisterSet.h" 36 42 #include "WASMFormat.h" … … 38 44 namespace JSC { namespace WASM { 39 45 40 typedef unsigned (*NextOffset)(unsigned currentOffset, Type type);46 typedef unsigned (*NextOffset)(unsigned currentOffset, B3::Type type); 41 47 42 template<unsigned offset, NextOffset updateOffset>48 template<unsigned headerSize, NextOffset updateOffset> 43 49 class CallingConvention { 44 50 public: 45 static const unsigned headerSize = offset;46 47 51 CallingConvention(Vector<GPRReg>&& registerArguments, RegisterSet&& calleeSaveRegisters) 48 52 : m_registerArguments(registerArguments) … … 65 69 block->appendNew<B3::Const64Value>(proc, origin, currentOffset)); 66 70 argument = block->appendNew<B3::MemoryValue>(proc, B3::Load, toB3Type(argumentTypes[i]), origin, address); 67 currentOffset = updateOffset(currentOffset, argumentTypes[i]);71 currentOffset = updateOffset(currentOffset, toB3Type(argumentTypes[i])); 68 72 } 69 73 functor(argument, i); 70 74 } 75 } 76 77 template<typename Functor> 78 B3::Value* setupCall(B3::Procedure& proc, B3::BasicBlock* block, B3::Origin origin, MacroAssemblerCodePtr target, const Vector<B3::Value*>& arguments, B3::Type returnType, const Functor& patchpointFunctor) const 79 { 80 size_t stackArgumentCount = arguments.size() < m_registerArguments.size() ? 0 : arguments.size() - m_registerArguments.size(); 81 unsigned offset = headerSize - sizeof(CallerFrameAndPC); 82 83 proc.requestCallArgAreaSizeInBytes(WTF::roundUpToMultipleOf(stackAlignmentBytes(), headerSize + (stackArgumentCount * sizeof(Register)))); 84 Vector<B3::ConstrainedValue> constrainedArguments; 85 for (unsigned i = 0; i < arguments.size(); ++i) { 86 B3::ValueRep rep; 87 if (i < m_registerArguments.size()) 88 rep = B3::ValueRep::reg(m_registerArguments[i]); 89 else 90 rep = B3::ValueRep::stackArgument(offset); 91 constrainedArguments.append(B3::ConstrainedValue(arguments[i], rep)); 92 offset = updateOffset(offset, arguments[i]->type()); 93 } 94 95 B3::PatchpointValue* patchpoint = block->appendNew<B3::PatchpointValue>(proc, returnType, origin); 96 patchpoint->appendVector(constrainedArguments); 97 patchpointFunctor(patchpoint); 98 patchpoint->setGenerator([=] (CCallHelpers& jit, const B3::StackmapGenerationParams&) { 99 AllowMacroScratchRegisterUsage allowScratch(jit); 100 101 CCallHelpers::Call call = jit.call(); 102 jit.addLinkTask([=] (LinkBuffer& linkBuffer) { 103 linkBuffer.link(call, FunctionPtr(target.executableAddress())); 104 }); 105 }); 106 107 if (returnType == B3::Void) 108 return nullptr; 109 110 patchpoint->resultConstraint = B3::ValueRep::reg(GPRInfo::returnValueGPR); 111 return patchpoint; 71 112 } 72 113 … … 76 117 }; 77 118 78 inline unsigned nextJSCOffset(unsigned currentOffset, Type)119 inline unsigned nextJSCOffset(unsigned currentOffset, B3::Type) 79 120 { 80 121 return currentOffset + sizeof(Register); -
trunk/Source/JavaScriptCore/wasm/WASMFormat.h
r206110 r207453 45 45 #if ENABLE(WEBASSEMBLY) 46 46 47 #include "B3Compilation.h" 47 48 #include "B3Type.h" 48 49 #include <wtf/Vector.h> … … 127 128 }; 128 129 130 struct FunctionCompilation { 131 std::unique_ptr<B3::Compilation> code; 132 std::unique_ptr<B3::Compilation> jsEntryPoint; 133 }; 134 129 135 } } // namespace JSC::WASM 130 136 -
trunk/Source/JavaScriptCore/wasm/WASMFunctionParser.h
r206794 r207453 155 155 } 156 156 157 FOR_EACH_WASM_MEMORY_LOAD_OP(CREATE_CASE) { 158 uint32_t alignment; 159 if (!parseVarUInt32(alignment)) 160 return false; 161 162 uint32_t offset; 163 if (!parseVarUInt32(offset)) 164 return false; 165 166 ExpressionType pointer = m_expressionStack.takeLast(); 167 ExpressionType result; 168 if (!m_context.load(static_cast<LoadOpType>(op), pointer, result, offset)) 169 return false; 170 m_expressionStack.append(result); 171 return true; 172 } 173 174 FOR_EACH_WASM_MEMORY_STORE_OP(CREATE_CASE) { 175 uint32_t alignment; 176 if (!parseVarUInt32(alignment)) 177 return false; 178 179 uint32_t offset; 180 if (!parseVarUInt32(offset)) 181 return false; 182 183 ExpressionType value = m_expressionStack.takeLast(); 184 ExpressionType pointer = m_expressionStack.takeLast(); 185 return m_context.store(static_cast<StoreOpType>(op), pointer, value, offset); 186 } 187 157 188 case OpType::I32Const: { 158 189 uint32_t constant; -
trunk/Source/JavaScriptCore/wasm/WASMModuleParser.cpp
r206110 r207453 29 29 #if ENABLE(WEBASSEMBLY) 30 30 31 #include "JSWASMModule.h" 31 32 #include "WASMFormat.h" 32 33 #include "WASMOps.h" 33 34 #include "WASMSections.h" 34 35 36 #include <sys/mman.h> 37 35 38 namespace JSC { namespace WASM { 36 39 … … 63 66 dataLogLn("Starting to parse next section at offset: ", m_offset); 64 67 65 Sections::Section section = Sections::Unknown;66 68 uint8_t sectionByte; 67 69 if (!parseUInt7(sectionByte)) 68 70 return false; 69 71 72 if (verbose) 73 dataLogLn("Section byte: ", sectionByte); 74 75 Sections::Section section = Sections::Unknown; 70 76 if (sectionByte) { 71 if (sectionByte >= Sections::Unknown) 72 section = Sections::Unknown; 73 else 77 if (sectionByte < Sections::Unknown) 74 78 section = static_cast<Sections::Section>(sectionByte); 75 79 } else { … … 97 101 98 102 switch (section) { 103 104 case Sections::Memory: { 105 if (verbose) 106 dataLogLn("Parsing Memory."); 107 if (!parseMemory()) 108 return false; 109 break; 110 } 111 99 112 case Sections::FunctionTypes: { 100 113 if (verbose) … … 142 155 // TODO 143 156 return true; 157 } 158 159 bool ModuleParser::parseMemory() 160 { 161 uint8_t flags; 162 if (!parseVarUInt1(flags)) 163 return false; 164 165 uint32_t size; 166 if (!parseVarUInt32(size)) 167 return false; 168 if (size > maxPageCount) 169 return false; 170 171 uint32_t capacity = maxPageCount; 172 if (flags) { 173 if (!parseVarUInt32(capacity)) 174 return false; 175 if (size > capacity || capacity > maxPageCount) 176 return false; 177 } 178 179 capacity *= pageSize; 180 size *= pageSize; 181 182 Vector<unsigned> pinnedSizes = { 0 }; 183 m_memory = std::make_unique<Memory>(size, capacity, pinnedSizes); 184 return m_memory->memory(); 144 185 } 145 186 -
trunk/Source/JavaScriptCore/wasm/WASMModuleParser.h
r205552 r207453 28 28 #if ENABLE(WEBASSEMBLY) 29 29 30 #include "WASMMemory.h" 30 31 #include "WASMOps.h" 31 32 #include "WASMParser.h" … … 46 47 bool WARN_UNUSED_RETURN parse(); 47 48 48 const Vector<FunctionInformation>& functionInformation() { return m_functions; } 49 const Vector<FunctionInformation>& functionInformation() const { return m_functions; } 50 std::unique_ptr<Memory>& memory() { return m_memory; } 49 51 50 52 private: 53 bool WARN_UNUSED_RETURN parseMemory(); 51 54 bool WARN_UNUSED_RETURN parseFunctionTypes(); 52 55 bool WARN_UNUSED_RETURN parseFunctionSignatures(); 53 56 bool WARN_UNUSED_RETURN parseFunctionDefinitions(); 54 57 bool WARN_UNUSED_RETURN parseFunctionDefinition(uint32_t number); 55 bool WARN_UNUSED_RETURN parseBlock();56 bool WARN_UNUSED_RETURN parseExpression(OpType);57 58 58 59 Vector<FunctionInformation> m_functions; 59 60 Vector<Signature> m_signatures; 61 std::unique_ptr<Memory> m_memory; 60 62 }; 61 63 -
trunk/Source/JavaScriptCore/wasm/WASMOps.h
r206794 r207453 160 160 macro(F64Ge, 0x9c, Oops) 161 161 162 #define FOR_EACH_WASM_MEMORY_LOAD_OP(macro) \ 163 macro(I32Load8S, 0x20, Oops) \ 164 macro(I32Load8U, 0x21, Oops) \ 165 macro(I32Load16S, 0x22, Oops) \ 166 macro(I32Load16U, 0x23, Oops) \ 167 macro(I64Load8S, 0x24, Oops) \ 168 macro(I64Load8U, 0x25, Oops) \ 169 macro(I64Load16S, 0x26, Oops) \ 170 macro(I64Load16U, 0x27, Oops) \ 171 macro(I64Load32S, 0x28, Oops) \ 172 macro(I64Load32U, 0x29, Oops) \ 173 macro(I32Load, 0x2a, Oops) \ 174 macro(I64Load, 0x2b, Oops) \ 175 macro(F32Load, 0x2c, Oops) \ 176 macro(F64Load, 0x2d, Oops) 177 178 #define FOR_EACH_WASM_MEMORY_STORE_OP(macro) \ 179 macro(I32Store8, 0x2e, Oops) \ 180 macro(I32Store16, 0x2f, Oops) \ 181 macro(I64Store8, 0x30, Oops) \ 182 macro(I64Store16, 0x31, Oops) \ 183 macro(I64Store32, 0x32, Oops) \ 184 macro(I32Store, 0x33, Oops) \ 185 macro(I64Store, 0x34, Oops) \ 186 macro(F32Store, 0x35, Oops) \ 187 macro(F64Store, 0x36, Oops) 188 162 189 163 190 … … 166 193 FOR_EACH_WASM_CONTROL_FLOW_OP(macro) \ 167 194 FOR_EACH_WASM_UNARY_OP(macro) \ 168 FOR_EACH_WASM_BINARY_OP(macro) 195 FOR_EACH_WASM_BINARY_OP(macro) \ 196 FOR_EACH_WASM_MEMORY_LOAD_OP(macro) \ 197 FOR_EACH_WASM_MEMORY_STORE_OP(macro) 169 198 170 199 #define CREATE_ENUM_VALUE(name, id, b3op) name = id, … … 188 217 enum class UnaryOpType : uint8_t { 189 218 FOR_EACH_WASM_UNARY_OP(CREATE_ENUM_VALUE) 219 }; 220 221 enum class LoadOpType : uint8_t { 222 FOR_EACH_WASM_MEMORY_LOAD_OP(CREATE_ENUM_VALUE) 223 }; 224 225 enum class StoreOpType : uint8_t { 226 FOR_EACH_WASM_MEMORY_STORE_OP(CREATE_ENUM_VALUE) 190 227 }; 191 228 -
trunk/Source/JavaScriptCore/wasm/WASMPlan.cpp
r205552 r207453 31 31 #include "B3Compilation.h" 32 32 #include "WASMB3IRGenerator.h" 33 #include "WASMCallingConvention.h" 33 34 #include "WASMModuleParser.h" 34 35 #include <wtf/DataLog.h> … … 54 55 if (verbose) 55 56 dataLogLn("Processing funcion starting at: ", info.start, " and ending at: ", info.end); 56 result.append(parseAndCompile(vm, source, info));57 result.append(parseAndCompile(vm, source, moduleParser.memory().get(), info)); 57 58 } 59 memory = WTFMove(moduleParser.memory()); 58 60 } 59 61 -
trunk/Source/JavaScriptCore/wasm/WASMPlan.h
r205552 r207453 30 30 #include "CompilationResult.h" 31 31 #include "VM.h" 32 #include "WASMFormat.h" 32 33 #include <wtf/ThreadSafeRefCounted.h> 33 34 #include <wtf/Vector.h> 34 35 35 namespace JSC { 36 37 namespace B3 { 38 class Compilation; 39 } // namespace B3 40 41 namespace WASM { 36 namespace JSC { namespace WASM { 37 class Memory; 42 38 43 39 // TODO: This should create a WASM Module not a list of functions. … … 46 42 JS_EXPORT_PRIVATE Plan(VM&, Vector<uint8_t> source); 47 43 48 Vector<std::unique_ptr<B3::Compilation>> result; 44 Vector<std::unique_ptr<FunctionCompilation>> result; 45 std::unique_ptr<Memory> memory; 49 46 }; 50 47 -
trunk/Source/JavaScriptCore/wasm/WASMSections.h
r206110 r207453 34 34 FunctionTypes = 1, 35 35 Signatures = 3, 36 Memory = 5, 36 37 Definitions = 10, 37 38 Unknown
Note: See TracChangeset
for help on using the changeset viewer.