Changeset 190062 in webkit


Ignore:
Timestamp:
Sep 21, 2015 11:47:38 AM (9 years ago)
Author:
Sukolsak Sakshuwong
Message:

Implement Store expressions in WebAssembly
https://bugs.webkit.org/show_bug.cgi?id=149395

Reviewed by Geoffrey Garen.

The Store instruction in WebAssembly stores a value in the linear memory
at the given index. It can be both a statement and an expression. When
it is an expression, it returns the assigned value. This patch
implements Store as an expression.

Since Store uses two operands, which are the index and the value, we
need to pop the two operands from the stack and push the value back to
the stack. We can simply implement this by copying the value to where
the index is in the stack.

  • tests/stress/wasm-linear-memory.js:
  • wasm/WASMFunctionCompiler.h:

(JSC::WASMFunctionCompiler::buildStore):

  • wasm/WASMFunctionParser.cpp:

(JSC::WASMFunctionParser::parseStatement):
(JSC::WASMFunctionParser::parseExpressionI32):
(JSC::WASMFunctionParser::parseExpressionF32):
(JSC::WASMFunctionParser::parseExpressionF64):
(JSC::WASMFunctionParser::parseStore):

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

(JSC::WASMFunctionSyntaxChecker::buildStore):

Location:
trunk/Source/JavaScriptCore
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r190043 r190062  
     12015-09-21  Sukolsak Sakshuwong  <sukolsak@gmail.com>
     2
     3        Implement Store expressions in WebAssembly
     4        https://bugs.webkit.org/show_bug.cgi?id=149395
     5
     6        Reviewed by Geoffrey Garen.
     7
     8        The Store instruction in WebAssembly stores a value in the linear memory
     9        at the given index. It can be both a statement and an expression. When
     10        it is an expression, it returns the assigned value. This patch
     11        implements Store as an expression.
     12
     13        Since Store uses two operands, which are the index and the value, we
     14        need to pop the two operands from the stack and push the value back to
     15        the stack. We can simply implement this by copying the value to where
     16        the index is in the stack.
     17
     18        * tests/stress/wasm-linear-memory.js:
     19        * wasm/WASMFunctionCompiler.h:
     20        (JSC::WASMFunctionCompiler::buildStore):
     21        * wasm/WASMFunctionParser.cpp:
     22        (JSC::WASMFunctionParser::parseStatement):
     23        (JSC::WASMFunctionParser::parseExpressionI32):
     24        (JSC::WASMFunctionParser::parseExpressionF32):
     25        (JSC::WASMFunctionParser::parseExpressionF64):
     26        (JSC::WASMFunctionParser::parseStore):
     27        * wasm/WASMFunctionParser.h:
     28        * wasm/WASMFunctionSyntaxChecker.h:
     29        (JSC::WASMFunctionSyntaxChecker::buildStore):
     30
    1312015-09-20  Sukolsak Sakshuwong  <sukolsak@gmail.com>
    232
  • trunk/Source/JavaScriptCore/tests/stress/wasm-linear-memory.js

    r189993 r190062  
    111111    }
    112112
     113    function setInt8Expression(i, x) {
     114        i = i | 0;
     115        x = x | 0;
     116        return (int8Array[i] = x) | 0;
     117    }
     118
     119    function setUint8Expression(i, x) {
     120        i = i | 0;
     121        x = x | 0;
     122        return (uint8Array[i] = x) | 0;
     123    }
     124
     125    function setInt16Expression(i, x) {
     126        i = i | 0;
     127        x = x | 0;
     128        return (int16Array[i >> 1] = x) | 0;
     129    }
     130
     131    function setUint16Expression(i, x) {
     132        i = i | 0;
     133        x = x | 0;
     134        return (uint16Array[i >> 1] = x) | 0;
     135    }
     136
     137    function setInt32Expression(i, x) {
     138        i = i | 0;
     139        x = x | 0;
     140        return (int32Array[i >> 2] = x) | 0;
     141    }
     142
     143    function setFloat32Expression(i, x) {
     144        i = i | 0;
     145        x = fround(x);
     146        return float32Array[i >> 2] = x;
     147    }
     148
     149    function setFloat64Expression(i, x) {
     150        i = i | 0;
     151        x = +x;
     152        return float64Array[i >> 3] = x;
     153    }
     154
    113155    return {
    114156        getInt8: getInt8,
     
    119161        getFloat32: getFloat32,
    120162        getFloat64: getFloat64,
     163
    121164        setInt8: setInt8,
    122165        setUint8: setUint8,
     
    126169        setFloat32: setFloat32,
    127170        setFloat64: setFloat64,
     171
     172        setInt8Expression: setInt8Expression,
     173        setUint8Expression: setUint8Expression,
     174        setInt16Expression: setInt16Expression,
     175        setUint16Expression: setUint16Expression,
     176        setInt32Expression: setInt32Expression,
     177        setFloat32Expression: setFloat32Expression,
     178        setFloat64Expression: setFloat64Expression,
    128179    };
    129180}
     
    203254module.setInt32(8, 6);
    204255shouldBe(int32Array[0] == 1 && int32Array[1] == 5 && int32Array[2] == 6, true);
     256
     257// Store expressions.
     258shouldBe(module.setInt8Expression(0, 1), 1);
     259shouldBe(module.getInt8(0), 1);
     260shouldBe(module.setUint8Expression(0, -1), -1);
     261shouldBe(module.getUint8(0), 255);
     262shouldBe(module.setInt16Expression(0, 2), 2);
     263shouldBe(module.getInt16(0), 2);
     264shouldBe(module.setUint16Expression(0, -1), -1);
     265shouldBe(module.getUint16(0), 65535);
     266shouldBe(module.setInt32Expression(0, 3), 3);
     267shouldBe(module.getInt32(0), 3);
     268shouldBe(module.setFloat32Expression(0, 4.2), 4.199999809265137);
     269shouldBe(module.getFloat32(0), 4.199999809265137);
     270shouldBe(module.setFloat64Expression(0, 4.2), 4.2);
     271shouldBe(module.getFloat64(0), 4.2);
  • trunk/Source/JavaScriptCore/wasm/WASMFunctionCompiler.h

    r190043 r190062  
    533533    }
    534534
    535     int buildStore(const MemoryAddress& memoryAddress, WASMExpressionType expressionType, WASMMemoryType memoryType, int)
     535    int buildStore(WASMOpKind opKind, const MemoryAddress& memoryAddress, WASMExpressionType expressionType, WASMMemoryType memoryType, int)
    536536    {
    537537        const ArrayBuffer* arrayBuffer = m_module->arrayBuffer()->impl();
     
    581581        }
    582582        m_tempStackTop -= 2;
     583
     584        if (opKind == WASMOpKind::Expression) {
     585            switch (expressionType) {
     586            case WASMExpressionType::I32:
     587            case WASMExpressionType::F32:
     588                store32(GPRInfo::regT2, temporaryAddress(m_tempStackTop++));
     589                break;
     590            case WASMExpressionType::F64:
     591                storeDouble(FPRInfo::fpRegT0, temporaryAddress(m_tempStackTop++));
     592                break;
     593            default:
     594                ASSERT_NOT_REACHED();
     595            }
     596        }
    583597        return UNUSED;
    584598    }
  • trunk/Source/JavaScriptCore/wasm/WASMFunctionParser.cpp

    r190055 r190062  
    159159            break;
    160160        case WASMOpStatement::I32Store8:
    161             parseStore(context, WASMExpressionType::I32, WASMMemoryType::I8, MemoryAccessOffsetMode::NoOffset);
     161            parseStore(context, WASMOpKind::Statement, WASMExpressionType::I32, WASMMemoryType::I8, MemoryAccessOffsetMode::NoOffset);
    162162            break;
    163163        case WASMOpStatement::I32StoreWithOffset8:
    164             parseStore(context, WASMExpressionType::I32, WASMMemoryType::I8, MemoryAccessOffsetMode::WithOffset);
     164            parseStore(context, WASMOpKind::Statement, WASMExpressionType::I32, WASMMemoryType::I8, MemoryAccessOffsetMode::WithOffset);
    165165            break;
    166166        case WASMOpStatement::I32Store16:
    167             parseStore(context, WASMExpressionType::I32, WASMMemoryType::I16, MemoryAccessOffsetMode::NoOffset);
     167            parseStore(context, WASMOpKind::Statement, WASMExpressionType::I32, WASMMemoryType::I16, MemoryAccessOffsetMode::NoOffset);
    168168            break;
    169169        case WASMOpStatement::I32StoreWithOffset16:
    170             parseStore(context, WASMExpressionType::I32, WASMMemoryType::I16, MemoryAccessOffsetMode::WithOffset);
     170            parseStore(context, WASMOpKind::Statement, WASMExpressionType::I32, WASMMemoryType::I16, MemoryAccessOffsetMode::WithOffset);
    171171            break;
    172172        case WASMOpStatement::I32Store32:
    173             parseStore(context, WASMExpressionType::I32, WASMMemoryType::I32, MemoryAccessOffsetMode::NoOffset);
     173            parseStore(context, WASMOpKind::Statement, WASMExpressionType::I32, WASMMemoryType::I32, MemoryAccessOffsetMode::NoOffset);
    174174            break;
    175175        case WASMOpStatement::I32StoreWithOffset32:
    176             parseStore(context, WASMExpressionType::I32, WASMMemoryType::I32, MemoryAccessOffsetMode::WithOffset);
     176            parseStore(context, WASMOpKind::Statement, WASMExpressionType::I32, WASMMemoryType::I32, MemoryAccessOffsetMode::WithOffset);
    177177            break;
    178178        case WASMOpStatement::F32Store:
    179             parseStore(context, WASMExpressionType::F32, WASMMemoryType::F32, MemoryAccessOffsetMode::NoOffset);
     179            parseStore(context, WASMOpKind::Statement, WASMExpressionType::F32, WASMMemoryType::F32, MemoryAccessOffsetMode::NoOffset);
    180180            break;
    181181        case WASMOpStatement::F32StoreWithOffset:
    182             parseStore(context, WASMExpressionType::F32, WASMMemoryType::F32, MemoryAccessOffsetMode::WithOffset);
     182            parseStore(context, WASMOpKind::Statement, WASMExpressionType::F32, WASMMemoryType::F32, MemoryAccessOffsetMode::WithOffset);
    183183            break;
    184184        case WASMOpStatement::F64Store:
    185             parseStore(context, WASMExpressionType::F64, WASMMemoryType::F64, MemoryAccessOffsetMode::NoOffset);
     185            parseStore(context, WASMOpKind::Statement, WASMExpressionType::F64, WASMMemoryType::F64, MemoryAccessOffsetMode::NoOffset);
    186186            break;
    187187        case WASMOpStatement::F64StoreWithOffset:
    188             parseStore(context, WASMExpressionType::F64, WASMMemoryType::F64, MemoryAccessOffsetMode::WithOffset);
     188            parseStore(context, WASMOpKind::Statement, WASMExpressionType::F64, WASMMemoryType::F64, MemoryAccessOffsetMode::WithOffset);
    189189            break;
    190190        case WASMOpStatement::Return:
     
    549549        case WASMOpExpressionI32::LoadWithOffset32:
    550550            return parseLoad(context, WASMExpressionType::I32, WASMMemoryType::I32, MemoryAccessOffsetMode::WithOffset);
     551        case WASMOpExpressionI32::Store8:
     552            return parseStore(context, WASMOpKind::Expression, WASMExpressionType::I32, WASMMemoryType::I8, MemoryAccessOffsetMode::NoOffset);
     553        case WASMOpExpressionI32::StoreWithOffset8:
     554            return parseStore(context, WASMOpKind::Expression, WASMExpressionType::I32, WASMMemoryType::I8, MemoryAccessOffsetMode::WithOffset);
     555        case WASMOpExpressionI32::Store16:
     556            return parseStore(context, WASMOpKind::Expression, WASMExpressionType::I32, WASMMemoryType::I16, MemoryAccessOffsetMode::NoOffset);
     557        case WASMOpExpressionI32::StoreWithOffset16:
     558            return parseStore(context, WASMOpKind::Expression, WASMExpressionType::I32, WASMMemoryType::I16, MemoryAccessOffsetMode::WithOffset);
     559        case WASMOpExpressionI32::Store32:
     560            return parseStore(context, WASMOpKind::Expression, WASMExpressionType::I32, WASMMemoryType::I32, MemoryAccessOffsetMode::NoOffset);
     561        case WASMOpExpressionI32::StoreWithOffset32:
     562            return parseStore(context, WASMOpKind::Expression, WASMExpressionType::I32, WASMMemoryType::I32, MemoryAccessOffsetMode::WithOffset);
    551563        case WASMOpExpressionI32::CallInternal:
    552564            return parseCallInternal(context, WASMExpressionType::I32);
     
    604616        case WASMOpExpressionI32::GreaterThanOrEqualF64:
    605617            return parseRelationalF64ExpressionI32(context, op);
    606         case WASMOpExpressionI32::Store8:
    607         case WASMOpExpressionI32::StoreWithOffset8:
    608         case WASMOpExpressionI32::Store16:
    609         case WASMOpExpressionI32::StoreWithOffset16:
    610         case WASMOpExpressionI32::Store32:
    611         case WASMOpExpressionI32::StoreWithOffset32:
    612618        case WASMOpExpressionI32::Conditional:
    613619        case WASMOpExpressionI32::Comma:
     
    739745        case WASMOpExpressionF32::LoadWithOffset:
    740746            return parseLoad(context, WASMExpressionType::F32, WASMMemoryType::F32, MemoryAccessOffsetMode::WithOffset);
     747        case WASMOpExpressionF32::Store:
     748            return parseStore(context, WASMOpKind::Expression, WASMExpressionType::F32, WASMMemoryType::F32, MemoryAccessOffsetMode::NoOffset);
     749        case WASMOpExpressionF32::StoreWithOffset:
     750            return parseStore(context, WASMOpKind::Expression, WASMExpressionType::F32, WASMMemoryType::F32, MemoryAccessOffsetMode::WithOffset);
    741751        case WASMOpExpressionF32::CallInternal:
    742752            return parseCallInternal(context, WASMExpressionType::F32);
     
    760770        case WASMOpExpressionF32::Div:
    761771            return parseBinaryExpressionF32(context, op);
    762         case WASMOpExpressionF32::Store:
    763         case WASMOpExpressionF32::StoreWithOffset:
    764772        case WASMOpExpressionF32::Conditional:
    765773        case WASMOpExpressionF32::Comma:
     
    849857        case WASMOpExpressionF64::LoadWithOffset:
    850858            return parseLoad(context, WASMExpressionType::F64, WASMMemoryType::F64, MemoryAccessOffsetMode::WithOffset);
     859        case WASMOpExpressionF64::Store:
     860            return parseStore(context, WASMOpKind::Expression, WASMExpressionType::F64, WASMMemoryType::F64, MemoryAccessOffsetMode::NoOffset);
     861        case WASMOpExpressionF64::StoreWithOffset:
     862            return parseStore(context, WASMOpKind::Expression, WASMExpressionType::F64, WASMMemoryType::F64, MemoryAccessOffsetMode::WithOffset);
    851863        case WASMOpExpressionF64::CallInternal:
    852864            return parseCallInternal(context, WASMExpressionType::F64);
     
    883895        case WASMOpExpressionF64::Pow:
    884896            return parseBinaryExpressionF64(context, op);
    885         case WASMOpExpressionF64::Store:
    886         case WASMOpExpressionF64::StoreWithOffset:
    887897        case WASMOpExpressionF64::Conditional:
    888898        case WASMOpExpressionF64::Comma:
     
    10351045
    10361046template <class Context>
    1037 ContextExpression WASMFunctionParser::parseStore(Context& context, WASMExpressionType expressionType, WASMMemoryType memoryType, MemoryAccessOffsetMode offsetMode)
     1047ContextExpression WASMFunctionParser::parseStore(Context& context, WASMOpKind opKind, WASMExpressionType expressionType, WASMMemoryType memoryType, MemoryAccessOffsetMode offsetMode)
    10381048{
    10391049    FAIL_IF_FALSE(m_module->arrayBuffer(), "An ArrayBuffer is not provided.");
     
    10431053    ContextExpression value = parseExpression(context, expressionType);
    10441054    PROPAGATE_ERROR();
    1045     return context.buildStore(memoryAddress, expressionType, memoryType, value);
     1055    return context.buildStore(opKind, memoryAddress, expressionType, memoryType, value);
    10461056}
    10471057
  • trunk/Source/JavaScriptCore/wasm/WASMFunctionParser.h

    r190043 r190062  
    113113    template <class Context> ContextMemoryAddress parseMemoryAddress(Context&, MemoryAccessOffsetMode);
    114114    template <class Context> ContextExpression parseLoad(Context&, WASMExpressionType, WASMMemoryType, MemoryAccessOffsetMode, MemoryAccessConversion = MemoryAccessConversion::NoConversion);
    115     template <class Context> ContextExpression parseStore(Context&, WASMExpressionType, WASMMemoryType, MemoryAccessOffsetMode);
     115    template <class Context> ContextExpression parseStore(Context&, WASMOpKind, WASMExpressionType, WASMMemoryType, MemoryAccessOffsetMode);
    116116    template <class Context> ContextExpressionList parseCallArguments(Context&, const Vector<WASMType>& arguments);
    117117    template <class Context> ContextExpression parseCallInternal(Context&, WASMExpressionType returnType);
  • trunk/Source/JavaScriptCore/wasm/WASMFunctionSyntaxChecker.h

    r190043 r190062  
    120120    }
    121121
    122     int buildStore(const MemoryAddress&, WASMExpressionType, WASMMemoryType, int)
     122    int buildStore(WASMOpKind opKind, const MemoryAddress&, WASMExpressionType, WASMMemoryType, int)
    123123    {
    124124        m_tempStackTop -= 2;
     125        if (opKind == WASMOpKind::Expression)
     126            m_tempStackTop++;
    125127        return UNUSED;
    126128    }
Note: See TracChangeset for help on using the changeset viewer.