Skip to content

Commit 2bdeb88

Browse files
addaleaxtargos
authored andcommitted
src: remove custom tracking for SharedArrayBuffers
Remove custom tracking for `SharedArrayBuffer`s and their allocators and instead let V8 do the tracking of both. This is required starting in V8 7.9, because lifetime management for `ArrayBuffer::Allocator`s differs from what was performed previously (i.e. it is no longer easily possible for one Isolate to release an `ArrayBuffer` and another to accept it into its own allocator), and the alternative would have been adapting the `SharedArrayBuffer` tracking logic to also apply to regular `ArrayBuffer` instances. Refs: #30044 PR-URL: #30020 Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Jiawen Geng <technicalcute@gmail.com> Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
1 parent 2707efd commit 2bdeb88

13 files changed

+58
-335
lines changed

node.gyp

-2
Original file line numberDiff line numberDiff line change
@@ -564,7 +564,6 @@
564564
'src/node_zlib.cc',
565565
'src/pipe_wrap.cc',
566566
'src/process_wrap.cc',
567-
'src/sharedarraybuffer_metadata.cc',
568567
'src/signal_wrap.cc',
569568
'src/spawn_sync.cc',
570569
'src/stream_base.cc',
@@ -642,7 +641,6 @@
642641
'src/pipe_wrap.h',
643642
'src/req_wrap.h',
644643
'src/req_wrap-inl.h',
645-
'src/sharedarraybuffer_metadata.h',
646644
'src/spawn_sync.h',
647645
'src/stream_base.h',
648646
'src/stream_base-inl.h',

src/api/environment.cc

+8
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,14 @@ Isolate* NewIsolate(ArrayBufferAllocator* allocator,
279279
return NewIsolate(&params, event_loop, platform);
280280
}
281281

