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.h"
9 
10 // Has to be the last include (doesn't have include guards):
11 #include "src/objects/object-macros.h"
12 
13 namespace v8 {
14 namespace internal {
15 
16 // Whether a JSArrayBuffer is a SharedArrayBuffer or not.
17 enum class SharedFlag { kNotShared, kShared };
18 
19 class JSArrayBuffer : public JSObject {
20  public:
21   // [byte_length]: length in bytes
22   DECL_ACCESSORS(byte_length, Object)
23 
24   // [backing_store]: backing memory for this array
25   DECL_ACCESSORS(backing_store, void)
26 
27   // For non-wasm, allocation_length and allocation_base are byte_length and
28   // backing_store, respectively.
29   inline size_t allocation_length() const;
30   inline void* allocation_base() const;
31 
32   inline uint32_t bit_field() const;
33   inline void set_bit_field(uint32_t bits);
34 
35   // [is_external]: true indicates that the embedder is in charge of freeing the
36   // backing_store, while is_external == false means that v8 will free the
37   // memory block once all ArrayBuffers referencing it are collected by the GC.
38   inline bool is_external();
39   inline void set_is_external(bool value);
40 
41   inline bool is_neuterable();
42   inline void set_is_neuterable(bool value);
43 
44   inline bool was_neutered();
45   inline void set_was_neutered(bool value);
46 
47   inline bool is_shared();
48   inline void set_is_shared(bool value);
49 
50   inline bool is_growable();
51   inline void set_is_growable(bool value);
52 
53   DECL_CAST(JSArrayBuffer)
54 
55   void Neuter();
56 
57   struct Allocation {
AllocationAllocation58     Allocation(void* allocation_base, size_t length, void* backing_store,
59                bool is_wasm_memory)
60         : allocation_base(allocation_base),
61           length(length),
62           backing_store(backing_store),
63           is_wasm_memory(is_wasm_memory) {}
64 
65     void* allocation_base;
66     size_t length;
67     void* backing_store;
68     bool is_wasm_memory;
69   };
70 
71   // Returns whether the buffer is tracked by the WasmMemoryTracker.
72   inline bool is_wasm_memory() const;
73 
74   // Sets whether the buffer is tracked by the WasmMemoryTracker.
75   void set_is_wasm_memory(bool is_wasm_memory);
76 
77   // Removes the backing store from the WasmMemoryTracker and sets
78   // |is_wasm_memory| to false.
79   void StopTrackingWasmMemory(Isolate* isolate);
80 
81   void FreeBackingStoreFromMainThread();
82   static void FreeBackingStore(Isolate* isolate, Allocation allocation);
83 
84   V8_EXPORT_PRIVATE static void Setup(
85       Handle<JSArrayBuffer> array_buffer, Isolate* isolate, bool is_external,
86       void* data, size_t allocated_length,
87       SharedFlag shared = SharedFlag::kNotShared, bool is_wasm_memory = false);
88 
89   // Returns false if array buffer contents could not be allocated.
90   // In this case, |array_buffer| will not be set up.
91   static bool SetupAllocatingData(
92       Handle<JSArrayBuffer> array_buffer, Isolate* isolate,
93       size_t allocated_length, bool initialize = true,
94       SharedFlag shared = SharedFlag::kNotShared) V8_WARN_UNUSED_RESULT;
95 
96   // Dispatched behavior.
97   DECL_PRINTER(JSArrayBuffer)
98   DECL_VERIFIER(JSArrayBuffer)
99 
100   static const int kByteLengthOffset = JSObject::kHeaderSize;
101   // The rest of the fields are not JSObjects, so they are not iterated over in
102   // objects-body-descriptors-inl.h.
103   static const int kBackingStoreOffset = kByteLengthOffset + kPointerSize;
104   static const int kBitFieldSlot = kBackingStoreOffset + kPointerSize;
105 #if V8_TARGET_LITTLE_ENDIAN || !V8_HOST_ARCH_64_BIT
106   static const int kBitFieldOffset = kBitFieldSlot;
107 #else
108   static const int kBitFieldOffset = kBitFieldSlot + kInt32Size;
109 #endif
110   static const int kSize = kBitFieldSlot + kPointerSize;
111 
112   static const int kSizeWithEmbedderFields =
113       kSize + v8::ArrayBuffer::kEmbedderFieldCount * kPointerSize;
114 
115   // Iterates all fields in the object including internal ones except
116   // kBackingStoreOffset and kBitFieldSlot.
117   class BodyDescriptor;
118   // No weak fields.
119   typedef BodyDescriptor BodyDescriptorWeak;
120 
121   class IsExternal : public BitField<bool, 1, 1> {};
122   class IsNeuterable : public BitField<bool, 2, 1> {};
123   class WasNeutered : public BitField<bool, 3, 1> {};
124   class IsShared : public BitField<bool, 4, 1> {};
125   class IsGrowable : public BitField<bool, 5, 1> {};
126   class IsWasmMemory : public BitField<bool, 6, 1> {};
127 
128  private:
129   DISALLOW_IMPLICIT_CONSTRUCTORS(JSArrayBuffer);
130 };
131 
132 class JSArrayBufferView : public JSObject {
133  public:
134   // [buffer]: ArrayBuffer that this typed array views.
135   DECL_ACCESSORS(buffer, Object)
136 
137   // [byte_offset]: offset of typed array in bytes.
138   DECL_ACCESSORS(byte_offset, Object)
139 
140   // [byte_length]: length of typed array in bytes.
141   DECL_ACCESSORS(byte_length, Object)
142 
143   DECL_CAST(JSArrayBufferView)
144 
145   DECL_VERIFIER(JSArrayBufferView)
146 
147   inline bool WasNeutered() const;
148 
149   static const int kBufferOffset = JSObject::kHeaderSize;
150   static const int kByteOffsetOffset = kBufferOffset + kPointerSize;
151   static const int kByteLengthOffset = kByteOffsetOffset + kPointerSize;
152   static const int kViewSize = kByteLengthOffset + kPointerSize;
153 
154  private:
155 #ifdef VERIFY_HEAP
156   DECL_ACCESSORS(raw_byte_offset, Object)
157   DECL_ACCESSORS(raw_byte_length, Object)
158 #endif
159 
160   DISALLOW_IMPLICIT_CONSTRUCTORS(JSArrayBufferView);
161 };
162 
163 class JSTypedArray : public JSArrayBufferView {
164  public:
165   // [length]: length of typed array in elements.
166   DECL_ACCESSORS(length, Object)
167   inline size_t length_value() const;
168 
169   // ES6 9.4.5.3
170   V8_WARN_UNUSED_RESULT static Maybe<bool> DefineOwnProperty(
171       Isolate* isolate, Handle<JSTypedArray> o, Handle<Object> key,
172       PropertyDescriptor* desc, ShouldThrow should_throw);
173 
174   DECL_CAST(JSTypedArray)
175 
176   ExternalArrayType type();
177   V8_EXPORT_PRIVATE size_t element_size();
178 
179   Handle<JSArrayBuffer> GetBuffer();
180 
181   // Whether the buffer's backing store is on-heap or off-heap.
182   inline bool is_on_heap() const;
183 
184   static inline MaybeHandle<JSTypedArray> Validate(Isolate* isolate,
185                                                    Handle<Object> receiver,
186                                                    const char* method_name);
187 
188   // Dispatched behavior.
189   DECL_PRINTER(JSTypedArray)
190   DECL_VERIFIER(JSTypedArray)
191 
192   static const int kLengthOffset = kViewSize;
193   static const int kSize = kLengthOffset + kPointerSize;
194 
195   static const int kSizeWithEmbedderFields =
196       kSize + v8::ArrayBufferView::kEmbedderFieldCount * kPointerSize;
197 
198  private:
199   static Handle<JSArrayBuffer> MaterializeArrayBuffer(
200       Handle<JSTypedArray> typed_array);
201 #ifdef VERIFY_HEAP
202   DECL_ACCESSORS(raw_length, Object)
203 #endif
204 
205   DISALLOW_IMPLICIT_CONSTRUCTORS(JSTypedArray);
206 };
207 
208 class JSDataView : public JSArrayBufferView {
209  public:
210   DECL_CAST(JSDataView)
211 
212   // Dispatched behavior.
213   DECL_PRINTER(JSDataView)
214   DECL_VERIFIER(JSDataView)
215 
216   static const int kSize = kViewSize;
217 
218   static const int kSizeWithEmbedderFields =
219       kSize + v8::ArrayBufferView::kEmbedderFieldCount * kPointerSize;
220 
221  private:
222   DISALLOW_IMPLICIT_CONSTRUCTORS(JSDataView);
223 };
224 
225 }  // namespace internal
226 }  // namespace v8
227 
228 #include "src/objects/object-macros-undef.h"
229 
230 #endif  // V8_OBJECTS_JS_ARRAY_BUFFER_H_
231