Changeset 190125 in webkit


Ignore:
Timestamp:
Sep 22, 2015 11:46:45 AM (9 years ago)
Author:
Sukolsak Sakshuwong
Message:

Implement the conditional instruction in WebAssembly
https://bugs.webkit.org/show_bug.cgi?id=149451

Reviewed by Geoffrey Garen.

This patch implements the conditional (ternary) instruction in WebAssembly.
This is basically "condition ? exp1 : exp2" in JavaScript.

The use of context.discard() in WASMFunctionParser::parseConditional()
is not ideal. We don't discard anything. We just use it to decrement the
stack top in the WebAssembly baseline JIT. When we optimize the JIT by
storing results directly into the destination like the JavaScript
baseline JIT, the code will look like this:

ContextExpression temp = context.newTemporary();
ContextExpression condition = parseExpressionI32(context);
context.jumpToTargetIf(Context::JumpCondition::Zero, condition, elseTarget);

parseExpression(context, temp, expressionType);
context.jumpToTarget(end);

context.linkTarget(elseTarget);
parseExpression(context, temp, expressionType);
context.linkTarget(end);

return temp;

which looks cleaner than using discard().

  • tests/stress/wasm-control-flow.js:
  • tests/stress/wasm/control-flow.wasm:
  • wasm/WASMFunctionParser.cpp:

(JSC::WASMFunctionParser::parseExpressionI32):
(JSC::WASMFunctionParser::parseExpressionF32):
(JSC::WASMFunctionParser::parseExpressionF64):
(JSC::WASMFunctionParser::parseConditional):

  • wasm/WASMFunctionParser.h:
