14514f5e3Sopenharmony_ci/* 24514f5e3Sopenharmony_ci * Copyright (c) 2022-2024 Huawei Device Co., Ltd. 34514f5e3Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 44514f5e3Sopenharmony_ci * you may not use this file except in compliance with the License. 54514f5e3Sopenharmony_ci * You may obtain a copy of the License at 64514f5e3Sopenharmony_ci * 74514f5e3Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 84514f5e3Sopenharmony_ci * 94514f5e3Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 104514f5e3Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 114514f5e3Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 124514f5e3Sopenharmony_ci * See the License for the specific language governing permissions and 134514f5e3Sopenharmony_ci * limitations under the License. 144514f5e3Sopenharmony_ci */ 154514f5e3Sopenharmony_ci 164514f5e3Sopenharmony_ci#include "ecmascript/builtins/builtins_atomics.h" 174514f5e3Sopenharmony_ci 184514f5e3Sopenharmony_ci#include "ecmascript/base/atomic_helper.h" 194514f5e3Sopenharmony_ci#include "ecmascript/base/typed_array_helper-inl.h" 204514f5e3Sopenharmony_ci#include "libpandabase/utils/time.h" 214514f5e3Sopenharmony_ci#include "ecmascript/checkpoint/thread_state_transition.h" 224514f5e3Sopenharmony_ci 234514f5e3Sopenharmony_cinamespace panda::ecmascript::builtins { 244514f5e3Sopenharmony_ciusing NumberHelper = base::NumberHelper; 254514f5e3Sopenharmony_ciusing AtomicHelper = base::AtomicHelper; 264514f5e3Sopenharmony_ciusing BytesSize = base::BytesSize; 274514f5e3Sopenharmony_ciusing BuiltinsArrayBuffer = builtins::BuiltinsArrayBuffer; 284514f5e3Sopenharmony_ci 294514f5e3Sopenharmony_ciWaiterList *g_waitLists = Singleton<WaiterList>::GetInstance(); 304514f5e3Sopenharmony_ciMutex *g_mutex = Singleton<Mutex>::GetInstance(); 314514f5e3Sopenharmony_ci 324514f5e3Sopenharmony_ci// 25.4.2 Atomics.add ( typedArray, index, value ) 334514f5e3Sopenharmony_ciJSTaggedValue BuiltinsAtomics::Sub(EcmaRuntimeCallInfo *argv) 344514f5e3Sopenharmony_ci{ 354514f5e3Sopenharmony_ci ASSERT(argv); 364514f5e3Sopenharmony_ci JSThread *thread = argv->GetThread(); 374514f5e3Sopenharmony_ci BUILTINS_API_TRACE(thread, Atomics, Sub); 384514f5e3Sopenharmony_ci [[maybe_unused]] EcmaHandleScope handleScope(thread); 394514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> typedArray = GetCallArg(argv, 0); 404514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> index = GetCallArg(argv, 1); 414514f5e3Sopenharmony_ci return AtomicReadModifyWrite(thread, typedArray, index, argv, AtomicHelper::SubFun()); 424514f5e3Sopenharmony_ci} 434514f5e3Sopenharmony_ci 444514f5e3Sopenharmony_ciJSTaggedValue BuiltinsAtomics::Add(EcmaRuntimeCallInfo *argv) 454514f5e3Sopenharmony_ci{ 464514f5e3Sopenharmony_ci ASSERT(argv); 474514f5e3Sopenharmony_ci JSThread *thread = argv->GetThread(); 484514f5e3Sopenharmony_ci BUILTINS_API_TRACE(thread, Atomics, Add); 494514f5e3Sopenharmony_ci [[maybe_unused]] EcmaHandleScope handleScope(thread); 504514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> typedArray = GetCallArg(argv, 0); 514514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> index = GetCallArg(argv, 1); 524514f5e3Sopenharmony_ci return AtomicReadModifyWrite(thread, typedArray, index, argv, AtomicHelper::AddFun()); 534514f5e3Sopenharmony_ci} 544514f5e3Sopenharmony_ci 554514f5e3Sopenharmony_ciJSTaggedValue BuiltinsAtomics::And(EcmaRuntimeCallInfo *argv) 564514f5e3Sopenharmony_ci{ 574514f5e3Sopenharmony_ci ASSERT(argv); 584514f5e3Sopenharmony_ci JSThread *thread = argv->GetThread(); 594514f5e3Sopenharmony_ci BUILTINS_API_TRACE(thread, Atomics, And); 604514f5e3Sopenharmony_ci [[maybe_unused]] EcmaHandleScope handleScope(thread); 614514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> typedArray = GetCallArg(argv, 0); 624514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> index = GetCallArg(argv, 1); 634514f5e3Sopenharmony_ci return AtomicReadModifyWrite(thread, typedArray, index, argv, AtomicHelper::AndFun()); 644514f5e3Sopenharmony_ci} 654514f5e3Sopenharmony_ci 664514f5e3Sopenharmony_ciJSTaggedValue BuiltinsAtomics::Or(EcmaRuntimeCallInfo *argv) 674514f5e3Sopenharmony_ci{ 684514f5e3Sopenharmony_ci ASSERT(argv); 694514f5e3Sopenharmony_ci JSThread *thread = argv->GetThread(); 704514f5e3Sopenharmony_ci BUILTINS_API_TRACE(thread, Atomics, Or); 714514f5e3Sopenharmony_ci [[maybe_unused]] EcmaHandleScope handleScope(thread); 724514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> typedArray = GetCallArg(argv, 0); 734514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> index = GetCallArg(argv, 1); 744514f5e3Sopenharmony_ci return AtomicReadModifyWrite(thread, typedArray, index, argv, AtomicHelper::OrFun()); 754514f5e3Sopenharmony_ci} 764514f5e3Sopenharmony_ci 774514f5e3Sopenharmony_ciJSTaggedValue BuiltinsAtomics::Xor(EcmaRuntimeCallInfo *argv) 784514f5e3Sopenharmony_ci{ 794514f5e3Sopenharmony_ci ASSERT(argv); 804514f5e3Sopenharmony_ci JSThread *thread = argv->GetThread(); 814514f5e3Sopenharmony_ci BUILTINS_API_TRACE(thread, Atomics, Xor); 824514f5e3Sopenharmony_ci [[maybe_unused]] EcmaHandleScope handleScope(thread); 834514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> typedArray = GetCallArg(argv, 0); 844514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> index = GetCallArg(argv, 1); 854514f5e3Sopenharmony_ci return AtomicReadModifyWrite(thread, typedArray, index, argv, AtomicHelper::XorFun()); 864514f5e3Sopenharmony_ci} 874514f5e3Sopenharmony_ci 884514f5e3Sopenharmony_ciJSTaggedValue BuiltinsAtomics::CompareExchange(EcmaRuntimeCallInfo *argv) 894514f5e3Sopenharmony_ci{ 904514f5e3Sopenharmony_ci ASSERT(argv); 914514f5e3Sopenharmony_ci JSThread *thread = argv->GetThread(); 924514f5e3Sopenharmony_ci BUILTINS_API_TRACE(thread, Atomics, CompareExchange); 934514f5e3Sopenharmony_ci [[maybe_unused]] EcmaHandleScope handleScope(thread); 944514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> typedArray = GetCallArg(argv, 0); 954514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> index = GetCallArg(argv, 1); 964514f5e3Sopenharmony_ci return AtomicReadModifyWrite(thread, typedArray, index, argv, AtomicHelper::CompareExchangeFun()); 974514f5e3Sopenharmony_ci} 984514f5e3Sopenharmony_ci 994514f5e3Sopenharmony_ciJSTaggedValue BuiltinsAtomics::Exchange(EcmaRuntimeCallInfo *argv) 1004514f5e3Sopenharmony_ci{ 1014514f5e3Sopenharmony_ci ASSERT(argv); 1024514f5e3Sopenharmony_ci JSThread *thread = argv->GetThread(); 1034514f5e3Sopenharmony_ci BUILTINS_API_TRACE(thread, Atomics, Exchange); 1044514f5e3Sopenharmony_ci [[maybe_unused]] EcmaHandleScope handleScope(thread); 1054514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> typedArray = GetCallArg(argv, 0); 1064514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> index = GetCallArg(argv, 1); 1074514f5e3Sopenharmony_ci return AtomicReadModifyWrite(thread, typedArray, index, argv, AtomicHelper::ExchangeFun()); 1084514f5e3Sopenharmony_ci} 1094514f5e3Sopenharmony_ci 1104514f5e3Sopenharmony_ciJSTaggedValue BuiltinsAtomics::Store(EcmaRuntimeCallInfo *argv) 1114514f5e3Sopenharmony_ci{ 1124514f5e3Sopenharmony_ci ASSERT(argv); 1134514f5e3Sopenharmony_ci JSThread *thread = argv->GetThread(); 1144514f5e3Sopenharmony_ci BUILTINS_API_TRACE(thread, Atomics, Store); 1154514f5e3Sopenharmony_ci [[maybe_unused]] EcmaHandleScope handleScope(thread); 1164514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> typedArray = GetCallArg(argv, 0); 1174514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> index = GetCallArg(argv, 1); 1184514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> value = GetCallArg(argv, BuiltinsBase::ArgsPosition::THIRD); 1194514f5e3Sopenharmony_ci return AtomicHelper::AtomicStore(thread, typedArray, index, value); 1204514f5e3Sopenharmony_ci} 1214514f5e3Sopenharmony_ci 1224514f5e3Sopenharmony_ciJSTaggedValue BuiltinsAtomics::Load(EcmaRuntimeCallInfo *argv) 1234514f5e3Sopenharmony_ci{ 1244514f5e3Sopenharmony_ci ASSERT(argv); 1254514f5e3Sopenharmony_ci JSThread *thread = argv->GetThread(); 1264514f5e3Sopenharmony_ci BUILTINS_API_TRACE(thread, Atomics, Load); 1274514f5e3Sopenharmony_ci [[maybe_unused]] EcmaHandleScope handleScope(thread); 1284514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> typedArray = GetCallArg(argv, 0); 1294514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> index = GetCallArg(argv, 1); 1304514f5e3Sopenharmony_ci return AtomicHelper::AtomicLoad(thread, typedArray, index); 1314514f5e3Sopenharmony_ci} 1324514f5e3Sopenharmony_ci 1334514f5e3Sopenharmony_ciJSTaggedValue BuiltinsAtomics::IsLockFree(EcmaRuntimeCallInfo *argv) 1344514f5e3Sopenharmony_ci{ 1354514f5e3Sopenharmony_ci ASSERT(argv); 1364514f5e3Sopenharmony_ci JSThread *thread = argv->GetThread(); 1374514f5e3Sopenharmony_ci BUILTINS_API_TRACE(thread, Atomics, IsLockFree); 1384514f5e3Sopenharmony_ci [[maybe_unused]] EcmaHandleScope handleScope(thread); 1394514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> sizeTag = GetCallArg(argv, 0); 1404514f5e3Sopenharmony_ci BytesSize size = BytesSize(JSTaggedValue::ToInt32(thread, sizeTag)); 1414514f5e3Sopenharmony_ci bool result = false; 1424514f5e3Sopenharmony_ci switch (size) { 1434514f5e3Sopenharmony_ci case BytesSize::ONEBYTES: 1444514f5e3Sopenharmony_ci case BytesSize::TWOBYTES: 1454514f5e3Sopenharmony_ci case BytesSize::FOURBYTES: 1464514f5e3Sopenharmony_ci case BytesSize::EIGHTBYTES: 1474514f5e3Sopenharmony_ci result = true; 1484514f5e3Sopenharmony_ci break; 1494514f5e3Sopenharmony_ci default: 1504514f5e3Sopenharmony_ci result = false; 1514514f5e3Sopenharmony_ci break; 1524514f5e3Sopenharmony_ci } 1534514f5e3Sopenharmony_ci return JSTaggedValue(result); 1544514f5e3Sopenharmony_ci} 1554514f5e3Sopenharmony_ci 1564514f5e3Sopenharmony_ci// 25.4.11 Atomics.wait ( typedArray, index, value, timeout ) 1574514f5e3Sopenharmony_ciJSTaggedValue BuiltinsAtomics::Wait(EcmaRuntimeCallInfo *argv) 1584514f5e3Sopenharmony_ci{ 1594514f5e3Sopenharmony_ci ASSERT(argv); 1604514f5e3Sopenharmony_ci JSThread *thread = argv->GetThread(); 1614514f5e3Sopenharmony_ci BUILTINS_API_TRACE(thread, Atomics, Wait); 1624514f5e3Sopenharmony_ci [[maybe_unused]] EcmaHandleScope handleScope(thread); 1634514f5e3Sopenharmony_ci 1644514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> array = GetCallArg(argv, 0); 1654514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> index = GetCallArg(argv, 1); 1664514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> value = GetCallArg(argv, BuiltinsBase::ArgsPosition::THIRD); 1674514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> timeout = GetCallArg(argv, BuiltinsBase::ArgsPosition::FOURTH); 1684514f5e3Sopenharmony_ci 1694514f5e3Sopenharmony_ci // 1. Let buffer be ? ValidateIntegerTypedArray(typedArray, true). 1704514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> arrayBuffer(thread, AtomicHelper::ValidateIntegerTypedArray(thread, array, true)); 1714514f5e3Sopenharmony_ci RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 1724514f5e3Sopenharmony_ci 1734514f5e3Sopenharmony_ci // 2. If IsSharedArrayBuffer(buffer) is false, throw a TypeError exception. 1744514f5e3Sopenharmony_ci if (!arrayBuffer->IsSharedArrayBuffer()) { 1754514f5e3Sopenharmony_ci THROW_TYPE_ERROR_AND_RETURN(thread, "buffer is not sharedArrayBuffer.", 1764514f5e3Sopenharmony_ci JSTaggedValue::Exception()); 1774514f5e3Sopenharmony_ci } 1784514f5e3Sopenharmony_ci 1794514f5e3Sopenharmony_ci // 3. Let indexedPosition be ? ValidateAtomicAccess(typedArray, index). 1804514f5e3Sopenharmony_ci uint32_t indexedPosition = AtomicHelper::ValidateAtomicAccess(thread, array, index); 1814514f5e3Sopenharmony_ci RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 1824514f5e3Sopenharmony_ci 1834514f5e3Sopenharmony_ci // 4. If typedArray.[[TypedArrayName]] is "BigInt64Array", let v be ? ToBigInt64(value). 1844514f5e3Sopenharmony_ci // 5. Otherwise, let v be ? ToInt32(value). 1854514f5e3Sopenharmony_ci int64_t v = 0; 1864514f5e3Sopenharmony_ci if (array->IsJSBigInt64Array()) { 1874514f5e3Sopenharmony_ci if (value->IsBoolean()) { 1884514f5e3Sopenharmony_ci value = JSHandle<JSTaggedValue>(thread, JSTaggedValue::ToBigInt64(thread, value)); 1894514f5e3Sopenharmony_ci RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 1904514f5e3Sopenharmony_ci } 1914514f5e3Sopenharmony_ci v = JSHandle<BigInt>::Cast(value)->ToInt64(); 1924514f5e3Sopenharmony_ci } else { 1934514f5e3Sopenharmony_ci v = static_cast<int64_t>(JSTaggedValue::ToInt32(thread, value)); 1944514f5e3Sopenharmony_ci } 1954514f5e3Sopenharmony_ci RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 1964514f5e3Sopenharmony_ci 1974514f5e3Sopenharmony_ci // 6. Let q be ? ToNumber(timeout). 1984514f5e3Sopenharmony_ci // 7. If q is NaN or +∞, let t be +∞; else if q is -∞, let t be 0; else let t be max(ℝ(q), 0). 1994514f5e3Sopenharmony_ci double t = 0; 2004514f5e3Sopenharmony_ci if (timeout->IsUndefined()) { 2014514f5e3Sopenharmony_ci t = base::POSITIVE_INFINITY; 2024514f5e3Sopenharmony_ci } else { 2034514f5e3Sopenharmony_ci JSTaggedNumber q = JSTaggedValue::ToNumber(thread, timeout); 2044514f5e3Sopenharmony_ci RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 2054514f5e3Sopenharmony_ci t = q.GetNumber(); 2064514f5e3Sopenharmony_ci if (NumberHelper::IsNaN(q) || (!NumberHelper::IsFinite(q) && t > 0)) { 2074514f5e3Sopenharmony_ci t = base::POSITIVE_INFINITY; 2084514f5e3Sopenharmony_ci } else if (t < 0) { 2094514f5e3Sopenharmony_ci t = 0; 2104514f5e3Sopenharmony_ci } 2114514f5e3Sopenharmony_ci } 2124514f5e3Sopenharmony_ci 2134514f5e3Sopenharmony_ci // 8. Let B be AgentCanSuspend(). 2144514f5e3Sopenharmony_ci // 9. If B is false, throw a TypeError exception. 2154514f5e3Sopenharmony_ci if (!thread->GetCurrentEcmaContext()->GetAllowAtomicWait()) { 2164514f5e3Sopenharmony_ci THROW_TYPE_ERROR_AND_RETURN(thread, "vm does not allow wait to block.", 2174514f5e3Sopenharmony_ci JSTaggedValue::Exception()); 2184514f5e3Sopenharmony_ci } 2194514f5e3Sopenharmony_ci WaitResult res = WaitResult::OK; 2204514f5e3Sopenharmony_ci if (array->IsJSBigInt64Array()) { 2214514f5e3Sopenharmony_ci // AtomicHelper::Wait<int64_t>(thread, arrayBuffer, indexedPosition, v, t); 2224514f5e3Sopenharmony_ci res = DoWait<int64_t>(thread, arrayBuffer, indexedPosition, v, t); 2234514f5e3Sopenharmony_ci } else { 2244514f5e3Sopenharmony_ci // AtomicHelper::Wait<int32_t>(thread, arrayBuffer, indexedPosition, static_cast<int32_t>(v), t); 2254514f5e3Sopenharmony_ci res = DoWait<int32_t>(thread, arrayBuffer, indexedPosition, static_cast<int32_t>(v), t); 2264514f5e3Sopenharmony_ci } 2274514f5e3Sopenharmony_ci const GlobalEnvConstants *globalConst = thread->GlobalConstants(); 2284514f5e3Sopenharmony_ci if (res == WaitResult::OK) { 2294514f5e3Sopenharmony_ci return globalConst->GetOkString(); 2304514f5e3Sopenharmony_ci } else if (res == WaitResult::NOT_EQ) { 2314514f5e3Sopenharmony_ci return globalConst->GetNotEqualString(); 2324514f5e3Sopenharmony_ci } 2334514f5e3Sopenharmony_ci return globalConst->GetTimeoutString(); 2344514f5e3Sopenharmony_ci} 2354514f5e3Sopenharmony_ci 2364514f5e3Sopenharmony_ci// 25.4.12 Atomics.notify ( typedArray, index, count ) 2374514f5e3Sopenharmony_ciJSTaggedValue BuiltinsAtomics::Notify(EcmaRuntimeCallInfo *argv) 2384514f5e3Sopenharmony_ci{ 2394514f5e3Sopenharmony_ci ASSERT(argv); 2404514f5e3Sopenharmony_ci JSThread *thread = argv->GetThread(); 2414514f5e3Sopenharmony_ci BUILTINS_API_TRACE(thread, Atomics, Notify); 2424514f5e3Sopenharmony_ci [[maybe_unused]] EcmaHandleScope handleScope(thread); 2434514f5e3Sopenharmony_ci 2444514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> array = GetCallArg(argv, 0); 2454514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> index = GetCallArg(argv, 1); 2464514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> count = GetCallArg(argv, BuiltinsBase::ArgsPosition::THIRD); 2474514f5e3Sopenharmony_ci 2484514f5e3Sopenharmony_ci // 1. Let buffer be ? ValidateIntegerTypedArray(typedArray, true). 2494514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> arrayBuffer(thread, AtomicHelper::ValidateIntegerTypedArray(thread, array, true)); 2504514f5e3Sopenharmony_ci RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 2514514f5e3Sopenharmony_ci 2524514f5e3Sopenharmony_ci // 2. Let indexedPosition be ? ValidateAtomicAccess(typedArray, index). 2534514f5e3Sopenharmony_ci uint32_t indexedPosition = AtomicHelper::ValidateAtomicAccess(thread, array, index); 2544514f5e3Sopenharmony_ci RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 2554514f5e3Sopenharmony_ci 2564514f5e3Sopenharmony_ci // 3. If count is undefined, let c be +∞. 2574514f5e3Sopenharmony_ci // 4. Else, 2584514f5e3Sopenharmony_ci // a. Let intCount be ? ToIntegerOrInfinity(count). 2594514f5e3Sopenharmony_ci // b. Let c be max(intCount, 0). 2604514f5e3Sopenharmony_ci double c = 0; 2614514f5e3Sopenharmony_ci if (count->IsUndefined()) { 2624514f5e3Sopenharmony_ci c = base::POSITIVE_INFINITY; 2634514f5e3Sopenharmony_ci } else { 2644514f5e3Sopenharmony_ci JSTaggedNumber countTemp = JSTaggedValue::ToNumber(thread, count); 2654514f5e3Sopenharmony_ci RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 2664514f5e3Sopenharmony_ci c = base::NumberHelper::TruncateDouble(countTemp.GetNumber()); 2674514f5e3Sopenharmony_ci c = c < 0 ? 0 : c; 2684514f5e3Sopenharmony_ci } 2694514f5e3Sopenharmony_ci // 6. If IsSharedArrayBuffer(buffer) is false, return +0. 2704514f5e3Sopenharmony_ci if (!arrayBuffer->IsSharedArrayBuffer()) { 2714514f5e3Sopenharmony_ci return JSTaggedValue(0); 2724514f5e3Sopenharmony_ci } 2734514f5e3Sopenharmony_ci return JSTaggedValue(Signal(arrayBuffer, indexedPosition, c)); 2744514f5e3Sopenharmony_ci} 2754514f5e3Sopenharmony_ci 2764514f5e3Sopenharmony_citemplate<typename callbackfun> 2774514f5e3Sopenharmony_ciJSTaggedValue BuiltinsAtomics::AtomicReadModifyWrite(JSThread *thread, const JSHandle<JSTaggedValue> &typedArray, 2784514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> &index, EcmaRuntimeCallInfo *argv, 2794514f5e3Sopenharmony_ci const callbackfun &op) 2804514f5e3Sopenharmony_ci{ 2814514f5e3Sopenharmony_ci BUILTINS_API_TRACE(thread, Atomics, AtomicReadModifyWrite); 2824514f5e3Sopenharmony_ci if (!typedArray->IsTypedArray()) { 2834514f5e3Sopenharmony_ci THROW_TYPE_ERROR_AND_RETURN(argv->GetThread(), "This is not a TypedArray.", JSTaggedValue::Exception()); 2844514f5e3Sopenharmony_ci } 2854514f5e3Sopenharmony_ci // 1. Let buffer be ? ValidateIntegerTypedArray(typedArray). 2864514f5e3Sopenharmony_ci JSTaggedValue bufferValue = base::AtomicHelper::ValidateIntegerTypedArray(thread, typedArray); 2874514f5e3Sopenharmony_ci RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 2884514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> buffer(thread, bufferValue); 2894514f5e3Sopenharmony_ci // 2. Let indexedPosition be ? ValidateAtomicAccess(typedArray, index). 2904514f5e3Sopenharmony_ci uint32_t indexedPosition = base::AtomicHelper::ValidateAtomicAccess(thread, typedArray, index); 2914514f5e3Sopenharmony_ci RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 2924514f5e3Sopenharmony_ci // 3. Let arrayTypeName be typedArray.[[TypedArrayName]]. 2934514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> arrayTypeName(thread, 2944514f5e3Sopenharmony_ci JSTypedArray::Cast(typedArray->GetTaggedObject())->GetTypedArrayName()); 2954514f5e3Sopenharmony_ci BuiltinsArrayBuffer::IsDetachedBuffer(thread, JSHandle<JSTypedArray>::Cast(typedArray)); 2964514f5e3Sopenharmony_ci RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 2974514f5e3Sopenharmony_ci // 7. NOTE: The above check is not redundant with the check in ValidateIntegerTypedArray because the call to 2984514f5e3Sopenharmony_ci // ToBigInt or ToIntegerOrInfinity on the preceding lines can have arbitrary side effects, which could cause the 2994514f5e3Sopenharmony_ci // buffer to become detached. 3004514f5e3Sopenharmony_ci // 8. Let elementType be the Element Type value in Table 60 for arrayTypeName. 3014514f5e3Sopenharmony_ci DataViewType elementType = JSTypedArray::GetTypeFromName(thread, arrayTypeName); 3024514f5e3Sopenharmony_ci // 9. Return GetModifySetValueInBuffer(buffer, indexedPosition, elementType, v, op). 3034514f5e3Sopenharmony_ci return AtomicReadModifyWriteCase(thread, buffer.GetTaggedValue(), elementType, indexedPosition, argv, op); 3044514f5e3Sopenharmony_ci} 3054514f5e3Sopenharmony_ci 3064514f5e3Sopenharmony_citemplate<typename callbackfun> 3074514f5e3Sopenharmony_ciJSTaggedValue BuiltinsAtomics::AtomicReadModifyWriteCase(JSThread *thread, JSTaggedValue arrBuf, 3084514f5e3Sopenharmony_ci DataViewType type, uint32_t indexedPosition, 3094514f5e3Sopenharmony_ci EcmaRuntimeCallInfo *argv, const callbackfun &op) 3104514f5e3Sopenharmony_ci{ 3114514f5e3Sopenharmony_ci BUILTINS_API_TRACE(thread, Atomics, AtomicReadModifyWriteCase); 3124514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> arrBufHadle(thread, arrBuf); 3134514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> value = BuiltinsBase::GetCallArg(argv, BuiltinsBase::ArgsPosition::THIRD); 3144514f5e3Sopenharmony_ci void *pointer = BuiltinsArrayBuffer::GetDataPointFromBuffer(arrBufHadle.GetTaggedValue()); 3154514f5e3Sopenharmony_ci uint8_t *block = reinterpret_cast<uint8_t *>(pointer); 3164514f5e3Sopenharmony_ci uint32_t size = argv->GetArgsNumber(); 3174514f5e3Sopenharmony_ci switch (type) { 3184514f5e3Sopenharmony_ci case DataViewType::UINT8: { 3194514f5e3Sopenharmony_ci uint8_t tag = JSTaggedValue::ToInt8(thread, value); 3204514f5e3Sopenharmony_ci pointer = BuiltinsArrayBuffer::GetDataPointFromBuffer(arrBufHadle.GetTaggedValue()); 3214514f5e3Sopenharmony_ci block = reinterpret_cast<uint8_t *>(pointer); 3224514f5e3Sopenharmony_ci return HandleWithUint8(thread, size, block, indexedPosition, argv, op, tag); 3234514f5e3Sopenharmony_ci } 3244514f5e3Sopenharmony_ci case DataViewType::INT8:{ 3254514f5e3Sopenharmony_ci int8_t tag = JSTaggedValue::ToInt8(thread, value); 3264514f5e3Sopenharmony_ci pointer = BuiltinsArrayBuffer::GetDataPointFromBuffer(arrBufHadle.GetTaggedValue()); 3274514f5e3Sopenharmony_ci block = reinterpret_cast<uint8_t *>(pointer); 3284514f5e3Sopenharmony_ci return HandleWithInt8(thread, size, block, indexedPosition, argv, op, tag); 3294514f5e3Sopenharmony_ci } 3304514f5e3Sopenharmony_ci case DataViewType::UINT16: { 3314514f5e3Sopenharmony_ci uint16_t tag = JSTaggedValue::ToInt16(thread, value); 3324514f5e3Sopenharmony_ci pointer = BuiltinsArrayBuffer::GetDataPointFromBuffer(arrBufHadle.GetTaggedValue()); 3334514f5e3Sopenharmony_ci block = reinterpret_cast<uint8_t *>(pointer); 3344514f5e3Sopenharmony_ci return HandleWithUint16(thread, size, block, indexedPosition, argv, op, tag); 3354514f5e3Sopenharmony_ci } 3364514f5e3Sopenharmony_ci case DataViewType::INT16: { 3374514f5e3Sopenharmony_ci int16_t tag = JSTaggedValue::ToInt16(thread, value); 3384514f5e3Sopenharmony_ci pointer = BuiltinsArrayBuffer::GetDataPointFromBuffer(arrBufHadle.GetTaggedValue()); 3394514f5e3Sopenharmony_ci block = reinterpret_cast<uint8_t *>(pointer); 3404514f5e3Sopenharmony_ci return HandleWithInt16(thread, size, block, indexedPosition, argv, op, tag); 3414514f5e3Sopenharmony_ci } 3424514f5e3Sopenharmony_ci case DataViewType::UINT32: { 3434514f5e3Sopenharmony_ci uint32_t tag = JSTaggedValue::ToUint32(thread, value); 3444514f5e3Sopenharmony_ci pointer = BuiltinsArrayBuffer::GetDataPointFromBuffer(arrBufHadle.GetTaggedValue()); 3454514f5e3Sopenharmony_ci block = reinterpret_cast<uint8_t *>(pointer); 3464514f5e3Sopenharmony_ci return HandleWithUint32(thread, size, block, indexedPosition, argv, op, tag); 3474514f5e3Sopenharmony_ci } 3484514f5e3Sopenharmony_ci case DataViewType::INT32: { 3494514f5e3Sopenharmony_ci int32_t tag = static_cast<int32_t>(JSTaggedValue::ToUint32(thread, value)); 3504514f5e3Sopenharmony_ci pointer = BuiltinsArrayBuffer::GetDataPointFromBuffer(arrBufHadle.GetTaggedValue()); 3514514f5e3Sopenharmony_ci block = reinterpret_cast<uint8_t *>(pointer); 3524514f5e3Sopenharmony_ci return HandleWithInt32(thread, size, block, indexedPosition, argv, op, tag); 3534514f5e3Sopenharmony_ci } 3544514f5e3Sopenharmony_ci case DataViewType::BIGINT64: { 3554514f5e3Sopenharmony_ci int64_t val = 0; 3564514f5e3Sopenharmony_ci bool lossless = true; 3574514f5e3Sopenharmony_ci BigInt::BigIntToInt64(thread, value, &val, &lossless); 3584514f5e3Sopenharmony_ci RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 3594514f5e3Sopenharmony_ci return HandleWithBigInt64(thread, size, block, indexedPosition, argv, op, val, lossless); 3604514f5e3Sopenharmony_ci } 3614514f5e3Sopenharmony_ci case DataViewType::BIGUINT64: { 3624514f5e3Sopenharmony_ci uint64_t val = 0; 3634514f5e3Sopenharmony_ci bool lossless = true; 3644514f5e3Sopenharmony_ci BigInt::BigIntToUint64(thread, value, &val, &lossless); 3654514f5e3Sopenharmony_ci RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 3664514f5e3Sopenharmony_ci return HandleWithBigUint64(thread, size, block, indexedPosition, argv, op, val, lossless); 3674514f5e3Sopenharmony_ci } 3684514f5e3Sopenharmony_ci default: 3694514f5e3Sopenharmony_ci break; 3704514f5e3Sopenharmony_ci } 3714514f5e3Sopenharmony_ci LOG_ECMA(FATAL) << "this branch is unreachable"; 3724514f5e3Sopenharmony_ci UNREACHABLE(); 3734514f5e3Sopenharmony_ci} 3744514f5e3Sopenharmony_ci 3754514f5e3Sopenharmony_citemplate<typename callbackfun> 3764514f5e3Sopenharmony_ciJSTaggedValue BuiltinsAtomics::HandleWithUint8(JSThread *thread, uint32_t size, uint8_t *block, 3774514f5e3Sopenharmony_ci uint32_t indexedPosition, 3784514f5e3Sopenharmony_ci EcmaRuntimeCallInfo *argv, const callbackfun &op, uint8_t &tag) 3794514f5e3Sopenharmony_ci{ 3804514f5e3Sopenharmony_ci BUILTINS_API_TRACE(thread, Atomics, HandleWithUint8); 3814514f5e3Sopenharmony_ci BuiltinsArrayBuffer::IsDetachedBuffer(thread, JSHandle<JSTypedArray>::Cast(GetCallArg(argv, 0))); 3824514f5e3Sopenharmony_ci RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 3834514f5e3Sopenharmony_ci uint8_t arg[ARGS_NUMBER] = {0}; 3844514f5e3Sopenharmony_ci arg[0] = tag; 3854514f5e3Sopenharmony_ci if (size == 3) { // the number of parameters is 3 3864514f5e3Sopenharmony_ci auto result = op((block + indexedPosition), arg, ARGS_NUMBER); 3874514f5e3Sopenharmony_ci return BuiltinsBase::GetTaggedInt(result); 3884514f5e3Sopenharmony_ci } 3894514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> newValue = BuiltinsBase::GetCallArg(argv, BuiltinsBase::ArgsPosition::FOURTH); 3904514f5e3Sopenharmony_ci uint8_t newTag = JSTaggedValue::ToUint8(thread, newValue); 3914514f5e3Sopenharmony_ci BuiltinsArrayBuffer::IsDetachedBuffer(thread, JSHandle<JSTypedArray>::Cast(GetCallArg(argv, 0))); 3924514f5e3Sopenharmony_ci RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 3934514f5e3Sopenharmony_ci arg[1] = newTag; 3944514f5e3Sopenharmony_ci auto result = op((block + indexedPosition), arg, ARGS_NUMBER); 3954514f5e3Sopenharmony_ci return JSTaggedValue(result); 3964514f5e3Sopenharmony_ci} 3974514f5e3Sopenharmony_ci 3984514f5e3Sopenharmony_citemplate<typename callbackfun> 3994514f5e3Sopenharmony_ciJSTaggedValue BuiltinsAtomics::HandleWithInt8(JSThread *thread, uint32_t size, uint8_t *block, 4004514f5e3Sopenharmony_ci uint32_t indexedPosition, 4014514f5e3Sopenharmony_ci EcmaRuntimeCallInfo *argv, const callbackfun &op, int8_t &tag) 4024514f5e3Sopenharmony_ci{ 4034514f5e3Sopenharmony_ci BUILTINS_API_TRACE(thread, Atomics, HandleWithInt8); 4044514f5e3Sopenharmony_ci BuiltinsArrayBuffer::IsDetachedBuffer(thread, JSHandle<JSTypedArray>::Cast(GetCallArg(argv, 0))); 4054514f5e3Sopenharmony_ci RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 4064514f5e3Sopenharmony_ci int8_t arg[ARGS_NUMBER] = {0}; 4074514f5e3Sopenharmony_ci arg[0] = tag; 4084514f5e3Sopenharmony_ci if (size == 3) { // the number of parameters is 3 4094514f5e3Sopenharmony_ci auto result = op(reinterpret_cast<int8_t *>(block + indexedPosition), arg, ARGS_NUMBER); 4104514f5e3Sopenharmony_ci return BuiltinsBase::GetTaggedInt(result); 4114514f5e3Sopenharmony_ci } 4124514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> newValue = BuiltinsBase::GetCallArg(argv, BuiltinsBase::ArgsPosition::FOURTH); 4134514f5e3Sopenharmony_ci int8_t newTag = JSTaggedValue::ToInt8(thread, newValue); 4144514f5e3Sopenharmony_ci BuiltinsArrayBuffer::IsDetachedBuffer(thread, JSHandle<JSTypedArray>::Cast(GetCallArg(argv, 0))); 4154514f5e3Sopenharmony_ci RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 4164514f5e3Sopenharmony_ci arg[1] = newTag; 4174514f5e3Sopenharmony_ci auto result = op(reinterpret_cast<int8_t *>(block + indexedPosition), arg, ARGS_NUMBER); 4184514f5e3Sopenharmony_ci return JSTaggedValue(result); 4194514f5e3Sopenharmony_ci} 4204514f5e3Sopenharmony_ci 4214514f5e3Sopenharmony_citemplate<typename callbackfun> 4224514f5e3Sopenharmony_ciJSTaggedValue BuiltinsAtomics::HandleWithUint16(JSThread *thread, uint32_t size, uint8_t *block, 4234514f5e3Sopenharmony_ci uint32_t indexedPosition, 4244514f5e3Sopenharmony_ci EcmaRuntimeCallInfo *argv, const callbackfun &op, uint16_t &tag) 4254514f5e3Sopenharmony_ci{ 4264514f5e3Sopenharmony_ci BUILTINS_API_TRACE(thread, Atomics, HandleWithUint16); 4274514f5e3Sopenharmony_ci BuiltinsArrayBuffer::IsDetachedBuffer(thread, JSHandle<JSTypedArray>::Cast(GetCallArg(argv, 0))); 4284514f5e3Sopenharmony_ci RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 4294514f5e3Sopenharmony_ci uint16_t arg[ARGS_NUMBER] = {0}; 4304514f5e3Sopenharmony_ci arg[0] = tag; 4314514f5e3Sopenharmony_ci if (size == 3) { // the number of parameters is 3 4324514f5e3Sopenharmony_ci auto result = op(reinterpret_cast<uint16_t *>(block + indexedPosition), arg, ARGS_NUMBER); 4334514f5e3Sopenharmony_ci return BuiltinsBase::GetTaggedInt(result); 4344514f5e3Sopenharmony_ci } 4354514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> newValue = BuiltinsBase::GetCallArg(argv, BuiltinsBase::ArgsPosition::FOURTH); 4364514f5e3Sopenharmony_ci uint16_t newTag = JSTaggedValue::ToUint16(thread, newValue); 4374514f5e3Sopenharmony_ci BuiltinsArrayBuffer::IsDetachedBuffer(thread, JSHandle<JSTypedArray>::Cast(GetCallArg(argv, 0))); 4384514f5e3Sopenharmony_ci RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 4394514f5e3Sopenharmony_ci arg[1] = newTag; 4404514f5e3Sopenharmony_ci auto result = op(reinterpret_cast<uint16_t *>(block + indexedPosition), arg, ARGS_NUMBER); 4414514f5e3Sopenharmony_ci return JSTaggedValue(result); 4424514f5e3Sopenharmony_ci} 4434514f5e3Sopenharmony_ci 4444514f5e3Sopenharmony_citemplate<typename callbackfun> 4454514f5e3Sopenharmony_ciJSTaggedValue BuiltinsAtomics::HandleWithInt16(JSThread *thread, uint32_t size, uint8_t *block, 4464514f5e3Sopenharmony_ci uint32_t indexedPosition, 4474514f5e3Sopenharmony_ci EcmaRuntimeCallInfo *argv, const callbackfun &op, int16_t &tag) 4484514f5e3Sopenharmony_ci{ 4494514f5e3Sopenharmony_ci BUILTINS_API_TRACE(thread, Atomics, HandleWithInt16); 4504514f5e3Sopenharmony_ci BuiltinsArrayBuffer::IsDetachedBuffer(thread, JSHandle<JSTypedArray>::Cast(GetCallArg(argv, 0))); 4514514f5e3Sopenharmony_ci RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 4524514f5e3Sopenharmony_ci int16_t arg[ARGS_NUMBER] = {0}; 4534514f5e3Sopenharmony_ci arg[0] = tag; 4544514f5e3Sopenharmony_ci if (size == 3) { // the number of parameters is 3 4554514f5e3Sopenharmony_ci auto result = op(reinterpret_cast<int16_t *>(block + indexedPosition), arg, ARGS_NUMBER); 4564514f5e3Sopenharmony_ci return BuiltinsBase::GetTaggedInt(result); 4574514f5e3Sopenharmony_ci } 4584514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> newValue = BuiltinsBase::GetCallArg(argv, BuiltinsBase::ArgsPosition::FOURTH); 4594514f5e3Sopenharmony_ci int16_t newTag = JSTaggedValue::ToInt16(thread, newValue); 4604514f5e3Sopenharmony_ci BuiltinsArrayBuffer::IsDetachedBuffer(thread, JSHandle<JSTypedArray>::Cast(GetCallArg(argv, 0))); 4614514f5e3Sopenharmony_ci RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 4624514f5e3Sopenharmony_ci arg[1] = newTag; 4634514f5e3Sopenharmony_ci auto result = op(reinterpret_cast<int16_t *>(block + indexedPosition), arg, ARGS_NUMBER); 4644514f5e3Sopenharmony_ci return JSTaggedValue(result); 4654514f5e3Sopenharmony_ci} 4664514f5e3Sopenharmony_ci 4674514f5e3Sopenharmony_citemplate<typename callbackfun> 4684514f5e3Sopenharmony_ciJSTaggedValue BuiltinsAtomics::HandleWithUint32(JSThread *thread, uint32_t size, uint8_t *block, 4694514f5e3Sopenharmony_ci uint32_t indexedPosition, 4704514f5e3Sopenharmony_ci EcmaRuntimeCallInfo *argv, const callbackfun &op, uint32_t &tag) 4714514f5e3Sopenharmony_ci{ 4724514f5e3Sopenharmony_ci BUILTINS_API_TRACE(thread, Atomics, HandleWithUint32); 4734514f5e3Sopenharmony_ci BuiltinsArrayBuffer::IsDetachedBuffer(thread, JSHandle<JSTypedArray>::Cast(GetCallArg(argv, 0))); 4744514f5e3Sopenharmony_ci RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 4754514f5e3Sopenharmony_ci uint32_t arg[ARGS_NUMBER] = {0}; 4764514f5e3Sopenharmony_ci arg[0] = tag; 4774514f5e3Sopenharmony_ci if (size == 3) { // the number of parameters is 3 4784514f5e3Sopenharmony_ci auto result = op(reinterpret_cast<uint32_t *>(block + indexedPosition), arg, ARGS_NUMBER); 4794514f5e3Sopenharmony_ci return JSTaggedValue(result); 4804514f5e3Sopenharmony_ci } 4814514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> newValue = BuiltinsBase::GetCallArg(argv, BuiltinsBase::ArgsPosition::FOURTH); 4824514f5e3Sopenharmony_ci uint32_t newTag = JSTaggedValue::ToUint32(thread, newValue); 4834514f5e3Sopenharmony_ci BuiltinsArrayBuffer::IsDetachedBuffer(thread, JSHandle<JSTypedArray>::Cast(GetCallArg(argv, 0))); 4844514f5e3Sopenharmony_ci RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 4854514f5e3Sopenharmony_ci arg[1] = newTag; 4864514f5e3Sopenharmony_ci auto result = op(reinterpret_cast<uint32_t *>(block + indexedPosition), arg, ARGS_NUMBER); 4874514f5e3Sopenharmony_ci return JSTaggedValue(result); 4884514f5e3Sopenharmony_ci} 4894514f5e3Sopenharmony_ci 4904514f5e3Sopenharmony_citemplate<typename callbackfun> 4914514f5e3Sopenharmony_ciJSTaggedValue BuiltinsAtomics::HandleWithInt32(JSThread *thread, uint32_t size, uint8_t *block, 4924514f5e3Sopenharmony_ci uint32_t indexedPosition, 4934514f5e3Sopenharmony_ci EcmaRuntimeCallInfo *argv, const callbackfun &op, int32_t &tag) 4944514f5e3Sopenharmony_ci{ 4954514f5e3Sopenharmony_ci BUILTINS_API_TRACE(thread, Atomics, HandleWithInt32); 4964514f5e3Sopenharmony_ci BuiltinsArrayBuffer::IsDetachedBuffer(thread, JSHandle<JSTypedArray>::Cast(GetCallArg(argv, 0))); 4974514f5e3Sopenharmony_ci RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 4984514f5e3Sopenharmony_ci int32_t arg[ARGS_NUMBER] = {0}; 4994514f5e3Sopenharmony_ci arg[0] = tag; 5004514f5e3Sopenharmony_ci if (size == 3) { // the number of parameters is 3 5014514f5e3Sopenharmony_ci auto result = op(reinterpret_cast<int32_t *>(block + indexedPosition), arg, ARGS_NUMBER); 5024514f5e3Sopenharmony_ci return BuiltinsBase::GetTaggedInt(result); 5034514f5e3Sopenharmony_ci } 5044514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> newValue = BuiltinsBase::GetCallArg(argv, BuiltinsBase::ArgsPosition::FOURTH); 5054514f5e3Sopenharmony_ci int32_t newTag = JSTaggedValue::ToInt32(thread, newValue); 5064514f5e3Sopenharmony_ci BuiltinsArrayBuffer::IsDetachedBuffer(thread, JSHandle<JSTypedArray>::Cast(GetCallArg(argv, 0))); 5074514f5e3Sopenharmony_ci RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 5084514f5e3Sopenharmony_ci arg[1] = newTag; 5094514f5e3Sopenharmony_ci auto result = op(reinterpret_cast<int32_t *>(block + indexedPosition), arg, ARGS_NUMBER); 5104514f5e3Sopenharmony_ci return JSTaggedValue(result); 5114514f5e3Sopenharmony_ci} 5124514f5e3Sopenharmony_ci 5134514f5e3Sopenharmony_citemplate<typename callbackfun> 5144514f5e3Sopenharmony_ciJSTaggedValue BuiltinsAtomics::HandleWithBigInt64(JSThread *thread, uint32_t size, uint8_t *block, 5154514f5e3Sopenharmony_ci uint32_t indexedPosition, 5164514f5e3Sopenharmony_ci EcmaRuntimeCallInfo *argv, const callbackfun &op, 5174514f5e3Sopenharmony_ci int64_t &tag, bool &lossless) 5184514f5e3Sopenharmony_ci{ 5194514f5e3Sopenharmony_ci BUILTINS_API_TRACE(thread, Atomics, HandleWithBigInt64); 5204514f5e3Sopenharmony_ci RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 5214514f5e3Sopenharmony_ci BuiltinsArrayBuffer::IsDetachedBuffer(thread, JSHandle<JSTypedArray>::Cast(GetCallArg(argv, 0))); 5224514f5e3Sopenharmony_ci RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 5234514f5e3Sopenharmony_ci int64_t arg[ARGS_NUMBER] = {0}; 5244514f5e3Sopenharmony_ci arg[0] = tag; 5254514f5e3Sopenharmony_ci if (size == 3) { // the number of parameters is 3 5264514f5e3Sopenharmony_ci auto result = op(reinterpret_cast<int64_t *>(block + indexedPosition), arg, ARGS_NUMBER); 5274514f5e3Sopenharmony_ci return BigInt::Int64ToBigInt(thread, result).GetTaggedValue(); 5284514f5e3Sopenharmony_ci } 5294514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> newValue = BuiltinsBase::GetCallArg(argv, BuiltinsBase::ArgsPosition::FOURTH); 5304514f5e3Sopenharmony_ci int64_t newVal = 0; 5314514f5e3Sopenharmony_ci BigInt::BigIntToInt64(thread, newValue, &newVal, &lossless); 5324514f5e3Sopenharmony_ci RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 5334514f5e3Sopenharmony_ci BuiltinsArrayBuffer::IsDetachedBuffer(thread, JSHandle<JSTypedArray>::Cast(GetCallArg(argv, 0))); 5344514f5e3Sopenharmony_ci RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 5354514f5e3Sopenharmony_ci arg[1] = newVal; 5364514f5e3Sopenharmony_ci auto result = op(reinterpret_cast<int64_t *>(block + indexedPosition), arg, ARGS_NUMBER); 5374514f5e3Sopenharmony_ci return BigInt::Int64ToBigInt(thread, result).GetTaggedValue(); 5384514f5e3Sopenharmony_ci} 5394514f5e3Sopenharmony_ci 5404514f5e3Sopenharmony_citemplate<typename callbackfun> 5414514f5e3Sopenharmony_ciJSTaggedValue BuiltinsAtomics::HandleWithBigUint64(JSThread *thread, uint32_t size, uint8_t *block, 5424514f5e3Sopenharmony_ci uint32_t indexedPosition, 5434514f5e3Sopenharmony_ci EcmaRuntimeCallInfo *argv, const callbackfun &op, 5444514f5e3Sopenharmony_ci uint64_t &tag, bool &lossless) 5454514f5e3Sopenharmony_ci{ 5464514f5e3Sopenharmony_ci BUILTINS_API_TRACE(thread, Atomics, HandleWithBigUint64); 5474514f5e3Sopenharmony_ci RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 5484514f5e3Sopenharmony_ci BuiltinsArrayBuffer::IsDetachedBuffer(thread, JSHandle<JSTypedArray>::Cast(GetCallArg(argv, 0))); 5494514f5e3Sopenharmony_ci RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 5504514f5e3Sopenharmony_ci uint64_t arg[ARGS_NUMBER] = {0}; 5514514f5e3Sopenharmony_ci arg[0] = tag; 5524514f5e3Sopenharmony_ci if (size == 3) { // the number of parameters is 3 5534514f5e3Sopenharmony_ci auto result = op(reinterpret_cast<uint64_t *>(block + indexedPosition), arg, ARGS_NUMBER); 5544514f5e3Sopenharmony_ci return BigInt::Uint64ToBigInt(thread, result).GetTaggedValue(); 5554514f5e3Sopenharmony_ci } 5564514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> newValue = BuiltinsBase::GetCallArg(argv, BuiltinsBase::ArgsPosition::FOURTH); 5574514f5e3Sopenharmony_ci uint64_t newVal = 0; 5584514f5e3Sopenharmony_ci BigInt::BigIntToUint64(thread, newValue, &newVal, &lossless); 5594514f5e3Sopenharmony_ci RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 5604514f5e3Sopenharmony_ci BuiltinsArrayBuffer::IsDetachedBuffer(thread, JSHandle<JSTypedArray>::Cast(GetCallArg(argv, 0))); 5614514f5e3Sopenharmony_ci RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 5624514f5e3Sopenharmony_ci arg[1] = newVal; 5634514f5e3Sopenharmony_ci auto result = op(reinterpret_cast<uint64_t *>(block + indexedPosition), arg, ARGS_NUMBER); 5644514f5e3Sopenharmony_ci return BigInt::Uint64ToBigInt(thread, result).GetTaggedValue(); 5654514f5e3Sopenharmony_ci} 5664514f5e3Sopenharmony_ci 5674514f5e3Sopenharmony_citemplate <typename T> 5684514f5e3Sopenharmony_ciWaitResult BuiltinsAtomics::DoWait(JSThread *thread, JSHandle<JSTaggedValue> &arrayBuffer, 5694514f5e3Sopenharmony_ci size_t index, T execpt, double timeout) 5704514f5e3Sopenharmony_ci{ 5714514f5e3Sopenharmony_ci BUILTINS_API_TRACE(thread, Atomics, DoWait); 5724514f5e3Sopenharmony_ci MutexGuard lockGuard(g_mutex); 5734514f5e3Sopenharmony_ci void *buffer = BuiltinsArrayBuffer::GetDataPointFromBuffer(arrayBuffer.GetTaggedValue()); 5744514f5e3Sopenharmony_ci ASSERT(buffer != nullptr); 5754514f5e3Sopenharmony_ci WaiterListNode *node = thread->GetCurrentEcmaContext()->GetWaiterListNode(); 5764514f5e3Sopenharmony_ci node->date_ = buffer; 5774514f5e3Sopenharmony_ci node->index_ = index; 5784514f5e3Sopenharmony_ci node->waitPointer_ = reinterpret_cast<int8_t*>(buffer) + index; 5794514f5e3Sopenharmony_ci node->waiting_ = true; 5804514f5e3Sopenharmony_ci std::atomic<T> *atomicValue = reinterpret_cast<std::atomic<T> *>(node->waitPointer_); 5814514f5e3Sopenharmony_ci T value = atomicValue->load(); 5824514f5e3Sopenharmony_ci if (value != execpt) { 5834514f5e3Sopenharmony_ci return WaitResult::NOT_EQ; 5844514f5e3Sopenharmony_ci } 5854514f5e3Sopenharmony_ci g_waitLists->AddNode(node); 5864514f5e3Sopenharmony_ci uint64_t currentTime = 0; 5874514f5e3Sopenharmony_ci uint64_t timeoutTime = 0; 5884514f5e3Sopenharmony_ci bool hasTimeout = timeout != base::POSITIVE_INFINITY; 5894514f5e3Sopenharmony_ci if (hasTimeout) { 5904514f5e3Sopenharmony_ci currentTime = time::GetCurrentTimeInMillis(); 5914514f5e3Sopenharmony_ci timeoutTime = currentTime + static_cast<uint64_t>(timeout); 5924514f5e3Sopenharmony_ci } 5934514f5e3Sopenharmony_ci WaitResult res = WaitResult::OK; 5944514f5e3Sopenharmony_ci ThreadNativeScope nativeScope(thread); 5954514f5e3Sopenharmony_ci while (true) { 5964514f5e3Sopenharmony_ci if (!node->waiting_) { 5974514f5e3Sopenharmony_ci res = WaitResult::OK; 5984514f5e3Sopenharmony_ci break; 5994514f5e3Sopenharmony_ci } 6004514f5e3Sopenharmony_ci if (hasTimeout) { 6014514f5e3Sopenharmony_ci currentTime = time::GetCurrentTimeInMillis(); 6024514f5e3Sopenharmony_ci if (currentTime >= timeoutTime) { 6034514f5e3Sopenharmony_ci res = WaitResult::TIME_OUT; 6044514f5e3Sopenharmony_ci break; 6054514f5e3Sopenharmony_ci } 6064514f5e3Sopenharmony_ci uint64_t untilTime = timeoutTime - currentTime; 6074514f5e3Sopenharmony_ci ASSERT(untilTime != 0); 6084514f5e3Sopenharmony_ci 6094514f5e3Sopenharmony_ci node->cond_.TimedWait(g_mutex, untilTime); 6104514f5e3Sopenharmony_ci } else { 6114514f5e3Sopenharmony_ci node->cond_.Wait(g_mutex); 6124514f5e3Sopenharmony_ci } 6134514f5e3Sopenharmony_ci } 6144514f5e3Sopenharmony_ci g_waitLists->DeleteNode(node); 6154514f5e3Sopenharmony_ci node->waiting_ = false; 6164514f5e3Sopenharmony_ci return res; 6174514f5e3Sopenharmony_ci} 6184514f5e3Sopenharmony_ci 6194514f5e3Sopenharmony_ciuint32_t BuiltinsAtomics::Signal(JSHandle<JSTaggedValue> &arrayBuffer, const size_t &index, double wakeCount) 6204514f5e3Sopenharmony_ci{ 6214514f5e3Sopenharmony_ci void *buffer = BuiltinsArrayBuffer::GetDataPointFromBuffer(arrayBuffer.GetTaggedValue()); 6224514f5e3Sopenharmony_ci ASSERT(buffer != nullptr); 6234514f5e3Sopenharmony_ci MutexGuard lockGuard(g_mutex); 6244514f5e3Sopenharmony_ci auto &locationListMap = g_waitLists->locationListMap_; 6254514f5e3Sopenharmony_ci auto iter = locationListMap.find(reinterpret_cast<int8_t *>(buffer) + index); 6264514f5e3Sopenharmony_ci if (iter == locationListMap.end()) { 6274514f5e3Sopenharmony_ci return 0; 6284514f5e3Sopenharmony_ci } 6294514f5e3Sopenharmony_ci WaiterListNode *node = iter->second.pHead; 6304514f5e3Sopenharmony_ci uint32_t wokenUpCount = 0; 6314514f5e3Sopenharmony_ci while (node != nullptr && wakeCount > 0.0) { 6324514f5e3Sopenharmony_ci if (!node->waiting_) { 6334514f5e3Sopenharmony_ci node = node->next_; 6344514f5e3Sopenharmony_ci continue; 6354514f5e3Sopenharmony_ci } 6364514f5e3Sopenharmony_ci if (buffer == node->date_) { 6374514f5e3Sopenharmony_ci ASSERT(index == node->index_); 6384514f5e3Sopenharmony_ci node->waiting_ = false; 6394514f5e3Sopenharmony_ci 6404514f5e3Sopenharmony_ci WaiterListNode *oldNode = node; 6414514f5e3Sopenharmony_ci node = node->next_; 6424514f5e3Sopenharmony_ci oldNode->cond_.Signal(); 6434514f5e3Sopenharmony_ci if (wakeCount != base::POSITIVE_INFINITY) { 6444514f5e3Sopenharmony_ci wakeCount--; 6454514f5e3Sopenharmony_ci } 6464514f5e3Sopenharmony_ci wokenUpCount++; 6474514f5e3Sopenharmony_ci continue; 6484514f5e3Sopenharmony_ci } 6494514f5e3Sopenharmony_ci node = node->next_; 6504514f5e3Sopenharmony_ci } 6514514f5e3Sopenharmony_ci return wokenUpCount; 6524514f5e3Sopenharmony_ci} 6534514f5e3Sopenharmony_ci} // namespace panda::ecmascript::builtins 654