v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
fixed-array.h
Go to the documentation of this file.
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 <optional>
9
10#include "src/common/globals.h"
15#include "src/objects/objects.h"
16#include "src/objects/smi.h"
17#include "src/objects/tagged.h"
19#include "src/roots/roots.h"
20#include "src/utils/memcopy.h"
21
22// Has to be the last include (doesn't have include guards):
24
25namespace v8::internal {
26
27#include "torque-generated/src/objects/fixed-array-tq.inc"
28
29// Limit all fixed arrays to the same max capacity, so that non-resizing
30// transitions between different elements kinds (like Smi to Double) will not
31// error.
32static constexpr int kMaxFixedArrayCapacity =
33 V8_LOWER_LIMITS_MODE_BOOL ? (16 * 1024 * 1024) : (64 * 1024 * 1024);
34
35namespace detail {
36template <class Super, bool kLengthEqualsCapacity>
38
39V8_OBJECT template <class Super>
40class ArrayHeaderBase<Super, false> : public Super {
41 public:
42 inline int capacity() const;
43 inline int capacity(AcquireLoadTag tag) const;
44 inline void set_capacity(int value);
45 inline void set_capacity(int value, ReleaseStoreTag tag);
46
47 // TODO(leszeks): Make this private.
48 public:
51
52V8_OBJECT template <class Super>
53class ArrayHeaderBase<Super, true> : public Super {
54 public:
55 inline int length() const;
56 inline int length(AcquireLoadTag tag) const;
57 inline void set_length(int value);
58 inline void set_length(int value, ReleaseStoreTag tag);
59
60 inline int capacity() const;
61 inline int capacity(AcquireLoadTag tag) const;
62 inline void set_capacity(int value);
63 inline void set_capacity(int value, ReleaseStoreTag tag);
64
65 // TODO(leszeks): Make this private.
66 public:
69
70template <class Shape, class Super, typename = void>
74template <class Shape, class Super>
76 Shape, Super, std::void_t<typename Shape::template ExtraFields<Super>>> {
78 using type = typename Shape::template ExtraFields<BaseHeader>;
79 static_assert(std::is_base_of<BaseHeader, type>::value);
80};
81template <class Shape, class Super>
83} // namespace detail
84
85#define V8_ARRAY_EXTRA_FIELDS(...) \
86 V8_OBJECT template <typename Super> \
87 struct ExtraFields : public Super __VA_ARGS__ V8_OBJECT_END
88
89// Derived: must not have any fields - extra fields can be specified in the
90// Shap using V8_ARRAY_EXTRA_FIELDS.
91V8_OBJECT template <class Derived, class ShapeT, class Super = HeapObjectLayout>
92class TaggedArrayBase : public detail::TaggedArrayHeader<ShapeT, Super> {
93 static_assert(std::is_base_of<HeapObjectLayout, Super>::value);
94 using ElementT = typename ShapeT::ElementT;
95
96 static_assert(sizeof(TaggedMember<ElementT>) == kTaggedSize);
98
101
102 template <typename ElementT>
103 static constexpr bool kSupportsSmiElements =
104 std::is_convertible_v<Smi, ElementT>;
105
107 std::is_same_v<ElementT, Smi> ? SKIP_WRITE_BARRIER : UPDATE_WRITE_BARRIER;
108
109 public:
112 static constexpr int kElementSize = kTaggedSize;
113
114 private:
115 using SlotType =
116 std::conditional_t<kElementsAreMaybeObject, MaybeObjectSlot, ObjectSlot>;
117
118 public:
119 using Shape = ShapeT;
120
121 inline Tagged<ElementT> get(int index) const;
122 inline Tagged<ElementT> get(int index, RelaxedLoadTag) const;
123 inline Tagged<ElementT> get(int index, AcquireLoadTag) const;
124 inline Tagged<ElementT> get(int index, SeqCstAccessTag) const;
125
126 inline void set(int index, Tagged<ElementT> value,
128 template <typename T = ElementT,
129 typename = std::enable_if<kSupportsSmiElements<T>>>
130 inline void set(int index, Tagged<Smi> value);
131 inline void set(int index, Tagged<ElementT> value, RelaxedStoreTag,
133 template <typename T = ElementT,
134 typename = std::enable_if<kSupportsSmiElements<T>>>
135 inline void set(int index, Tagged<Smi> value, RelaxedStoreTag);
136 inline void set(int index, Tagged<ElementT> value, ReleaseStoreTag,
138 template <typename T = ElementT,
139 typename = std::enable_if<kSupportsSmiElements<T>>>
140 inline void set(int index, Tagged<Smi> value, ReleaseStoreTag);
141 inline void set(int index, Tagged<ElementT> value, SeqCstAccessTag,
143 template <typename T = ElementT,
144 typename = std::enable_if<kSupportsSmiElements<T>>>
145 inline void set(int index, Tagged<Smi> value, SeqCstAccessTag);
146
147 inline Tagged<ElementT> swap(int index, Tagged<ElementT> value,
151 int index, Tagged<ElementT> expected, Tagged<ElementT> value,
153
154 // Move vs. Copy behaves like memmove vs. memcpy: for Move, the memory
155 // regions may overlap, for Copy they must not overlap.
156 inline static void MoveElements(Isolate* isolate, Tagged<Derived> dst,
157 int dst_index, Tagged<Derived> src,
158 int src_index, int len,
160 inline static void CopyElements(Isolate* isolate, Tagged<Derived> dst,
161 int dst_index, Tagged<Derived> src,
162 int src_index, int len,
164
165 // Right-trim the array.
166 // Invariant: 0 < new_length <= length()
167 inline void RightTrim(Isolate* isolate, int new_capacity);
168
169 inline int AllocatedSize() const;
170 static inline constexpr int SizeFor(int capacity) {
171 return sizeof(Header) + capacity * kElementSize;
172 }
173 static inline constexpr int OffsetOfElementAt(int index) {
174 return SizeFor(index);
175 }
176
177 // Gives access to raw memory which stores the array's data.
178 inline SlotType RawFieldOfFirstElement() const;
179 inline SlotType RawFieldOfElementAt(int index) const;
180
181 // Maximal allowed capacity, in number of elements. Chosen s.t. the byte size
182 // fits into a Smi which is necessary for being able to create a free space
183 // filler.
184 // TODO(jgruber): The kMaxCapacity could be larger (`(Smi::kMaxValue -
185 // Shape::kHeaderSize) / kElementSize`), but our tests rely on a
186 // smaller maximum to avoid timeouts.
187 static constexpr int kMaxCapacity = kMaxFixedArrayCapacity;
188 static_assert(Smi::IsValid(SizeFor(kMaxCapacity)));
189
190 // Maximally allowed length for regular (non large object space) object.
191 static constexpr int kMaxRegularCapacity =
193 static_assert(kMaxRegularCapacity < kMaxCapacity);
194
195 protected:
196 template <class IsolateT>
198 IsolateT* isolate, int capacity,
199 std::optional<DisallowGarbageCollection>* no_gc_out,
201
202 static constexpr int NewCapacityForIndex(int index, int old_capacity);
203
204 inline bool IsInBounds(int index) const;
205 inline bool IsCowArray() const;
206
209
210class TaggedArrayShape final : public AllStatic {
211 public:
214 static constexpr RootIndex kMapRootIndex = RootIndex::kFixedArrayMap;
215 static constexpr bool kLengthEqualsCapacity = true;
216};
217
218// FixedArray describes fixed-sized arrays with element type Object.
220 : public TaggedArrayBase<FixedArray, TaggedArrayShape> {
222
223 public:
224 template <class IsolateT>
225 static inline Handle<FixedArray> New(
226 IsolateT* isolate, int capacity,
228
231
232 // TODO(jgruber): Only needed for FixedArrays used as JSObject elements.
233 inline void MoveElements(Isolate* isolate, int dst_index, int src_index,
234 int len, WriteBarrierMode mode);
235 inline void CopyElements(Isolate* isolate, int dst_index,
236 Tagged<FixedArray> src, int src_index, int len,
237 WriteBarrierMode mode);
238
239 // Return a grown copy if the index is bigger than the array's length.
240 template <template <typename> typename HandleType>
241 requires(
242 std::is_convertible_v<HandleType<FixedArray>, DirectHandle<FixedArray>>)
243 V8_EXPORT_PRIVATE static HandleType<FixedArray> SetAndGrow(
244 Isolate* isolate, HandleType<FixedArray> array, int index,
246
247 // Right-trim the array.
248 // Invariant: 0 < new_length <= length()
249 V8_EXPORT_PRIVATE void RightTrim(Isolate* isolate, int new_capacity);
250 // Right-trims the array, and canonicalizes length 0 to empty_fixed_array.
251 template <template <typename> typename HandleType>
252 requires(
253 std::is_convertible_v<HandleType<FixedArray>, DirectHandle<FixedArray>>)
254 static HandleType<FixedArray> RightTrimOrEmpty(Isolate* isolate,
255 HandleType<FixedArray> array,
256 int new_length);
257
258 // TODO(jgruber): Only needed for FixedArrays used as JSObject elements.
259 inline void FillWithHoles(int from, int to);
260
261 // For compatibility with FixedDoubleArray:
262 // TODO(jgruber): Only needed for FixedArrays used as JSObject elements.
263 inline bool is_the_hole(Isolate* isolate, int index);
264 inline void set_the_hole(Isolate* isolate, int index);
265 inline void set_the_hole(ReadOnlyRoots ro_roots, int index);
266
269
270 class BodyDescriptor;
271
272 static constexpr int kMaxLength = FixedArray::kMaxCapacity;
274
275 private:
276 inline static Handle<FixedArray> Resize(
277 Isolate* isolate, DirectHandle<FixedArray> xs, int new_capacity,
281
282static_assert(sizeof(FixedArray) == Internals::kFixedArrayHeaderSize);
283
284class TrustedArrayShape final : public AllStatic {
285 public:
287 // The elements in a TrustedFixedArray are pointers into the main cage!
289 static constexpr RootIndex kMapRootIndex = RootIndex::kTrustedFixedArrayMap;
290 static constexpr bool kLengthEqualsCapacity = true;
291};
292
293// A FixedArray in trusted space and with a unique instance type.
294//
295// Note: while the array itself is trusted, it contains tagged pointers into
296// the main pointer compression heap and therefore to _untrusted_ objects.
297// If you are storing references to other trusted object (i.e. protected
298// pointers), use ProtectedFixedArray.
300 : public TaggedArrayBase<TrustedFixedArray, TrustedArrayShape,
301 TrustedObjectLayout> {
304
305 public:
306 template <class IsolateT>
307 static inline Handle<TrustedFixedArray> New(
308 IsolateT* isolate, int capacity,
310
313
314 class BodyDescriptor;
315
317 static constexpr int kMaxRegularLength =
320
321class ProtectedArrayShape final : public AllStatic {
322 public:
325 static constexpr RootIndex kMapRootIndex = RootIndex::kProtectedFixedArrayMap;
326 static constexpr bool kLengthEqualsCapacity = true;
327};
328
329// A FixedArray in trusted space, holding protected pointers (to other trusted
330// objects). If you want to store JS-heap references, use TrustedFixedArray.
331// ProtectedFixedArray has a unique instance type.
333 : public TaggedArrayBase<ProtectedFixedArray, ProtectedArrayShape,
334 TrustedObjectLayout> {
337
338 public:
339 // Allocate a new ProtectedFixedArray of the given capacity, initialized with
340 // Smi::zero().
341 template <class IsolateT>
342 static inline Handle<ProtectedFixedArray> New(IsolateT* isolate,
343 int capacity);
344
347
348 class BodyDescriptor;
349
350 static constexpr int kMaxLength = Super::kMaxCapacity;
351 static constexpr int kMaxRegularLength =
354
355// FixedArray alias added only because of IsFixedArrayExact() predicate, which
356// checks for the exact instance type FIXED_ARRAY_TYPE instead of a range
357// check: [FIRST_FIXED_ARRAY_TYPE, LAST_FIXED_ARRAY_TYPE].
359class FixedArrayExact final : public FixedArray {
361
362// Common superclass for FixedArrays that allow implementations to share common
363// accessors and some code paths. Note that due to single-inheritance
364// restrictions, it is not part of the actual type hierarchy. Instead, we slot
365// it in with manual is_subtype specializations in tagged.h.
366// TODO(jgruber): This class is really specific to FixedArrays used as
367// elements backing stores and should not be part of the common FixedArray
368// hierarchy.
370class FixedArrayBase : public detail::ArrayHeaderBase<HeapObjectLayout, true> {
371 public:
373 static constexpr int kHeaderSize = kLengthOffset + kTaggedSize;
374 static constexpr int kMaxLength = FixedArray::kMaxCapacity;
376
378
379 V8_EXPORT_PRIVATE bool IsCowArray() const;
380
383
385template <class Derived, class ShapeT, class Super = HeapObjectLayout>
386class PrimitiveArrayBase : public detail::ArrayHeaderBase<Super, true> {
387 static_assert(std::is_base_of<HeapObjectLayout, Super>::value);
388
389 using ElementT = typename ShapeT::ElementT;
390 static_assert(!is_subtype_v<ElementT, Object>);
391
392 // Bug(v8:8875): Doubles may be unaligned.
393 using ElementMemberT = std::conditional_t<std::is_same_v<ElementT, double>,
395 static_assert(alignof(ElementMemberT) <= alignof(Tagged_t));
396
397 public:
398 using Shape = ShapeT;
399 static constexpr bool kElementsAreMaybeObject = false;
400 static constexpr int kElementSize = sizeof(ElementMemberT);
402
403 inline ElementMemberT get(int index) const;
404 inline void set(int index, ElementMemberT value);
405
406 inline int AllocatedSize() const;
407 static inline constexpr int SizeFor(int length) {
409 }
410 static inline constexpr int OffsetOfElementAt(int index) {
411 return sizeof(Header) + index * kElementSize;
412 }
413
414 // Gives access to raw memory which stores the array's data.
415 // Note that on 32-bit archs and on 64-bit platforms with pointer compression
416 // the pointers to 8-byte size elements are not guaranteed to be aligned.
417 inline ElementMemberT* begin();
418 inline const ElementMemberT* begin() const;
419 inline ElementMemberT* end();
420 inline const ElementMemberT* end() const;
421 inline int DataSize() const;
422
424
425 // Maximal allowed length, in number of elements. Chosen s.t. the byte size
426 // fits into a Smi which is necessary for being able to create a free space
427 // filler.
428 // TODO(jgruber): The kMaxLength could be larger (`(Smi::kMaxValue -
429 // sizeof(Header)) / kElementSize`), but our tests rely on a
430 // smaller maximum to avoid timeouts.
431 static constexpr int kMaxLength = kMaxFixedArrayCapacity;
432 static_assert(Smi::IsValid(SizeFor(kMaxLength)));
433
434 // Maximally allowed length for regular (non large object space) object.
435 static constexpr int kMaxRegularLength =
437 static_assert(kMaxRegularLength < kMaxLength);
438
439 protected:
440 template <class IsolateT>
442 IsolateT* isolate, int length,
443 std::optional<DisallowGarbageCollection>* no_gc_out,
445
446 inline bool IsInBounds(int index) const;
447
450
451class FixedDoubleArrayShape final : public AllStatic {
452 public:
453 using ElementT = double;
454 static constexpr RootIndex kMapRootIndex = RootIndex::kFixedDoubleArrayMap;
455};
456
457// FixedDoubleArray describes fixed-sized arrays with element type double.
459 : public PrimitiveArrayBase<FixedDoubleArray, FixedDoubleArrayShape> {
461
462 public:
463 // Note this returns FixedArrayBase due to canonicalization to
464 // empty_fixed_array.
465 template <class IsolateT>
466 static inline Handle<FixedArrayBase> New(
467 IsolateT* isolate, int capacity,
469
470 // Setter and getter for elements.
471 inline double get_scalar(int index);
472 inline uint64_t get_representation(int index);
473 static inline Handle<Object> get(Tagged<FixedDoubleArray> array, int index,
474 Isolate* isolate);
475 inline void set(int index, double value);
476#ifdef V8_ENABLE_EXPERIMENTAL_UNDEFINED_DOUBLE
477 inline void set_undefined(int index);
478 inline bool is_undefined(int index);
479#endif // V8_ENABLE_EXPERIMENTAL_UNDEFINED_DOUBLE
480
481 inline void set_the_hole(Isolate* isolate, int index);
482 inline void set_the_hole(int index);
483 inline bool is_the_hole(Isolate* isolate, int index);
484 inline bool is_the_hole(int index);
485
486 inline void MoveElements(Isolate* isolate, int dst_index, int src_index,
487 int len, WriteBarrierMode /* unused */);
488
489 inline void FillWithHoles(int from, int to);
490
493
494 class BodyDescriptor;
496
498
499class WeakFixedArrayShape final : public AllStatic {
500 public:
503 static constexpr RootIndex kMapRootIndex = RootIndex::kWeakFixedArrayMap;
504 static constexpr bool kLengthEqualsCapacity = true;
505};
506
507// WeakFixedArray describes fixed-sized arrays with element type
508// Tagged<MaybeObject>.
510 : public TaggedArrayBase<WeakFixedArray, WeakFixedArrayShape> {
512
513 public:
514 template <class IsolateT>
515 static inline Handle<WeakFixedArray> New(
516 IsolateT* isolate, int capacity,
518 MaybeDirectHandle<Object> initial_value = {});
519
522
523 class BodyDescriptor;
525
527 public:
530 static constexpr RootIndex kMapRootIndex =
531 RootIndex::kTrustedWeakFixedArrayMap;
532 static constexpr bool kLengthEqualsCapacity = true;
533};
534
535// A WeakFixedArray in trusted space holding pointers into the main cage.
537 : public TaggedArrayBase<TrustedWeakFixedArray, TrustedWeakFixedArrayShape,
538 TrustedObjectLayout> {
539 using Super =
541
542 public:
543 template <class IsolateT>
544 static inline Handle<TrustedWeakFixedArray> New(IsolateT* isolate,
545 int capacity);
546
549
550 class BodyDescriptor;
552
554 public:
557 static constexpr RootIndex kMapRootIndex =
558 RootIndex::kProtectedWeakFixedArrayMap;
559 static constexpr bool kLengthEqualsCapacity = true;
560};
561
562// A WeakFixedArray in trusted space, containing weak pointers to other
563// trusted objects (or smis).
565 : public TaggedArrayBase<ProtectedWeakFixedArray,
566 ProtectedWeakFixedArrayShape,
567 TrustedObjectLayout> {
568 using Super =
571
572 public:
573 template <class IsolateT>
574 static inline Handle<ProtectedWeakFixedArray> New(IsolateT* isolate,
575 int capacity);
578
579 class BodyDescriptor;
581
582// WeakArrayList is like a WeakFixedArray with static convenience methods for
583// adding more elements. length() returns the number of elements in the list and
584// capacity() returns the allocated size. The number of elements is stored at
585// kLengthOffset and is updated with every insertion. The array grows
586// dynamically with O(1) amortized insertion.
588 : public TorqueGeneratedWeakArrayList<WeakArrayList, HeapObject> {
589 public:
592
594 Isolate* isolate, Handle<WeakArrayList> array,
596
597 // A version that adds two elements. This ensures that the elements are
598 // inserted atomically w.r.t GC.
600 Isolate* isolate, Handle<WeakArrayList> array,
601 MaybeObjectDirectHandle value1, Tagged<Smi> value2);
602
603 // Appends an element to the array and possibly compacts and shrinks live weak
604 // references to the start of the collection. Only use this method when
605 // indices to elements can change.
607 Isolate* isolate, DirectHandle<WeakArrayList> array,
610
611 // Compact weak references to the beginning of the array.
612 V8_EXPORT_PRIVATE void Compact(Isolate* isolate);
613
614 inline Tagged<MaybeObject> Get(int index) const;
615 inline Tagged<MaybeObject> Get(PtrComprCageBase cage_base, int index) const;
616 // TODO(jgruber): Remove this once it's no longer needed for compatibility
617 // with WeakFixedArray.
618 inline Tagged<MaybeObject> get(int index) const;
619
620 // Set the element at index to obj. The underlying array must be large enough.
621 // If you need to grow the WeakArrayList, use the static AddToEnd() method
622 // instead.
623 inline void Set(int index, Tagged<MaybeObject> value,
625 inline void Set(int index, Tagged<Smi> value);
626
627 static constexpr int SizeForCapacity(int capacity) {
628 return SizeFor(capacity);
629 }
630
631 static constexpr int CapacityForLength(int length) {
632 return length + std::max(length / 2, 2);
633 }
634
635 // Gives access to raw memory which stores the array's data.
637
638 inline void CopyElements(Isolate* isolate, int dst_index,
639 Tagged<WeakArrayList> src, int src_index, int len,
640 WriteBarrierMode mode);
641
642 V8_EXPORT_PRIVATE bool IsFull() const;
643
644 inline int AllocatedSize() const;
645
646 class BodyDescriptor;
647
648 // Maximal allowed length, in number of elements. Chosen s.t. the byte size
649 // fits into a Smi which is necessary for being able to create a free space
650 // filler.
651 // TODO(jgruber): The kMaxLength could be larger (`(Smi::kMaxValue -
652 // sizeof(Header)) / kElementSize`), but our tests rely on a
653 // smaller maximum to avoid timeouts.
654 static constexpr int kMaxCapacity = kMaxFixedArrayCapacity;
655 static_assert(Smi::IsValid(SizeFor(kMaxCapacity)));
656
658 Isolate* isolate, Handle<WeakArrayList> array, int length,
660
661 // Returns the number of non-cleaned weak references in the array.
662 int CountLiveWeakReferences() const;
663
664 // Returns the number of non-cleaned elements in the array.
665 int CountLiveElements() const;
666
667 // Returns whether an entry was found and removed. Will move the elements
668 // around in the array - this method can only be used in cases where the user
669 // doesn't care about the indices! Users should make sure there are no
670 // duplicates.
672
673 // Searches the array (linear time) and returns whether it contains the value.
675
676 class Iterator;
677
678 private:
679 static int OffsetOfElementAt(int index) {
680 return kHeaderSize + index * kTaggedSize;
681 }
682
684};
685
687 public:
688 explicit Iterator(Tagged<WeakArrayList> array) : index_(0), array_(array) {}
689 Iterator(const Iterator&) = delete;
690 Iterator& operator=(const Iterator&) = delete;
691
692 inline Tagged<HeapObject> Next();
693
694 private:
698};
699
700class ArrayListShape final : public AllStatic {
701 public:
704 static constexpr RootIndex kMapRootIndex = RootIndex::kArrayListMap;
705 static constexpr bool kLengthEqualsCapacity = false;
706
708};
709
710// A generic array that grows dynamically with O(1) amortized insertion.
711V8_OBJECT class ArrayList : public TaggedArrayBase<ArrayList, ArrayListShape> {
713
714 public:
716
717 template <class IsolateT>
718 static inline DirectHandle<ArrayList> New(
719 IsolateT* isolate, int capacity,
721
722 inline int length() const;
723 inline void set_length(int value);
724
726 Isolate* isolate, DirectHandle<ArrayList> array, Tagged<Smi> obj,
732 Isolate* isolate, DirectHandle<ArrayList> array,
735
737 Isolate* isolate, DirectHandle<ArrayList> array,
739
740 // Right-trim the array.
741 // Invariant: 0 < new_length <= length()
742 void RightTrim(Isolate* isolate, int new_capacity);
743
746
747 class BodyDescriptor;
748
749 private:
751 Isolate* isolate, DirectHandle<ArrayList> array, int length,
754
755class ByteArrayShape final : public AllStatic {
756 public:
757 static constexpr int kElementSize = kUInt8Size;
758 using ElementT = uint8_t;
759 static constexpr RootIndex kMapRootIndex = RootIndex::kByteArrayMap;
760 static constexpr bool kLengthEqualsCapacity = true;
761};
762
763// ByteArray represents fixed sized arrays containing raw bytes that will not
764// be scanned by the garbage collector.
766 : public PrimitiveArrayBase<ByteArray, ByteArrayShape> {
768
769 public:
771
772 template <class IsolateT>
773 static inline Handle<ByteArray> New(
774 IsolateT* isolate, int capacity,
776
777 inline uint32_t get_int(int offset) const;
778 inline void set_int(int offset, uint32_t value);
779
780 // Given the full object size in bytes, return the length that should be
781 // passed to New s.t. an object of the same size is created.
782 static constexpr int LengthFor(int size_in_bytes) {
783 DCHECK(IsAligned(size_in_bytes, kTaggedSize));
784 DCHECK_GE(size_in_bytes, sizeof(Header));
785 return size_in_bytes - sizeof(Header);
786 }
787
790
791 class BodyDescriptor;
793
794class TrustedByteArrayShape final : public AllStatic {
795 public:
796 static constexpr int kElementSize = kUInt8Size;
797 using ElementT = uint8_t;
798 static constexpr RootIndex kMapRootIndex = RootIndex::kTrustedByteArrayMap;
799 static constexpr bool kLengthEqualsCapacity = true;
800};
801
802// A ByteArray in trusted space.
805 : public PrimitiveArrayBase<TrustedByteArray, TrustedByteArrayShape,
806 TrustedObjectLayout> {
809
810 public:
812
813 template <class IsolateT>
814 static inline Handle<TrustedByteArray> New(
815 IsolateT* isolate, int capacity,
816 AllocationType allocation_type = AllocationType::kTrusted);
817
818 inline uint32_t get_int(int offset) const;
819 inline void set_int(int offset, uint32_t value);
820
821 // Given the full object size in bytes, return the length that should be
822 // passed to New s.t. an object of the same size is created.
823 static constexpr int LengthFor(int size_in_bytes) {
824 DCHECK(IsAligned(size_in_bytes, kTaggedSize));
825 DCHECK_GE(size_in_bytes, sizeof(Header));
826 return size_in_bytes - sizeof(Header);
827 }
828
831
832 class BodyDescriptor;
834
835// Convenience class for treating a ByteArray / TrustedByteArray as array of
836// fixed-size integers.
838template <typename T, typename Base>
839class FixedIntegerArrayBase : public Base {
840 static_assert(std::is_integral<T>::value);
841
842 public:
843 // {MoreArgs...} allows passing the `AllocationType` if `Base` is `ByteArray`.
844 template <typename... MoreArgs>
846 int length,
847 MoreArgs&&... more_args);
848
849 // Get/set the contents of this array.
850 T get(int index) const;
851 void set(int index, T value);
852
853 // Code Generation support.
854 static constexpr int OffsetOfElementAt(int index) {
855 return sizeof(typename Base::Header) + index * sizeof(T);
856 }
857
858 inline int length() const;
859
860 protected:
861 Address get_element_address(int index) const;
863
872
873// Use with care! Raw addresses on the heap are not safe in combination with
874// the sandbox. However, this can for example be used to store sandboxed
875// pointers, which is safe.
877template <typename Base>
878class FixedAddressArrayBase : public FixedIntegerArrayBase<Address, Base> {
880
881 public:
882 // Get/set a sandboxed pointer from this array.
883 inline Address get_sandboxed_pointer(int index) const;
884 inline void set_sandboxed_pointer(int index, Address value);
885
886 // {MoreArgs...} allows passing the `AllocationType` if `Base` is `ByteArray`.
887 template <typename... MoreArgs>
889 Isolate* isolate, int length, MoreArgs&&... more_args);
891
894
896template <class T, class Super>
897class PodArrayBase : public Super {
898 public:
899 void copy_out(int index, T* result, int length) {
900 MemCopy(result, &this->values()[index * sizeof(T)], length * sizeof(T));
901 }
902
903 void copy_in(int index, const T* buffer, int length) {
904 MemCopy(&this->values()[index * sizeof(T)], buffer, length * sizeof(T));
905 }
906
907 bool matches(const T* buffer, int length) {
908 DCHECK_LE(length, this->length());
909 return memcmp(this->begin(), buffer, length * sizeof(T)) == 0;
910 }
911
912 bool matches(int offset, const T* buffer, int length) {
913 DCHECK_LE(offset, this->length());
914 DCHECK_LE(offset + length, this->length());
915 return memcmp(this->begin() + sizeof(T) * offset, buffer,
916 length * sizeof(T)) == 0;
917 }
918
919 T get(int index) {
920 T result;
921 copy_out(index, &result, 1);
922 return result;
923 }
924
925 void set(int index, const T& value) { copy_in(index, &value, 1); }
926
927 inline int length() const;
929
930// Wrapper class for ByteArray which can store arbitrary C++ classes, as long
931// as they can be copied with memcpy.
933template <class T>
934class PodArray : public PodArrayBase<T, ByteArray> {
935 public:
936 static Handle<PodArray<T>> New(
937 Isolate* isolate, int length,
939 static Handle<PodArray<T>> New(
940 LocalIsolate* isolate, int length,
943
945template <class T>
946class TrustedPodArray : public PodArrayBase<T, TrustedByteArray> {
947 public:
948 static DirectHandle<TrustedPodArray<T>> New(Isolate* isolate, int length);
950 int length);
952
953} // namespace v8::internal
954
956
957#endif // V8_OBJECTS_FIXED_ARRAY_H_
#define DISALLOW_GARBAGE_COLLECTION(name)
Builtins::Kind kind
Definition builtins.cc:40
static constexpr bool kLengthEqualsCapacity
V8_ARRAY_EXTRA_FIELDS({ TaggedMember< Smi > length_;})
static constexpr RootIndex kMapRootIndex
static V8_EXPORT_PRIVATE DirectHandle< ArrayList > Add(Isolate *isolate, DirectHandle< ArrayList > array, Tagged< Smi > obj, AllocationType allocation=AllocationType::kYoung)
static V8_EXPORT_PRIVATE DirectHandle< FixedArray > ToFixedArray(Isolate *isolate, DirectHandle< ArrayList > array, AllocationType allocation=AllocationType::kYoung)
static DirectHandle< ArrayList > EnsureSpace(Isolate *isolate, DirectHandle< ArrayList > array, int length, AllocationType allocation=AllocationType::kYoung)
void RightTrim(Isolate *isolate, int new_capacity)
static DirectHandle< ArrayList > New(IsolateT *isolate, int capacity, AllocationType allocation=AllocationType::kYoung)
static constexpr int kElementSize
static constexpr RootIndex kMapRootIndex
static constexpr bool kLengthEqualsCapacity
static Handle< ByteArray > New(IsolateT *isolate, int capacity, AllocationType allocation=AllocationType::kYoung)
uint32_t get_int(int offset) const
static constexpr int LengthFor(int size_in_bytes)
void set_int(int offset, uint32_t value)
void set_sandboxed_pointer(int index, Address value)
static DirectHandle< FixedAddressArrayBase > New(Isolate *isolate, int length, MoreArgs &&... more_args)
Address get_sandboxed_pointer(int index) const
V8_EXPORT_PRIVATE bool IsCowArray() const
static constexpr int kMaxRegularLength
static int GetMaxLengthForNewSpaceAllocation(ElementsKind kind)
static constexpr int kHeaderSize
static constexpr int kMaxLength
static constexpr int kLengthOffset
V8_EXPORT_PRIVATE void RightTrim(Isolate *isolate, int new_capacity)
static constexpr int kMaxLength
static HandleType< FixedArray > RightTrimOrEmpty(Isolate *isolate, HandleType< FixedArray > array, int new_length)
static constexpr int kMaxRegularLength
static Handle< FixedArray > New(IsolateT *isolate, int capacity, AllocationType allocation=AllocationType::kYoung)
static V8_EXPORT_PRIVATE HandleType< FixedArray > SetAndGrow(Isolate *isolate, HandleType< FixedArray > array, int index, DirectHandle< Object > value)
void CopyElements(Isolate *isolate, int dst_index, Tagged< FixedArray > src, int src_index, int len, WriteBarrierMode mode)
void FillWithHoles(int from, int to)
static Handle< FixedArray > Resize(Isolate *isolate, DirectHandle< FixedArray > xs, int new_capacity, AllocationType allocation=AllocationType::kYoung, WriteBarrierMode mode=UPDATE_WRITE_BARRIER)
void set_the_hole(Isolate *isolate, int index)
void MoveElements(Isolate *isolate, int dst_index, int src_index, int len, WriteBarrierMode mode)
bool is_the_hole(Isolate *isolate, int index)
static constexpr RootIndex kMapRootIndex
void set_the_hole(Isolate *isolate, int index)
bool is_the_hole(Isolate *isolate, int index)
uint64_t get_representation(int index)
void set(int index, double value)
static Handle< Object > get(Tagged< FixedDoubleArray > array, int index, Isolate *isolate)
void MoveElements(Isolate *isolate, int dst_index, int src_index, int len, WriteBarrierMode)
static Handle< FixedArrayBase > New(IsolateT *isolate, int capacity, AllocationType allocation=AllocationType::kYoung)
void FillWithHoles(int from, int to)
Address get_element_address(int index) const
static constexpr int OffsetOfElementAt(int index)
static Handle< FixedIntegerArrayBase< T, Base > > New(Isolate *isolate, int length, MoreArgs &&... more_args)
static constexpr int kHeaderSize
static const int kFixedArrayHeaderSize
void copy_in(int index, const T *buffer, int length)
bool matches(int offset, const T *buffer, int length)
bool matches(const T *buffer, int length)
void set(int index, const T &value)
void copy_out(int index, T *result, int length)
static Handle< PodArray< T > > New(Isolate *isolate, int length, AllocationType allocation=AllocationType::kYoung)
static constexpr int kMaxLength
static constexpr int kElementSize
static constexpr bool kElementsAreMaybeObject
static Tagged< Derived > FromAddressOfFirstElement(Address address)
static constexpr int kMaxRegularLength
static constexpr int OffsetOfElementAt(int index)
static constexpr int SizeFor(int length)
typename ShapeT::ElementT ElementT
void set(int index, ElementMemberT value)
ElementMemberT get(int index) const
std::conditional_t< std::is_same_v< ElementT, double >, UnalignedDoubleMember, ElementT > ElementMemberT
detail::ArrayHeaderBase< Super, true > Header
static Handle< Derived > Allocate(IsolateT *isolate, int length, std::optional< DisallowGarbageCollection > *no_gc_out, AllocationType allocation=AllocationType::kYoung)
FLEXIBLE_ARRAY_MEMBER(ElementMemberT, values)
static constexpr RootIndex kMapRootIndex
static constexpr bool kLengthEqualsCapacity
static constexpr int kMaxRegularLength
static constexpr int kMaxLength
static Handle< ProtectedFixedArray > New(IsolateT *isolate, int capacity)
static constexpr RootIndex kMapRootIndex
static Handle< ProtectedWeakFixedArray > New(IsolateT *isolate, int capacity)
static bool constexpr IsValid(T value)
Definition smi.h:67
static Handle< Derived > Allocate(IsolateT *isolate, int capacity, std::optional< DisallowGarbageCollection > *no_gc_out, AllocationType allocation=AllocationType::kYoung)
void RightTrim(Isolate *isolate, int new_capacity)
FLEXIBLE_ARRAY_MEMBER(ElementMemberT, objects)
Tagged< ElementT > compare_and_swap(int index, Tagged< ElementT > expected, Tagged< ElementT > value, SeqCstAccessTag, WriteBarrierMode mode=kDefaultMode)
SlotType RawFieldOfElementAt(int index) const
static constexpr bool kSupportsSmiElements
detail::TaggedArrayHeader< ShapeT, Super > Header
static void CopyElements(Isolate *isolate, Tagged< Derived > dst, int dst_index, Tagged< Derived > src, int src_index, int len, WriteBarrierMode mode=kDefaultMode)
Tagged< ElementT > swap(int index, Tagged< ElementT > value, SeqCstAccessTag, WriteBarrierMode mode=kDefaultMode)
std::conditional_t< kElementsAreMaybeObject, MaybeObjectSlot, ObjectSlot > SlotType
typename ShapeT::ElementT ElementT
Definition fixed-array.h:94
void set(int index, Tagged< ElementT > value, WriteBarrierMode mode=kDefaultMode)
static constexpr int OffsetOfElementAt(int index)
bool IsInBounds(int index) const
static void MoveElements(Isolate *isolate, Tagged< Derived > dst, int dst_index, Tagged< Derived > src, int src_index, int len, WriteBarrierMode mode=kDefaultMode)
static constexpr WriteBarrierMode kDefaultMode
static constexpr int kMaxRegularCapacity
static constexpr bool kElementsAreMaybeObject
static constexpr int kMaxCapacity
SlotType RawFieldOfFirstElement() const
static constexpr int kElementSize
Tagged< ElementT > get(int index) const
static constexpr int NewCapacityForIndex(int index, int old_capacity)
static constexpr int SizeFor(int capacity)
static constexpr RootIndex kMapRootIndex
static constexpr bool kLengthEqualsCapacity
static constexpr bool kLengthEqualsCapacity
static constexpr RootIndex kMapRootIndex
static constexpr bool kLengthEqualsCapacity
static constexpr int kElementSize
static constexpr RootIndex kMapRootIndex
void set_int(int offset, uint32_t value)
uint32_t get_int(int offset) const
static Handle< TrustedByteArray > New(IsolateT *isolate, int capacity, AllocationType allocation_type=AllocationType::kTrusted)
static constexpr int LengthFor(int size_in_bytes)
static Handle< TrustedFixedArray > New(IsolateT *isolate, int capacity, AllocationType allocation=AllocationType::kTrusted)
static constexpr int kMaxLength
static constexpr int kMaxRegularLength
static DirectHandle< TrustedPodArray< T > > New(Isolate *isolate, int length)
static constexpr RootIndex kMapRootIndex
static constexpr bool kLengthEqualsCapacity
static Handle< TrustedWeakFixedArray > New(IsolateT *isolate, int capacity)
Iterator & operator=(const Iterator &)=delete
Iterator(Tagged< WeakArrayList > array)
Iterator(const Iterator &)=delete
static int OffsetOfElementAt(int index)
V8_EXPORT_PRIVATE bool Contains(Tagged< MaybeObject > value)
static Handle< WeakArrayList > EnsureSpace(Isolate *isolate, Handle< WeakArrayList > array, int length, AllocationType allocation=AllocationType::kYoung)
void CopyElements(Isolate *isolate, int dst_index, Tagged< WeakArrayList > src, int src_index, int len, WriteBarrierMode mode)
V8_EXPORT_PRIVATE bool IsFull() const
static constexpr int SizeForCapacity(int capacity)
V8_EXPORT_PRIVATE bool RemoveOne(MaybeObjectDirectHandle value)
Tagged< MaybeObject > get(int index) const
static V8_WARN_UNUSED_RESULT DirectHandle< WeakArrayList > Append(Isolate *isolate, DirectHandle< WeakArrayList > array, MaybeObjectDirectHandle value, AllocationType allocation=AllocationType::kYoung)
void Set(int index, Tagged< MaybeObject > value, WriteBarrierMode mode=UPDATE_WRITE_BARRIER)
static constexpr int kMaxCapacity
NEVER_READ_ONLY_SPACE static V8_EXPORT_PRIVATE Handle< WeakArrayList > AddToEnd(Isolate *isolate, Handle< WeakArrayList > array, MaybeObjectDirectHandle value)
static constexpr int CapacityForLength(int length)
V8_EXPORT_PRIVATE void Compact(Isolate *isolate)
Tagged< MaybeObject > Get(int index) const
static constexpr bool kLengthEqualsCapacity
static constexpr RootIndex kMapRootIndex
static Handle< WeakFixedArray > New(IsolateT *isolate, int capacity, AllocationType allocation=AllocationType::kYoung, MaybeDirectHandle< Object > initial_value={})
void set_capacity(int value, ReleaseStoreTag tag)
void set_length(int value, ReleaseStoreTag tag)
void set_capacity(int value, ReleaseStoreTag tag)
#define OBJECT_POINTER_ALIGN(value)
Definition globals.h:1783
#define V8_LOWER_LIMITS_MODE_BOOL
Definition globals.h:129
DisallowGarbageCollection no_gc_
int32_t offset
ZoneVector< RpoNumber > & result
const int length_
Definition mul-fft.cc:473
STL namespace.
typename TaggedArrayHeaderHelper< Shape, Super >::type TaggedArrayHeader
Definition fixed-array.h:82
v8::internal::detail::ArrayHeaderBase< Super, false > V8_OBJECT_END
constexpr int kUInt8Size
Definition globals.h:394
constexpr int kTaggedSize
Definition globals.h:542
constexpr int kMaxRegularHeapObjectSize
Definition globals.h:680
@ SKIP_WRITE_BARRIER
Definition objects.h:52
@ UPDATE_WRITE_BARRIER
Definition objects.h:55
static constexpr bool is_maybe_weak_v
Definition tagged.h:94
Address Tagged_t
Definition globals.h:547
static constexpr bool is_subtype_v
Definition tagged.h:121
v8::internal::LoadHandler V8_OBJECT_END
MaybeWeak< Object > MaybeObject
Definition globals.h:1203
void MemCopy(void *dest, const void *src, size_t size)
Definition memcopy.h:124
V8HeapCompressionScheme TrustedSpaceCompressionScheme
Definition globals.h:1143
V8HeapCompressionSchemeImpl< MainCage > V8HeapCompressionScheme
Definition globals.h:1137
static constexpr int kMaxFixedArrayCapacity
Definition fixed-array.h:32
#define DECL_VERIFIER(Name)
#define V8_OBJECT
#define NEVER_READ_ONLY_SPACE
#define DECL_PRINTER(Name)
#define TQ_OBJECT_CONSTRUCTORS(Type)
#define DCHECK_LE(v1, v2)
Definition logging.h:490
#define DCHECK_GE(v1, v2)
Definition logging.h:488
#define DCHECK(condition)
Definition logging.h:482
#define V8_EXPORT_PRIVATE
Definition macros.h:460
constexpr bool IsAligned(T value, U alignment)
Definition macros.h:403
#define V8_WARN_UNUSED_RESULT
Definition v8config.h:671