v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
fixed-array-inl.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_INL_H_
6#define V8_OBJECTS_FIXED_ARRAY_INL_H_
7
9// Include the non-inl header before the rest of the headers.
10
11#include <optional>
12
13#include "src/common/globals.h"
18#include "src/objects/bigint.h"
20#include "src/objects/hole.h"
21#include "src/objects/map.h"
24#include "src/objects/oddball.h"
26#include "src/objects/slots.h"
27#include "src/roots/roots-inl.h"
31
32// Has to be the last include (doesn't have include guards):
34
35namespace v8::internal {
36
37#include "torque-generated/src/objects/fixed-array-tq-inl.inc"
38
39template <class S>
40int detail::ArrayHeaderBase<S, false>::capacity() const {
41 return capacity_.load().value();
42}
43
44template <class S>
45int detail::ArrayHeaderBase<S, false>::capacity(AcquireLoadTag tag) const {
46 return capacity_.Acquire_Load().value();
47}
48
49template <class S>
50void detail::ArrayHeaderBase<S, false>::set_capacity(int value) {
51 capacity_.store(this, Smi::FromInt(value));
52}
53
54template <class S>
55void detail::ArrayHeaderBase<S, false>::set_capacity(int value,
56 ReleaseStoreTag tag) {
57 capacity_.Release_Store(this, Smi::FromInt(value));
58}
59
60template <class S>
61int detail::ArrayHeaderBase<S, true>::length() const {
62 return length_.load().value();
63}
64
65template <class S>
66int detail::ArrayHeaderBase<S, true>::length(AcquireLoadTag tag) const {
67 return length_.Acquire_Load().value();
68}
69
70template <class S>
71void detail::ArrayHeaderBase<S, true>::set_length(int value) {
72 length_.store(this, Smi::FromInt(value));
73}
74
75template <class S>
76void detail::ArrayHeaderBase<S, true>::set_length(int value,
77 ReleaseStoreTag tag) {
78 length_.Release_Store(this, Smi::FromInt(value));
79}
80
81template <class S>
82int detail::ArrayHeaderBase<S, true>::capacity() const {
83 return length();
84}
85
86template <class S>
87int detail::ArrayHeaderBase<S, true>::capacity(AcquireLoadTag tag) const {
88 return length(tag);
89}
90
91template <class S>
92void detail::ArrayHeaderBase<S, true>::set_capacity(int value) {
93 set_length(value);
94}
95
96template <class S>
97void detail::ArrayHeaderBase<S, true>::set_capacity(int value,
98 ReleaseStoreTag tag) {
99 set_length(value, tag);
100}
101
102template <class D, class S, class P>
104 return static_cast<unsigned>(index) < static_cast<unsigned>(this->capacity());
105}
106
107template <class D, class S, class P>
109 return this->map() ==
110 this->EarlyGetReadOnlyRoots().unchecked_fixed_cow_array_map();
111}
112
113template <class D, class S, class P>
116 DCHECK(IsInBounds(index));
117 // TODO(jgruber): This tag-less overload shouldn't be relaxed.
118 return objects()[index].Relaxed_Load();
119}
120
121template <class D, class S, class P>
124 DCHECK(IsInBounds(index));
125 return objects()[index].Relaxed_Load();
127
128template <class D, class S, class P>
131 DCHECK(IsInBounds(index));
132 return objects()[index].Acquire_Load();
133}
134
135template <class D, class S, class P>
138 DCHECK(IsInBounds(index));
139 return objects()[index].SeqCst_Load();
142template <class D, class S, class P>
144 WriteBarrierMode mode) {
145 DCHECK(!IsCowArray());
146 DCHECK(IsInBounds(index));
147 // TODO(jgruber): This tag-less overload shouldn't be relaxed.
148 objects()[index].Relaxed_Store(this, value, mode);
149}
151template <class D, class S, class P>
152template <typename, typename>
154 set(index, value, SKIP_WRITE_BARRIER);
155}
157template <class D, class S, class P>
160 DCHECK(!IsCowArray());
161 DCHECK(IsInBounds(index));
162 objects()[index].Relaxed_Store(this, value, mode);
163}
164
165template <class D, class S, class P>
166template <typename, typename>
168 RelaxedStoreTag tag) {
169 set(index, value, tag, SKIP_WRITE_BARRIER);
170}
171
172template <class D, class S, class P>
175 DCHECK(!IsCowArray());
176 DCHECK(IsInBounds(index));
177 objects()[index].Release_Store(this, value, mode);
180template <class D, class S, class P>
181template <typename, typename>
183 ReleaseStoreTag tag) {
184 set(index, value, tag, SKIP_WRITE_BARRIER);
185}
186
187template <class D, class S, class P>
190 DCHECK(!IsCowArray());
191 DCHECK(IsInBounds(index));
192 objects()[index].SeqCst_Store(this, value, mode);
193}
194
195template <class D, class S, class P>
196template <typename, typename>
198 SeqCstAccessTag tag) {
199 set(index, value, tag, SKIP_WRITE_BARRIER);
200}
201
202template <class D, class S, class P>
206 DCHECK(!IsCowArray());
207 DCHECK(IsInBounds(index));
208 return objects()[index].SeqCst_Swap(this, value, mode);
209}
210
211template <class D, class S, class P>
214 Tagged<ElementT> value,
216 WriteBarrierMode mode) {
217 DCHECK(!IsCowArray());
218 DCHECK(IsInBounds(index));
219 return objects()[index].SeqCst_CompareAndSwap(this, expected, value, mode);
220}
221
222template <class D, class S, class P>
224 int dst_index, Tagged<D> src,
225 int src_index, int len,
226 WriteBarrierMode mode) {
227 if (len == 0) return;
228
229 DCHECK_GE(len, 0);
230 DCHECK(dst->IsInBounds(dst_index));
231 DCHECK_LE(dst_index + len, dst->length());
232 DCHECK(src->IsInBounds(src_index));
233 DCHECK_LE(src_index + len, src->length());
234
236 SlotType dst_slot(&dst->objects()[dst_index]);
237 SlotType src_slot(&src->objects()[src_index]);
238 isolate->heap()->MoveRange(dst, dst_slot, src_slot, len, mode);
239}
240
241template <class D, class S, class P>
243 int dst_index, Tagged<D> src,
244 int src_index, int len,
245 WriteBarrierMode mode) {
246 if (len == 0) return;
247
248 DCHECK_GE(len, 0);
249 DCHECK(dst->IsInBounds(dst_index));
250 DCHECK_LE(dst_index + len, dst->capacity());
251 DCHECK(src->IsInBounds(src_index));
252 DCHECK_LE(src_index + len, src->capacity());
253
255 SlotType dst_slot(&dst->objects()[dst_index]);
256 SlotType src_slot(&src->objects()[src_index]);
257 isolate->heap()->CopyRange(dst, dst_slot, src_slot, len, mode);
258}
259
260template <class D, class S, class P>
261void TaggedArrayBase<D, S, P>::RightTrim(Isolate* isolate, int new_capacity) {
262 int old_capacity = this->capacity();
263 CHECK_GT(new_capacity, 0); // Due to possible canonicalization.
264 CHECK_LE(new_capacity, old_capacity);
265 if (new_capacity == old_capacity) return;
266 isolate->heap()->RightTrimArray(Cast<D>(this), new_capacity, old_capacity);
267}
268
269// Due to right-trimming (which creates a filler object before publishing the
270// length through a release-store, see Heap::RightTrimArray), concurrent
271// visitors need to read the length with acquire semantics.
272template <class D, class S, class P>
274 return SizeFor(this->capacity(kAcquireLoad));
275}
276
277template <class D, class S, class P>
280 return RawFieldOfElementAt(0);
281}
282
283template <class D, class S, class P>
286 return SlotType(&objects()[index]);
287}
288
289// static
290template <class IsolateT>
291Handle<FixedArray> FixedArray::New(IsolateT* isolate, int capacity,
292 AllocationType allocation) {
293 if (V8_UNLIKELY(static_cast<unsigned>(capacity) >
295 FATAL("Fatal JavaScript invalid size error %d (see crbug.com/1201626)",
296 capacity);
297 } else if (V8_UNLIKELY(capacity == 0)) {
298 return isolate->factory()->empty_fixed_array();
299 }
300
301 std::optional<DisallowGarbageCollection> no_gc;
303 Cast<FixedArray>(Allocate(isolate, capacity, &no_gc, allocation));
304 ReadOnlyRoots roots{isolate};
305 MemsetTagged((*result)->RawFieldOfFirstElement(), roots.undefined_value(),
306 capacity);
307 return result;
308}
309
310// static
311template <class IsolateT>
313 int capacity,
314 AllocationType allocation) {
315 DCHECK(allocation == AllocationType::kTrusted ||
316 allocation == AllocationType::kSharedTrusted);
317
318 if (V8_UNLIKELY(static_cast<unsigned>(capacity) >
320 FATAL("Fatal JavaScript invalid size error %d (see crbug.com/1201626)",
321 capacity);
322 }
323 // TODO(saelo): once we have trusted read-only roots, we can return the
324 // empty_trusted_fixed_array here. Currently this isn't possible because the
325 // (mutable) empty_trusted_fixed_array will be created via this function.
326 // The same is true for the other trusted-space arrays below.
327
328 std::optional<DisallowGarbageCollection> no_gc;
330 Cast<TrustedFixedArray>(Allocate(isolate, capacity, &no_gc, allocation));
331 MemsetTagged((*result)->RawFieldOfFirstElement(), Smi::zero(), capacity);
332 return result;
333}
334
335// static
336template <class IsolateT>
338 int capacity) {
339 if (V8_UNLIKELY(static_cast<unsigned>(capacity) >
341 FATAL("Fatal JavaScript invalid size error %d (see crbug.com/1201626)",
342 capacity);
343 }
344
345 std::optional<DisallowGarbageCollection> no_gc;
347 Allocate(isolate, capacity, &no_gc, AllocationType::kTrusted));
348 MemsetTagged((*result)->RawFieldOfFirstElement(), Smi::zero(), capacity);
349 return result;
350}
351
352// static
353template <class D, class S, class P>
354template <class IsolateT>
356 IsolateT* isolate, int capacity,
357 std::optional<DisallowGarbageCollection>* no_gc_out,
358 AllocationType allocation) {
359 // Note 0-capacity is explicitly allowed since not all subtypes can be
360 // assumed to have canonical 0-capacity instances.
361 DCHECK_GE(capacity, 0);
362 DCHECK_LE(capacity, kMaxCapacity);
363 DCHECK(!no_gc_out->has_value());
364
366 isolate->factory()->AllocateRawArray(SizeFor(capacity), allocation));
367
368 ReadOnlyRoots roots{isolate};
369 if (DEBUG_BOOL) no_gc_out->emplace();
370 Tagged<Map> map = Cast<Map>(roots.object_at(S::kMapRootIndex));
372
373 xs->set_map_after_allocation(isolate, map, SKIP_WRITE_BARRIER);
374 xs->set_capacity(capacity);
375
376 return handle(xs, isolate);
377}
378
379// static
380template <class D, class S, class P>
382 int old_capacity) {
383 DCHECK_GE(index, old_capacity);
384 // Note this is currently based on JSObject::NewElementsCapacity.
385 int capacity = old_capacity;
386 do {
387 capacity = capacity + (capacity >> 1) + 16;
388 } while (capacity <= index);
389 return capacity;
390}
391
393
395
396bool FixedArray::is_the_hole(Isolate* isolate, int index) {
397 return IsTheHole(get(index), isolate);
398}
399
400void FixedArray::set_the_hole(Isolate* isolate, int index) {
401 set_the_hole(ReadOnlyRoots(isolate), index);
402}
404void FixedArray::set_the_hole(ReadOnlyRoots ro_roots, int index) {
405 set(index, ro_roots.the_hole_value(), SKIP_WRITE_BARRIER);
407
408void FixedArray::FillWithHoles(int from, int to) {
410 for (int i = from; i < to; i++) {
411 set(i, roots.the_hole_value(), SKIP_WRITE_BARRIER);
412 }
413}
414
415void FixedArray::MoveElements(Isolate* isolate, int dst_index, int src_index,
416 int len, WriteBarrierMode mode) {
417 MoveElements(isolate, this, dst_index, this, src_index, len, mode);
420void FixedArray::CopyElements(Isolate* isolate, int dst_index,
421 Tagged<FixedArray> src, int src_index, int len,
422 WriteBarrierMode mode) {
423 CopyElements(isolate, this, dst_index, src, src_index, len, mode);
424}
425
426// static
429 int new_capacity,
430 AllocationType allocation,
431 WriteBarrierMode mode) {
432 Handle<FixedArray> ys = New(isolate, new_capacity, allocation);
433 int elements_to_copy = std::min(new_capacity, xs->capacity());
434 FixedArray::CopyElements(isolate, *ys, 0, *xs, 0, elements_to_copy, mode);
435 return ys;
436}
437
438inline int WeakArrayList::AllocatedSize() const { return SizeFor(capacity()); }
439
440template <class D, class S, class P>
442 return static_cast<unsigned>(index) < static_cast<unsigned>(this->length());
443}
444
445template <class D, class S, class P>
447 DCHECK(IsInBounds(index));
448 return values()[index];
449}
450
451template <class D, class S, class P>
453 DCHECK(IsInBounds(index));
454 values()[index] = value;
455}
456
457// Due to right-trimming (which creates a filler object before publishing the
458// length through a release-store, see Heap::RightTrimArray), concurrent
459// visitors need to read the length with acquire semantics.
460template <class D, class S, class P>
462 return SizeFor(this->length(kAcquireLoad));
463}
464
465template <class D, class S, class P>
467 return &values()[0];
468}
469
470template <class D, class S, class P>
472 return &values()[0];
473}
474
475template <class D, class S, class P>
477 return &values()[this->length()];
478}
479
480template <class D, class S, class P>
482 return &values()[this->length()];
483}
484
485template <class D, class S, class P>
487 int data_size = SizeFor(this->length()) - sizeof(Header);
488 DCHECK_EQ(data_size, OBJECT_POINTER_ALIGN(this->length() * kElementSize));
489 return data_size;
490}
491
492// static
493template <class D, class S, class P>
495 Address address) {
496 DCHECK_TAG_ALIGNED(address);
497 return Cast<D>(Tagged<Object>(address - S::kHeaderSize + kHeapObjectTag));
498}
499
500// static
501template <class IsolateT>
502Handle<FixedArrayBase> FixedDoubleArray::New(IsolateT* isolate, int length,
503 AllocationType allocation) {
504 if (V8_UNLIKELY(static_cast<unsigned>(length) > kMaxLength)) {
505 FATAL("Fatal JavaScript invalid size error %d (see crbug.com/1201626)",
506 length);
507 } else if (V8_UNLIKELY(length == 0)) {
508 return isolate->factory()->empty_fixed_array();
509 }
510
511 std::optional<DisallowGarbageCollection> no_gc;
512 return Cast<FixedDoubleArray>(Allocate(isolate, length, &no_gc, allocation));
513}
514
515// static
516template <class D, class S, class P>
517template <class IsolateT>
519 IsolateT* isolate, int length,
520 std::optional<DisallowGarbageCollection>* no_gc_out,
521 AllocationType allocation) {
522 // Note 0-length is explicitly allowed since not all subtypes can be
523 // assumed to have canonical 0-length instances.
524 DCHECK_GE(length, 0);
525 DCHECK_LE(length, kMaxLength);
526 DCHECK(!no_gc_out->has_value());
527
529 isolate->factory()->AllocateRawArray(SizeFor(length), allocation));
530
531 ReadOnlyRoots roots{isolate};
532 if (DEBUG_BOOL) no_gc_out->emplace();
533 Tagged<Map> map = Cast<Map>(roots.object_at(S::kMapRootIndex));
535
536 xs->set_map_after_allocation(isolate, map, SKIP_WRITE_BARRIER);
537 xs->set_length(length);
538
539 return handle(xs, isolate);
540}
541
543 DCHECK(!is_the_hole(index));
544 return values()[index].value();
545}
546
548 DCHECK(IsInBounds(index));
549 return values()[index].value_as_bits();
550}
551
553 Isolate* isolate) {
554 if (array->is_the_hole(index)) {
555 return isolate->factory()->the_hole_value();
556#ifdef V8_ENABLE_EXPERIMENTAL_UNDEFINED_DOUBLE
557 } else if (array->is_undefined(index)) {
558 return isolate->factory()->undefined_value();
559#endif // V8_ENABLE_EXPERIMENTAL_UNDEFINED_DOUBLE
560 } else {
561 return isolate->factory()->NewNumber(array->get_scalar(index));
562 }
563}
564
565void FixedDoubleArray::set(int index, double value) {
566 if (std::isnan(value)) {
567#ifdef V8_ENABLE_EXPERIMENTAL_UNDEFINED_DOUBLE
568 DCHECK(!IsUndefinedNan(value));
569#endif // V8_ENABLE_EXPERIMENTAL_UNDEFINED_DOUBLE
570 value = std::numeric_limits<double>::quiet_NaN();
571 }
572 values()[index].set_value(value);
573 DCHECK(!is_the_hole(index));
574}
575
576#ifdef V8_ENABLE_EXPERIMENTAL_UNDEFINED_DOUBLE
577void FixedDoubleArray::set_undefined(int index) {
578 values()[index].set_value(UndefinedNan());
579 DCHECK(!is_the_hole(index));
580 DCHECK(is_undefined(index));
581}
582
583bool FixedDoubleArray::is_undefined(int index) {
584 return get_representation(index) == kUndefinedNanInt64;
585}
586#endif // V8_ENABLE_EXPERIMENTAL_UNDEFINED_DOUBLE
587
588void FixedDoubleArray::set_the_hole(Isolate* isolate, int index) {
589 set_the_hole(index);
590}
591
593 DCHECK(IsInBounds(index));
594 values()[index].set_value_as_bits(kHoleNanInt64);
595}
596
597bool FixedDoubleArray::is_the_hole(Isolate* isolate, int index) {
598 return is_the_hole(index);
599}
600
602 return get_representation(index) == kHoleNanInt64;
603}
604
605void FixedDoubleArray::MoveElements(Isolate* isolate, int dst_index,
606 int src_index, int len,
607 WriteBarrierMode mode) {
609 MemMove(&values()[dst_index], &values()[src_index], len * kElementSize);
610}
611
612void FixedDoubleArray::FillWithHoles(int from, int to) {
613 for (int i = from; i < to; i++) {
615 }
616}
617
618// static
619template <class IsolateT>
621 IsolateT* isolate, int capacity, AllocationType allocation,
622 MaybeDirectHandle<Object> initial_value) {
623 CHECK_LE(static_cast<unsigned>(capacity), kMaxCapacity);
624
625 if (V8_UNLIKELY(capacity == 0)) {
626 return isolate->factory()->empty_weak_fixed_array();
627 }
628
629 std::optional<DisallowGarbageCollection> no_gc;
631 Cast<WeakFixedArray>(Allocate(isolate, capacity, &no_gc, allocation));
632 ReadOnlyRoots roots{isolate};
633 MemsetTagged((*result)->RawFieldOfFirstElement(),
634 initial_value.is_null() ? roots.undefined_value()
635 : *initial_value.ToHandleChecked(),
636 capacity);
637 return result;
638}
639
640template <class IsolateT>
642 int capacity) {
643 if (V8_UNLIKELY(static_cast<unsigned>(capacity) >
645 FATAL("Fatal JavaScript invalid size error %d (see crbug.com/1201626)",
646 capacity);
647 }
648
649 std::optional<DisallowGarbageCollection> no_gc;
651 Allocate(isolate, capacity, &no_gc, AllocationType::kTrusted));
652 MemsetTagged((*result)->RawFieldOfFirstElement(), Smi::zero(), capacity);
653 return result;
654}
655
656template <class IsolateT>
658 int capacity) {
659 if (V8_UNLIKELY(static_cast<unsigned>(capacity) >
661 FATAL("Fatal JavaScript invalid size error %d (see crbug.com/1201626)",
662 capacity);
663 }
664 std::optional<DisallowGarbageCollection> no_gc;
666 Allocate(isolate, capacity, &no_gc, AllocationType::kTrusted));
667 MemsetTagged((*result)->RawFieldOfFirstElement(), Smi::zero(), capacity);
668 return result;
669}
670
673 return Get(cage_base, index);
674}
675Tagged<MaybeObject> WeakArrayList::get(int index) const { return Get(index); }
676
678 int index) const {
679 DCHECK_LT(static_cast<unsigned>(index), static_cast<unsigned>(capacity()));
680 return objects(cage_base, index, kRelaxedLoad);
681}
682
684 WriteBarrierMode mode) {
685 set_objects(index, value, kRelaxedStore, mode);
686}
687
688void WeakArrayList::Set(int index, Tagged<Smi> value) {
689 Set(index, value, SKIP_WRITE_BARRIER);
690}
691
693 return RawMaybeWeakField(kObjectsOffset);
694}
695
696void WeakArrayList::CopyElements(Isolate* isolate, int dst_index,
697 Tagged<WeakArrayList> src, int src_index,
698 int len, WriteBarrierMode mode) {
699 if (len == 0) return;
700 DCHECK_LE(dst_index + len, capacity());
701 DCHECK_LE(src_index + len, src->capacity());
703
704 MaybeObjectSlot dst_slot(data_start() + dst_index);
705 MaybeObjectSlot src_slot(src->data_start() + src_index);
706 isolate->heap()->CopyRange(*this, dst_slot, src_slot, len, mode);
707}
708
710 if (!array_.is_null()) {
711 while (index_ < array_->length()) {
712 Tagged<MaybeObject> item = array_->Get(index_++);
713 DCHECK(item.IsWeakOrCleared());
714 if (!item.IsCleared()) return item.GetHeapObjectAssumeWeak();
715 }
717 }
718 return Tagged<HeapObject>();
719}
720
721int ArrayList ::length() const { return length_.load().value(); }
722void ArrayList ::set_length(int value) {
723 length_.store(this, Smi::FromInt(value));
724}
725
726// static
727template <class IsolateT>
728DirectHandle<ArrayList> ArrayList::New(IsolateT* isolate, int capacity,
729 AllocationType allocation) {
730 if (capacity == 0) return isolate->factory()->empty_array_list();
731
732 DCHECK_GT(capacity, 0);
733 DCHECK_LE(capacity, kMaxCapacity);
734
735 std::optional<DisallowGarbageCollection> no_gc;
737 Cast<ArrayList>(Allocate(isolate, capacity, &no_gc, allocation));
738 result->set_length(0);
739 ReadOnlyRoots roots{isolate};
740 MemsetTagged(result->RawFieldOfFirstElement(), roots.undefined_value(),
741 capacity);
742 return result;
743}
744
745// static
746template <class IsolateT>
747Handle<ByteArray> ByteArray::New(IsolateT* isolate, int length,
748 AllocationType allocation) {
749 if (V8_UNLIKELY(static_cast<unsigned>(length) > kMaxLength)) {
750 FATAL("Fatal JavaScript invalid size error %d", length);
751 } else if (V8_UNLIKELY(length == 0)) {
752 return isolate->factory()->empty_byte_array();
753 }
754
755 std::optional<DisallowGarbageCollection> no_gc;
757 Cast<ByteArray>(Allocate(isolate, length, &no_gc, allocation));
758
759 int padding_size = SizeFor(length) - OffsetOfElementAt(length);
760 memset(&result->values()[length], 0, padding_size);
761
762 return result;
763}
764
765uint32_t ByteArray::get_int(int offset) const {
766 DCHECK(IsInBounds(offset));
767 DCHECK_LE(offset + sizeof(uint32_t), length());
769 reinterpret_cast<Address>(&values()[offset]));
770}
771
772void ByteArray::set_int(int offset, uint32_t value) {
773 DCHECK(IsInBounds(offset));
774 DCHECK_LE(offset + sizeof(uint32_t), length());
776 reinterpret_cast<Address>(&values()[offset]), value);
777}
778
779// static
780template <class IsolateT>
782 AllocationType allocation_type) {
783 DCHECK(allocation_type == AllocationType::kTrusted ||
784 allocation_type == AllocationType::kSharedTrusted);
785 if (V8_UNLIKELY(static_cast<unsigned>(length) > kMaxLength)) {
786 FATAL("Fatal JavaScript invalid size error %d", length);
787 }
788
789 std::optional<DisallowGarbageCollection> no_gc;
791 Allocate(isolate, length, &no_gc, allocation_type));
792
793 int padding_size = SizeFor(length) - OffsetOfElementAt(length);
794 memset(&result->values()[length], 0, padding_size);
795
796 return result;
797}
798
800 DCHECK(IsInBounds(offset));
801 DCHECK_LE(offset + sizeof(uint32_t), length());
803 reinterpret_cast<Address>(&values()[offset]));
804}
805
806void TrustedByteArray::set_int(int offset, uint32_t value) {
807 DCHECK(IsInBounds(offset));
808 DCHECK_LE(offset + sizeof(uint32_t), length());
810 reinterpret_cast<Address>(&values()[offset]), value);
811}
812
813template <typename Base>
814template <typename... MoreArgs>
815// static
817 Isolate* isolate, int length, MoreArgs&&... more_args) {
819 Underlying::New(isolate, length, std::forward<MoreArgs>(more_args)...));
820}
821
822template <typename T, typename Base>
823template <typename... MoreArgs>
824// static
826 Isolate* isolate, int length, MoreArgs&&... more_args) {
827 int byte_length;
828 CHECK(!base::bits::SignedMulOverflow32(length, sizeof(T), &byte_length));
830 Base::New(isolate, byte_length, std::forward<MoreArgs>(more_args)...));
831}
832
833template <typename T, typename Base>
835 DCHECK_GE(index, 0);
836 DCHECK_LT(index, length());
837 return reinterpret_cast<Address>(&this->values()[index * sizeof(T)]);
838}
839
840template <typename T, typename Base>
842 static_assert(std::is_integral<T>::value);
843 return base::ReadUnalignedValue<T>(get_element_address(index));
844}
846template <typename T, typename Base>
847void FixedIntegerArrayBase<T, Base>::set(int index, T value) {
848 static_assert(std::is_integral<T>::value);
849 return base::WriteUnalignedValue<T>(get_element_address(index), value);
852template <typename T, typename Base>
854 DCHECK_EQ(Base::length() % sizeof(T), 0);
855 return Base::length() / sizeof(T);
856}
857
858template <typename Base>
860 PtrComprCageBase sandbox_base = GetPtrComprCageBase(this);
862 sandbox_base);
863}
864
865template <typename Base>
867 Address value) {
868 PtrComprCageBase sandbox_base = GetPtrComprCageBase(this);
869 WriteSandboxedPointerField(this->get_element_address(index), sandbox_base,
870 value);
871}
872
873template <class T, class Super>
875 return Super::length() / sizeof(T);
876}
877
878// static
879template <class T>
881 AllocationType allocation) {
882 int byte_length;
883 CHECK(!base::bits::SignedMulOverflow32(length, sizeof(T), &byte_length));
884 return Cast<PodArray<T>>(
885 isolate->factory()->NewByteArray(byte_length, allocation));
886}
887
888// static
889template <class T>
891 AllocationType allocation) {
892 int byte_length;
893 CHECK(!base::bits::SignedMulOverflow32(length, sizeof(T), &byte_length));
894 return Cast<PodArray<T>>(
895 isolate->factory()->NewByteArray(byte_length, allocation));
896}
897
898// static
899template <class T>
901 int length) {
902 int byte_length;
903 CHECK(!base::bits::SignedMulOverflow32(length, sizeof(T), &byte_length));
905 isolate->factory()->NewTrustedByteArray(byte_length));
906}
907
908// static
909template <class T>
911 int length) {
912 int byte_length;
913 CHECK(!base::bits::SignedMulOverflow32(length, sizeof(T), &byte_length));
915 isolate->factory()->NewTrustedByteArray(byte_length));
916}
917
918} // namespace v8::internal
919
921
922#endif // V8_OBJECTS_FIXED_ARRAY_INL_H_
#define T
#define DCHECK_TAG_ALIGNED(address)
Definition checks.h:25
static DirectHandle< ArrayList > New(IsolateT *isolate, int capacity, AllocationType allocation=AllocationType::kYoung)
static Handle< ByteArray > New(IsolateT *isolate, int capacity, AllocationType allocation=AllocationType::kYoung)
uint32_t get_int(int offset) const
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
static constexpr int kMaxLength
static Handle< FixedArray > New(IsolateT *isolate, int capacity, AllocationType allocation=AllocationType::kYoung)
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)
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 Handle< FixedIntegerArrayBase< T, Base > > New(Isolate *isolate, int length, MoreArgs &&... more_args)
V8_INLINE DirectHandle< T > ToHandleChecked() const
V8_INLINE bool is_null() const
static Handle< PodArray< T > > New(Isolate *isolate, int length, AllocationType allocation=AllocationType::kYoung)
static Tagged< Derived > FromAddressOfFirstElement(Address address)
void set(int index, ElementMemberT value)
ElementMemberT get(int index) const
std::conditional_t< std::is_same_v< ElementT, double >, UnalignedDoubleMember, ElementT > ElementMemberT
static Handle< FixedDoubleArray > Allocate(IsolateT *isolate, int length, std::optional< DisallowGarbageCollection > *no_gc_out, AllocationType allocation=AllocationType::kYoung)
static constexpr int kMaxLength
static Handle< ProtectedFixedArray > New(IsolateT *isolate, int capacity)
static Handle< ProtectedWeakFixedArray > New(IsolateT *isolate, int capacity)
static V8_EXPORT_PRIVATE bool Contains(Address address)
static constexpr Tagged< Smi > FromInt(int value)
Definition smi.h:38
static constexpr Tagged< Smi > zero()
Definition smi.h:99
static Handle< FixedArray > Allocate(IsolateT *isolate, int capacity, std::optional< DisallowGarbageCollection > *no_gc_out, AllocationType allocation=AllocationType::kYoung)
void RightTrim(Isolate *isolate, int new_capacity)
Tagged< ElementT > compare_and_swap(int index, Tagged< ElementT > expected, Tagged< ElementT > value, SeqCstAccessTag, WriteBarrierMode mode=kDefaultMode)
SlotType RawFieldOfElementAt(int index) const
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
void set(int index, Tagged< ElementT > value, WriteBarrierMode mode=kDefaultMode)
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)
SlotType RawFieldOfFirstElement() const
Tagged< ElementT > get(int index) const
static constexpr int NewCapacityForIndex(int index, int old_capacity)
constexpr bool IsCleared() const
constexpr bool IsWeakOrCleared() const
Tagged< HeapObject > GetHeapObjectAssumeWeak() const
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 Handle< TrustedFixedArray > New(IsolateT *isolate, int capacity, AllocationType allocation=AllocationType::kTrusted)
static constexpr int kMaxLength
static DirectHandle< TrustedPodArray< T > > New(Isolate *isolate, int length)
static Handle< TrustedWeakFixedArray > New(IsolateT *isolate, int capacity)
static int OffsetOfElementAt(int index)
void CopyElements(Isolate *isolate, int dst_index, Tagged< WeakArrayList > src, int src_index, int len, WriteBarrierMode mode)
Tagged< MaybeObject > get(int index) const
void Set(int index, Tagged< MaybeObject > value, WriteBarrierMode mode=UPDATE_WRITE_BARRIER)
static constexpr int kMaxCapacity
Tagged< MaybeObject > Get(int index) const
static Handle< WeakFixedArray > New(IsolateT *isolate, int capacity, AllocationType allocation=AllocationType::kYoung, MaybeDirectHandle< Object > initial_value={})
#define DEBUG_BOOL
Definition globals.h:87
#define OBJECT_POINTER_ALIGN(value)
Definition globals.h:1783
int32_t offset
std::map< const std::string, const std::string > map
ZoneVector< RpoNumber > & result
Point to
const int length_
Definition mul-fft.cc:473
bool SignedMulOverflow32(int32_t lhs, int32_t rhs, int32_t *val)
Definition bits.h:323
static V ReadUnalignedValue(Address p)
Definition memory.h:28
static void WriteUnalignedValue(Address p, V value)
Definition memory.h:41
V8_INLINE IndirectHandle< T > handle(Tagged< T > object, Isolate *isolate)
Definition handles-inl.h:72
@ SKIP_WRITE_BARRIER
Definition objects.h:52
ReadOnlyRoots GetReadOnlyRoots()
Definition roots-inl.h:86
V8_INLINE Address ReadSandboxedPointerField(Address field_address, PtrComprCageBase cage_base)
constexpr uint64_t kHoleNanInt64
Definition globals.h:1960
kInterpreterTrampolineOffset Tagged< HeapObject >
void MemsetTagged(Tagged_t *start, Tagged< MaybeObject > value, size_t counter)
Definition slots-inl.h:486
Handle< To > UncheckedCast(Handle< From > value)
Definition handles-inl.h:55
V8_INLINE PtrComprCageBase GetPtrComprCageBase()
V8_EXPORT_PRIVATE void MemMove(void *dest, const void *src, size_t size)
Definition memcopy.h:189
const int kHeapObjectTag
Definition v8-internal.h:72
V8_INLINE void WriteSandboxedPointerField(Address field_address, PtrComprCageBase cage_base, Address pointer)
return value
Definition map-inl.h:893
Tagged< To > Cast(Tagged< From > value, const v8::SourceLocation &loc=INIT_SOURCE_LOCATION_IN_DEBUG)
Definition casting.h:150
static constexpr RelaxedLoadTag kRelaxedLoad
Definition globals.h:2909
static constexpr RelaxedStoreTag kRelaxedStore
Definition globals.h:2911
static constexpr AcquireLoadTag kAcquireLoad
Definition globals.h:2908
#define TQ_OBJECT_CONSTRUCTORS_IMPL(Type)
#define NEVER_READ_ONLY_SPACE_IMPL(Type)
#define FATAL(...)
Definition logging.h:47
#define DCHECK_LE(v1, v2)
Definition logging.h:490
#define CHECK(condition)
Definition logging.h:124
#define CHECK_GT(lhs, rhs)
#define CHECK_LE(lhs, rhs)
#define DCHECK_GE(v1, v2)
Definition logging.h:488
#define DCHECK(condition)
Definition logging.h:482
#define DCHECK_LT(v1, v2)
Definition logging.h:489
#define DCHECK_EQ(v1, v2)
Definition logging.h:485
#define DCHECK_GT(v1, v2)
Definition logging.h:487
#define V8_UNLIKELY(condition)
Definition v8config.h:660