Line data Source code
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_INL_H_
6 : #define V8_OBJECTS_JS_ARRAY_BUFFER_INL_H_
7 :
8 : #include "src/objects/js-array-buffer.h"
9 :
10 : #include "src/heap/heap-write-barrier-inl.h"
11 : #include "src/objects-inl.h"
12 : #include "src/objects/js-objects-inl.h"
13 : #include "src/wasm/wasm-engine.h"
14 :
15 : // Has to be the last include (doesn't have include guards):
16 : #include "src/objects/object-macros.h"
17 :
18 : namespace v8 {
19 : namespace internal {
20 :
21 132434194 : OBJECT_CONSTRUCTORS_IMPL(JSArrayBuffer, JSObject)
22 3825672 : OBJECT_CONSTRUCTORS_IMPL(JSArrayBufferView, JSObject)
23 40983108 : OBJECT_CONSTRUCTORS_IMPL(JSTypedArray, JSArrayBufferView)
24 40372 : OBJECT_CONSTRUCTORS_IMPL(JSDataView, JSArrayBufferView)
25 :
26 66217124 : CAST_ACCESSOR(JSArrayBuffer)
27 1912836 : CAST_ACCESSOR(JSArrayBufferView)
28 20491514 : CAST_ACCESSOR(JSTypedArray)
29 20186 : CAST_ACCESSOR(JSDataView)
30 :
31 3293 : size_t JSArrayBuffer::byte_length() const {
32 1148550 : return READ_UINTPTR_FIELD(*this, kByteLengthOffset);
33 : }
34 :
35 : void JSArrayBuffer::set_byte_length(size_t value) {
36 410966 : WRITE_UINTPTR_FIELD(*this, kByteLengthOffset, value);
37 : }
38 :
39 6322 : void* JSArrayBuffer::backing_store() const {
40 22264068 : intptr_t ptr = READ_INTPTR_FIELD(*this, kBackingStoreOffset);
41 22264068 : return reinterpret_cast<void*>(ptr);
42 : }
43 :
44 : void JSArrayBuffer::set_backing_store(void* value, WriteBarrierMode mode) {
45 416743 : intptr_t ptr = reinterpret_cast<intptr_t>(value);
46 421953 : WRITE_INTPTR_FIELD(*this, kBackingStoreOffset, ptr);
47 : }
48 :
49 282439 : size_t JSArrayBuffer::allocation_length() const {
50 282439 : if (backing_store() == nullptr) {
51 : return 0;
52 : }
53 : // If this buffer is managed by the WasmMemoryTracker
54 282243 : if (is_wasm_memory()) {
55 : const auto* data =
56 : GetIsolate()->wasm_engine()->memory_tracker()->FindAllocationData(
57 2276 : backing_store());
58 : DCHECK_NOT_NULL(data);
59 2276 : return data->allocation_length;
60 : }
61 279967 : return byte_length();
62 : }
63 :
64 280290 : void* JSArrayBuffer::allocation_base() const {
65 280290 : if (backing_store() == nullptr) {
66 : return nullptr;
67 : }
68 : // If this buffer is managed by the WasmMemoryTracker
69 280094 : if (is_wasm_memory()) {
70 : const auto* data =
71 : GetIsolate()->wasm_engine()->memory_tracker()->FindAllocationData(
72 128 : backing_store());
73 : DCHECK_NOT_NULL(data);
74 128 : return data->allocation_base;
75 : }
76 : return backing_store();
77 : }
78 :
79 : bool JSArrayBuffer::is_wasm_memory() const {
80 : bool const is_wasm_memory = IsWasmMemoryBit::decode(bit_field());
81 : DCHECK_EQ(is_wasm_memory,
82 : GetIsolate()->wasm_engine()->memory_tracker()->IsWasmMemory(
83 : backing_store()));
84 : return is_wasm_memory;
85 : }
86 :
87 : void JSArrayBuffer::set_is_wasm_memory(bool is_wasm_memory) {
88 : set_bit_field(IsWasmMemoryBit::update(bit_field(), is_wasm_memory));
89 : }
90 :
91 : void JSArrayBuffer::clear_padding() {
92 : if (FIELD_SIZE(kOptionalPaddingOffset) != 0) {
93 : DCHECK_EQ(4, FIELD_SIZE(kOptionalPaddingOffset));
94 : memset(reinterpret_cast<void*>(address() + kOptionalPaddingOffset), 0,
95 405807 : FIELD_SIZE(kOptionalPaddingOffset));
96 : }
97 : }
98 :
99 : void JSArrayBuffer::set_bit_field(uint32_t bits) {
100 2424381 : WRITE_UINT32_FIELD(*this, kBitFieldOffset, bits);
101 : }
102 :
103 : uint32_t JSArrayBuffer::bit_field() const {
104 48965197 : return READ_UINT32_FIELD(*this, kBitFieldOffset);
105 : }
106 :
107 : // |bit_field| fields.
108 5914 : BIT_FIELD_ACCESSORS(JSArrayBuffer, bit_field, is_external,
109 : JSArrayBuffer::IsExternalBit)
110 5968 : BIT_FIELD_ACCESSORS(JSArrayBuffer, bit_field, is_detachable,
111 : JSArrayBuffer::IsDetachableBit)
112 : BIT_FIELD_ACCESSORS(JSArrayBuffer, bit_field, was_detached,
113 : JSArrayBuffer::WasDetachedBit)
114 40389662 : BIT_FIELD_ACCESSORS(JSArrayBuffer, bit_field, is_shared,
115 : JSArrayBuffer::IsSharedBit)
116 : BIT_FIELD_ACCESSORS(JSArrayBuffer, bit_field, is_growable,
117 : JSArrayBuffer::IsGrowableBit)
118 :
119 20191874 : size_t JSArrayBufferView::byte_offset() const {
120 20196224 : return READ_UINTPTR_FIELD(*this, kByteOffsetOffset);
121 : }
122 :
123 : void JSArrayBufferView::set_byte_offset(size_t value) {
124 4376 : WRITE_UINTPTR_FIELD(*this, kByteOffsetOffset, value);
125 : }
126 :
127 : size_t JSArrayBufferView::byte_length() const {
128 7039 : return READ_UINTPTR_FIELD(*this, kByteLengthOffset);
129 : }
130 :
131 : void JSArrayBufferView::set_byte_length(size_t value) {
132 4376 : WRITE_UINTPTR_FIELD(*this, kByteLengthOffset, value);
133 : }
134 :
135 64579872 : ACCESSORS(JSArrayBufferView, buffer, Object, kBufferOffset)
136 :
137 24152369 : bool JSArrayBufferView::WasDetached() const {
138 24152369 : return JSArrayBuffer::cast(buffer())->was_detached();
139 : }
140 :
141 60597936 : Object JSTypedArray::length() const { return READ_FIELD(*this, kLengthOffset); }
142 :
143 1737 : size_t JSTypedArray::length_value() const {
144 22314 : double val = length()->Number();
145 : DCHECK_LE(val, kMaxSafeInteger); // 2^53-1
146 : DCHECK_GE(val, -kMaxSafeInteger); // -2^53+1
147 : DCHECK_LE(val, std::numeric_limits<size_t>::max());
148 : DCHECK_GE(val, std::numeric_limits<size_t>::min());
149 22314 : return static_cast<size_t>(val);
150 : }
151 :
152 394 : void JSTypedArray::set_length(Object value, WriteBarrierMode mode) {
153 394 : WRITE_FIELD(*this, kLengthOffset, value);
154 1182 : CONDITIONAL_WRITE_BARRIER(*this, kLengthOffset, value, mode);
155 394 : }
156 :
157 40407079 : bool JSTypedArray::is_on_heap() const {
158 : DisallowHeapAllocation no_gc;
159 : // Checking that buffer()->backing_store() is not nullptr is not sufficient;
160 : // it will be nullptr when byte_length is 0 as well.
161 80814157 : FixedTypedArrayBase fta = FixedTypedArrayBase::cast(elements());
162 40407078 : return fta->base_pointer()->ptr() == fta.ptr();
163 : }
164 :
165 : // static
166 13778 : MaybeHandle<JSTypedArray> JSTypedArray::Validate(Isolate* isolate,
167 : Handle<Object> receiver,
168 : const char* method_name) {
169 27556 : if (V8_UNLIKELY(!receiver->IsJSTypedArray())) {
170 : const MessageTemplate message = MessageTemplate::kNotTypedArray;
171 846 : THROW_NEW_ERROR(isolate, NewTypeError(message), JSTypedArray);
172 : }
173 :
174 12932 : Handle<JSTypedArray> array = Handle<JSTypedArray>::cast(receiver);
175 12932 : if (V8_UNLIKELY(array->WasDetached())) {
176 : const MessageTemplate message = MessageTemplate::kDetachedOperation;
177 : Handle<String> operation =
178 405 : isolate->factory()->NewStringFromAsciiChecked(method_name);
179 405 : THROW_NEW_ERROR(isolate, NewTypeError(message, operation), JSTypedArray);
180 : }
181 :
182 : // spec describes to return `buffer`, but it may disrupt current
183 : // implementations, and it's much useful to return array for now.
184 12527 : return array;
185 : }
186 :
187 : #ifdef VERIFY_HEAP
188 : ACCESSORS(JSTypedArray, raw_length, Object, kLengthOffset)
189 : #endif
190 :
191 : } // namespace internal
192 : } // namespace v8
193 :
194 : #include "src/objects/object-macros-undef.h"
195 :
196 : #endif // V8_OBJECTS_JS_ARRAY_BUFFER_INL_H_
|