Changeset 205552 in webkit


Ignore:
Timestamp:
Sep 7, 2016 10:12:08 AM (8 years ago)
Author:
keith_miller@apple.com
Message:

Add support for WASM Loops and Branches
https://bugs.webkit.org/show_bug.cgi?id=161569

Reviewed by Benjamin Poulain.

This patch adds support for loops and branches to WASM. In order
to support loops, we needed to change the way the B3IRGenerator
tracked control information. Now, the control data holds three
pieces of information: The continuation block, the loop branch
target, and variables exiting the block. Whenever we branch to
some control point we first check if it is a loop by checking that
the loop branch target is non-null. If the branch is not targeting
a loop, we map the stack values to the associated B3 variables for
that stack slot.

Another interesting thing of note is that we now only allocate the
continuation basic block lazily. This is beneficial when the
continuation would just fall through to another block anyway. For
example, in code like: (block ... (block (add 1 2) end) end) the
continuation for the inner block just falls through to the outer
block's continuation so we don't need an extra block.

  • B3CallingConventions.cpp:

(JSC::B3::jscCallingConvention): Deleted.

  • B3CallingConventions.h:

(JSC::B3::CallingConvention::CallingConvention): Deleted.
(JSC::B3::CallingConvention::iterate): Deleted.
(JSC::B3::nextJSCOffset): Deleted.

(runWASMTests):

  • wasm/WASMB3IRGenerator.cpp:

(JSC::WASM::B3IRGenerator::LazyBlock::LazyBlock):
(JSC::WASM::B3IRGenerator::LazyBlock::operator bool):
(JSC::WASM::B3IRGenerator::LazyBlock::get):
(JSC::WASM::B3IRGenerator::LazyBlock::dump):
(JSC::WASM::B3IRGenerator::ControlData::ControlData):
(JSC::WASM::B3IRGenerator::ControlData::dump):
(JSC::WASM::B3IRGenerator::ControlData::targetBlockForBranch):
(JSC::WASM::B3IRGenerator::ControlData::isLoop):
(JSC::WASM::B3IRGenerator::addLocal):
(JSC::WASM::B3IRGenerator::addArguments):
(JSC::WASM::B3IRGenerator::setLocal):
(JSC::WASM::B3IRGenerator::addBlock):
(JSC::WASM::B3IRGenerator::addLoop):
(JSC::WASM::B3IRGenerator::endBlock):
(JSC::WASM::B3IRGenerator::addReturn):
(JSC::WASM::B3IRGenerator::addBranch):
(JSC::WASM::B3IRGenerator::initializeIncommingTypes):
(JSC::WASM::B3IRGenerator::unifyValuesWithBlock):
(JSC::WASM::B3IRGenerator::controlDataForLevel):
(JSC::WASM::B3IRGenerator::dumpGraphAndControlStack):
(JSC::WASM::parseAndCompile):
(JSC::WASM::B3IRGenerator::unifyValuesWithLevel): Deleted.
(JSC::WASM::B3IRGenerator::stackForControlLevel): Deleted.
(JSC::WASM::B3IRGenerator::blockForControlLevel): Deleted.

  • wasm/WASMCallingConvention.cpp: Renamed from Source/JavaScriptCore/B3CallingConventions.cpp.

(JSC::WASM::jscCallingConvention):

  • wasm/WASMCallingConvention.h: Renamed from Source/JavaScriptCore/B3CallingConventions.h.

(JSC::WASM::CallingConvention::CallingConvention):
(JSC::WASM::CallingConvention::iterate):
(JSC::WASM::nextJSCOffset):

  • wasm/WASMFormat.h:

(JSC::WASM::toB3Type):
(JSC::WASM::isValueType):

  • wasm/WASMFunctionParser.h:

(JSC::WASM::FunctionParser<Context>::parse):
(JSC::WASM::FunctionParser<Context>::parseExpression):

  • wasm/WASMModuleParser.cpp:

(JSC::WASM::ModuleParser::parseFunctionTypes):

  • wasm/WASMOps.h:
