Skip to content

Commit

Permalink
Merge pull request #16 from AmyrAhmady/node16
Browse files Browse the repository at this point in the history
Upgrade Node.js to v16
  • Loading branch information
AmyrAhmady authored Nov 17, 2021
2 parents 283c01d + 3961a06 commit 42613a4
Show file tree
Hide file tree
Showing 260 changed files with 31,018 additions and 24,167 deletions.
174 changes: 124 additions & 50 deletions deps/node/include/aliased_buffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,18 @@

#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS

#include "v8.h"
#include <cinttypes>
#include "util-inl.h"
#include "v8.h"

namespace node {

typedef size_t AliasedBufferIndex;

/**
* Do not use this class directly when creating instances of it - use the
* Aliased*Array defined at the end of this file instead.
*
* This class encapsulates the technique of having a native buffer mapped to
* a JS object. Writes to the native buffer can happen efficiently without
* going through JS, and the data is then available to user's via the exposed
Expand All @@ -22,56 +28,66 @@ namespace node {
* The encapsulation herein provides a placeholder where such writes can be
* observed. Any notification APIs will be left as a future exercise.
*/
template <class NativeT, class V8T>
class AliasedBuffer {
template <class NativeT,
class V8T,
// SFINAE NativeT to be scalar
typename = std::enable_if_t<std::is_scalar<NativeT>::value>>
class AliasedBufferBase {
public:
AliasedBuffer(v8::Isolate* isolate, const size_t count)
: isolate_(isolate),
count_(count),
byte_offset_(0),
free_buffer_(true) {
AliasedBufferBase(v8::Isolate* isolate,
const size_t count,
const AliasedBufferIndex* index = nullptr)
: isolate_(isolate), count_(count), byte_offset_(0), index_(index) {
CHECK_GT(count, 0);
if (index != nullptr) {
// Will be deserialized later.
return;
}
const v8::HandleScope handle_scope(isolate_);

const size_t sizeInBytes = sizeof(NativeT) * count;

// allocate native buffer
buffer_ = Calloc<NativeT>(count);
const size_t size_in_bytes =
MultiplyWithOverflowCheck(sizeof(NativeT), count);

// allocate v8 ArrayBuffer
v8::Local<v8::ArrayBuffer> ab = v8::ArrayBuffer::New(
isolate_, buffer_, sizeInBytes);
isolate_, size_in_bytes);
buffer_ = static_cast<NativeT*>(ab->GetBackingStore()->Data());

// allocate v8 TypedArray
v8::Local<V8T> js_array = V8T::New(ab, byte_offset_, count);
js_array_ = v8::Global<V8T>(isolate, js_array);
}

/**
* Create an AliasedBuffer over a sub-region of another aliased buffer.
* Create an AliasedBufferBase over a sub-region of another aliased buffer.
* The two will share a v8::ArrayBuffer instance &
* a native buffer, but will each read/write to different sections of the
* native buffer.
*
* Note that byte_offset must by aligned by sizeof(NativeT).
*/
AliasedBuffer(v8::Isolate* isolate,
const size_t byte_offset,
const size_t count,
const AliasedBuffer<uint8_t,
v8::Uint8Array>& backing_buffer)
// TODO(refack): refactor into a non-owning `AliasedBufferBaseView`
AliasedBufferBase(
v8::Isolate* isolate,
const size_t byte_offset,
const size_t count,
const AliasedBufferBase<uint8_t, v8::Uint8Array>& backing_buffer,
const AliasedBufferIndex* index = nullptr)
: isolate_(isolate),
count_(count),
byte_offset_(byte_offset),
free_buffer_(false) {
index_(index) {
if (index != nullptr) {
// Will be deserialized later.
return;
}
const v8::HandleScope handle_scope(isolate_);

v8::Local<v8::ArrayBuffer> ab = backing_buffer.GetArrayBuffer();

// validate that the byte_offset is aligned with sizeof(NativeT)
CHECK_EQ(byte_offset & (sizeof(NativeT) - 1), 0);
// validate this fits inside the backing buffer
CHECK_LE(sizeof(NativeT) * count, ab->ByteLength() - byte_offset);
CHECK_LE(MultiplyWithOverflowCheck(sizeof(NativeT), count),
ab->ByteLength() - byte_offset);

buffer_ = reinterpret_cast<NativeT*>(
const_cast<uint8_t*>(backing_buffer.GetNativeBuffer() + byte_offset));
Expand All @@ -80,29 +96,43 @@ class AliasedBuffer {
js_array_ = v8::Global<V8T>(isolate, js_array);
}

AliasedBuffer(const AliasedBuffer& that)
AliasedBufferBase(const AliasedBufferBase& that)
: isolate_(that.isolate_),
count_(that.count_),
byte_offset_(that.byte_offset_),
buffer_(that.buffer_),
free_buffer_(false) {
buffer_(that.buffer_) {
DCHECK_NULL(index_);
js_array_ = v8::Global<V8T>(that.isolate_, that.GetJSArray());
}

~AliasedBuffer() {
if (free_buffer_ && buffer_ != nullptr) {
free(buffer_);
}
js_array_.Reset();
AliasedBufferIndex Serialize(v8::Local<v8::Context> context,
v8::SnapshotCreator* creator) {
DCHECK_NULL(index_);
return creator->AddData(context, GetJSArray());
}

inline void Deserialize(v8::Local<v8::Context> context) {
DCHECK_NOT_NULL(index_);
v8::Local<V8T> arr =
context->GetDataFromSnapshotOnce<V8T>(*index_).ToLocalChecked();
// These may not hold true for AliasedBuffers that have grown, so should
// be removed when we expand the snapshot support.
DCHECK_EQ(count_, arr->Length());
DCHECK_EQ(byte_offset_, arr->ByteOffset());
uint8_t* raw =
static_cast<uint8_t*>(arr->Buffer()->GetBackingStore()->Data());
buffer_ = reinterpret_cast<NativeT*>(raw + byte_offset_);
js_array_.Reset(isolate_, arr);
index_ = nullptr;
}

AliasedBuffer& operator=(AliasedBuffer&& that) {
this->~AliasedBuffer();
AliasedBufferBase& operator=(AliasedBufferBase&& that) noexcept {
DCHECK_NULL(index_);
this->~AliasedBufferBase();
isolate_ = that.isolate_;
count_ = that.count_;
byte_offset_ = that.byte_offset_;
buffer_ = that.buffer_;
free_buffer_ = that.free_buffer_;

js_array_.Reset(isolate_, that.js_array_.Get(isolate_));

Expand All @@ -117,10 +147,8 @@ class AliasedBuffer {
*/
class Reference {
public:
Reference(AliasedBuffer<NativeT, V8T>* aliased_buffer, size_t index)
: aliased_buffer_(aliased_buffer),
index_(index) {
}
Reference(AliasedBufferBase<NativeT, V8T>* aliased_buffer, size_t index)
: aliased_buffer_(aliased_buffer), index_(index) {}

Reference(const Reference& that)
: aliased_buffer_(that.aliased_buffer_),
Expand Down Expand Up @@ -157,17 +185,23 @@ class AliasedBuffer {
}

private:
AliasedBuffer<NativeT, V8T>* aliased_buffer_;
AliasedBufferBase<NativeT, V8T>* aliased_buffer_;
size_t index_;
};

/**
* Get the underlying v8 TypedArray overlayed on top of the native buffer
*/
v8::Local<V8T> GetJSArray() const {
DCHECK_NULL(index_);
return js_array_.Get(isolate_);
}

void Release() {
DCHECK_NULL(index_);
js_array_.Reset();
}

/**
* Get the underlying v8::ArrayBuffer underlying the TypedArray and
* overlaying the native buffer
Expand All @@ -181,6 +215,7 @@ class AliasedBuffer {
* through the GetValue/SetValue/operator[] methods
*/
inline const NativeT* GetNativeBuffer() const {
DCHECK_NULL(index_);
return buffer_;
}

Expand All @@ -195,26 +230,25 @@ class AliasedBuffer {
* Set position index to given value.
*/
inline void SetValue(const size_t index, NativeT value) {
#if defined(DEBUG) && DEBUG
CHECK_LT(index, count_);
#endif
DCHECK_LT(index, count_);
DCHECK_NULL(index_);
buffer_[index] = value;
}

/**
* Get value at position index
*/
inline const NativeT GetValue(const size_t index) const {
#if defined(DEBUG) && DEBUG
CHECK_LT(index, count_);
#endif
DCHECK_NULL(index_);
DCHECK_LT(index, count_);
return buffer_[index];
}

/**
* Effectively, a synonym for GetValue/SetValue
*/
Reference operator[](size_t index) {
DCHECK_NULL(index_);
return Reference(this, index);
}

Expand All @@ -226,14 +260,54 @@ class AliasedBuffer {
return count_;
}

// Should only be used to extend the array.
// Should only be used on an owning array, not one created as a sub array of
// an owning `AliasedBufferBase`.
void reserve(size_t new_capacity) {
DCHECK_NULL(index_);
DCHECK_GE(new_capacity, count_);
DCHECK_EQ(byte_offset_, 0);
const v8::HandleScope handle_scope(isolate_);

const size_t old_size_in_bytes = sizeof(NativeT) * count_;
const size_t new_size_in_bytes = MultiplyWithOverflowCheck(sizeof(NativeT),
new_capacity);

// allocate v8 new ArrayBuffer
v8::Local<v8::ArrayBuffer> ab = v8::ArrayBuffer::New(
isolate_, new_size_in_bytes);

// allocate new native buffer
NativeT* new_buffer = static_cast<NativeT*>(ab->GetBackingStore()->Data());
// copy old content
memcpy(new_buffer, buffer_, old_size_in_bytes);

// allocate v8 TypedArray
v8::Local<V8T> js_array = V8T::New(ab, byte_offset_, new_capacity);

// move over old v8 TypedArray
js_array_ = std::move(v8::Global<V8T>(isolate_, js_array));

buffer_ = new_buffer;
count_ = new_capacity;
}

private:
v8::Isolate* isolate_;
size_t count_;
size_t byte_offset_;
NativeT* buffer_;
v8::Isolate* isolate_ = nullptr;
size_t count_ = 0;
size_t byte_offset_ = 0;
NativeT* buffer_ = nullptr;
v8::Global<V8T> js_array_;
bool free_buffer_;

// Deserialize data
const AliasedBufferIndex* index_ = nullptr;
};

typedef AliasedBufferBase<int32_t, v8::Int32Array> AliasedInt32Array;
typedef AliasedBufferBase<uint8_t, v8::Uint8Array> AliasedUint8Array;
typedef AliasedBufferBase<uint32_t, v8::Uint32Array> AliasedUint32Array;
typedef AliasedBufferBase<double, v8::Float64Array> AliasedFloat64Array;
typedef AliasedBufferBase<uint64_t, v8::BigUint64Array> AliasedBigUint64Array;
} // namespace node

#endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
Expand Down
54 changes: 54 additions & 0 deletions deps/node/include/aliased_struct-inl.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
#ifndef SRC_ALIASED_STRUCT_INL_H_
#define SRC_ALIASED_STRUCT_INL_H_

#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS

#include "aliased_struct.h"
#include "v8.h"
#include <memory>

namespace node {

template <typename T>
template <typename... Args>
AliasedStruct<T>::AliasedStruct(v8::Isolate* isolate, Args&&... args)
: isolate_(isolate) {
const v8::HandleScope handle_scope(isolate);

store_ = v8::ArrayBuffer::NewBackingStore(isolate, sizeof(T));
ptr_ = new (store_->Data()) T(std::forward<Args>(args)...);
DCHECK_NOT_NULL(ptr_);

v8::Local<v8::ArrayBuffer> buffer = v8::ArrayBuffer::New(isolate, store_);
buffer_ = v8::Global<v8::ArrayBuffer>(isolate, buffer);
}

template <typename T>
AliasedStruct<T>::AliasedStruct(const AliasedStruct& that)
: AliasedStruct(that.isolate_, *that) {}

template <typename T>
AliasedStruct<T>& AliasedStruct<T>::operator=(
AliasedStruct<T>&& that) noexcept {
this->~AliasedStruct();
isolate_ = that.isolate_;
store_ = that.store_;
ptr_ = that.ptr_;

buffer_ = std::move(that.buffer_);

that.ptr_ = nullptr;
that.store_.reset();
return *this;
}

template <typename T>
AliasedStruct<T>::~AliasedStruct() {
if (ptr_ != nullptr) ptr_->~T();
}

} // namespace node

#endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS

#endif // SRC_ALIASED_STRUCT_INL_H_
Loading

0 comments on commit 42613a4

Please sign in to comment.