Changeset 189514 in webkit


Ignore:
Timestamp:
Sep 8, 2015 4:04:44 PM (9 years ago)
Author:
commit-queue@webkit.org
Message:

Implement control flow statements in WebAssembly
https://bugs.webkit.org/show_bug.cgi?id=148934

Patch by Sukolsak Sakshuwong <Sukolsak Sakshuwong> on 2015-09-08
Reviewed by Geoffrey Garen.

This patch implements if, while, do, label, break, and continue
statements in WebAssembly. Switches will be implemented in a subsequent
patch.

  • tests/stress/wasm-control-flow.js: Added.

(shouldBe):

  • tests/stress/wasm/control-flow.wasm: Added.
  • wasm/WASMFunctionCompiler.h:

(JSC::WASMFunctionCompiler::linkTarget):
(JSC::WASMFunctionCompiler::jumpToTarget):
(JSC::WASMFunctionCompiler::jumpToTargetIf):
(JSC::WASMFunctionCompiler::startLoop):
(JSC::WASMFunctionCompiler::endLoop):
(JSC::WASMFunctionCompiler::startSwitch):
(JSC::WASMFunctionCompiler::endSwitch):
(JSC::WASMFunctionCompiler::startLabel):
(JSC::WASMFunctionCompiler::endLabel):
(JSC::WASMFunctionCompiler::breakTarget):
(JSC::WASMFunctionCompiler::continueTarget):
(JSC::WASMFunctionCompiler::breakLabelTarget):
(JSC::WASMFunctionCompiler::continueLabelTarget):

  • wasm/WASMFunctionParser.cpp:

(JSC::WASMFunctionParser::parseIfStatement):
(JSC::WASMFunctionParser::parseIfElseStatement):
(JSC::WASMFunctionParser::parseWhileStatement):
(JSC::WASMFunctionParser::parseDoStatement):
(JSC::WASMFunctionParser::parseLabelStatement):
(JSC::WASMFunctionParser::parseBreakStatement):
(JSC::WASMFunctionParser::parseBreakLabelStatement):
(JSC::WASMFunctionParser::parseContinueStatement):
(JSC::WASMFunctionParser::parseContinueLabelStatement):

  • wasm/WASMFunctionParser.h:
  • wasm/WASMFunctionSyntaxChecker.h:

(JSC::WASMFunctionSyntaxChecker::linkTarget):
(JSC::WASMFunctionSyntaxChecker::jumpToTarget):
(JSC::WASMFunctionSyntaxChecker::jumpToTargetIf):
(JSC::WASMFunctionSyntaxChecker::startLoop):
(JSC::WASMFunctionSyntaxChecker::endLoop):
(JSC::WASMFunctionSyntaxChecker::startSwitch):
(JSC::WASMFunctionSyntaxChecker::endSwitch):
(JSC::WASMFunctionSyntaxChecker::startLabel):
(JSC::WASMFunctionSyntaxChecker::endLabel):
(JSC::WASMFunctionSyntaxChecker::breakTarget):
(JSC::WASMFunctionSyntaxChecker::continueTarget):
(JSC::WASMFunctionSyntaxChecker::breakLabelTarget):
(JSC::WASMFunctionSyntaxChecker::continueLabelTarget):