Location:
trunk/Source/JavaScriptCore
Files:
17 edited
2 moved

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/CMakeLists.txt

    r205520 r205552  
    855855    wasm/WASMPlan.cpp
    856856    wasm/WASMSections.cpp
     857    wasm/WASMCallingConventions.cpp
    857858
    858859    yarr/RegularExpression.cpp
  • trunk/Source/JavaScriptCore/ChangeLog

    r205549 r205552  
     12016-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
    1762016-09-07  Youenn Fablet  <youenn@apple.com>
    277
  • trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj

    r205520 r205552  
    11961196                531374BD1D5CE67600AF7A0B /* WASMPlan.h in Headers */ = {isa = PBXBuildFile; fileRef = 531374BC1D5CE67600AF7A0B /* WASMPlan.h */; };
    11971197                531374BF1D5CE95000AF7A0B /* WASMPlan.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 531374BE1D5CE95000AF7A0B /* WASMPlan.cpp */; };
    1198                 531B3C871D74C603005B3236 /* B3CallingConventions.h in Headers */ = {isa = PBXBuildFile; fileRef = 531B3C861D74C603005B3236 /* B3CallingConventions.h */; };
    11991198                53486BB71C1795C300F6F3AF /* JSTypedArray.h in Headers */ = {isa = PBXBuildFile; fileRef = 53486BB61C1795C300F6F3AF /* JSTypedArray.h */; settings = {ATTRIBUTES = (Public, ); }; };
    12001199                53486BBB1C18E84500F6F3AF /* JSTypedArray.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 53486BBA1C18E84500F6F3AF /* JSTypedArray.cpp */; };
     
    12051204                5370B4F51BF26202005C40FC /* AdaptiveInferredPropertyValueWatchpointBase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5370B4F31BF25EA2005C40FC /* AdaptiveInferredPropertyValueWatchpointBase.cpp */; };
    12061205                5370B4F61BF26205005C40FC /* AdaptiveInferredPropertyValueWatchpointBase.h in Headers */ = {isa = PBXBuildFile; fileRef = 5370B4F41BF25EA2005C40FC /* AdaptiveInferredPropertyValueWatchpointBase.h */; };
    1207                 5388B4041D76640B00D3D852 /* B3CallingConventions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5388B4031D76640B00D3D852 /* B3CallingConventions.cpp */; };
    12081206                53917E7B1B7906FA000EBD33 /* JSGenericTypedArrayViewPrototypeFunctions.h in Headers */ = {isa = PBXBuildFile; fileRef = 53917E7A1B7906E4000EBD33 /* JSGenericTypedArrayViewPrototypeFunctions.h */; };
    12091207                539EB0791D55607000C82EF7 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 51F0EB6105C86C6B00E6DF1B /* Foundation.framework */; };
     
    12231221                53FA2AE11CF37F3F0022711D /* LLIntPrototypeLoadAdaptiveStructureWatchpoint.h in Headers */ = {isa = PBXBuildFile; fileRef = 53FA2AE01CF37F3F0022711D /* LLIntPrototypeLoadAdaptiveStructureWatchpoint.h */; settings = {ATTRIBUTES = (Private, ); }; };
    12241222                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 */; };
    12251225                5D5D8AD10E0D0EBE00F9C692 /* libedit.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 5D5D8AD00E0D0EBE00F9C692 /* libedit.dylib */; };
    12261226                5DBB151B131D0B310056AD36 /* testapi.js in Copy Support Script */ = {isa = PBXBuildFile; fileRef = 14D857740A4696C80032146C /* testapi.js */; };
     
    34103410                531374BC1D5CE67600AF7A0B /* WASMPlan.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WASMPlan.h; sourceTree = "<group>"; };
    34113411                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>"; };
    34133412                53486BB61C1795C300F6F3AF /* JSTypedArray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSTypedArray.h; sourceTree = "<group>"; };
    34143413                53486BBA1C18E84500F6F3AF /* JSTypedArray.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSTypedArray.cpp; sourceTree = "<group>"; };
     
    34213420                5370B4F31BF25EA2005C40FC /* AdaptiveInferredPropertyValueWatchpointBase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AdaptiveInferredPropertyValueWatchpointBase.cpp; sourceTree = "<group>"; };
    34223421                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>"; };
    34243422                53917E7A1B7906E4000EBD33 /* JSGenericTypedArrayViewPrototypeFunctions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSGenericTypedArrayViewPrototypeFunctions.h; sourceTree = "<group>"; };
    34253423                53917E7C1B791106000EBD33 /* JSTypedArrayViewPrototype.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSTypedArrayViewPrototype.h; sourceTree = "<group>"; };
     
    34413439                53FA2AE01CF37F3F0022711D /* LLIntPrototypeLoadAdaptiveStructureWatchpoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LLIntPrototypeLoadAdaptiveStructureWatchpoint.h; sourceTree = "<group>"; };
    34423440                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>"; };
    34433443                593D43CCA0BBE06D89C59707 /* MapDataInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MapDataInlines.h; sourceTree = "<group>"; };
    34443444                5D5D8AD00E0D0EBE00F9C692 /* libedit.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libedit.dylib; path = /usr/lib/libedit.dylib; sourceTree = "<absolute>"; };
     
    48204820                                0F6B8ADE1C4EFE1700969052 /* B3BreakCriticalEdges.cpp */,
    48214821                                0F6B8ADF1C4EFE1700969052 /* B3BreakCriticalEdges.h */,
    4822                                 5388B4031D76640B00D3D852 /* B3CallingConventions.cpp */,
    4823                                 531B3C861D74C603005B3236 /* B3CallingConventions.h */,
    48244822                                DC9A0C1C1D2D94EF0085124E /* B3CaseCollection.cpp */,
    48254823                                DC9A0C1D1D2D94EF0085124E /* B3CaseCollection.h */,
     
    56295627                                7B98D1341B60CD5A0023B1A4 /* JSWASMModule.cpp */,
    56305628                                7B98D1351B60CD5A0023B1A4 /* JSWASMModule.h */,
     5629                                53F40E8E1D5902820099A1B6 /* WASMB3IRGenerator.cpp */,
     5630                                53F40E921D5A4AB30099A1B6 /* WASMB3IRGenerator.h */,
     5631                                53FD04D11D7AB187003287D3 /* WASMCallingConvention.cpp */,
     5632                                53FD04D21D7AB187003287D3 /* WASMCallingConvention.h */,
    56315633                                53F40E901D5903020099A1B6 /* WASMOps.h */,
    56325634                                7BC547D21B69599B00959B58 /* WASMFormat.h */,
    5633                                 53F40E8E1D5902820099A1B6 /* WASMB3IRGenerator.cpp */,
    5634                                 53F40E921D5A4AB30099A1B6 /* WASMB3IRGenerator.h */,
    56355635                                53F40E8A1D5901BB0099A1B6 /* WASMFunctionParser.h */,
    56365636                                53F40E961D5A7BEC0099A1B6 /* WASMModuleParser.cpp */,
     
    82968296                                705B41B01A6E501E00716757 /* SymbolObject.h in Headers */,
    82978297                                0F33FCFC1C1625BE00323F67 /* B3Dominators.h in Headers */,
     8298                                53FD04D41D7AB291003287D3 /* WASMCallingConvention.h in Headers */,
    82988299                                705B41B21A6E501E00716757 /* SymbolPrototype.h in Headers */,
    82998300                                996B73281BDA08EF00331B84 /* SymbolPrototype.lut.h in Headers */,
     
    83448345                                0F963B3813FC6FE90002D9B2 /* ValueProfile.h in Headers */,
    83458346                                0F426A481460CBB300131F8F /* ValueRecovery.h in Headers */,
    8346                                 531B3C871D74C603005B3236 /* B3CallingConventions.h in Headers */,
    83478347                                79EE0C001B4AFB85000385C9 /* VariableEnvironment.h in Headers */,
    83488348                                0F6C73511AC9F99F00BE1682 /* VariableWriteFireDetail.h in Headers */,
     
    89978997                                C2FCAE1217A9C24E0034C735 /* BytecodeLivenessAnalysis.cpp in Sources */,
    89988998                                0F338E0D1BF0276C0013C88F /* B3DataSection.cpp in Sources */,
    8999                                 5388B4041D76640B00D3D852 /* B3CallingConventions.cpp in Sources */,
    90008999                                65B8392F1BACAD6A0044E824 /* CachedRecovery.cpp in Sources */,
    90019000                                1428082D107EC0570013E7B2 /* CallData.cpp in Sources */,
     
    91309129                                FEA0C4021CDD7D1D00481991 /* FunctionWhitelist.cpp in Sources */,
    91319130                                A73A535A1799CD5D00170C19 /* DFGLazyJSValue.cpp in Sources */,
     9131                                53FD04D31D7AB277003287D3 /* WASMCallingConvention.cpp in Sources */,
    91329132                                62F2AA371B0BEDE300610C7A /* DFGLazyNode.cpp in Sources */,
    91339133                                A7D9A29717A0BC7400EE2618 /* DFGLICMPhase.cpp in Sources */,
  • trunk/Source/JavaScriptCore/b3/B3Type.h

    r205309 r205552  
    4040
    4141enum Type : int8_t {
     42    Void,
    4243    Int32,
    4344    Int64,
    4445    Float,
    4546    Double,
    46     LastValueType = Double,
    47     Void
    4847};
    4948
  • trunk/Source/JavaScriptCore/testWASM.cpp

    r205330 r205552  
    8383}
    8484
     85StaticLock 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
    8597#define FOR_EACH_UNSIGNED_LEB_TEST(macro) \
    8698    /* 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) \
    94106    /* 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) \
    99111    /* 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) \
    105117    /* 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) \
    111123    /* 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) \
    115127    /* 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) \
    117129
    118130
     
    123135        uint32_t result; \
    124136        bool status = decodeUInt32(vector.data(), vector.size(), offset, result); \
    125         RELEASE_ASSERT(status == expectedStatus); \
     137        CHECK_EQ(status, expectedStatus); \
    126138        if (expectedStatus) { \
    127             RELEASE_ASSERT(result == expectedResult); \
    128             RELEASE_ASSERT(offset == expectedOffset); \
     139            CHECK_EQ(result, expectedResult); \
     140            CHECK_EQ(offset, expectedOffset); \
    129141        } \
    130142    };
     
    133145#define FOR_EACH_SIGNED_LEB_TEST(macro) \
    134146    /* 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) \
    142154    /* 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) \
    147159    /* 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) \
    153165    /* 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) \
    159171    /* 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) \
    163175    /* 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) \
    165177
    166178
     
    171183        int32_t result; \
    172184        bool status = decodeInt32(vector.data(), vector.size(), offset, result); \
    173         RELEASE_ASSERT(status == expectedStatus); \
     185        CHECK_EQ(status, expectedStatus); \
    174186        if (expectedStatus) { \
    175187            int32_t expected = expectedResult; \
    176             RELEASE_ASSERT(result == expected); \
    177             RELEASE_ASSERT(offset == expectedOffset); \
     188            CHECK_EQ(result, expected); \
     189            CHECK_EQ(offset, expectedOffset); \
    178190        } \
    179191    };
     
    247259
    248260        // Test this doesn't crash.
    249         RELEASE_ASSERT(invoke<int>(*plan.result[0], { }) == 5);
     261        CHECK_EQ(invoke<int>(*plan.result[0], { }), 5);
    250262    }
    251263
     
    269281
    270282        // Test this doesn't crash.
    271         RELEASE_ASSERT(invoke<int>(*plan.result[0], { }) == 11);
     283        CHECK_EQ(invoke<int>(*plan.result[0], { }), 11);
    272284    }
    273285   
     
    290302
    291303        // Test this doesn't crash.
    292         RELEASE_ASSERT(invoke<int>(*plan.result[0], { }) == 11);
     304        CHECK_EQ(invoke<int>(*plan.result[0], { }), 11);
    293305    }
    294306
     
    311323
    312324        // Test this doesn't crash.
    313         RELEASE_ASSERT(invoke<int>(*plan.result[0], { }) == 11);
     325        CHECK_EQ(invoke<int>(*plan.result[0], { }), 11);
    314326    }
    315327
     
    330342
    331343        // 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
    337525}
    338526
  • trunk/Source/JavaScriptCore/wasm/WASMB3IRGenerator.cpp

    r205330 r205552  
    3030
    3131#include "B3BasicBlockInlines.h"
    32 #include "B3CallingConventions.h"
     32#include "B3FixSSA.h"
     33#include "B3Validate.h"
    3334#include "B3ValueInlines.h"
    3435#include "B3Variable.h"
    3536#include "B3VariableValue.h"
    3637#include "VirtualRegister.h"
     38#include "WASMCallingConvention.h"
    3739#include "WASMFunctionParser.h"
    3840#include <wtf/Optional.h>
    3941
    40 namespace JSC {
    41 
    42 namespace WASM {
     42namespace JSC { namespace WASM {
     43
     44namespace {
    4345
    4446using namespace B3;
     47
     48const bool verbose = false;
    4549
    4650inline B3::Opcode toB3Op(BinaryOpType op)
     
    6569
    6670class B3IRGenerator {
     71private:
     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
    67128public:
    68129    typedef Value* ExpressionType;
     130    static constexpr ExpressionType emptyExpression = nullptr;
    69131
    70132    B3IRGenerator(Procedure&);
     
    75137
    76138    bool WARN_UNUSED_RETURN getLocal(uint32_t index, ExpressionType& result);
     139    bool WARN_UNUSED_RETURN setLocal(uint32_t index, ExpressionType value);
    77140
    78141    bool WARN_UNUSED_RETURN binaryOp(BinaryOpType, ExpressionType left, ExpressionType right, ExpressionType& result);
     
    80143
    81144    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
    83148    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();
    84152
    85153private:
    86     Optional<Vector<Variable*>>& stackForControlLevel(unsigned);
    87     BasicBlock* blockForControlLevel(unsigned);
     154    ControlData& controlDataForLevel(unsigned);
    88155    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
     159public:
     160    unsigned unreachable { 0 };
     161
     162private:
    92163    Procedure& m_proc;
    93164    BasicBlock* m_currentBlock;
    94165    // 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;
    96167    Vector<Variable*> m_locals;
    97168};
     
    107178    m_locals.reserveCapacity(m_locals.size() + count);
    108179    for (uint32_t i = 0; i < count; ++i)
    109         m_locals.append(m_proc.addVariable(type));
     180        m_locals.append(m_proc.addVariable(toB3Type(type)));
    110181}
    111182
    112183void B3IRGenerator::addArguments(const Vector<Type>& types)
    113184{
    114     // TODO: Add locals.
    115185    ASSERT(!m_locals.size());
    116186    m_locals.grow(types.size());
     
    127197    ASSERT(m_locals[index]);
    128198    result = m_currentBlock->appendNew<VariableValue>(m_proc, B3::Get, Origin(), m_locals[index]);
     199    return true;
     200}
     201
     202bool 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);
    129206    return true;
    130207}
     
    161238bool B3IRGenerator::addBlock()
    162239{
    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
     254bool 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
     273bool 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    }
    169284    // This means that we are exiting the function.
    170285    if (!m_controlStack.size()) {
     
    173288    }
    174289
    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;
    178306    return true;
    179307}
     
    181309bool B3IRGenerator::addReturn(const Vector<ExpressionType, 1>& returnValues)
    182310{
     311    if (unreachable)
     312        return true;
     313
     314    if (verbose) {
     315        dataLogLn("Adding return");
     316        dumpGraphAndControlStack();
     317    }
     318
    183319    ASSERT(returnValues.size() <= 1);
    184320    if (returnValues.size())
     
    186322    else
    187323        m_currentBlock->appendNewControlValue(m_proc, B3::Return, Origin());
     324    unreachable = 1;
     325    return true;
     326}
     327
     328bool 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
    188356    return true;
    189357}
     
    194362}
    195363
    196 Vector<Variable*> B3IRGenerator::initializeIncommingTypes(BasicBlock* block, const Vector<ExpressionType>& source)
     364Vector<Variable*> B3IRGenerator::initializeIncommingTypes(BasicBlock* block, const Vector<ExpressionType, 1>& source)
    197365{
    198366    Vector<Variable*> result;
    199367    result.reserveInitialCapacity(source.size());
    200368    for (ExpressionType expr : source) {
    201         ASSERT(expr->type() != Void);
     369        ASSERT(expr->type() != B3::Void);
    202370        Variable* var = m_proc.addVariable(expr->type());
    203371        result.append(var);
     
    208376}
    209377
    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);
     378void B3IRGenerator::unifyValuesWithBlock(const Vector<ExpressionType, 1>& resultStack, Optional<Vector<Variable*>>& stack, BasicBlock* target)
     379{
     380    if (!stack) {
     381        stack = initializeIncommingTypes(target, resultStack);
    217382        return;
    218383    }
    219384
    220     ASSERT(expectedStack.value().size() != resultStack.size());
     385    ASSERT(stack.value().size() == resultStack.size());
    221386
    222387    for (size_t i = 0; i < resultStack.size(); ++i)
    223         unify(expectedStack.value()[i], resultStack[i]);
     388        unify(stack.value()[i], resultStack[i]);
    224389}
    225390   
    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 }
     391B3IRGenerator::ControlData& B3IRGenerator::controlDataForLevel(unsigned level)
     392{
     393    return m_controlStack[m_controlStack.size() - 1 - level];
     394}
     395
     396void 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
    235408
    236409std::unique_ptr<Compilation> parseAndCompile(VM& vm, Vector<uint8_t>& source, FunctionInformation info, unsigned optLevel)
     
    242415        RELEASE_ASSERT_NOT_REACHED();
    243416
     417    validate(procedure, "After parsing:\n");
     418
     419    fixSSA(procedure);
     420    if (verbose)
     421        dataLog("Post SSA: ", procedure);
    244422    return std::make_unique<Compilation>(vm, procedure, optLevel);
    245423}
    246424
    247 } // namespace WASM
    248 
    249 } // namespace JSC
     425} } // namespace JSC::WASM
    250426
    251427#endif // ENABLE(WEBASSEMBLY)
  • trunk/Source/JavaScriptCore/wasm/WASMB3IRGenerator.h

    r205309 r205552  
    3232#include "WASMFormat.h"
    3333
    34 namespace JSC {
    35 
    36 namespace WASM {
     34namespace JSC { namespace WASM {
    3735
    3836std::unique_ptr<B3::Compilation> parseAndCompile(VM&, Vector<uint8_t>&, FunctionInformation, unsigned optLevel = 1);
    3937
    40 } // namespace WASM
    41 
    42 } // namespace JSC
     38} } // namespace JSC::WASM
    4339
    4440#endif // ENABLE(WEBASSEMBLY)
  • trunk/Source/JavaScriptCore/wasm/WASMCallingConvention.cpp

    r205550 r205552  
    2525
    2626#include "config.h"
    27 #include "B3CallingConventions.h"
     27#include "WASMCallingConvention.h"
     28
     29#if ENABLE(WEBASSEMBLY)
    2830
    2931#include <wtf/NeverDestroyed.h>
    3032
    31 #if ENABLE(B3_JIT)
     33namespace JSC { namespace WASM {
    3234
    33 namespace JSC {
    34 
    35 namespace B3 {
    36 
    37 JSCCallingConvention& jscCallingConvention()
     35const JSCCallingConvention& jscCallingConvention()
    3836{
    3937    static LazyNeverDestroyed<JSCCallingConvention> staticJSCCallingConvention;
     
    4644}
    4745
    48 } // namespace B3
    49 
    50 } // namespace JSC
     46} } // namespace JSC::WASM
    5147
    5248#endif // ENABLE(B3_JIT)
  • trunk/Source/JavaScriptCore/wasm/WASMCallingConvention.h

    r205550 r205552  
    2626#pragma once
    2727
    28 #if ENABLE(B3_JIT)
     28#if ENABLE(WEBASSEMBLY)
    2929
    3030#include "B3ArgumentRegValue.h"
     
    3232#include "B3Const64Value.h"
    3333#include "B3MemoryValue.h"
    34 #include "B3Type.h"
    3534#include "CallFrame.h"
    3635#include "RegisterSet.h"
     36#include "WASMFormat.h"
    3737
    38 namespace JSC {
    39 
    40 namespace B3 {
     38namespace JSC { namespace WASM {
    4139
    4240typedef unsigned (*NextOffset)(unsigned currentOffset, Type type);
     
    5452
    5553    template<typename Functor>
    56     void iterate(const Vector<Type>& argumentTypes, Procedure& proc, BasicBlock* block, Origin origin, const Functor& functor) const
     54    void iterate(const Vector<Type>& argumentTypes, B3::Procedure& proc, B3::BasicBlock* block, B3::Origin origin, const Functor& functor) const
    5755    {
    5856        unsigned currentOffset = headerSize;
    59         Value* framePointer = block->appendNew<Value>(proc, FramePointer, origin);
     57        B3::Value* framePointer = block->appendNew<B3::Value>(proc, B3::FramePointer, origin);
    6058
    6159        for (unsigned i = 0; i < argumentTypes.size(); ++i) {
    62             Value* argument;
     60            B3::Value* argument;
    6361            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]);
    6563            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);
    6967                currentOffset = updateOffset(currentOffset, argumentTypes[i]);
    7068            }
     
    8684typedef CallingConvention<jscHeaderSize, nextJSCOffset> JSCCallingConvention;
    8785
    88 JSCCallingConvention& jscCallingConvention();
     86const JSCCallingConvention& jscCallingConvention();
    8987
    90 } // namespace B3
     88} } // namespace JSC::WASM
    9189
    92 } // namespace JSC
    93 
    94 #endif // ENABLE(B3_JIT)
     90#endif // ENABLE(WEBASSEMBLY)
  • trunk/Source/JavaScriptCore/wasm/WASMFormat.h

    r205330 r205552  
    5555namespace WASM {
    5656
    57 using B3::Type;
    58 using B3::Int32;
    59 using B3::Int64;
    60 using B3::Float;
    61 using B3::Double;
     57enum Type : uint8_t {
     58    I32 = 1,
     59    I64,
     60    F32,
     61    F64,
     62    LastValueType = F64,
     63    Void
     64};
    6265
    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");
     66static_assert(I32 == 1, "WASM needs I32 to have the value 1");
     67static_assert(I64 == 2, "WASM needs I64 to have the value 2");
     68static_assert(F32 == 3, "WASM needs F32 to have the value 3");
     69static_assert(F64 == 4, "WASM needs F64 to have the value 4");
     70
     71inline 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
     84inline 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
    6798
    6899struct Signature {
     
    96127};
    97128
    98 } // namespace WASM
    99 
    100 } // namespace JSC
     129} } // namespace JSC::WASM
    101130
    102131#endif // ENABLE(WEBASSEMBLY)
  • trunk/Source/JavaScriptCore/wasm/WASMFunctionParser.h

    r205330 r205552  
    3131#include <wtf/DataLog.h>
    3232
    33 namespace JSC {
    34 
    35 namespace WASM {
     33namespace JSC { namespace WASM {
    3634
    3735template<typename Context>
     
    5452
    5553    Context& m_context;
    56     Vector<ExpressionType> m_expressionStack;
     54    Vector<ExpressionType, 1> m_expressionStack;
    5755};
    5856
     
    7371
    7472    for (uint32_t i = 0; i < localCount; ++i) {
    75         uint32_t numberOfLocalsWithType;
    76         if (!parseUInt32(numberOfLocalsWithType))
     73        uint32_t numberOfLocals;
     74        if (!parseVarUInt32(numberOfLocals))
    7775            return false;
    7876
     
    8179            return false;
    8280
     81        m_context.addLocal(typeOfLocal, numberOfLocals);
    8382    }
    8483
     
    110109bool FunctionParser<Context>::parseExpression(OpType op)
    111110{
     111    if (m_context.unreachable && !isControlOp(op))
     112        return true;
     113
    112114    switch (op) {
    113115#define CREATE_CASE(name, id, b3op) case name:
    114116    FOR_EACH_WASM_BINARY_OP(CREATE_CASE) {
     117        ExpressionType right = m_expressionStack.takeLast();
    115118        ExpressionType left = m_expressionStack.takeLast();
    116         ExpressionType right = m_expressionStack.takeLast();
    117119        ExpressionType result;
    118120        if (!m_context.binaryOp(static_cast<BinaryOpType>(op), left, right, result))
     
    136138        if (!parseVarUInt32(constant))
    137139            return false;
    138         m_expressionStack.append(m_context.addConstant(Int32, constant));
     140        m_expressionStack.append(m_context.addConstant(I32, constant));
    139141        return true;
    140142    }
     
    152154    }
    153155
     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
    154164    case OpType::Block: {
    155165        if (!m_context.addBlock())
    156166            return false;
    157167        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);
    158196    }
    159197
     
    178216}
    179217
    180 } // namespace WASM
    181 
    182 } // namespace JSC
     218} } // namespace JSC::WASM
    183219
    184220#endif // ENABLE(WEBASSEMBLY)
  • trunk/Source/JavaScriptCore/wasm/WASMModuleParser.cpp

    r205330 r205552  
    3333#include "WASMSections.h"
    3434
    35 namespace JSC {
    36 
    37 namespace WASM {
     35namespace JSC { namespace WASM {
    3836
    3937static const bool verbose = false;
     
    164162
    165163        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);
    169167        }
    170168
     
    234232}
    235233
    236 } // namespace WASM
    237 
    238 } // namespace JSC
     234} } // namespace JSC::WASM
    239235
    240236#endif // ENABLE(WEBASSEMBLY)
  • trunk/Source/JavaScriptCore/wasm/WASMModuleParser.h

    r205330 r205552  
    3232#include <wtf/Vector.h>
    3333
    34 namespace JSC {
    35 
    36 namespace WASM {
     34namespace JSC { namespace WASM {
    3735
    3836class ModuleParser : public Parser {
     
    6260};
    6361
    64 } // namespace WASM
    65 
    66 } // namespace JSC
     62} } // namespace JSC::WASM
    6763
    6864#endif // ENABLE(WEBASSEMBLY)
  • trunk/Source/JavaScriptCore/wasm/WASMOps.h

    r205330 r205552  
    2828#if ENABLE(WEBASSEMBLY)
    2929
    30 namespace JSC {
    31 
    32 namespace WASM {
     30namespace JSC { namespace WASM {
    3331
    3432#define FOR_EACH_WASM_SPECIAL_OP(macro) \
    3533    macro(I32Const, 0x10, NA) \
    36     macro(GetLocal, 0x14, NA)
     34    macro(GetLocal, 0x14, NA) \
     35    macro(SetLocal, 0x15, NA)
    3736
    3837#define FOR_EACH_WASM_CONTROL_FLOW_OP(macro) \
    3938    macro(Block, 0x01, NA) \
     39    macro(Loop, 0x02, NA) \
     40    macro(Branch, 0x06, NA) \
     41    macro(BranchIf, 0x07, NA) \
    4042    macro(Return, 0x09, NA) \
    4143    macro(End, 0x0f, NA)
     
    122124#undef CREATE_ENUM_VALUE
    123125
    124 } // namespace WASM
     126inline 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}
    125138
    126 } // namespace JSC
     139} } // namespace JSC::WASM
    127140
    128141#endif // ENABLE(WEBASSEMBLY)
  • trunk/Source/JavaScriptCore/wasm/WASMParser.h

    r205309 r205552  
    3535#include <wtf/LEBDecoder.h>
    3636
    37 namespace JSC {
    38 
    39 namespace WASM {
     37namespace JSC { namespace WASM {
    4038
    4139class Parser {
     
    128126}
    129127
    130 } // namespace WASM
    131 
    132 } // namespace JSC
     128} } // namespace JSC::WASM
    133129
    134130#endif // ENABLE(WEBASSEMBLY)
  • trunk/Source/JavaScriptCore/wasm/WASMPlan.cpp

    r205309 r205552  
    3434#include <wtf/DataLog.h>
    3535
    36 namespace JSC {
    37 
    38 namespace WASM {
     36namespace JSC { namespace WASM {
    3937
    4038static const bool verbose = false;
     
    6058}
    6159
    62 } // namespace WASM
    63 
    64 } // namespace JSC
     60} } // namespace JSC::WASM
    6561
    6662#endif // ENABLE(WEBASSEMBLY)
  • trunk/Source/JavaScriptCore/wasm/WASMPlan.h

    r205021 r205552  
    4949};
    5050
    51 } // namespace WASM
    52 
    53 } // namespace JSC
     51} } // namespace JSC::WASM
    5452
    5553#endif // ENABLE(WEBASSEMBLY)
  • trunk/Source/JavaScriptCore/wasm/WASMSections.cpp

    r205309 r205552  
    3232#include <wtf/text/WTFString.h>
    3333
    34 namespace JSC {
    35 
    36 namespace WASM {
     34namespace JSC { namespace WASM {
    3735
    3836struct SectionData {
     
    6361}
    6462
    65 } // namespace WASM
    66 
    67 } // namespace JSC
     63} } // namespace JSC::WASM
    6864
    6965#endif // ENABLE(WEBASSEMBLY)
  • trunk/Source/JavaScriptCore/wasm/WASMSections.h

    r205309 r205552  
    2828#if ENABLE(WEBASSEMBLY)
    2929
    30 namespace JSC {
    31 
    32 namespace WASM {
     30namespace JSC { namespace WASM {
    3331
    3432// These should be in the order that we expect them to be in the binary.
     
    5755};
    5856
    59 } // namespace WASM
    60 
    61 } // namespace JSC
     57} } // namespace JSC::WASM
    6258
    6359#endif // ENABLE(WEBASSEMBLY)
Note: See TracChangeset for help on using the changeset viewer.