Changeset 189582 in webkit


Ignore:
Timestamp:
Sep 10, 2015 12:01:47 PM (9 years ago)
Author:
commit-queue@webkit.org
Message:

Convert arguments to WebAssembly functions to the declared types
https://bugs.webkit.org/show_bug.cgi?id=149033

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

This patch checks the types of arguments to WebAssembly functions and
converts them to the declared types. This is necessary because:

  • For example, if a function expects an argument of type double and we pass 1.0 to it, it will get a JSValue of an integer, not a double.
  • We should follow asm.js's behavior for now, because we want to be able to test WebAssembly apps against asm.js apps. asm.js does type coercion on arguments by using int|0, Math.fround(float), and +double.
  • jit/JITOperations.h:
  • tests/stress/wasm-type-conversion.js: Added.

(shouldBe):
(two.valueOf):

  • tests/stress/wasm/type-conversion.wasm: Added.
  • wasm/WASMFunctionCompiler.h:

(JSC::operationConvertJSValueToInt32):
(JSC::operationConvertJSValueToDouble):
(JSC::WASMFunctionCompiler::startFunction):
(JSC::WASMFunctionCompiler::appendCallSetResult):
(JSC::WASMFunctionCompiler::callOperation):
(JSC::WASMFunctionCompiler::loadValueAndConvertToInt32):
(JSC::WASMFunctionCompiler::loadValueAndConvertToDouble):

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

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r189577 r189582  
     12015-09-10  Sukolsak Sakshuwong  <sukolsak@gmail.com>
     2
     3        Convert arguments to WebAssembly functions to the declared types
     4        https://bugs.webkit.org/show_bug.cgi?id=149033
     5
     6        Reviewed by Geoffrey Garen.
     7
     8        This patch checks the types of arguments to WebAssembly functions and
     9        converts them to the declared types. This is necessary because:
     10        - For example, if a function expects an argument of type double and we
     11          pass 1.0 to it, it will get a JSValue of an integer, not a double.
     12        - We should follow asm.js's behavior for now, because we want to be able
     13          to test WebAssembly apps against asm.js apps. asm.js does type
     14          coercion on arguments by using int|0, Math.fround(float), and +double.
     15
     16        * jit/JITOperations.h:
     17        * tests/stress/wasm-type-conversion.js: Added.
     18        (shouldBe):
     19        (two.valueOf):
     20        * tests/stress/wasm/type-conversion.wasm: Added.
     21        * wasm/WASMFunctionCompiler.h:
     22        (JSC::operationConvertJSValueToInt32):
     23        (JSC::operationConvertJSValueToDouble):
     24        (JSC::WASMFunctionCompiler::startFunction):
     25        (JSC::WASMFunctionCompiler::appendCallSetResult):
     26        (JSC::WASMFunctionCompiler::callOperation):
     27        (JSC::WASMFunctionCompiler::loadValueAndConvertToInt32):
     28        (JSC::WASMFunctionCompiler::loadValueAndConvertToDouble):
     29
    1302015-09-10  Yusuke Suzuki  <utatane.tea@gmail.com>
    231
  • trunk/Source/JavaScriptCore/jit/JITOperations.h

    r189504 r189582  
    174174typedef int32_t JIT_OPERATION (*Z_JITOperation_EGC)(ExecState*, JSGlobalObject*, JSCell*);
    175175typedef int32_t JIT_OPERATION (*Z_JITOperation_ESJss)(ExecState*, size_t, JSString*);
     176typedef int32_t JIT_OPERATION (*Z_JITOperation_EJ)(ExecState*, EncodedJSValue);
    176177typedef int32_t JIT_OPERATION (*Z_JITOperation_EJZ)(ExecState*, EncodedJSValue, int32_t);
    177178typedef int32_t JIT_OPERATION (*Z_JITOperation_EJZZ)(ExecState*, EncodedJSValue, int32_t, int32_t);
  • trunk/Source/JavaScriptCore/wasm/WASMFunctionCompiler.h

    r189563 r189582  
    3939namespace JSC {
    4040
     41static int32_t JIT_OPERATION operationConvertJSValueToInt32(ExecState* exec, EncodedJSValue value)
     42{
     43    return JSValue::decode(value).toInt32(exec);
     44}
     45
     46static double JIT_OPERATION operationConvertJSValueToDouble(ExecState* exec, EncodedJSValue value)
     47{
     48    return JSValue::decode(value).toNumber(exec);
     49}
     50
    4151#if !CPU(X86) && !CPU(X86_64)
    4252static int32_t JIT_OPERATION operationDiv(int32_t left, int32_t right)
     
    99109            switch (arguments[i]) {
    100110            case WASMType::I32:
    101                 load32(address, GPRInfo::regT0);
     111#if USE(JSVALUE64)
     112                loadValueAndConvertToInt32(address, GPRInfo::regT0);
     113#else
     114                loadValueAndConvertToInt32(address, GPRInfo::regT0, GPRInfo::regT1);
     115#endif
    102116                store32(GPRInfo::regT0, localAddress(localIndex++));
    103117                break;
    104118            case WASMType::F32:
    105                 load64(address, GPRInfo::regT0);
    106                 unboxDoubleWithoutAssertions(GPRInfo::regT0, FPRInfo::fpRegT0);
    107                 convertDoubleToFloat(FPRInfo::fpRegT0, FPRInfo::fpRegT0);
    108                 storeDouble(FPRInfo::fpRegT0, localAddress(localIndex++));
    109                 break;
    110119            case WASMType::F64:
    111                 load64(address, GPRInfo::regT0);
    112                 unboxDoubleWithoutAssertions(GPRInfo::regT0, FPRInfo::fpRegT0);
     120#if USE(JSVALUE64)
     121                loadValueAndConvertToDouble(address, FPRInfo::fpRegT0, GPRInfo::regT0, GPRInfo::regT1);
     122#else
     123                loadValueAndConvertToDouble(address, FPRInfo::fpRegT0, GPRInfo::regT0, GPRInfo::regT1, GPRInfo::regT2, FPRInfo::fpRegT1);
     124#endif
     125                if (arguments[i] == WASMType::F32)
     126                    convertDoubleToFloat(FPRInfo::fpRegT0, FPRInfo::fpRegT0);
    113127                storeDouble(FPRInfo::fpRegT0, localAddress(localIndex++));
    114128                break;
     
    620634    }
    621635
     636    void appendCallSetResult(const FunctionPtr& function, GPRReg result)
     637    {
     638        appendCall(function);
     639        move(GPRInfo::returnValueGPR, result);
     640    }
     641
     642#if CPU(X86)
     643    void appendCallSetResult(const FunctionPtr& function, FPRReg result)
     644    {
     645        appendCall(function);
     646        m_assembler.fstpl(0, stackPointerRegister);
     647        loadDouble(stackPointerRegister, result);
     648    }
     649#elif CPU(ARM) && !CPU(ARM_HARDFP)
     650    void appendCallSetResult(const FunctionPtr& function, FPRReg result)
     651    {
     652        appendCall(function);
     653        m_assembler.vmov(result, GPRInfo::returnValueGPR, GPRInfo::returnValueGPR2);
     654    }
     655#else // CPU(X86_64) || (CPU(ARM) && CPU(ARM_HARDFP)) || CPU(ARM64) || CPU(MIPS) || CPU(SH4)
     656    void appendCallSetResult(const FunctionPtr& function, FPRReg result)
     657    {
     658        appendCall(function);
     659        moveDouble(FPRInfo::returnValueFPR, result);
     660    }
     661#endif
     662
     663#if USE(JSVALUE64)
     664    void callOperation(Z_JITOperation_EJ operation, GPRReg src, GPRReg dst)
     665    {
     666        setupArgumentsWithExecState(src);
     667        appendCallSetResult(operation, dst);
     668    }
     669
     670    void callOperation(D_JITOperation_EJ operation, GPRReg src, FPRReg dst)
     671    {
     672        setupArgumentsWithExecState(src);
     673        appendCallSetResult(operation, dst);
     674    }
     675#else
     676    void callOperation(Z_JITOperation_EJ operation, GPRReg srcTag, GPRReg srcPayload, GPRReg dst)
     677    {
     678        setupArgumentsWithExecState(EABI_32BIT_DUMMY_ARG srcPayload, srcTag);
     679        appendCallSetResult(operation, dst);
     680    }
     681
     682    void callOperation(D_JITOperation_EJ operation, GPRReg srcTag, GPRReg srcPayload, FPRReg dst)
     683    {
     684        setupArgumentsWithExecState(EABI_32BIT_DUMMY_ARG srcPayload, srcTag);
     685        appendCallSetResult(operation, dst);
     686    }
     687#endif
     688
    622689    void callOperation(int32_t JIT_OPERATION (*operation)(int32_t, int32_t), GPRReg src1, GPRReg src2, GPRReg dst)
    623690    {
    624691        setupArguments(src1, src2);
    625         appendCall(operation);
    626         move(GPRInfo::returnValueGPR, dst);
     692        appendCallSetResult(operation, dst);
    627693    }
    628694
     
    630696    {
    631697        setupArguments(src1, src2);
    632         appendCall(operation);
    633         move(GPRInfo::returnValueGPR, dst);
     698        appendCallSetResult(operation, dst);
    634699    }
    635700
     
    704769    }
    705770
     771#if USE(JSVALUE64)
     772    void loadValueAndConvertToInt32(Address address, GPRReg dst)
     773    {
     774        JSValueRegs tempRegs(dst);
     775        loadValue(address, tempRegs);
     776        Jump checkJSInt32 = branchIfInt32(tempRegs);
     777
     778        callOperation(operationConvertJSValueToInt32, dst, dst);
     779
     780        checkJSInt32.link(this);
     781    }
     782
     783    void loadValueAndConvertToDouble(Address address, FPRReg dst, GPRReg scratch1, GPRReg scratch2)
     784    {
     785        JSValueRegs tempRegs(scratch1);
     786        loadValue(address, tempRegs);
     787        Jump checkJSInt32 = branchIfInt32(tempRegs);
     788        Jump checkJSNumber = branchIfNumber(tempRegs, scratch2);
     789        JumpList end;
     790
     791        callOperation(operationConvertJSValueToDouble, tempRegs.gpr(), dst);
     792        end.append(jump());
     793
     794        checkJSInt32.link(this);
     795        convertInt32ToDouble(tempRegs.gpr(), dst);
     796        end.append(jump());
     797
     798        checkJSNumber.link(this);
     799        unboxDoubleWithoutAssertions(tempRegs.gpr(), dst);
     800        end.link(this);
     801    }
     802#else
     803    void loadValueAndConvertToInt32(Address address, GPRReg dst, GPRReg scratch)
     804    {
     805        JSValueRegs tempRegs(scratch, dst);
     806        loadValue(address, tempRegs);
     807        Jump checkJSInt32 = branchIfInt32(tempRegs);
     808
     809        callOperation(operationConvertJSValueToInt32, tempRegs.tagGPR(), tempRegs.payloadGPR(), dst);
     810
     811        checkJSInt32.link(this);
     812    }
     813
     814    void loadValueAndConvertToDouble(Address address, FPRReg dst, GPRReg scratch1, GPRReg scratch2, GPRReg scratch3, FPRReg fpScratch)
     815    {
     816        JSValueRegs tempRegs(scratch2, scratch1);
     817        loadValue(address, tempRegs);
     818        Jump checkJSInt32 = branchIfInt32(tempRegs);
     819        Jump checkJSNumber = branchIfNumber(tempRegs, scratch3);
     820        JumpList end;
     821
     822        callOperation(operationConvertJSValueToDouble, tempRegs.tagGPR(), tempRegs.payloadGPR(), dst);
     823        end.append(jump());
     824
     825        checkJSInt32.link(this);
     826        convertInt32ToDouble(tempRegs.payloadGPR(), dst);
     827        end.append(jump());
     828
     829        checkJSNumber.link(this);
     830        unboxDouble(tempRegs.tagGPR(), tempRegs.payloadGPR(), dst, fpScratch)
     831        end.link(this);
     832    }
     833#endif
     834
    706835    JSWASMModule* m_module;
    707836    unsigned m_stackHeight;
Note: See TracChangeset for help on using the changeset viewer.