Changeset 272341 in webkit


Ignore:
Timestamp:
Feb 3, 2021 3:07:41 PM (18 months ago)
Author:
ysuzuki@apple.com
Message:

[JSC] Atomics should support BigInt64Array / BigUint64Array
https://bugs.webkit.org/show_bug.cgi?id=221245

Reviewed by Keith Miller.

JSTests:

  • stress/atomic-increment-bigint64.js: Added.

(shouldBe):
(i.agent.start.262.agent.receiveBroadcast):

  • stress/bigint-atomics-fail.js: Added.

(shouldThrow):

  • stress/bigint64-atomics.js: Added.

(shouldBe):
(test):

  • stress/biguint64-atomics.js: Added.

(shouldBe):
(test):

  • stress/isLockFree.js:

(foo6):
(foo7):
(foo8):
(foo9):

  • stress/shared-array-buffer-bigint.js: Added.

(shouldFail):
(shouldSucceed):
(runAtomic):

  • test262/config.yaml:

Source/JavaScriptCore:

This patch adds BigInt64Array / BigUint64Array support for Atomics.

  1. Atomics.store should be rewritten since it returns non-type-coerced result, so we cannot use atomicReadModifyWrite. The spec also describes Atomics.store without using AtomicReadModifyWrite[1].
  2. Extend Atomics.isLockFree to also accept a size of 8.
  3. Currently, DFG / FTL handle Atomics + BigInt64Array/BigUint64Array as Array::Generic.

[1]: https://tc39.es/ecma262/#sec-atomics.store

  • dfg/DFGSpeculativeJIT64.cpp:

(JSC::DFG::SpeculativeJIT::compile):

  • ftl/FTLLowerDFGToB3.cpp:

(JSC::FTL::DFG::LowerDFGToB3::compileAtomicsIsLockFree):

  • runtime/AtomicsObject.cpp:

(JSC::JSC_DEFINE_HOST_FUNCTION):
(JSC::atomicsWaitImpl):
(JSC::JSC_DEFINE_JIT_OPERATION):

  • runtime/ToNativeFromValue.h:

(JSC::toNativeFromValue):

