Line data Source code
1 : // Copyright 2017 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_INL_H_
6 : #define V8_OBJECTS_JS_ARRAY_INL_H_
7 :
8 : #include "src/objects/js-array.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 268809055 : TYPE_CHECKER(JSArray, JS_ARRAY_TYPE)
17 429319169 : TYPE_CHECKER(JSArrayBuffer, JS_ARRAY_BUFFER_TYPE)
18 374580482 : TYPE_CHECKER(JSTypedArray, JS_TYPED_ARRAY_TYPE)
19 :
20 : CAST_ACCESSOR(JSArray)
21 : CAST_ACCESSOR(JSArrayBuffer)
22 : CAST_ACCESSOR(JSArrayBufferView)
23 : CAST_ACCESSOR(JSArrayIterator)
24 : CAST_ACCESSOR(JSTypedArray)
25 :
26 205925336 : ACCESSORS(JSArray, length, Object, kLengthOffset)
27 :
28 : template <>
29 : inline bool Is<JSArray>(Object* obj) {
30 : return obj->IsJSArray();
31 : }
32 :
33 1481 : void JSArray::set_length(Smi* length) {
34 : // Don't need a write barrier for a Smi.
35 18403178 : set_length(static_cast<Object*>(length), SKIP_WRITE_BARRIER);
36 1481 : }
37 :
38 3322 : bool JSArray::SetLengthWouldNormalize(Heap* heap, uint32_t new_length) {
39 3322 : return new_length > kMaxFastArrayLength;
40 : }
41 :
42 : bool JSArray::AllowsSetLength() {
43 : bool result = elements()->IsFixedArray() || elements()->IsFixedDoubleArray();
44 : DCHECK(result == !HasFixedTypedArrayElements());
45 : return result;
46 : }
47 :
48 93724 : void JSArray::SetContent(Handle<JSArray> array,
49 : Handle<FixedArrayBase> storage) {
50 : EnsureCanContainElements(array, storage, storage->length(),
51 187448 : ALLOW_COPIED_DOUBLE_ELEMENTS);
52 :
53 : DCHECK((storage->map() == array->GetHeap()->fixed_double_array_map() &&
54 : IsDoubleElementsKind(array->GetElementsKind())) ||
55 : ((storage->map() != array->GetHeap()->fixed_double_array_map()) &&
56 : (IsObjectElementsKind(array->GetElementsKind()) ||
57 : (IsSmiElementsKind(array->GetElementsKind()) &&
58 : Handle<FixedArray>::cast(storage)->ContainsOnlySmisOrHoles()))));
59 93724 : array->set_elements(*storage);
60 : array->set_length(Smi::FromInt(storage->length()));
61 93724 : }
62 :
63 545767 : bool JSArray::HasArrayPrototype(Isolate* isolate) {
64 1091534 : return map()->prototype() == *isolate->initial_array_prototype();
65 : }
66 :
67 2096 : void* JSArrayBuffer::backing_store() const {
68 30169388 : intptr_t ptr = READ_INTPTR_FIELD(this, kBackingStoreOffset);
69 30169388 : return reinterpret_cast<void*>(ptr);
70 : }
71 :
72 : void JSArrayBuffer::set_backing_store(void* value, WriteBarrierMode mode) {
73 260924 : intptr_t ptr = reinterpret_cast<intptr_t>(value);
74 504637 : WRITE_INTPTR_FIELD(this, kBackingStoreOffset, ptr);
75 : }
76 :
77 1976041 : ACCESSORS(JSArrayBuffer, byte_length, Object, kByteLengthOffset)
78 :
79 934 : void* JSArrayBuffer::allocation_base() const {
80 546793 : intptr_t ptr = READ_INTPTR_FIELD(this, kAllocationBaseOffset);
81 546793 : return reinterpret_cast<void*>(ptr);
82 : }
83 :
84 : void JSArrayBuffer::set_allocation_base(void* value, WriteBarrierMode mode) {
85 : intptr_t ptr = reinterpret_cast<intptr_t>(value);
86 504613 : WRITE_INTPTR_FIELD(this, kAllocationBaseOffset, ptr);
87 : }
88 :
89 : size_t JSArrayBuffer::allocation_length() const {
90 : return *reinterpret_cast<const size_t*>(
91 560720 : FIELD_ADDR_CONST(this, kAllocationLengthOffset));
92 : }
93 :
94 : void JSArrayBuffer::set_allocation_length(size_t value) {
95 : (*reinterpret_cast<size_t*>(FIELD_ADDR(this, kAllocationLengthOffset))) =
96 504583 : value;
97 : }
98 :
99 : ArrayBuffer::Allocator::AllocationMode JSArrayBuffer::allocation_mode() const {
100 : using AllocationMode = ArrayBuffer::Allocator::AllocationMode;
101 : return has_guard_region() ? AllocationMode::kReservation
102 241350 : : AllocationMode::kNormal;
103 : }
104 :
105 : void JSArrayBuffer::set_bit_field(uint32_t bits) {
106 : if (kInt32Size != kPointerSize) {
107 : #if V8_TARGET_LITTLE_ENDIAN
108 1074774 : WRITE_UINT32_FIELD(this, kBitFieldSlot + kInt32Size, 0);
109 : #else
110 : WRITE_UINT32_FIELD(this, kBitFieldSlot, 0);
111 : #endif
112 : }
113 1074774 : WRITE_UINT32_FIELD(this, kBitFieldOffset, bits);
114 : }
115 :
116 : uint32_t JSArrayBuffer::bit_field() const {
117 53225032 : return READ_UINT32_FIELD(this, kBitFieldOffset);
118 : }
119 :
120 140 : bool JSArrayBuffer::is_external() { return IsExternal::decode(bit_field()); }
121 :
122 2086 : void JSArrayBuffer::set_is_external(bool value) {
123 : set_bit_field(IsExternal::update(bit_field(), value));
124 2086 : }
125 :
126 1956 : bool JSArrayBuffer::is_neuterable() {
127 1956 : return IsNeuterable::decode(bit_field());
128 : }
129 :
130 : void JSArrayBuffer::set_is_neuterable(bool value) {
131 : set_bit_field(IsNeuterable::update(bit_field(), value));
132 : }
133 :
134 : bool JSArrayBuffer::was_neutered() { return WasNeutered::decode(bit_field()); }
135 :
136 : void JSArrayBuffer::set_was_neutered(bool value) {
137 : set_bit_field(WasNeutered::update(bit_field(), value));
138 : }
139 :
140 19663416 : bool JSArrayBuffer::is_shared() { return IsShared::decode(bit_field()); }
141 :
142 : void JSArrayBuffer::set_is_shared(bool value) {
143 : set_bit_field(IsShared::update(bit_field(), value));
144 : }
145 :
146 : bool JSArrayBuffer::has_guard_region() const {
147 : return HasGuardRegion::decode(bit_field());
148 : }
149 :
150 : void JSArrayBuffer::set_has_guard_region(bool value) {
151 : set_bit_field(HasGuardRegion::update(bit_field(), value));
152 : }
153 :
154 : bool JSArrayBuffer::is_wasm_buffer() {
155 : return IsWasmBuffer::decode(bit_field());
156 : }
157 :
158 : void JSArrayBuffer::set_is_wasm_buffer(bool value) {
159 : set_bit_field(IsWasmBuffer::update(bit_field(), value));
160 : }
161 :
162 9838211 : Object* JSArrayBufferView::byte_offset() const {
163 9858723 : if (WasNeutered()) return Smi::kZero;
164 9858579 : return Object::cast(READ_FIELD(this, kByteOffsetOffset));
165 : }
166 :
167 4170 : void JSArrayBufferView::set_byte_offset(Object* value, WriteBarrierMode mode) {
168 4170 : WRITE_FIELD(this, kByteOffsetOffset, value);
169 16680 : CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kByteOffsetOffset, value, mode);
170 4170 : }
171 :
172 1514 : Object* JSArrayBufferView::byte_length() const {
173 28080 : if (WasNeutered()) return Smi::kZero;
174 27935 : return Object::cast(READ_FIELD(this, kByteLengthOffset));
175 : }
176 :
177 4170 : void JSArrayBufferView::set_byte_length(Object* value, WriteBarrierMode mode) {
178 4170 : WRITE_FIELD(this, kByteLengthOffset, value);
179 16680 : CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kByteLengthOffset, value, mode);
180 4170 : }
181 :
182 41661925 : ACCESSORS(JSArrayBufferView, buffer, Object, kBufferOffset)
183 : #ifdef VERIFY_HEAP
184 : ACCESSORS(JSArrayBufferView, raw_byte_offset, Object, kByteOffsetOffset)
185 : ACCESSORS(JSArrayBufferView, raw_byte_length, Object, kByteLengthOffset)
186 : #endif
187 :
188 18101 : bool JSArrayBufferView::WasNeutered() const {
189 18101 : return JSArrayBuffer::cast(buffer())->was_neutered();
190 : }
191 :
192 9848681 : Object* JSTypedArray::length() const {
193 9848872 : if (WasNeutered()) return Smi::kZero;
194 9848845 : return Object::cast(READ_FIELD(this, kLengthOffset));
195 : }
196 :
197 48847 : uint32_t JSTypedArray::length_value() const {
198 48847 : if (WasNeutered()) return 0;
199 48739 : uint32_t index = 0;
200 97478 : CHECK(Object::cast(READ_FIELD(this, kLengthOffset))->ToArrayLength(&index));
201 48739 : return index;
202 : }
203 :
204 535 : void JSTypedArray::set_length(Object* value, WriteBarrierMode mode) {
205 535 : WRITE_FIELD(this, kLengthOffset, value);
206 2140 : CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kLengthOffset, value, mode);
207 535 : }
208 :
209 : // static
210 31102 : MaybeHandle<JSTypedArray> JSTypedArray::Validate(Isolate* isolate,
211 : Handle<Object> receiver,
212 : const char* method_name) {
213 31102 : if (V8_UNLIKELY(!receiver->IsJSTypedArray())) {
214 : const MessageTemplate::Template message = MessageTemplate::kNotTypedArray;
215 2340 : THROW_NEW_ERROR(isolate, NewTypeError(message), JSTypedArray);
216 : }
217 :
218 : Handle<JSTypedArray> array = Handle<JSTypedArray>::cast(receiver);
219 29932 : if (V8_UNLIKELY(array->WasNeutered())) {
220 : const MessageTemplate::Template message =
221 : MessageTemplate::kDetachedOperation;
222 : Handle<String> operation =
223 486 : isolate->factory()->NewStringFromAsciiChecked(method_name);
224 972 : THROW_NEW_ERROR(isolate, NewTypeError(message, operation), JSTypedArray);
225 : }
226 :
227 : // spec describes to return `buffer`, but it may disrupt current
228 : // implementations, and it's much useful to return array for now.
229 29446 : return array;
230 : }
231 :
232 : #ifdef VERIFY_HEAP
233 : ACCESSORS(JSTypedArray, raw_length, Object, kLengthOffset)
234 : #endif
235 :
236 505 : ACCESSORS(JSArrayIterator, object, Object, kIteratedObjectOffset)
237 1010 : ACCESSORS(JSArrayIterator, index, Object, kNextIndexOffset)
238 505 : ACCESSORS(JSArrayIterator, object_map, Object, kIteratedObjectMapOffset)
239 :
240 : } // namespace internal
241 : } // namespace v8
242 :
243 : #include "src/objects/object-macros-undef.h"
244 :
245 : #endif // V8_OBJECTS_JS_ARRAY_INL_H_
|