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