Changeset 188808 in webkit


Ignore:
Timestamp:
Aug 21, 2015 5:49:20 PM (9 years ago)
Author:
commit-queue@webkit.org
Message:

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

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

Parse control flow statements in WebAssembly files generated by pack-asmjs
<https://github.com/WebAssembly/polyfill-prototype-1>.

  • wasm/WASMConstants.h:
  • wasm/WASMFunctionParser.cpp:

(JSC::WASMFunctionParser::parseStatement):
(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):
(JSC::WASMFunctionParser::parseSwitchStatement):

  • wasm/WASMFunctionParser.h:

(JSC::WASMFunctionParser::WASMFunctionParser):

  • wasm/WASMReader.cpp:

(JSC::WASMReader::readCompactInt32):
(JSC::WASMReader::readSwitchCase):

  • wasm/WASMReader.h:
Location:
trunk/Source/JavaScriptCore
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r188803 r188808  
     12015-08-21  Sukolsak Sakshuwong  <sukolsak@gmail.com>
     2
     3        Parse control flow statements in WebAssembly
     4        https://bugs.webkit.org/show_bug.cgi?id=148333
     5
     6        Reviewed by Geoffrey Garen.
     7
     8        Parse control flow statements in WebAssembly files generated by pack-asmjs
     9        <https://github.com/WebAssembly/polyfill-prototype-1>.
     10
     11        * wasm/WASMConstants.h:
     12        * wasm/WASMFunctionParser.cpp:
     13        (JSC::WASMFunctionParser::parseStatement):
     14        (JSC::WASMFunctionParser::parseIfStatement):
     15        (JSC::WASMFunctionParser::parseIfElseStatement):
     16        (JSC::WASMFunctionParser::parseWhileStatement):
     17        (JSC::WASMFunctionParser::parseDoStatement):
     18        (JSC::WASMFunctionParser::parseLabelStatement):
     19        (JSC::WASMFunctionParser::parseBreakStatement):
     20        (JSC::WASMFunctionParser::parseBreakLabelStatement):
     21        (JSC::WASMFunctionParser::parseContinueStatement):
     22        (JSC::WASMFunctionParser::parseContinueLabelStatement):
     23        (JSC::WASMFunctionParser::parseSwitchStatement):
     24        * wasm/WASMFunctionParser.h:
     25        (JSC::WASMFunctionParser::WASMFunctionParser):
     26        * wasm/WASMReader.cpp:
     27        (JSC::WASMReader::readCompactInt32):
     28        (JSC::WASMReader::readSwitchCase):
     29        * wasm/WASMReader.h:
     30
    1312015-08-21  Geoffrey Garen  <ggaren@apple.com>
    232
  • trunk/Source/JavaScriptCore/wasm/WASMConstants.h

    r188778 r188808  
    183183};
    184184
     185enum class WASMSwitchCase : uint8_t {
     186    CaseWithNoStatements,
     187    CaseWithStatement,
     188    CaseWithBlockStatement,
     189    DefaultWithNoStatements,
     190    DefaultWithStatement,
     191    DefaultWithBlockStatement,
     192    NumberOfSwitchCases
     193};
     194
    185195enum class WASMExportFormat : uint8_t {
    186196    Default,
  • trunk/Source/JavaScriptCore/wasm/WASMFunctionParser.cpp

    r188778 r188808  
    3434#define PROPAGATE_ERROR() do { if (!m_errorMessage.isNull()) return 0; } while (0)
    3535#define FAIL_WITH_MESSAGE(errorMessage) do {  m_errorMessage = errorMessage; return 0; } while (0)
     36#define READ_COMPACT_INT32_OR_FAIL(result, errorMessage) do { if (!m_reader.readCompactInt32(result)) FAIL_WITH_MESSAGE(errorMessage); } while (0)
    3637#define READ_COMPACT_UINT32_OR_FAIL(result, errorMessage) do { if (!m_reader.readCompactUInt32(result)) FAIL_WITH_MESSAGE(errorMessage); } while (0)
    3738#define READ_OP_STATEMENT_OR_FAIL(hasImmediate, op, opWithImmediate, immediate, errorMessage) do { if (!m_reader.readOpStatement(hasImmediate, op, opWithImmediate, immediate)) FAIL_WITH_MESSAGE(errorMessage); } while (0)
    3839#define READ_OP_EXPRESSION_I32_OR_FAIL(hasImmediate, op, opWithImmediate, immediate, errorMessage) do { if (!m_reader.readOpExpressionI32(hasImmediate, op, opWithImmediate, immediate)) FAIL_WITH_MESSAGE(errorMessage); } while (0)
    3940#define READ_VARIABLE_TYPES_OR_FAIL(hasImmediate, variableTypes, variableTypesWithImmediate, immediate, errorMessage) do { if (!m_reader.readVariableTypes(hasImmediate, variableTypes, variableTypesWithImmediate, immediate)) FAIL_WITH_MESSAGE(errorMessage); } while (0)
     41#define READ_SWITCH_CASE_OR_FAIL(result, errorMessage) do { if (!m_reader.readSwitchCase(result)) FAIL_WITH_MESSAGE(errorMessage); } while (0)
    4042#define FAIL_IF_FALSE(condition, errorMessage) do { if (!(condition)) FAIL_WITH_MESSAGE(errorMessage); } while (0)
    4143
     
    124126            parseBlockStatement(context);
    125127            break;
     128        case WASMOpStatement::If:
     129            parseIfStatement(context);
     130            break;
     131        case WASMOpStatement::IfElse:
     132            parseIfElseStatement(context);
     133            break;
     134        case WASMOpStatement::While:
     135            parseWhileStatement(context);
     136            break;
     137        case WASMOpStatement::Do:
     138            parseDoStatement(context);
     139            break;
     140        case WASMOpStatement::Label:
     141            parseLabelStatement(context);
     142            break;
     143        case WASMOpStatement::Break:
     144            parseBreakStatement(context);
     145            break;
     146        case WASMOpStatement::BreakLabel:
     147            parseBreakLabelStatement(context);
     148            break;
     149        case WASMOpStatement::Continue:
     150            parseContinueStatement(context);
     151            break;
     152        case WASMOpStatement::ContinueLabel:
     153            parseContinueLabelStatement(context);
     154            break;
     155        case WASMOpStatement::Switch:
     156            parseSwitchStatement(context);
     157            break;
    126158        case WASMOpStatement::SetGlobal:
    127         case WASMOpStatement::If:
    128         case WASMOpStatement::IfElse:
    129         case WASMOpStatement::While:
    130         case WASMOpStatement::Do:
    131         case WASMOpStatement::Label:
    132         case WASMOpStatement::Break:
    133         case WASMOpStatement::BreakLabel:
    134         case WASMOpStatement::Continue:
    135         case WASMOpStatement::ContinueLabel:
    136         case WASMOpStatement::Switch:
    137159        case WASMOpStatement::I32Store8:
    138160        case WASMOpStatement::I32StoreWithOffset8:
     
    204226        PROPAGATE_ERROR();
    205227    }
     228    return UNUSED;
     229}
     230
     231template <class Context>
     232ContextStatement WASMFunctionParser::parseIfStatement(Context& context)
     233{
     234    parseExpressionI32(context);
     235    PROPAGATE_ERROR();
     236    parseStatement(context);
     237    // FIXME: Implement this instruction.
     238    return UNUSED;
     239}
     240
     241template <class Context>
     242ContextStatement WASMFunctionParser::parseIfElseStatement(Context& context)
     243{
     244    parseExpressionI32(context);
     245    PROPAGATE_ERROR();
     246    parseStatement(context);
     247    PROPAGATE_ERROR();
     248    parseStatement(context);
     249    // FIXME: Implement this instruction.
     250    return UNUSED;
     251}
     252
     253template <class Context>
     254ContextStatement WASMFunctionParser::parseWhileStatement(Context& context)
     255{
     256    parseExpressionI32(context);
     257    PROPAGATE_ERROR();
     258
     259    m_breakScopeDepth++;
     260    m_continueScopeDepth++;
     261    parseStatement(context);
     262    PROPAGATE_ERROR();
     263    m_continueScopeDepth--;
     264    m_breakScopeDepth--;
     265    // FIXME: Implement this instruction.
     266    return UNUSED;
     267}
     268
     269template <class Context>
     270ContextStatement WASMFunctionParser::parseDoStatement(Context& context)
     271{
     272    m_breakScopeDepth++;
     273    m_continueScopeDepth++;
     274    parseStatement(context);
     275    PROPAGATE_ERROR();
     276    m_continueScopeDepth--;
     277    m_breakScopeDepth--;
     278
     279    parseExpressionI32(context);
     280    // FIXME: Implement this instruction.
     281    return UNUSED;
     282}
     283
     284template <class Context>
     285ContextStatement WASMFunctionParser::parseLabelStatement(Context& context)
     286{
     287    m_labelDepth++;
     288    parseStatement(context);
     289    PROPAGATE_ERROR();
     290    m_labelDepth--;
     291    // FIXME: Implement this instruction.
     292    return UNUSED;
     293}
     294
     295template <class Context>
     296ContextStatement WASMFunctionParser::parseBreakStatement(Context&)
     297{
     298    FAIL_IF_FALSE(m_breakScopeDepth, "'break' is only valid inside a switch or loop statement.");
     299    // FIXME: Implement this instruction.
     300    return UNUSED;
     301}
     302
     303template <class Context>
     304ContextStatement WASMFunctionParser::parseBreakLabelStatement(Context&)
     305{
     306    uint32_t labelIndex;
     307    READ_COMPACT_UINT32_OR_FAIL(labelIndex, "Cannot read the label index.");
     308    FAIL_IF_FALSE(labelIndex < m_labelDepth, "The label index is incorrect.");
     309    // FIXME: Implement this instruction.
     310    return UNUSED;
     311}
     312
     313template <class Context>
     314ContextStatement WASMFunctionParser::parseContinueStatement(Context&)
     315{
     316    FAIL_IF_FALSE(m_continueScopeDepth, "'continue' is only valid inside a loop statement.");
     317    // FIXME: Implement this instruction.
     318    return UNUSED;
     319}
     320
     321template <class Context>
     322ContextStatement WASMFunctionParser::parseContinueLabelStatement(Context&)
     323{
     324    uint32_t labelIndex;
     325    READ_COMPACT_UINT32_OR_FAIL(labelIndex, "Cannot read the label index.");
     326    FAIL_IF_FALSE(labelIndex < m_labelDepth, "The label index is incorrect.");
     327    // FIXME: Implement this instruction.
     328    return UNUSED;
     329}
     330
     331template <class Context>
     332ContextStatement WASMFunctionParser::parseSwitchStatement(Context& context)
     333{
     334    uint32_t numberOfCases;
     335    READ_COMPACT_UINT32_OR_FAIL(numberOfCases, "Cannot read the number of cases.");
     336    parseExpressionI32(context);
     337    PROPAGATE_ERROR();
     338
     339    m_breakScopeDepth++;
     340    for (uint32_t i = 0; i < numberOfCases; ++i) {
     341        WASMSwitchCase switchCase;
     342        READ_SWITCH_CASE_OR_FAIL(switchCase, "Cannot read the switch case.");
     343        switch (switchCase) {
     344        case WASMSwitchCase::CaseWithNoStatements:
     345        case WASMSwitchCase::CaseWithStatement:
     346        case WASMSwitchCase::CaseWithBlockStatement: {
     347            uint32_t value;
     348            READ_COMPACT_INT32_OR_FAIL(value, "Cannot read the value of the switch case.");
     349            if (switchCase == WASMSwitchCase::CaseWithStatement) {
     350                parseStatement(context);
     351                PROPAGATE_ERROR();
     352            } else if (switchCase == WASMSwitchCase::CaseWithBlockStatement) {
     353                parseBlockStatement(context);
     354                PROPAGATE_ERROR();
     355            }
     356            break;
     357        }
     358        case WASMSwitchCase::DefaultWithNoStatements:
     359        case WASMSwitchCase::DefaultWithStatement:
     360        case WASMSwitchCase::DefaultWithBlockStatement: {
     361            FAIL_IF_FALSE(i == numberOfCases - 1, "The default case must be the last case.");
     362            if (switchCase == WASMSwitchCase::DefaultWithStatement) {
     363                parseStatement(context);
     364                PROPAGATE_ERROR();
     365            } else if (switchCase == WASMSwitchCase::DefaultWithBlockStatement) {
     366                parseBlockStatement(context);
     367                PROPAGATE_ERROR();
     368            }
     369            break;
     370        }
     371        default:
     372            ASSERT_NOT_REACHED();
     373        }
     374    }
     375    m_breakScopeDepth--;
     376    // FIXME: Implement this instruction.
    206377    return UNUSED;
    207378}
  • trunk/Source/JavaScriptCore/wasm/WASMFunctionParser.h

    r188778 r188808  
    4848        , m_reader(static_cast<WebAssemblySourceProvider*>(source.provider())->data())
    4949        , m_functionIndex(functionIndex)
     50        , m_breakScopeDepth(0)
     51        , m_continueScopeDepth(0)
     52        , m_labelDepth(0)
    5053    {
    5154    }
     
    5962    template <class Context> ContextStatement parseReturnStatement(Context&);
    6063    template <class Context> ContextStatement parseBlockStatement(Context&);
     64    template <class Context> ContextStatement parseIfStatement(Context&);
     65    template <class Context> ContextStatement parseIfElseStatement(Context&);
     66    template <class Context> ContextStatement parseWhileStatement(Context&);
     67    template <class Context> ContextStatement parseDoStatement(Context&);
     68    template <class Context> ContextStatement parseLabelStatement(Context&);
     69    template <class Context> ContextStatement parseBreakStatement(Context&);
     70    template <class Context> ContextStatement parseBreakLabelStatement(Context&);
     71    template <class Context> ContextStatement parseContinueStatement(Context&);
     72    template <class Context> ContextStatement parseContinueLabelStatement(Context&);
     73    template <class Context> ContextStatement parseSwitchStatement(Context&);
    6174
    6275    template <class Context> ContextExpression parseExpression(Context&, WASMExpressionType);
     
    7689    uint32_t m_numberOfF32LocalVariables;
    7790    uint32_t m_numberOfF64LocalVariables;
     91
     92    unsigned m_breakScopeDepth;
     93    unsigned m_continueScopeDepth;
     94    unsigned m_labelDepth;
    7895};
    7996
  • trunk/Source/JavaScriptCore/wasm/WASMReader.cpp

    r188778 r188808  
    9494    m_cursor += 8;
    9595    return true;
     96}
     97
     98bool WASMReader::readCompactInt32(uint32_t& result)
     99{
     100    uint32_t sum = 0;
     101    unsigned shift = 0;
     102    do {
     103        CHECK_READ(1);
     104        uint8_t byte = *m_cursor++;
     105        if (byte < 0x80) {
     106            sum |= byte << shift;
     107            int signExtend = (32 - 7) - shift;
     108            if (signExtend > 0)
     109                result = int32_t(sum) << signExtend >> signExtend;
     110            else
     111                result = int32_t(sum);
     112            return true;
     113        }
     114        sum |= (byte & firstSevenBitsMask) << shift;
     115        shift += 7;
     116    } while (shift < 35);
     117    return false;
    96118}
    97119
     
    198220}
    199221
     222bool WASMReader::readSwitchCase(WASMSwitchCase& result)
     223{
     224    return readByte<WASMSwitchCase>(result, static_cast<uint8_t>(WASMSwitchCase::NumberOfSwitchCases));
     225}
     226
    200227} // namespace JSC
    201228
  • trunk/Source/JavaScriptCore/wasm/WASMReader.h

    r188778 r188808  
    4949    bool readFloat(float& result);
    5050    bool readDouble(double& result);
     51    bool readCompactInt32(uint32_t& result);
    5152    bool readCompactUInt32(uint32_t& result);
    5253    bool readString(String& result);
     
    5758    bool readOpExpressionI32(bool& hasImmediate, WASMOpExpressionI32&, WASMOpExpressionI32WithImmediate&, uint8_t& immediate);
    5859    bool readVariableTypes(bool& hasImmediate, WASMVariableTypes&, WASMVariableTypesWithImmediate&, uint8_t& immediate);
     60    bool readSwitchCase(WASMSwitchCase& result);
    5961
    6062private:
Note: See TracChangeset for help on using the changeset viewer.