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 : OBJECT_CONSTRUCTORS_IMPL(JSArrayBuffer, JSObject)
22 : OBJECT_CONSTRUCTORS_IMPL(JSArrayBufferView, JSObject)
23 : OBJECT_CONSTRUCTORS_IMPL(JSTypedArray, JSArrayBufferView)
24 : OBJECT_CONSTRUCTORS_IMPL(JSDataView, JSArrayBufferView)
25 :
26 : CAST_ACCESSOR(JSArrayBuffer)
27 : CAST_ACCESSOR(JSArrayBufferView)
28 : CAST_ACCESSOR(JSTypedArray)
29 : CAST_ACCESSOR(JSDataView)
30 :
31 : size_t JSArrayBuffer::byte_length() const {
32 1265699 : return READ_UINTPTR_FIELD(*this, kByteLengthOffset);
33 : }
34 :
35 : void JSArrayBuffer::set_byte_length(size_t value) {
36 515739 : WRITE_UINTPTR_FIELD(*this, kByteLengthOffset, value);
37 : }
38 :
39 : void* JSArrayBuffer::backing_store() const {
40 34065863 : intptr_t ptr = READ_INTPTR_FIELD(*this, kBackingStoreOffset);
41 34046475 : return reinterpret_cast<void*>(ptr);
42 : }
43 :
44 : void JSArrayBuffer::set_backing_store(void* value, WriteBarrierMode mode) {
45 527862 : intptr_t ptr = reinterpret_cast<intptr_t>(value);
46 532897 : WRITE_INTPTR_FIELD(*this, kBackingStoreOffset, ptr);
47 : }
48 :
49 287193 : size_t JSArrayBuffer::allocation_length() const {
50 287193 : if (backing_store() == nullptr) {
51 : return 0;
52 : }
53 : // If this buffer is managed by the WasmMemoryTracker
54 286997 : if (is_wasm_memory()) {
55 : const auto* data =
56 : GetIsolate()->wasm_engine()->memory_tracker()->FindAllocationData(
57 4576 : backing_store());
58 : DCHECK_NOT_NULL(data);
59 4576 : return data->allocation_length;
60 : }
61 282421 : return byte_length();
62 : }
63 :
64 282793 : void* JSArrayBuffer::allocation_base() const {
65 282793 : if (backing_store() == nullptr) {
66 : return nullptr;
67 : }
68 : // If this buffer is managed by the WasmMemoryTracker
69 282597 : if (is_wasm_memory()) {
70 : const auto* data =
71 : GetIsolate()->wasm_engine()->memory_tracker()->FindAllocationData(
72 172 : backing_store());
73 : DCHECK_NOT_NULL(data);
74 172 : return data->allocation_base;
75 : }
76 : return backing_store();
77 : }
78 :
79 : bool JSArrayBuffer::is_wasm_memory() const {
80 : return IsWasmMemoryBit::decode(bit_field());
81 : }
82 :
83 : void JSArrayBuffer::set_is_wasm_memory(bool is_wasm_memory) {
84 : set_bit_field(IsWasmMemoryBit::update(bit_field(), is_wasm_memory));
85 : }
86 :
87 : void JSArrayBuffer::clear_padding() {
88 : if (FIELD_SIZE(kOptionalPaddingOffset) != 0) {
89 : DCHECK_EQ(4, FIELD_SIZE(kOptionalPaddingOffset));
90 : memset(reinterpret_cast<void*>(address() + kOptionalPaddingOffset), 0,
91 : FIELD_SIZE(kOptionalPaddingOffset));
92 : }
93 : }
94 :
95 : void JSArrayBuffer::set_bit_field(uint32_t bits) {
96 2956582 : WRITE_UINT32_FIELD(*this, kBitFieldOffset, bits);
97 : }
98 :
99 : uint32_t JSArrayBuffer::bit_field() const {
100 82962078 : return READ_UINT32_FIELD(*this, kBitFieldOffset);
101 : }
102 :
103 : // |bit_field| fields.
104 : BIT_FIELD_ACCESSORS(JSArrayBuffer, bit_field, is_external,
105 : JSArrayBuffer::IsExternalBit)
106 : BIT_FIELD_ACCESSORS(JSArrayBuffer, bit_field, is_detachable,
107 : JSArrayBuffer::IsDetachableBit)
108 : BIT_FIELD_ACCESSORS(JSArrayBuffer, bit_field, was_detached,
109 : JSArrayBuffer::WasDetachedBit)
110 : BIT_FIELD_ACCESSORS(JSArrayBuffer, bit_field, is_shared,
111 : JSArrayBuffer::IsSharedBit)
112 : BIT_FIELD_ACCESSORS(JSArrayBuffer, bit_field, is_growable,
113 : JSArrayBuffer::IsGrowableBit)
114 :
115 : size_t JSArrayBufferView::byte_offset() const {
116 31851570 : return READ_UINTPTR_FIELD(*this, kByteOffsetOffset);
117 : }
118 :
119 : void JSArrayBufferView::set_byte_offset(size_t value) {
120 4450 : WRITE_UINTPTR_FIELD(*this, kByteOffsetOffset, value);
121 : }
122 :
123 : size_t JSArrayBufferView::byte_length() const {
124 31972 : return READ_UINTPTR_FIELD(*this, kByteLengthOffset);
125 : }
126 :
127 : void JSArrayBufferView::set_byte_length(size_t value) {
128 4450 : WRITE_UINTPTR_FIELD(*this, kByteLengthOffset, value);
129 : }
130 :
131 99778627 : ACCESSORS(JSArrayBufferView, buffer, Object, kBufferOffset)
132 :
133 : bool JSArrayBufferView::WasDetached() const {
134 : return JSArrayBuffer::cast(buffer())->was_detached();
135 : }
136 :
137 31845092 : Object JSTypedArray::length() const { return READ_FIELD(*this, kLengthOffset); }
138 :
139 : size_t JSTypedArray::length_value() const {
140 : double val = length()->Number();
141 : DCHECK_LE(val, kMaxSafeInteger); // 2^53-1
142 : DCHECK_GE(val, -kMaxSafeInteger); // -2^53+1
143 : DCHECK_LE(val, std::numeric_limits<size_t>::max());
144 : DCHECK_GE(val, std::numeric_limits<size_t>::min());
145 22563 : return static_cast<size_t>(val);
146 : }
147 :
148 432 : void JSTypedArray::set_length(Object value, WriteBarrierMode mode) {
149 432 : WRITE_FIELD(*this, kLengthOffset, value);
150 864 : CONDITIONAL_WRITE_BARRIER(*this, kLengthOffset, value, mode);
151 432 : }
152 :
153 63855063 : bool JSTypedArray::is_on_heap() const {
154 : DisallowHeapAllocation no_gc;
155 : // Checking that buffer()->backing_store() is not nullptr is not sufficient;
156 : // it will be nullptr when byte_length is 0 as well.
157 : FixedTypedArrayBase fta = FixedTypedArrayBase::cast(elements());
158 63855063 : return fta->base_pointer()->ptr() == fta.ptr();
159 : }
160 :
161 : // static
162 13787 : MaybeHandle<JSTypedArray> JSTypedArray::Validate(Isolate* isolate,
163 : Handle<Object> receiver,
164 : const char* method_name) {
165 13787 : if (V8_UNLIKELY(!receiver->IsJSTypedArray())) {
166 : const MessageTemplate message = MessageTemplate::kNotTypedArray;
167 1692 : THROW_NEW_ERROR(isolate, NewTypeError(message), JSTypedArray);
168 : }
169 :
170 : Handle<JSTypedArray> array = Handle<JSTypedArray>::cast(receiver);
171 12941 : if (V8_UNLIKELY(array->WasDetached())) {
172 : const MessageTemplate message = MessageTemplate::kDetachedOperation;
173 : Handle<String> operation =
174 405 : isolate->factory()->NewStringFromAsciiChecked(method_name);
175 810 : THROW_NEW_ERROR(isolate, NewTypeError(message, operation), JSTypedArray);
176 : }
177 :
178 : // spec describes to return `buffer`, but it may disrupt current
179 : // implementations, and it's much useful to return array for now.
180 12536 : return array;
181 : }
182 :
183 : #ifdef VERIFY_HEAP
184 : ACCESSORS(JSTypedArray, raw_length, Object, kLengthOffset)
185 : #endif
186 :
187 : } // namespace internal
188 : } // namespace v8
189 :
190 : #include "src/objects/object-macros-undef.h"
191 :
192 : #endif // V8_OBJECTS_JS_ARRAY_BUFFER_INL_H_
|