Changeset 189744 in webkit


Ignore:
Timestamp:
Sep 14, 2015 11:30:08 AM (9 years ago)
Author:
commit-queue@webkit.org
Message:

Implement the arithmetic instructions for floats in WebAssembly
https://bugs.webkit.org/show_bug.cgi?id=149102

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

This patch implements the arithmetic instructions for floats (float32)
in WebAssembly by converting the float operands to doubles, performing
the equivalent double instructions, and converting the result back to
float. The asm.js spec says that "As proved in 'When is double rounding
innocuous?' (Figueroa 1995), both the 32- and 64-bit versions of
standard arithmetic operations produce equivalent results when given
32-bit inputs and coerced to 32-bit outputs."
(http://asmjs.org/spec/latest/#floatish)

This patch also pads WebAssembly call frames by maxFrameExtentForSlowPathCall,
so that there is no need to adjust the stack pointer every time we make
a slow path call.

  • tests/stress/wasm-arithmetic-float32.js:
  • tests/stress/wasm/arithmetic-float32.wasm:
  • wasm/WASMFunctionCompiler.h:

(JSC::WASMFunctionCompiler::startFunction):
(JSC::WASMFunctionCompiler::buildUnaryF32):
(JSC::WASMFunctionCompiler::buildBinaryF32):
(JSC::WASMFunctionCompiler::callOperation):
(JSC::WASMFunctionCompiler::callAndUnboxResult):
(JSC::WASMFunctionCompiler::endFunction): Deleted.
(JSC::WASMFunctionCompiler::buildBinaryI32): Deleted.

  • wasm/WASMFunctionParser.cpp:

(JSC::WASMFunctionParser::parseExpressionF32):
(JSC::WASMFunctionParser::parseUnaryExpressionF32):
(JSC::WASMFunctionParser::parseBinaryExpressionF32):

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

(JSC::WASMFunctionSyntaxChecker::buildUnaryF32):
(JSC::WASMFunctionSyntaxChecker::buildBinaryF32):

Location:
trunk/Source/JavaScriptCore
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r189731 r189744  
     12015-09-14  Sukolsak Sakshuwong  <sukolsak@gmail.com>
     2
     3        Implement the arithmetic instructions for floats in WebAssembly
     4        https://bugs.webkit.org/show_bug.cgi?id=149102
     5
     6        Reviewed by Geoffrey Garen.
     7
     8        This patch implements the arithmetic instructions for floats (float32)
     9        in WebAssembly by converting the float operands to doubles, performing
     10        the equivalent double instructions, and converting the result back to
     11        float. The asm.js spec says that "As proved in 'When is double rounding
     12        innocuous?' (Figueroa 1995), both the 32- and 64-bit versions of
     13        standard arithmetic operations produce equivalent results when given
     14        32-bit inputs and coerced to 32-bit outputs."
     15        (http://asmjs.org/spec/latest/#floatish)
     16
     17        This patch also pads WebAssembly call frames by maxFrameExtentForSlowPathCall,
     18        so that there is no need to adjust the stack pointer every time we make
     19        a slow path call.
     20
     21        * tests/stress/wasm-arithmetic-float32.js:
     22        * tests/stress/wasm/arithmetic-float32.wasm:
     23        * wasm/WASMFunctionCompiler.h:
     24        (JSC::WASMFunctionCompiler::startFunction):
     25        (JSC::WASMFunctionCompiler::buildUnaryF32):
     26        (JSC::WASMFunctionCompiler::buildBinaryF32):
     27        (JSC::WASMFunctionCompiler::callOperation):
     28        (JSC::WASMFunctionCompiler::callAndUnboxResult):
     29        (JSC::WASMFunctionCompiler::endFunction): Deleted.
     30        (JSC::WASMFunctionCompiler::buildBinaryI32): Deleted.
     31        * wasm/WASMFunctionParser.cpp:
     32        (JSC::WASMFunctionParser::parseExpressionF32):
     33        (JSC::WASMFunctionParser::parseUnaryExpressionF32):
     34        (JSC::WASMFunctionParser::parseBinaryExpressionF32):
     35        * wasm/WASMFunctionParser.h:
     36        * wasm/WASMFunctionSyntaxChecker.h:
     37        (JSC::WASMFunctionSyntaxChecker::buildUnaryF32):
     38        (JSC::WASMFunctionSyntaxChecker::buildBinaryF32):
     39
    1402015-09-13  Geoffrey Garen  <ggaren@apple.com>
    241
  • trunk/Source/JavaScriptCore/tests/stress/wasm-arithmetic-float32.js

    r189624 r189744  
    1313
    1414    var fround = global.Math.fround;
     15    var abs = global.Math.abs;
     16    var ceil = global.Math.ceil;
     17    var floor = global.Math.floor;
     18    var sqrt = global.Math.sqrt;
    1519
    1620    function number() {
     
    1822    }
    1923
     24    function negate(x) {
     25        x = fround(x);
     26        return fround(-x);
     27    }
     28
     29    function add(x, y) {
     30        x = fround(x);
     31        y = fround(y);
     32        return fround(x + y);
     33    }
     34
     35    function subtract(x, y) {
     36        x = fround(x);
     37        y = fround(y);
     38        return fround(x - y);
     39    }
     40
     41    function multiply(x, y) {
     42        x = fround(x);
     43        y = fround(y);
     44        return fround(x * y);
     45    }
     46
     47    function divide(x, y) {
     48        x = fround(x);
     49        y = fround(y);
     50        return fround(x / y);
     51    }
     52
     53    function absolute(x) {
     54        x = fround(x);
     55        return fround(abs(x));
     56    }
     57
     58    function ceilNumber(x) {
     59        x = fround(x);
     60        return fround(ceil(x));
     61    }
     62
     63    function floorNumber(x) {
     64        x = fround(x);
     65        return fround(floor(x));
     66    }
     67
     68    function squareRoot(x) {
     69        x = fround(x);
     70        return fround(sqrt(x));
     71    }
     72
    2073    return {
    2174        number: number,
     75        negate: negate,
     76        add: add,
     77        subtract: subtract,
     78        multiply: multiply,
     79        divide: divide,
     80        absolute: absolute,
     81        ceilNumber: ceilNumber,
     82        floorNumber: floorNumber,
     83        squareRoot: squareRoot,
    2284    };
    2385}
     
    2789
    2890shouldBe(module.number(), 0.5);
     91shouldBe(module.negate(0.1), -0.10000000149011612);
     92shouldBe(module.add(0.1, 0.5), 0.6000000238418579);
     93shouldBe(isNaN(module.add(0.1, NaN)), true);
     94shouldBe(module.add(0.1, Infinity), Infinity);
     95shouldBe(isNaN(module.add(Infinity, -Infinity)), true);
     96shouldBe(module.subtract(0.1, 0.5), -0.4000000059604645);
     97shouldBe(module.multiply(0.1, 0.5), 0.05000000074505806);
     98shouldBe(module.divide(0.1, 0.5), 0.20000000298023224);
     99shouldBe(module.divide(0.1, 0), Infinity);
     100shouldBe(module.divide(0.1, -0), -Infinity);
     101shouldBe(module.absolute(-4.2), 4.199999809265137);
     102shouldBe(module.absolute(4.2), 4.199999809265137);
     103shouldBe(module.ceilNumber(4.2), 5);
     104shouldBe(module.floorNumber(4.2), 4);
     105shouldBe(module.squareRoot(0.09), 0.30000001192092896);
  • trunk/Source/JavaScriptCore/wasm/WASMFunctionCompiler.h

    r189645 r189744  
    9797        m_beginLabel = label();
    9898
    99         addPtr(TrustedImm32(-WTF::roundUpToMultipleOf(stackAlignmentRegisters(), m_stackHeight) * sizeof(StackSlot)), GPRInfo::callFrameRegister, GPRInfo::regT1);
     99        addPtr(TrustedImm32(-WTF::roundUpToMultipleOf(stackAlignmentRegisters(), m_stackHeight) * sizeof(StackSlot) - maxFrameExtentForSlowPathCall), GPRInfo::callFrameRegister, GPRInfo::regT1);
    100100        m_stackOverflow = branchPtr(Above, AbsoluteAddress(m_vm->addressOfStackLimit()), GPRInfo::regT1);
    101101
     
    166166            m_divideErrorJumpList.link(this);
    167167
    168             if (maxFrameExtentForSlowPathCall)
    169                 addPtr(TrustedImm32(-maxFrameExtentForSlowPathCall), stackPointerRegister);
    170168            setupArgumentsExecState();
    171169            appendCallWithExceptionCheck(operationThrowDivideError);
     
    378376        }
    379377        store32(GPRInfo::regT0, temporaryAddress(m_tempStackTop - 1));
     378        return UNUSED;
     379    }
     380
     381    int buildUnaryF32(int, WASMOpExpressionF32 op)
     382    {
     383        loadDouble(temporaryAddress(m_tempStackTop - 1), FPRInfo::fpRegT1);
     384        switch (op) {
     385        case WASMOpExpressionF32::Negate:
     386            convertFloatToDouble(FPRInfo::fpRegT1, FPRInfo::fpRegT1);
     387            negateDouble(FPRInfo::fpRegT1, FPRInfo::fpRegT0);
     388            convertDoubleToFloat(FPRInfo::fpRegT0, FPRInfo::fpRegT0);
     389            break;
     390        case WASMOpExpressionF32::Abs:
     391            convertFloatToDouble(FPRInfo::fpRegT1, FPRInfo::fpRegT1);
     392            absDouble(FPRInfo::fpRegT1, FPRInfo::fpRegT0);
     393            convertDoubleToFloat(FPRInfo::fpRegT0, FPRInfo::fpRegT0);
     394            break;
     395        case WASMOpExpressionF32::Ceil:
     396            callOperation(ceilf, FPRInfo::fpRegT1, FPRInfo::fpRegT0);
     397            break;
     398        case WASMOpExpressionF32::Floor:
     399            callOperation(floorf, FPRInfo::fpRegT1, FPRInfo::fpRegT0);
     400            break;
     401        case WASMOpExpressionF32::Sqrt:
     402            convertFloatToDouble(FPRInfo::fpRegT1, FPRInfo::fpRegT1);
     403            sqrtDouble(FPRInfo::fpRegT1, FPRInfo::fpRegT0);
     404            convertDoubleToFloat(FPRInfo::fpRegT0, FPRInfo::fpRegT0);
     405            break;
     406        default:
     407            ASSERT_NOT_REACHED();
     408        }
     409        storeDouble(FPRInfo::fpRegT0, temporaryAddress(m_tempStackTop - 1));
    380410        return UNUSED;
    381411    }
     
    420450#else
    421451            // FIXME: We should be able to do an inline div on ARMv7 and ARM64.
    422             if (maxFrameExtentForSlowPathCall)
    423                 addPtr(TrustedImm32(-maxFrameExtentForSlowPathCall), stackPointerRegister);
    424452            switch (op) {
    425453            case WASMOpExpressionI32::SDiv:
     
    438466                ASSERT_NOT_REACHED();
    439467            }
    440             if (maxFrameExtentForSlowPathCall)
    441                 addPtr(TrustedImm32(maxFrameExtentForSlowPathCall), stackPointerRegister);
    442468#endif
    443469            break;
     
    466492        m_tempStackTop--;
    467493        store32(GPRInfo::regT0, temporaryAddress(m_tempStackTop - 1));
     494        return UNUSED;
     495    }
     496
     497    int buildBinaryF32(int, int, WASMOpExpressionF32 op)
     498    {
     499        loadDouble(temporaryAddress(m_tempStackTop - 2), FPRInfo::fpRegT0);
     500        loadDouble(temporaryAddress(m_tempStackTop - 1), FPRInfo::fpRegT1);
     501        convertFloatToDouble(FPRInfo::fpRegT0, FPRInfo::fpRegT0);
     502        convertFloatToDouble(FPRInfo::fpRegT1, FPRInfo::fpRegT1);
     503        switch (op) {
     504        case WASMOpExpressionF32::Add:
     505            addDouble(FPRInfo::fpRegT1, FPRInfo::fpRegT0);
     506            break;
     507        case WASMOpExpressionF32::Sub:
     508            subDouble(FPRInfo::fpRegT1, FPRInfo::fpRegT0);
     509            break;
     510        case WASMOpExpressionF32::Mul:
     511            mulDouble(FPRInfo::fpRegT1, FPRInfo::fpRegT0);
     512            break;
     513        case WASMOpExpressionF32::Div:
     514            divDouble(FPRInfo::fpRegT1, FPRInfo::fpRegT0);
     515            break;
     516        default:
     517            RELEASE_ASSERT_NOT_REACHED();
     518        }
     519        convertDoubleToFloat(FPRInfo::fpRegT0, FPRInfo::fpRegT0);
     520        m_tempStackTop--;
     521        storeDouble(FPRInfo::fpRegT0, temporaryAddress(m_tempStackTop - 1));
    468522        return UNUSED;
    469523    }
     
    787841    }
    788842#endif
     843
     844    void callOperation(float JIT_OPERATION (*operation)(float), FPRegisterID src, FPRegisterID dst)
     845    {
     846        setupArguments(src);
     847        appendCallSetResult(operation, dst);
     848    }
    789849
    790850    void callOperation(int32_t JIT_OPERATION (*operation)(int32_t, int32_t), GPRReg src1, GPRReg src2, GPRReg dst)
     
    856916
    857917        end.link(this);
    858         addPtr(TrustedImm32(-WTF::roundUpToMultipleOf(stackAlignmentRegisters(), m_stackHeight) * sizeof(StackSlot)), GPRInfo::callFrameRegister, stackPointerRegister);
     918        addPtr(TrustedImm32(-WTF::roundUpToMultipleOf(stackAlignmentRegisters(), m_stackHeight) * sizeof(StackSlot) - maxFrameExtentForSlowPathCall), GPRInfo::callFrameRegister, stackPointerRegister);
    859919        checkStackPointerAlignment();
    860920
  • trunk/Source/JavaScriptCore/wasm/WASMFunctionParser.cpp

    r189645 r189744  
    751751        case WASMOpExpressionF32::GetGlobal:
    752752            return parseGetGlobalExpressionF32(context);
     753        case WASMOpExpressionF32::Negate:
     754        case WASMOpExpressionF32::Abs:
     755        case WASMOpExpressionF32::Ceil:
     756        case WASMOpExpressionF32::Floor:
     757        case WASMOpExpressionF32::Sqrt:
     758            return parseUnaryExpressionF32(context, op);
     759        case WASMOpExpressionF32::Add:
     760        case WASMOpExpressionF32::Sub:
     761        case WASMOpExpressionF32::Mul:
     762        case WASMOpExpressionF32::Div:
     763            return parseBinaryExpressionF32(context, op);
    753764        case WASMOpExpressionF32::SetLocal:
    754765        case WASMOpExpressionF32::SetGlobal:
     
    764775        case WASMOpExpressionF32::FromU32:
    765776        case WASMOpExpressionF32::FromF64:
    766         case WASMOpExpressionF32::Negate:
    767         case WASMOpExpressionF32::Add:
    768         case WASMOpExpressionF32::Sub:
    769         case WASMOpExpressionF32::Mul:
    770         case WASMOpExpressionF32::Div:
    771         case WASMOpExpressionF32::Abs:
    772         case WASMOpExpressionF32::Ceil:
    773         case WASMOpExpressionF32::Floor:
    774         case WASMOpExpressionF32::Sqrt:
    775777            // FIXME: Implement these instructions.
    776778            FAIL_WITH_MESSAGE("Unsupported instruction.");
     
    838840    FAIL_IF_FALSE(m_module->globalVariableTypes()[globalIndex] == WASMType::F32, "Expected a global variable of type float32.");
    839841    return context.buildGetGlobal(globalIndex, WASMType::F32);
     842}
     843
     844template <class Context>
     845ContextExpression WASMFunctionParser::parseUnaryExpressionF32(Context& context, WASMOpExpressionF32 op)
     846{
     847    ContextExpression expression = parseExpressionF32(context);
     848    PROPAGATE_ERROR();
     849    return context.buildUnaryF32(expression, op);
     850}
     851
     852template <class Context>
     853ContextExpression WASMFunctionParser::parseBinaryExpressionF32(Context& context, WASMOpExpressionF32 op)
     854{
     855    ContextExpression left = parseExpressionF32(context);
     856    PROPAGATE_ERROR();
     857    ContextExpression right = parseExpressionF32(context);
     858    PROPAGATE_ERROR();
     859    return context.buildBinaryF32(left, right, op);
    840860}
    841861
  • trunk/Source/JavaScriptCore/wasm/WASMFunctionParser.h

    r189645 r189744  
    104104    template <class Context> ContextExpression parseGetLocalExpressionF32(Context&);
    105105    template <class Context> ContextExpression parseGetGlobalExpressionF32(Context&);
     106    template <class Context> ContextExpression parseUnaryExpressionF32(Context&, WASMOpExpressionF32);
     107    template <class Context> ContextExpression parseBinaryExpressionF32(Context&, WASMOpExpressionF32);
    106108
    107109    template <class Context> ContextExpression parseExpressionF64(Context&);
  • trunk/Source/JavaScriptCore/wasm/WASMFunctionSyntaxChecker.h

    r189645 r189744  
    107107    }
    108108
     109    int buildUnaryF32(int, WASMOpExpressionF32)
     110    {
     111        return UNUSED;
     112    }
     113
    109114    int buildBinaryI32(int, int, WASMOpExpressionI32)
     115    {
     116        m_tempStackTop--;
     117        return UNUSED;
     118    }
     119
     120    int buildBinaryF32(int, int, WASMOpExpressionF32)
    110121    {
    111122        m_tempStackTop--;
Note: See TracChangeset for help on using the changeset viewer.