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_FIXED_ARRAY_H_
6 : #define V8_OBJECTS_FIXED_ARRAY_H_
7 :
8 : #include "src/maybe-handles.h"
9 : #include "src/objects/instance-type.h"
10 : #include "src/objects/smi.h"
11 : #include "torque-generated/class-definitions-from-dsl.h"
12 :
13 : // Has to be the last include (doesn't have include guards):
14 : #include "src/objects/object-macros.h"
15 :
16 : namespace v8 {
17 : namespace internal {
18 : using WeakArrayBodyDescriptor =
19 : FlexibleWeakBodyDescriptor<HeapObject::kHeaderSize>;
20 :
21 : #define FIXED_ARRAY_SUB_INSTANCE_TYPE_LIST(V) \
22 : V(BYTECODE_ARRAY_CONSTANT_POOL_SUB_TYPE) \
23 : V(BYTECODE_ARRAY_HANDLER_TABLE_SUB_TYPE) \
24 : V(CODE_STUBS_TABLE_SUB_TYPE) \
25 : V(COMPILATION_CACHE_TABLE_SUB_TYPE) \
26 : V(CONTEXT_SUB_TYPE) \
27 : V(COPY_ON_WRITE_SUB_TYPE) \
28 : V(DEOPTIMIZATION_DATA_SUB_TYPE) \
29 : V(DESCRIPTOR_ARRAY_SUB_TYPE) \
30 : V(EMBEDDED_OBJECT_SUB_TYPE) \
31 : V(ENUM_CACHE_SUB_TYPE) \
32 : V(ENUM_INDICES_CACHE_SUB_TYPE) \
33 : V(DEPENDENT_CODE_SUB_TYPE) \
34 : V(DICTIONARY_ELEMENTS_SUB_TYPE) \
35 : V(DICTIONARY_PROPERTIES_SUB_TYPE) \
36 : V(EMPTY_PROPERTIES_DICTIONARY_SUB_TYPE) \
37 : V(PACKED_ELEMENTS_SUB_TYPE) \
38 : V(FAST_PROPERTIES_SUB_TYPE) \
39 : V(FAST_TEMPLATE_INSTANTIATIONS_CACHE_SUB_TYPE) \
40 : V(HANDLER_TABLE_SUB_TYPE) \
41 : V(JS_COLLECTION_SUB_TYPE) \
42 : V(JS_WEAK_COLLECTION_SUB_TYPE) \
43 : V(NOSCRIPT_SHARED_FUNCTION_INFOS_SUB_TYPE) \
44 : V(NUMBER_STRING_CACHE_SUB_TYPE) \
45 : V(OBJECT_TO_CODE_SUB_TYPE) \
46 : V(OPTIMIZED_CODE_LITERALS_SUB_TYPE) \
47 : V(OPTIMIZED_CODE_MAP_SUB_TYPE) \
48 : V(PROTOTYPE_USERS_SUB_TYPE) \
49 : V(REGEXP_MULTIPLE_CACHE_SUB_TYPE) \
50 : V(RETAINED_MAPS_SUB_TYPE) \
51 : V(SCOPE_INFO_SUB_TYPE) \
52 : V(SCRIPT_LIST_SUB_TYPE) \
53 : V(SERIALIZED_OBJECTS_SUB_TYPE) \
54 : V(SHARED_FUNCTION_INFOS_SUB_TYPE) \
55 : V(SINGLE_CHARACTER_STRING_CACHE_SUB_TYPE) \
56 : V(SLOW_TEMPLATE_INSTANTIATIONS_CACHE_SUB_TYPE) \
57 : V(STRING_SPLIT_CACHE_SUB_TYPE) \
58 : V(STRING_TABLE_SUB_TYPE) \
59 : V(TEMPLATE_INFO_SUB_TYPE) \
60 : V(FEEDBACK_METADATA_SUB_TYPE) \
61 : V(WEAK_NEW_SPACE_OBJECT_TO_CODE_SUB_TYPE)
62 :
63 : enum FixedArraySubInstanceType {
64 : #define DEFINE_FIXED_ARRAY_SUB_INSTANCE_TYPE(name) name,
65 : FIXED_ARRAY_SUB_INSTANCE_TYPE_LIST(DEFINE_FIXED_ARRAY_SUB_INSTANCE_TYPE)
66 : #undef DEFINE_FIXED_ARRAY_SUB_INSTANCE_TYPE
67 : LAST_FIXED_ARRAY_SUB_TYPE = WEAK_NEW_SPACE_OBJECT_TO_CODE_SUB_TYPE
68 : };
69 :
70 : // Common superclass for FixedArrays that allow implementations to share
71 : // common accessors and some code paths.
72 : class FixedArrayBase : public HeapObject {
73 : public:
74 : // [length]: length of the array.
75 : inline int length() const;
76 : inline void set_length(int value);
77 :
78 : // Get and set the length using acquire loads and release stores.
79 : inline int synchronized_length() const;
80 : inline void synchronized_set_length(int value);
81 :
82 : inline Object unchecked_synchronized_length() const;
83 :
84 : DECL_CAST(FixedArrayBase)
85 :
86 : static int GetMaxLengthForNewSpaceAllocation(ElementsKind kind);
87 :
88 : V8_EXPORT_PRIVATE bool IsCowArray() const;
89 :
90 : // Maximal allowed size, in bytes, of a single FixedArrayBase.
91 : // Prevents overflowing size computations, as well as extreme memory
92 : // consumption.
93 : #ifdef V8_HOST_ARCH_32_BIT
94 : static const int kMaxSize = 512 * MB;
95 : #else
96 : static const int kMaxSize = 1024 * MB;
97 : #endif // V8_HOST_ARCH_32_BIT
98 :
99 : // Layout description.
100 : DEFINE_FIELD_OFFSET_CONSTANTS(HeapObject::kHeaderSize,
101 : TORQUE_GENERATED_FIXED_ARRAY_BASE_FIELDS)
102 :
103 : static const int kHeaderSize = kSize;
104 :
105 : protected:
106 : // Special-purpose constructor for subclasses that have fast paths where
107 : // their ptr() is a Smi.
108 : inline FixedArrayBase(Address ptr, AllowInlineSmiStorage allow_smi);
109 :
110 : OBJECT_CONSTRUCTORS(FixedArrayBase, HeapObject);
111 : };
112 :
113 : // FixedArray describes fixed-sized arrays with element type Object.
114 : class FixedArray : public FixedArrayBase {
115 : public:
116 : // Setter and getter for elements.
117 : inline Object get(int index) const;
118 : static inline Handle<Object> get(FixedArray array, int index,
119 : Isolate* isolate);
120 : template <class T>
121 : MaybeHandle<T> GetValue(Isolate* isolate, int index) const;
122 :
123 : template <class T>
124 : Handle<T> GetValueChecked(Isolate* isolate, int index) const;
125 :
126 : // Return a grown copy if the index is bigger than the array's length.
127 : V8_EXPORT_PRIVATE static Handle<FixedArray> SetAndGrow(
128 : Isolate* isolate, Handle<FixedArray> array, int index,
129 : Handle<Object> value, AllocationType allocation = AllocationType::kYoung);
130 :
131 : // Setter that uses write barrier.
132 : inline void set(int index, Object value);
133 : inline bool is_the_hole(Isolate* isolate, int index);
134 :
135 : // Setter that doesn't need write barrier.
136 : inline void set(int index, Smi value);
137 : // Setter with explicit barrier mode.
138 : inline void set(int index, Object value, WriteBarrierMode mode);
139 :
140 : // Setters for frequently used oddballs located in old space.
141 : inline void set_undefined(int index);
142 : inline void set_undefined(Isolate* isolate, int index);
143 : inline void set_null(int index);
144 : inline void set_null(Isolate* isolate, int index);
145 : inline void set_the_hole(int index);
146 : inline void set_the_hole(Isolate* isolate, int index);
147 :
148 : inline ObjectSlot GetFirstElementAddress();
149 : inline bool ContainsOnlySmisOrHoles();
150 : // Returns true iff the elements are Numbers and sorted ascending.
151 : bool ContainsSortedNumbers();
152 :
153 : // Gives access to raw memory which stores the array's data.
154 : inline ObjectSlot data_start();
155 :
156 : inline void MoveElements(Heap* heap, int dst_index, int src_index, int len,
157 : WriteBarrierMode mode);
158 :
159 : inline void CopyElements(Heap* heap, int dst_index, FixedArray src,
160 : int src_index, int len, WriteBarrierMode mode);
161 :
162 : inline void FillWithHoles(int from, int to);
163 :
164 : // Shrink the array and insert filler objects. {new_length} must be > 0.
165 : V8_EXPORT_PRIVATE void Shrink(Isolate* isolate, int new_length);
166 : // If {new_length} is 0, return the canonical empty FixedArray. Otherwise
167 : // like above.
168 : static Handle<FixedArray> ShrinkOrEmpty(Isolate* isolate,
169 : Handle<FixedArray> array,
170 : int new_length);
171 :
172 : // Copy a sub array from the receiver to dest.
173 : V8_EXPORT_PRIVATE void CopyTo(int pos, FixedArray dest, int dest_pos,
174 : int len) const;
175 :
176 : // Garbage collection support.
177 : static constexpr int SizeFor(int length) {
178 131872067 : return kHeaderSize + length * kTaggedSize;
179 : }
180 :
181 : // Code Generation support.
182 : static constexpr int OffsetOfElementAt(int index) { return SizeFor(index); }
183 :
184 : // Garbage collection support.
185 : inline ObjectSlot RawFieldOfElementAt(int index);
186 :
187 : DECL_CAST(FixedArray)
188 : // Maximally allowed length of a FixedArray.
189 : static const int kMaxLength = (kMaxSize - kHeaderSize) / kTaggedSize;
190 : static_assert(Internals::IsValidSmi(kMaxLength),
191 : "FixedArray maxLength not a Smi");
192 :
193 : // Maximally allowed length for regular (non large object space) object.
194 : STATIC_ASSERT(kMaxRegularHeapObjectSize < kMaxSize);
195 : static const int kMaxRegularLength =
196 : (kMaxRegularHeapObjectSize - kHeaderSize) / kTaggedSize;
197 :
198 : // Dispatched behavior.
199 : DECL_PRINTER(FixedArray)
200 : DECL_VERIFIER(FixedArray)
201 :
202 : using BodyDescriptor = FlexibleBodyDescriptor<kHeaderSize>;
203 :
204 : protected:
205 : // Set operation on FixedArray without using write barriers. Can
206 : // only be used for storing old space objects or smis.
207 : static inline void NoWriteBarrierSet(FixedArray array, int index,
208 : Object value);
209 :
210 : private:
211 : STATIC_ASSERT(kHeaderSize == Internals::kFixedArrayHeaderSize);
212 :
213 : inline void set_undefined(ReadOnlyRoots ro_roots, int index);
214 : inline void set_null(ReadOnlyRoots ro_roots, int index);
215 : inline void set_the_hole(ReadOnlyRoots ro_roots, int index);
216 :
217 : OBJECT_CONSTRUCTORS(FixedArray, FixedArrayBase);
218 : };
219 :
220 : // FixedArray alias added only because of IsFixedArrayExact() predicate, which
221 : // checks for the exact instance type FIXED_ARRAY_TYPE instead of a range
222 : // check: [FIRST_FIXED_ARRAY_TYPE, LAST_FIXED_ARRAY_TYPE].
223 : class FixedArrayExact final : public FixedArray {};
224 :
225 : // FixedDoubleArray describes fixed-sized arrays with element type double.
226 : class FixedDoubleArray : public FixedArrayBase {
227 : public:
228 : // Setter and getter for elements.
229 : inline double get_scalar(int index);
230 : inline uint64_t get_representation(int index);
231 : static inline Handle<Object> get(FixedDoubleArray array, int index,
232 : Isolate* isolate);
233 : inline void set(int index, double value);
234 : inline void set_the_hole(Isolate* isolate, int index);
235 : inline void set_the_hole(int index);
236 :
237 : // Checking for the hole.
238 : inline bool is_the_hole(Isolate* isolate, int index);
239 : inline bool is_the_hole(int index);
240 :
241 : // Garbage collection support.
242 : inline static int SizeFor(int length) {
243 1248784 : return kHeaderSize + length * kDoubleSize;
244 : }
245 :
246 : inline void MoveElements(Heap* heap, int dst_index, int src_index, int len,
247 : WriteBarrierMode mode);
248 :
249 : inline void FillWithHoles(int from, int to);
250 :
251 : // Code Generation support.
252 : static int OffsetOfElementAt(int index) { return SizeFor(index); }
253 :
254 : DECL_CAST(FixedDoubleArray)
255 :
256 : // Maximally allowed length of a FixedArray.
257 : static const int kMaxLength = (kMaxSize - kHeaderSize) / kDoubleSize;
258 : static_assert(Internals::IsValidSmi(kMaxLength),
259 : "FixedDoubleArray maxLength not a Smi");
260 :
261 : // Dispatched behavior.
262 : DECL_PRINTER(FixedDoubleArray)
263 : DECL_VERIFIER(FixedDoubleArray)
264 :
265 : class BodyDescriptor;
266 :
267 : OBJECT_CONSTRUCTORS(FixedDoubleArray, FixedArrayBase);
268 : };
269 :
270 : // WeakFixedArray describes fixed-sized arrays with element type
271 : // MaybeObject.
272 : class WeakFixedArray : public HeapObject {
273 : public:
274 : DECL_CAST(WeakFixedArray)
275 :
276 : inline MaybeObject Get(int index) const;
277 :
278 : // Setter that uses write barrier.
279 : inline void Set(int index, MaybeObject value);
280 :
281 : // Setter with explicit barrier mode.
282 : inline void Set(int index, MaybeObject value, WriteBarrierMode mode);
283 :
284 : static constexpr int SizeFor(int length) {
285 13174082 : return kHeaderSize + length * kTaggedSize;
286 : }
287 :
288 : DECL_INT_ACCESSORS(length)
289 :
290 : // Get and set the length using acquire loads and release stores.
291 : inline int synchronized_length() const;
292 : inline void synchronized_set_length(int value);
293 :
294 : // Gives access to raw memory which stores the array's data.
295 : inline MaybeObjectSlot data_start();
296 :
297 : inline MaybeObjectSlot RawFieldOfElementAt(int index);
298 :
299 : DECL_PRINTER(WeakFixedArray)
300 : DECL_VERIFIER(WeakFixedArray)
301 :
302 : using BodyDescriptor = WeakArrayBodyDescriptor;
303 :
304 : DEFINE_FIELD_OFFSET_CONSTANTS(HeapObject::kHeaderSize,
305 : TORQUE_GENERATED_WEAK_FIXED_ARRAY_FIELDS)
306 : static constexpr int kHeaderSize = kSize;
307 :
308 : static const int kMaxLength =
309 : (FixedArray::kMaxSize - kHeaderSize) / kTaggedSize;
310 : static_assert(Internals::IsValidSmi(kMaxLength),
311 : "WeakFixedArray maxLength not a Smi");
312 :
313 : protected:
314 : static int OffsetOfElementAt(int index) {
315 238059825 : return kHeaderSize + index * kTaggedSize;
316 : }
317 :
318 : private:
319 : friend class Heap;
320 :
321 : static const int kFirstIndex = 1;
322 :
323 : OBJECT_CONSTRUCTORS(WeakFixedArray, HeapObject);
324 : };
325 :
326 : // WeakArrayList is like a WeakFixedArray with static convenience methods for
327 : // adding more elements. length() returns the number of elements in the list and
328 : // capacity() returns the allocated size. The number of elements is stored at
329 : // kLengthOffset and is updated with every insertion. The array grows
330 : // dynamically with O(1) amortized insertion.
331 : class WeakArrayList : public HeapObject {
332 : public:
333 : NEVER_READ_ONLY_SPACE
334 : DECL_CAST(WeakArrayList)
335 : DECL_VERIFIER(WeakArrayList)
336 : DECL_PRINTER(WeakArrayList)
337 :
338 : V8_EXPORT_PRIVATE static Handle<WeakArrayList> AddToEnd(
339 : Isolate* isolate, Handle<WeakArrayList> array,
340 : const MaybeObjectHandle& value);
341 :
342 : inline MaybeObject Get(int index) const;
343 :
344 : // Set the element at index to obj. The underlying array must be large enough.
345 : // If you need to grow the WeakArrayList, use the static AddToEnd() method
346 : // instead.
347 : inline void Set(int index, MaybeObject value,
348 : WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
349 :
350 : static constexpr int SizeForCapacity(int capacity) {
351 5320011 : return kHeaderSize + capacity * kTaggedSize;
352 : }
353 :
354 : // Gives access to raw memory which stores the array's data.
355 : inline MaybeObjectSlot data_start();
356 :
357 : V8_EXPORT_PRIVATE bool IsFull();
358 :
359 : DECL_INT_ACCESSORS(capacity)
360 : DECL_INT_ACCESSORS(length)
361 :
362 : // Get and set the capacity using acquire loads and release stores.
363 : inline int synchronized_capacity() const;
364 : inline void synchronized_set_capacity(int value);
365 :
366 :
367 : // Layout description.
368 : #define WEAK_ARRAY_LIST_FIELDS(V) \
369 : V(kCapacityOffset, kTaggedSize) \
370 : V(kLengthOffset, kTaggedSize) \
371 : /* Header size. */ \
372 : V(kHeaderSize, 0)
373 :
374 : DEFINE_FIELD_OFFSET_CONSTANTS(HeapObject::kHeaderSize, WEAK_ARRAY_LIST_FIELDS)
375 : #undef WEAK_ARRAY_LIST_FIELDS
376 :
377 : using BodyDescriptor = WeakArrayBodyDescriptor;
378 :
379 : static const int kMaxCapacity =
380 : (FixedArray::kMaxSize - kHeaderSize) / kTaggedSize;
381 :
382 : static Handle<WeakArrayList> EnsureSpace(
383 : Isolate* isolate, Handle<WeakArrayList> array, int length,
384 : AllocationType allocation = AllocationType::kYoung);
385 :
386 : // Returns the number of non-cleaned weak references in the array.
387 : int CountLiveWeakReferences() const;
388 :
389 : // Returns whether an entry was found and removed. Will move the elements
390 : // around in the array - this method can only be used in cases where the user
391 : // doesn't care about the indices! Users should make sure there are no
392 : // duplicates.
393 : V8_EXPORT_PRIVATE bool RemoveOne(const MaybeObjectHandle& value);
394 :
395 : class Iterator;
396 :
397 : private:
398 : static int OffsetOfElementAt(int index) {
399 67119663 : return kHeaderSize + index * kTaggedSize;
400 : }
401 :
402 : OBJECT_CONSTRUCTORS(WeakArrayList, HeapObject);
403 : };
404 :
405 : class WeakArrayList::Iterator {
406 : public:
407 135734 : explicit Iterator(WeakArrayList array) : index_(0), array_(array) {}
408 :
409 : inline HeapObject Next();
410 :
411 : private:
412 : int index_;
413 : WeakArrayList array_;
414 : #ifdef DEBUG
415 : DisallowHeapAllocation no_gc_;
416 : #endif // DEBUG
417 : DISALLOW_COPY_AND_ASSIGN(Iterator);
418 : };
419 :
420 : // Generic array grows dynamically with O(1) amortized insertion.
421 : //
422 : // ArrayList is a FixedArray with static convenience methods for adding more
423 : // elements. The Length() method returns the number of elements in the list, not
424 : // the allocated size. The number of elements is stored at kLengthIndex and is
425 : // updated with every insertion. The elements of the ArrayList are stored in the
426 : // underlying FixedArray starting at kFirstIndex.
427 : class ArrayList : public FixedArray {
428 : public:
429 : V8_EXPORT_PRIVATE static Handle<ArrayList> Add(Isolate* isolate,
430 : Handle<ArrayList> array,
431 : Handle<Object> obj);
432 : V8_EXPORT_PRIVATE static Handle<ArrayList> Add(Isolate* isolate,
433 : Handle<ArrayList> array,
434 : Handle<Object> obj1,
435 : Handle<Object> obj2);
436 : static Handle<ArrayList> New(Isolate* isolate, int size);
437 :
438 : // Returns the number of elements in the list, not the allocated size, which
439 : // is length(). Lower and upper case length() return different results!
440 : inline int Length() const;
441 :
442 : // Sets the Length() as used by Elements(). Does not change the underlying
443 : // storage capacity, i.e., length().
444 : inline void SetLength(int length);
445 : inline Object Get(int index) const;
446 : inline ObjectSlot Slot(int index);
447 :
448 : // Set the element at index to obj. The underlying array must be large enough.
449 : // If you need to grow the ArrayList, use the static Add() methods instead.
450 : inline void Set(int index, Object obj,
451 : WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
452 :
453 : // Set the element at index to undefined. This does not change the Length().
454 : inline void Clear(int index, Object undefined);
455 :
456 : // Return a copy of the list of size Length() without the first entry. The
457 : // number returned by Length() is stored in the first entry.
458 : static Handle<FixedArray> Elements(Isolate* isolate, Handle<ArrayList> array);
459 : DECL_CAST(ArrayList)
460 :
461 : private:
462 : static Handle<ArrayList> EnsureSpace(Isolate* isolate,
463 : Handle<ArrayList> array, int length);
464 : static const int kLengthIndex = 0;
465 : static const int kFirstIndex = 1;
466 : OBJECT_CONSTRUCTORS(ArrayList, FixedArray);
467 : };
468 :
469 : enum SearchMode { ALL_ENTRIES, VALID_ENTRIES };
470 :
471 : template <SearchMode search_mode, typename T>
472 : inline int Search(T* array, Name name, int valid_entries = 0,
473 : int* out_insertion_index = nullptr);
474 :
475 : // ByteArray represents fixed sized byte arrays. Used for the relocation info
476 : // that is attached to code objects.
477 : class ByteArray : public FixedArrayBase {
478 : public:
479 : inline int Size();
480 :
481 : // Setter and getter.
482 : inline byte get(int index) const;
483 : inline void set(int index, byte value);
484 :
485 : // Copy in / copy out whole byte slices.
486 : inline void copy_out(int index, byte* buffer, int length);
487 : inline void copy_in(int index, const byte* buffer, int length);
488 :
489 : // Treat contents as an int array.
490 : inline int get_int(int index) const;
491 : inline void set_int(int index, int value);
492 :
493 : inline uint32_t get_uint32(int index) const;
494 : inline void set_uint32(int index, uint32_t value);
495 :
496 : // Clear uninitialized padding space. This ensures that the snapshot content
497 : // is deterministic.
498 : inline void clear_padding();
499 :
500 : static int SizeFor(int length) {
501 30530859 : return OBJECT_POINTER_ALIGN(kHeaderSize + length);
502 : }
503 : // We use byte arrays for free blocks in the heap. Given a desired size in
504 : // bytes that is a multiple of the word size and big enough to hold a byte
505 : // array, this function returns the number of elements a byte array should
506 : // have.
507 : static int LengthFor(int size_in_bytes) {
508 : DCHECK(IsAligned(size_in_bytes, kTaggedSize));
509 : DCHECK_GE(size_in_bytes, kHeaderSize);
510 56334 : return size_in_bytes - kHeaderSize;
511 : }
512 :
513 : // Returns data start address.
514 : inline byte* GetDataStartAddress();
515 : // Returns address of the past-the-end element.
516 : inline byte* GetDataEndAddress();
517 :
518 : inline int DataSize() const;
519 :
520 : // Returns a pointer to the ByteArray object for a given data start address.
521 : static inline ByteArray FromDataStartAddress(Address address);
522 :
523 : DECL_CAST(ByteArray)
524 :
525 : // Dispatched behavior.
526 : inline int ByteArraySize();
527 : DECL_PRINTER(ByteArray)
528 : DECL_VERIFIER(ByteArray)
529 :
530 : // Layout description.
531 : static const int kAlignedSize = OBJECT_POINTER_ALIGN(kHeaderSize);
532 :
533 : // Maximal length of a single ByteArray.
534 : static const int kMaxLength = kMaxSize - kHeaderSize;
535 : static_assert(Internals::IsValidSmi(kMaxLength),
536 : "ByteArray maxLength not a Smi");
537 :
538 : class BodyDescriptor;
539 :
540 : protected:
541 : // Special-purpose constructor for subclasses that have fast paths where
542 : // their ptr() is a Smi.
543 : inline ByteArray(Address ptr, AllowInlineSmiStorage allow_smi);
544 :
545 : OBJECT_CONSTRUCTORS(ByteArray, FixedArrayBase);
546 : };
547 :
548 : // Wrapper class for ByteArray which can store arbitrary C++ classes, as long
549 : // as they can be copied with memcpy.
550 : template <class T>
551 : class PodArray : public ByteArray {
552 : public:
553 : static Handle<PodArray<T>> New(
554 : Isolate* isolate, int length,
555 : AllocationType allocation = AllocationType::kYoung);
556 : void copy_out(int index, T* result) {
557 104 : ByteArray::copy_out(index * sizeof(T), reinterpret_cast<byte*>(result),
558 : sizeof(T));
559 : }
560 :
561 : void copy_in(int index, const T* buffer, int length) {
562 65584 : ByteArray::copy_in(index * sizeof(T), reinterpret_cast<const byte*>(buffer),
563 : length * sizeof(T));
564 : }
565 :
566 : T get(int index) {
567 : T result;
568 : copy_out(index, &result);
569 60874 : return result;
570 : }
571 :
572 : void set(int index, const T& value) { copy_in(index, &value, 1); }
573 :
574 : inline int length() const;
575 : DECL_CAST(PodArray<T>)
576 :
577 : OBJECT_CONSTRUCTORS(PodArray<T>, ByteArray);
578 : };
579 :
580 : class FixedTypedArrayBase : public FixedArrayBase {
581 : public:
582 : // [base_pointer]: Either points to the FixedTypedArrayBase itself or nullptr.
583 : DECL_ACCESSORS(base_pointer, Object)
584 :
585 : // [external_pointer]: Contains the offset between base_pointer and the start
586 : // of the data. If the base_pointer is a nullptr, the external_pointer
587 : // therefore points to the actual backing store.
588 : DECL_PRIMITIVE_ACCESSORS(external_pointer, void*)
589 :
590 : // Dispatched behavior.
591 : DECL_CAST(FixedTypedArrayBase)
592 :
593 : DEFINE_FIELD_OFFSET_CONSTANTS(FixedArrayBase::kHeaderSize,
594 : TORQUE_GENERATED_FIXED_TYPED_ARRAY_BASE_FIELDS)
595 : static const int kHeaderSize = kSize;
596 :
597 : #ifdef V8_COMPRESS_POINTERS
598 : // TODO(ishell, v8:8875): When pointer compression is enabled the kHeaderSize
599 : // is only kTaggedSize aligned but we can keep using unaligned access since
600 : // both x64 and arm64 architectures (where pointer compression supported)
601 : // allow unaligned access to doubles.
602 : STATIC_ASSERT(IsAligned(kHeaderSize, kTaggedSize));
603 : #else
604 : STATIC_ASSERT(IsAligned(kHeaderSize, kDoubleAlignment));
605 : #endif
606 :
607 : static const int kDataOffset = kHeaderSize;
608 :
609 : static const int kMaxElementSize = 8;
610 :
611 : #ifdef V8_HOST_ARCH_32_BIT
612 : static const size_t kMaxByteLength = std::numeric_limits<size_t>::max();
613 : #else
614 : static const size_t kMaxByteLength =
615 : static_cast<size_t>(Smi::kMaxValue) * kMaxElementSize;
616 : #endif // V8_HOST_ARCH_32_BIT
617 :
618 : static const size_t kMaxLength = Smi::kMaxValue;
619 :
620 : class BodyDescriptor;
621 :
622 : inline int size() const;
623 :
624 : static inline int TypedArraySize(InstanceType type, int length);
625 : inline int TypedArraySize(InstanceType type) const;
626 :
627 : // Use with care: returns raw pointer into heap.
628 : inline void* DataPtr();
629 :
630 : inline int DataSize() const;
631 :
632 : inline size_t ByteLength() const;
633 :
634 : static inline intptr_t ExternalPointerValueForOnHeapArray() {
635 : return FixedTypedArrayBase::kDataOffset - kHeapObjectTag;
636 : }
637 :
638 : static inline void* ExternalPointerPtrForOnHeapArray() {
639 : return reinterpret_cast<void*>(ExternalPointerValueForOnHeapArray());
640 : }
641 :
642 : private:
643 : static inline int ElementSize(InstanceType type);
644 :
645 : inline int DataSize(InstanceType type) const;
646 :
647 : OBJECT_CONSTRUCTORS(FixedTypedArrayBase, FixedArrayBase);
648 : };
649 :
650 : template <class Traits>
651 : class FixedTypedArray : public FixedTypedArrayBase {
652 : public:
653 : using ElementType = typename Traits::ElementType;
654 : static const InstanceType kInstanceType = Traits::kInstanceType;
655 :
656 : DECL_CAST(FixedTypedArray<Traits>)
657 :
658 : static inline ElementType get_scalar_from_data_ptr(void* data_ptr, int index);
659 : inline ElementType get_scalar(int index);
660 : static inline Handle<Object> get(Isolate* isolate, FixedTypedArray array,
661 : int index);
662 : inline void set(int index, ElementType value);
663 :
664 : static inline ElementType from(int value);
665 : static inline ElementType from(uint32_t value);
666 : static inline ElementType from(double value);
667 : static inline ElementType from(int64_t value);
668 : static inline ElementType from(uint64_t value);
669 :
670 : static inline ElementType FromHandle(Handle<Object> value,
671 : bool* lossless = nullptr);
672 :
673 : // This accessor applies the correct conversion from Smi, HeapNumber
674 : // and undefined.
675 : inline void SetValue(uint32_t index, Object value);
676 :
677 : DECL_PRINTER(FixedTypedArray)
678 : DECL_VERIFIER(FixedTypedArray)
679 :
680 : private:
681 : OBJECT_CONSTRUCTORS(FixedTypedArray, FixedTypedArrayBase);
682 : };
683 :
684 : #define FIXED_TYPED_ARRAY_TRAITS(Type, type, TYPE, elementType) \
685 : STATIC_ASSERT(sizeof(elementType) <= FixedTypedArrayBase::kMaxElementSize); \
686 : class Type##ArrayTraits { \
687 : public: /* NOLINT */ \
688 : using ElementType = elementType; \
689 : static const InstanceType kInstanceType = FIXED_##TYPE##_ARRAY_TYPE; \
690 : static const char* ArrayTypeName() { return "Fixed" #Type "Array"; } \
691 : static inline Handle<Object> ToHandle(Isolate* isolate, \
692 : elementType scalar); \
693 : static inline elementType defaultValue(); \
694 : }; \
695 : \
696 : using Fixed##Type##Array = FixedTypedArray<Type##ArrayTraits>;
697 :
698 : TYPED_ARRAYS(FIXED_TYPED_ARRAY_TRAITS)
699 :
700 : #undef FIXED_TYPED_ARRAY_TRAITS
701 :
702 : class TemplateList : public FixedArray {
703 : public:
704 : static Handle<TemplateList> New(Isolate* isolate, int size);
705 : inline int length() const;
706 : inline Object get(int index) const;
707 : inline void set(int index, Object value);
708 : static Handle<TemplateList> Add(Isolate* isolate, Handle<TemplateList> list,
709 : Handle<Object> value);
710 : DECL_CAST(TemplateList)
711 : private:
712 : static const int kLengthIndex = 0;
713 : static const int kFirstElementIndex = kLengthIndex + 1;
714 :
715 : OBJECT_CONSTRUCTORS(TemplateList, FixedArray);
716 : };
717 :
718 : } // namespace internal
719 : } // namespace v8
720 :
721 : #include "src/objects/object-macros-undef.h"
722 :
723 : #endif // V8_OBJECTS_FIXED_ARRAY_H_
|