@@ -79,65 +79,60 @@ void JSArrayBuffer::SetBackingStoreRefForSerialization(uint32_t ref) {
79
79
80
80
ArrayBufferExtension* JSArrayBuffer::extension () const {
81
81
#if V8_COMPRESS_POINTERS
82
- // With pointer compression the extension-field might not be
83
- // pointer-aligned. However on ARM64 this field needs to be aligned to
84
- // perform atomic operations on it. Therefore we split the pointer into two
85
- // 32-bit words that we update atomically. We don't have an ABA problem here
86
- // since there can never be an Attach() after Detach() (transitions only
87
- // from NULL --> some ptr --> NULL).
88
-
89
- // Synchronize with publishing release store of non-null extension
90
- uint32_t lo = base::AsAtomic32::Acquire_Load (extension_lo ());
91
- if (lo & kUninitializedTagMask ) return nullptr ;
92
-
93
- // Synchronize with release store of null extension
94
- uint32_t hi = base::AsAtomic32::Acquire_Load (extension_hi ());
95
- uint32_t verify_lo = base::AsAtomic32::Relaxed_Load (extension_lo ());
96
- if (lo != verify_lo) return nullptr ;
97
-
98
- uintptr_t address = static_cast <uintptr_t >(lo);
99
- address |= static_cast <uintptr_t >(hi) << 32 ;
100
- return reinterpret_cast <ArrayBufferExtension*>(address);
82
+ // We need Acquire semantics here when loading the entry, see below.
83
+ // Consider adding respective external pointer accessors if non-relaxed
84
+ // ordering semantics are ever needed in other places as well.
85
+ Isolate* isolate = GetIsolateFromWritableObject (*this );
86
+ ExternalPointerHandle handle =
87
+ base::AsAtomic32::Acquire_Load (extension_handle_location ());
88
+ return reinterpret_cast <ArrayBufferExtension*>(
89
+ isolate->external_pointer_table ().Get (handle, kArrayBufferExtensionTag ));
101
90
#else
102
- return base::AsAtomicPointer::Acquire_Load (extension_location ());
103
- #endif
91
+ return base::AsAtomicPointer::Acquire_Load (extension_location ());
92
+ #endif // V8_COMPRESS_POINTERS
104
93
}
105
94
106
95
void JSArrayBuffer::set_extension (ArrayBufferExtension* extension) {
107
96
#if V8_COMPRESS_POINTERS
108
- if (extension != nullptr ) {
109
- uintptr_t address = reinterpret_cast <uintptr_t >(extension);
110
- base::AsAtomic32::Relaxed_Store (extension_hi (),
111
- static_cast <uint32_t >(address >> 32 ));
112
- base::AsAtomic32::Release_Store (extension_lo (),
113
- static_cast <uint32_t >(address));
114
- } else {
115
- base::AsAtomic32::Relaxed_Store (extension_lo (),
116
- 0 | kUninitializedTagMask );
117
- base::AsAtomic32::Release_Store (extension_hi (), 0 );
118
- }
97
+ if (extension != nullptr ) {
98
+ Isolate* isolate = GetIsolateFromWritableObject (*this );
99
+ ExternalPointerTable& table = isolate->external_pointer_table ();
100
+
101
+ // The external pointer handle for the extension is initialized lazily and
102
+ // so has to be zero here since, once set, the extension field can only be
103
+ // cleared, but not changed.
104
+ DCHECK_EQ (0 , base::AsAtomic32::Relaxed_Load (extension_handle_location ()));
105
+
106
+ // We need Release semantics here, see above.
107
+ ExternalPointerHandle handle = table.AllocateAndInitializeEntry (
108
+ isolate, reinterpret_cast <Address>(extension),
109
+ kArrayBufferExtensionTag );
110
+ base::AsAtomic32::Release_Store (extension_handle_location (), handle);
111
+ } else {
112
+ // This special handling of nullptr is required as it is used to initialize
113
+ // the slot, but is also beneficial when an ArrayBuffer is detached as it
114
+ // allows the external pointer table entry to be reclaimed while the
115
+ // ArrayBuffer is still alive.
116
+ base::AsAtomic32::Release_Store (extension_handle_location (),
117
+ kNullExternalPointerHandle );
118
+ }
119
119
#else
120
- base::AsAtomicPointer::Release_Store (extension_location (), extension);
121
- #endif
122
- WriteBarrier::Marking (*this , extension);
123
- }
124
-
125
- ArrayBufferExtension** JSArrayBuffer::extension_location () const {
126
- Address location = field_address (kExtensionOffset );
127
- return reinterpret_cast <ArrayBufferExtension**>(location);
120
+ base::AsAtomicPointer::Release_Store (extension_location (), extension);
121
+ #endif // V8_COMPRESS_POINTERS
122
+ WriteBarrier::Marking (*this , extension);
128
123
}
129
124
130
125
#if V8_COMPRESS_POINTERS
131
- uint32_t * JSArrayBuffer::extension_lo () const {
126
+ ExternalPointerHandle * JSArrayBuffer::extension_handle_location () const {
132
127
Address location = field_address (kExtensionOffset );
133
- return reinterpret_cast <uint32_t *>(location);
128
+ return reinterpret_cast <ExternalPointerHandle *>(location);
134
129
}
135
-
136
- uint32_t * JSArrayBuffer::extension_hi () const {
137
- Address location = field_address (kExtensionOffset ) + sizeof ( uint32_t ) ;
138
- return reinterpret_cast <uint32_t *>(location);
130
+ # else
131
+ ArrayBufferExtension** JSArrayBuffer::extension_location () const {
132
+ Address location = field_address (kExtensionOffset );
133
+ return reinterpret_cast <ArrayBufferExtension* *>(location);
139
134
}
140
- #endif
135
+ #endif // V8_COMPRESS_POINTERS
141
136
142
137
void JSArrayBuffer::clear_padding () {
143
138
if (FIELD_SIZE (kOptionalPaddingOffset ) != 0 ) {
0 commit comments