Changeset 205552 in webkit
- Timestamp:
- Sep 7, 2016 10:12:08 AM (8 years ago)
- Location:
- trunk/Source/JavaScriptCore
- Files:
-
- 17 edited
- 2 moved
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/CMakeLists.txt
r205520 r205552 855 855 wasm/WASMPlan.cpp 856 856 wasm/WASMSections.cpp 857 wasm/WASMCallingConventions.cpp 857 858 858 859 yarr/RegularExpression.cpp -
trunk/Source/JavaScriptCore/ChangeLog
r205549 r205552 1 2016-09-03 Keith Miller <keith_miller@apple.com> 2 3 Add support for WASM Loops and Branches 4 https://bugs.webkit.org/show_bug.cgi?id=161569 5 6 Reviewed by Benjamin Poulain. 7 8 This patch adds support for loops and branches to WASM. In order 9 to support loops, we needed to change the way the B3IRGenerator 10 tracked control information. Now, the control data holds three 11 pieces of information: The continuation block, the loop branch 12 target, and variables exiting the block. Whenever we branch to 13 some control point we first check if it is a loop by checking that 14 the loop branch target is non-null. If the branch is not targeting 15 a loop, we map the stack values to the associated B3 variables for 16 that stack slot. 17 18 Another interesting thing of note is that we now only allocate the 19 continuation basic block lazily. This is beneficial when the 20 continuation would just fall through to another block anyway. For 21 example, in code like: (block ... (block (add 1 2) end) end) the 22 continuation for the inner block just falls through to the outer 23 block's continuation so we don't need an extra block. 24 25 * B3CallingConventions.cpp: 26 (JSC::B3::jscCallingConvention): Deleted. 27 * B3CallingConventions.h: 28 (JSC::B3::CallingConvention::CallingConvention): Deleted. 29 (JSC::B3::CallingConvention::iterate): Deleted. 30 (JSC::B3::nextJSCOffset): Deleted. 31 * JavaScriptCore.xcodeproj/project.pbxproj: 32 * b3/B3Type.h: 33 * testWASM.cpp: 34 (runWASMTests): 35 * wasm/WASMB3IRGenerator.cpp: 36 (JSC::WASM::B3IRGenerator::LazyBlock::LazyBlock): 37 (JSC::WASM::B3IRGenerator::LazyBlock::operator bool): 38 (JSC::WASM::B3IRGenerator::LazyBlock::get): 39 (JSC::WASM::B3IRGenerator::LazyBlock::dump): 40 (JSC::WASM::B3IRGenerator::ControlData::ControlData): 41 (JSC::WASM::B3IRGenerator::ControlData::dump): 42 (JSC::WASM::B3IRGenerator::ControlData::targetBlockForBranch): 43 (JSC::WASM::B3IRGenerator::ControlData::isLoop): 44 (JSC::WASM::B3IRGenerator::addLocal): 45 (JSC::WASM::B3IRGenerator::addArguments): 46 (JSC::WASM::B3IRGenerator::setLocal): 47 (JSC::WASM::B3IRGenerator::addBlock): 48 (JSC::WASM::B3IRGenerator::addLoop): 49 (JSC::WASM::B3IRGenerator::endBlock): 50 (JSC::WASM::B3IRGenerator::addReturn): 51 (JSC::WASM::B3IRGenerator::addBranch): 52 (JSC::WASM::B3IRGenerator::initializeIncommingTypes): 53 (JSC::WASM::B3IRGenerator::unifyValuesWithBlock): 54 (JSC::WASM::B3IRGenerator::controlDataForLevel): 55 (JSC::WASM::B3IRGenerator::dumpGraphAndControlStack): 56 (JSC::WASM::parseAndCompile): 57 (JSC::WASM::B3IRGenerator::unifyValuesWithLevel): Deleted. 58 (JSC::WASM::B3IRGenerator::stackForControlLevel): Deleted. 59 (JSC::WASM::B3IRGenerator::blockForControlLevel): Deleted. 60 * wasm/WASMCallingConvention.cpp: Renamed from Source/JavaScriptCore/B3CallingConventions.cpp. 61 (JSC::WASM::jscCallingConvention): 62 * wasm/WASMCallingConvention.h: Renamed from Source/JavaScriptCore/B3CallingConventions.h. 63 (JSC::WASM::CallingConvention::CallingConvention): 64 (JSC::WASM::CallingConvention::iterate): 65 (JSC::WASM::nextJSCOffset): 66 * wasm/WASMFormat.h: 67 (JSC::WASM::toB3Type): 68 (JSC::WASM::isValueType): 69 * wasm/WASMFunctionParser.h: 70 (JSC::WASM::FunctionParser<Context>::parse): 71 (JSC::WASM::FunctionParser<Context>::parseExpression): 72 * wasm/WASMModuleParser.cpp: 73 (JSC::WASM::ModuleParser::parseFunctionTypes): 74 * wasm/WASMOps.h: 75 1 76 2016-09-07 Youenn Fablet <youenn@apple.com> 2 77 -
trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
r205520 r205552 1196 1196 531374BD1D5CE67600AF7A0B /* WASMPlan.h in Headers */ = {isa = PBXBuildFile; fileRef = 531374BC1D5CE67600AF7A0B /* WASMPlan.h */; }; 1197 1197 531374BF1D5CE95000AF7A0B /* WASMPlan.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 531374BE1D5CE95000AF7A0B /* WASMPlan.cpp */; }; 1198 531B3C871D74C603005B3236 /* B3CallingConventions.h in Headers */ = {isa = PBXBuildFile; fileRef = 531B3C861D74C603005B3236 /* B3CallingConventions.h */; };1199 1198 53486BB71C1795C300F6F3AF /* JSTypedArray.h in Headers */ = {isa = PBXBuildFile; fileRef = 53486BB61C1795C300F6F3AF /* JSTypedArray.h */; settings = {ATTRIBUTES = (Public, ); }; }; 1200 1199 53486BBB1C18E84500F6F3AF /* JSTypedArray.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 53486BBA1C18E84500F6F3AF /* JSTypedArray.cpp */; }; … … 1205 1204 5370B4F51BF26202005C40FC /* AdaptiveInferredPropertyValueWatchpointBase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5370B4F31BF25EA2005C40FC /* AdaptiveInferredPropertyValueWatchpointBase.cpp */; }; 1206 1205 5370B4F61BF26205005C40FC /* AdaptiveInferredPropertyValueWatchpointBase.h in Headers */ = {isa = PBXBuildFile; fileRef = 5370B4F41BF25EA2005C40FC /* AdaptiveInferredPropertyValueWatchpointBase.h */; }; 1207 5388B4041D76640B00D3D852 /* B3CallingConventions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5388B4031D76640B00D3D852 /* B3CallingConventions.cpp */; };1208 1206 53917E7B1B7906FA000EBD33 /* JSGenericTypedArrayViewPrototypeFunctions.h in Headers */ = {isa = PBXBuildFile; fileRef = 53917E7A1B7906E4000EBD33 /* JSGenericTypedArrayViewPrototypeFunctions.h */; }; 1209 1207 539EB0791D55607000C82EF7 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 51F0EB6105C86C6B00E6DF1B /* Foundation.framework */; }; … … 1223 1221 53FA2AE11CF37F3F0022711D /* LLIntPrototypeLoadAdaptiveStructureWatchpoint.h in Headers */ = {isa = PBXBuildFile; fileRef = 53FA2AE01CF37F3F0022711D /* LLIntPrototypeLoadAdaptiveStructureWatchpoint.h */; settings = {ATTRIBUTES = (Private, ); }; }; 1224 1222 53FA2AE31CF380390022711D /* LLIntPrototypeLoadAdaptiveStructureWatchpoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 53FA2AE21CF380390022711D /* LLIntPrototypeLoadAdaptiveStructureWatchpoint.cpp */; }; 1223 53FD04D31D7AB277003287D3 /* WASMCallingConvention.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 53FD04D11D7AB187003287D3 /* WASMCallingConvention.cpp */; }; 1224 53FD04D41D7AB291003287D3 /* WASMCallingConvention.h in Headers */ = {isa = PBXBuildFile; fileRef = 53FD04D21D7AB187003287D3 /* WASMCallingConvention.h */; }; 1225 1225 5D5D8AD10E0D0EBE00F9C692 /* libedit.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 5D5D8AD00E0D0EBE00F9C692 /* libedit.dylib */; }; 1226 1226 5DBB151B131D0B310056AD36 /* testapi.js in Copy Support Script */ = {isa = PBXBuildFile; fileRef = 14D857740A4696C80032146C /* testapi.js */; }; … … 3410 3410 531374BC1D5CE67600AF7A0B /* WASMPlan.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WASMPlan.h; sourceTree = "<group>"; }; 3411 3411 531374BE1D5CE95000AF7A0B /* WASMPlan.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WASMPlan.cpp; sourceTree = "<group>"; }; 3412 531B3C861D74C603005B3236 /* B3CallingConventions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = B3CallingConventions.h; sourceTree = "<group>"; };3413 3412 53486BB61C1795C300F6F3AF /* JSTypedArray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSTypedArray.h; sourceTree = "<group>"; }; 3414 3413 53486BBA1C18E84500F6F3AF /* JSTypedArray.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSTypedArray.cpp; sourceTree = "<group>"; }; … … 3421 3420 5370B4F31BF25EA2005C40FC /* AdaptiveInferredPropertyValueWatchpointBase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AdaptiveInferredPropertyValueWatchpointBase.cpp; sourceTree = "<group>"; }; 3422 3421 5370B4F41BF25EA2005C40FC /* AdaptiveInferredPropertyValueWatchpointBase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AdaptiveInferredPropertyValueWatchpointBase.h; sourceTree = "<group>"; }; 3423 5388B4031D76640B00D3D852 /* B3CallingConventions.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = B3CallingConventions.cpp; sourceTree = "<group>"; };3424 3422 53917E7A1B7906E4000EBD33 /* JSGenericTypedArrayViewPrototypeFunctions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSGenericTypedArrayViewPrototypeFunctions.h; sourceTree = "<group>"; }; 3425 3423 53917E7C1B791106000EBD33 /* JSTypedArrayViewPrototype.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSTypedArrayViewPrototype.h; sourceTree = "<group>"; }; … … 3441 3439 53FA2AE01CF37F3F0022711D /* LLIntPrototypeLoadAdaptiveStructureWatchpoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LLIntPrototypeLoadAdaptiveStructureWatchpoint.h; sourceTree = "<group>"; }; 3442 3440 53FA2AE21CF380390022711D /* LLIntPrototypeLoadAdaptiveStructureWatchpoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LLIntPrototypeLoadAdaptiveStructureWatchpoint.cpp; sourceTree = "<group>"; }; 3441 53FD04D11D7AB187003287D3 /* WASMCallingConvention.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WASMCallingConvention.cpp; sourceTree = "<group>"; }; 3442 53FD04D21D7AB187003287D3 /* WASMCallingConvention.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WASMCallingConvention.h; sourceTree = "<group>"; }; 3443 3443 593D43CCA0BBE06D89C59707 /* MapDataInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MapDataInlines.h; sourceTree = "<group>"; }; 3444 3444 5D5D8AD00E0D0EBE00F9C692 /* libedit.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libedit.dylib; path = /usr/lib/libedit.dylib; sourceTree = "<absolute>"; }; … … 4820 4820 0F6B8ADE1C4EFE1700969052 /* B3BreakCriticalEdges.cpp */, 4821 4821 0F6B8ADF1C4EFE1700969052 /* B3BreakCriticalEdges.h */, 4822 5388B4031D76640B00D3D852 /* B3CallingConventions.cpp */,4823 531B3C861D74C603005B3236 /* B3CallingConventions.h */,4824 4822 DC9A0C1C1D2D94EF0085124E /* B3CaseCollection.cpp */, 4825 4823 DC9A0C1D1D2D94EF0085124E /* B3CaseCollection.h */, … … 5629 5627 7B98D1341B60CD5A0023B1A4 /* JSWASMModule.cpp */, 5630 5628 7B98D1351B60CD5A0023B1A4 /* JSWASMModule.h */, 5629 53F40E8E1D5902820099A1B6 /* WASMB3IRGenerator.cpp */, 5630 53F40E921D5A4AB30099A1B6 /* WASMB3IRGenerator.h */, 5631 53FD04D11D7AB187003287D3 /* WASMCallingConvention.cpp */, 5632 53FD04D21D7AB187003287D3 /* WASMCallingConvention.h */, 5631 5633 53F40E901D5903020099A1B6 /* WASMOps.h */, 5632 5634 7BC547D21B69599B00959B58 /* WASMFormat.h */, 5633 53F40E8E1D5902820099A1B6 /* WASMB3IRGenerator.cpp */,5634 53F40E921D5A4AB30099A1B6 /* WASMB3IRGenerator.h */,5635 5635 53F40E8A1D5901BB0099A1B6 /* WASMFunctionParser.h */, 5636 5636 53F40E961D5A7BEC0099A1B6 /* WASMModuleParser.cpp */, … … 8296 8296 705B41B01A6E501E00716757 /* SymbolObject.h in Headers */, 8297 8297 0F33FCFC1C1625BE00323F67 /* B3Dominators.h in Headers */, 8298 53FD04D41D7AB291003287D3 /* WASMCallingConvention.h in Headers */, 8298 8299 705B41B21A6E501E00716757 /* SymbolPrototype.h in Headers */, 8299 8300 996B73281BDA08EF00331B84 /* SymbolPrototype.lut.h in Headers */, … … 8344 8345 0F963B3813FC6FE90002D9B2 /* ValueProfile.h in Headers */, 8345 8346 0F426A481460CBB300131F8F /* ValueRecovery.h in Headers */, 8346 531B3C871D74C603005B3236 /* B3CallingConventions.h in Headers */,8347 8347 79EE0C001B4AFB85000385C9 /* VariableEnvironment.h in Headers */, 8348 8348 0F6C73511AC9F99F00BE1682 /* VariableWriteFireDetail.h in Headers */, … … 8997 8997 C2FCAE1217A9C24E0034C735 /* BytecodeLivenessAnalysis.cpp in Sources */, 8998 8998 0F338E0D1BF0276C0013C88F /* B3DataSection.cpp in Sources */, 8999 5388B4041D76640B00D3D852 /* B3CallingConventions.cpp in Sources */,9000 8999 65B8392F1BACAD6A0044E824 /* CachedRecovery.cpp in Sources */, 9001 9000 1428082D107EC0570013E7B2 /* CallData.cpp in Sources */, … … 9130 9129 FEA0C4021CDD7D1D00481991 /* FunctionWhitelist.cpp in Sources */, 9131 9130 A73A535A1799CD5D00170C19 /* DFGLazyJSValue.cpp in Sources */, 9131 53FD04D31D7AB277003287D3 /* WASMCallingConvention.cpp in Sources */, 9132 9132 62F2AA371B0BEDE300610C7A /* DFGLazyNode.cpp in Sources */, 9133 9133 A7D9A29717A0BC7400EE2618 /* DFGLICMPhase.cpp in Sources */, -
trunk/Source/JavaScriptCore/b3/B3Type.h
r205309 r205552 40 40 41 41 enum Type : int8_t { 42 Void, 42 43 Int32, 43 44 Int64, 44 45 Float, 45 46 Double, 46 LastValueType = Double,47 Void48 47 }; 49 48 -
trunk/Source/JavaScriptCore/testWASM.cpp
r205330 r205552 83 83 } 84 84 85 StaticLock crashLock; 86 87 #define CHECK_EQ(x, y) do { \ 88 auto __x = (x); \ 89 auto __y = (y); \ 90 if (__x == __y) \ 91 break; \ 92 crashLock.lock(); \ 93 WTFReportAssertionFailure(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, toCString(#x " == " #y, " (" #x " == ", __x, ", " #y " == ", __y, ")").data()); \ 94 CRASH(); \ 95 } while (false) 96 85 97 #define FOR_EACH_UNSIGNED_LEB_TEST(macro) \ 86 98 /* Simple tests that use all the bits in the array */ \ 87 macro(({ 0x07 }), 0, true, 0x7 , 1) \88 macro(({ 0x77 }), 0, true, 0x77 , 1) \89 macro(({ 0x80, 0x07 }), 0, true, 0x380 , 2) \90 macro(({ 0x89, 0x12 }), 0, true, 0x909 , 2) \91 macro(({ 0xf3, 0x85, 0x02 }), 0, true, 0x82f3 , 3) \92 macro(({ 0xf3, 0x85, 0xff, 0x74 }), 0, true, 0xe9fc2f3 , 4) \93 macro(({ 0xf3, 0x85, 0xff, 0xf4, 0x7f }), 0, true, 0xfe9fc2f3 , 5) \99 macro(({ 0x07 }), 0, true, 0x7lu, 1lu) \ 100 macro(({ 0x77 }), 0, true, 0x77lu, 1lu) \ 101 macro(({ 0x80, 0x07 }), 0, true, 0x380lu, 2lu) \ 102 macro(({ 0x89, 0x12 }), 0, true, 0x909lu, 2lu) \ 103 macro(({ 0xf3, 0x85, 0x02 }), 0, true, 0x82f3lu, 3lu) \ 104 macro(({ 0xf3, 0x85, 0xff, 0x74 }), 0, true, 0xe9fc2f3lu, 4lu) \ 105 macro(({ 0xf3, 0x85, 0xff, 0xf4, 0x7f }), 0, true, 0xfe9fc2f3lu, 5lu) \ 94 106 /* Test with extra trailing numbers */ \ 95 macro(({ 0x07, 0x80 }), 0, true, 0x7 , 1) \96 macro(({ 0x07, 0x75 }), 0, true, 0x7 , 1) \97 macro(({ 0xf3, 0x85, 0xff, 0x74, 0x43 }), 0, true, 0xe9fc2f3 , 4) \98 macro(({ 0xf3, 0x85, 0xff, 0x74, 0x80 }), 0, true, 0xe9fc2f3 , 4) \107 macro(({ 0x07, 0x80 }), 0, true, 0x7lu, 1lu) \ 108 macro(({ 0x07, 0x75 }), 0, true, 0x7lu, 1lu) \ 109 macro(({ 0xf3, 0x85, 0xff, 0x74, 0x43 }), 0, true, 0xe9fc2f3lu, 4lu) \ 110 macro(({ 0xf3, 0x85, 0xff, 0x74, 0x80 }), 0, true, 0xe9fc2f3lu, 4lu) \ 99 111 /* Test with preceeding numbers */ \ 100 macro(({ 0xf3, 0x07 }), 1, true, 0x7 , 2) \101 macro(({ 0x03, 0x07 }), 1, true, 0x7 , 2) \102 macro(({ 0xf2, 0x53, 0x43, 0x67, 0x79, 0x77 }), 5, true, 0x77 , 6) \103 macro(({ 0xf2, 0x53, 0x43, 0xf7, 0x84, 0x77 }), 5, true, 0x77 , 6) \104 macro(({ 0xf2, 0x53, 0x43, 0xf3, 0x85, 0x02 }), 3, true, 0x82f3 , 6) \112 macro(({ 0xf3, 0x07 }), 1, true, 0x7lu, 2lu) \ 113 macro(({ 0x03, 0x07 }), 1, true, 0x7lu, 2lu) \ 114 macro(({ 0xf2, 0x53, 0x43, 0x67, 0x79, 0x77 }), 5, true, 0x77lu, 6lu) \ 115 macro(({ 0xf2, 0x53, 0x43, 0xf7, 0x84, 0x77 }), 5, true, 0x77lu, 6ul) \ 116 macro(({ 0xf2, 0x53, 0x43, 0xf3, 0x85, 0x02 }), 3, true, 0x82f3lu, 6lu) \ 105 117 /* Test in the middle */ \ 106 macro(({ 0xf3, 0x07, 0x89 }), 1, true, 0x7 , 2) \107 macro(({ 0x03, 0x07, 0x23 }), 1, true, 0x7 , 2) \108 macro(({ 0xf2, 0x53, 0x43, 0x67, 0x79, 0x77, 0x43 }), 5, true, 0x77 , 6) \109 macro(({ 0xf2, 0x53, 0x43, 0xf7, 0x84, 0x77, 0xf9 }), 5, true, 0x77 , 6) \110 macro(({ 0xf2, 0x53, 0x43, 0xf3, 0x85, 0x02, 0xa4 }), 3, true, 0x82f3 , 6) \118 macro(({ 0xf3, 0x07, 0x89 }), 1, true, 0x7lu, 2lu) \ 119 macro(({ 0x03, 0x07, 0x23 }), 1, true, 0x7lu, 2lu) \ 120 macro(({ 0xf2, 0x53, 0x43, 0x67, 0x79, 0x77, 0x43 }), 5, true, 0x77lu, 6lu) \ 121 macro(({ 0xf2, 0x53, 0x43, 0xf7, 0x84, 0x77, 0xf9 }), 5, true, 0x77lu, 6lu) \ 122 macro(({ 0xf2, 0x53, 0x43, 0xf3, 0x85, 0x02, 0xa4 }), 3, true, 0x82f3lu, 6lu) \ 111 123 /* Test decode too long */ \ 112 macro(({ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80}), 0, false, 0x0 , 0) \113 macro(({ 0x80, 0x80, 0xab, 0x8a, 0x9a, 0xa3, 0xff}), 1, false, 0x0 , 0) \114 macro(({ 0x80, 0x80, 0xab, 0x8a, 0x9a, 0xa3, 0xff}), 0, false, 0x0 , 0) \124 macro(({ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80}), 0, false, 0x0lu, 0lu) \ 125 macro(({ 0x80, 0x80, 0xab, 0x8a, 0x9a, 0xa3, 0xff}), 1, false, 0x0lu, 0lu) \ 126 macro(({ 0x80, 0x80, 0xab, 0x8a, 0x9a, 0xa3, 0xff}), 0, false, 0x0lu, 0lu) \ 115 127 /* Test decode off end of array */ \ 116 macro(({ 0x80, 0x80, 0xab, 0x8a, 0x9a, 0xa3, 0xff}), 2, false, 0x0 , 0) \128 macro(({ 0x80, 0x80, 0xab, 0x8a, 0x9a, 0xa3, 0xff}), 2, false, 0x0lu, 0lu) \ 117 129 118 130 … … 123 135 uint32_t result; \ 124 136 bool status = decodeUInt32(vector.data(), vector.size(), offset, result); \ 125 RELEASE_ASSERT(status ==expectedStatus); \137 CHECK_EQ(status, expectedStatus); \ 126 138 if (expectedStatus) { \ 127 RELEASE_ASSERT(result ==expectedResult); \128 RELEASE_ASSERT(offset ==expectedOffset); \139 CHECK_EQ(result, expectedResult); \ 140 CHECK_EQ(offset, expectedOffset); \ 129 141 } \ 130 142 }; … … 133 145 #define FOR_EACH_SIGNED_LEB_TEST(macro) \ 134 146 /* Simple tests that use all the bits in the array */ \ 135 macro(({ 0x07 }), 0, true, 0x7, 1 ) \136 macro(({ 0x77 }), 0, true, -0x9, 1 ) \137 macro(({ 0x80, 0x07 }), 0, true, 0x380, 2 ) \138 macro(({ 0x89, 0x12 }), 0, true, 0x909, 2 ) \139 macro(({ 0xf3, 0x85, 0x02 }), 0, true, 0x82f3, 3 ) \140 macro(({ 0xf3, 0x85, 0xff, 0x74 }), 0, true, 0xfe9fc2f3, 4 ) \141 macro(({ 0xf3, 0x85, 0xff, 0xf4, 0x7f }), 0, true, 0xfe9fc2f3, 5 ) \147 macro(({ 0x07 }), 0, true, 0x7, 1lu) \ 148 macro(({ 0x77 }), 0, true, -0x9, 1lu) \ 149 macro(({ 0x80, 0x07 }), 0, true, 0x380, 2lu) \ 150 macro(({ 0x89, 0x12 }), 0, true, 0x909, 2lu) \ 151 macro(({ 0xf3, 0x85, 0x02 }), 0, true, 0x82f3, 3lu) \ 152 macro(({ 0xf3, 0x85, 0xff, 0x74 }), 0, true, 0xfe9fc2f3, 4lu) \ 153 macro(({ 0xf3, 0x85, 0xff, 0xf4, 0x7f }), 0, true, 0xfe9fc2f3, 5lu) \ 142 154 /* Test with extra trailing numbers */ \ 143 macro(({ 0x07, 0x80 }), 0, true, 0x7, 1 ) \144 macro(({ 0x07, 0x75 }), 0, true, 0x7, 1 ) \145 macro(({ 0xf3, 0x85, 0xff, 0x74, 0x43 }), 0, true, 0xfe9fc2f3, 4 ) \146 macro(({ 0xf3, 0x85, 0xff, 0x74, 0x80 }), 0, true, 0xfe9fc2f3, 4 ) \155 macro(({ 0x07, 0x80 }), 0, true, 0x7, 1lu) \ 156 macro(({ 0x07, 0x75 }), 0, true, 0x7, 1lu) \ 157 macro(({ 0xf3, 0x85, 0xff, 0x74, 0x43 }), 0, true, 0xfe9fc2f3, 4lu) \ 158 macro(({ 0xf3, 0x85, 0xff, 0x74, 0x80 }), 0, true, 0xfe9fc2f3, 4lu) \ 147 159 /* Test with preceeding numbers */ \ 148 macro(({ 0xf3, 0x07 }), 1, true, 0x7, 2 ) \149 macro(({ 0x03, 0x07 }), 1, true, 0x7, 2 ) \150 macro(({ 0xf2, 0x53, 0x43, 0x67, 0x79, 0x77 }), 5, true, -0x9, 6 ) \151 macro(({ 0xf2, 0x53, 0x43, 0xf7, 0x84, 0x77 }), 5, true, -0x9, 6 ) \152 macro(({ 0xf2, 0x53, 0x43, 0xf3, 0x85, 0x02 }), 3, true, 0x82f3, 6 ) \160 macro(({ 0xf3, 0x07 }), 1, true, 0x7, 2lu) \ 161 macro(({ 0x03, 0x07 }), 1, true, 0x7, 2lu) \ 162 macro(({ 0xf2, 0x53, 0x43, 0x67, 0x79, 0x77 }), 5, true, -0x9, 6lu) \ 163 macro(({ 0xf2, 0x53, 0x43, 0xf7, 0x84, 0x77 }), 5, true, -0x9, 6lu) \ 164 macro(({ 0xf2, 0x53, 0x43, 0xf3, 0x85, 0x02 }), 3, true, 0x82f3, 6lu) \ 153 165 /* Test in the middle */ \ 154 macro(({ 0xf3, 0x07, 0x89 }), 1, true, 0x7, 2 ) \155 macro(({ 0x03, 0x07, 0x23 }), 1, true, 0x7, 2 ) \156 macro(({ 0xf2, 0x53, 0x43, 0x67, 0x79, 0x77, 0x43 }), 5, true, -0x9, 6 ) \157 macro(({ 0xf2, 0x53, 0x43, 0xf7, 0x84, 0x77, 0xf9 }), 5, true, -0x9, 6 ) \158 macro(({ 0xf2, 0x53, 0x43, 0xf3, 0x85, 0x02, 0xa4 }), 3, true, 0x82f3, 6 ) \166 macro(({ 0xf3, 0x07, 0x89 }), 1, true, 0x7, 2lu) \ 167 macro(({ 0x03, 0x07, 0x23 }), 1, true, 0x7, 2lu) \ 168 macro(({ 0xf2, 0x53, 0x43, 0x67, 0x79, 0x77, 0x43 }), 5, true, -0x9, 6lu) \ 169 macro(({ 0xf2, 0x53, 0x43, 0xf7, 0x84, 0x77, 0xf9 }), 5, true, -0x9, 6lu) \ 170 macro(({ 0xf2, 0x53, 0x43, 0xf3, 0x85, 0x02, 0xa4 }), 3, true, 0x82f3, 6lu) \ 159 171 /* Test decode too long */ \ 160 macro(({ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80}), 0, false, 0x0, 0 ) \161 macro(({ 0x80, 0x80, 0xab, 0x8a, 0x9a, 0xa3, 0xff}), 1, false, 0x0, 0 ) \162 macro(({ 0x80, 0x80, 0xab, 0x8a, 0x9a, 0xa3, 0xff}), 0, false, 0x0, 0 ) \172 macro(({ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80}), 0, false, 0x0, 0lu) \ 173 macro(({ 0x80, 0x80, 0xab, 0x8a, 0x9a, 0xa3, 0xff}), 1, false, 0x0, 0lu) \ 174 macro(({ 0x80, 0x80, 0xab, 0x8a, 0x9a, 0xa3, 0xff}), 0, false, 0x0, 0lu) \ 163 175 /* Test decode off end of array */ \ 164 macro(({ 0x80, 0x80, 0xab, 0x8a, 0x9a, 0xa3, 0xff}), 2, false, 0x0, 0 ) \176 macro(({ 0x80, 0x80, 0xab, 0x8a, 0x9a, 0xa3, 0xff}), 2, false, 0x0, 0lu) \ 165 177 166 178 … … 171 183 int32_t result; \ 172 184 bool status = decodeInt32(vector.data(), vector.size(), offset, result); \ 173 RELEASE_ASSERT(status ==expectedStatus); \185 CHECK_EQ(status, expectedStatus); \ 174 186 if (expectedStatus) { \ 175 187 int32_t expected = expectedResult; \ 176 RELEASE_ASSERT(result ==expected); \177 RELEASE_ASSERT(offset ==expectedOffset); \188 CHECK_EQ(result, expected); \ 189 CHECK_EQ(offset, expectedOffset); \ 178 190 } \ 179 191 }; … … 247 259 248 260 // Test this doesn't crash. 249 RELEASE_ASSERT(invoke<int>(*plan.result[0], { }) ==5);261 CHECK_EQ(invoke<int>(*plan.result[0], { }), 5); 250 262 } 251 263 … … 269 281 270 282 // Test this doesn't crash. 271 RELEASE_ASSERT(invoke<int>(*plan.result[0], { }) ==11);283 CHECK_EQ(invoke<int>(*plan.result[0], { }), 11); 272 284 } 273 285 … … 290 302 291 303 // Test this doesn't crash. 292 RELEASE_ASSERT(invoke<int>(*plan.result[0], { }) ==11);304 CHECK_EQ(invoke<int>(*plan.result[0], { }), 11); 293 305 } 294 306 … … 311 323 312 324 // Test this doesn't crash. 313 RELEASE_ASSERT(invoke<int>(*plan.result[0], { }) ==11);325 CHECK_EQ(invoke<int>(*plan.result[0], { }), 11); 314 326 } 315 327 … … 330 342 331 343 // Test this doesn't crash. 332 RELEASE_ASSERT(invoke<int>(*plan.result[0], {box(0), box(1)}) == 1); 333 RELEASE_ASSERT(invoke<int>(*plan.result[0], {box(100), box(1)}) == 101); 334 RELEASE_ASSERT(invoke<int>(*plan.result[0], {box(-1), box(1)}) == 0); 335 RELEASE_ASSERT(invoke<int>(*plan.result[0], {box(std::numeric_limits<int>::max()), box(1)}) == std::numeric_limits<int>::min()); 336 } 344 CHECK_EQ(invoke<int>(*plan.result[0], { box(0), box(1) }), 1); 345 CHECK_EQ(invoke<int>(*plan.result[0], { box(100), box(1) }), 101); 346 CHECK_EQ(invoke<int>(*plan.result[0], { box(-1), box(1)}), 0); 347 CHECK_EQ(invoke<int>(*plan.result[0], { box(std::numeric_limits<int>::max()), box(1) }), std::numeric_limits<int>::min()); 348 } 349 350 { 351 // Generated from: 352 // (module 353 // (func "locals" (param $x i32) (result i32) (local $num i32) 354 // (set_local $num (get_local $x)) 355 // (return (get_local $num)) 356 // ) 357 // ) 358 Vector<uint8_t> vector = { 359 0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x74, 0x79, 0x70, 0x65, 0x86, 0x80, 0x80, 360 0x00, 0x01, 0x40, 0x01, 0x01, 0x01, 0x01, 0x08, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 361 0x82, 0x80, 0x80, 0x00, 0x01, 0x00, 0x06, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x89, 0x80, 0x80, 362 0x00, 0x01, 0x00, 0x06, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x73, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x91, 363 0x80, 0x80, 0x00, 0x01, 0x8c, 0x80, 0x80, 0x00, 0x01, 0x01, 0x01, 0x14, 0x00, 0x15, 0x01, 0x14, 364 0x01, 0x09, 0x01, 0x0f 365 }; 366 367 Plan plan(*vm, vector); 368 if (plan.result.size() != 1 || !plan.result[0]) { 369 dataLogLn("Module failed to compile correctly."); 370 CRASH(); 371 } 372 373 // Test this doesn't crash. 374 CHECK_EQ(invoke<int>(*plan.result[0], { box(0) }), 0); 375 CHECK_EQ(invoke<int>(*plan.result[0], { box(10) }), 10); 376 } 377 378 { 379 // Generated from: 380 // (module 381 // (func "dumb-mult" (param $x i32) (param $y i32) (result i32) (local $total i32) (local $i i32) (local $j i32) 382 // (set_local $total (i32.const 0)) 383 // (set_local $i (i32.const 0)) 384 // (block 385 // (loop 386 // (br_if 1 (i32.eq (get_local $i) (get_local $x))) 387 // (set_local $j (i32.const 0)) 388 // (set_local $i (i32.add (get_local $i) (i32.const 1))) 389 // (loop 390 // (br_if 1 (i32.eq (get_local $j) (get_local $y))) 391 // (set_local $total (i32.add (get_local $total) (i32.const 1))) 392 // (set_local $j (i32.add (get_local $j) (i32.const 1))) 393 // (br 0) 394 // ) 395 // ) 396 // ) 397 // (return (get_local $total)) 398 // ) 399 // ) 400 Vector<uint8_t> vector = { 401 0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x74, 0x79, 0x70, 0x65, 0x86, 0x80, 0x80, 402 0x00, 0x01, 0x40, 0x01, 0x01, 0x01, 0x01, 0x08, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 403 0x82, 0x80, 0x80, 0x00, 0x01, 0x00, 0x06, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x86, 0x80, 0x80, 404 0x00, 0x01, 0x00, 0x03, 0x73, 0x75, 0x6d, 0x04, 0x63, 0x6f, 0x64, 0x65, 0xae, 0x80, 0x80, 0x00, 405 0x01, 0xa9, 0x80, 0x80, 0x00, 0x01, 0x01, 0x01, 0x10, 0x00, 0x15, 0x01, 0x02, 0x01, 0x14, 0x00, 406 0x10, 0x00, 0x4d, 0x07, 0x00, 0x00, 0x14, 0x00, 0x14, 0x01, 0x40, 0x15, 0x01, 0x14, 0x00, 0x10, 407 0x01, 0x41, 0x15, 0x00, 0x06, 0x00, 0x01, 0x0f, 0x0f, 0x14, 0x01, 0x09, 0x01, 0x0f 408 }; 409 410 Plan plan(*vm, vector); 411 if (plan.result.size() != 1 || !plan.result[0]) { 412 dataLogLn("Module failed to compile correctly."); 413 CRASH(); 414 } 415 416 // Test this doesn't crash. 417 CHECK_EQ(invoke<int>(*plan.result[0], { box(0) }), 0); 418 CHECK_EQ(invoke<int>(*plan.result[0], { box(1) }), 1); 419 CHECK_EQ(invoke<int>(*plan.result[0], { box(2)}), 3); 420 CHECK_EQ(invoke<int>(*plan.result[0], { box(100) }), 5050); 421 } 422 423 { 424 // Generated from: 425 // (module 426 // (func "dumb-mult" (param $x i32) (param $y i32) (result i32) (local $total i32) (local $i i32) (local $j i32) 427 // (set_local $total (i32.const 0)) 428 // (set_local $i (i32.const 0)) 429 // (block (loop 430 // (br_if 1 (i32.eq (get_local $i) (get_local $x))) 431 // (set_local $j (i32.const 0)) 432 // (set_local $i (i32.add (get_local $i) (i32.const 1))) 433 // (loop 434 // (br_if 1 (i32.eq (get_local $j) (get_local $y))) 435 // (set_local $total (i32.add (get_local $total) (i32.const 1))) 436 // (set_local $j (i32.add (get_local $j) (i32.const 1))) 437 // (br 0) 438 // ) 439 // )) 440 // (return (get_local $total)) 441 // ) 442 // ) 443 Vector<uint8_t> vector = { 444 0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x74, 0x79, 0x70, 0x65, 0x87, 0x80, 0x80, 445 0x00, 0x01, 0x40, 0x02, 0x01, 0x01, 0x01, 0x01, 0x08, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 446 0x6e, 0x82, 0x80, 0x80, 0x00, 0x01, 0x00, 0x06, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x8c, 0x80, 447 0x80, 0x00, 0x01, 0x00, 0x09, 0x64, 0x75, 0x6d, 0x62, 0x2d, 0x6d, 0x75, 0x6c, 0x74, 0x04, 0x63, 448 0x6f, 0x64, 0x65, 0xc7, 0x80, 0x80, 0x00, 0x01, 0xc2, 0x80, 0x80, 0x00, 0x01, 0x03, 0x01, 0x10, 449 0x00, 0x15, 0x02, 0x10, 0x00, 0x15, 0x03, 0x01, 0x02, 0x14, 0x03, 0x14, 0x00, 0x4d, 0x07, 0x00, 450 0x01, 0x10, 0x00, 0x15, 0x04, 0x14, 0x03, 0x10, 0x01, 0x40, 0x15, 0x03, 0x02, 0x14, 0x04, 0x14, 451 0x01, 0x4d, 0x07, 0x00, 0x01, 0x14, 0x02, 0x10, 0x01, 0x40, 0x15, 0x02, 0x14, 0x04, 0x10, 0x01, 452 0x40, 0x15, 0x04, 0x06, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x14, 0x02, 0x09, 0x01, 0x0f 453 }; 454 455 Plan plan(*vm, vector); 456 if (plan.result.size() != 1 || !plan.result[0]) { 457 dataLogLn("Module failed to compile correctly."); 458 CRASH(); 459 } 460 461 // Test this doesn't crash. 462 CHECK_EQ(invoke<int>(*plan.result[0], { box(0), box(1) }), 0); 463 CHECK_EQ(invoke<int>(*plan.result[0], { box(1), box(0) }), 0); 464 CHECK_EQ(invoke<int>(*plan.result[0], { box(2), box(1) }), 2); 465 CHECK_EQ(invoke<int>(*plan.result[0], { box(1), box(2) }), 2); 466 CHECK_EQ(invoke<int>(*plan.result[0], { box(2), box(2) }), 4); 467 CHECK_EQ(invoke<int>(*plan.result[0], { box(2), box(6) }), 12); 468 CHECK_EQ(invoke<int>(*plan.result[0], { box(100), box(6) }), 600); 469 CHECK_EQ(invoke<int>(*plan.result[0], { box(100), box(100) }), 10000); 470 } 471 472 { 473 // Generated from: 474 // (module 475 // (func "dumb-less-than" (param $x i32) (param $y i32) (result i32) 476 // (loop 477 // (block 478 // (block 479 // (br_if 0 (i32.eq (get_local $x) (i32.const 0))) 480 // (br 1) 481 // ) 482 // (return (i32.const 1)) 483 // ) 484 // (block 485 // (block 486 // (br_if 0 (i32.eq (get_local $x) (get_local $y))) 487 // (br 1) 488 // ) 489 // (return (i32.const 0)) 490 // ) 491 // (set_local $x (i32.sub (get_local $x) (i32.const 1))) 492 // (br 0) 493 // ) 494 // ) 495 // ) 496 Vector<uint8_t> vector = { 497 0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x74, 0x79, 0x70, 0x65, 0x87, 0x80, 0x80, 498 0x00, 0x01, 0x40, 0x02, 0x01, 0x01, 0x01, 0x01, 0x08, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 499 0x6e, 0x82, 0x80, 0x80, 0x00, 0x01, 0x00, 0x06, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x91, 0x80, 500 0x80, 0x00, 0x01, 0x00, 0x0e, 0x64, 0x75, 0x6d, 0x62, 0x2d, 0x6c, 0x65, 0x73, 0x73, 0x2d, 0x74, 501 0x68, 0x61, 0x6e, 0x04, 0x63, 0x6f, 0x64, 0x65, 0xb9, 0x80, 0x80, 0x00, 0x01, 0xb4, 0x80, 0x80, 502 0x00, 0x00, 0x02, 0x01, 0x01, 0x14, 0x00, 0x14, 0x01, 0x4d, 0x07, 0x00, 0x00, 0x06, 0x00, 0x01, 503 0x0f, 0x10, 0x00, 0x09, 0x01, 0x0f, 0x01, 0x01, 0x14, 0x00, 0x10, 0x00, 0x4d, 0x07, 0x00, 0x00, 504 0x06, 0x00, 0x01, 0x0f, 0x10, 0x01, 0x09, 0x01, 0x0f, 0x14, 0x00, 0x10, 0x01, 0x41, 0x15, 0x00, 505 0x06, 0x00, 0x00, 0x0f, 0x0f 506 }; 507 508 Plan plan(*vm, vector); 509 if (plan.result.size() != 1 || !plan.result[0]) { 510 dataLogLn("Module failed to compile correctly."); 511 CRASH(); 512 } 513 514 // Test this doesn't crash. 515 CHECK_EQ(invoke<int>(*plan.result[0], { box(0), box(1) }), 1); 516 CHECK_EQ(invoke<int>(*plan.result[0], { box(1), box(0) }), 0); 517 CHECK_EQ(invoke<int>(*plan.result[0], { box(2), box(1) }), 0); 518 CHECK_EQ(invoke<int>(*plan.result[0], { box(1), box(2) }), 1); 519 CHECK_EQ(invoke<int>(*plan.result[0], { box(2), box(2) }), 0); 520 CHECK_EQ(invoke<int>(*plan.result[0], { box(1), box(1) }), 0); 521 CHECK_EQ(invoke<int>(*plan.result[0], { box(2), box(6) }), 1); 522 CHECK_EQ(invoke<int>(*plan.result[0], { box(100), box(6) }), 0); 523 } 524 337 525 } 338 526 -
trunk/Source/JavaScriptCore/wasm/WASMB3IRGenerator.cpp
r205330 r205552 30 30 31 31 #include "B3BasicBlockInlines.h" 32 #include "B3CallingConventions.h" 32 #include "B3FixSSA.h" 33 #include "B3Validate.h" 33 34 #include "B3ValueInlines.h" 34 35 #include "B3Variable.h" 35 36 #include "B3VariableValue.h" 36 37 #include "VirtualRegister.h" 38 #include "WASMCallingConvention.h" 37 39 #include "WASMFunctionParser.h" 38 40 #include <wtf/Optional.h> 39 41 40 namespace JSC { 41 42 namespace WASM{42 namespace JSC { namespace WASM { 43 44 namespace { 43 45 44 46 using namespace B3; 47 48 const bool verbose = false; 45 49 46 50 inline B3::Opcode toB3Op(BinaryOpType op) … … 65 69 66 70 class B3IRGenerator { 71 private: 72 class LazyBlock { 73 public: 74 explicit operator bool() { return !!m_block; } 75 76 BasicBlock* get(Procedure& proc) 77 { 78 if (!m_block) 79 m_block = proc.addBlock(); 80 return m_block; 81 } 82 83 void dump(PrintStream& out) const 84 { 85 if (m_block) 86 out.print(*m_block); 87 else 88 out.print("Uninitialized"); 89 } 90 91 private: 92 BasicBlock* m_block { nullptr }; 93 }; 94 95 struct ControlData { 96 ControlData(Optional<Vector<Variable*>>&& stack, BasicBlock* loopTarget = nullptr) 97 : loopTarget(loopTarget) 98 , stack(stack) 99 { 100 } 101 102 void dump(PrintStream& out) const 103 { 104 out.print("Continuation: ", continuation, ", Target: "); 105 if (loopTarget) 106 out.print(*loopTarget); 107 else 108 out.print(continuation); 109 } 110 111 BasicBlock* targetBlockForBranch(Procedure& proc) 112 { 113 if (loopTarget) 114 return loopTarget; 115 return continuation.get(proc); 116 } 117 118 bool isLoop() { return !!loopTarget; } 119 120 // We use a LazyBlock for the continuation since B3::validate does not like orphaned blocks. Note, 121 // it's possible to create an orphaned block by doing something like (block (return (...))). In 122 // that example, if we eagerly allocate a BasicBlock for the continuation it will never be reachable. 123 LazyBlock continuation; 124 BasicBlock* loopTarget; 125 Optional<Vector<Variable*>> stack; 126 }; 127 67 128 public: 68 129 typedef Value* ExpressionType; 130 static constexpr ExpressionType emptyExpression = nullptr; 69 131 70 132 B3IRGenerator(Procedure&); … … 75 137 76 138 bool WARN_UNUSED_RETURN getLocal(uint32_t index, ExpressionType& result); 139 bool WARN_UNUSED_RETURN setLocal(uint32_t index, ExpressionType value); 77 140 78 141 bool WARN_UNUSED_RETURN binaryOp(BinaryOpType, ExpressionType left, ExpressionType right, ExpressionType& result); … … 80 143 81 144 bool WARN_UNUSED_RETURN addBlock(); 82 bool WARN_UNUSED_RETURN endBlock(Vector<ExpressionType>& expressionStack); 145 bool WARN_UNUSED_RETURN addLoop(); 146 bool WARN_UNUSED_RETURN endBlock(Vector<ExpressionType, 1>& expressionStack); 147 83 148 bool WARN_UNUSED_RETURN addReturn(const Vector<ExpressionType, 1>& returnValues); 149 bool WARN_UNUSED_RETURN addBranch(ExpressionType condition, const Vector<ExpressionType, 1>& returnValues, uint32_t target); 150 151 void dumpGraphAndControlStack(); 84 152 85 153 private: 86 Optional<Vector<Variable*>>& stackForControlLevel(unsigned); 87 BasicBlock* blockForControlLevel(unsigned); 154 ControlData& controlDataForLevel(unsigned); 88 155 void unify(Variable* target, const ExpressionType source); 89 Vector<Variable*> initializeIncommingTypes(BasicBlock*, const Vector<ExpressionType>&); 90 void unifyValuesWithLevel(const Vector<ExpressionType>& resultStack, unsigned); 91 156 Vector<Variable*> initializeIncommingTypes(BasicBlock*, const Vector<ExpressionType, 1>&); 157 void unifyValuesWithBlock(const Vector<ExpressionType, 1>& resultStack, Optional<Vector<Variable*>>& stack, BasicBlock* target); 158 159 public: 160 unsigned unreachable { 0 }; 161 162 private: 92 163 Procedure& m_proc; 93 164 BasicBlock* m_currentBlock; 94 165 // This is a pair of the continuation and the types expected on the stack for that continuation. 95 Vector< std::pair<BasicBlock*, Optional<Vector<Variable*>>>> m_controlStack;166 Vector<ControlData> m_controlStack; 96 167 Vector<Variable*> m_locals; 97 168 }; … … 107 178 m_locals.reserveCapacity(m_locals.size() + count); 108 179 for (uint32_t i = 0; i < count; ++i) 109 m_locals.append(m_proc.addVariable(t ype));180 m_locals.append(m_proc.addVariable(toB3Type(type))); 110 181 } 111 182 112 183 void B3IRGenerator::addArguments(const Vector<Type>& types) 113 184 { 114 // TODO: Add locals.115 185 ASSERT(!m_locals.size()); 116 186 m_locals.grow(types.size()); … … 127 197 ASSERT(m_locals[index]); 128 198 result = m_currentBlock->appendNew<VariableValue>(m_proc, B3::Get, Origin(), m_locals[index]); 199 return true; 200 } 201 202 bool WARN_UNUSED_RETURN B3IRGenerator::setLocal(uint32_t index, ExpressionType value) 203 { 204 ASSERT(m_locals[index]); 205 m_currentBlock->appendNew<VariableValue>(m_proc, B3::Set, Origin(), m_locals[index], value); 129 206 return true; 130 207 } … … 161 238 bool B3IRGenerator::addBlock() 162 239 { 163 m_controlStack.append(std::make_pair(m_proc.addBlock(), Nullopt)); 164 return true; 165 } 166 167 bool B3IRGenerator::endBlock(Vector<ExpressionType>& expressionStack) 168 { 240 if (unreachable) { 241 unreachable++; 242 return true; 243 } 244 245 if (verbose) { 246 dataLogLn("Adding block"); 247 dumpGraphAndControlStack(); 248 } 249 m_controlStack.append(ControlData(Nullopt)); 250 251 return true; 252 } 253 254 bool B3IRGenerator::addLoop() 255 { 256 if (unreachable) { 257 unreachable++; 258 return true; 259 } 260 261 if (verbose) { 262 dataLogLn("Adding loop"); 263 dumpGraphAndControlStack(); 264 } 265 BasicBlock* body = m_proc.addBlock(); 266 m_currentBlock->appendNewControlValue(m_proc, Jump, Origin(), body); 267 body->addPredecessor(m_currentBlock); 268 m_currentBlock = body; 269 m_controlStack.append(ControlData(Vector<Variable*>(), body)); 270 return true; 271 } 272 273 bool B3IRGenerator::endBlock(Vector<ExpressionType, 1>& expressionStack) 274 { 275 if (unreachable > 1) { 276 unreachable--; 277 return true; 278 } 279 280 if (verbose) { 281 dataLogLn("Falling out of block"); 282 dumpGraphAndControlStack(); 283 } 169 284 // This means that we are exiting the function. 170 285 if (!m_controlStack.size()) { … … 173 288 } 174 289 175 unifyValuesWithLevel(expressionStack, 0); 176 177 m_currentBlock = m_controlStack.takeLast().first; 290 ControlData data = m_controlStack.takeLast(); 291 if (unreachable) { 292 // If nothing targets the continuation of the current block then we don't want to create 293 // an orphaned BasicBlock since it can't be reached by fallthrough. 294 if (data.continuation) { 295 m_currentBlock = data.continuation.get(m_proc); 296 unreachable--; 297 } 298 return true; 299 } 300 301 BasicBlock* continuation = data.continuation.get(m_proc); 302 unifyValuesWithBlock(expressionStack, data.stack, continuation); 303 m_currentBlock->appendNewControlValue(m_proc, Jump, Origin(), continuation); 304 continuation->addPredecessor(m_currentBlock); 305 m_currentBlock = continuation; 178 306 return true; 179 307 } … … 181 309 bool B3IRGenerator::addReturn(const Vector<ExpressionType, 1>& returnValues) 182 310 { 311 if (unreachable) 312 return true; 313 314 if (verbose) { 315 dataLogLn("Adding return"); 316 dumpGraphAndControlStack(); 317 } 318 183 319 ASSERT(returnValues.size() <= 1); 184 320 if (returnValues.size()) … … 186 322 else 187 323 m_currentBlock->appendNewControlValue(m_proc, B3::Return, Origin()); 324 unreachable = 1; 325 return true; 326 } 327 328 bool B3IRGenerator::addBranch(ExpressionType condition, const Vector<ExpressionType, 1>& returnValues, uint32_t level) 329 { 330 if (unreachable) 331 return true; 332 333 ASSERT(level < m_controlStack.size()); 334 ControlData& data = controlDataForLevel(level); 335 if (verbose) { 336 dataLogLn("Adding Branch from: ", *m_currentBlock, " targeting: ", level, " with data: ", data); 337 dumpGraphAndControlStack(); 338 } 339 340 341 BasicBlock* target = data.targetBlockForBranch(m_proc); 342 unifyValuesWithBlock(returnValues, data.stack, target); 343 if (condition) { 344 BasicBlock* continuation = m_proc.addBlock(); 345 m_currentBlock->appendNew<Value>(m_proc, B3::Branch, Origin(), condition); 346 m_currentBlock->setSuccessors(FrequentedBlock(target), FrequentedBlock(continuation)); 347 target->addPredecessor(m_currentBlock); 348 continuation->addPredecessor(m_currentBlock); 349 m_currentBlock = continuation; 350 } else { 351 m_currentBlock->appendNewControlValue(m_proc, Jump, Origin(), FrequentedBlock(target)); 352 target->addPredecessor(m_currentBlock); 353 unreachable = 1; 354 } 355 188 356 return true; 189 357 } … … 194 362 } 195 363 196 Vector<Variable*> B3IRGenerator::initializeIncommingTypes(BasicBlock* block, const Vector<ExpressionType >& source)364 Vector<Variable*> B3IRGenerator::initializeIncommingTypes(BasicBlock* block, const Vector<ExpressionType, 1>& source) 197 365 { 198 366 Vector<Variable*> result; 199 367 result.reserveInitialCapacity(source.size()); 200 368 for (ExpressionType expr : source) { 201 ASSERT(expr->type() != Void);369 ASSERT(expr->type() != B3::Void); 202 370 Variable* var = m_proc.addVariable(expr->type()); 203 371 result.append(var); … … 208 376 } 209 377 210 void B3IRGenerator::unifyValuesWithLevel(const Vector<ExpressionType>& resultStack, unsigned level) 211 { 212 ASSERT(level < m_controlStack.size()); 213 214 Optional<Vector<Variable*>>& expectedStack = stackForControlLevel(level); 215 if (!expectedStack) { 216 expectedStack = initializeIncommingTypes(blockForControlLevel(level), resultStack); 378 void B3IRGenerator::unifyValuesWithBlock(const Vector<ExpressionType, 1>& resultStack, Optional<Vector<Variable*>>& stack, BasicBlock* target) 379 { 380 if (!stack) { 381 stack = initializeIncommingTypes(target, resultStack); 217 382 return; 218 383 } 219 384 220 ASSERT( expectedStack.value().size() != resultStack.size());385 ASSERT(stack.value().size() == resultStack.size()); 221 386 222 387 for (size_t i = 0; i < resultStack.size(); ++i) 223 unify( expectedStack.value()[i], resultStack[i]);388 unify(stack.value()[i], resultStack[i]); 224 389 } 225 390 226 Optional<Vector<Variable*>>& B3IRGenerator::stackForControlLevel(unsigned level) 227 { 228 return m_controlStack[m_controlStack.size() - 1 - level].second; 229 } 230 231 BasicBlock* B3IRGenerator::blockForControlLevel(unsigned level) 232 { 233 return m_controlStack[m_controlStack.size() - 1 - level].first; 234 } 391 B3IRGenerator::ControlData& B3IRGenerator::controlDataForLevel(unsigned level) 392 { 393 return m_controlStack[m_controlStack.size() - 1 - level]; 394 } 395 396 void B3IRGenerator::dumpGraphAndControlStack() 397 { 398 dataLogLn("Processing Graph:"); 399 dataLog(m_proc); 400 dataLogLn("With current block:", *m_currentBlock); 401 dataLogLn("With Control Stack:"); 402 for (unsigned i = 0; i < m_controlStack.size(); ++i) 403 dataLogLn("[", i, "] ", m_controlStack[i]); 404 dataLogLn("\n"); 405 } 406 407 } // anonymous namespace 235 408 236 409 std::unique_ptr<Compilation> parseAndCompile(VM& vm, Vector<uint8_t>& source, FunctionInformation info, unsigned optLevel) … … 242 415 RELEASE_ASSERT_NOT_REACHED(); 243 416 417 validate(procedure, "After parsing:\n"); 418 419 fixSSA(procedure); 420 if (verbose) 421 dataLog("Post SSA: ", procedure); 244 422 return std::make_unique<Compilation>(vm, procedure, optLevel); 245 423 } 246 424 247 } // namespace WASM 248 249 } // namespace JSC 425 } } // namespace JSC::WASM 250 426 251 427 #endif // ENABLE(WEBASSEMBLY) -
trunk/Source/JavaScriptCore/wasm/WASMB3IRGenerator.h
r205309 r205552 32 32 #include "WASMFormat.h" 33 33 34 namespace JSC { 35 36 namespace WASM { 34 namespace JSC { namespace WASM { 37 35 38 36 std::unique_ptr<B3::Compilation> parseAndCompile(VM&, Vector<uint8_t>&, FunctionInformation, unsigned optLevel = 1); 39 37 40 } // namespace WASM 41 42 } // namespace JSC 38 } } // namespace JSC::WASM 43 39 44 40 #endif // ENABLE(WEBASSEMBLY) -
trunk/Source/JavaScriptCore/wasm/WASMCallingConvention.cpp
r205550 r205552 25 25 26 26 #include "config.h" 27 #include "B3CallingConventions.h" 27 #include "WASMCallingConvention.h" 28 29 #if ENABLE(WEBASSEMBLY) 28 30 29 31 #include <wtf/NeverDestroyed.h> 30 32 31 #if ENABLE(B3_JIT) 33 namespace JSC { namespace WASM { 32 34 33 namespace JSC { 34 35 namespace B3 { 36 37 JSCCallingConvention& jscCallingConvention() 35 const JSCCallingConvention& jscCallingConvention() 38 36 { 39 37 static LazyNeverDestroyed<JSCCallingConvention> staticJSCCallingConvention; … … 46 44 } 47 45 48 } // namespace B3 49 50 } // namespace JSC 46 } } // namespace JSC::WASM 51 47 52 48 #endif // ENABLE(B3_JIT) -
trunk/Source/JavaScriptCore/wasm/WASMCallingConvention.h
r205550 r205552 26 26 #pragma once 27 27 28 #if ENABLE( B3_JIT)28 #if ENABLE(WEBASSEMBLY) 29 29 30 30 #include "B3ArgumentRegValue.h" … … 32 32 #include "B3Const64Value.h" 33 33 #include "B3MemoryValue.h" 34 #include "B3Type.h"35 34 #include "CallFrame.h" 36 35 #include "RegisterSet.h" 36 #include "WASMFormat.h" 37 37 38 namespace JSC { 39 40 namespace B3 { 38 namespace JSC { namespace WASM { 41 39 42 40 typedef unsigned (*NextOffset)(unsigned currentOffset, Type type); … … 54 52 55 53 template<typename Functor> 56 void iterate(const Vector<Type>& argumentTypes, Procedure& proc, BasicBlock* block,Origin origin, const Functor& functor) const54 void iterate(const Vector<Type>& argumentTypes, B3::Procedure& proc, B3::BasicBlock* block, B3::Origin origin, const Functor& functor) const 57 55 { 58 56 unsigned currentOffset = headerSize; 59 Value* framePointer = block->appendNew<Value>(proc,FramePointer, origin);57 B3::Value* framePointer = block->appendNew<B3::Value>(proc, B3::FramePointer, origin); 60 58 61 59 for (unsigned i = 0; i < argumentTypes.size(); ++i) { 62 Value* argument;60 B3::Value* argument; 63 61 if (i < m_registerArguments.size()) 64 argument = block->appendNew< ArgumentRegValue>(proc, origin, m_registerArguments[i]);62 argument = block->appendNew<B3::ArgumentRegValue>(proc, origin, m_registerArguments[i]); 65 63 else { 66 Value* address = block->appendNew<Value>(proc,Add, origin, framePointer,67 block->appendNew< Const64Value>(proc, origin, currentOffset));68 argument = block->appendNew< MemoryValue>(proc, Load, argumentTypes[i], origin, address);64 B3::Value* address = block->appendNew<B3::Value>(proc, B3::Add, origin, framePointer, 65 block->appendNew<B3::Const64Value>(proc, origin, currentOffset)); 66 argument = block->appendNew<B3::MemoryValue>(proc, B3::Load, toB3Type(argumentTypes[i]), origin, address); 69 67 currentOffset = updateOffset(currentOffset, argumentTypes[i]); 70 68 } … … 86 84 typedef CallingConvention<jscHeaderSize, nextJSCOffset> JSCCallingConvention; 87 85 88 JSCCallingConvention& jscCallingConvention();86 const JSCCallingConvention& jscCallingConvention(); 89 87 90 } // namespace B388 } } // namespace JSC::WASM 91 89 92 } // namespace JSC 93 94 #endif // ENABLE(B3_JIT) 90 #endif // ENABLE(WEBASSEMBLY) -
trunk/Source/JavaScriptCore/wasm/WASMFormat.h
r205330 r205552 55 55 namespace WASM { 56 56 57 using B3::Type; 58 using B3::Int32; 59 using B3::Int64; 60 using B3::Float; 61 using B3::Double; 57 enum Type : uint8_t { 58 I32 = 1, 59 I64, 60 F32, 61 F64, 62 LastValueType = F64, 63 Void 64 }; 62 65 63 static_assert(Int32 == 0, "WASM needs B3::Type::Int32 to have the value 0"); 64 static_assert(Int64 == 1, "WASM needs B3::Type::Int64 to have the value 1"); 65 static_assert(Float == 2, "WASM needs B3::Type::Float to have the value 2"); 66 static_assert(Double == 3, "WASM needs B3::Type::Double to have the value 3"); 66 static_assert(I32 == 1, "WASM needs I32 to have the value 1"); 67 static_assert(I64 == 2, "WASM needs I64 to have the value 2"); 68 static_assert(F32 == 3, "WASM needs F32 to have the value 3"); 69 static_assert(F64 == 4, "WASM needs F64 to have the value 4"); 70 71 inline B3::Type toB3Type(Type type) 72 { 73 switch (type) { 74 case I32: return B3::Int32; 75 case I64: return B3::Int64; 76 case F32: return B3::Float; 77 case F64: return B3::Double; 78 case Void: return B3::Void; 79 default: break; 80 } 81 RELEASE_ASSERT_NOT_REACHED(); 82 } 83 84 inline bool isValueType(Type type) 85 { 86 switch (type) { 87 case I32: 88 case I64: 89 case F32: 90 case F64: 91 return true; 92 default: 93 break; 94 } 95 return false; 96 } 97 67 98 68 99 struct Signature { … … 96 127 }; 97 128 98 } // namespace WASM 99 100 } // namespace JSC 129 } } // namespace JSC::WASM 101 130 102 131 #endif // ENABLE(WEBASSEMBLY) -
trunk/Source/JavaScriptCore/wasm/WASMFunctionParser.h
r205330 r205552 31 31 #include <wtf/DataLog.h> 32 32 33 namespace JSC { 34 35 namespace WASM { 33 namespace JSC { namespace WASM { 36 34 37 35 template<typename Context> … … 54 52 55 53 Context& m_context; 56 Vector<ExpressionType > m_expressionStack;54 Vector<ExpressionType, 1> m_expressionStack; 57 55 }; 58 56 … … 73 71 74 72 for (uint32_t i = 0; i < localCount; ++i) { 75 uint32_t numberOfLocals WithType;76 if (!parse UInt32(numberOfLocalsWithType))73 uint32_t numberOfLocals; 74 if (!parseVarUInt32(numberOfLocals)) 77 75 return false; 78 76 … … 81 79 return false; 82 80 81 m_context.addLocal(typeOfLocal, numberOfLocals); 83 82 } 84 83 … … 110 109 bool FunctionParser<Context>::parseExpression(OpType op) 111 110 { 111 if (m_context.unreachable && !isControlOp(op)) 112 return true; 113 112 114 switch (op) { 113 115 #define CREATE_CASE(name, id, b3op) case name: 114 116 FOR_EACH_WASM_BINARY_OP(CREATE_CASE) { 117 ExpressionType right = m_expressionStack.takeLast(); 115 118 ExpressionType left = m_expressionStack.takeLast(); 116 ExpressionType right = m_expressionStack.takeLast();117 119 ExpressionType result; 118 120 if (!m_context.binaryOp(static_cast<BinaryOpType>(op), left, right, result)) … … 136 138 if (!parseVarUInt32(constant)) 137 139 return false; 138 m_expressionStack.append(m_context.addConstant(I nt32, constant));140 m_expressionStack.append(m_context.addConstant(I32, constant)); 139 141 return true; 140 142 } … … 152 154 } 153 155 156 case OpType::SetLocal: { 157 uint32_t index; 158 if (!parseVarUInt32(index)) 159 return false; 160 ExpressionType value = m_expressionStack.takeLast(); 161 return m_context.setLocal(index, value); 162 } 163 154 164 case OpType::Block: { 155 165 if (!m_context.addBlock()) 156 166 return false; 157 167 return parseBlock(); 168 } 169 170 case OpType::Loop: { 171 if (!m_context.addLoop()) 172 return false; 173 return parseBlock(); 174 } 175 176 case OpType::Branch: 177 case OpType::BranchIf: { 178 uint32_t arity; 179 if (!parseVarUInt32(arity) || arity > m_expressionStack.size()) 180 return false; 181 182 uint32_t target; 183 if (!parseVarUInt32(target)) 184 return false; 185 186 ExpressionType condition = Context::emptyExpression; 187 if (op == OpType::BranchIf) 188 condition = m_expressionStack.takeLast(); 189 190 191 Vector<ExpressionType, 1> values(arity); 192 for (unsigned i = arity; i; i--) 193 values[i-1] = m_expressionStack.takeLast(); 194 195 return m_context.addBranch(condition, values, target); 158 196 } 159 197 … … 178 216 } 179 217 180 } // namespace WASM 181 182 } // namespace JSC 218 } } // namespace JSC::WASM 183 219 184 220 #endif // ENABLE(WEBASSEMBLY) -
trunk/Source/JavaScriptCore/wasm/WASMModuleParser.cpp
r205330 r205552 33 33 #include "WASMSections.h" 34 34 35 namespace JSC { 36 37 namespace WASM { 35 namespace JSC { namespace WASM { 38 36 39 37 static const bool verbose = false; … … 164 162 165 163 for (unsigned i = 0; i < argumentCount; ++i) { 166 if (!parseUInt7(type) || type >= static_cast<uint8_t>(Type::LastValueType))167 return false; 168 argumentTypes .append(static_cast<Type>(type));164 if (!parseUInt7(type) || !isValueType(static_cast<Type>(type))) 165 return false; 166 argumentTypes[i] = static_cast<Type>(type); 169 167 } 170 168 … … 234 232 } 235 233 236 } // namespace WASM 237 238 } // namespace JSC 234 } } // namespace JSC::WASM 239 235 240 236 #endif // ENABLE(WEBASSEMBLY) -
trunk/Source/JavaScriptCore/wasm/WASMModuleParser.h
r205330 r205552 32 32 #include <wtf/Vector.h> 33 33 34 namespace JSC { 35 36 namespace WASM { 34 namespace JSC { namespace WASM { 37 35 38 36 class ModuleParser : public Parser { … … 62 60 }; 63 61 64 } // namespace WASM 65 66 } // namespace JSC 62 } } // namespace JSC::WASM 67 63 68 64 #endif // ENABLE(WEBASSEMBLY) -
trunk/Source/JavaScriptCore/wasm/WASMOps.h
r205330 r205552 28 28 #if ENABLE(WEBASSEMBLY) 29 29 30 namespace JSC { 31 32 namespace WASM { 30 namespace JSC { namespace WASM { 33 31 34 32 #define FOR_EACH_WASM_SPECIAL_OP(macro) \ 35 33 macro(I32Const, 0x10, NA) \ 36 macro(GetLocal, 0x14, NA) 34 macro(GetLocal, 0x14, NA) \ 35 macro(SetLocal, 0x15, NA) 37 36 38 37 #define FOR_EACH_WASM_CONTROL_FLOW_OP(macro) \ 39 38 macro(Block, 0x01, NA) \ 39 macro(Loop, 0x02, NA) \ 40 macro(Branch, 0x06, NA) \ 41 macro(BranchIf, 0x07, NA) \ 40 42 macro(Return, 0x09, NA) \ 41 43 macro(End, 0x0f, NA) … … 122 124 #undef CREATE_ENUM_VALUE 123 125 124 } // namespace WASM 126 inline bool isControlOp(OpType op) 127 { 128 switch (op) { 129 #define CREATE_CASE(name, id, b3op) case OpType::name: 130 FOR_EACH_WASM_CONTROL_FLOW_OP(CREATE_CASE) 131 return true; 132 #undef CREATE_CASE 133 default: 134 break; 135 } 136 return false; 137 } 125 138 126 } // namespace JSC139 } } // namespace JSC::WASM 127 140 128 141 #endif // ENABLE(WEBASSEMBLY) -
trunk/Source/JavaScriptCore/wasm/WASMParser.h
r205309 r205552 35 35 #include <wtf/LEBDecoder.h> 36 36 37 namespace JSC { 38 39 namespace WASM { 37 namespace JSC { namespace WASM { 40 38 41 39 class Parser { … … 128 126 } 129 127 130 } // namespace WASM 131 132 } // namespace JSC 128 } } // namespace JSC::WASM 133 129 134 130 #endif // ENABLE(WEBASSEMBLY) -
trunk/Source/JavaScriptCore/wasm/WASMPlan.cpp
r205309 r205552 34 34 #include <wtf/DataLog.h> 35 35 36 namespace JSC { 37 38 namespace WASM { 36 namespace JSC { namespace WASM { 39 37 40 38 static const bool verbose = false; … … 60 58 } 61 59 62 } // namespace WASM 63 64 } // namespace JSC 60 } } // namespace JSC::WASM 65 61 66 62 #endif // ENABLE(WEBASSEMBLY) -
trunk/Source/JavaScriptCore/wasm/WASMPlan.h
r205021 r205552 49 49 }; 50 50 51 } // namespace WASM 52 53 } // namespace JSC 51 } } // namespace JSC::WASM 54 52 55 53 #endif // ENABLE(WEBASSEMBLY) -
trunk/Source/JavaScriptCore/wasm/WASMSections.cpp
r205309 r205552 32 32 #include <wtf/text/WTFString.h> 33 33 34 namespace JSC { 35 36 namespace WASM { 34 namespace JSC { namespace WASM { 37 35 38 36 struct SectionData { … … 63 61 } 64 62 65 } // namespace WASM 66 67 } // namespace JSC 63 } } // namespace JSC::WASM 68 64 69 65 #endif // ENABLE(WEBASSEMBLY) -
trunk/Source/JavaScriptCore/wasm/WASMSections.h
r205309 r205552 28 28 #if ENABLE(WEBASSEMBLY) 29 29 30 namespace JSC { 31 32 namespace WASM { 30 namespace JSC { namespace WASM { 33 31 34 32 // These should be in the order that we expect them to be in the binary. … … 57 55 }; 58 56 59 } // namespace WASM 60 61 } // namespace JSC 57 } } // namespace JSC::WASM 62 58 63 59 #endif // ENABLE(WEBASSEMBLY)
Note: See TracChangeset
for help on using the changeset viewer.