11cb0ef41Sopenharmony_ci// Copyright 2018 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#ifndef V8_OBJECTS_JS_ARRAY_BUFFER_INL_H_ 61cb0ef41Sopenharmony_ci#define V8_OBJECTS_JS_ARRAY_BUFFER_INL_H_ 71cb0ef41Sopenharmony_ci 81cb0ef41Sopenharmony_ci#include "src/heap/heap-write-barrier-inl.h" 91cb0ef41Sopenharmony_ci#include "src/objects/js-array-buffer.h" 101cb0ef41Sopenharmony_ci#include "src/objects/js-objects-inl.h" 111cb0ef41Sopenharmony_ci#include "src/objects/objects-inl.h" 121cb0ef41Sopenharmony_ci 131cb0ef41Sopenharmony_ci// Has to be the last include (doesn't have include guards): 141cb0ef41Sopenharmony_ci#include "src/objects/object-macros.h" 151cb0ef41Sopenharmony_ci 161cb0ef41Sopenharmony_cinamespace v8 { 171cb0ef41Sopenharmony_cinamespace internal { 181cb0ef41Sopenharmony_ci 191cb0ef41Sopenharmony_ci#include "torque-generated/src/objects/js-array-buffer-tq-inl.inc" 201cb0ef41Sopenharmony_ci 211cb0ef41Sopenharmony_ciTQ_OBJECT_CONSTRUCTORS_IMPL(JSArrayBuffer) 221cb0ef41Sopenharmony_ciTQ_OBJECT_CONSTRUCTORS_IMPL(JSArrayBufferView) 231cb0ef41Sopenharmony_ciTQ_OBJECT_CONSTRUCTORS_IMPL(JSTypedArray) 241cb0ef41Sopenharmony_ciTQ_OBJECT_CONSTRUCTORS_IMPL(JSDataView) 251cb0ef41Sopenharmony_ci 261cb0ef41Sopenharmony_ciACCESSORS(JSTypedArray, base_pointer, Object, kBasePointerOffset) 271cb0ef41Sopenharmony_ciRELEASE_ACQUIRE_ACCESSORS(JSTypedArray, base_pointer, Object, 281cb0ef41Sopenharmony_ci kBasePointerOffset) 291cb0ef41Sopenharmony_ci 301cb0ef41Sopenharmony_cisize_t JSArrayBuffer::byte_length() const { 311cb0ef41Sopenharmony_ci return ReadField<size_t>(kByteLengthOffset); 321cb0ef41Sopenharmony_ci} 331cb0ef41Sopenharmony_ci 341cb0ef41Sopenharmony_civoid JSArrayBuffer::set_byte_length(size_t value) { 351cb0ef41Sopenharmony_ci WriteField<size_t>(kByteLengthOffset, value); 361cb0ef41Sopenharmony_ci} 371cb0ef41Sopenharmony_ci 381cb0ef41Sopenharmony_ciDEF_GETTER(JSArrayBuffer, backing_store, void*) { 391cb0ef41Sopenharmony_ci Address value = ReadSandboxedPointerField(kBackingStoreOffset, cage_base); 401cb0ef41Sopenharmony_ci return reinterpret_cast<void*>(value); 411cb0ef41Sopenharmony_ci} 421cb0ef41Sopenharmony_ci 431cb0ef41Sopenharmony_civoid JSArrayBuffer::set_backing_store(Isolate* isolate, void* value) { 441cb0ef41Sopenharmony_ci Address addr = reinterpret_cast<Address>(value); 451cb0ef41Sopenharmony_ci WriteSandboxedPointerField(kBackingStoreOffset, isolate, addr); 461cb0ef41Sopenharmony_ci} 471cb0ef41Sopenharmony_ci 481cb0ef41Sopenharmony_cistd::shared_ptr<BackingStore> JSArrayBuffer::GetBackingStore() const { 491cb0ef41Sopenharmony_ci if (!extension()) return nullptr; 501cb0ef41Sopenharmony_ci return extension()->backing_store(); 511cb0ef41Sopenharmony_ci} 521cb0ef41Sopenharmony_ci 531cb0ef41Sopenharmony_cisize_t JSArrayBuffer::GetByteLength() const { 541cb0ef41Sopenharmony_ci if V8_UNLIKELY (is_shared() && is_resizable()) { 551cb0ef41Sopenharmony_ci // Invariant: byte_length for GSAB is 0 (it needs to be read from the 561cb0ef41Sopenharmony_ci // BackingStore). 571cb0ef41Sopenharmony_ci DCHECK_EQ(0, byte_length()); 581cb0ef41Sopenharmony_ci 591cb0ef41Sopenharmony_ci return GetBackingStore()->byte_length(std::memory_order_seq_cst); 601cb0ef41Sopenharmony_ci } 611cb0ef41Sopenharmony_ci return byte_length(); 621cb0ef41Sopenharmony_ci} 631cb0ef41Sopenharmony_ci 641cb0ef41Sopenharmony_ciuint32_t JSArrayBuffer::GetBackingStoreRefForDeserialization() const { 651cb0ef41Sopenharmony_ci return static_cast<uint32_t>(ReadField<Address>(kBackingStoreOffset)); 661cb0ef41Sopenharmony_ci} 671cb0ef41Sopenharmony_ci 681cb0ef41Sopenharmony_civoid JSArrayBuffer::SetBackingStoreRefForSerialization(uint32_t ref) { 691cb0ef41Sopenharmony_ci WriteField<Address>(kBackingStoreOffset, static_cast<Address>(ref)); 701cb0ef41Sopenharmony_ci} 711cb0ef41Sopenharmony_ci 721cb0ef41Sopenharmony_ciArrayBufferExtension* JSArrayBuffer::extension() const { 731cb0ef41Sopenharmony_ci#if V8_COMPRESS_POINTERS 741cb0ef41Sopenharmony_ci // With pointer compression the extension-field might not be 751cb0ef41Sopenharmony_ci // pointer-aligned. However on ARM64 this field needs to be aligned to 761cb0ef41Sopenharmony_ci // perform atomic operations on it. Therefore we split the pointer into two 771cb0ef41Sopenharmony_ci // 32-bit words that we update atomically. We don't have an ABA problem here 781cb0ef41Sopenharmony_ci // since there can never be an Attach() after Detach() (transitions only 791cb0ef41Sopenharmony_ci // from NULL --> some ptr --> NULL). 801cb0ef41Sopenharmony_ci 811cb0ef41Sopenharmony_ci // Synchronize with publishing release store of non-null extension 821cb0ef41Sopenharmony_ci uint32_t lo = base::AsAtomic32::Acquire_Load(extension_lo()); 831cb0ef41Sopenharmony_ci if (lo & kUninitializedTagMask) return nullptr; 841cb0ef41Sopenharmony_ci 851cb0ef41Sopenharmony_ci // Synchronize with release store of null extension 861cb0ef41Sopenharmony_ci uint32_t hi = base::AsAtomic32::Acquire_Load(extension_hi()); 871cb0ef41Sopenharmony_ci uint32_t verify_lo = base::AsAtomic32::Relaxed_Load(extension_lo()); 881cb0ef41Sopenharmony_ci if (lo != verify_lo) return nullptr; 891cb0ef41Sopenharmony_ci 901cb0ef41Sopenharmony_ci uintptr_t address = static_cast<uintptr_t>(lo); 911cb0ef41Sopenharmony_ci address |= static_cast<uintptr_t>(hi) << 32; 921cb0ef41Sopenharmony_ci return reinterpret_cast<ArrayBufferExtension*>(address); 931cb0ef41Sopenharmony_ci#else 941cb0ef41Sopenharmony_ci return base::AsAtomicPointer::Acquire_Load(extension_location()); 951cb0ef41Sopenharmony_ci#endif 961cb0ef41Sopenharmony_ci} 971cb0ef41Sopenharmony_ci 981cb0ef41Sopenharmony_civoid JSArrayBuffer::set_extension(ArrayBufferExtension* extension) { 991cb0ef41Sopenharmony_ci#if V8_COMPRESS_POINTERS 1001cb0ef41Sopenharmony_ci if (extension != nullptr) { 1011cb0ef41Sopenharmony_ci uintptr_t address = reinterpret_cast<uintptr_t>(extension); 1021cb0ef41Sopenharmony_ci base::AsAtomic32::Relaxed_Store(extension_hi(), 1031cb0ef41Sopenharmony_ci static_cast<uint32_t>(address >> 32)); 1041cb0ef41Sopenharmony_ci base::AsAtomic32::Release_Store(extension_lo(), 1051cb0ef41Sopenharmony_ci static_cast<uint32_t>(address)); 1061cb0ef41Sopenharmony_ci } else { 1071cb0ef41Sopenharmony_ci base::AsAtomic32::Relaxed_Store(extension_lo(), 1081cb0ef41Sopenharmony_ci 0 | kUninitializedTagMask); 1091cb0ef41Sopenharmony_ci base::AsAtomic32::Release_Store(extension_hi(), 0); 1101cb0ef41Sopenharmony_ci } 1111cb0ef41Sopenharmony_ci#else 1121cb0ef41Sopenharmony_ci base::AsAtomicPointer::Release_Store(extension_location(), extension); 1131cb0ef41Sopenharmony_ci#endif 1141cb0ef41Sopenharmony_ci WriteBarrier::Marking(*this, extension); 1151cb0ef41Sopenharmony_ci} 1161cb0ef41Sopenharmony_ci 1171cb0ef41Sopenharmony_ciArrayBufferExtension** JSArrayBuffer::extension_location() const { 1181cb0ef41Sopenharmony_ci Address location = field_address(kExtensionOffset); 1191cb0ef41Sopenharmony_ci return reinterpret_cast<ArrayBufferExtension**>(location); 1201cb0ef41Sopenharmony_ci} 1211cb0ef41Sopenharmony_ci 1221cb0ef41Sopenharmony_ci#if V8_COMPRESS_POINTERS 1231cb0ef41Sopenharmony_ciuint32_t* JSArrayBuffer::extension_lo() const { 1241cb0ef41Sopenharmony_ci Address location = field_address(kExtensionOffset); 1251cb0ef41Sopenharmony_ci return reinterpret_cast<uint32_t*>(location); 1261cb0ef41Sopenharmony_ci} 1271cb0ef41Sopenharmony_ci 1281cb0ef41Sopenharmony_ciuint32_t* JSArrayBuffer::extension_hi() const { 1291cb0ef41Sopenharmony_ci Address location = field_address(kExtensionOffset) + sizeof(uint32_t); 1301cb0ef41Sopenharmony_ci return reinterpret_cast<uint32_t*>(location); 1311cb0ef41Sopenharmony_ci} 1321cb0ef41Sopenharmony_ci#endif 1331cb0ef41Sopenharmony_ci 1341cb0ef41Sopenharmony_civoid JSArrayBuffer::clear_padding() { 1351cb0ef41Sopenharmony_ci if (FIELD_SIZE(kOptionalPaddingOffset) != 0) { 1361cb0ef41Sopenharmony_ci DCHECK_EQ(4, FIELD_SIZE(kOptionalPaddingOffset)); 1371cb0ef41Sopenharmony_ci memset(reinterpret_cast<void*>(address() + kOptionalPaddingOffset), 0, 1381cb0ef41Sopenharmony_ci FIELD_SIZE(kOptionalPaddingOffset)); 1391cb0ef41Sopenharmony_ci } 1401cb0ef41Sopenharmony_ci} 1411cb0ef41Sopenharmony_ci 1421cb0ef41Sopenharmony_civoid JSArrayBuffer::set_bit_field(uint32_t bits) { 1431cb0ef41Sopenharmony_ci RELAXED_WRITE_UINT32_FIELD(*this, kBitFieldOffset, bits); 1441cb0ef41Sopenharmony_ci} 1451cb0ef41Sopenharmony_ci 1461cb0ef41Sopenharmony_ciuint32_t JSArrayBuffer::bit_field() const { 1471cb0ef41Sopenharmony_ci return RELAXED_READ_UINT32_FIELD(*this, kBitFieldOffset); 1481cb0ef41Sopenharmony_ci} 1491cb0ef41Sopenharmony_ci 1501cb0ef41Sopenharmony_ci// |bit_field| fields. 1511cb0ef41Sopenharmony_ciBIT_FIELD_ACCESSORS(JSArrayBuffer, bit_field, is_external, 1521cb0ef41Sopenharmony_ci JSArrayBuffer::IsExternalBit) 1531cb0ef41Sopenharmony_ciBIT_FIELD_ACCESSORS(JSArrayBuffer, bit_field, is_detachable, 1541cb0ef41Sopenharmony_ci JSArrayBuffer::IsDetachableBit) 1551cb0ef41Sopenharmony_ciBIT_FIELD_ACCESSORS(JSArrayBuffer, bit_field, was_detached, 1561cb0ef41Sopenharmony_ci JSArrayBuffer::WasDetachedBit) 1571cb0ef41Sopenharmony_ciBIT_FIELD_ACCESSORS(JSArrayBuffer, bit_field, is_asmjs_memory, 1581cb0ef41Sopenharmony_ci JSArrayBuffer::IsAsmJsMemoryBit) 1591cb0ef41Sopenharmony_ciBIT_FIELD_ACCESSORS(JSArrayBuffer, bit_field, is_shared, 1601cb0ef41Sopenharmony_ci JSArrayBuffer::IsSharedBit) 1611cb0ef41Sopenharmony_ciBIT_FIELD_ACCESSORS(JSArrayBuffer, bit_field, is_resizable, 1621cb0ef41Sopenharmony_ci JSArrayBuffer::IsResizableBit) 1631cb0ef41Sopenharmony_ci 1641cb0ef41Sopenharmony_cibool JSArrayBuffer::IsEmpty() const { 1651cb0ef41Sopenharmony_ci auto backing_store = GetBackingStore(); 1661cb0ef41Sopenharmony_ci bool is_empty = !backing_store || backing_store->IsEmpty(); 1671cb0ef41Sopenharmony_ci DCHECK_IMPLIES(is_empty, byte_length() == 0); 1681cb0ef41Sopenharmony_ci return is_empty; 1691cb0ef41Sopenharmony_ci} 1701cb0ef41Sopenharmony_ci 1711cb0ef41Sopenharmony_cisize_t JSArrayBufferView::byte_offset() const { 1721cb0ef41Sopenharmony_ci return ReadField<size_t>(kByteOffsetOffset); 1731cb0ef41Sopenharmony_ci} 1741cb0ef41Sopenharmony_ci 1751cb0ef41Sopenharmony_civoid JSArrayBufferView::set_byte_offset(size_t value) { 1761cb0ef41Sopenharmony_ci WriteField<size_t>(kByteOffsetOffset, value); 1771cb0ef41Sopenharmony_ci} 1781cb0ef41Sopenharmony_ci 1791cb0ef41Sopenharmony_cisize_t JSArrayBufferView::byte_length() const { 1801cb0ef41Sopenharmony_ci return ReadField<size_t>(kByteLengthOffset); 1811cb0ef41Sopenharmony_ci} 1821cb0ef41Sopenharmony_ci 1831cb0ef41Sopenharmony_civoid JSArrayBufferView::set_byte_length(size_t value) { 1841cb0ef41Sopenharmony_ci WriteField<size_t>(kByteLengthOffset, value); 1851cb0ef41Sopenharmony_ci} 1861cb0ef41Sopenharmony_ci 1871cb0ef41Sopenharmony_cibool JSArrayBufferView::WasDetached() const { 1881cb0ef41Sopenharmony_ci return JSArrayBuffer::cast(buffer()).was_detached(); 1891cb0ef41Sopenharmony_ci} 1901cb0ef41Sopenharmony_ci 1911cb0ef41Sopenharmony_ciBIT_FIELD_ACCESSORS(JSArrayBufferView, bit_field, is_length_tracking, 1921cb0ef41Sopenharmony_ci JSArrayBufferView::IsLengthTrackingBit) 1931cb0ef41Sopenharmony_ciBIT_FIELD_ACCESSORS(JSArrayBufferView, bit_field, is_backed_by_rab, 1941cb0ef41Sopenharmony_ci JSArrayBufferView::IsBackedByRabBit) 1951cb0ef41Sopenharmony_ci 1961cb0ef41Sopenharmony_cibool JSArrayBufferView::IsVariableLength() const { 1971cb0ef41Sopenharmony_ci return is_length_tracking() || is_backed_by_rab(); 1981cb0ef41Sopenharmony_ci} 1991cb0ef41Sopenharmony_ci 2001cb0ef41Sopenharmony_cisize_t JSTypedArray::GetLengthOrOutOfBounds(bool& out_of_bounds) const { 2011cb0ef41Sopenharmony_ci DCHECK(!out_of_bounds); 2021cb0ef41Sopenharmony_ci if (WasDetached()) return 0; 2031cb0ef41Sopenharmony_ci if (IsVariableLength()) { 2041cb0ef41Sopenharmony_ci return GetVariableLengthOrOutOfBounds(out_of_bounds); 2051cb0ef41Sopenharmony_ci } 2061cb0ef41Sopenharmony_ci return LengthUnchecked(); 2071cb0ef41Sopenharmony_ci} 2081cb0ef41Sopenharmony_ci 2091cb0ef41Sopenharmony_cisize_t JSTypedArray::GetLength() const { 2101cb0ef41Sopenharmony_ci bool out_of_bounds = false; 2111cb0ef41Sopenharmony_ci return GetLengthOrOutOfBounds(out_of_bounds); 2121cb0ef41Sopenharmony_ci} 2131cb0ef41Sopenharmony_ci 2141cb0ef41Sopenharmony_cisize_t JSTypedArray::GetByteLength() const { 2151cb0ef41Sopenharmony_ci return GetLength() * element_size(); 2161cb0ef41Sopenharmony_ci} 2171cb0ef41Sopenharmony_ci 2181cb0ef41Sopenharmony_cibool JSTypedArray::IsOutOfBounds() const { 2191cb0ef41Sopenharmony_ci bool out_of_bounds = false; 2201cb0ef41Sopenharmony_ci GetLengthOrOutOfBounds(out_of_bounds); 2211cb0ef41Sopenharmony_ci return out_of_bounds; 2221cb0ef41Sopenharmony_ci} 2231cb0ef41Sopenharmony_ci 2241cb0ef41Sopenharmony_cibool JSTypedArray::IsDetachedOrOutOfBounds() const { 2251cb0ef41Sopenharmony_ci if (WasDetached()) { 2261cb0ef41Sopenharmony_ci return true; 2271cb0ef41Sopenharmony_ci } 2281cb0ef41Sopenharmony_ci bool out_of_bounds = false; 2291cb0ef41Sopenharmony_ci GetLengthOrOutOfBounds(out_of_bounds); 2301cb0ef41Sopenharmony_ci return out_of_bounds; 2311cb0ef41Sopenharmony_ci} 2321cb0ef41Sopenharmony_ci 2331cb0ef41Sopenharmony_cisize_t JSTypedArray::length() const { 2341cb0ef41Sopenharmony_ci DCHECK(!is_length_tracking()); 2351cb0ef41Sopenharmony_ci DCHECK(!is_backed_by_rab()); 2361cb0ef41Sopenharmony_ci return ReadField<size_t>(kLengthOffset); 2371cb0ef41Sopenharmony_ci} 2381cb0ef41Sopenharmony_ci 2391cb0ef41Sopenharmony_cisize_t JSTypedArray::LengthUnchecked() const { 2401cb0ef41Sopenharmony_ci return ReadField<size_t>(kLengthOffset); 2411cb0ef41Sopenharmony_ci} 2421cb0ef41Sopenharmony_ci 2431cb0ef41Sopenharmony_civoid JSTypedArray::set_length(size_t value) { 2441cb0ef41Sopenharmony_ci WriteField<size_t>(kLengthOffset, value); 2451cb0ef41Sopenharmony_ci} 2461cb0ef41Sopenharmony_ci 2471cb0ef41Sopenharmony_ciDEF_GETTER(JSTypedArray, external_pointer, Address) { 2481cb0ef41Sopenharmony_ci return ReadSandboxedPointerField(kExternalPointerOffset, cage_base); 2491cb0ef41Sopenharmony_ci} 2501cb0ef41Sopenharmony_ci 2511cb0ef41Sopenharmony_civoid JSTypedArray::set_external_pointer(Isolate* isolate, Address value) { 2521cb0ef41Sopenharmony_ci WriteSandboxedPointerField(kExternalPointerOffset, isolate, value); 2531cb0ef41Sopenharmony_ci} 2541cb0ef41Sopenharmony_ci 2551cb0ef41Sopenharmony_ciAddress JSTypedArray::ExternalPointerCompensationForOnHeapArray( 2561cb0ef41Sopenharmony_ci PtrComprCageBase cage_base) { 2571cb0ef41Sopenharmony_ci#ifdef V8_COMPRESS_POINTERS 2581cb0ef41Sopenharmony_ci return cage_base.address(); 2591cb0ef41Sopenharmony_ci#else 2601cb0ef41Sopenharmony_ci return 0; 2611cb0ef41Sopenharmony_ci#endif 2621cb0ef41Sopenharmony_ci} 2631cb0ef41Sopenharmony_ci 2641cb0ef41Sopenharmony_ciuint32_t JSTypedArray::GetExternalBackingStoreRefForDeserialization() const { 2651cb0ef41Sopenharmony_ci DCHECK(!is_on_heap()); 2661cb0ef41Sopenharmony_ci return static_cast<uint32_t>(ReadField<Address>(kExternalPointerOffset)); 2671cb0ef41Sopenharmony_ci} 2681cb0ef41Sopenharmony_ci 2691cb0ef41Sopenharmony_civoid JSTypedArray::SetExternalBackingStoreRefForSerialization(uint32_t ref) { 2701cb0ef41Sopenharmony_ci DCHECK(!is_on_heap()); 2711cb0ef41Sopenharmony_ci WriteField<Address>(kExternalPointerOffset, static_cast<Address>(ref)); 2721cb0ef41Sopenharmony_ci} 2731cb0ef41Sopenharmony_ci 2741cb0ef41Sopenharmony_civoid JSTypedArray::RemoveExternalPointerCompensationForSerialization( 2751cb0ef41Sopenharmony_ci Isolate* isolate) { 2761cb0ef41Sopenharmony_ci DCHECK(is_on_heap()); 2771cb0ef41Sopenharmony_ci Address offset = 2781cb0ef41Sopenharmony_ci external_pointer() - ExternalPointerCompensationForOnHeapArray(isolate); 2791cb0ef41Sopenharmony_ci WriteField<Address>(kExternalPointerOffset, offset); 2801cb0ef41Sopenharmony_ci} 2811cb0ef41Sopenharmony_ci 2821cb0ef41Sopenharmony_civoid JSTypedArray::AddExternalPointerCompensationForDeserialization( 2831cb0ef41Sopenharmony_ci Isolate* isolate) { 2841cb0ef41Sopenharmony_ci DCHECK(is_on_heap()); 2851cb0ef41Sopenharmony_ci Address pointer = ReadField<Address>(kExternalPointerOffset) + 2861cb0ef41Sopenharmony_ci ExternalPointerCompensationForOnHeapArray(isolate); 2871cb0ef41Sopenharmony_ci set_external_pointer(isolate, pointer); 2881cb0ef41Sopenharmony_ci} 2891cb0ef41Sopenharmony_ci 2901cb0ef41Sopenharmony_civoid* JSTypedArray::DataPtr() { 2911cb0ef41Sopenharmony_ci // Zero-extend Tagged_t to Address according to current compression scheme 2921cb0ef41Sopenharmony_ci // so that the addition with |external_pointer| (which already contains 2931cb0ef41Sopenharmony_ci // compensated offset value) will decompress the tagged value. 2941cb0ef41Sopenharmony_ci // See JSTypedArray::ExternalPointerCompensationForOnHeapArray() for details. 2951cb0ef41Sopenharmony_ci STATIC_ASSERT(kOffHeapDataPtrEqualsExternalPointer); 2961cb0ef41Sopenharmony_ci return reinterpret_cast<void*>(external_pointer() + 2971cb0ef41Sopenharmony_ci static_cast<Tagged_t>(base_pointer().ptr())); 2981cb0ef41Sopenharmony_ci} 2991cb0ef41Sopenharmony_ci 3001cb0ef41Sopenharmony_civoid JSTypedArray::SetOffHeapDataPtr(Isolate* isolate, void* base, 3011cb0ef41Sopenharmony_ci Address offset) { 3021cb0ef41Sopenharmony_ci Address address = reinterpret_cast<Address>(base) + offset; 3031cb0ef41Sopenharmony_ci set_external_pointer(isolate, address); 3041cb0ef41Sopenharmony_ci // This is the only spot in which the `base_pointer` field can be mutated 3051cb0ef41Sopenharmony_ci // after object initialization. Note this can happen at most once, when 3061cb0ef41Sopenharmony_ci // `JSTypedArray::GetBuffer` transitions from an on- to off-heap 3071cb0ef41Sopenharmony_ci // representation. 3081cb0ef41Sopenharmony_ci // To play well with Turbofan concurrency requirements, `base_pointer` is set 3091cb0ef41Sopenharmony_ci // with a release store, after external_pointer has been set. 3101cb0ef41Sopenharmony_ci set_base_pointer(Smi::zero(), kReleaseStore, SKIP_WRITE_BARRIER); 3111cb0ef41Sopenharmony_ci DCHECK_EQ(address, reinterpret_cast<Address>(DataPtr())); 3121cb0ef41Sopenharmony_ci} 3131cb0ef41Sopenharmony_ci 3141cb0ef41Sopenharmony_cibool JSTypedArray::is_on_heap() const { 3151cb0ef41Sopenharmony_ci // Keep synced with `is_on_heap(AcquireLoadTag)`. 3161cb0ef41Sopenharmony_ci DisallowGarbageCollection no_gc; 3171cb0ef41Sopenharmony_ci return base_pointer() != Smi::zero(); 3181cb0ef41Sopenharmony_ci} 3191cb0ef41Sopenharmony_ci 3201cb0ef41Sopenharmony_cibool JSTypedArray::is_on_heap(AcquireLoadTag tag) const { 3211cb0ef41Sopenharmony_ci // Keep synced with `is_on_heap()`. 3221cb0ef41Sopenharmony_ci // Note: For Turbofan concurrency requirements, it's important that this 3231cb0ef41Sopenharmony_ci // function reads only `base_pointer`. 3241cb0ef41Sopenharmony_ci DisallowGarbageCollection no_gc; 3251cb0ef41Sopenharmony_ci return base_pointer(tag) != Smi::zero(); 3261cb0ef41Sopenharmony_ci} 3271cb0ef41Sopenharmony_ci 3281cb0ef41Sopenharmony_ci// static 3291cb0ef41Sopenharmony_ciMaybeHandle<JSTypedArray> JSTypedArray::Validate(Isolate* isolate, 3301cb0ef41Sopenharmony_ci Handle<Object> receiver, 3311cb0ef41Sopenharmony_ci const char* method_name) { 3321cb0ef41Sopenharmony_ci if (V8_UNLIKELY(!receiver->IsJSTypedArray())) { 3331cb0ef41Sopenharmony_ci const MessageTemplate message = MessageTemplate::kNotTypedArray; 3341cb0ef41Sopenharmony_ci THROW_NEW_ERROR(isolate, NewTypeError(message), JSTypedArray); 3351cb0ef41Sopenharmony_ci } 3361cb0ef41Sopenharmony_ci 3371cb0ef41Sopenharmony_ci Handle<JSTypedArray> array = Handle<JSTypedArray>::cast(receiver); 3381cb0ef41Sopenharmony_ci if (V8_UNLIKELY(array->WasDetached())) { 3391cb0ef41Sopenharmony_ci const MessageTemplate message = MessageTemplate::kDetachedOperation; 3401cb0ef41Sopenharmony_ci Handle<String> operation = 3411cb0ef41Sopenharmony_ci isolate->factory()->NewStringFromAsciiChecked(method_name); 3421cb0ef41Sopenharmony_ci THROW_NEW_ERROR(isolate, NewTypeError(message, operation), JSTypedArray); 3431cb0ef41Sopenharmony_ci } 3441cb0ef41Sopenharmony_ci 3451cb0ef41Sopenharmony_ci if (V8_UNLIKELY(array->IsVariableLength() && array->IsOutOfBounds())) { 3461cb0ef41Sopenharmony_ci const MessageTemplate message = MessageTemplate::kDetachedOperation; 3471cb0ef41Sopenharmony_ci Handle<String> operation = 3481cb0ef41Sopenharmony_ci isolate->factory()->NewStringFromAsciiChecked(method_name); 3491cb0ef41Sopenharmony_ci THROW_NEW_ERROR(isolate, NewTypeError(message, operation), JSTypedArray); 3501cb0ef41Sopenharmony_ci } 3511cb0ef41Sopenharmony_ci 3521cb0ef41Sopenharmony_ci // spec describes to return `buffer`, but it may disrupt current 3531cb0ef41Sopenharmony_ci // implementations, and it's much useful to return array for now. 3541cb0ef41Sopenharmony_ci return array; 3551cb0ef41Sopenharmony_ci} 3561cb0ef41Sopenharmony_ci 3571cb0ef41Sopenharmony_ciDEF_GETTER(JSDataView, data_pointer, void*) { 3581cb0ef41Sopenharmony_ci Address value = ReadSandboxedPointerField(kDataPointerOffset, cage_base); 3591cb0ef41Sopenharmony_ci return reinterpret_cast<void*>(value); 3601cb0ef41Sopenharmony_ci} 3611cb0ef41Sopenharmony_ci 3621cb0ef41Sopenharmony_civoid JSDataView::set_data_pointer(Isolate* isolate, void* ptr) { 3631cb0ef41Sopenharmony_ci Address value = reinterpret_cast<Address>(ptr); 3641cb0ef41Sopenharmony_ci WriteSandboxedPointerField(kDataPointerOffset, isolate, value); 3651cb0ef41Sopenharmony_ci} 3661cb0ef41Sopenharmony_ci 3671cb0ef41Sopenharmony_ci} // namespace internal 3681cb0ef41Sopenharmony_ci} // namespace v8 3691cb0ef41Sopenharmony_ci 3701cb0ef41Sopenharmony_ci#include "src/objects/object-macros-undef.h" 3711cb0ef41Sopenharmony_ci 3721cb0ef41Sopenharmony_ci#endif // V8_OBJECTS_JS_ARRAY_BUFFER_INL_H_ 373