Title: [189599] trunk/Source/_javascript_Core
Revision
189599
Author
[email protected]
Date
2015-09-10 18:37:09 -0700 (Thu, 10 Sep 2015)

Log Message

Implement switch statements in WebAssembly
https://bugs.webkit.org/show_bug.cgi?id=149051

Patch by Sukolsak Sakshuwong <[email protected]> on 2015-09-10
Reviewed by Geoffrey Garen.

This patch implements switch statements in WebAssembly using the
JSC::BinarySwitch class.

* tests/stress/wasm-control-flow.js:
* tests/stress/wasm/control-flow.wasm:
* wasm/WASMFunctionCompiler.h:
(JSC::WASMFunctionCompiler::buildSwitch):
* wasm/WASMFunctionParser.cpp:
(JSC::WASMFunctionParser::parseSwitchStatement):
* wasm/WASMFunctionSyntaxChecker.h:
(JSC::WASMFunctionSyntaxChecker::buildSwitch):

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (189598 => 189599)


--- trunk/Source/_javascript_Core/ChangeLog	2015-09-11 00:55:14 UTC (rev 189598)
+++ trunk/Source/_javascript_Core/ChangeLog	2015-09-11 01:37:09 UTC (rev 189599)
@@ -1,3 +1,22 @@
+2015-09-10  Sukolsak Sakshuwong  <[email protected]>
+
+        Implement switch statements in WebAssembly
+        https://bugs.webkit.org/show_bug.cgi?id=149051
+
+        Reviewed by Geoffrey Garen.
+
+        This patch implements switch statements in WebAssembly using the
+        JSC::BinarySwitch class.
+
+        * tests/stress/wasm-control-flow.js:
+        * tests/stress/wasm/control-flow.wasm:
+        * wasm/WASMFunctionCompiler.h:
+        (JSC::WASMFunctionCompiler::buildSwitch):
+        * wasm/WASMFunctionParser.cpp:
+        (JSC::WASMFunctionParser::parseSwitchStatement):
+        * wasm/WASMFunctionSyntaxChecker.h:
+        (JSC::WASMFunctionSyntaxChecker::buildSwitch):
+
 2015-09-10  Filip Pizlo  <[email protected]>
 
         Structure should be able to tell you if it had ever been a dictionary

Modified: trunk/Source/_javascript_Core/tests/stress/wasm/control-flow.wasm (189598 => 189599)


--- trunk/Source/_javascript_Core/tests/stress/wasm/control-flow.wasm	2015-09-11 00:55:14 UTC (rev 189598)
+++ trunk/Source/_javascript_Core/tests/stress/wasm/control-flow.wasm	2015-09-11 01:37:09 UTC (rev 189599)
@@ -1,4 +1,3 @@
-wasm
-\x81\x80\xA5<\xC0\xA0\xA1\xA0\x81<\xC0\xA0\xA1\xA0\x81\x80\xA5<\xC0\xA0\xA1\xA2\x81<\xC0\xA0\xA1\xA2\x82\x80\xA1.\xC0\xA0.\xC1\xA0\xA1\xA2.\xC1\xA0\xA3\xA4\x824\xC1\xA5\x80\xC0\xA1\x81\xC1\xA1\xC0\x82\xA1.\xC1\xA2\x80\xC0\xA1\x81\xC1\xA1\xC0\x824\xC1\xA5.\xC1\xA2\x81\xA3\x80\xC0\xA1\x81\xC1\xA1\xC0\x834\xC1\xA5\x82\xA04¢\x80\xC0\xA1\x82¡\x81\xC1\xA1\xC0\x82\x80\xC0\xA1\x81\xC1\xA14\xC1\xA0\xC0\x82.\xC1\xA2\x80\xC0\xA1\x81\xC1\xA1\xA1\xC0\x82.\xC1\xA2\x81\xA3\x80\xC0\xA1\x81\xC1\xA14\xC1\xA5\xC0\x81\x80\xA1\x80\xA2\xA0\xC0\x81.\xC0\xA1\x80\xA1\x80\xA2\xA0\xC0\x81\x80\xA1\x80\xA2\x80\xA3\xA0\x80\xA4\xA0\xC0\x81\x80\xA1\x80\xA2\x80\xA3\xA0\x80\xA4\xA0\xC0\x834\xC1\xA5\x82\xA04¢\x80\xC0\xA1.\xC0\xA8\x82¡\x81\xC1\xA1\xC0ifTrueifFalseifElseTrueifElseFalseifInIfwhileLoop
 whileBreakwhileContinuewhileInWhiledoLoop	doBreak
