Skip to content

Commit

Permalink
src: extract AllocatedBuffer from env.h
Browse files Browse the repository at this point in the history
Cleanup up env.h by removing things that are not
specific to `Environment`.

PR-URL: #33291
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: David Carlier <devnexen@gmail.com>
  • Loading branch information
jasnell committed May 30, 2020
1 parent c24b74a commit 56ff1ee
Show file tree
Hide file tree
Showing 23 changed files with 241 additions and 161 deletions.
2 changes: 2 additions & 0 deletions node.gyp
Original file line number Diff line number Diff line change
Expand Up @@ -643,6 +643,8 @@
'src/aliased_buffer.h',
'src/aliased_struct.h',
'src/aliased_struct-inl.h',
'src/allocated_buffer.h',
'src/allocated_buffer-inl.h'
'src/async_wrap.h',
'src/async_wrap-inl.h',
'src/base_object.h',
Expand Down
110 changes: 110 additions & 0 deletions src/allocated_buffer-inl.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
#ifndef SRC_ALLOCATED_BUFFER_INL_H_
#define SRC_ALLOCATED_BUFFER_INL_H_

#include "allocated_buffer.h"
#include "base_object-inl.h"
#include "node_buffer.h"
#include "env-inl.h"
#include "uv.h"
#include "v8.h"
#include "util-inl.h"
#include "node_internals.h"

namespace node {

AllocatedBuffer AllocatedBuffer::AllocateManaged(
Environment* env,
size_t size,
int flags) {
char* data = flags & ALLOCATE_MANAGED_UNCHECKED ?
env->AllocateUnchecked(size) :
env->Allocate(size);
if (data == nullptr) size = 0;
return AllocatedBuffer(env, uv_buf_init(data, size));
}

inline AllocatedBuffer::AllocatedBuffer(Environment* env, uv_buf_t buf)
: env_(env), buffer_(buf) {}

inline void AllocatedBuffer::Resize(size_t len) {
// The `len` check is to make sure we don't end up with `nullptr` as our base.
char* new_data = env_->Reallocate(buffer_.base, buffer_.len,
len > 0 ? len : 1);
CHECK_NOT_NULL(new_data);
buffer_ = uv_buf_init(new_data, len);
}

inline uv_buf_t AllocatedBuffer::release() {
uv_buf_t ret = buffer_;
buffer_ = uv_buf_init(nullptr, 0);
return ret;
}

inline char* AllocatedBuffer::data() {
return buffer_.base;
}

inline const char* AllocatedBuffer::data() const {
return buffer_.base;
}

inline size_t AllocatedBuffer::size() const {
return buffer_.len;
}

inline AllocatedBuffer::AllocatedBuffer(Environment* env)
: env_(env), buffer_(uv_buf_init(nullptr, 0)) {}

inline AllocatedBuffer::AllocatedBuffer(AllocatedBuffer&& other)
: AllocatedBuffer() {
*this = std::move(other);
}

inline AllocatedBuffer& AllocatedBuffer::operator=(AllocatedBuffer&& other) {
clear();
env_ = other.env_;
buffer_ = other.release();
return *this;
}

inline AllocatedBuffer::~AllocatedBuffer() {
clear();
}

inline void AllocatedBuffer::clear() {
uv_buf_t buf = release();
if (buf.base != nullptr) {
CHECK_NOT_NULL(env_);
env_->Free(buf.base, buf.len);
}
}

inline v8::MaybeLocal<v8::Object> AllocatedBuffer::ToBuffer() {
CHECK_NOT_NULL(env_);
v8::MaybeLocal<v8::Object> obj = Buffer::New(env_, data(), size(), false);
if (!obj.IsEmpty()) release();
return obj;
}

inline v8::Local<v8::ArrayBuffer> AllocatedBuffer::ToArrayBuffer() {
CHECK_NOT_NULL(env_);
uv_buf_t buf = release();
auto callback = [](void* data, size_t length, void* deleter_data){
CHECK_NOT_NULL(deleter_data);

static_cast<v8::ArrayBuffer::Allocator*>(deleter_data)
->Free(data, length);
};
std::unique_ptr<v8::BackingStore> backing =
v8::ArrayBuffer::NewBackingStore(buf.base,
buf.len,
callback,
env_->isolate()
->GetArrayBufferAllocator());
return v8::ArrayBuffer::New(env_->isolate(),
std::move(backing));
}

} // namespace node

