1 #ifndef SRC_ALIASED_BUFFER_INL_H_
2 #define SRC_ALIASED_BUFFER_INL_H_
3
4 #if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
5
6 #include "aliased_buffer.h"
7 #include "util-inl.h"
8
9 namespace node {
10
11 typedef size_t AliasedBufferIndex;
12
13 template <typename NativeT, typename V8T>
AliasedBufferBase( v8::Isolate* isolate, const size_t count, const AliasedBufferIndex* index)14 AliasedBufferBase<NativeT, V8T>::AliasedBufferBase(
15 v8::Isolate* isolate, const size_t count, const AliasedBufferIndex* index)
16 : isolate_(isolate), count_(count), byte_offset_(0), index_(index) {
17 CHECK_GT(count, 0);
18 if (index != nullptr) {
19 // Will be deserialized later.
20 return;
21 }
22 const v8::HandleScope handle_scope(isolate_);
23 const size_t size_in_bytes =
24 MultiplyWithOverflowCheck(sizeof(NativeT), count);
25
26 // allocate v8 ArrayBuffer
27 v8::Local<v8::ArrayBuffer> ab = v8::ArrayBuffer::New(isolate_, size_in_bytes);
28 buffer_ = static_cast<NativeT*>(ab->Data());
29
30 // allocate v8 TypedArray
31 v8::Local<V8T> js_array = V8T::New(ab, byte_offset_, count);
32 js_array_ = v8::Global<V8T>(isolate, js_array);
33 }
34
35 template <typename NativeT, typename V8T>
AliasedBufferBase( v8::Isolate* isolate, const size_t byte_offset, const size_t count, const AliasedBufferBase<uint8_t, v8::Uint8Array>& backing_buffer, const AliasedBufferIndex* index)36 AliasedBufferBase<NativeT, V8T>::AliasedBufferBase(
37 v8::Isolate* isolate,
38 const size_t byte_offset,
39 const size_t count,
40 const AliasedBufferBase<uint8_t, v8::Uint8Array>& backing_buffer,
41 const AliasedBufferIndex* index)
42 : isolate_(isolate),
43 count_(count),
44 byte_offset_(byte_offset),
45 index_(index) {
46 if (index != nullptr) {
47 // Will be deserialized later.
48 return;
49 }
50 const v8::HandleScope handle_scope(isolate_);
51 v8::Local<v8::ArrayBuffer> ab = backing_buffer.GetArrayBuffer();
52
53 // validate that the byte_offset is aligned with sizeof(NativeT)
54 CHECK_EQ(byte_offset & (sizeof(NativeT) - 1), 0);
55 // validate this fits inside the backing buffer
56 CHECK_LE(MultiplyWithOverflowCheck(sizeof(NativeT), count),
57 ab->ByteLength() - byte_offset);
58
59 buffer_ = reinterpret_cast<NativeT*>(
60 const_cast<uint8_t*>(backing_buffer.GetNativeBuffer() + byte_offset));
61
62 v8::Local<V8T> js_array = V8T::New(ab, byte_offset, count);
63 js_array_ = v8::Global<V8T>(isolate, js_array);
64 }
65
66 template <typename NativeT, typename V8T>
AliasedBufferBase( const AliasedBufferBase& that)67 AliasedBufferBase<NativeT, V8T>::AliasedBufferBase(
68 const AliasedBufferBase& that)
69 : isolate_(that.isolate_),
70 count_(that.count_),
71 byte_offset_(that.byte_offset_),
72 buffer_(that.buffer_) {
73 DCHECK_NULL(index_);
74 js_array_ = v8::Global<V8T>(that.isolate_, that.GetJSArray());
75 }
76
77 template <typename NativeT, typename V8T>
Serialize( v8::Local<v8::Context> context, v8::SnapshotCreator* creator)78 AliasedBufferIndex AliasedBufferBase<NativeT, V8T>::Serialize(
79 v8::Local<v8::Context> context, v8::SnapshotCreator* creator) {
80 DCHECK_NULL(index_);
81 return creator->AddData(context, GetJSArray());
82 }
83
84 template <typename NativeT, typename V8T>
Deserialize( v8::Local<v8::Context> context)85 inline void AliasedBufferBase<NativeT, V8T>::Deserialize(
86 v8::Local<v8::Context> context) {
87 DCHECK_NOT_NULL(index_);
88 v8::Local<V8T> arr =
89 context->GetDataFromSnapshotOnce<V8T>(*index_).ToLocalChecked();
90 // These may not hold true for AliasedBuffers that have grown, so should
91 // be removed when we expand the snapshot support.
92 DCHECK_EQ(count_, arr->Length());
93 DCHECK_EQ(byte_offset_, arr->ByteOffset());
94 uint8_t* raw = static_cast<uint8_t*>(arr->Buffer()->Data());
95 buffer_ = reinterpret_cast<NativeT*>(raw + byte_offset_);
96 js_array_.Reset(isolate_, arr);
97 index_ = nullptr;
98 }
99
100 template <typename NativeT, typename V8T>
101 AliasedBufferBase<NativeT, V8T>& AliasedBufferBase<NativeT, V8T>::operator=(
102 AliasedBufferBase<NativeT, V8T>&& that) noexcept {
103 DCHECK_NULL(index_);
104 this->~AliasedBufferBase();
105 isolate_ = that.isolate_;
106 count_ = that.count_;
107 byte_offset_ = that.byte_offset_;
108 buffer_ = that.buffer_;
109
110 js_array_.Reset(isolate_, that.js_array_.Get(isolate_));
111
112 that.buffer_ = nullptr;
113 that.js_array_.Reset();
114 return *this;
115 }
116
117 template <typename NativeT, typename V8T>
GetJSArray() const118 v8::Local<V8T> AliasedBufferBase<NativeT, V8T>::GetJSArray() const {
119 DCHECK_NULL(index_);
120 return js_array_.Get(isolate_);
121 }
122
123 template <typename NativeT, typename V8T>
Release()124 void AliasedBufferBase<NativeT, V8T>::Release() {
125 DCHECK_NULL(index_);
126 js_array_.Reset();
127 }
128
129 template <typename NativeT, typename V8T>
GetArrayBuffer() const130 v8::Local<v8::ArrayBuffer> AliasedBufferBase<NativeT, V8T>::GetArrayBuffer()
131 const {
132 return GetJSArray()->Buffer();
133 }
134
135 template <typename NativeT, typename V8T>
GetNativeBuffer() const136 inline const NativeT* AliasedBufferBase<NativeT, V8T>::GetNativeBuffer() const {
137 DCHECK_NULL(index_);
138 return buffer_;
139 }
140
141 template <typename NativeT, typename V8T>
operator *() const142 inline const NativeT* AliasedBufferBase<NativeT, V8T>::operator*() const {
143 return GetNativeBuffer();
144 }
145
146 template <typename NativeT, typename V8T>
SetValue(const size_t index, NativeT value)147 inline void AliasedBufferBase<NativeT, V8T>::SetValue(const size_t index,
148 NativeT value) {
149 DCHECK_LT(index, count_);
150 DCHECK_NULL(index_);
151 buffer_[index] = value;
152 }
153
154 template <typename NativeT, typename V8T>
GetValue( const size_t index) const155 inline const NativeT AliasedBufferBase<NativeT, V8T>::GetValue(
156 const size_t index) const {
157 DCHECK_NULL(index_);
158 DCHECK_LT(index, count_);
159 return buffer_[index];
160 }
161
162 template <typename NativeT, typename V8T>
163 typename AliasedBufferBase<NativeT, V8T>::Reference
operator [](size_t index)164 AliasedBufferBase<NativeT, V8T>::operator[](size_t index) {
165 DCHECK_NULL(index_);
166 return Reference(this, index);
167 }
168
169 template <typename NativeT, typename V8T>
operator [](size_t index) const170 NativeT AliasedBufferBase<NativeT, V8T>::operator[](size_t index) const {
171 return GetValue(index);
172 }
173
174 template <typename NativeT, typename V8T>
Length() const175 size_t AliasedBufferBase<NativeT, V8T>::Length() const {
176 return count_;
177 }
178
179 template <typename NativeT, typename V8T>
reserve(size_t new_capacity)180 void AliasedBufferBase<NativeT, V8T>::reserve(size_t new_capacity) {
181 DCHECK_NULL(index_);
182 DCHECK_GE(new_capacity, count_);
183 DCHECK_EQ(byte_offset_, 0);
184 const v8::HandleScope handle_scope(isolate_);
185
186 const size_t old_size_in_bytes = sizeof(NativeT) * count_;
187 const size_t new_size_in_bytes =
188 MultiplyWithOverflowCheck(sizeof(NativeT), new_capacity);
189
190 // allocate v8 new ArrayBuffer
191 v8::Local<v8::ArrayBuffer> ab =
192 v8::ArrayBuffer::New(isolate_, new_size_in_bytes);
193
194 // allocate new native buffer
195 NativeT* new_buffer = static_cast<NativeT*>(ab->Data());
196 // copy old content
197 memcpy(new_buffer, buffer_, old_size_in_bytes);
198
199 // allocate v8 TypedArray
200 v8::Local<V8T> js_array = V8T::New(ab, byte_offset_, new_capacity);
201
202 // move over old v8 TypedArray
203 js_array_ = std::move(v8::Global<V8T>(isolate_, js_array));
204
205 buffer_ = new_buffer;
206 count_ = new_capacity;
207 }
208
209 template <typename NativeT, typename V8T>
SelfSize() const210 inline size_t AliasedBufferBase<NativeT, V8T>::SelfSize() const {
211 return sizeof(*this);
212 }
213
214 #define VM(NativeT, V8T) \
215 template <> \
216 inline const char* AliasedBufferBase<NativeT, v8::V8T>::MemoryInfoName() \
217 const { \
218 return "Aliased" #V8T; \
219 } \
220 template <> \
221 inline void AliasedBufferBase<NativeT, v8::V8T>::MemoryInfo( \
222 node::MemoryTracker* tracker) const { \
223 tracker->TrackField("js_array", js_array_); \
224 }
225 ALIASED_BUFFER_LIST(VM)
226 #undef VM
227
228 } // namespace node
229
230 #endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
231
232 #endif // SRC_ALIASED_BUFFER_INL_H_
233