+wasm6\x81\x80\xA5<\xC0\xA0\xA1\xA0\x81<\xC0\xA0\xA1\xA0\x81\x80\xA5<\xC0\xA0\xA1\xA2\x81<\xC0\xA0\xA1\xA2\x82\x80\xA1.\xC0\xA0.\xC1\xA0\xA1\xA2.\xC1\xA0\xA3\xA4\x824\xC1\xA5\x80\xC0\xA1\x81\xC1\xA1\xC0\x82\xA1.\xC1\xA2\x80\xC0\xA1\x81\xC1\xA1\xC0\x824\xC1\xA5.\xC1\xA2\x81\xA3\x80\xC0\xA1\x81\xC1\xA1\xC0\x834\xC1\xA5\x82\xA04¢\x80\xC0\xA1\x82¡\x81\xC1\xA1\xC0\x82\x80\xC0\xA1\x81\xC1\xA14\xC1\xA0\xC0\x82.\xC1\xA2\x80\xC0\xA1\x81\xC1\xA1\xA1\xC0\x82.\xC1\xA2\x81\xA3\x80\xC0\xA1\x81\xC1\xA14\xC1\xA5\xC0\x81\x80\xA1\x80\xA2\xA0\xC0\x81.\xC0\xA1\x80\xA1\x80\xA2\xA0\xC0\x81\x80\xA1\x80\xA2\x80\xA3\xA0\x80\xA4\xA0\xC0\x81\x80\xA1\x80\xA2\x80\xA3\xA0\x80\xA4\xA0\xC0\x834\xC1\xA5\x82\xA04¢\x80\xC0\xA1.\xC0\xA8\x82¡\x81\xC1\xA1\xC0\x81\xC0\x81\xA1\x81\xA2\x
 81\xA3\xC1\x81\xC0\x81\xC1\xE8\x81\xC1d\x81\xC1\xAA\x81\xC1\xA1\xC1ifTrueifFalseifElseTrueifElseFalseifInIfwhileLoopwhileBreakwhileContinuewhileInWhiledoLoop	doBreak
 doContinuelabelBreaklabelContinue-labelInLabelBreakInnerlabelInLabelBreakOuterwhileInWhileBreakOuter
\ No newline at end of file
+labelInLabelBreakInnerlabelInLabelBreakOuterwhileInWhileBreakOuterswitchCaseswitchFallThrough
\ No newline at end of file

Modified: trunk/Source/_javascript_Core/tests/stress/wasm-control-flow.js (189598 => 189599)


--- trunk/Source/_javascript_Core/tests/stress/wasm-control-flow.js	2015-09-11 00:55:14 UTC (rev 189598)
+++ trunk/Source/_javascript_Core/tests/stress/wasm-control-flow.js	2015-09-11 01:37:09 UTC (rev 189599)
@@ -204,6 +204,39 @@
         return x;
     }
 
+    function switchCase(x) {
+        x = x | 0;
+        var y = 0;
+        switch (x) {
+        case 0:
+            y = 1;
+            break;
+        case 1:
+            y = 2;
+            break;
+        case 2:
+            y = 3;
+            break;
+        }
+        return y;
+    }
+
+    function switchFallThrough(x) {
+        x = x | 0;
+        var y = 0;
+        switch (x) {
+        case 3:
+            y = (y + 1000) | 0;
+        case 2:
+            y = (y + 100) | 0;
+        case 1:
+            y = (y + 10) | 0;
+        default:
+            y = (y + 1) | 0;
+        }
+        return y;
+    }
+
     return {
         ifTrue: ifTrue,
         ifFalse: ifFalse,
@@ -222,6 +255,8 @@
         labelInLabelBreakInner: labelInLabelBreakInner,
         labelInLabelBreakOuter: labelInLabelBreakOuter,
         whileInWhileBreakOuter: whileInWhileBreakOuter,
+        switchCase: switchCase,
+        switchFallThrough: switchFallThrough,
     };
 }
 */
@@ -233,15 +268,28 @@
 shouldBe(module.ifElseTrue(), 1);
 shouldBe(module.ifElseFalse(), 2);
 shouldBe(module.ifInIf(), 3);
+
 shouldBe(module.whileLoop(), 5);
 shouldBe(module.whileBreak(), 2);
 shouldBe(module.whileContinue(), 4);
 shouldBe(module.whileInWhile(), 10);
+
 shouldBe(module.doLoop(), 1);
 shouldBe(module.doBreak(), 2);
 shouldBe(module.doContinue(), 4);
+
 shouldBe(module.labelBreak(), 1);
 shouldBe(module.labelContinue(), 1);
 shouldBe(module.labelInLabelBreakInner(), 4);
 shouldBe(module.labelInLabelBreakOuter(), 2);
 shouldBe(module.whileInWhileBreakOuter(), 8);
+
+shouldBe(module.switchCase(0), 1);
+shouldBe(module.switchCase(1), 2);
+shouldBe(module.switchCase(2), 3);
+shouldBe(module.switchCase(3), 0);
+shouldBe(module.switchFallThrough(0), 1);
+shouldBe(module.switchFallThrough(1), 11);
+shouldBe(module.switchFallThrough(2), 111);
+shouldBe(module.switchFallThrough(3), 1111);
+shouldBe(module.switchFallThrough(4), 1);

Modified: trunk/Source/_javascript_Core/wasm/WASMFunctionCompiler.h (189598 => 189599)


