1// Copyright 2018 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 V8_OBJECTS_JS_ARRAY_BUFFER_H_
6#define V8_OBJECTS_JS_ARRAY_BUFFER_H_
7
8#include "src/objects/js-objects.h"
9
10// Has to be the last include (doesn't have include guards):
11#include "src/objects/object-macros.h"
12
13namespace v8 {
14namespace internal {
15
16// Whether a JSArrayBuffer is a SharedArrayBuffer or not.
17enum class SharedFlag : uint32_t { kNotShared, kShared };
18
19class JSArrayBuffer : public JSObject {
20 public:
21// The maximum length for JSArrayBuffer's supported by V8.
22// On 32-bit architectures we limit this to 2GiB, so that
23// we can continue to use CheckBounds with the Unsigned31
24// restriction for the length.
25#if V8_HOST_ARCH_32_BIT
26 static constexpr size_t kMaxByteLength = kMaxInt;
27#else
28 static constexpr size_t kMaxByteLength = kMaxSafeInteger;
29#endif
30
31 // [byte_length]: length in bytes
32 DECL_PRIMITIVE_ACCESSORS(byte_length, size_t)
33
34 // [backing_store]: backing memory for this array
35 DECL_ACCESSORS(backing_store, void*)
36
37 // For non-wasm, allocation_length and allocation_base are byte_length and
38 // backing_store, respectively.
39 inline size_t allocation_length() const;
40 inline void* allocation_base() const;
41
42 // [bit_field]: boolean flags
43 DECL_PRIMITIVE_ACCESSORS(bit_field, uint32_t)
44
45 // Clear uninitialized padding space. This ensures that the snapshot content
46 // is deterministic. Depending on the V8 build mode there could be no padding.
47 V8_INLINE void clear_padding();
48
49// Bit positions for [bit_field].
50#define JS_ARRAY_BUFFER_BIT_FIELD_FIELDS(V, _) \
51 V(IsExternalBit, bool, 1, _) \
52 V(IsDetachableBit, bool, 1, _) \
53 V(WasDetachedBit, bool, 1, _) \
54 V(IsSharedBit, bool, 1, _) \
55 V(IsWasmMemoryBit, bool, 1, _)
56 DEFINE_BIT_FIELDS(JS_ARRAY_BUFFER_BIT_FIELD_FIELDS)
57#undef JS_ARRAY_BUFFER_BIT_FIELD_FIELDS
58
59 // [is_external]: true indicates that the embedder is in charge of freeing the
60 // backing_store, while is_external == false means that v8 will free the
61 // memory block once all ArrayBuffers referencing it are collected by the GC.
62 DECL_BOOLEAN_ACCESSORS(is_external)
63
64 // [is_detachable]: false indicates that this buffer cannot be detached.
65 DECL_BOOLEAN_ACCESSORS(is_detachable)
66
67 // [was_detached]: true if the buffer was previously detached.
68 DECL_BOOLEAN_ACCESSORS(was_detached)
69
70 // [is_shared]: tells whether this is an ArrayBuffer or a SharedArrayBuffer.
71 DECL_BOOLEAN_ACCESSORS(is_shared)
72
73 // [is_wasm_memory]: whether the buffer is tracked by the WasmMemoryTracker.
74 DECL_BOOLEAN_ACCESSORS(is_wasm_memory)
75
76 DECL_CAST(JSArrayBuffer)
77
78 void Detach();
79
80 struct Allocation {
81 Allocation(void* allocation_base, size_t length, void* backing_store,
82 bool is_wasm_memory)
83 : allocation_base(allocation_base),
84 length(length),
85 backing_store(backing_store),
86 is_wasm_memory(is_wasm_memory) {}
87
88 void* allocation_base;
89 size_t length;
90 void* backing_store;
91 bool is_wasm_memory;
92 };
93
94 V8_EXPORT_PRIVATE void FreeBackingStoreFromMainThread();
95 V8_EXPORT_PRIVATE static void FreeBackingStore(Isolate* isolate,
96 Allocation allocation);
97
98 V8_EXPORT_PRIVATE static void Setup(
99 Handle<JSArrayBuffer> array_buffer, Isolate* isolate, bool is_external,
100 void* data, size_t allocated_length,
101 SharedFlag shared_flag = SharedFlag::kNotShared,
102 bool is_wasm_memory = false);
103
104 // Initialize the object as empty one to avoid confusing heap verifier if
105 // the failure happened in the middle of JSArrayBuffer construction.
106 V8_EXPORT_PRIVATE static void SetupAsEmpty(Handle<JSArrayBuffer> array_buffer,
107 Isolate* isolate);
108
109 // Returns false if array buffer contents could not be allocated.
110 // In this case, |array_buffer| will not be set up.
111 V8_EXPORT_PRIVATE static bool SetupAllocatingData(
112 Handle<JSArrayBuffer> array_buffer, Isolate* isolate,
113 size_t allocated_length, bool initialize = true,
114 SharedFlag shared_flag = SharedFlag::kNotShared) V8_WARN_UNUSED_RESULT;
115
116 // Dispatched behavior.
117 DECL_PRINTER(JSArrayBuffer)
118 DECL_VERIFIER(JSArrayBuffer)
119
120// Layout description.
121#define JS_ARRAY_BUFFER_FIELDS(V) \
122 V(kEndOfTaggedFieldsOffset, 0) \
123 /* Raw data fields. */ \
124 V(kByteLengthOffset, kUIntptrSize) \
125 V(kBackingStoreOffset, kSystemPointerSize) \
126 V(kBitFieldOffset, kInt32Size) \
127 /* Pads header size to be a multiple of kTaggedSize. */ \
128 V(kOptionalPaddingOffset, OBJECT_POINTER_PADDING(kOptionalPaddingOffset)) \
129 /* Header size. */ \
130 V(kHeaderSize, 0)
131
132 DEFINE_FIELD_OFFSET_CONSTANTS(JSObject::kHeaderSize, JS_ARRAY_BUFFER_FIELDS)
133#undef JS_ARRAY_BUFFER_FIELDS
134
135 static const int kSizeWithEmbedderFields =
136 kHeaderSize +
137 v8::ArrayBuffer::kEmbedderFieldCount * kEmbedderDataSlotSize;
138
139 class BodyDescriptor;
140
141 OBJECT_CONSTRUCTORS(JSArrayBuffer, JSObject);
142};
143
144class JSArrayBufferView : public JSObject {
145 public:
146 // [buffer]: ArrayBuffer that this typed array views.
147 DECL_ACCESSORS(buffer, Object)
148
149 // [byte_offset]: offset of typed array in bytes.
150 DECL_PRIMITIVE_ACCESSORS(byte_offset, size_t)
151
152 // [byte_length]: length of typed array in bytes.
153 DECL_PRIMITIVE_ACCESSORS(byte_length, size_t)
154
155 DECL_CAST(JSArrayBufferView)
156
157 DECL_VERIFIER(JSArrayBufferView)
158
159 inline bool WasDetached() const;
160
161// Layout description.
162#define JS_ARRAY_BUFFER_VIEW_FIELDS(V) \
163 V(kBufferOffset, kTaggedSize) \
164 V(kEndOfTaggedFieldsOffset, 0) \
165 /* Raw data fields. */ \
166 V(kByteOffsetOffset, kUIntptrSize) \
167 V(kByteLengthOffset, kUIntptrSize) \
168 /* Header size. */ \
169 V(kHeaderSize, 0)
170
171 DEFINE_FIELD_OFFSET_CONSTANTS(JSObject::kHeaderSize,
172 JS_ARRAY_BUFFER_VIEW_FIELDS)
173#undef JS_ARRAY_BUFFER_VIEW_FIELDS
174
175 class BodyDescriptor;
176
177 OBJECT_CONSTRUCTORS(JSArrayBufferView, JSObject);
178};
179
180class JSTypedArray : public JSArrayBufferView {
181 public:
182 // [length]: length of typed array in elements.
183 DECL_PRIMITIVE_ACCESSORS(length, size_t)
184
185 // ES6 9.4.5.3
186 V8_WARN_UNUSED_RESULT static Maybe<bool> DefineOwnProperty(
187 Isolate* isolate, Handle<JSTypedArray> o, Handle<Object> key,
188 PropertyDescriptor* desc, Maybe<ShouldThrow> should_throw);
189
190 DECL_CAST(JSTypedArray)
191
192 ExternalArrayType type();
193 V8_EXPORT_PRIVATE size_t element_size();
194
195 V8_EXPORT_PRIVATE Handle<JSArrayBuffer> GetBuffer();
196
197 // Whether the buffer's backing store is on-heap or off-heap.
198 inline bool is_on_heap() const;
199
200 static inline MaybeHandle<JSTypedArray> Validate(Isolate* isolate,
201 Handle<Object> receiver,
202 const char* method_name);
203
204 // Dispatched behavior.
205 DECL_PRINTER(JSTypedArray)
206 DECL_VERIFIER(JSTypedArray)
207
208// Layout description.
209#define JS_TYPED_ARRAY_FIELDS(V) \
210 /* Raw data fields. */ \
211 V(kLengthOffset, kTaggedSize) \
212 /* Header size. */ \
213 V(kHeaderSize, 0)
214
215 DEFINE_FIELD_OFFSET_CONSTANTS(JSArrayBufferView::kHeaderSize,
216 JS_TYPED_ARRAY_FIELDS)
217#undef JS_TYPED_ARRAY_FIELDS
218
219 static const int kSizeWithEmbedderFields =
220 kHeaderSize +
221 v8::ArrayBufferView::kEmbedderFieldCount * kEmbedderDataSlotSize;
222
223 private:
224 static Handle<JSArrayBuffer> MaterializeArrayBuffer(
225 Handle<JSTypedArray> typed_array);
226
227 DECL_ACCESSORS(raw_length, Object)
228
229 OBJECT_CONSTRUCTORS(JSTypedArray, JSArrayBufferView);
230};
231
232class JSDataView : public JSArrayBufferView {
233 public:
234 DECL_CAST(JSDataView)
235
236 // Dispatched behavior.
237 DECL_PRINTER(JSDataView)
238 DECL_VERIFIER(JSDataView)
239
240 // Layout description.
241 static const int kSizeWithEmbedderFields =
242 kHeaderSize +
243 v8::ArrayBufferView::kEmbedderFieldCount * kEmbedderDataSlotSize;
244
245 OBJECT_CONSTRUCTORS(JSDataView, JSArrayBufferView);
246};
247
248} // namespace internal
249} // namespace v8
250
251#include "src/objects/object-macros-undef.h"
252
253#endif // V8_OBJECTS_JS_ARRAY_BUFFER_H_
254