From b0404047c1e4f7652aaf6ecf911d5850d5acf570 Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Sun, 13 May 2018 19:39:32 +0200 Subject: worker: add `SharedArrayBuffer` sharing Logic is added to the `MessagePort` mechanism that attaches hidden objects to those instances when they are transferred that track their lifetime and maintain a reference count, to make sure that memory is freed at the appropriate times. Thanks to Stephen Belanger for reviewing this change in its original PR. Refs: https://github.com/ayojs/ayo/pull/106 PR-URL: https://github.com/nodejs/node/pull/20876 Reviewed-By: Gireesh Punathil Reviewed-By: Benjamin Gruenbaum Reviewed-By: Shingo Inoue Reviewed-By: Matteo Collina Reviewed-By: Tiancheng "Timothy" Gu Reviewed-By: John-David Dalton Reviewed-By: Gus Caplan --- src/node_messaging.cc | 57 ++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 54 insertions(+), 3 deletions(-) (limited to 'src/node_messaging.cc') diff --git a/src/node_messaging.cc b/src/node_messaging.cc index 1c6551e096..ede38cc817 100644 --- a/src/node_messaging.cc +++ b/src/node_messaging.cc @@ -24,6 +24,7 @@ using v8::Maybe; using v8::MaybeLocal; using v8::Nothing; using v8::Object; +using v8::SharedArrayBuffer; using v8::String; using v8::Value; using v8::ValueDeserializer; @@ -43,8 +44,13 @@ class DeserializerDelegate : public ValueDeserializer::Delegate { public: DeserializerDelegate(Message* m, Environment* env, - const std::vector& message_ports) - : env_(env), msg_(m), message_ports_(message_ports) {} + const std::vector& message_ports, + const std::vector>& + shared_array_buffers) + : env_(env), + msg_(m), + message_ports_(message_ports), + shared_array_buffers_(shared_array_buffers) {} MaybeLocal ReadHostObject(Isolate* isolate) override { // Currently, only MessagePort hosts objects are supported, so identifying @@ -56,12 +62,19 @@ class DeserializerDelegate : public ValueDeserializer::Delegate { return message_ports_[id]->object(); }; + MaybeLocal GetSharedArrayBufferFromId( + Isolate* isolate, uint32_t clone_id) override { + CHECK_LE(clone_id, shared_array_buffers_.size()); + return shared_array_buffers_[clone_id]; + } + ValueDeserializer* deserializer = nullptr; private: Environment* env_; Message* msg_; const std::vector& message_ports_; + const std::vector>& shared_array_buffers_; }; } // anonymous namespace @@ -87,7 +100,18 @@ MaybeLocal Message::Deserialize(Environment* env, } message_ports_.clear(); - DeserializerDelegate delegate(this, env, ports); + std::vector> shared_array_buffers; + // Attach all transfered SharedArrayBuffers to their new Isolate. + for (uint32_t i = 0; i < shared_array_buffers_.size(); ++i) { + Local sab; + if (!shared_array_buffers_[i]->GetSharedArrayBuffer(env, context) + .ToLocal(&sab)) + return MaybeLocal(); + shared_array_buffers.push_back(sab); + } + shared_array_buffers_.clear(); + + DeserializerDelegate delegate(this, env, ports, shared_array_buffers); ValueDeserializer deserializer( env->isolate(), reinterpret_cast(main_message_buf_.data), @@ -112,6 +136,11 @@ MaybeLocal Message::Deserialize(Environment* env, deserializer.ReadValue(context).FromMaybe(Local())); } +void Message::AddSharedArrayBuffer( + SharedArrayBufferMetadataReference reference) { + shared_array_buffers_.push_back(reference); +} + void Message::AddMessagePort(std::unique_ptr&& data) { message_ports_.emplace_back(std::move(data)); } @@ -139,6 +168,27 @@ class SerializerDelegate : public ValueSerializer::Delegate { return Nothing(); } + Maybe GetSharedArrayBufferId( + Isolate* isolate, + Local shared_array_buffer) override { + uint32_t i; + for (i = 0; i < seen_shared_array_buffers_.size(); ++i) { + if (seen_shared_array_buffers_[i] == shared_array_buffer) + return Just(i); + } + + auto reference = SharedArrayBufferMetadata::ForSharedArrayBuffer( + env_, + context_, + shared_array_buffer); + if (!reference) { + return Nothing(); + } + seen_shared_array_buffers_.push_back(shared_array_buffer); + msg_->AddSharedArrayBuffer(reference); + return Just(i); + } + void Finish() { // Only close the MessagePort handles and actually transfer them // once we know that serialization succeeded. @@ -166,6 +216,7 @@ class SerializerDelegate : public ValueSerializer::Delegate { Environment* env_; Local context_; Message* msg_; + std::vector> seen_shared_array_buffers_; std::vector ports_; friend class worker::Message; -- cgit v1.2.3