11cb0ef41Sopenharmony_ci// Copyright 2017 the V8 project authors. All rights reserved. 21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be 31cb0ef41Sopenharmony_ci// found in the LICENSE file. 41cb0ef41Sopenharmony_ci 51cb0ef41Sopenharmony_ci#include "src/builtins/builtins-utils-gen.h" 61cb0ef41Sopenharmony_ci#include "src/builtins/builtins.h" 71cb0ef41Sopenharmony_ci#include "src/codegen/code-stub-assembler.h" 81cb0ef41Sopenharmony_ci#include "src/objects/objects.h" 91cb0ef41Sopenharmony_ci 101cb0ef41Sopenharmony_cinamespace v8 { 111cb0ef41Sopenharmony_cinamespace internal { 121cb0ef41Sopenharmony_ci 131cb0ef41Sopenharmony_ciclass SharedArrayBufferBuiltinsAssembler : public CodeStubAssembler { 141cb0ef41Sopenharmony_ci public: 151cb0ef41Sopenharmony_ci explicit SharedArrayBufferBuiltinsAssembler( 161cb0ef41Sopenharmony_ci compiler::CodeAssemblerState* state) 171cb0ef41Sopenharmony_ci : CodeStubAssembler(state) {} 181cb0ef41Sopenharmony_ci 191cb0ef41Sopenharmony_ci protected: 201cb0ef41Sopenharmony_ci using AssemblerFunction = TNode<Word32T> (CodeAssembler::*)( 211cb0ef41Sopenharmony_ci MachineType type, TNode<RawPtrT> base, TNode<UintPtrT> offset, 221cb0ef41Sopenharmony_ci TNode<Word32T> value); 231cb0ef41Sopenharmony_ci template <class Type> 241cb0ef41Sopenharmony_ci using AssemblerFunction64 = TNode<Type> (CodeAssembler::*)( 251cb0ef41Sopenharmony_ci TNode<RawPtrT> base, TNode<UintPtrT> offset, TNode<UintPtrT> value, 261cb0ef41Sopenharmony_ci TNode<UintPtrT> value_high); 271cb0ef41Sopenharmony_ci TNode<JSArrayBuffer> ValidateIntegerTypedArray( 281cb0ef41Sopenharmony_ci TNode<Object> maybe_array, TNode<Context> context, 291cb0ef41Sopenharmony_ci TNode<Int32T>* out_elements_kind, TNode<RawPtrT>* out_backing_store, 301cb0ef41Sopenharmony_ci Label* detached); 311cb0ef41Sopenharmony_ci 321cb0ef41Sopenharmony_ci TNode<UintPtrT> ValidateAtomicAccess(TNode<JSTypedArray> array, 331cb0ef41Sopenharmony_ci TNode<Object> index, 341cb0ef41Sopenharmony_ci TNode<Context> context); 351cb0ef41Sopenharmony_ci 361cb0ef41Sopenharmony_ci inline void DebugCheckAtomicIndex(TNode<JSTypedArray> array, 371cb0ef41Sopenharmony_ci TNode<UintPtrT> index); 381cb0ef41Sopenharmony_ci 391cb0ef41Sopenharmony_ci void AtomicBinopBuiltinCommon( 401cb0ef41Sopenharmony_ci TNode<Object> maybe_array, TNode<Object> index, TNode<Object> value, 411cb0ef41Sopenharmony_ci TNode<Context> context, AssemblerFunction function, 421cb0ef41Sopenharmony_ci AssemblerFunction64<AtomicInt64> function_int_64, 431cb0ef41Sopenharmony_ci AssemblerFunction64<AtomicUint64> function_uint_64, 441cb0ef41Sopenharmony_ci Runtime::FunctionId runtime_function, const char* method_name); 451cb0ef41Sopenharmony_ci 461cb0ef41Sopenharmony_ci // Create a BigInt from the result of a 64-bit atomic operation, using 471cb0ef41Sopenharmony_ci // projections on 32-bit platforms. 481cb0ef41Sopenharmony_ci TNode<BigInt> BigIntFromSigned64(TNode<AtomicInt64> signed64); 491cb0ef41Sopenharmony_ci TNode<BigInt> BigIntFromUnsigned64(TNode<AtomicUint64> unsigned64); 501cb0ef41Sopenharmony_ci}; 511cb0ef41Sopenharmony_ci 521cb0ef41Sopenharmony_ci// https://tc39.es/ecma262/#sec-validateintegertypedarray 531cb0ef41Sopenharmony_ciTNode<JSArrayBuffer> 541cb0ef41Sopenharmony_ciSharedArrayBufferBuiltinsAssembler::ValidateIntegerTypedArray( 551cb0ef41Sopenharmony_ci TNode<Object> maybe_array, TNode<Context> context, 561cb0ef41Sopenharmony_ci TNode<Int32T>* out_elements_kind, TNode<RawPtrT>* out_backing_store, 571cb0ef41Sopenharmony_ci Label* detached) { 581cb0ef41Sopenharmony_ci Label not_float_or_clamped(this), invalid(this); 591cb0ef41Sopenharmony_ci 601cb0ef41Sopenharmony_ci // The logic of TypedArrayBuiltinsAssembler::ValidateTypedArrayBuffer is 611cb0ef41Sopenharmony_ci // inlined to avoid duplicate error branches. 621cb0ef41Sopenharmony_ci 631cb0ef41Sopenharmony_ci // Fail if it is not a heap object. 641cb0ef41Sopenharmony_ci GotoIf(TaggedIsSmi(maybe_array), &invalid); 651cb0ef41Sopenharmony_ci 661cb0ef41Sopenharmony_ci // Fail if the array's instance type is not JSTypedArray. 671cb0ef41Sopenharmony_ci TNode<Map> map = LoadMap(CAST(maybe_array)); 681cb0ef41Sopenharmony_ci GotoIfNot(IsJSTypedArrayMap(map), &invalid); 691cb0ef41Sopenharmony_ci TNode<JSTypedArray> array = CAST(maybe_array); 701cb0ef41Sopenharmony_ci 711cb0ef41Sopenharmony_ci // Fail if the array's JSArrayBuffer is detached. 721cb0ef41Sopenharmony_ci TNode<JSArrayBuffer> array_buffer = GetTypedArrayBuffer(context, array); 731cb0ef41Sopenharmony_ci GotoIf(IsDetachedBuffer(array_buffer), detached); 741cb0ef41Sopenharmony_ci 751cb0ef41Sopenharmony_ci // Fail if the array's element type is float32, float64 or clamped. 761cb0ef41Sopenharmony_ci STATIC_ASSERT(INT8_ELEMENTS < FLOAT32_ELEMENTS); 771cb0ef41Sopenharmony_ci STATIC_ASSERT(INT16_ELEMENTS < FLOAT32_ELEMENTS); 781cb0ef41Sopenharmony_ci STATIC_ASSERT(INT32_ELEMENTS < FLOAT32_ELEMENTS); 791cb0ef41Sopenharmony_ci STATIC_ASSERT(UINT8_ELEMENTS < FLOAT32_ELEMENTS); 801cb0ef41Sopenharmony_ci STATIC_ASSERT(UINT16_ELEMENTS < FLOAT32_ELEMENTS); 811cb0ef41Sopenharmony_ci STATIC_ASSERT(UINT32_ELEMENTS < FLOAT32_ELEMENTS); 821cb0ef41Sopenharmony_ci TNode<Int32T> elements_kind = LoadMapElementsKind(map); 831cb0ef41Sopenharmony_ci GotoIf(Int32LessThan(elements_kind, Int32Constant(FLOAT32_ELEMENTS)), 841cb0ef41Sopenharmony_ci ¬_float_or_clamped); 851cb0ef41Sopenharmony_ci STATIC_ASSERT(BIGINT64_ELEMENTS > UINT8_CLAMPED_ELEMENTS); 861cb0ef41Sopenharmony_ci STATIC_ASSERT(BIGUINT64_ELEMENTS > UINT8_CLAMPED_ELEMENTS); 871cb0ef41Sopenharmony_ci Branch(Int32GreaterThan(elements_kind, Int32Constant(UINT8_CLAMPED_ELEMENTS)), 881cb0ef41Sopenharmony_ci ¬_float_or_clamped, &invalid); 891cb0ef41Sopenharmony_ci 901cb0ef41Sopenharmony_ci BIND(&invalid); 911cb0ef41Sopenharmony_ci { 921cb0ef41Sopenharmony_ci ThrowTypeError(context, MessageTemplate::kNotIntegerTypedArray, 931cb0ef41Sopenharmony_ci maybe_array); 941cb0ef41Sopenharmony_ci } 951cb0ef41Sopenharmony_ci 961cb0ef41Sopenharmony_ci BIND(¬_float_or_clamped); 971cb0ef41Sopenharmony_ci *out_elements_kind = elements_kind; 981cb0ef41Sopenharmony_ci 991cb0ef41Sopenharmony_ci TNode<RawPtrT> backing_store = LoadJSArrayBufferBackingStorePtr(array_buffer); 1001cb0ef41Sopenharmony_ci TNode<UintPtrT> byte_offset = LoadJSArrayBufferViewByteOffset(array); 1011cb0ef41Sopenharmony_ci *out_backing_store = RawPtrAdd(backing_store, Signed(byte_offset)); 1021cb0ef41Sopenharmony_ci 1031cb0ef41Sopenharmony_ci return array_buffer; 1041cb0ef41Sopenharmony_ci} 1051cb0ef41Sopenharmony_ci 1061cb0ef41Sopenharmony_ci// https://tc39.github.io/ecma262/#sec-validateatomicaccess 1071cb0ef41Sopenharmony_ci// ValidateAtomicAccess( typedArray, requestIndex ) 1081cb0ef41Sopenharmony_ciTNode<UintPtrT> SharedArrayBufferBuiltinsAssembler::ValidateAtomicAccess( 1091cb0ef41Sopenharmony_ci TNode<JSTypedArray> array, TNode<Object> index, TNode<Context> context) { 1101cb0ef41Sopenharmony_ci Label done(this), range_error(this); 1111cb0ef41Sopenharmony_ci // TODO(v8:11111): Support RAB / GSAB. 1121cb0ef41Sopenharmony_ci 1131cb0ef41Sopenharmony_ci // 1. Assert: typedArray is an Object that has a [[ViewedArrayBuffer]] 1141cb0ef41Sopenharmony_ci // internal slot. 1151cb0ef41Sopenharmony_ci // 2. Let length be typedArray.[[ArrayLength]]. 1161cb0ef41Sopenharmony_ci TNode<UintPtrT> array_length = LoadJSTypedArrayLength(array); 1171cb0ef41Sopenharmony_ci 1181cb0ef41Sopenharmony_ci // 3. Let accessIndex be ? ToIndex(requestIndex). 1191cb0ef41Sopenharmony_ci TNode<UintPtrT> index_uintptr = ToIndex(context, index, &range_error); 1201cb0ef41Sopenharmony_ci 1211cb0ef41Sopenharmony_ci // 4. Assert: accessIndex ≥ 0. 1221cb0ef41Sopenharmony_ci // 5. If accessIndex ≥ length, throw a RangeError exception. 1231cb0ef41Sopenharmony_ci Branch(UintPtrLessThan(index_uintptr, array_length), &done, &range_error); 1241cb0ef41Sopenharmony_ci 1251cb0ef41Sopenharmony_ci BIND(&range_error); 1261cb0ef41Sopenharmony_ci ThrowRangeError(context, MessageTemplate::kInvalidAtomicAccessIndex); 1271cb0ef41Sopenharmony_ci 1281cb0ef41Sopenharmony_ci // 6. Return accessIndex. 1291cb0ef41Sopenharmony_ci BIND(&done); 1301cb0ef41Sopenharmony_ci return index_uintptr; 1311cb0ef41Sopenharmony_ci} 1321cb0ef41Sopenharmony_ci 1331cb0ef41Sopenharmony_civoid SharedArrayBufferBuiltinsAssembler::DebugCheckAtomicIndex( 1341cb0ef41Sopenharmony_ci TNode<JSTypedArray> array, TNode<UintPtrT> index) { 1351cb0ef41Sopenharmony_ci // In Debug mode, we re-validate the index as a sanity check because ToInteger 1361cb0ef41Sopenharmony_ci // above calls out to JavaScript. Atomics work on ArrayBuffers, which may be 1371cb0ef41Sopenharmony_ci // detached, and detachment state must be checked and throw before this 1381cb0ef41Sopenharmony_ci // check. The length cannot change. 1391cb0ef41Sopenharmony_ci // 1401cb0ef41Sopenharmony_ci // This function must always be called after ValidateIntegerTypedArray, which 1411cb0ef41Sopenharmony_ci // will ensure that LoadJSArrayBufferViewBuffer will not be null. 1421cb0ef41Sopenharmony_ci CSA_DCHECK(this, Word32BinaryNot( 1431cb0ef41Sopenharmony_ci IsDetachedBuffer(LoadJSArrayBufferViewBuffer(array)))); 1441cb0ef41Sopenharmony_ci CSA_DCHECK(this, UintPtrLessThan(index, LoadJSTypedArrayLength(array))); 1451cb0ef41Sopenharmony_ci} 1461cb0ef41Sopenharmony_ci 1471cb0ef41Sopenharmony_ciTNode<BigInt> SharedArrayBufferBuiltinsAssembler::BigIntFromSigned64( 1481cb0ef41Sopenharmony_ci TNode<AtomicInt64> signed64) { 1491cb0ef41Sopenharmony_ci#if defined(V8_HOST_ARCH_32_BIT) 1501cb0ef41Sopenharmony_ci TNode<IntPtrT> low = Projection<0>(signed64); 1511cb0ef41Sopenharmony_ci TNode<IntPtrT> high = Projection<1>(signed64); 1521cb0ef41Sopenharmony_ci return BigIntFromInt32Pair(low, high); 1531cb0ef41Sopenharmony_ci#else 1541cb0ef41Sopenharmony_ci return BigIntFromInt64(signed64); 1551cb0ef41Sopenharmony_ci#endif 1561cb0ef41Sopenharmony_ci} 1571cb0ef41Sopenharmony_ci 1581cb0ef41Sopenharmony_ciTNode<BigInt> SharedArrayBufferBuiltinsAssembler::BigIntFromUnsigned64( 1591cb0ef41Sopenharmony_ci TNode<AtomicUint64> unsigned64) { 1601cb0ef41Sopenharmony_ci#if defined(V8_HOST_ARCH_32_BIT) 1611cb0ef41Sopenharmony_ci TNode<UintPtrT> low = Projection<0>(unsigned64); 1621cb0ef41Sopenharmony_ci TNode<UintPtrT> high = Projection<1>(unsigned64); 1631cb0ef41Sopenharmony_ci return BigIntFromUint32Pair(low, high); 1641cb0ef41Sopenharmony_ci#else 1651cb0ef41Sopenharmony_ci return BigIntFromUint64(unsigned64); 1661cb0ef41Sopenharmony_ci#endif 1671cb0ef41Sopenharmony_ci} 1681cb0ef41Sopenharmony_ci 1691cb0ef41Sopenharmony_ci// https://tc39.es/ecma262/#sec-atomicload 1701cb0ef41Sopenharmony_ciTF_BUILTIN(AtomicsLoad, SharedArrayBufferBuiltinsAssembler) { 1711cb0ef41Sopenharmony_ci auto maybe_array_or_shared_struct = 1721cb0ef41Sopenharmony_ci Parameter<Object>(Descriptor::kArrayOrSharedStruct); 1731cb0ef41Sopenharmony_ci auto index_or_field_name = Parameter<Object>(Descriptor::kIndexOrFieldName); 1741cb0ef41Sopenharmony_ci auto context = Parameter<Context>(Descriptor::kContext); 1751cb0ef41Sopenharmony_ci 1761cb0ef41Sopenharmony_ci Label shared_struct(this); 1771cb0ef41Sopenharmony_ci GotoIf(IsJSSharedStruct(maybe_array_or_shared_struct), &shared_struct); 1781cb0ef41Sopenharmony_ci 1791cb0ef41Sopenharmony_ci // 1. Let buffer be ? ValidateIntegerTypedArray(typedArray). 1801cb0ef41Sopenharmony_ci Label detached(this); 1811cb0ef41Sopenharmony_ci TNode<Int32T> elements_kind; 1821cb0ef41Sopenharmony_ci TNode<RawPtrT> backing_store; 1831cb0ef41Sopenharmony_ci TNode<JSArrayBuffer> array_buffer = 1841cb0ef41Sopenharmony_ci ValidateIntegerTypedArray(maybe_array_or_shared_struct, context, 1851cb0ef41Sopenharmony_ci &elements_kind, &backing_store, &detached); 1861cb0ef41Sopenharmony_ci TNode<JSTypedArray> array = CAST(maybe_array_or_shared_struct); 1871cb0ef41Sopenharmony_ci 1881cb0ef41Sopenharmony_ci // 2. Let i be ? ValidateAtomicAccess(typedArray, index). 1891cb0ef41Sopenharmony_ci TNode<UintPtrT> index_word = 1901cb0ef41Sopenharmony_ci ValidateAtomicAccess(array, index_or_field_name, context); 1911cb0ef41Sopenharmony_ci 1921cb0ef41Sopenharmony_ci // 3. If IsDetachedBuffer(buffer) is true, throw a TypeError exception. 1931cb0ef41Sopenharmony_ci // 4. NOTE: The above check is not redundant with the check in 1941cb0ef41Sopenharmony_ci // ValidateIntegerTypedArray because the call to ValidateAtomicAccess on the 1951cb0ef41Sopenharmony_ci // preceding line can have arbitrary side effects, which could cause the 1961cb0ef41Sopenharmony_ci // buffer to become detached. 1971cb0ef41Sopenharmony_ci GotoIf(IsDetachedBuffer(array_buffer), &detached); 1981cb0ef41Sopenharmony_ci 1991cb0ef41Sopenharmony_ci // Steps 5-10. 2001cb0ef41Sopenharmony_ci // 2011cb0ef41Sopenharmony_ci // (Not copied from ecma262 due to the axiomatic nature of the memory model.) 2021cb0ef41Sopenharmony_ci Label i8(this), u8(this), i16(this), u16(this), i32(this), u32(this), 2031cb0ef41Sopenharmony_ci i64(this), u64(this), other(this); 2041cb0ef41Sopenharmony_ci int32_t case_values[] = { 2051cb0ef41Sopenharmony_ci INT8_ELEMENTS, UINT8_ELEMENTS, INT16_ELEMENTS, UINT16_ELEMENTS, 2061cb0ef41Sopenharmony_ci INT32_ELEMENTS, UINT32_ELEMENTS, BIGINT64_ELEMENTS, BIGUINT64_ELEMENTS, 2071cb0ef41Sopenharmony_ci }; 2081cb0ef41Sopenharmony_ci Label* case_labels[] = {&i8, &u8, &i16, &u16, &i32, &u32, &i64, &u64}; 2091cb0ef41Sopenharmony_ci Switch(elements_kind, &other, case_values, case_labels, 2101cb0ef41Sopenharmony_ci arraysize(case_labels)); 2111cb0ef41Sopenharmony_ci 2121cb0ef41Sopenharmony_ci BIND(&i8); 2131cb0ef41Sopenharmony_ci Return(SmiFromInt32(AtomicLoad<Int8T>(AtomicMemoryOrder::kSeqCst, 2141cb0ef41Sopenharmony_ci backing_store, index_word))); 2151cb0ef41Sopenharmony_ci 2161cb0ef41Sopenharmony_ci BIND(&u8); 2171cb0ef41Sopenharmony_ci Return(SmiFromInt32(AtomicLoad<Uint8T>(AtomicMemoryOrder::kSeqCst, 2181cb0ef41Sopenharmony_ci backing_store, index_word))); 2191cb0ef41Sopenharmony_ci 2201cb0ef41Sopenharmony_ci BIND(&i16); 2211cb0ef41Sopenharmony_ci Return(SmiFromInt32(AtomicLoad<Int16T>( 2221cb0ef41Sopenharmony_ci AtomicMemoryOrder::kSeqCst, backing_store, WordShl(index_word, 1)))); 2231cb0ef41Sopenharmony_ci 2241cb0ef41Sopenharmony_ci BIND(&u16); 2251cb0ef41Sopenharmony_ci Return(SmiFromInt32(AtomicLoad<Uint16T>( 2261cb0ef41Sopenharmony_ci AtomicMemoryOrder::kSeqCst, backing_store, WordShl(index_word, 1)))); 2271cb0ef41Sopenharmony_ci 2281cb0ef41Sopenharmony_ci BIND(&i32); 2291cb0ef41Sopenharmony_ci Return(ChangeInt32ToTagged(AtomicLoad<Int32T>( 2301cb0ef41Sopenharmony_ci AtomicMemoryOrder::kSeqCst, backing_store, WordShl(index_word, 2)))); 2311cb0ef41Sopenharmony_ci 2321cb0ef41Sopenharmony_ci BIND(&u32); 2331cb0ef41Sopenharmony_ci Return(ChangeUint32ToTagged(AtomicLoad<Uint32T>( 2341cb0ef41Sopenharmony_ci AtomicMemoryOrder::kSeqCst, backing_store, WordShl(index_word, 2)))); 2351cb0ef41Sopenharmony_ci#if V8_TARGET_ARCH_MIPS && !_MIPS_ARCH_MIPS32R6 2361cb0ef41Sopenharmony_ci BIND(&i64); 2371cb0ef41Sopenharmony_ci Goto(&u64); 2381cb0ef41Sopenharmony_ci 2391cb0ef41Sopenharmony_ci BIND(&u64); 2401cb0ef41Sopenharmony_ci { 2411cb0ef41Sopenharmony_ci TNode<Number> index_number = ChangeUintPtrToTagged(index_word); 2421cb0ef41Sopenharmony_ci Return(CallRuntime(Runtime::kAtomicsLoad64, context, array, index_number)); 2431cb0ef41Sopenharmony_ci } 2441cb0ef41Sopenharmony_ci#else 2451cb0ef41Sopenharmony_ci BIND(&i64); 2461cb0ef41Sopenharmony_ci Return(BigIntFromSigned64(AtomicLoad64<AtomicInt64>( 2471cb0ef41Sopenharmony_ci AtomicMemoryOrder::kSeqCst, backing_store, WordShl(index_word, 3)))); 2481cb0ef41Sopenharmony_ci 2491cb0ef41Sopenharmony_ci BIND(&u64); 2501cb0ef41Sopenharmony_ci Return(BigIntFromUnsigned64(AtomicLoad64<AtomicUint64>( 2511cb0ef41Sopenharmony_ci AtomicMemoryOrder::kSeqCst, backing_store, WordShl(index_word, 3)))); 2521cb0ef41Sopenharmony_ci#endif 2531cb0ef41Sopenharmony_ci 2541cb0ef41Sopenharmony_ci // This shouldn't happen, we've already validated the type. 2551cb0ef41Sopenharmony_ci BIND(&other); 2561cb0ef41Sopenharmony_ci Unreachable(); 2571cb0ef41Sopenharmony_ci 2581cb0ef41Sopenharmony_ci BIND(&detached); 2591cb0ef41Sopenharmony_ci { 2601cb0ef41Sopenharmony_ci ThrowTypeError(context, MessageTemplate::kDetachedOperation, 2611cb0ef41Sopenharmony_ci "Atomics.load"); 2621cb0ef41Sopenharmony_ci } 2631cb0ef41Sopenharmony_ci 2641cb0ef41Sopenharmony_ci BIND(&shared_struct); 2651cb0ef41Sopenharmony_ci { 2661cb0ef41Sopenharmony_ci Return(CallRuntime(Runtime::kAtomicsLoadSharedStructField, context, 2671cb0ef41Sopenharmony_ci maybe_array_or_shared_struct, index_or_field_name)); 2681cb0ef41Sopenharmony_ci } 2691cb0ef41Sopenharmony_ci} 2701cb0ef41Sopenharmony_ci 2711cb0ef41Sopenharmony_ci// https://tc39.es/ecma262/#sec-atomics.store 2721cb0ef41Sopenharmony_ciTF_BUILTIN(AtomicsStore, SharedArrayBufferBuiltinsAssembler) { 2731cb0ef41Sopenharmony_ci auto maybe_array_or_shared_struct = 2741cb0ef41Sopenharmony_ci Parameter<Object>(Descriptor::kArrayOrSharedStruct); 2751cb0ef41Sopenharmony_ci auto index_or_field_name = Parameter<Object>(Descriptor::kIndexOrFieldName); 2761cb0ef41Sopenharmony_ci auto value = Parameter<Object>(Descriptor::kValue); 2771cb0ef41Sopenharmony_ci auto context = Parameter<Context>(Descriptor::kContext); 2781cb0ef41Sopenharmony_ci 2791cb0ef41Sopenharmony_ci Label shared_struct(this); 2801cb0ef41Sopenharmony_ci GotoIf(IsJSSharedStruct(maybe_array_or_shared_struct), &shared_struct); 2811cb0ef41Sopenharmony_ci 2821cb0ef41Sopenharmony_ci // 1. Let buffer be ? ValidateIntegerTypedArray(typedArray). 2831cb0ef41Sopenharmony_ci Label detached(this); 2841cb0ef41Sopenharmony_ci TNode<Int32T> elements_kind; 2851cb0ef41Sopenharmony_ci TNode<RawPtrT> backing_store; 2861cb0ef41Sopenharmony_ci TNode<JSArrayBuffer> array_buffer = 2871cb0ef41Sopenharmony_ci ValidateIntegerTypedArray(maybe_array_or_shared_struct, context, 2881cb0ef41Sopenharmony_ci &elements_kind, &backing_store, &detached); 2891cb0ef41Sopenharmony_ci TNode<JSTypedArray> array = CAST(maybe_array_or_shared_struct); 2901cb0ef41Sopenharmony_ci 2911cb0ef41Sopenharmony_ci // 2. Let i be ? ValidateAtomicAccess(typedArray, index). 2921cb0ef41Sopenharmony_ci TNode<UintPtrT> index_word = 2931cb0ef41Sopenharmony_ci ValidateAtomicAccess(array, index_or_field_name, context); 2941cb0ef41Sopenharmony_ci 2951cb0ef41Sopenharmony_ci Label u8(this), u16(this), u32(this), u64(this), other(this); 2961cb0ef41Sopenharmony_ci 2971cb0ef41Sopenharmony_ci // 3. Let arrayTypeName be typedArray.[[TypedArrayName]]. 2981cb0ef41Sopenharmony_ci // 4. If arrayTypeName is "BigUint64Array" or "BigInt64Array", 2991cb0ef41Sopenharmony_ci // let v be ? ToBigInt(value). 3001cb0ef41Sopenharmony_ci STATIC_ASSERT(BIGINT64_ELEMENTS > INT32_ELEMENTS); 3011cb0ef41Sopenharmony_ci STATIC_ASSERT(BIGUINT64_ELEMENTS > INT32_ELEMENTS); 3021cb0ef41Sopenharmony_ci GotoIf(Int32GreaterThan(elements_kind, Int32Constant(INT32_ELEMENTS)), &u64); 3031cb0ef41Sopenharmony_ci 3041cb0ef41Sopenharmony_ci // 5. Otherwise, let v be ? ToInteger(value). 3051cb0ef41Sopenharmony_ci TNode<Number> value_integer = ToInteger_Inline(context, value); 3061cb0ef41Sopenharmony_ci 3071cb0ef41Sopenharmony_ci // 6. If IsDetachedBuffer(buffer) is true, throw a TypeError exception. 3081cb0ef41Sopenharmony_ci // 7. NOTE: The above check is not redundant with the check in 3091cb0ef41Sopenharmony_ci // ValidateIntegerTypedArray because the call to ToBigInt or ToInteger on the 3101cb0ef41Sopenharmony_ci // preceding lines can have arbitrary side effects, which could cause the 3111cb0ef41Sopenharmony_ci // buffer to become detached. 3121cb0ef41Sopenharmony_ci GotoIf(IsDetachedBuffer(array_buffer), &detached); 3131cb0ef41Sopenharmony_ci 3141cb0ef41Sopenharmony_ci TNode<Word32T> value_word32 = TruncateTaggedToWord32(context, value_integer); 3151cb0ef41Sopenharmony_ci 3161cb0ef41Sopenharmony_ci DebugCheckAtomicIndex(array, index_word); 3171cb0ef41Sopenharmony_ci 3181cb0ef41Sopenharmony_ci // Steps 8-13. 3191cb0ef41Sopenharmony_ci // 3201cb0ef41Sopenharmony_ci // (Not copied from ecma262 due to the axiomatic nature of the memory model.) 3211cb0ef41Sopenharmony_ci int32_t case_values[] = { 3221cb0ef41Sopenharmony_ci INT8_ELEMENTS, UINT8_ELEMENTS, INT16_ELEMENTS, 3231cb0ef41Sopenharmony_ci UINT16_ELEMENTS, INT32_ELEMENTS, UINT32_ELEMENTS, 3241cb0ef41Sopenharmony_ci }; 3251cb0ef41Sopenharmony_ci Label* case_labels[] = {&u8, &u8, &u16, &u16, &u32, &u32}; 3261cb0ef41Sopenharmony_ci Switch(elements_kind, &other, case_values, case_labels, 3271cb0ef41Sopenharmony_ci arraysize(case_labels)); 3281cb0ef41Sopenharmony_ci 3291cb0ef41Sopenharmony_ci BIND(&u8); 3301cb0ef41Sopenharmony_ci AtomicStore(MachineRepresentation::kWord8, AtomicMemoryOrder::kSeqCst, 3311cb0ef41Sopenharmony_ci backing_store, index_word, value_word32); 3321cb0ef41Sopenharmony_ci Return(value_integer); 3331cb0ef41Sopenharmony_ci 3341cb0ef41Sopenharmony_ci BIND(&u16); 3351cb0ef41Sopenharmony_ci AtomicStore(MachineRepresentation::kWord16, AtomicMemoryOrder::kSeqCst, 3361cb0ef41Sopenharmony_ci backing_store, WordShl(index_word, 1), value_word32); 3371cb0ef41Sopenharmony_ci Return(value_integer); 3381cb0ef41Sopenharmony_ci 3391cb0ef41Sopenharmony_ci BIND(&u32); 3401cb0ef41Sopenharmony_ci AtomicStore(MachineRepresentation::kWord32, AtomicMemoryOrder::kSeqCst, 3411cb0ef41Sopenharmony_ci backing_store, WordShl(index_word, 2), value_word32); 3421cb0ef41Sopenharmony_ci Return(value_integer); 3431cb0ef41Sopenharmony_ci 3441cb0ef41Sopenharmony_ci BIND(&u64); 3451cb0ef41Sopenharmony_ci#if V8_TARGET_ARCH_MIPS && !_MIPS_ARCH_MIPS32R6 3461cb0ef41Sopenharmony_ci TNode<Number> index_number = ChangeUintPtrToTagged(index_word); 3471cb0ef41Sopenharmony_ci Return(CallRuntime(Runtime::kAtomicsStore64, context, array, index_number, 3481cb0ef41Sopenharmony_ci value)); 3491cb0ef41Sopenharmony_ci#else 3501cb0ef41Sopenharmony_ci // 4. If arrayTypeName is "BigUint64Array" or "BigInt64Array", 3511cb0ef41Sopenharmony_ci // let v be ? ToBigInt(value). 3521cb0ef41Sopenharmony_ci TNode<BigInt> value_bigint = ToBigInt(context, value); 3531cb0ef41Sopenharmony_ci 3541cb0ef41Sopenharmony_ci // 6. If IsDetachedBuffer(buffer) is true, throw a TypeError exception. 3551cb0ef41Sopenharmony_ci GotoIf(IsDetachedBuffer(array_buffer), &detached); 3561cb0ef41Sopenharmony_ci 3571cb0ef41Sopenharmony_ci DebugCheckAtomicIndex(array, index_word); 3581cb0ef41Sopenharmony_ci 3591cb0ef41Sopenharmony_ci TVARIABLE(UintPtrT, var_low); 3601cb0ef41Sopenharmony_ci TVARIABLE(UintPtrT, var_high); 3611cb0ef41Sopenharmony_ci BigIntToRawBytes(value_bigint, &var_low, &var_high); 3621cb0ef41Sopenharmony_ci TNode<UintPtrT> high = Is64() ? TNode<UintPtrT>() : var_high.value(); 3631cb0ef41Sopenharmony_ci AtomicStore64(AtomicMemoryOrder::kSeqCst, backing_store, 3641cb0ef41Sopenharmony_ci WordShl(index_word, 3), var_low.value(), high); 3651cb0ef41Sopenharmony_ci Return(value_bigint); 3661cb0ef41Sopenharmony_ci#endif 3671cb0ef41Sopenharmony_ci 3681cb0ef41Sopenharmony_ci // This shouldn't happen, we've already validated the type. 3691cb0ef41Sopenharmony_ci BIND(&other); 3701cb0ef41Sopenharmony_ci Unreachable(); 3711cb0ef41Sopenharmony_ci 3721cb0ef41Sopenharmony_ci BIND(&detached); 3731cb0ef41Sopenharmony_ci { 3741cb0ef41Sopenharmony_ci ThrowTypeError(context, MessageTemplate::kDetachedOperation, 3751cb0ef41Sopenharmony_ci "Atomics.store"); 3761cb0ef41Sopenharmony_ci } 3771cb0ef41Sopenharmony_ci 3781cb0ef41Sopenharmony_ci BIND(&shared_struct); 3791cb0ef41Sopenharmony_ci { 3801cb0ef41Sopenharmony_ci Return(CallRuntime(Runtime::kAtomicsStoreSharedStructField, context, 3811cb0ef41Sopenharmony_ci maybe_array_or_shared_struct, index_or_field_name, 3821cb0ef41Sopenharmony_ci value)); 3831cb0ef41Sopenharmony_ci } 3841cb0ef41Sopenharmony_ci} 3851cb0ef41Sopenharmony_ci 3861cb0ef41Sopenharmony_ci// https://tc39.es/ecma262/#sec-atomics.exchange 3871cb0ef41Sopenharmony_ciTF_BUILTIN(AtomicsExchange, SharedArrayBufferBuiltinsAssembler) { 3881cb0ef41Sopenharmony_ci auto maybe_array_or_shared_struct = 3891cb0ef41Sopenharmony_ci Parameter<Object>(Descriptor::kArrayOrSharedStruct); 3901cb0ef41Sopenharmony_ci auto index_or_field_name = Parameter<Object>(Descriptor::kIndexOrFieldName); 3911cb0ef41Sopenharmony_ci auto value = Parameter<Object>(Descriptor::kValue); 3921cb0ef41Sopenharmony_ci auto context = Parameter<Context>(Descriptor::kContext); 3931cb0ef41Sopenharmony_ci 3941cb0ef41Sopenharmony_ci Label shared_struct(this); 3951cb0ef41Sopenharmony_ci GotoIf(IsJSSharedStruct(maybe_array_or_shared_struct), &shared_struct); 3961cb0ef41Sopenharmony_ci 3971cb0ef41Sopenharmony_ci // Inlines AtomicReadModifyWrite 3981cb0ef41Sopenharmony_ci // https://tc39.es/ecma262/#sec-atomicreadmodifywrite 3991cb0ef41Sopenharmony_ci 4001cb0ef41Sopenharmony_ci // 1. Let buffer be ? ValidateIntegerTypedArray(typedArray). 4011cb0ef41Sopenharmony_ci Label detached(this); 4021cb0ef41Sopenharmony_ci TNode<Int32T> elements_kind; 4031cb0ef41Sopenharmony_ci TNode<RawPtrT> backing_store; 4041cb0ef41Sopenharmony_ci TNode<JSArrayBuffer> array_buffer = 4051cb0ef41Sopenharmony_ci ValidateIntegerTypedArray(maybe_array_or_shared_struct, context, 4061cb0ef41Sopenharmony_ci &elements_kind, &backing_store, &detached); 4071cb0ef41Sopenharmony_ci TNode<JSTypedArray> array = CAST(maybe_array_or_shared_struct); 4081cb0ef41Sopenharmony_ci 4091cb0ef41Sopenharmony_ci // 2. Let i be ? ValidateAtomicAccess(typedArray, index). 4101cb0ef41Sopenharmony_ci TNode<UintPtrT> index_word = 4111cb0ef41Sopenharmony_ci ValidateAtomicAccess(array, index_or_field_name, context); 4121cb0ef41Sopenharmony_ci 4131cb0ef41Sopenharmony_ci#if V8_TARGET_ARCH_MIPS || V8_TARGET_ARCH_MIPS64 || V8_TARGET_ARCH_RISCV64 4141cb0ef41Sopenharmony_ci USE(array_buffer); 4151cb0ef41Sopenharmony_ci TNode<Number> index_number = ChangeUintPtrToTagged(index_word); 4161cb0ef41Sopenharmony_ci Return(CallRuntime(Runtime::kAtomicsExchange, context, array, index_number, 4171cb0ef41Sopenharmony_ci value)); 4181cb0ef41Sopenharmony_ci#else 4191cb0ef41Sopenharmony_ci 4201cb0ef41Sopenharmony_ci Label i8(this), u8(this), i16(this), u16(this), i32(this), u32(this), 4211cb0ef41Sopenharmony_ci i64(this), u64(this), big(this), other(this); 4221cb0ef41Sopenharmony_ci 4231cb0ef41Sopenharmony_ci // 3. Let arrayTypeName be typedArray.[[TypedArrayName]]. 4241cb0ef41Sopenharmony_ci // 4. If typedArray.[[ContentType]] is BigInt, let v be ? ToBigInt(value). 4251cb0ef41Sopenharmony_ci STATIC_ASSERT(BIGINT64_ELEMENTS > INT32_ELEMENTS); 4261cb0ef41Sopenharmony_ci STATIC_ASSERT(BIGUINT64_ELEMENTS > INT32_ELEMENTS); 4271cb0ef41Sopenharmony_ci GotoIf(Int32GreaterThan(elements_kind, Int32Constant(INT32_ELEMENTS)), &big); 4281cb0ef41Sopenharmony_ci 4291cb0ef41Sopenharmony_ci // 5. Otherwise, let v be ? ToInteger(value). 4301cb0ef41Sopenharmony_ci TNode<Number> value_integer = ToInteger_Inline(context, value); 4311cb0ef41Sopenharmony_ci 4321cb0ef41Sopenharmony_ci // 6. If IsDetachedBuffer(buffer) is true, throw a TypeError exception. 4331cb0ef41Sopenharmony_ci // 7. NOTE: The above check is not redundant with the check in 4341cb0ef41Sopenharmony_ci // ValidateIntegerTypedArray because the call to ToBigInt or ToInteger on the 4351cb0ef41Sopenharmony_ci // preceding lines can have arbitrary side effects, which could cause the 4361cb0ef41Sopenharmony_ci // buffer to become detached. 4371cb0ef41Sopenharmony_ci GotoIf(IsDetachedBuffer(array_buffer), &detached); 4381cb0ef41Sopenharmony_ci 4391cb0ef41Sopenharmony_ci DebugCheckAtomicIndex(array, index_word); 4401cb0ef41Sopenharmony_ci 4411cb0ef41Sopenharmony_ci TNode<Word32T> value_word32 = TruncateTaggedToWord32(context, value_integer); 4421cb0ef41Sopenharmony_ci 4431cb0ef41Sopenharmony_ci // Steps 8-12. 4441cb0ef41Sopenharmony_ci // 4451cb0ef41Sopenharmony_ci // (Not copied from ecma262 due to the axiomatic nature of the memory model.) 4461cb0ef41Sopenharmony_ci int32_t case_values[] = { 4471cb0ef41Sopenharmony_ci INT8_ELEMENTS, UINT8_ELEMENTS, INT16_ELEMENTS, 4481cb0ef41Sopenharmony_ci UINT16_ELEMENTS, INT32_ELEMENTS, UINT32_ELEMENTS, 4491cb0ef41Sopenharmony_ci }; 4501cb0ef41Sopenharmony_ci Label* case_labels[] = { 4511cb0ef41Sopenharmony_ci &i8, &u8, &i16, &u16, &i32, &u32, 4521cb0ef41Sopenharmony_ci }; 4531cb0ef41Sopenharmony_ci Switch(elements_kind, &other, case_values, case_labels, 4541cb0ef41Sopenharmony_ci arraysize(case_labels)); 4551cb0ef41Sopenharmony_ci 4561cb0ef41Sopenharmony_ci BIND(&i8); 4571cb0ef41Sopenharmony_ci Return(SmiFromInt32(Signed(AtomicExchange(MachineType::Int8(), backing_store, 4581cb0ef41Sopenharmony_ci index_word, value_word32)))); 4591cb0ef41Sopenharmony_ci 4601cb0ef41Sopenharmony_ci BIND(&u8); 4611cb0ef41Sopenharmony_ci Return(SmiFromInt32(Signed(AtomicExchange(MachineType::Uint8(), backing_store, 4621cb0ef41Sopenharmony_ci index_word, value_word32)))); 4631cb0ef41Sopenharmony_ci 4641cb0ef41Sopenharmony_ci BIND(&i16); 4651cb0ef41Sopenharmony_ci Return(SmiFromInt32(Signed( 4661cb0ef41Sopenharmony_ci AtomicExchange(MachineType::Int16(), backing_store, 4671cb0ef41Sopenharmony_ci WordShl(index_word, UintPtrConstant(1)), value_word32)))); 4681cb0ef41Sopenharmony_ci 4691cb0ef41Sopenharmony_ci BIND(&u16); 4701cb0ef41Sopenharmony_ci Return(SmiFromInt32(Signed( 4711cb0ef41Sopenharmony_ci AtomicExchange(MachineType::Uint16(), backing_store, 4721cb0ef41Sopenharmony_ci WordShl(index_word, UintPtrConstant(1)), value_word32)))); 4731cb0ef41Sopenharmony_ci 4741cb0ef41Sopenharmony_ci BIND(&i32); 4751cb0ef41Sopenharmony_ci Return(ChangeInt32ToTagged(Signed( 4761cb0ef41Sopenharmony_ci AtomicExchange(MachineType::Int32(), backing_store, 4771cb0ef41Sopenharmony_ci WordShl(index_word, UintPtrConstant(2)), value_word32)))); 4781cb0ef41Sopenharmony_ci 4791cb0ef41Sopenharmony_ci BIND(&u32); 4801cb0ef41Sopenharmony_ci Return(ChangeUint32ToTagged(Unsigned( 4811cb0ef41Sopenharmony_ci AtomicExchange(MachineType::Uint32(), backing_store, 4821cb0ef41Sopenharmony_ci WordShl(index_word, UintPtrConstant(2)), value_word32)))); 4831cb0ef41Sopenharmony_ci 4841cb0ef41Sopenharmony_ci BIND(&big); 4851cb0ef41Sopenharmony_ci // 4. If typedArray.[[ContentType]] is BigInt, let v be ? ToBigInt(value). 4861cb0ef41Sopenharmony_ci TNode<BigInt> value_bigint = ToBigInt(context, value); 4871cb0ef41Sopenharmony_ci 4881cb0ef41Sopenharmony_ci // 6. If IsDetachedBuffer(buffer) is true, throw a TypeError exception. 4891cb0ef41Sopenharmony_ci GotoIf(IsDetachedBuffer(array_buffer), &detached); 4901cb0ef41Sopenharmony_ci 4911cb0ef41Sopenharmony_ci DebugCheckAtomicIndex(array, index_word); 4921cb0ef41Sopenharmony_ci 4931cb0ef41Sopenharmony_ci TVARIABLE(UintPtrT, var_low); 4941cb0ef41Sopenharmony_ci TVARIABLE(UintPtrT, var_high); 4951cb0ef41Sopenharmony_ci BigIntToRawBytes(value_bigint, &var_low, &var_high); 4961cb0ef41Sopenharmony_ci TNode<UintPtrT> high = Is64() ? TNode<UintPtrT>() : var_high.value(); 4971cb0ef41Sopenharmony_ci GotoIf(Word32Equal(elements_kind, Int32Constant(BIGINT64_ELEMENTS)), &i64); 4981cb0ef41Sopenharmony_ci GotoIf(Word32Equal(elements_kind, Int32Constant(BIGUINT64_ELEMENTS)), &u64); 4991cb0ef41Sopenharmony_ci Unreachable(); 5001cb0ef41Sopenharmony_ci 5011cb0ef41Sopenharmony_ci BIND(&i64); 5021cb0ef41Sopenharmony_ci Return(BigIntFromSigned64(AtomicExchange64<AtomicInt64>( 5031cb0ef41Sopenharmony_ci backing_store, WordShl(index_word, UintPtrConstant(3)), var_low.value(), 5041cb0ef41Sopenharmony_ci high))); 5051cb0ef41Sopenharmony_ci 5061cb0ef41Sopenharmony_ci BIND(&u64); 5071cb0ef41Sopenharmony_ci Return(BigIntFromUnsigned64(AtomicExchange64<AtomicUint64>( 5081cb0ef41Sopenharmony_ci backing_store, WordShl(index_word, UintPtrConstant(3)), var_low.value(), 5091cb0ef41Sopenharmony_ci high))); 5101cb0ef41Sopenharmony_ci 5111cb0ef41Sopenharmony_ci // This shouldn't happen, we've already validated the type. 5121cb0ef41Sopenharmony_ci BIND(&other); 5131cb0ef41Sopenharmony_ci Unreachable(); 5141cb0ef41Sopenharmony_ci#endif // V8_TARGET_ARCH_MIPS || V8_TARGET_ARCH_MIPS64 || 5151cb0ef41Sopenharmony_ci // V8_TARGET_ARCH_RISCV64 5161cb0ef41Sopenharmony_ci 5171cb0ef41Sopenharmony_ci BIND(&detached); 5181cb0ef41Sopenharmony_ci { 5191cb0ef41Sopenharmony_ci ThrowTypeError(context, MessageTemplate::kDetachedOperation, 5201cb0ef41Sopenharmony_ci "Atomics.exchange"); 5211cb0ef41Sopenharmony_ci } 5221cb0ef41Sopenharmony_ci 5231cb0ef41Sopenharmony_ci BIND(&shared_struct); 5241cb0ef41Sopenharmony_ci { 5251cb0ef41Sopenharmony_ci Return(CallRuntime(Runtime::kAtomicsExchangeSharedStructField, context, 5261cb0ef41Sopenharmony_ci maybe_array_or_shared_struct, index_or_field_name, 5271cb0ef41Sopenharmony_ci value)); 5281cb0ef41Sopenharmony_ci } 5291cb0ef41Sopenharmony_ci} 5301cb0ef41Sopenharmony_ci 5311cb0ef41Sopenharmony_ci// https://tc39.es/ecma262/#sec-atomics.compareexchange 5321cb0ef41Sopenharmony_ciTF_BUILTIN(AtomicsCompareExchange, SharedArrayBufferBuiltinsAssembler) { 5331cb0ef41Sopenharmony_ci auto maybe_array = Parameter<Object>(Descriptor::kArray); 5341cb0ef41Sopenharmony_ci auto index = Parameter<Object>(Descriptor::kIndex); 5351cb0ef41Sopenharmony_ci auto old_value = Parameter<Object>(Descriptor::kOldValue); 5361cb0ef41Sopenharmony_ci auto new_value = Parameter<Object>(Descriptor::kNewValue); 5371cb0ef41Sopenharmony_ci auto context = Parameter<Context>(Descriptor::kContext); 5381cb0ef41Sopenharmony_ci 5391cb0ef41Sopenharmony_ci // 1. Let buffer be ? ValidateIntegerTypedArray(typedArray). 5401cb0ef41Sopenharmony_ci Label detached(this); 5411cb0ef41Sopenharmony_ci TNode<Int32T> elements_kind; 5421cb0ef41Sopenharmony_ci TNode<RawPtrT> backing_store; 5431cb0ef41Sopenharmony_ci TNode<JSArrayBuffer> array_buffer = ValidateIntegerTypedArray( 5441cb0ef41Sopenharmony_ci maybe_array, context, &elements_kind, &backing_store, &detached); 5451cb0ef41Sopenharmony_ci TNode<JSTypedArray> array = CAST(maybe_array); 5461cb0ef41Sopenharmony_ci 5471cb0ef41Sopenharmony_ci // 2. Let i be ? ValidateAtomicAccess(typedArray, index). 5481cb0ef41Sopenharmony_ci TNode<UintPtrT> index_word = ValidateAtomicAccess(array, index, context); 5491cb0ef41Sopenharmony_ci 5501cb0ef41Sopenharmony_ci#if V8_TARGET_ARCH_MIPS || V8_TARGET_ARCH_MIPS64 || V8_TARGET_ARCH_PPC64 || \ 5511cb0ef41Sopenharmony_ci V8_TARGET_ARCH_PPC || V8_TARGET_ARCH_S390 || V8_TARGET_ARCH_S390X || \ 5521cb0ef41Sopenharmony_ci V8_TARGET_ARCH_RISCV64 5531cb0ef41Sopenharmony_ci USE(array_buffer); 5541cb0ef41Sopenharmony_ci TNode<Number> index_number = ChangeUintPtrToTagged(index_word); 5551cb0ef41Sopenharmony_ci Return(CallRuntime(Runtime::kAtomicsCompareExchange, context, array, 5561cb0ef41Sopenharmony_ci index_number, old_value, new_value)); 5571cb0ef41Sopenharmony_ci#else 5581cb0ef41Sopenharmony_ci Label i8(this), u8(this), i16(this), u16(this), i32(this), u32(this), 5591cb0ef41Sopenharmony_ci i64(this), u64(this), big(this), other(this); 5601cb0ef41Sopenharmony_ci 5611cb0ef41Sopenharmony_ci // 3. Let arrayTypeName be typedArray.[[TypedArrayName]]. 5621cb0ef41Sopenharmony_ci // 4. If typedArray.[[ContentType]] is BigInt, then 5631cb0ef41Sopenharmony_ci // a. Let expected be ? ToBigInt(expectedValue). 5641cb0ef41Sopenharmony_ci // b. Let replacement be ? ToBigInt(replacementValue). 5651cb0ef41Sopenharmony_ci STATIC_ASSERT(BIGINT64_ELEMENTS > INT32_ELEMENTS); 5661cb0ef41Sopenharmony_ci STATIC_ASSERT(BIGUINT64_ELEMENTS > INT32_ELEMENTS); 5671cb0ef41Sopenharmony_ci GotoIf(Int32GreaterThan(elements_kind, Int32Constant(INT32_ELEMENTS)), &big); 5681cb0ef41Sopenharmony_ci 5691cb0ef41Sopenharmony_ci // 5. Else, 5701cb0ef41Sopenharmony_ci // a. Let expected be ? ToInteger(expectedValue). 5711cb0ef41Sopenharmony_ci // b. Let replacement be ? ToInteger(replacementValue). 5721cb0ef41Sopenharmony_ci TNode<Number> old_value_integer = ToInteger_Inline(context, old_value); 5731cb0ef41Sopenharmony_ci TNode<Number> new_value_integer = ToInteger_Inline(context, new_value); 5741cb0ef41Sopenharmony_ci 5751cb0ef41Sopenharmony_ci // 6. If IsDetachedBuffer(buffer) is true, throw a TypeError exception. 5761cb0ef41Sopenharmony_ci // 7. NOTE: The above check is not redundant with the check in 5771cb0ef41Sopenharmony_ci // ValidateIntegerTypedArray because the call to ToBigInt or ToInteger on the 5781cb0ef41Sopenharmony_ci // preceding lines can have arbitrary side effects, which could cause the 5791cb0ef41Sopenharmony_ci // buffer to become detached. 5801cb0ef41Sopenharmony_ci GotoIf(IsDetachedBuffer(array_buffer), &detached); 5811cb0ef41Sopenharmony_ci 5821cb0ef41Sopenharmony_ci DebugCheckAtomicIndex(array, index_word); 5831cb0ef41Sopenharmony_ci 5841cb0ef41Sopenharmony_ci TNode<Word32T> old_value_word32 = 5851cb0ef41Sopenharmony_ci TruncateTaggedToWord32(context, old_value_integer); 5861cb0ef41Sopenharmony_ci TNode<Word32T> new_value_word32 = 5871cb0ef41Sopenharmony_ci TruncateTaggedToWord32(context, new_value_integer); 5881cb0ef41Sopenharmony_ci 5891cb0ef41Sopenharmony_ci // Steps 8-14. 5901cb0ef41Sopenharmony_ci // 5911cb0ef41Sopenharmony_ci // (Not copied from ecma262 due to the axiomatic nature of the memory model.) 5921cb0ef41Sopenharmony_ci int32_t case_values[] = { 5931cb0ef41Sopenharmony_ci INT8_ELEMENTS, UINT8_ELEMENTS, INT16_ELEMENTS, 5941cb0ef41Sopenharmony_ci UINT16_ELEMENTS, INT32_ELEMENTS, UINT32_ELEMENTS, 5951cb0ef41Sopenharmony_ci }; 5961cb0ef41Sopenharmony_ci Label* case_labels[] = { 5971cb0ef41Sopenharmony_ci &i8, &u8, &i16, &u16, &i32, &u32, 5981cb0ef41Sopenharmony_ci }; 5991cb0ef41Sopenharmony_ci Switch(elements_kind, &other, case_values, case_labels, 6001cb0ef41Sopenharmony_ci arraysize(case_labels)); 6011cb0ef41Sopenharmony_ci 6021cb0ef41Sopenharmony_ci BIND(&i8); 6031cb0ef41Sopenharmony_ci Return(SmiFromInt32(Signed( 6041cb0ef41Sopenharmony_ci AtomicCompareExchange(MachineType::Int8(), backing_store, index_word, 6051cb0ef41Sopenharmony_ci old_value_word32, new_value_word32)))); 6061cb0ef41Sopenharmony_ci 6071cb0ef41Sopenharmony_ci BIND(&u8); 6081cb0ef41Sopenharmony_ci Return(SmiFromInt32(Signed( 6091cb0ef41Sopenharmony_ci AtomicCompareExchange(MachineType::Uint8(), backing_store, index_word, 6101cb0ef41Sopenharmony_ci old_value_word32, new_value_word32)))); 6111cb0ef41Sopenharmony_ci 6121cb0ef41Sopenharmony_ci BIND(&i16); 6131cb0ef41Sopenharmony_ci Return(SmiFromInt32(Signed(AtomicCompareExchange( 6141cb0ef41Sopenharmony_ci MachineType::Int16(), backing_store, WordShl(index_word, 1), 6151cb0ef41Sopenharmony_ci old_value_word32, new_value_word32)))); 6161cb0ef41Sopenharmony_ci 6171cb0ef41Sopenharmony_ci BIND(&u16); 6181cb0ef41Sopenharmony_ci Return(SmiFromInt32(Signed(AtomicCompareExchange( 6191cb0ef41Sopenharmony_ci MachineType::Uint16(), backing_store, WordShl(index_word, 1), 6201cb0ef41Sopenharmony_ci old_value_word32, new_value_word32)))); 6211cb0ef41Sopenharmony_ci 6221cb0ef41Sopenharmony_ci BIND(&i32); 6231cb0ef41Sopenharmony_ci Return(ChangeInt32ToTagged(Signed(AtomicCompareExchange( 6241cb0ef41Sopenharmony_ci MachineType::Int32(), backing_store, WordShl(index_word, 2), 6251cb0ef41Sopenharmony_ci old_value_word32, new_value_word32)))); 6261cb0ef41Sopenharmony_ci 6271cb0ef41Sopenharmony_ci BIND(&u32); 6281cb0ef41Sopenharmony_ci Return(ChangeUint32ToTagged(Unsigned(AtomicCompareExchange( 6291cb0ef41Sopenharmony_ci MachineType::Uint32(), backing_store, WordShl(index_word, 2), 6301cb0ef41Sopenharmony_ci old_value_word32, new_value_word32)))); 6311cb0ef41Sopenharmony_ci 6321cb0ef41Sopenharmony_ci BIND(&big); 6331cb0ef41Sopenharmony_ci // 4. If typedArray.[[ContentType]] is BigInt, then 6341cb0ef41Sopenharmony_ci // a. Let expected be ? ToBigInt(expectedValue). 6351cb0ef41Sopenharmony_ci // b. Let replacement be ? ToBigInt(replacementValue). 6361cb0ef41Sopenharmony_ci TNode<BigInt> old_value_bigint = ToBigInt(context, old_value); 6371cb0ef41Sopenharmony_ci TNode<BigInt> new_value_bigint = ToBigInt(context, new_value); 6381cb0ef41Sopenharmony_ci 6391cb0ef41Sopenharmony_ci // 6. If IsDetachedBuffer(buffer) is true, throw a TypeError exception. 6401cb0ef41Sopenharmony_ci GotoIf(IsDetachedBuffer(array_buffer), &detached); 6411cb0ef41Sopenharmony_ci 6421cb0ef41Sopenharmony_ci DebugCheckAtomicIndex(array, index_word); 6431cb0ef41Sopenharmony_ci 6441cb0ef41Sopenharmony_ci TVARIABLE(UintPtrT, var_old_low); 6451cb0ef41Sopenharmony_ci TVARIABLE(UintPtrT, var_old_high); 6461cb0ef41Sopenharmony_ci TVARIABLE(UintPtrT, var_new_low); 6471cb0ef41Sopenharmony_ci TVARIABLE(UintPtrT, var_new_high); 6481cb0ef41Sopenharmony_ci BigIntToRawBytes(old_value_bigint, &var_old_low, &var_old_high); 6491cb0ef41Sopenharmony_ci BigIntToRawBytes(new_value_bigint, &var_new_low, &var_new_high); 6501cb0ef41Sopenharmony_ci TNode<UintPtrT> old_high = Is64() ? TNode<UintPtrT>() : var_old_high.value(); 6511cb0ef41Sopenharmony_ci TNode<UintPtrT> new_high = Is64() ? TNode<UintPtrT>() : var_new_high.value(); 6521cb0ef41Sopenharmony_ci GotoIf(Word32Equal(elements_kind, Int32Constant(BIGINT64_ELEMENTS)), &i64); 6531cb0ef41Sopenharmony_ci GotoIf(Word32Equal(elements_kind, Int32Constant(BIGUINT64_ELEMENTS)), &u64); 6541cb0ef41Sopenharmony_ci Unreachable(); 6551cb0ef41Sopenharmony_ci 6561cb0ef41Sopenharmony_ci BIND(&i64); 6571cb0ef41Sopenharmony_ci // This uses Uint64() intentionally: AtomicCompareExchange is not implemented 6581cb0ef41Sopenharmony_ci // for Int64(), which is fine because the machine instruction only cares 6591cb0ef41Sopenharmony_ci // about words. 6601cb0ef41Sopenharmony_ci Return(BigIntFromSigned64(AtomicCompareExchange64<AtomicInt64>( 6611cb0ef41Sopenharmony_ci backing_store, WordShl(index_word, 3), var_old_low.value(), 6621cb0ef41Sopenharmony_ci var_new_low.value(), old_high, new_high))); 6631cb0ef41Sopenharmony_ci 6641cb0ef41Sopenharmony_ci BIND(&u64); 6651cb0ef41Sopenharmony_ci Return(BigIntFromUnsigned64(AtomicCompareExchange64<AtomicUint64>( 6661cb0ef41Sopenharmony_ci backing_store, WordShl(index_word, 3), var_old_low.value(), 6671cb0ef41Sopenharmony_ci var_new_low.value(), old_high, new_high))); 6681cb0ef41Sopenharmony_ci 6691cb0ef41Sopenharmony_ci // This shouldn't happen, we've already validated the type. 6701cb0ef41Sopenharmony_ci BIND(&other); 6711cb0ef41Sopenharmony_ci Unreachable(); 6721cb0ef41Sopenharmony_ci#endif // V8_TARGET_ARCH_MIPS || V8_TARGET_ARCH_MIPS64 || V8_TARGET_ARCH_PPC64 6731cb0ef41Sopenharmony_ci // || V8_TARGET_ARCH_PPC || V8_TARGET_ARCH_S390 || V8_TARGET_ARCH_S390X 6741cb0ef41Sopenharmony_ci // || V8_TARGET_ARCH_RISCV64 6751cb0ef41Sopenharmony_ci 6761cb0ef41Sopenharmony_ci BIND(&detached); 6771cb0ef41Sopenharmony_ci { 6781cb0ef41Sopenharmony_ci ThrowTypeError(context, MessageTemplate::kDetachedOperation, 6791cb0ef41Sopenharmony_ci "Atomics.store"); 6801cb0ef41Sopenharmony_ci } 6811cb0ef41Sopenharmony_ci} 6821cb0ef41Sopenharmony_ci 6831cb0ef41Sopenharmony_ci#define BINOP_BUILTIN(op, method_name) \ 6841cb0ef41Sopenharmony_ci TF_BUILTIN(Atomics##op, SharedArrayBufferBuiltinsAssembler) { \ 6851cb0ef41Sopenharmony_ci auto array = Parameter<Object>(Descriptor::kArray); \ 6861cb0ef41Sopenharmony_ci auto index = Parameter<Object>(Descriptor::kIndex); \ 6871cb0ef41Sopenharmony_ci auto value = Parameter<Object>(Descriptor::kValue); \ 6881cb0ef41Sopenharmony_ci auto context = Parameter<Context>(Descriptor::kContext); \ 6891cb0ef41Sopenharmony_ci AtomicBinopBuiltinCommon(array, index, value, context, \ 6901cb0ef41Sopenharmony_ci &CodeAssembler::Atomic##op, \ 6911cb0ef41Sopenharmony_ci &CodeAssembler::Atomic##op##64 < AtomicInt64 >, \ 6921cb0ef41Sopenharmony_ci &CodeAssembler::Atomic##op##64 < AtomicUint64 >, \ 6931cb0ef41Sopenharmony_ci Runtime::kAtomics##op, method_name); \ 6941cb0ef41Sopenharmony_ci } 6951cb0ef41Sopenharmony_ci// https://tc39.es/ecma262/#sec-atomics.add 6961cb0ef41Sopenharmony_ciBINOP_BUILTIN(Add, "Atomics.add") 6971cb0ef41Sopenharmony_ci// https://tc39.es/ecma262/#sec-atomics.sub 6981cb0ef41Sopenharmony_ciBINOP_BUILTIN(Sub, "Atomics.sub") 6991cb0ef41Sopenharmony_ci// https://tc39.es/ecma262/#sec-atomics.and 7001cb0ef41Sopenharmony_ciBINOP_BUILTIN(And, "Atomics.and") 7011cb0ef41Sopenharmony_ci// https://tc39.es/ecma262/#sec-atomics.or 7021cb0ef41Sopenharmony_ciBINOP_BUILTIN(Or, "Atomics.or") 7031cb0ef41Sopenharmony_ci// https://tc39.es/ecma262/#sec-atomics.xor 7041cb0ef41Sopenharmony_ciBINOP_BUILTIN(Xor, "Atomics.xor") 7051cb0ef41Sopenharmony_ci#undef BINOP_BUILTIN 7061cb0ef41Sopenharmony_ci 7071cb0ef41Sopenharmony_ci// https://tc39.es/ecma262/#sec-atomicreadmodifywrite 7081cb0ef41Sopenharmony_civoid SharedArrayBufferBuiltinsAssembler::AtomicBinopBuiltinCommon( 7091cb0ef41Sopenharmony_ci TNode<Object> maybe_array, TNode<Object> index, TNode<Object> value, 7101cb0ef41Sopenharmony_ci TNode<Context> context, AssemblerFunction function, 7111cb0ef41Sopenharmony_ci AssemblerFunction64<AtomicInt64> function_int_64, 7121cb0ef41Sopenharmony_ci AssemblerFunction64<AtomicUint64> function_uint_64, 7131cb0ef41Sopenharmony_ci Runtime::FunctionId runtime_function, const char* method_name) { 7141cb0ef41Sopenharmony_ci // 1. Let buffer be ? ValidateIntegerTypedArray(typedArray). 7151cb0ef41Sopenharmony_ci Label detached(this); 7161cb0ef41Sopenharmony_ci TNode<Int32T> elements_kind; 7171cb0ef41Sopenharmony_ci TNode<RawPtrT> backing_store; 7181cb0ef41Sopenharmony_ci TNode<JSArrayBuffer> array_buffer = ValidateIntegerTypedArray( 7191cb0ef41Sopenharmony_ci maybe_array, context, &elements_kind, &backing_store, &detached); 7201cb0ef41Sopenharmony_ci TNode<JSTypedArray> array = CAST(maybe_array); 7211cb0ef41Sopenharmony_ci 7221cb0ef41Sopenharmony_ci // 2. Let i be ? ValidateAtomicAccess(typedArray, index). 7231cb0ef41Sopenharmony_ci TNode<UintPtrT> index_word = ValidateAtomicAccess(array, index, context); 7241cb0ef41Sopenharmony_ci 7251cb0ef41Sopenharmony_ci#if V8_TARGET_ARCH_MIPS || V8_TARGET_ARCH_MIPS64 || V8_TARGET_ARCH_PPC64 || \ 7261cb0ef41Sopenharmony_ci V8_TARGET_ARCH_PPC || V8_TARGET_ARCH_S390 || V8_TARGET_ARCH_S390X || \ 7271cb0ef41Sopenharmony_ci V8_TARGET_ARCH_RISCV64 7281cb0ef41Sopenharmony_ci USE(array_buffer); 7291cb0ef41Sopenharmony_ci TNode<Number> index_number = ChangeUintPtrToTagged(index_word); 7301cb0ef41Sopenharmony_ci Return(CallRuntime(runtime_function, context, array, index_number, value)); 7311cb0ef41Sopenharmony_ci#else 7321cb0ef41Sopenharmony_ci Label i8(this), u8(this), i16(this), u16(this), i32(this), u32(this), 7331cb0ef41Sopenharmony_ci i64(this), u64(this), big(this), other(this); 7341cb0ef41Sopenharmony_ci 7351cb0ef41Sopenharmony_ci // 3. Let arrayTypeName be typedArray.[[TypedArrayName]]. 7361cb0ef41Sopenharmony_ci // 4. If typedArray.[[ContentType]] is BigInt, let v be ? ToBigInt(value). 7371cb0ef41Sopenharmony_ci STATIC_ASSERT(BIGINT64_ELEMENTS > INT32_ELEMENTS); 7381cb0ef41Sopenharmony_ci STATIC_ASSERT(BIGUINT64_ELEMENTS > INT32_ELEMENTS); 7391cb0ef41Sopenharmony_ci GotoIf(Int32GreaterThan(elements_kind, Int32Constant(INT32_ELEMENTS)), &big); 7401cb0ef41Sopenharmony_ci 7411cb0ef41Sopenharmony_ci // 5. Otherwise, let v be ? ToInteger(value). 7421cb0ef41Sopenharmony_ci TNode<Number> value_integer = ToInteger_Inline(context, value); 7431cb0ef41Sopenharmony_ci 7441cb0ef41Sopenharmony_ci // 6. If IsDetachedBuffer(buffer) is true, throw a TypeError exception. 7451cb0ef41Sopenharmony_ci // 7. NOTE: The above check is not redundant with the check in 7461cb0ef41Sopenharmony_ci // ValidateIntegerTypedArray because the call to ToBigInt or ToInteger on the 7471cb0ef41Sopenharmony_ci // preceding lines can have arbitrary side effects, which could cause the 7481cb0ef41Sopenharmony_ci // buffer to become detached. 7491cb0ef41Sopenharmony_ci GotoIf(IsDetachedBuffer(array_buffer), &detached); 7501cb0ef41Sopenharmony_ci 7511cb0ef41Sopenharmony_ci DebugCheckAtomicIndex(array, index_word); 7521cb0ef41Sopenharmony_ci 7531cb0ef41Sopenharmony_ci TNode<Word32T> value_word32 = TruncateTaggedToWord32(context, value_integer); 7541cb0ef41Sopenharmony_ci 7551cb0ef41Sopenharmony_ci // Steps 8-12. 7561cb0ef41Sopenharmony_ci // 7571cb0ef41Sopenharmony_ci // (Not copied from ecma262 due to the axiomatic nature of the memory model.) 7581cb0ef41Sopenharmony_ci int32_t case_values[] = { 7591cb0ef41Sopenharmony_ci INT8_ELEMENTS, UINT8_ELEMENTS, INT16_ELEMENTS, 7601cb0ef41Sopenharmony_ci UINT16_ELEMENTS, INT32_ELEMENTS, UINT32_ELEMENTS, 7611cb0ef41Sopenharmony_ci }; 7621cb0ef41Sopenharmony_ci Label* case_labels[] = { 7631cb0ef41Sopenharmony_ci &i8, &u8, &i16, &u16, &i32, &u32, 7641cb0ef41Sopenharmony_ci }; 7651cb0ef41Sopenharmony_ci Switch(elements_kind, &other, case_values, case_labels, 7661cb0ef41Sopenharmony_ci arraysize(case_labels)); 7671cb0ef41Sopenharmony_ci 7681cb0ef41Sopenharmony_ci BIND(&i8); 7691cb0ef41Sopenharmony_ci Return(SmiFromInt32(Signed((this->*function)( 7701cb0ef41Sopenharmony_ci MachineType::Int8(), backing_store, index_word, value_word32)))); 7711cb0ef41Sopenharmony_ci BIND(&u8); 7721cb0ef41Sopenharmony_ci Return(SmiFromInt32(Signed((this->*function)( 7731cb0ef41Sopenharmony_ci MachineType::Uint8(), backing_store, index_word, value_word32)))); 7741cb0ef41Sopenharmony_ci BIND(&i16); 7751cb0ef41Sopenharmony_ci Return(SmiFromInt32(Signed((this->*function)( 7761cb0ef41Sopenharmony_ci MachineType::Int16(), backing_store, 7771cb0ef41Sopenharmony_ci WordShl(index_word, UintPtrConstant(1)), value_word32)))); 7781cb0ef41Sopenharmony_ci BIND(&u16); 7791cb0ef41Sopenharmony_ci Return(SmiFromInt32(Signed((this->*function)( 7801cb0ef41Sopenharmony_ci MachineType::Uint16(), backing_store, 7811cb0ef41Sopenharmony_ci WordShl(index_word, UintPtrConstant(1)), value_word32)))); 7821cb0ef41Sopenharmony_ci BIND(&i32); 7831cb0ef41Sopenharmony_ci Return(ChangeInt32ToTagged(Signed((this->*function)( 7841cb0ef41Sopenharmony_ci MachineType::Int32(), backing_store, 7851cb0ef41Sopenharmony_ci WordShl(index_word, UintPtrConstant(2)), value_word32)))); 7861cb0ef41Sopenharmony_ci BIND(&u32); 7871cb0ef41Sopenharmony_ci Return(ChangeUint32ToTagged(Unsigned((this->*function)( 7881cb0ef41Sopenharmony_ci MachineType::Uint32(), backing_store, 7891cb0ef41Sopenharmony_ci WordShl(index_word, UintPtrConstant(2)), value_word32)))); 7901cb0ef41Sopenharmony_ci BIND(&big); 7911cb0ef41Sopenharmony_ci // 4. If typedArray.[[ContentType]] is BigInt, let v be ? ToBigInt(value). 7921cb0ef41Sopenharmony_ci TNode<BigInt> value_bigint = ToBigInt(context, value); 7931cb0ef41Sopenharmony_ci 7941cb0ef41Sopenharmony_ci // 6. If IsDetachedBuffer(buffer) is true, throw a TypeError exception. 7951cb0ef41Sopenharmony_ci GotoIf(IsDetachedBuffer(array_buffer), &detached); 7961cb0ef41Sopenharmony_ci 7971cb0ef41Sopenharmony_ci DebugCheckAtomicIndex(array, index_word); 7981cb0ef41Sopenharmony_ci 7991cb0ef41Sopenharmony_ci TVARIABLE(UintPtrT, var_low); 8001cb0ef41Sopenharmony_ci TVARIABLE(UintPtrT, var_high); 8011cb0ef41Sopenharmony_ci BigIntToRawBytes(value_bigint, &var_low, &var_high); 8021cb0ef41Sopenharmony_ci TNode<UintPtrT> high = Is64() ? TNode<UintPtrT>() : var_high.value(); 8031cb0ef41Sopenharmony_ci GotoIf(Word32Equal(elements_kind, Int32Constant(BIGINT64_ELEMENTS)), &i64); 8041cb0ef41Sopenharmony_ci GotoIf(Word32Equal(elements_kind, Int32Constant(BIGUINT64_ELEMENTS)), &u64); 8051cb0ef41Sopenharmony_ci Unreachable(); 8061cb0ef41Sopenharmony_ci 8071cb0ef41Sopenharmony_ci BIND(&i64); 8081cb0ef41Sopenharmony_ci Return(BigIntFromSigned64((this->*function_int_64)( 8091cb0ef41Sopenharmony_ci backing_store, WordShl(index_word, UintPtrConstant(3)), var_low.value(), 8101cb0ef41Sopenharmony_ci high))); 8111cb0ef41Sopenharmony_ci BIND(&u64); 8121cb0ef41Sopenharmony_ci Return(BigIntFromUnsigned64((this->*function_uint_64)( 8131cb0ef41Sopenharmony_ci backing_store, WordShl(index_word, UintPtrConstant(3)), var_low.value(), 8141cb0ef41Sopenharmony_ci high))); 8151cb0ef41Sopenharmony_ci // // This shouldn't happen, we've already validated the type. 8161cb0ef41Sopenharmony_ci BIND(&other); 8171cb0ef41Sopenharmony_ci Unreachable(); 8181cb0ef41Sopenharmony_ci#endif // V8_TARGET_ARCH_MIPS || V8_TARGET_ARCH_MIPS64 || V8_TARGET_ARCH_PPC64 8191cb0ef41Sopenharmony_ci // || V8_TARGET_ARCH_PPC || V8_TARGET_ARCH_S390 || V8_TARGET_ARCH_S390X 8201cb0ef41Sopenharmony_ci // || V8_TARGET_ARCH_RISCV64 8211cb0ef41Sopenharmony_ci 8221cb0ef41Sopenharmony_ci BIND(&detached); 8231cb0ef41Sopenharmony_ci ThrowTypeError(context, MessageTemplate::kDetachedOperation, method_name); 8241cb0ef41Sopenharmony_ci} 8251cb0ef41Sopenharmony_ci 8261cb0ef41Sopenharmony_ci} // namespace internal 8271cb0ef41Sopenharmony_ci} // namespace v8 828