Changeset 189599 in webkit


Ignore:
Timestamp:
Sep 10, 2015 6:37:09 PM (9 years ago)
Author:
commit-queue@webkit.org
Message:

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

Patch by Sukolsak Sakshuwong <Sukolsak Sakshuwong> 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):

Location:
trunk/Source/JavaScriptCore
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r189596 r189599  
     12015-09-10  Sukolsak Sakshuwong  <sukolsak@gmail.com>
     2
     3        Implement switch statements in WebAssembly
     4        https://bugs.webkit.org/show_bug.cgi?id=149051
     5
     6        Reviewed by Geoffrey Garen.
     7
     8        This patch implements switch statements in WebAssembly using the
     9        JSC::BinarySwitch class.
     10
     11        * tests/stress/wasm-control-flow.js:
     12        * tests/stress/wasm/control-flow.wasm:
     13        * wasm/WASMFunctionCompiler.h:
     14        (JSC::WASMFunctionCompiler::buildSwitch):
     15        * wasm/WASMFunctionParser.cpp:
     16        (JSC::WASMFunctionParser::parseSwitchStatement):
     17        * wasm/WASMFunctionSyntaxChecker.h:
     18        (JSC::WASMFunctionSyntaxChecker::buildSwitch):
     19
    1202015-09-10  Filip Pizlo  <fpizlo@apple.com>
    221
  • trunk/Source/JavaScriptCore/tests/stress/wasm-control-flow.js

    r189514 r189599  
    203203        }
    204204        return x;
     205    }
     206
     207    function switchCase(x) {
     208        x = x | 0;
     209        var y = 0;
     210        switch (x) {
     211        case 0:
     212            y = 1;
     213            break;
     214        case 1:
     215            y = 2;
     216            break;
     217        case 2:
     218            y = 3;
     219            break;
     220        }
     221        return y;
     222    }
     223
     224    function switchFallThrough(x) {
     225        x = x | 0;
     226        var y = 0;
     227        switch (x) {
     228        case 3:
     229            y = (y + 1000) | 0;
     230        case 2:
     231            y = (y + 100) | 0;
     232        case 1:
     233            y = (y + 10) | 0;
     234        default:
     235            y = (y + 1) | 0;
     236        }
     237        return y;
    205238    }
    206239
     
    223256        labelInLabelBreakOuter: labelInLabelBreakOuter,
    224257        whileInWhileBreakOuter: whileInWhileBreakOuter,
     258        switchCase: switchCase,
     259        switchFallThrough: switchFallThrough,
    225260    };
    226261}
     
    234269shouldBe(module.ifElseFalse(), 2);
    235270shouldBe(module.ifInIf(), 3);
     271
    236272shouldBe(module.whileLoop(), 5);
    237273shouldBe(module.whileBreak(), 2);
    238274shouldBe(module.whileContinue(), 4);
    239275shouldBe(module.whileInWhile(), 10);
     276
    240277shouldBe(module.doLoop(), 1);
    241278shouldBe(module.doBreak(), 2);
    242279shouldBe(module.doContinue(), 4);
     280
    243281shouldBe(module.labelBreak(), 1);
    244282shouldBe(module.labelContinue(), 1);
     
    246284shouldBe(module.labelInLabelBreakOuter(), 2);
    247285shouldBe(module.whileInWhileBreakOuter(), 8);
     286
     287shouldBe(module.switchCase(0), 1);
     288shouldBe(module.switchCase(1), 2);
     289shouldBe(module.switchCase(2), 3);
     290shouldBe(module.switchCase(3), 0);
     291shouldBe(module.switchFallThrough(0), 1);
     292shouldBe(module.switchFallThrough(1), 11);
     293shouldBe(module.switchFallThrough(2), 111);
     294shouldBe(module.switchFallThrough(3), 1111);
     295shouldBe(module.switchFallThrough(4), 1);
  • trunk/Source/JavaScriptCore/wasm/WASMFunctionCompiler.h

    r189584 r189599  
    2929#if ENABLE(WEBASSEMBLY)
    3030
     31#include "BinarySwitch.h"
    3132#include "CCallHelpers.h"
    3233#include "JIT.h"
     
    635636    }
    636637
     638    void buildSwitch(int, const Vector<int64_t>& cases, Vector<JumpTarget>& targets, JumpTarget defaultTarget)
     639    {
     640        load32(temporaryAddress(m_tempStackTop - 1), GPRInfo::regT0);
     641        m_tempStackTop--;
     642        BinarySwitch binarySwitch(GPRInfo::regT0, cases, BinarySwitch::Int32);
     643        while (binarySwitch.advance(*this)) {
     644            unsigned index = binarySwitch.caseIndex();
     645            jump(targets[index].label);
     646        }
     647        binarySwitch.fallThrough().linkTo(defaultTarget.label, this);
     648    }
     649
    637650private:
    638651    union StackSlot {
  • trunk/Source/JavaScriptCore/wasm/WASMFunctionParser.cpp

    r189584 r189599  
    416416ContextStatement WASMFunctionParser::parseSwitchStatement(Context& context)
    417417{
     418    context.startSwitch();
    418419    uint32_t numberOfCases;
    419420    READ_COMPACT_UINT32_OR_FAIL(numberOfCases, "Cannot read the number of cases.");
    420     parseExpressionI32(context);
    421     PROPAGATE_ERROR();
     421    ContextExpression expression = parseExpressionI32(context);
     422    PROPAGATE_ERROR();
     423
     424    ContextJumpTarget compare;
     425    context.jumpToTarget(compare);
     426
     427    Vector<int64_t> cases;
     428    Vector<ContextJumpTarget> targets;
     429    cases.reserveInitialCapacity(numberOfCases);
     430    targets.reserveInitialCapacity(numberOfCases);
     431    bool hasDefault = false;
     432    ContextJumpTarget defaultTarget;
    422433
    423434    m_breakScopeDepth++;
     
    431442            uint32_t value;
    432443            READ_COMPACT_INT32_OR_FAIL(value, "Cannot read the value of the switch case.");
     444            cases.uncheckedAppend(value);
     445            ContextJumpTarget target;
     446            context.linkTarget(target);
     447            targets.uncheckedAppend(target);
    433448            if (switchCase == WASMSwitchCase::CaseWithStatement) {
    434449                parseStatement(context);
     
    444459        case WASMSwitchCase::DefaultWithBlockStatement: {
    445460            FAIL_IF_FALSE(i == numberOfCases - 1, "The default case must be the last case.");
     461            hasDefault = true;
     462            context.linkTarget(defaultTarget);
    446463            if (switchCase == WASMSwitchCase::DefaultWithStatement) {
    447464                parseStatement(context);
     
    457474        }
    458475    }
     476    if (!hasDefault)
     477        context.linkTarget(defaultTarget);
     478
    459479    m_breakScopeDepth--;
    460     // FIXME: Implement this instruction.
     480
     481    context.jumpToTarget(context.breakTarget());
     482    context.linkTarget(compare);
     483
     484    context.buildSwitch(expression, cases, targets, defaultTarget);
     485
     486    context.linkTarget(context.breakTarget());
     487    context.endSwitch();
    461488    return UNUSED;
    462489}
  • trunk/Source/JavaScriptCore/wasm/WASMFunctionSyntaxChecker.h

    r189584 r189599  
    156156    int continueLabelTarget(uint32_t) { return UNUSED; }
    157157
     158    void buildSwitch(int, const Vector<int64_t>&, const Vector<int>&, const int&)
     159    {
     160        m_tempStackTop--;
     161    }
     162
    158163    unsigned stackHeight()
    159164    {
Note: See TracChangeset for help on using the changeset viewer.