Location:
trunk/Source/JavaScriptCore
Files:
2 added
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r189506 r189514  
     12015-09-08  Sukolsak Sakshuwong  <sukolsak@gmail.com>
     2
     3        Implement control flow statements in WebAssembly
     4        https://bugs.webkit.org/show_bug.cgi?id=148934
     5
     6        Reviewed by Geoffrey Garen.
     7
     8        This patch implements if, while, do, label, break, and continue
     9        statements in WebAssembly. Switches will be implemented in a subsequent
     10        patch.
     11
     12        * tests/stress/wasm-control-flow.js: Added.
     13        (shouldBe):
     14        * tests/stress/wasm/control-flow.wasm: Added.
     15        * wasm/WASMFunctionCompiler.h:
     16        (JSC::WASMFunctionCompiler::linkTarget):
     17        (JSC::WASMFunctionCompiler::jumpToTarget):
     18        (JSC::WASMFunctionCompiler::jumpToTargetIf):
     19        (JSC::WASMFunctionCompiler::startLoop):
     20        (JSC::WASMFunctionCompiler::endLoop):
     21        (JSC::WASMFunctionCompiler::startSwitch):
     22        (JSC::WASMFunctionCompiler::endSwitch):
     23        (JSC::WASMFunctionCompiler::startLabel):
     24        (JSC::WASMFunctionCompiler::endLabel):
     25        (JSC::WASMFunctionCompiler::breakTarget):
     26        (JSC::WASMFunctionCompiler::continueTarget):
     27        (JSC::WASMFunctionCompiler::breakLabelTarget):
     28        (JSC::WASMFunctionCompiler::continueLabelTarget):
     29        * wasm/WASMFunctionParser.cpp:
     30        (JSC::WASMFunctionParser::parseIfStatement):
     31        (JSC::WASMFunctionParser::parseIfElseStatement):
     32        (JSC::WASMFunctionParser::parseWhileStatement):
     33        (JSC::WASMFunctionParser::parseDoStatement):
     34        (JSC::WASMFunctionParser::parseLabelStatement):
     35        (JSC::WASMFunctionParser::parseBreakStatement):
     36        (JSC::WASMFunctionParser::parseBreakLabelStatement):
     37        (JSC::WASMFunctionParser::parseContinueStatement):
     38        (JSC::WASMFunctionParser::parseContinueLabelStatement):
     39        * wasm/WASMFunctionParser.h:
     40        * wasm/WASMFunctionSyntaxChecker.h:
     41        (JSC::WASMFunctionSyntaxChecker::linkTarget):
     42        (JSC::WASMFunctionSyntaxChecker::jumpToTarget):
     43        (JSC::WASMFunctionSyntaxChecker::jumpToTargetIf):
     44        (JSC::WASMFunctionSyntaxChecker::startLoop):
     45        (JSC::WASMFunctionSyntaxChecker::endLoop):
     46        (JSC::WASMFunctionSyntaxChecker::startSwitch):
     47        (JSC::WASMFunctionSyntaxChecker::endSwitch):
     48        (JSC::WASMFunctionSyntaxChecker::startLabel):
     49        (JSC::WASMFunctionSyntaxChecker::endLabel):
     50        (JSC::WASMFunctionSyntaxChecker::breakTarget):
     51        (JSC::WASMFunctionSyntaxChecker::continueTarget):
     52        (JSC::WASMFunctionSyntaxChecker::breakLabelTarget):
     53        (JSC::WASMFunctionSyntaxChecker::continueLabelTarget):
     54
    1552015-09-08  Per Arne Vollan  <peavo@outlook.com>
    256
  • trunk/Source/JavaScriptCore/wasm/WASMFunctionCompiler.h

    r189499 r189514  
    6464    typedef int Expression;
    6565    typedef int Statement;
     66    struct JumpTarget {
     67        Label label;
     68        JumpList jumpList;
     69    };
     70    enum class JumpCondition { Zero, NonZero };
    6671
    6772    WASMFunctionCompiler(VM& vm, CodeBlock* codeBlock, unsigned stackHeight)
     
    434439    }
    435440
     441    void linkTarget(JumpTarget& target)
     442    {
     443        target.label = label();
     444        target.jumpList.link(this);
     445    }
     446
     447    void jumpToTarget(JumpTarget& target)
     448    {
     449        if (target.label.isSet())
     450            jump(target.label);
     451        else
     452            target.jumpList.append(jump());
     453    }
     454
     455    void jumpToTargetIf(JumpCondition condition, int, JumpTarget& target)
     456    {
     457        load32(temporaryAddress(m_tempStackTop - 1), GPRInfo::regT0);
     458        m_tempStackTop--;
     459        Jump taken = branchTest32((condition == JumpCondition::Zero) ? Zero : NonZero, GPRInfo::regT0);
     460        if (target.label.isSet())
     461            taken.linkTo(target.label, this);
     462        else
     463            target.jumpList.append(taken);
     464    }
     465
     466    void startLoop()
     467    {
     468        m_breakTargets.append(JumpTarget());
     469        m_continueTargets.append(JumpTarget());
     470    }
     471
     472    void endLoop()
     473    {
     474        m_breakTargets.removeLast();
     475        m_continueTargets.removeLast();
     476    }
     477
     478    void startSwitch()
     479    {
     480        m_breakTargets.append(JumpTarget());
     481    }
     482
     483    void endSwitch()
     484    {
     485        m_breakTargets.removeLast();
     486    }
     487
     488    void startLabel()
     489    {
     490        m_breakLabelTargets.append(JumpTarget());
     491        m_continueLabelTargets.append(JumpTarget());
     492
     493        linkTarget(m_continueLabelTargets.last());
     494    }
     495
     496    void endLabel()
     497    {
     498        linkTarget(m_breakLabelTargets.last());
     499
     500        m_breakLabelTargets.removeLast();
     501        m_continueLabelTargets.removeLast();
     502    }
     503
     504    JumpTarget& breakTarget()
     505    {
     506        return m_breakTargets.last();
     507    }
     508
     509    JumpTarget& continueTarget()
     510    {
     511        return m_continueTargets.last();
     512    }
     513
     514    JumpTarget& breakLabelTarget(uint32_t labelIndex)
     515    {
     516        return m_breakLabelTargets[labelIndex];
     517    }
     518
     519    JumpTarget& continueLabelTarget(uint32_t labelIndex)
     520    {
     521        return m_continueLabelTargets[labelIndex];
     522    }
     523
    436524private:
    437525    union StackSlot {
     
    482570    unsigned m_tempStackTop { 0 };
    483571
     572    Vector<JumpTarget> m_breakTargets;
     573    Vector<JumpTarget> m_continueTargets;
     574    Vector<JumpTarget> m_breakLabelTargets;
     575    Vector<JumpTarget> m_continueLabelTargets;
     576
    484577    Label m_beginLabel;
    485578    Jump m_stackOverflow;
  • trunk/Source/JavaScriptCore/wasm/WASMFunctionParser.cpp

    r189499 r189514  
    254254ContextStatement WASMFunctionParser::parseIfStatement(Context& context)
    255255{
    256     parseExpressionI32(context);
    257     PROPAGATE_ERROR();
     256    ContextJumpTarget end;
     257
     258    ContextExpression expression = parseExpressionI32(context);
     259    PROPAGATE_ERROR();
     260
     261    context.jumpToTargetIf(Context::JumpCondition::Zero, expression, end);
     262
    258263    parseStatement(context);
    259     // FIXME: Implement this instruction.
     264    PROPAGATE_ERROR();
     265
     266    context.linkTarget(end);
    260267    return UNUSED;
    261268}
     
    264271ContextStatement WASMFunctionParser::parseIfElseStatement(Context& context)
    265272{
    266     parseExpressionI32(context);
    267     PROPAGATE_ERROR();
     273    ContextJumpTarget elseTarget;
     274    ContextJumpTarget end;
     275
     276    ContextExpression expression = parseExpressionI32(context);
     277    PROPAGATE_ERROR();
     278
     279    context.jumpToTargetIf(Context::JumpCondition::Zero, expression, elseTarget);
     280
    268281    parseStatement(context);
    269282    PROPAGATE_ERROR();
     283
     284    context.jumpToTarget(end);
     285    context.linkTarget(elseTarget);
     286
    270287    parseStatement(context);
    271     // FIXME: Implement this instruction.
     288    PROPAGATE_ERROR();
     289
     290    context.linkTarget(end);
    272291    return UNUSED;
    273292}
     
    276295ContextStatement WASMFunctionParser::parseWhileStatement(Context& context)
    277296{
    278     parseExpressionI32(context);
    279     PROPAGATE_ERROR();
     297    context.startLoop();
     298    context.linkTarget(context.continueTarget());
     299
     300    ContextExpression expression = parseExpressionI32(context);
     301    PROPAGATE_ERROR();
     302
     303    context.jumpToTargetIf(Context::JumpCondition::Zero, expression, context.breakTarget());
    280304
    281305    m_breakScopeDepth++;
     
    285309    m_continueScopeDepth--;
    286310    m_breakScopeDepth--;
    287     // FIXME: Implement this instruction.
     311
     312    context.jumpToTarget(context.continueTarget());
     313
     314    context.linkTarget(context.breakTarget());
     315    context.endLoop();
    288316    return UNUSED;
    289317}
     
    292320ContextStatement WASMFunctionParser::parseDoStatement(Context& context)
    293321{
     322    context.startLoop();
     323
     324    ContextJumpTarget topOfLoop;
     325    context.linkTarget(topOfLoop);
     326
    294327    m_breakScopeDepth++;
    295328    m_continueScopeDepth++;
     
    299332    m_breakScopeDepth--;
    300333
    301     parseExpressionI32(context);
    302     // FIXME: Implement this instruction.
     334    context.linkTarget(context.continueTarget());
     335
     336    ContextExpression expression = parseExpressionI32(context);
     337    PROPAGATE_ERROR();
     338
     339    context.jumpToTargetIf(Context::JumpCondition::NonZero, expression, topOfLoop);
     340
     341    context.linkTarget(context.breakTarget());
     342    context.endLoop();
    303343    return UNUSED;
    304344}
     
    307347ContextStatement WASMFunctionParser::parseLabelStatement(Context& context)
    308348{
     349    context.startLabel();
    309350    m_labelDepth++;
    310351    parseStatement(context);
    311352    PROPAGATE_ERROR();
    312353    m_labelDepth--;
    313     // FIXME: Implement this instruction.
    314     return UNUSED;
    315 }
    316 
    317 template <class Context>
    318 ContextStatement WASMFunctionParser::parseBreakStatement(Context&)
     354    context.endLabel();
     355    return UNUSED;
     356}
     357
     358template <class Context>
     359ContextStatement WASMFunctionParser::parseBreakStatement(Context& context)
    319360{
    320361    FAIL_IF_FALSE(m_breakScopeDepth, "'break' is only valid inside a switch or loop statement.");
    321     // FIXME: Implement this instruction.
    322     return UNUSED;
    323 }
    324 
    325 template <class Context>
    326 ContextStatement WASMFunctionParser::parseBreakLabelStatement(Context&)
     362    context.jumpToTarget(context.breakTarget());
     363    return UNUSED;
     364}
     365
     366template <class Context>
     367ContextStatement WASMFunctionParser::parseBreakLabelStatement(Context& context)
    327368{
    328369    uint32_t labelIndex;
    329370    READ_COMPACT_UINT32_OR_FAIL(labelIndex, "Cannot read the label index.");
    330371    FAIL_IF_FALSE(labelIndex < m_labelDepth, "The label index is incorrect.");
    331     // FIXME: Implement this instruction.
    332     return UNUSED;
    333 }
    334 
    335 template <class Context>
    336 ContextStatement WASMFunctionParser::parseContinueStatement(Context&)
     372    context.jumpToTarget(context.breakLabelTarget(labelIndex));
     373    return UNUSED;
     374}
     375
     376template <class Context>
     377ContextStatement WASMFunctionParser::parseContinueStatement(Context& context)
    337378{
    338379    FAIL_IF_FALSE(m_continueScopeDepth, "'continue' is only valid inside a loop statement.");
    339     // FIXME: Implement this instruction.
    340     return UNUSED;
    341 }
    342 
    343 template <class Context>
    344 ContextStatement WASMFunctionParser::parseContinueLabelStatement(Context&)
     380    context.jumpToTarget(context.continueTarget());
     381    return UNUSED;
     382}
     383
     384template <class Context>
     385ContextStatement WASMFunctionParser::parseContinueLabelStatement(Context& context)
    345386{
    346387    uint32_t labelIndex;
    347388    READ_COMPACT_UINT32_OR_FAIL(labelIndex, "Cannot read the label index.");
    348389    FAIL_IF_FALSE(labelIndex < m_labelDepth, "The label index is incorrect.");
    349     // FIXME: Implement this instruction.
     390    context.jumpToTarget(context.continueLabelTarget(labelIndex));
    350391    return UNUSED;
    351392}
  • trunk/Source/JavaScriptCore/wasm/WASMFunctionParser.h

    r189499 r189514  
    3434#define ContextExpression typename Context::Expression
    3535#define ContextStatement typename Context::Statement
     36#define ContextJumpTarget typename Context::JumpTarget
    3637
    3738namespace JSC {
  • trunk/Source/JavaScriptCore/wasm/WASMFunctionSyntaxChecker.h

    r189499 r189514  
    3737    typedef int Expression;
    3838    typedef int Statement;
     39    typedef int JumpTarget;
     40    enum class JumpCondition { Zero, NonZero };
    3941
    4042    void startFunction(const Vector<WASMType>& arguments, uint32_t numberOfI32LocalVariables, uint32_t numberOfF32LocalVariables, uint32_t numberOfF64LocalVariables)
     
    9799    }
    98100
     101    void linkTarget(const int&) { }
     102    void jumpToTarget(const int&) { }
     103    void jumpToTargetIf(JumpCondition, int, const int&)
     104    {
     105        m_tempStackTop--;
     106    }
     107
     108    void startLoop() { }
     109    void endLoop() { }
     110    void startSwitch() { }
     111    void endSwitch() { }
     112    void startLabel() { }
     113    void endLabel() { }
     114
     115    int breakTarget() { return UNUSED; }
     116    int continueTarget() { return UNUSED; }
     117    int breakLabelTarget(uint32_t) { return UNUSED; }
     118    int continueLabelTarget(uint32_t) { return UNUSED; }
     119
    99120    unsigned stackHeight()
    100121    {
Note: See TracChangeset for help on using the changeset viewer.