Location:
trunk/Source/JavaScriptCore
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r190113 r190125  
     12015-09-22  Sukolsak Sakshuwong  <sukolsak@gmail.com>
     2
     3        Implement the conditional instruction in WebAssembly
     4        https://bugs.webkit.org/show_bug.cgi?id=149451
     5
     6        Reviewed by Geoffrey Garen.
     7
     8        This patch implements the conditional (ternary) instruction in WebAssembly.
     9        This is basically "condition ? exp1 : exp2" in JavaScript.
     10       
     11        The use of context.discard() in WASMFunctionParser::parseConditional()
     12        is not ideal. We don't discard anything. We just use it to decrement the
     13        stack top in the WebAssembly baseline JIT. When we optimize the JIT by
     14        storing results directly into the destination like the JavaScript
     15        baseline JIT, the code will look like this:
     16
     17            ContextExpression temp = context.newTemporary();
     18            ContextExpression condition = parseExpressionI32(context);
     19            context.jumpToTargetIf(Context::JumpCondition::Zero, condition, elseTarget);
     20
     21            parseExpression(context, temp, expressionType);
     22            context.jumpToTarget(end);
     23
     24            context.linkTarget(elseTarget);
     25            parseExpression(context, temp, expressionType);
     26            context.linkTarget(end);
     27
     28            return temp;
     29
     30        which looks cleaner than using discard().
     31
     32        * tests/stress/wasm-control-flow.js:
     33        * tests/stress/wasm/control-flow.wasm:
     34        * wasm/WASMFunctionParser.cpp:
     35        (JSC::WASMFunctionParser::parseExpressionI32):
     36        (JSC::WASMFunctionParser::parseExpressionF32):
     37        (JSC::WASMFunctionParser::parseExpressionF64):
     38        (JSC::WASMFunctionParser::parseConditional):
     39        * wasm/WASMFunctionParser.h:
     40
    1412015-09-22  Commit Queue  <commit-queue@webkit.org>
    242
  • trunk/Source/JavaScriptCore/tests/stress/wasm-control-flow.js

    r189844 r190125  
    241241    }
    242242
     243    function conditionalTrue() {
     244        var x = 0;
     245        x = 5;
     246        return (((x | 0) > 0) ? 1 : 2) | 0;
     247    }
     248
     249    function conditionalFalse() {
     250        var x = 0;
     251        return ((x | 0) > 0) ? 1.0 : 2.0;
     252    }
     253
     254    function conditionalFalse2() {
     255        var x = 0, y = 0;
     256        return (((x | 0) > 0) ? (y = (y + 1) | 0) : (y = (y + 2) | 0)) | 0;
     257    }
     258
    243259    return {
    244260        ifTrue: ifTrue,
     
    247263        ifElseFalse: ifElseFalse,
    248264        ifInIf: ifInIf,
     265
    249266        whileLoop: whileLoop,
    250267        whileBreak: whileBreak,
    251268        whileContinue: whileContinue,
    252269        whileInWhile: whileInWhile,
     270
    253271        doLoop: doLoop,
    254272        doBreak: doBreak,
    255273        doContinue: doContinue,
     274
    256275        labelBreak: labelBreak,
    257276        labelContinue: labelContinue,
     
    259278        labelInLabelBreakOuter: labelInLabelBreakOuter,
    260279        whileInWhileBreakOuter: whileInWhileBreakOuter,
     280
    261281        switchCase: switchCase,
    262282        switchFallThrough: switchFallThrough,
     283
     284        conditionalTrue: conditionalTrue,
     285        conditionalFalse: conditionalFalse,
     286        conditionalFalse2: conditionalFalse2,
    263287    };
    264288}
     
    297321shouldBe(module.switchFallThrough(3), 1111);
    298322shouldBe(module.switchFallThrough(4), 1);
     323
     324shouldBe(module.conditionalTrue(), 1);
     325shouldBe(module.conditionalFalse(), 2);
     326shouldBe(module.conditionalFalse2(), 2);
  • trunk/Source/JavaScriptCore/wasm/WASMFunctionParser.cpp

    r190105 r190125  
    571571        case WASMOpExpressionI32::CallImport:
    572572            return parseCallImport(context, WASMOpKind::Expression, WASMExpressionType::I32);
     573        case WASMOpExpressionI32::Conditional:
     574            return parseConditional(context, WASMExpressionType::I32);
    573575        case WASMOpExpressionI32::Comma:
    574576            return parseComma(context, WASMExpressionType::I32);
     
    622624        case WASMOpExpressionI32::GreaterThanOrEqualF64:
    623625            return parseRelationalF64ExpressionI32(context, op);
    624         case WASMOpExpressionI32::Conditional:
    625626        case WASMOpExpressionI32::SMin:
    626627        case WASMOpExpressionI32::UMin:
     
    758759        case WASMOpExpressionF32::CallIndirect:
    759760            return parseCallIndirect(context, WASMOpKind::Expression, WASMExpressionType::F32);
     761        case WASMOpExpressionF32::Conditional:
     762            return parseConditional(context, WASMExpressionType::F32);
    760763        case WASMOpExpressionF32::Comma:
    761764            return parseComma(context, WASMExpressionType::F32);
     
    777780        case WASMOpExpressionF32::Div:
    778781            return parseBinaryExpressionF32(context, op);
    779         case WASMOpExpressionF32::Conditional:
    780             // FIXME: Implement these instructions.
    781             FAIL_WITH_MESSAGE("Unsupported instruction.");
    782782        default:
    783783            ASSERT_NOT_REACHED();
     
    873873        case WASMOpExpressionF64::CallIndirect:
    874874            return parseCallIndirect(context, WASMOpKind::Expression, WASMExpressionType::F64);
     875        case WASMOpExpressionF64::Conditional:
     876            return parseConditional(context, WASMExpressionType::F64);
    875877        case WASMOpExpressionF64::Comma:
    876878            return parseComma(context, WASMExpressionType::F64);
     
    903905        case WASMOpExpressionF64::Pow:
    904906            return parseBinaryExpressionF64(context, op);
    905         case WASMOpExpressionF64::Conditional:
    906907        case WASMOpExpressionF64::Min:
    907908        case WASMOpExpressionF64::Max:
     
    11431144
    11441145template <class Context>
     1146ContextExpression WASMFunctionParser::parseConditional(Context& context, WASMExpressionType expressionType)
     1147{
     1148    ContextJumpTarget elseTarget;
     1149    ContextJumpTarget end;
     1150
     1151    ContextExpression condition = parseExpressionI32(context);
     1152    PROPAGATE_ERROR();
     1153
     1154    context.jumpToTargetIf(Context::JumpCondition::Zero, condition, elseTarget);
     1155
     1156    parseExpression(context, expressionType);
     1157    PROPAGATE_ERROR();
     1158   
     1159    context.jumpToTarget(end);
     1160    context.linkTarget(elseTarget);
     1161
     1162    // We use discard() here to decrement the stack top in the baseline JIT.
     1163    context.discard(UNUSED);
     1164    parseExpression(context, expressionType);
     1165    PROPAGATE_ERROR();
     1166   
     1167    context.linkTarget(end);
     1168    return UNUSED;
     1169}
     1170
     1171template <class Context>
    11451172ContextExpression WASMFunctionParser::parseComma(Context& context, WASMExpressionType expressionType)
    11461173{
  • trunk/Source/JavaScriptCore/wasm/WASMFunctionParser.h

    r190105 r190125  
    120120    template <class Context> ContextExpression parseCallIndirect(Context&, WASMOpKind, WASMExpressionType returnType);
    121121    template <class Context> ContextExpression parseCallImport(Context&, WASMOpKind, WASMExpressionType returnType);
     122    template <class Context> ContextExpression parseConditional(Context&, WASMExpressionType);
    122123    template <class Context> ContextExpression parseComma(Context&, WASMExpressionType);
    123124    template <class Context> ContextExpression parseConvertType(Context&, WASMExpressionType fromType, WASMExpressionType toType, WASMTypeConversion);
Note: See TracChangeset for help on using the changeset viewer.