282+
Isolate* NewIsolate(std::shared_ptr<ArrayBufferAllocator> allocator,
283+
uv_loop_t* event_loop,
284+
MultiIsolatePlatform* platform) {
285+
Isolate::CreateParams params;
286+
if (allocator) params.array_buffer_allocator_shared = allocator;
287+
return NewIsolate(&params, event_loop, platform);
288+
}
289+
282290
IsolateData* CreateIsolateData(Isolate* isolate,
283291
uv_loop_t* loop,
284292
MultiIsolatePlatform* platform,

src/env.cc

-15
Original file line numberDiff line numberDiff line change
@@ -1038,21 +1038,6 @@ char* Environment::Reallocate(char* data, size_t old_size, size_t size) {
10381038
return new_data;
10391039
}
10401040

1041-
void Environment::AddArrayBufferAllocatorToKeepAliveUntilIsolateDispose(
1042-
std::shared_ptr<v8::ArrayBuffer::Allocator> allocator) {
1043-
if (keep_alive_allocators_ == nullptr) {
1044-
MultiIsolatePlatform* platform = isolate_data()->platform();
1045-
CHECK_NOT_NULL(platform);
1046-
1047-
keep_alive_allocators_ = new ArrayBufferAllocatorList();
1048-
platform->AddIsolateFinishedCallback(isolate(), [](void* data) {
1049-
delete static_cast<ArrayBufferAllocatorList*>(data);
1050-
}, static_cast<void*>(keep_alive_allocators_));
1051-
}
1052-
1053-
keep_alive_allocators_->insert(allocator);
1054-
}
1055-
10561041
bool Environment::RunWeakRefCleanup() {
10571042
isolate()->ClearKeptObjects();
10581043

src/env.h

-9
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,6 @@ constexpr size_t kFsStatsBufferLength =
156156
V(contextify_global_private_symbol, "node:contextify:global") \
157157
V(decorated_private_symbol, "node:decorated") \
158158
V(napi_wrapper, "node:napi:wrapper") \
159-
V(sab_lifetimepartner_symbol, "node:sharedArrayBufferLifetimePartner") \
160159

161160
// Symbols are per-isolate primitives but Environment proxies them
162161
// for the sake of convenience.
@@ -1250,10 +1249,6 @@ class Environment : public MemoryRetainer {
12501249

12511250
#endif // HAVE_INSPECTOR
12521251

1253-
// Only available if a MultiIsolatePlatform is in use.
1254-
void AddArrayBufferAllocatorToKeepAliveUntilIsolateDispose(
1255-
std::shared_ptr<v8::ArrayBuffer::Allocator>);
1256-
12571252
private:
12581253
template <typename Fn>
12591254
inline void CreateImmediate(Fn&& cb,
@@ -1433,10 +1428,6 @@ class Environment : public MemoryRetainer {
14331428
// Used by embedders to shutdown running Node instance.
14341429
AsyncRequest thread_stopper_;
14351430

1436-
typedef std::unordered_set<std::shared_ptr<v8::ArrayBuffer::Allocator>>
1437-
ArrayBufferAllocatorList;
1438-
ArrayBufferAllocatorList* keep_alive_allocators_ = nullptr;
1439-
14401431
template <typename T>
14411432
void ForEachBaseObject(T&& iterator);
14421433

src/memory_tracker-inl.h

+16
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,16 @@ void MemoryTracker::TrackField(const char* edge_name,
109109
TrackField(edge_name, value.get(), node_name);
110110
}
111111

112+
template <typename T>
113+
void MemoryTracker::TrackField(const char* edge_name,
114+
const std::shared_ptr<T>& value,
115+
const char* node_name) {
116+
if (value.get() == nullptr) {
117+
return;
118+
}
119+
TrackField(edge_name, value.get(), node_name);
120+
}
121+
112122
template <typename T, typename Iterator>
113123
void MemoryTracker::TrackField(const char* edge_name,
114124
const T& value,
@@ -206,6 +216,12 @@ void MemoryTracker::TrackField(const char* edge_name,
206216
TrackFieldWithSize(edge_name, value.size, "MallocedBuffer");
207217
}
208218

219+
void MemoryTracker::TrackField(const char* edge_name,
220+
const v8::BackingStore* value,
221+
const char* node_name) {
222+
TrackFieldWithSize(edge_name, value->ByteLength(), "BackingStore");
223+
}
224+
209225
void MemoryTracker::TrackField(const char* name,
210226
const uv_buf_t& value,
211227
const char* node_name) {

src/memory_tracker.h

+7
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,10 @@ class MemoryTracker {
138138
inline void TrackField(const char* edge_name,
139139
const std::unique_ptr<T>& value,
140140
const char* node_name = nullptr);
141+
template <typename T>
142+
inline void TrackField(const char* edge_name,
143+
const std::shared_ptr<T>& value,
144+
const char* node_name = nullptr);
141145

142146
// For containers, the elements will be graphed as grandchildren nodes
143147
// if the container is not empty.
@@ -197,6 +201,9 @@ class MemoryTracker {
197201
inline void TrackField(const char* edge_name,
198202
const MallocedBuffer<T>& value,
199203
const char* node_name = nullptr);
204+
inline void TrackField(const char* edge_name,
205+
const v8::BackingStore* value,
206+
const char* node_name = nullptr);
200207
// We do not implement CleanupHookCallback as MemoryRetainer
201208
// but instead specialize the method here to avoid the cost of
202209
// virtual pointers.

src/node.h

+4
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,10 @@ NODE_EXTERN v8::Isolate* NewIsolate(ArrayBufferAllocator* allocator,
328328
NODE_EXTERN v8::Isolate* NewIsolate(ArrayBufferAllocator* allocator,
329329
struct uv_loop_s* event_loop,
330330
MultiIsolatePlatform* platform);
331+
NODE_EXTERN v8::Isolate* NewIsolate(
332+
std::shared_ptr<ArrayBufferAllocator> allocator,
333+
struct uv_loop_s* event_loop,
334+
MultiIsolatePlatform* platform);
331335

332336
// Creates a new context with Node.js-specific tweaks.
333337
NODE_EXTERN v8::Local<v8::Context> NewContext(

src/node_messaging.cc

+16-49
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
using node::contextify::ContextifyContext;
1313
using v8::Array;
1414
using v8::ArrayBuffer;
15-
using v8::ArrayBufferCreationMode;
15+
using v8::BackingStore;
1616
using v8::Context;
1717
using v8::EscapableHandleScope;
1818
using v8::Exception;
@@ -123,10 +123,9 @@ MaybeLocal<Value> Message::Deserialize(Environment* env,
123123
std::vector<Local<SharedArrayBuffer>> shared_array_buffers;
124124
// Attach all transferred SharedArrayBuffers to their new Isolate.
125125
for (uint32_t i = 0; i < shared_array_buffers_.size(); ++i) {
126-
Local<SharedArrayBuffer> sab;
127-
if (!shared_array_buffers_[i]->GetSharedArrayBuffer(env, context)
128-
.ToLocal(&sab))
129-
return MaybeLocal<Value>();
126+
Local<SharedArrayBuffer> sab =
127+
SharedArrayBuffer::New(env->isolate(),
128+
std::move(shared_array_buffers_[i]));
130129
shared_array_buffers.push_back(sab);
131130
}
132131
shared_array_buffers_.clear();
@@ -141,30 +140,12 @@ MaybeLocal<Value> Message::Deserialize(Environment* env,
141140
delegate.deserializer = &deserializer;
142141

143142
// Attach all transferred ArrayBuffers to their new Isolate.
144-
for (uint32_t i = 0; i < array_buffer_contents_.size(); ++i) {
145-
if (!env->isolate_data()->uses_node_allocator()) {
146-
// We don't use Node's allocator on the receiving side, so we have
147-
// to create the ArrayBuffer from a copy of the memory.
148-
AllocatedBuffer buf =
149-
env->AllocateManaged(array_buffer_contents_[i].size);
150-
memcpy(buf.data(),
151-
array_buffer_contents_[i].data,
152-
array_buffer_contents_[i].size);
153-
deserializer.TransferArrayBuffer(i, buf.ToArrayBuffer());
154-
continue;
155-
}
156-
157-
env->isolate_data()->node_allocator()->RegisterPointer(
158-
array_buffer_contents_[i].data, array_buffer_contents_[i].size);
159-
143+
for (uint32_t i = 0; i < array_buffers_.size(); ++i) {
160144
Local<ArrayBuffer> ab =
161-
ArrayBuffer::New(env->isolate(),
162-
array_buffer_contents_[i].release(),
163-
array_buffer_contents_[i].size,
164-
ArrayBufferCreationMode::kInternalized);
145+
ArrayBuffer::New(env->isolate(), std::move(array_buffers_[i]));
165146
deserializer.TransferArrayBuffer(i, ab);
166147
}
167-
array_buffer_contents_.clear();
148+
array_buffers_.clear();
168149

169150
if (deserializer.ReadHeader(context).IsNothing())
170151
return MaybeLocal<Value>();
@@ -173,8 +154,8 @@ MaybeLocal<Value> Message::Deserialize(Environment* env,
173154
}
174155

175156
void Message::AddSharedArrayBuffer(
176-
const SharedArrayBufferMetadataReference& reference) {
177-
shared_array_buffers_.push_back(reference);
157+
std::shared_ptr<BackingStore> backing_store) {
158+
shared_array_buffers_.emplace_back(std::move(backing_store));
178159
}
179160

180161
void Message::AddMessagePort(std::unique_ptr<MessagePortData>&& data) {
@@ -249,16 +230,9 @@ class SerializerDelegate : public ValueSerializer::Delegate {
249230
}
250231
}
251232

252-
auto reference = SharedArrayBufferMetadata::ForSharedArrayBuffer(
253-
env_,
254-
context_,
255-
shared_array_buffer);
256-
if (!reference) {
257-
return Nothing<uint32_t>();
258-
}
259233
seen_shared_array_buffers_.emplace_back(
260234
Global<SharedArrayBuffer> { isolate, shared_array_buffer });
261-
msg_->AddSharedArrayBuffer(reference);
235+
msg_->AddSharedArrayBuffer(shared_array_buffer->GetBackingStore());
262236
return Just(i);
263237
}
264238

@@ -386,18 +360,12 @@ Maybe<bool> Message::Serialize(Environment* env,
386360
}
387361

388362
for (Local<ArrayBuffer> ab : array_buffers) {
389-
// If serialization succeeded, we want to take ownership of
390-
// (a.k.a. externalize) the underlying memory region and render
391-
// it inaccessible in this Isolate.
392-
ArrayBuffer::Contents contents = ab->Externalize();
363+
// If serialization succeeded, we render it inaccessible in this Isolate.
364+
std::shared_ptr<BackingStore> backing_store = ab->GetBackingStore();
365+
ab->Externalize(backing_store);
393366
ab->Detach();
394367

395-
CHECK(env->isolate_data()->uses_node_allocator());
396-
env->isolate_data()->node_allocator()->UnregisterPointer(
397-
contents.Data(), contents.ByteLength());
398-
399-
array_buffer_contents_.emplace_back(MallocedBuffer<char>{
400-
static_cast<char*>(contents.Data()), contents.ByteLength()});
368+
array_buffers_.emplace_back(std::move(backing_store));
401369
}
402370

403371
delegate.Finish();
@@ -411,9 +379,8 @@ Maybe<bool> Message::Serialize(Environment* env,
411379
}
412380

413381
void Message::MemoryInfo(MemoryTracker* tracker) const {
414-
tracker->TrackField("array_buffer_contents", array_buffer_contents_);
415-
tracker->TrackFieldWithSize("shared_array_buffers",
416-
shared_array_buffers_.size() * sizeof(shared_array_buffers_[0]));
382+
tracker->TrackField("array_buffers_", array_buffers_);
383+
tracker->TrackField("shared_array_buffers", shared_array_buffers_);
417384
tracker->TrackField("message_ports", message_ports_);
418385
}
419386

src/node_messaging.h

+3-4
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55

66
#include "env.h"
77
#include "node_mutex.h"
8-
#include "sharedarraybuffer_metadata.h"
98
#include <list>
109

1110
namespace node {
@@ -52,7 +51,7 @@ class Message : public MemoryRetainer {
5251

5352
// Internal method of Message that is called when a new SharedArrayBuffer
5453
// object is encountered in the incoming value's structure.
55-
void AddSharedArrayBuffer(const SharedArrayBufferMetadataReference& ref);
54+
void AddSharedArrayBuffer(std::shared_ptr<v8::BackingStore> backing_store);
5655
// Internal method of Message that is called once serialization finishes
5756
// and that transfers ownership of `data` to this message.
5857
void AddMessagePort(std::unique_ptr<MessagePortData>&& data);
@@ -74,8 +73,8 @@ class Message : public MemoryRetainer {
7473

7574
private:
7675
MallocedBuffer<char> main_message_buf_;
77-
std::vector<MallocedBuffer<char>> array_buffer_contents_;
78-
std::vector<SharedArrayBufferMetadataReference> shared_array_buffers_;
76+
std::vector<std::shared_ptr<v8::BackingStore>> array_buffers_;
77+
std::vector<std::shared_ptr<v8::BackingStore>> shared_array_buffers_;
7978
std::vector<std::unique_ptr<MessagePortData>> message_ports_;
8079
std::vector<v8::WasmModuleObject::TransferrableModule> wasm_modules_;
8180

src/node_worker.cc

+4-7
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,6 @@ Worker::Worker(Environment* env,
5151
per_isolate_opts_(per_isolate_opts),
5252
exec_argv_(exec_argv),
5353
platform_(env->isolate_data()->platform()),
54-
array_buffer_allocator_(ArrayBufferAllocator::Create()),
5554
start_profiler_idle_notifier_(env->profiler_idle_notifier_started()),
5655
thread_id_(Environment::AllocateThreadId()),
5756
env_vars_(env->env_vars()) {
@@ -95,10 +94,6 @@ bool Worker::is_stopped() const {
9594
return stopped_;
9695
}
9796

98-
std::shared_ptr<ArrayBufferAllocator> Worker::array_buffer_allocator() {
99-
return array_buffer_allocator_;
100-
}
101-
10297
void Worker::UpdateResourceConstraints(ResourceConstraints* constraints) {
10398
constraints->set_stack_limit(reinterpret_cast<uint32_t*>(stack_base_));
10499

@@ -138,9 +133,11 @@ class WorkerThreadData {
138133
: w_(w) {
139134
CHECK_EQ(uv_loop_init(&loop_), 0);
140135

136+
std::shared_ptr<ArrayBufferAllocator> allocator =
137+
ArrayBufferAllocator::Create();
141138
Isolate::CreateParams params;
142139
SetIsolateCreateParamsForNode(&params);
143-
params.array_buffer_allocator = w->array_buffer_allocator_.get();
140+
params.array_buffer_allocator_shared = allocator;
144141

145142
w->UpdateResourceConstraints(&params.constraints);
146143

@@ -164,7 +161,7 @@ class WorkerThreadData {
164161
isolate_data_.reset(CreateIsolateData(isolate,
165162
&loop_,
166163
w_->platform_,
167-
w->array_buffer_allocator_.get()));
164+
allocator.get()));
168165
CHECK(isolate_data_);
169166
if (w_->per_isolate_opts_)
170167
isolate_data_->set_options(std::move(w_->per_isolate_opts_));

src/node_worker.h

-2
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,6 @@ class Worker : public AsyncWrap {
4848
SET_SELF_SIZE(Worker)
4949

5050
bool is_stopped() const;
51-
std::shared_ptr<ArrayBufferAllocator> array_buffer_allocator();
5251

5352
static void New(const v8::FunctionCallbackInfo<v8::Value>& args);
5453
static void CloneParentEnvVars(
@@ -72,7 +71,6 @@ class Worker : public AsyncWrap {
7271
std::vector<std::string> argv_;
7372

7473
MultiIsolatePlatform* platform_;
75-
std::shared_ptr<ArrayBufferAllocator> array_buffer_allocator_;
7674
v8::Isolate* isolate_ = nullptr;
7775
bool start_profiler_idle_notifier_;
7876
uv_thread_t tid_;

0 commit comments

Comments
 (0)