--- trunk/Source/_javascript_Core/wasm/WASMFunctionCompiler.h	2015-09-11 00:55:14 UTC (rev 189598)
+++ trunk/Source/_javascript_Core/wasm/WASMFunctionCompiler.h	2015-09-11 01:37:09 UTC (rev 189599)
@@ -28,6 +28,7 @@
 
 #if ENABLE(WEBASSEMBLY)
 
+#include "BinarySwitch.h"
 #include "CCallHelpers.h"
 #include "JIT.h"
 #include "JITOperations.h"
@@ -634,6 +635,18 @@
         return m_continueLabelTargets[labelIndex];
     }
 
+    void buildSwitch(int, const Vector<int64_t>& cases, Vector<JumpTarget>& targets, JumpTarget defaultTarget)
+    {
+        load32(temporaryAddress(m_tempStackTop - 1), GPRInfo::regT0);
+        m_tempStackTop--;
+        BinarySwitch binarySwitch(GPRInfo::regT0, cases, BinarySwitch::Int32);
+        while (binarySwitch.advance(*this)) {
+            unsigned index = binarySwitch.caseIndex();
+            jump(targets[index].label);
+        }
+        binarySwitch.fallThrough().linkTo(defaultTarget.label, this);
+    }
+
 private:
     union StackSlot {
         int32_t intValue;

Modified: trunk/Source/_javascript_Core/wasm/WASMFunctionParser.cpp (189598 => 189599)


--- trunk/Source/_javascript_Core/wasm/WASMFunctionParser.cpp	2015-09-11 00:55:14 UTC (rev 189598)
+++ trunk/Source/_javascript_Core/wasm/WASMFunctionParser.cpp	2015-09-11 01:37:09 UTC (rev 189599)
@@ -415,11 +415,22 @@
 template <class Context>
 ContextStatement WASMFunctionParser::parseSwitchStatement(Context& context)
 {
+    context.startSwitch();
     uint32_t numberOfCases;
     READ_COMPACT_UINT32_OR_FAIL(numberOfCases, "Cannot read the number of cases.");
-    parseExpressionI32(context);
+    ContextExpression _expression_ = parseExpressionI32(context);
     PROPAGATE_ERROR();
 
+    ContextJumpTarget compare;
+    context.jumpToTarget(compare);
+
+    Vector<int64_t> cases;
+    Vector<ContextJumpTarget> targets;
+    cases.reserveInitialCapacity(numberOfCases);
+    targets.reserveInitialCapacity(numberOfCases);
+    bool hasDefault = false;
+    ContextJumpTarget defaultTarget;
+
     m_breakScopeDepth++;
     for (uint32_t i = 0; i < numberOfCases; ++i) {
         WASMSwitchCase switchCase;
@@ -430,6 +441,10 @@
         case WASMSwitchCase::CaseWithBlockStatement: {
             uint32_t value;
             READ_COMPACT_INT32_OR_FAIL(value, "Cannot read the value of the switch case.");
+            cases.uncheckedAppend(value);
+            ContextJumpTarget target;
+            context.linkTarget(target);
+            targets.uncheckedAppend(target);
             if (switchCase == WASMSwitchCase::CaseWithStatement) {
                 parseStatement(context);
                 PROPAGATE_ERROR();
@@ -443,6 +458,8 @@
         case WASMSwitchCase::DefaultWithStatement:
         case WASMSwitchCase::DefaultWithBlockStatement: {
             FAIL_IF_FALSE(i == numberOfCases - 1, "The default case must be the last case.");
+            hasDefault = true;
+            context.linkTarget(defaultTarget);
             if (switchCase == WASMSwitchCase::DefaultWithStatement) {
                 parseStatement(context);
                 PROPAGATE_ERROR();
@@ -456,8 +473,18 @@
             ASSERT_NOT_REACHED();
         }
     }
+    if (!hasDefault)
+        context.linkTarget(defaultTarget);
+
     m_breakScopeDepth--;
-    // FIXME: Implement this instruction.
+
+    context.jumpToTarget(context.breakTarget());
+    context.linkTarget(compare);
+
+    context.buildSwitch(_expression_, cases, targets, defaultTarget);
+
+    context.linkTarget(context.breakTarget());
+    context.endSwitch();
     return UNUSED;
 }
 

Modified: trunk/Source/_javascript_Core/wasm/WASMFunctionSyntaxChecker.h (189598 => 189599)


--- trunk/Source/_javascript_Core/wasm/WASMFunctionSyntaxChecker.h	2015-09-11 00:55:14 UTC (rev 189598)
+++ trunk/Source/_javascript_Core/wasm/WASMFunctionSyntaxChecker.h	2015-09-11 01:37:09 UTC (rev 189599)
@@ -155,6 +155,11 @@
     int breakLabelTarget(uint32_t) { return UNUSED; }
     int continueLabelTarget(uint32_t) { return UNUSED; }
 
+    void buildSwitch(int, const Vector<int64_t>&, const Vector<int>&, const int&)
+    {
+        m_tempStackTop--;
+    }
+
     unsigned stackHeight()
     {
         return m_numberOfLocals + m_tempStackHeight;
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to