Files
node/src/sharedarraybuffer_metadata.h
T
Anna Henningsen 7899a96e66 worker: keep allocators for transferred SAB instances alive longer
Keep the `ArrayBuffer::Allocator` behind a `SharedArrayBuffer` instance
alive for at least as long as the receiving Isolate lives, if the
`SharedArrayBuffer` instance isn’t already destroyed through GC.

This is to work around the fact that V8 7.9 started refactoring
how backing stores for `SharedArrayBuffer` instances work, changing
the timing of the call that releases the backing store to be
during Isolate disposal.

The flag added to the test is optional but helps verify that the
backing store is actually free’d at the end of the test and does not
leak memory.

Fixes: https://github.com/nodejs/node-v8/issues/115
PR-URL: https://github.com/nodejs/node/pull/29637
Reviewed-By: Rich Trott <rtrott@gmail.com>
Reviewed-By: Michaël Zasso <targos@protonmail.com>
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
2019-09-24 21:35:40 -07:00

73 lines
2.6 KiB
C++

#ifndef SRC_SHAREDARRAYBUFFER_METADATA_H_
#define SRC_SHAREDARRAYBUFFER_METADATA_H_
#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
#include "node.h"
#include <memory>
namespace node {
namespace worker {
class SharedArrayBufferMetadata;
// This is an object associated with a SharedArrayBuffer, which keeps track
// of a cross-thread reference count. Once a SharedArrayBuffer is transferred
// for the first time (or is attempted to be transferred), one of these objects
// is created, and the SharedArrayBuffer is moved from internalized mode into
// externalized mode (i.e. the JS engine no longer frees the memory on its own).
//
// This will always be referred to using a std::shared_ptr, since it keeps
// a reference count and is guaranteed to be thread-safe.
typedef std::shared_ptr<SharedArrayBufferMetadata>
SharedArrayBufferMetadataReference;
class SharedArrayBufferMetadata
: public std::enable_shared_from_this<SharedArrayBufferMetadata> {
public:
static SharedArrayBufferMetadataReference ForSharedArrayBuffer(
Environment* env,
v8::Local<v8::Context> context,
v8::Local<v8::SharedArrayBuffer> source);
~SharedArrayBufferMetadata();
// Create a SharedArrayBuffer object for a specific Environment and Context.
// The created SharedArrayBuffer will be in externalized mode and has
// a hidden object attached to it, during whose lifetime the reference
// count is increased by 1.
v8::MaybeLocal<v8::SharedArrayBuffer> GetSharedArrayBuffer(
Environment* env, v8::Local<v8::Context> context);
std::shared_ptr<v8::ArrayBuffer::Allocator> allocator() const {
return allocator_;
}
SharedArrayBufferMetadata(SharedArrayBufferMetadata&& other) = delete;
SharedArrayBufferMetadata& operator=(
SharedArrayBufferMetadata&& other) = delete;
SharedArrayBufferMetadata& operator=(
const SharedArrayBufferMetadata&) = delete;
SharedArrayBufferMetadata(const SharedArrayBufferMetadata&) = delete;
private:
SharedArrayBufferMetadata(
const v8::SharedArrayBuffer::Contents&,
std::shared_ptr<v8::ArrayBuffer::Allocator>);
// Attach a lifetime tracker object with a reference count to `target`.
v8::Maybe<bool> AssignToSharedArrayBuffer(
Environment* env,
v8::Local<v8::Context> context,
v8::Local<v8::SharedArrayBuffer> target);
v8::SharedArrayBuffer::Contents contents_;
std::shared_ptr<v8::ArrayBuffer::Allocator> allocator_;
};
} // namespace worker
} // namespace node
#endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
#endif // SRC_SHAREDARRAYBUFFER_METADATA_H_