/src/node/deps/v8/include/v8-array-buffer.h
Line | Count | Source (jump to first uncovered line) |
1 | | // Copyright 2021 the V8 project authors. All rights reserved. |
2 | | // Use of this source code is governed by a BSD-style license that can be |
3 | | // found in the LICENSE file. |
4 | | |
5 | | #ifndef INCLUDE_V8_ARRAY_BUFFER_H_ |
6 | | #define INCLUDE_V8_ARRAY_BUFFER_H_ |
7 | | |
8 | | #include <stddef.h> |
9 | | |
10 | | #include <memory> |
11 | | |
12 | | #include "v8-local-handle.h" // NOLINT(build/include_directory) |
13 | | #include "v8-object.h" // NOLINT(build/include_directory) |
14 | | #include "v8config.h" // NOLINT(build/include_directory) |
15 | | |
16 | | namespace v8 { |
17 | | |
18 | | class SharedArrayBuffer; |
19 | | |
20 | | #ifndef V8_ARRAY_BUFFER_INTERNAL_FIELD_COUNT |
21 | | // The number of required internal fields can be defined by embedder. |
22 | | #define V8_ARRAY_BUFFER_INTERNAL_FIELD_COUNT 2 |
23 | | #endif |
24 | | |
25 | | enum class ArrayBufferCreationMode { kInternalized, kExternalized }; |
26 | | |
27 | | /** |
28 | | * A wrapper around the backing store (i.e. the raw memory) of an array buffer. |
29 | | * See a document linked in http://crbug.com/v8/9908 for more information. |
30 | | * |
31 | | * The allocation and destruction of backing stores is generally managed by |
32 | | * V8. Clients should always use standard C++ memory ownership types (i.e. |
33 | | * std::unique_ptr and std::shared_ptr) to manage lifetimes of backing stores |
34 | | * properly, since V8 internal objects may alias backing stores. |
35 | | * |
36 | | * This object does not keep the underlying |ArrayBuffer::Allocator| alive by |
37 | | * default. Use Isolate::CreateParams::array_buffer_allocator_shared when |
38 | | * creating the Isolate to make it hold a reference to the allocator itself. |
39 | | */ |
40 | | class V8_EXPORT BackingStore : public v8::internal::BackingStoreBase { |
41 | | public: |
42 | | ~BackingStore(); |
43 | | |
44 | | /** |
45 | | * Return a pointer to the beginning of the memory block for this backing |
46 | | * store. The pointer is only valid as long as this backing store object |
47 | | * lives. |
48 | | */ |
49 | | void* Data() const; |
50 | | |
51 | | /** |
52 | | * The length (in bytes) of this backing store. |
53 | | */ |
54 | | size_t ByteLength() const; |
55 | | |
56 | | /** |
57 | | * The maximum length (in bytes) that this backing store may grow to. |
58 | | * |
59 | | * If this backing store was created for a resizable ArrayBuffer or a growable |
60 | | * SharedArrayBuffer, it is >= ByteLength(). Otherwise it is == |
61 | | * ByteLength(). |
62 | | */ |
63 | | size_t MaxByteLength() const; |
64 | | |
65 | | /** |
66 | | * Indicates whether the backing store was created for an ArrayBuffer or |
67 | | * a SharedArrayBuffer. |
68 | | */ |
69 | | bool IsShared() const; |
70 | | |
71 | | /** |
72 | | * Indicates whether the backing store was created for a resizable ArrayBuffer |
73 | | * or a growable SharedArrayBuffer, and thus may be resized by user JavaScript |
74 | | * code. |
75 | | */ |
76 | | bool IsResizableByUserJavaScript() const; |
77 | | |
78 | | /** |
79 | | * Prevent implicit instantiation of operator delete with size_t argument. |
80 | | * The size_t argument would be incorrect because ptr points to the |
81 | | * internal BackingStore object. |
82 | | */ |
83 | 4.79k | void operator delete(void* ptr) { ::operator delete(ptr); } |
84 | | |
85 | | /** |
86 | | * Wrapper around ArrayBuffer::Allocator::Reallocate that preserves IsShared. |
87 | | * Assumes that the backing_store was allocated by the ArrayBuffer allocator |
88 | | * of the given isolate. |
89 | | */ |
90 | | static std::unique_ptr<BackingStore> Reallocate( |
91 | | v8::Isolate* isolate, std::unique_ptr<BackingStore> backing_store, |
92 | | size_t byte_length); |
93 | | |
94 | | /** |
95 | | * This callback is used only if the memory block for a BackingStore cannot be |
96 | | * allocated with an ArrayBuffer::Allocator. In such cases the destructor of |
97 | | * the BackingStore invokes the callback to free the memory block. |
98 | | */ |
99 | | using DeleterCallback = void (*)(void* data, size_t length, |
100 | | void* deleter_data); |
101 | | |
102 | | /** |
103 | | * If the memory block of a BackingStore is static or is managed manually, |
104 | | * then this empty deleter along with nullptr deleter_data can be passed to |
105 | | * ArrayBuffer::NewBackingStore to indicate that. |
106 | | * |
107 | | * The manually managed case should be used with caution and only when it |
108 | | * is guaranteed that the memory block freeing happens after detaching its |
109 | | * ArrayBuffer. |
110 | | */ |
111 | | static void EmptyDeleter(void* data, size_t length, void* deleter_data); |
112 | | |
113 | | private: |
114 | | /** |
115 | | * See [Shared]ArrayBuffer::GetBackingStore and |
116 | | * [Shared]ArrayBuffer::NewBackingStore. |
117 | | */ |
118 | | BackingStore(); |
119 | | }; |
120 | | |
121 | | #if !defined(V8_IMMINENT_DEPRECATION_WARNINGS) |
122 | | // Use v8::BackingStore::DeleterCallback instead. |
123 | | using BackingStoreDeleterCallback = void (*)(void* data, size_t length, |
124 | | void* deleter_data); |
125 | | |
126 | | #endif |
127 | | |
128 | | /** |
129 | | * An instance of the built-in ArrayBuffer constructor (ES6 draft 15.13.5). |
130 | | */ |
131 | | class V8_EXPORT ArrayBuffer : public Object { |
132 | | public: |
133 | | /** |
134 | | * A thread-safe allocator that V8 uses to allocate |ArrayBuffer|'s memory. |
135 | | * The allocator is a global V8 setting. It has to be set via |
136 | | * Isolate::CreateParams. |
137 | | * |
138 | | * Memory allocated through this allocator by V8 is accounted for as external |
139 | | * memory by V8. Note that V8 keeps track of the memory for all internalized |
140 | | * |ArrayBuffer|s. Responsibility for tracking external memory (using |
141 | | * Isolate::AdjustAmountOfExternalAllocatedMemory) is handed over to the |
142 | | * embedder upon externalization and taken over upon internalization (creating |
143 | | * an internalized buffer from an existing buffer). |
144 | | * |
145 | | * Note that it is unsafe to call back into V8 from any of the allocator |
146 | | * functions. |
147 | | */ |
148 | | class V8_EXPORT Allocator { |
149 | | public: |
150 | 134k | virtual ~Allocator() = default; |
151 | | |
152 | | /** |
153 | | * Allocate |length| bytes. Return nullptr if allocation is not successful. |
154 | | * Memory should be initialized to zeroes. |
155 | | */ |
156 | | virtual void* Allocate(size_t length) = 0; |
157 | | |
158 | | /** |
159 | | * Allocate |length| bytes. Return nullptr if allocation is not successful. |
160 | | * Memory does not have to be initialized. |
161 | | */ |
162 | | virtual void* AllocateUninitialized(size_t length) = 0; |
163 | | |
164 | | /** |
165 | | * Free the memory block of size |length|, pointed to by |data|. |
166 | | * That memory is guaranteed to be previously allocated by |Allocate|. |
167 | | */ |
168 | | virtual void Free(void* data, size_t length) = 0; |
169 | | |
170 | | /** |
171 | | * Reallocate the memory block of size |old_length| to a memory block of |
172 | | * size |new_length| by expanding, contracting, or copying the existing |
173 | | * memory block. If |new_length| > |old_length|, then the new part of |
174 | | * the memory must be initialized to zeros. Return nullptr if reallocation |
175 | | * is not successful. |
176 | | * |
177 | | * The caller guarantees that the memory block was previously allocated |
178 | | * using Allocate or AllocateUninitialized. |
179 | | * |
180 | | * The default implementation allocates a new block and copies data. |
181 | | */ |
182 | | virtual void* Reallocate(void* data, size_t old_length, size_t new_length); |
183 | | |
184 | | /** |
185 | | * ArrayBuffer allocation mode. kNormal is a malloc/free style allocation, |
186 | | * while kReservation is for larger allocations with the ability to set |
187 | | * access permissions. |
188 | | */ |
189 | | enum class AllocationMode { kNormal, kReservation }; |
190 | | |
191 | | /** |
192 | | * Convenience allocator. |
193 | | * |
194 | | * When the sandbox is enabled, this allocator will allocate its backing |
195 | | * memory inside the sandbox. Otherwise, it will rely on malloc/free. |
196 | | * |
197 | | * Caller takes ownership, i.e. the returned object needs to be freed using |
198 | | * |delete allocator| once it is no longer in use. |
199 | | */ |
200 | | static Allocator* NewDefaultAllocator(); |
201 | | }; |
202 | | |
203 | | /** |
204 | | * Data length in bytes. |
205 | | */ |
206 | | size_t ByteLength() const; |
207 | | |
208 | | /** |
209 | | * Maximum length in bytes. |
210 | | */ |
211 | | size_t MaxByteLength() const; |
212 | | |
213 | | /** |
214 | | * Create a new ArrayBuffer. Allocate |byte_length| bytes. |
215 | | * Allocated memory will be owned by a created ArrayBuffer and |
216 | | * will be deallocated when it is garbage-collected, |
217 | | * unless the object is externalized. |
218 | | */ |
219 | | static Local<ArrayBuffer> New(Isolate* isolate, size_t byte_length); |
220 | | |
221 | | /** |
222 | | * Create a new ArrayBuffer with an existing backing store. |
223 | | * The created array keeps a reference to the backing store until the array |
224 | | * is garbage collected. Note that the IsExternal bit does not affect this |
225 | | * reference from the array to the backing store. |
226 | | * |
227 | | * In future IsExternal bit will be removed. Until then the bit is set as |
228 | | * follows. If the backing store does not own the underlying buffer, then |
229 | | * the array is created in externalized state. Otherwise, the array is created |
230 | | * in internalized state. In the latter case the array can be transitioned |
231 | | * to the externalized state using Externalize(backing_store). |
232 | | */ |
233 | | static Local<ArrayBuffer> New(Isolate* isolate, |
234 | | std::shared_ptr<BackingStore> backing_store); |
235 | | |
236 | | /** |
237 | | * Returns a new standalone BackingStore that is allocated using the array |
238 | | * buffer allocator of the isolate. The result can be later passed to |
239 | | * ArrayBuffer::New. |
240 | | * |
241 | | * If the allocator returns nullptr, then the function may cause GCs in the |
242 | | * given isolate and re-try the allocation. If GCs do not help, then the |
243 | | * function will crash with an out-of-memory error. |
244 | | */ |
245 | | static std::unique_ptr<BackingStore> NewBackingStore(Isolate* isolate, |
246 | | size_t byte_length); |
247 | | /** |
248 | | * Returns a new standalone BackingStore that takes over the ownership of |
249 | | * the given buffer. The destructor of the BackingStore invokes the given |
250 | | * deleter callback. |
251 | | * |
252 | | * The result can be later passed to ArrayBuffer::New. The raw pointer |
253 | | * to the buffer must not be passed again to any V8 API function. |
254 | | */ |
255 | | static std::unique_ptr<BackingStore> NewBackingStore( |
256 | | void* data, size_t byte_length, v8::BackingStore::DeleterCallback deleter, |
257 | | void* deleter_data); |
258 | | |
259 | | /** |
260 | | * Returns a new resizable standalone BackingStore that is allocated using the |
261 | | * array buffer allocator of the isolate. The result can be later passed to |
262 | | * ArrayBuffer::New. |
263 | | * |
264 | | * |byte_length| must be <= |max_byte_length|. |
265 | | * |
266 | | * This function is usable without an isolate. Unlike |NewBackingStore| calls |
267 | | * with an isolate, GCs cannot be triggered, and there are no |
268 | | * retries. Allocation failure will cause the function to crash with an |
269 | | * out-of-memory error. |
270 | | */ |
271 | | static std::unique_ptr<BackingStore> NewResizableBackingStore( |
272 | | size_t byte_length, size_t max_byte_length); |
273 | | |
274 | | /** |
275 | | * Returns true if this ArrayBuffer may be detached. |
276 | | */ |
277 | | bool IsDetachable() const; |
278 | | |
279 | | /** |
280 | | * Returns true if this ArrayBuffer has been detached. |
281 | | */ |
282 | | bool WasDetached() const; |
283 | | |
284 | | /** |
285 | | * Detaches this ArrayBuffer and all its views (typed arrays). |
286 | | * Detaching sets the byte length of the buffer and all typed arrays to zero, |
287 | | * preventing JavaScript from ever accessing underlying backing store. |
288 | | * ArrayBuffer should have been externalized and must be detachable. |
289 | | */ |
290 | | V8_DEPRECATE_SOON( |
291 | | "Use the version which takes a key parameter (passing a null handle is " |
292 | | "ok).") |
293 | | void Detach(); |
294 | | |
295 | | /** |
296 | | * Detaches this ArrayBuffer and all its views (typed arrays). |
297 | | * Detaching sets the byte length of the buffer and all typed arrays to zero, |
298 | | * preventing JavaScript from ever accessing underlying backing store. |
299 | | * ArrayBuffer should have been externalized and must be detachable. Returns |
300 | | * Nothing if the key didn't pass the [[ArrayBufferDetachKey]] check, |
301 | | * Just(true) otherwise. |
302 | | */ |
303 | | V8_WARN_UNUSED_RESULT Maybe<bool> Detach(v8::Local<v8::Value> key); |
304 | | |
305 | | /** |
306 | | * Sets the ArrayBufferDetachKey. |
307 | | */ |
308 | | void SetDetachKey(v8::Local<v8::Value> key); |
309 | | |
310 | | /** |
311 | | * Get a shared pointer to the backing store of this array buffer. This |
312 | | * pointer coordinates the lifetime management of the internal storage |
313 | | * with any live ArrayBuffers on the heap, even across isolates. The embedder |
314 | | * should not attempt to manage lifetime of the storage through other means. |
315 | | * |
316 | | * The returned shared pointer will not be empty, even if the ArrayBuffer has |
317 | | * been detached. Use |WasDetached| to tell if it has been detached instead. |
318 | | */ |
319 | | std::shared_ptr<BackingStore> GetBackingStore(); |
320 | | |
321 | | /** |
322 | | * More efficient shortcut for GetBackingStore()->Data(). The returned pointer |
323 | | * is valid as long as the ArrayBuffer is alive. |
324 | | */ |
325 | | void* Data() const; |
326 | | |
327 | 0 | V8_INLINE static ArrayBuffer* Cast(Value* value) { |
328 | 0 | #ifdef V8_ENABLE_CHECKS |
329 | 0 | CheckCast(value); |
330 | 0 | #endif |
331 | 0 | return static_cast<ArrayBuffer*>(value); |
332 | 0 | } |
333 | | |
334 | | static const int kInternalFieldCount = V8_ARRAY_BUFFER_INTERNAL_FIELD_COUNT; |
335 | | static const int kEmbedderFieldCount = V8_ARRAY_BUFFER_INTERNAL_FIELD_COUNT; |
336 | | |
337 | | private: |
338 | | ArrayBuffer(); |
339 | | static void CheckCast(Value* obj); |
340 | | }; |
341 | | |
342 | | #ifndef V8_ARRAY_BUFFER_VIEW_INTERNAL_FIELD_COUNT |
343 | | // The number of required internal fields can be defined by embedder. |
344 | | #define V8_ARRAY_BUFFER_VIEW_INTERNAL_FIELD_COUNT 2 |
345 | | #endif |
346 | | |
347 | | /** |
348 | | * A base class for an instance of one of "views" over ArrayBuffer, |
349 | | * including TypedArrays and DataView (ES6 draft 15.13). |
350 | | */ |
351 | | class V8_EXPORT ArrayBufferView : public Object { |
352 | | public: |
353 | | /** |
354 | | * Returns underlying ArrayBuffer. |
355 | | */ |
356 | | Local<ArrayBuffer> Buffer(); |
357 | | /** |
358 | | * Byte offset in |Buffer|. |
359 | | */ |
360 | | size_t ByteOffset(); |
361 | | /** |
362 | | * Size of a view in bytes. |
363 | | */ |
364 | | size_t ByteLength(); |
365 | | |
366 | | /** |
367 | | * Copy the contents of the ArrayBufferView's buffer to an embedder defined |
368 | | * memory without additional overhead that calling ArrayBufferView::Buffer |
369 | | * might incur. |
370 | | * |
371 | | * Will write at most min(|byte_length|, ByteLength) bytes starting at |
372 | | * ByteOffset of the underlying buffer to the memory starting at |dest|. |
373 | | * Returns the number of bytes actually written. |
374 | | */ |
375 | | size_t CopyContents(void* dest, size_t byte_length); |
376 | | |
377 | | /** |
378 | | * Returns true if ArrayBufferView's backing ArrayBuffer has already been |
379 | | * allocated. |
380 | | */ |
381 | | bool HasBuffer() const; |
382 | | |
383 | 0 | V8_INLINE static ArrayBufferView* Cast(Value* value) { |
384 | 0 | #ifdef V8_ENABLE_CHECKS |
385 | 0 | CheckCast(value); |
386 | 0 | #endif |
387 | 0 | return static_cast<ArrayBufferView*>(value); |
388 | 0 | } |
389 | | |
390 | | static const int kInternalFieldCount = |
391 | | V8_ARRAY_BUFFER_VIEW_INTERNAL_FIELD_COUNT; |
392 | | static const int kEmbedderFieldCount = |
393 | | V8_ARRAY_BUFFER_VIEW_INTERNAL_FIELD_COUNT; |
394 | | |
395 | | private: |
396 | | ArrayBufferView(); |
397 | | static void CheckCast(Value* obj); |
398 | | }; |
399 | | |
400 | | /** |
401 | | * An instance of DataView constructor (ES6 draft 15.13.7). |
402 | | */ |
403 | | class V8_EXPORT DataView : public ArrayBufferView { |
404 | | public: |
405 | | static Local<DataView> New(Local<ArrayBuffer> array_buffer, |
406 | | size_t byte_offset, size_t length); |
407 | | static Local<DataView> New(Local<SharedArrayBuffer> shared_array_buffer, |
408 | | size_t byte_offset, size_t length); |
409 | 0 | V8_INLINE static DataView* Cast(Value* value) { |
410 | 0 | #ifdef V8_ENABLE_CHECKS |
411 | 0 | CheckCast(value); |
412 | 0 | #endif |
413 | 0 | return static_cast<DataView*>(value); |
414 | 0 | } |
415 | | |
416 | | private: |
417 | | DataView(); |
418 | | static void CheckCast(Value* obj); |
419 | | }; |
420 | | |
421 | | /** |
422 | | * An instance of the built-in SharedArrayBuffer constructor. |
423 | | */ |
424 | | class V8_EXPORT SharedArrayBuffer : public Object { |
425 | | public: |
426 | | /** |
427 | | * Data length in bytes. |
428 | | */ |
429 | | size_t ByteLength() const; |
430 | | |
431 | | /** |
432 | | * Maximum length in bytes. |
433 | | */ |
434 | | size_t MaxByteLength() const; |
435 | | |
436 | | /** |
437 | | * Create a new SharedArrayBuffer. Allocate |byte_length| bytes. |
438 | | * Allocated memory will be owned by a created SharedArrayBuffer and |
439 | | * will be deallocated when it is garbage-collected, |
440 | | * unless the object is externalized. |
441 | | */ |
442 | | static Local<SharedArrayBuffer> New(Isolate* isolate, size_t byte_length); |
443 | | |
444 | | /** |
445 | | * Create a new SharedArrayBuffer with an existing backing store. |
446 | | * The created array keeps a reference to the backing store until the array |
447 | | * is garbage collected. Note that the IsExternal bit does not affect this |
448 | | * reference from the array to the backing store. |
449 | | * |
450 | | * In future IsExternal bit will be removed. Until then the bit is set as |
451 | | * follows. If the backing store does not own the underlying buffer, then |
452 | | * the array is created in externalized state. Otherwise, the array is created |
453 | | * in internalized state. In the latter case the array can be transitioned |
454 | | * to the externalized state using Externalize(backing_store). |
455 | | */ |
456 | | static Local<SharedArrayBuffer> New( |
457 | | Isolate* isolate, std::shared_ptr<BackingStore> backing_store); |
458 | | |
459 | | /** |
460 | | * Returns a new standalone BackingStore that is allocated using the array |
461 | | * buffer allocator of the isolate. The result can be later passed to |
462 | | * SharedArrayBuffer::New. |
463 | | * |
464 | | * If the allocator returns nullptr, then the function may cause GCs in the |
465 | | * given isolate and re-try the allocation. If GCs do not help, then the |
466 | | * function will crash with an out-of-memory error. |
467 | | */ |
468 | | static std::unique_ptr<BackingStore> NewBackingStore(Isolate* isolate, |
469 | | size_t byte_length); |
470 | | /** |
471 | | * Returns a new standalone BackingStore that takes over the ownership of |
472 | | * the given buffer. The destructor of the BackingStore invokes the given |
473 | | * deleter callback. |
474 | | * |
475 | | * The result can be later passed to SharedArrayBuffer::New. The raw pointer |
476 | | * to the buffer must not be passed again to any V8 functions. |
477 | | */ |
478 | | static std::unique_ptr<BackingStore> NewBackingStore( |
479 | | void* data, size_t byte_length, v8::BackingStore::DeleterCallback deleter, |
480 | | void* deleter_data); |
481 | | |
482 | | /** |
483 | | * Get a shared pointer to the backing store of this array buffer. This |
484 | | * pointer coordinates the lifetime management of the internal storage |
485 | | * with any live ArrayBuffers on the heap, even across isolates. The embedder |
486 | | * should not attempt to manage lifetime of the storage through other means. |
487 | | */ |
488 | | std::shared_ptr<BackingStore> GetBackingStore(); |
489 | | |
490 | | /** |
491 | | * More efficient shortcut for GetBackingStore()->Data(). The returned pointer |
492 | | * is valid as long as the ArrayBuffer is alive. |
493 | | */ |
494 | | void* Data() const; |
495 | | |
496 | 0 | V8_INLINE static SharedArrayBuffer* Cast(Value* value) { |
497 | 0 | #ifdef V8_ENABLE_CHECKS |
498 | 0 | CheckCast(value); |
499 | 0 | #endif |
500 | 0 | return static_cast<SharedArrayBuffer*>(value); |
501 | 0 | } |
502 | | |
503 | | static const int kInternalFieldCount = V8_ARRAY_BUFFER_INTERNAL_FIELD_COUNT; |
504 | | |
505 | | private: |
506 | | SharedArrayBuffer(); |
507 | | static void CheckCast(Value* obj); |
508 | | }; |
509 | | |
510 | | } // namespace v8 |
511 | | |
512 | | #endif // INCLUDE_V8_ARRAY_BUFFER_H_ |