#endif // SRC_ALLOCATED_BUFFER_INL_H_
63 changes: 63 additions & 0 deletions src/allocated_buffer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
#ifndef SRC_ALLOCATED_BUFFER_H_
#define SRC_ALLOCATED_BUFFER_H_

#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS

#include "base_object.h"
#include "uv.h"
#include "v8.h"

namespace node {

class Environment;

// A unique-pointer-ish object that is compatible with the JS engine's
// ArrayBuffer::Allocator.
struct AllocatedBuffer {
public:
enum AllocateManagedFlags {
ALLOCATE_MANAGED_FLAG_NONE,
ALLOCATE_MANAGED_UNCHECKED
};

// Utilities that allocate memory using the Isolate's ArrayBuffer::Allocator.
// In particular, using AllocateManaged() will provide a RAII-style object
// with easy conversion to `Buffer` and `ArrayBuffer` objects.
inline static AllocatedBuffer AllocateManaged(
Environment* env,
size_t size,
int flags = ALLOCATE_MANAGED_FLAG_NONE);

explicit inline AllocatedBuffer(Environment* env = nullptr);
inline AllocatedBuffer(Environment* env, uv_buf_t buf);
inline ~AllocatedBuffer();
inline void Resize(size_t len);

inline uv_buf_t release();
inline char* data();
inline const char* data() const;
inline size_t size() const;
inline void clear();

inline v8::MaybeLocal<v8::Object> ToBuffer();
inline v8::Local<v8::ArrayBuffer> ToArrayBuffer();

inline AllocatedBuffer(AllocatedBuffer&& other);
inline AllocatedBuffer& operator=(AllocatedBuffer&& other);
AllocatedBuffer(const AllocatedBuffer& other) = delete;
AllocatedBuffer& operator=(const AllocatedBuffer& other) = delete;

private:
Environment* env_;
// We do not pass this to libuv directly, but uv_buf_t is a convenient way
// to represent a chunk of memory, and plays nicely with other parts of core.
uv_buf_t buffer_;

friend class Environment;
};

} // namespace node

#endif // NODE_WANT_INTERNALS

#endif // SRC_ALLOCATED_BUFFER_H_
88 changes: 0 additions & 88 deletions src/env-inl.h
Original file line number Diff line number Diff line change
Expand Up @@ -883,68 +883,6 @@ inline void Environment::Free(char* data, size_t size) {
isolate_data()->allocator()->Free(data, size);
}

inline AllocatedBuffer Environment::AllocateManaged(size_t size, bool checked) {
char* data = checked ? Allocate(size) : AllocateUnchecked(size);
if (data == nullptr) size = 0;
return AllocatedBuffer(this, uv_buf_init(data, size));
}

inline AllocatedBuffer::AllocatedBuffer(Environment* env, uv_buf_t buf)
: env_(env), buffer_(buf) {}

inline void AllocatedBuffer::Resize(size_t len) {
// The `len` check is to make sure we don't end up with `nullptr` as our base.
char* new_data = env_->Reallocate(buffer_.base, buffer_.len,
len > 0 ? len : 1);
CHECK_NOT_NULL(new_data);
buffer_ = uv_buf_init(new_data, len);
}

inline uv_buf_t AllocatedBuffer::release() {
uv_buf_t ret = buffer_;
buffer_ = uv_buf_init(nullptr, 0);
return ret;
}

inline char* AllocatedBuffer::data() {
return buffer_.base;
}

inline const char* AllocatedBuffer::data() const {
return buffer_.base;
}

inline size_t AllocatedBuffer::size() const {
return buffer_.len;
}

inline AllocatedBuffer::AllocatedBuffer(Environment* env)
: env_(env), buffer_(uv_buf_init(nullptr, 0)) {}

inline AllocatedBuffer::AllocatedBuffer(AllocatedBuffer&& other)
: AllocatedBuffer() {
*this = std::move(other);
}

inline AllocatedBuffer& AllocatedBuffer::operator=(AllocatedBuffer&& other) {
clear();
env_ = other.env_;
buffer_ = other.release();
return *this;
}

inline AllocatedBuffer::~AllocatedBuffer() {
clear();
}

inline void AllocatedBuffer::clear() {
uv_buf_t buf = release();
if (buf.base != nullptr) {
CHECK_NOT_NULL(env_);
env_->Free(buf.base, buf.len);
}
}

// It's a bit awkward to define this Buffer::New() overload here, but it
// avoids a circular dependency with node_internals.h.
namespace Buffer {
Expand All @@ -954,32 +892,6 @@ v8::MaybeLocal<v8::Object> New(Environment* env,
bool uses_malloc);
}