Location:
trunk
Files:
5 added
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/JSTests/ChangeLog

    r272243 r272341  
     12021-02-01  Yusuke Suzuki  <ysuzuki@apple.com>
     2
     3        [JSC] Atomics should support BigInt64Array / BigUint64Array
     4        https://bugs.webkit.org/show_bug.cgi?id=221245
     5
     6        Reviewed by Keith Miller.
     7
     8        * stress/atomic-increment-bigint64.js: Added.
     9        (shouldBe):
     10        (i.agent.start.262.agent.receiveBroadcast):
     11        * stress/bigint-atomics-fail.js: Added.
     12        (shouldThrow):
     13        * stress/bigint64-atomics.js: Added.
     14        (shouldBe):
     15        (test):
     16        * stress/biguint64-atomics.js: Added.
     17        (shouldBe):
     18        (test):
     19        * stress/isLockFree.js:
     20        (foo6):
     21        (foo7):
     22        (foo8):
     23        (foo9):
     24        * stress/shared-array-buffer-bigint.js: Added.
     25        (shouldFail):
     26        (shouldSucceed):
     27        (runAtomic):
     28        * test262/config.yaml:
     29
    1302021-02-02  Ross Kirsling  <ross.kirsling@sony.com>
    231
  • trunk/JSTests/stress/isLockFree.js

    r227104 r272341  
    3636noInline(foo5);
    3737
     38function foo6(bytes) {
     39    return Atomics.isLockFree(6);
     40}
     41noInline(foo6);
     42
     43function foo7(bytes) {
     44    return Atomics.isLockFree(7);
     45}
     46noInline(foo7);
     47
     48function foo8(bytes) {
     49    return Atomics.isLockFree(8);
     50}
     51noInline(foo8);
     52
     53function foo9(bytes) {
     54    return Atomics.isLockFree(9);
     55}
     56noInline(foo9);
     57
    3858for (var i = 0; i < 10000; ++i) {
    3959    var result = foo(0);
     
    5373        throw new Error("Bad result: " + result);
    5474    var result = foo(5);
     75    if (result !== false)
     76        throw new Error("Bad result: " + result);
     77    var result = foo(6);
     78    if (result !== false)
     79        throw new Error("Bad result: " + result);
     80    var result = foo(7);
     81    if (result !== false)
     82        throw new Error("Bad result: " + result);
     83    var result = foo(8);
     84    if (result !== true)
     85        throw new Error("Bad result: " + result);
     86    var result = foo(9);
    5587    if (result !== false)
    5688        throw new Error("Bad result: " + result);
     
    73105    if (result !== false)
    74106        throw new Error("Bad result: " + result);
     107    var result = foo6();
     108    if (result !== false)
     109        throw new Error("Bad result: " + result);
     110    var result = foo7();
     111    if (result !== false)
     112        throw new Error("Bad result: " + result);
     113    var result = foo8();
     114    if (result !== true)
     115        throw new Error("Bad result: " + result);
     116    var result = foo9();
     117    if (result !== false)
     118        throw new Error("Bad result: " + result);
    75119}
  • trunk/JSTests/test262/config.yaml

    r272170 r272341  
    2929    - Intl.ListFormat
    3030  paths:
    31     - test/built-ins/Atomics/add/bigint
    32     - test/built-ins/Atomics/and/bigint
    33     - test/built-ins/Atomics/compareExchange/bigint
    34     - test/built-ins/Atomics/exchange/bigint
    35     - test/built-ins/Atomics/isLockFree/bigint
    36     - test/built-ins/Atomics/load/bigint
    37     - test/built-ins/Atomics/notify/bigint
    38     - test/built-ins/Atomics/or/bigint
    39     - test/built-ins/Atomics/store/bigint
    40     - test/built-ins/Atomics/sub/bigint
    41     - test/built-ins/Atomics/wait/bigint
    42     - test/built-ins/Atomics/xor/bigint
    43 
    4431    # test262 bot is using Catalina's ICU 64, upgrading to Big Sur is required
    4532    # https://bugs.webkit.org/show_bug.cgi?id=218844
  • trunk/Source/JavaScriptCore/ChangeLog

    r272330 r272341  
     12021-02-01  Yusuke Suzuki  <ysuzuki@apple.com>
     2
     3        [JSC] Atomics should support BigInt64Array / BigUint64Array
     4        https://bugs.webkit.org/show_bug.cgi?id=221245
     5
     6        Reviewed by Keith Miller.
     7
     8        This patch adds BigInt64Array / BigUint64Array support for Atomics.
     9
     10        1. Atomics.store should be rewritten since it returns non-type-coerced result, so we cannot use atomicReadModifyWrite.
     11           The spec also describes Atomics.store without using AtomicReadModifyWrite[1].
     12        2. Extend Atomics.isLockFree to also accept a size of 8.
     13        3. Currently, DFG / FTL handle Atomics + BigInt64Array/BigUint64Array as Array::Generic.
     14
     15        [1]: https://tc39.es/ecma262/#sec-atomics.store
     16
     17        * dfg/DFGSpeculativeJIT64.cpp:
     18        (JSC::DFG::SpeculativeJIT::compile):
     19        * ftl/FTLLowerDFGToB3.cpp:
     20        (JSC::FTL::DFG::LowerDFGToB3::compileAtomicsIsLockFree):
     21        * runtime/AtomicsObject.cpp:
     22        (JSC::JSC_DEFINE_HOST_FUNCTION):
     23        (JSC::atomicsWaitImpl):
     24        (JSC::JSC_DEFINE_JIT_OPERATION):
     25        * runtime/ToNativeFromValue.h:
     26        (JSC::toNativeFromValue):
     27
    1282021-02-03  Yusuke Suzuki  <ysuzuki@apple.com>
    229
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp

    r272170 r272341  
    34563456        m_jit.move(TrustedImm32(JSValue::ValueTrue), resultGPR);
    34573457        JITCompiler::JumpList done;
     3458        done.append(m_jit.branch32(JITCompiler::Equal, operandGPR, TrustedImm32(8)));
    34583459        done.append(m_jit.branch32(JITCompiler::Equal, operandGPR, TrustedImm32(4)));
    34593460        done.append(m_jit.branch32(JITCompiler::Equal, operandGPR, TrustedImm32(1)));
  • trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp

    r272170 r272341  
    42964296        LBasicBlock lastNext = m_out.insertNewBlocksBefore(trueCase);
    42974297       
    4298         Vector<SwitchCase> cases;
     4298        Vector<SwitchCase, 4> cases;
    42994299        cases.append(SwitchCase(m_out.constInt32(1), trueCase, Weight()));
    43004300        cases.append(SwitchCase(m_out.constInt32(2), trueCase, Weight()));
    43014301        cases.append(SwitchCase(m_out.constInt32(4), trueCase, Weight()));
     4302        cases.append(SwitchCase(m_out.constInt32(8), trueCase, Weight()));
    43024303        m_out.switchInstruction(bytes, cases, falseCase, Weight());
    43034304       
  • trunk/Source/JavaScriptCore/runtime/AtomicsObject.cpp

    r272170 r272341  
    9191
    9292template<typename Adaptor, typename Func>
    93 EncodedJSValue atomicReadModifyWriteCase(JSGlobalObject* globalObject, const JSValue* args, ThrowScope& scope, JSArrayBufferView* typedArrayView, unsigned accessIndex, const Func& func)
    94 {
     93EncodedJSValue atomicReadModifyWriteCase(JSGlobalObject* globalObject, VM& vm, const JSValue* args, JSArrayBufferView* typedArrayView, unsigned accessIndex, const Func& func)
     94{
     95    auto scope = DECLARE_THROW_SCOPE(vm);
     96
    9597    JSGenericTypedArrayView<Adaptor>* typedArray = jsCast<JSGenericTypedArrayView<Adaptor>*>(typedArrayView);
    9698   
    97     double extraArgs[Func::numExtraArgs + 1]; // Add 1 to avoid 0 size array error in VS.
     99    typename Adaptor::Type extraArgs[Func::numExtraArgs + 1]; // Add 1 to avoid 0 size array error in VS.
    98100    for (unsigned i = 0; i < Func::numExtraArgs; ++i) {
    99         double value = args[2 + i].toIntegerOrInfinity(globalObject);
    100         RETURN_IF_EXCEPTION(scope, JSValue::encode(jsUndefined()));
     101        auto value = toNativeFromValue<Adaptor>(globalObject, args[2 + i]);
     102        RETURN_IF_EXCEPTION(scope, { });
    101103        extraArgs[i] = value;
    102104    }
     
    105107        return throwVMTypeError(globalObject, scope, typedArrayBufferHasBeenDetachedErrorMessage);
    106108
    107     return JSValue::encode(func(typedArray->typedVector() + accessIndex, extraArgs));
    108 }
    109 
    110 static unsigned validateAtomicAccess(VM& vm, JSGlobalObject* globalObject, JSArrayBufferView* typedArrayView, JSValue accessIndexValue)
     109    auto result = func(typedArray->typedVector() + accessIndex, extraArgs);
     110    RELEASE_AND_RETURN(scope, JSValue::encode(Adaptor::toJSValue(globalObject, result)));
     111}
     112
     113static unsigned validateAtomicAccess(JSGlobalObject* globalObject, VM& vm, JSArrayBufferView* typedArrayView, JSValue accessIndexValue)
    111114{
    112115    auto scope = DECLARE_THROW_SCOPE(vm);
     
    128131}
    129132
    130 enum class TypedArrayOperationMode { Read, Write };
     133enum class TypedArrayOperationMode { ReadWrite, Wait };
    131134template<TypedArrayOperationMode mode>
    132135inline JSArrayBufferView* validateIntegerTypedArray(JSGlobalObject* globalObject, JSValue typedArrayValue)
     
    138141    RETURN_IF_EXCEPTION(scope, { });
    139142
    140     if constexpr (mode == TypedArrayOperationMode::Write) {
     143    if constexpr (mode == TypedArrayOperationMode::Wait) {
    141144        switch (typedArray->type()) {
    142145        case Int32ArrayType:
     146        case BigInt64ArrayType:
    143147            break;
    144148        default:
    145             throwTypeError(globalObject, scope, "Typed array argument must be an Int32Array."_s);
     149            throwTypeError(globalObject, scope, "Typed array argument must be an Int32Array or BigInt64Array."_s);
    146150            return { };
    147151        }
     
    154158        case Uint16ArrayType:
    155159        case Uint32ArrayType:
     160        case BigInt64ArrayType:
     161        case BigUint64ArrayType:
    156162            break;
    157163        default:
    158             throwTypeError(globalObject, scope, "Typed array argument must be an Int8Array, Int16Array, Int32Array, Uint8Array, Uint16Array, or Uint32Array."_s);
     164            throwTypeError(globalObject, scope, "Typed array argument must be an Int8Array, Int16Array, Int32Array, Uint8Array, Uint16Array, Uint32Array, BigInt64Array, or BigUint64Array."_s);
    159165            return { };
    160166        }
     
    164170
    165171template<typename Func>
    166 EncodedJSValue atomicReadModifyWrite(VM& vm, JSGlobalObject* globalObject, const JSValue* args, const Func& func)
    167 {
    168     auto scope = DECLARE_THROW_SCOPE(vm);
    169 
    170     JSArrayBufferView* typedArrayView = validateIntegerTypedArray<TypedArrayOperationMode::Read>(globalObject, args[0]);
    171     RETURN_IF_EXCEPTION(scope, { });
    172 
    173     unsigned accessIndex = validateAtomicAccess(vm, globalObject, typedArrayView, args[1]);
    174     RETURN_IF_EXCEPTION(scope, { });
    175 
     172EncodedJSValue atomicReadModifyWrite(JSGlobalObject* globalObject, VM& vm, const JSValue* args, const Func& func)
     173{
     174    auto scope = DECLARE_THROW_SCOPE(vm);
     175
     176    JSArrayBufferView* typedArrayView = validateIntegerTypedArray<TypedArrayOperationMode::ReadWrite>(globalObject, args[0]);
     177    RETURN_IF_EXCEPTION(scope, { });
     178
     179    unsigned accessIndex = validateAtomicAccess(globalObject, vm, typedArrayView, args[1]);
     180    RETURN_IF_EXCEPTION(scope, { });
     181
     182    scope.release();
    176183    switch (typedArrayView->type()) {
    177184    case Int8ArrayType:
    178         return atomicReadModifyWriteCase<Int8Adaptor>(globalObject, args, scope, typedArrayView, accessIndex, func);
     185        return atomicReadModifyWriteCase<Int8Adaptor>(globalObject, vm, args, typedArrayView, accessIndex, func);
    179186    case Int16ArrayType:
    180         return atomicReadModifyWriteCase<Int16Adaptor>(globalObject, args, scope, typedArrayView, accessIndex, func);
     187        return atomicReadModifyWriteCase<Int16Adaptor>(globalObject, vm, args, typedArrayView, accessIndex, func);
    181188    case Int32ArrayType:
    182         return atomicReadModifyWriteCase<Int32Adaptor>(globalObject, args, scope, typedArrayView, accessIndex, func);
     189        return atomicReadModifyWriteCase<Int32Adaptor>(globalObject, vm, args, typedArrayView, accessIndex, func);
    183190    case Uint8ArrayType:
    184         return atomicReadModifyWriteCase<Uint8Adaptor>(globalObject, args, scope, typedArrayView, accessIndex, func);
     191        return atomicReadModifyWriteCase<Uint8Adaptor>(globalObject, vm, args, typedArrayView, accessIndex, func);
    185192    case Uint16ArrayType:
    186         return atomicReadModifyWriteCase<Uint16Adaptor>(globalObject, args, scope, typedArrayView, accessIndex, func);
     193        return atomicReadModifyWriteCase<Uint16Adaptor>(globalObject, vm, args, typedArrayView, accessIndex, func);
    187194    case Uint32ArrayType:
    188         return atomicReadModifyWriteCase<Uint32Adaptor>(globalObject, args, scope, typedArrayView, accessIndex, func);
     195        return atomicReadModifyWriteCase<Uint32Adaptor>(globalObject, vm, args, typedArrayView, accessIndex, func);
     196    case BigInt64ArrayType:
     197        return atomicReadModifyWriteCase<BigInt64Adaptor>(globalObject, vm, args, typedArrayView, accessIndex, func);
     198    case BigUint64ArrayType:
     199        return atomicReadModifyWriteCase<BigUint64Adaptor>(globalObject, vm, args, typedArrayView, accessIndex, func);
    189200    default:
    190201        RELEASE_ASSERT_NOT_REACHED();
     
    199210    for (unsigned i = 2 + Func::numExtraArgs; i--;)
    200211        args[i] = callFrame->argument(i);
    201     return atomicReadModifyWrite(globalObject->vm(), globalObject, args, func);
     212    return atomicReadModifyWrite(globalObject, globalObject->vm(), args, func);
    202213}
    203214
     
    206217   
    207218    template<typename T>
    208     JSValue operator()(T* ptr, const double* args) const
    209     {
    210         return jsNumber(WTF::atomicExchangeAdd(ptr, toInt32(args[0])));
     219    T operator()(T* ptr, const T* args) const
     220    {
     221        return WTF::atomicExchangeAdd(ptr, args[0]);
    211222    }
    212223};
     
    216227   
    217228    template<typename T>
    218     JSValue operator()(T* ptr, const double* args) const
    219     {
    220         return jsNumber(WTF::atomicExchangeAnd(ptr, toInt32(args[0])));
     229    T operator()(T* ptr, const T* args) const
     230    {
     231        return WTF::atomicExchangeAnd(ptr, args[0]);
    221232    }
    222233};
     
    226237   
    227238    template<typename T>
    228     JSValue operator()(T* ptr, const double* args) const
    229     {
    230         T expected = static_cast<T>(toInt32(args[0]));
    231         T newValue = static_cast<T>(toInt32(args[1]));
    232         return jsNumber(WTF::atomicCompareExchangeStrong(ptr, expected, newValue));
     239    T operator()(T* ptr, const T* args) const
     240    {
     241        T expected = args[0];
     242        T newValue = args[1];
     243        return WTF::atomicCompareExchangeStrong(ptr, expected, newValue);
    233244    }
    234245};
     
    238249   
    239250    template<typename T>
    240     JSValue operator()(T* ptr, const double* args) const
    241     {
    242         return jsNumber(WTF::atomicExchange(ptr, static_cast<T>(toInt32(args[0]))));
     251    T operator()(T* ptr, const T* args) const
     252    {
     253        return WTF::atomicExchange(ptr, args[0]);
    243254    }
    244255};
     
    248259   
    249260    template<typename T>
    250     JSValue operator()(T* ptr, const double*) const
    251     {
    252         return jsNumber(WTF::atomicLoadFullyFenced(ptr));
     261    T operator()(T* ptr, const T*) const
     262    {
     263        return WTF::atomicLoadFullyFenced(ptr);
    253264    }
    254265};
     
    258269   
    259270    template<typename T>
    260     JSValue operator()(T* ptr, const double* args) const
    261     {
    262         return jsNumber(WTF::atomicExchangeOr(ptr, toInt32(args[0])));
    263     }
    264 };
    265 
    266 struct StoreFunc {
    267     static constexpr unsigned numExtraArgs = 1;
    268    
    269     template<typename T>
    270     JSValue operator()(T* ptr, const double* args) const
    271     {
    272         double valueAsInt = args[0];
    273         T valueAsT = static_cast<T>(toInt32(valueAsInt));
    274         WTF::atomicStoreFullyFenced(ptr, valueAsT);
    275         return jsNumber(valueAsInt);
     271    T operator()(T* ptr, const T* args) const
     272    {
     273        return WTF::atomicExchangeOr(ptr, args[0]);
    276274    }
    277275};
     
    281279   
    282280    template<typename T>
    283     JSValue operator()(T* ptr, const double* args) const
    284     {
    285         return jsNumber(WTF::atomicExchangeSub(ptr, toInt32(args[0])));
     281    T operator()(T* ptr, const T* args) const
     282    {
     283        return WTF::atomicExchangeSub(ptr, args[0]);
    286284    }
    287285};
     
    291289   
    292290    template<typename T>
    293     JSValue operator()(T* ptr, const double* args) const
    294     {
    295         return jsNumber(WTF::atomicExchangeXor(ptr, toInt32(args[0])));
     291    T operator()(T* ptr, const T* args) const
     292    {
     293        return WTF::atomicExchangeXor(ptr, args[0]);
    296294    }
    297295};
     
    310308    case 2:
    311309    case 4:
     310    case 8:
    312311        result = true;
    313312        break;
     
    319318}
    320319
     320template<typename Adaptor>
     321EncodedJSValue atomicStoreCase(JSGlobalObject* globalObject, VM& vm, JSValue operand, JSArrayBufferView* typedArrayView, unsigned accessIndex)
     322{
     323    auto scope = DECLARE_THROW_SCOPE(vm);
     324
     325    JSGenericTypedArrayView<Adaptor>* typedArray = jsCast<JSGenericTypedArrayView<Adaptor>*>(typedArrayView);
     326
     327    typename Adaptor::Type extraArg;
     328    JSValue value;
     329    if constexpr (std::is_same_v<Adaptor, BigInt64Adaptor> || std::is_same_v<Adaptor, BigUint64Adaptor>) {
     330        value = operand.toBigInt(globalObject);
     331        RETURN_IF_EXCEPTION(scope, { });
     332        extraArg = toNativeFromValue<Adaptor>(globalObject, value);
     333        RETURN_IF_EXCEPTION(scope, { });
     334    } else {
     335        value = jsNumber(operand.toIntegerOrInfinity(globalObject));
     336        RETURN_IF_EXCEPTION(scope, { });
     337        extraArg = toNativeFromValue<Adaptor>(globalObject, value);
     338        RETURN_IF_EXCEPTION(scope, { });
     339    }
     340
     341    if (typedArray->isDetached())
     342        return throwVMTypeError(globalObject, scope, typedArrayBufferHasBeenDetachedErrorMessage);
     343
     344    WTF::atomicStoreFullyFenced(typedArray->typedVector() + accessIndex, extraArg);
     345    RELEASE_AND_RETURN(scope, JSValue::encode(value));
     346}
     347
     348EncodedJSValue atomicStore(JSGlobalObject* globalObject, VM& vm, JSValue base, JSValue index, JSValue operand)
     349{
     350    // https://tc39.es/ecma262/#sec-atomics.store
     351
     352    auto scope = DECLARE_THROW_SCOPE(vm);
     353
     354    JSArrayBufferView* typedArrayView = validateIntegerTypedArray<TypedArrayOperationMode::ReadWrite>(globalObject, base);
     355    RETURN_IF_EXCEPTION(scope, { });
     356
     357    unsigned accessIndex = validateAtomicAccess(globalObject, vm, typedArrayView, index);
     358    RETURN_IF_EXCEPTION(scope, { });
     359
     360    scope.release();
     361    switch (typedArrayView->type()) {
     362    case Int8ArrayType:
     363        return atomicStoreCase<Int8Adaptor>(globalObject, vm, operand, typedArrayView, accessIndex);
     364    case Int16ArrayType:
     365        return atomicStoreCase<Int16Adaptor>(globalObject, vm, operand, typedArrayView, accessIndex);
     366    case Int32ArrayType:
     367        return atomicStoreCase<Int32Adaptor>(globalObject, vm, operand, typedArrayView, accessIndex);
     368    case Uint8ArrayType:
     369        return atomicStoreCase<Uint8Adaptor>(globalObject, vm, operand, typedArrayView, accessIndex);
     370    case Uint16ArrayType:
     371        return atomicStoreCase<Uint16Adaptor>(globalObject, vm, operand, typedArrayView, accessIndex);
     372    case Uint32ArrayType:
     373        return atomicStoreCase<Uint32Adaptor>(globalObject, vm, operand, typedArrayView, accessIndex);
     374    case BigInt64ArrayType:
     375        return atomicStoreCase<BigInt64Adaptor>(globalObject, vm, operand, typedArrayView, accessIndex);
     376    case BigUint64ArrayType:
     377        return atomicStoreCase<BigUint64Adaptor>(globalObject, vm, operand, typedArrayView, accessIndex);
     378    default:
     379        RELEASE_ASSERT_NOT_REACHED();
     380        return { };
     381    }
     382}
     383
    321384} // anonymous namespace
    322385
     
    358421JSC_DEFINE_HOST_FUNCTION(atomicsFuncStore, (JSGlobalObject* globalObject, CallFrame* callFrame))
    359422{
    360     return atomicReadModifyWrite(globalObject, callFrame, StoreFunc());
     423    return atomicStore(globalObject, globalObject->vm(), callFrame->argument(0), callFrame->argument(1), callFrame->argument(2));
    361424}
    362425
     
    366429}
    367430
    368 JSC_DEFINE_HOST_FUNCTION(atomicsFuncWait, (JSGlobalObject* globalObject, CallFrame* callFrame))
    369 {
    370     VM& vm = globalObject->vm();
    371     auto scope = DECLARE_THROW_SCOPE(vm);
    372 
    373     auto* typedArrayBuffer = validateIntegerTypedArray<TypedArrayOperationMode::Write>(globalObject, callFrame->argument(0));
    374     RETURN_IF_EXCEPTION(scope, { });
    375     auto* typedArray = jsCast<JSInt32Array*>(typedArrayBuffer);
    376 
    377     if (!typedArray->isShared()) {
    378         throwTypeError(globalObject, scope, "Typed array for wait/notify must wrap a SharedArrayBuffer."_s);
    379         return JSValue::encode(jsUndefined());
    380     }
    381 
    382     unsigned accessIndex = validateAtomicAccess(vm, globalObject, typedArray, callFrame->argument(1));
    383     RETURN_IF_EXCEPTION(scope, { });
    384 
    385     int32_t* ptr = typedArray->typedVector() + accessIndex;
    386 
    387     int32_t expectedValue = callFrame->argument(2).toInt32(globalObject);
    388     RETURN_IF_EXCEPTION(scope, JSValue::encode(jsUndefined()));
    389 
    390     double timeoutInMilliseconds = callFrame->argument(3).toNumber(globalObject);
    391     RETURN_IF_EXCEPTION(scope, JSValue::encode(jsUndefined()));
     431template<typename ValueType, typename JSArrayType>
     432JSValue atomicsWaitImpl(JSGlobalObject* globalObject, JSArrayType* typedArray, unsigned accessIndex, ValueType expectedValue, JSValue timeoutValue)
     433{
     434    VM& vm = globalObject->vm();
     435    auto scope = DECLARE_THROW_SCOPE(vm);
     436
     437    ValueType* ptr = typedArray->typedVector() + accessIndex;
     438
     439    double timeoutInMilliseconds = timeoutValue.toNumber(globalObject);
     440    RETURN_IF_EXCEPTION(scope, { });
    392441    Seconds timeout = Seconds::infinity();
    393442    if (!std::isnan(timeoutInMilliseconds))
     
    396445    if (!vm.m_typedArrayController->isAtomicsWaitAllowedOnCurrentThread()) {
    397446        throwTypeError(globalObject, scope, "Atomics.wait cannot be called from the current thread."_s);
    398         return JSValue::encode(jsUndefined());
     447        return { };
    399448    }
    400449
     
    413462    }
    414463    if (!didPassValidation)
    415         return JSValue::encode(vm.smallStrings.notEqualString());
     464        return vm.smallStrings.notEqualString();
    416465    if (!result.wasUnparked)
    417         return JSValue::encode(vm.smallStrings.timedOutString());
    418     return JSValue::encode(vm.smallStrings.okString());
     466        return vm.smallStrings.timedOutString();
     467    return vm.smallStrings.okString();
     468}
     469
     470JSC_DEFINE_HOST_FUNCTION(atomicsFuncWait, (JSGlobalObject* globalObject, CallFrame* callFrame))
     471{
     472    VM& vm = globalObject->vm();
     473    auto scope = DECLARE_THROW_SCOPE(vm);
     474
     475    auto* typedArrayView = validateIntegerTypedArray<TypedArrayOperationMode::Wait>(globalObject, callFrame->argument(0));
     476    RETURN_IF_EXCEPTION(scope, { });
     477
     478    if (!typedArrayView->isShared())
     479        return throwVMTypeError(globalObject, scope, "Typed array for wait/notify must wrap a SharedArrayBuffer."_s);
     480
     481    unsigned accessIndex = validateAtomicAccess(globalObject, vm, typedArrayView, callFrame->argument(1));
     482    RETURN_IF_EXCEPTION(scope, { });
     483
     484    switch (typedArrayView->type()) {
     485    case Int32ArrayType: {
     486        int32_t expectedValue = callFrame->argument(2).toInt32(globalObject);
     487        RETURN_IF_EXCEPTION(scope, { });
     488        RELEASE_AND_RETURN(scope, JSValue::encode(atomicsWaitImpl<int32_t>(globalObject, jsCast<JSInt32Array*>(typedArrayView), accessIndex, expectedValue, callFrame->argument(3))));
     489    }
     490    case BigInt64ArrayType: {
     491        int64_t expectedValue = callFrame->argument(2).toBigInt64(globalObject);
     492        RETURN_IF_EXCEPTION(scope, { });
     493        RELEASE_AND_RETURN(scope, JSValue::encode(atomicsWaitImpl<int64_t>(globalObject, jsCast<JSBigInt64Array*>(typedArrayView), accessIndex, expectedValue, callFrame->argument(3))));
     494    }
     495    default:
     496        RELEASE_ASSERT_NOT_REACHED();
     497        break;
     498    }
     499    return { };
    419500}
    420501
     
    424505    auto scope = DECLARE_THROW_SCOPE(vm);
    425506
    426     auto* typedArrayBuffer = validateIntegerTypedArray<TypedArrayOperationMode::Write>(globalObject, callFrame->argument(0));
    427     RETURN_IF_EXCEPTION(scope, { });
    428     auto* typedArray = jsCast<JSInt32Array*>(typedArrayBuffer);
    429 
    430     unsigned accessIndex = validateAtomicAccess(vm, globalObject, typedArray, callFrame->argument(1));
     507    auto* typedArrayView = validateIntegerTypedArray<TypedArrayOperationMode::Wait>(globalObject, callFrame->argument(0));
     508    RETURN_IF_EXCEPTION(scope, { });
     509
     510    unsigned accessIndex = validateAtomicAccess(globalObject, vm, typedArrayView, callFrame->argument(1));
    431511    RETURN_IF_EXCEPTION(scope, { });
    432512
     
    441521    }
    442522
    443     if (!typedArray->isShared())
     523    if (!typedArrayView->isShared())
    444524        return JSValue::encode(jsNumber(0));
    445525
    446     int32_t* ptr = typedArray->typedVector() + accessIndex;
    447     return JSValue::encode(jsNumber(ParkingLot::unparkCount(ptr, count)));
     526    switch (typedArrayView->type()) {
     527    case Int32ArrayType: {
     528        int32_t* ptr = jsCast<JSInt32Array*>(typedArrayView)->typedVector() + accessIndex;
     529        return JSValue::encode(jsNumber(ParkingLot::unparkCount(ptr, count)));
     530    }
     531    case BigInt64ArrayType: {
     532        int64_t* ptr = jsCast<JSBigInt64Array*>(typedArrayView)->typedVector() + accessIndex;
     533        return JSValue::encode(jsNumber(ParkingLot::unparkCount(ptr, count)));
     534    }
     535    default:
     536        RELEASE_ASSERT_NOT_REACHED();
     537        break;
     538    }
     539    return { };
    448540}
    449541
     
    461553    JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
    462554    JSValue args[] = {JSValue::decode(base), JSValue::decode(index), JSValue::decode(operand)};
    463     return atomicReadModifyWrite(vm, globalObject, args, AddFunc());
     555    return atomicReadModifyWrite(globalObject, vm, args, AddFunc());
    464556}
    465557
     
    470562    JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
    471563    JSValue args[] = {JSValue::decode(base), JSValue::decode(index), JSValue::decode(operand)};
    472     return atomicReadModifyWrite(vm, globalObject, args, AndFunc());
     564    return atomicReadModifyWrite(globalObject, vm, args, AndFunc());
    473565}
    474566
     
    479571    JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
    480572    JSValue args[] = {JSValue::decode(base), JSValue::decode(index), JSValue::decode(expected), JSValue::decode(newValue)};
    481     return atomicReadModifyWrite(vm, globalObject, args, CompareExchangeFunc());
     573    return atomicReadModifyWrite(globalObject, vm, args, CompareExchangeFunc());
    482574}
    483575
     
    488580    JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
    489581    JSValue args[] = {JSValue::decode(base), JSValue::decode(index), JSValue::decode(operand)};
    490     return atomicReadModifyWrite(vm, globalObject, args, ExchangeFunc());
     582    return atomicReadModifyWrite(globalObject, vm, args, ExchangeFunc());
    491583}
    492584
     
    505597    JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
    506598    JSValue args[] = {JSValue::decode(base), JSValue::decode(index)};
    507     return atomicReadModifyWrite(vm, globalObject, args, LoadFunc());
     599    return atomicReadModifyWrite(globalObject, vm, args, LoadFunc());
    508600}
    509601
     
    514606    JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
    515607    JSValue args[] = {JSValue::decode(base), JSValue::decode(index), JSValue::decode(operand)};
    516     return atomicReadModifyWrite(vm, globalObject, args, OrFunc());
     608    return atomicReadModifyWrite(globalObject, vm, args, OrFunc());
    517609}
    518610
     
    522614    CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
    523615    JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
     616    return atomicStore(globalObject, vm, JSValue::decode(base), JSValue::decode(index), JSValue::decode(operand));
     617}
     618
     619JSC_DEFINE_JIT_OPERATION(operationAtomicsSub, EncodedJSValue, (JSGlobalObject* globalObject, EncodedJSValue base, EncodedJSValue index, EncodedJSValue operand))
     620{
     621    VM& vm = globalObject->vm();
     622    CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
     623    JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
    524624    JSValue args[] = {JSValue::decode(base), JSValue::decode(index), JSValue::decode(operand)};
    525     return atomicReadModifyWrite(vm, globalObject, args, StoreFunc());
    526 }
    527 
    528 JSC_DEFINE_JIT_OPERATION(operationAtomicsSub, EncodedJSValue, (JSGlobalObject* globalObject, EncodedJSValue base, EncodedJSValue index, EncodedJSValue operand))
     625    return atomicReadModifyWrite(globalObject, vm, args, SubFunc());
     626}
     627
     628JSC_DEFINE_JIT_OPERATION(operationAtomicsXor, EncodedJSValue, (JSGlobalObject* globalObject, EncodedJSValue base, EncodedJSValue index, EncodedJSValue operand))
    529629{
    530630    VM& vm = globalObject->vm();
     
    532632    JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
    533633    JSValue args[] = {JSValue::decode(base), JSValue::decode(index), JSValue::decode(operand)};
    534     return atomicReadModifyWrite(vm, globalObject, args, SubFunc());
    535 }
    536 
    537 JSC_DEFINE_JIT_OPERATION(operationAtomicsXor, EncodedJSValue, (JSGlobalObject* globalObject, EncodedJSValue base, EncodedJSValue index, EncodedJSValue operand))
    538 {
    539     VM& vm = globalObject->vm();
    540     CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
    541     JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
    542     JSValue args[] = {JSValue::decode(base), JSValue::decode(index), JSValue::decode(operand)};
    543     return atomicReadModifyWrite(vm, globalObject, args, XorFunc());
     634    return atomicReadModifyWrite(globalObject, vm, args, XorFunc());
    544635}
    545636
  • trunk/Source/JavaScriptCore/runtime/ToNativeFromValue.h

    r272170 r272341  
    3434typename Adaptor::Type toNativeFromValue(JSValue value)
    3535{
    36     // FIXME: BigInt
     36    ASSERT(!value.isBigInt());
    3737    if (value.isInt32())
    3838        return Adaptor::toNativeFromInt32(value.asInt32());
Note: See TracChangeset for help on using the changeset viewer.