inline v8::MaybeLocal<v8::Object> AllocatedBuffer::ToBuffer() {
CHECK_NOT_NULL(env_);
v8::MaybeLocal<v8::Object> obj = Buffer::New(env_, data(), size(), false);
if (!obj.IsEmpty()) release();
return obj;
}

inline v8::Local<v8::ArrayBuffer> AllocatedBuffer::ToArrayBuffer() {
CHECK_NOT_NULL(env_);
uv_buf_t buf = release();
auto callback = [](void* data, size_t length, void* deleter_data){
CHECK_NOT_NULL(deleter_data);

static_cast<v8::ArrayBuffer::Allocator*>(deleter_data)
->Free(data, length);
};
std::unique_ptr<v8::BackingStore> backing =
v8::ArrayBuffer::NewBackingStore(buf.base,
buf.len,
callback,
env_->isolate()
->GetArrayBufferAllocator());
return v8::ArrayBuffer::New(env_->isolate(),
std::move(backing));
}

inline void Environment::ThrowError(const char* errmsg) {
ThrowError(v8::Exception::Error, errmsg);
}
Expand Down
2 changes: 1 addition & 1 deletion src/env.cc
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#include "env.h"

#include "allocated_buffer-inl.h"
#include "async_wrap.h"
#include "base_object-inl.h"
#include "debug_utils-inl.h"
Expand Down
37 changes: 1 addition & 36 deletions src/env.h
Original file line number Diff line number Diff line change
Expand Up @@ -472,6 +472,7 @@ constexpr size_t kFsStatsBufferLength =
V(url_constructor_function, v8::Function)

class Environment;
struct AllocatedBuffer;

class IsolateData : public MemoryRetainer {
public:
Expand Down Expand Up @@ -558,38 +559,6 @@ struct ContextInfo {

class EnabledDebugList;

// A unique-pointer-ish object that is compatible with the JS engine's
// ArrayBuffer::Allocator.
struct AllocatedBuffer {
public:
explicit inline AllocatedBuffer(Environment* env = nullptr);
inline AllocatedBuffer(Environment* env, uv_buf_t buf);
inline ~AllocatedBuffer();
inline void Resize(size_t len);

inline uv_buf_t release();
inline char* data();
inline const char* data() const;
inline size_t size() const;
inline void clear();

inline v8::MaybeLocal<v8::Object> ToBuffer();
inline v8::Local<v8::ArrayBuffer> ToArrayBuffer();

inline AllocatedBuffer(AllocatedBuffer&& other);
inline AllocatedBuffer& operator=(AllocatedBuffer&& other);
AllocatedBuffer(const AllocatedBuffer& other) = delete;
AllocatedBuffer& operator=(const AllocatedBuffer& other) = delete;

private:
Environment* env_;
// We do not pass this to libuv directly, but uv_buf_t is a convenient way
// to represent a chunk of memory, and plays nicely with other parts of core.
uv_buf_t buffer_;

friend class Environment;
};

class KVStore {
public:
KVStore() = default;
Expand Down Expand Up @@ -957,10 +926,6 @@ class Environment : public MemoryRetainer {

inline IsolateData* isolate_data() const;

// Utilities that allocate memory using the Isolate's ArrayBuffer::Allocator.
// In particular, using AllocateManaged() will provide a RAII-style object
// with easy conversion to `Buffer` and `ArrayBuffer` objects.
inline AllocatedBuffer AllocateManaged(size_t size, bool checked = true);
inline char* Allocate(size_t size);
inline char* AllocateUnchecked(size_t size);
char* Reallocate(char* data, size_t old_size, size_t size);
Expand Down
1 change: 1 addition & 0 deletions src/inspector_io.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include "inspector_socket_server.h"
#include "inspector/main_thread_interface.h"
#include "inspector/node_string.h"
#include "allocated_buffer-inl.h" // Inlined functions needed by node_crypto.h.
#include "base_object-inl.h"
#include "debug_utils-inl.h"
#include "node.h"
Expand Down
1 change: 1 addition & 0 deletions src/node.cc
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
#include "node_version.h"

#if HAVE_OPENSSL
#include "allocated_buffer-inl.h" // Inlined functions needed by node_crypto.h
#include "node_crypto.h"
#endif

Expand Down
Loading

0 comments on commit 56ff1ee

Please sign in to comment.