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/handles/maybe-handles.h" 9 #include "src/objects/instance-type.h" 10 #include "src/objects/objects.h" 11 #include "src/objects/smi.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 19 #define FIXED_ARRAY_SUB_INSTANCE_TYPE_LIST(V) \ 20 V(BYTECODE_ARRAY_CONSTANT_POOL_SUB_TYPE) \ 21 V(BYTECODE_ARRAY_HANDLER_TABLE_SUB_TYPE) \ 22 V(CODE_STUBS_TABLE_SUB_TYPE) \ 23 V(COMPILATION_CACHE_TABLE_SUB_TYPE) \ 24 V(CONTEXT_SUB_TYPE) \ 25 V(COPY_ON_WRITE_SUB_TYPE) \ 26 V(DEOPTIMIZATION_DATA_SUB_TYPE) \ 27 V(DESCRIPTOR_ARRAY_SUB_TYPE) \ 28 V(EMBEDDED_OBJECT_SUB_TYPE) \ 29 V(ENUM_CACHE_SUB_TYPE) \ 30 V(ENUM_INDICES_CACHE_SUB_TYPE) \ 31 V(DEPENDENT_CODE_SUB_TYPE) \ 32 V(DICTIONARY_ELEMENTS_SUB_TYPE) \ 33 V(DICTIONARY_PROPERTIES_SUB_TYPE) \ 34 V(EMPTY_PROPERTIES_DICTIONARY_SUB_TYPE) \ 35 V(PACKED_ELEMENTS_SUB_TYPE) \ 36 V(FAST_PROPERTIES_SUB_TYPE) \ 37 V(FAST_TEMPLATE_INSTANTIATIONS_CACHE_SUB_TYPE) \ 38 V(HANDLER_TABLE_SUB_TYPE) \ 39 V(JS_COLLECTION_SUB_TYPE) \ 40 V(JS_WEAK_COLLECTION_SUB_TYPE) \ 41 V(NOSCRIPT_SHARED_FUNCTION_INFOS_SUB_TYPE) \ 42 V(NUMBER_STRING_CACHE_SUB_TYPE) \ 43 V(OBJECT_TO_CODE_SUB_TYPE) \ 44 V(OPTIMIZED_CODE_LITERALS_SUB_TYPE) \ 45 V(OPTIMIZED_CODE_MAP_SUB_TYPE) \ 46 V(PROTOTYPE_USERS_SUB_TYPE) \ 47 V(REGEXP_MULTIPLE_CACHE_SUB_TYPE) \ 48 V(RETAINED_MAPS_SUB_TYPE) \ 49 V(SCOPE_INFO_SUB_TYPE) \ 50 V(SCRIPT_LIST_SUB_TYPE) \ 51 V(SERIALIZED_OBJECTS_SUB_TYPE) \ 52 V(SHARED_FUNCTION_INFOS_SUB_TYPE) \ 53 V(SINGLE_CHARACTER_STRING_CACHE_SUB_TYPE) \ 54 V(SLOW_TEMPLATE_INSTANTIATIONS_CACHE_SUB_TYPE) \ 55 V(STRING_SPLIT_CACHE_SUB_TYPE) \ 56 V(TEMPLATE_INFO_SUB_TYPE) \ 57 V(FEEDBACK_METADATA_SUB_TYPE) \ 58 V(WEAK_NEW_SPACE_OBJECT_TO_CODE_SUB_TYPE) 59 60 enum FixedArraySubInstanceType { 61 #define DEFINE_FIXED_ARRAY_SUB_INSTANCE_TYPE(name) name, 62 FIXED_ARRAY_SUB_INSTANCE_TYPE_LIST(DEFINE_FIXED_ARRAY_SUB_INSTANCE_TYPE) 63 #undef DEFINE_FIXED_ARRAY_SUB_INSTANCE_TYPE 64 LAST_FIXED_ARRAY_SUB_TYPE = WEAK_NEW_SPACE_OBJECT_TO_CODE_SUB_TYPE 65 }; 66 67 #include "torque-generated/src/objects/fixed-array-tq.inc" 68 69 // Common superclass for FixedArrays that allow implementations to share 70 // common accessors and some code paths. 71 class FixedArrayBase 72 : public TorqueGeneratedFixedArrayBase<FixedArrayBase, HeapObject> { 73 public: 74 // Forward declare the non-atomic (set_)length defined in torque. 75 using TorqueGeneratedFixedArrayBase::length; 76 using TorqueGeneratedFixedArrayBase::set_length; 77 DECL_RELEASE_ACQUIRE_INT_ACCESSORS(length) 78 79 inline Object unchecked_length(AcquireLoadTag) const; 80 81 static int GetMaxLengthForNewSpaceAllocation(ElementsKind kind); 82 83 V8_EXPORT_PRIVATE bool IsCowArray() const; 84 85 // Maximal allowed size, in bytes, of a single FixedArrayBase. 86 // Prevents overflowing size computations, as well as extreme memory 87 // consumption. It's either (512Mb - kTaggedSize) or (1024Mb - kTaggedSize). 88 // -kTaggedSize is here to ensure that this max size always fits into Smi 89 // which is necessary for being able to create a free space filler for the 90 // whole array of kMaxSize. 91 static const int kMaxSize = 128 * kTaggedSize * MB - kTaggedSize; 92 STATIC_ASSERT(Smi::IsValid(kMaxSize)); 93 94 protected: 95 TQ_OBJECT_CONSTRUCTORS(FixedArrayBase) 96 inline FixedArrayBase(Address ptr, 97 HeapObject::AllowInlineSmiStorage allow_smi); 98 }; 99 100 // FixedArray describes fixed-sized arrays with element type Object. 101 class FixedArray 102 : public TorqueGeneratedFixedArray<FixedArray, FixedArrayBase> { 103 public: 104 // Setter and getter for elements. 105 inline Object get(int index) const; 106 inline Object get(PtrComprCageBase cage_base, int index) const; 107 108 static inline Handle<Object> get(FixedArray array, int index, 109 Isolate* isolate); 110 111 // Return a grown copy if the index is bigger than the array's length. 112 V8_EXPORT_PRIVATE static Handle<FixedArray> SetAndGrow( 113 Isolate* isolate, Handle<FixedArray> array, int index, 114 Handle<Object> value); 115 116 // Relaxed accessors. 117 inline Object get(int index, RelaxedLoadTag) const; 118 inline Object get(PtrComprCageBase cage_base, int index, 119 RelaxedLoadTag) const; 120 inline void set(int index, Object value, RelaxedStoreTag, 121 WriteBarrierMode mode = UPDATE_WRITE_BARRIER); 122 inline void set(int index, Smi value, RelaxedStoreTag); 123 124 // Acquire/release accessors. 125 inline Object get(int index, AcquireLoadTag) const; 126 inline Object get(PtrComprCageBase cage_base, int index, 127 AcquireLoadTag) const; 128 inline void set(int index, Object value, ReleaseStoreTag, 129 WriteBarrierMode mode = UPDATE_WRITE_BARRIER); 130 inline void set(int index, Smi value, ReleaseStoreTag); 131 132 // Setter that uses write barrier. 133 inline void set(int index, Object value); 134 inline bool is_the_hole(Isolate* isolate, int index); 135 136 // Setter that doesn't need write barrier. 137 #if !defined(_WIN32) || (defined(_WIN64) && _MSC_VER < 1930 && __cplusplus < 201703L) 138 inline void set(int index, Smi value); 139 #else set(int index,Smi value)140 inline void set(int index, Smi value) { 141 #if !defined(_WIN32) 142 DCHECK_NE(map(), GetReadOnlyRoots().fixed_cow_array_map()); 143 #endif 144 DCHECK_LT(static_cast<unsigned>(index), static_cast<unsigned>(length())); 145 DCHECK(Object(value).IsSmi()); 146 int offset = OffsetOfElementAt(index); 147 RELAXED_WRITE_FIELD(*this, offset, value); 148 } 149 #endif 150 151 // Setter with explicit barrier mode. 152 inline void set(int index, Object value, WriteBarrierMode mode); 153 154 // Setters for frequently used oddballs located in old space. 155 inline void set_undefined(int index); 156 inline void set_undefined(Isolate* isolate, int index); 157 inline void set_undefined(ReadOnlyRoots ro_roots, int index); 158 inline void set_null(int index); 159 inline void set_null(Isolate* isolate, int index); 160 inline void set_null(ReadOnlyRoots ro_roots, int index); 161 inline void set_the_hole(int index); 162 inline void set_the_hole(Isolate* isolate, int index); 163 inline void set_the_hole(ReadOnlyRoots ro_roots, int index); 164 165 inline ObjectSlot GetFirstElementAddress(); 166 inline bool ContainsOnlySmisOrHoles(); 167 168 // Gives access to raw memory which stores the array's data. 169 inline ObjectSlot data_start(); 170 171 inline void MoveElements(Isolate* isolate, int dst_index, int src_index, 172 int len, WriteBarrierMode mode); 173 174 inline void CopyElements(Isolate* isolate, int dst_index, FixedArray src, 175 int src_index, int len, WriteBarrierMode mode); 176 177 inline void FillWithHoles(int from, int to); 178 179 // Shrink the array and insert filler objects. {new_length} must be > 0. 180 V8_EXPORT_PRIVATE void Shrink(Isolate* isolate, int new_length); 181 // If {new_length} is 0, return the canonical empty FixedArray. Otherwise 182 // like above. 183 static Handle<FixedArray> ShrinkOrEmpty(Isolate* isolate, 184 Handle<FixedArray> array, 185 int new_length); 186 187 // Copy a sub array from the receiver to dest. 188 V8_EXPORT_PRIVATE void CopyTo(int pos, FixedArray dest, int dest_pos, 189 int len) const; 190 191 // Garbage collection support. SizeFor(int length)192 static constexpr int SizeFor(int length) { 193 return kHeaderSize + length * kTaggedSize; 194 } 195 196 // Code Generation support. OffsetOfElementAt(int index)197 static constexpr int OffsetOfElementAt(int index) { 198 STATIC_ASSERT(kObjectsOffset == SizeFor(0)); 199 return SizeFor(index); 200 } 201 202 // Garbage collection support. 203 inline ObjectSlot RawFieldOfElementAt(int index); 204 205 // Maximally allowed length of a FixedArray. 206 static const int kMaxLength = (kMaxSize - kHeaderSize) / kTaggedSize; 207 static_assert(Internals::IsValidSmi(kMaxLength), 208 "FixedArray maxLength not a Smi"); 209 210 // Maximally allowed length for regular (non large object space) object. 211 STATIC_ASSERT(kMaxRegularHeapObjectSize < kMaxSize); 212 static const int kMaxRegularLength = 213 (kMaxRegularHeapObjectSize - kHeaderSize) / kTaggedSize; 214 215 // Dispatched behavior. 216 DECL_PRINTER(FixedArray) 217 DECL_VERIFIER(FixedArray) 218 219 int AllocatedSize(); 220 221 class BodyDescriptor; 222 223 static constexpr int kObjectsOffset = kHeaderSize; 224 225 protected: 226 // Set operation on FixedArray without using write barriers. Can 227 // only be used for storing old space objects or smis. 228 static inline void NoWriteBarrierSet(FixedArray array, int index, 229 Object value); 230 231 private: 232 STATIC_ASSERT(kHeaderSize == Internals::kFixedArrayHeaderSize); 233 234 TQ_OBJECT_CONSTRUCTORS(FixedArray) 235 }; 236 237 // FixedArray alias added only because of IsFixedArrayExact() predicate, which 238 // checks for the exact instance type FIXED_ARRAY_TYPE instead of a range 239 // check: [FIRST_FIXED_ARRAY_TYPE, LAST_FIXED_ARRAY_TYPE]. 240 class FixedArrayExact final : public FixedArray {}; 241 242 // FixedDoubleArray describes fixed-sized arrays with element type double. 243 class FixedDoubleArray 244 : public TorqueGeneratedFixedDoubleArray<FixedDoubleArray, FixedArrayBase> { 245 public: 246 // Setter and getter for elements. 247 inline double get_scalar(int index); 248 inline uint64_t get_representation(int index); 249 static inline Handle<Object> get(FixedDoubleArray array, int index, 250 Isolate* isolate); 251 inline void set(int index, double value); 252 inline void set_the_hole(Isolate* isolate, int index); 253 inline void set_the_hole(int index); 254 255 // Checking for the hole. 256 inline bool is_the_hole(Isolate* isolate, int index); 257 inline bool is_the_hole(int index); 258 259 // Garbage collection support. SizeFor(int length)260 inline static int SizeFor(int length) { 261 return kHeaderSize + length * kDoubleSize; 262 } 263 264 inline void MoveElements(Isolate* isolate, int dst_index, int src_index, 265 int len, WriteBarrierMode mode); 266 267 inline void FillWithHoles(int from, int to); 268 269 // Code Generation support. OffsetOfElementAt(int index)270 static int OffsetOfElementAt(int index) { return SizeFor(index); } 271 272 // Start offset of elements. 273 static constexpr int kFloatsOffset = kHeaderSize; 274 275 // Maximally allowed length of a FixedDoubleArray. 276 static const int kMaxLength = (kMaxSize - kHeaderSize) / kDoubleSize; 277 static_assert(Internals::IsValidSmi(kMaxLength), 278 "FixedDoubleArray maxLength not a Smi"); 279 280 // Dispatched behavior. 281 DECL_PRINTER(FixedDoubleArray) 282 DECL_VERIFIER(FixedDoubleArray) 283 284 class BodyDescriptor; 285 286 TQ_OBJECT_CONSTRUCTORS(FixedDoubleArray) 287 }; 288 289 // WeakFixedArray describes fixed-sized arrays with element type 290 // MaybeObject. 291 class WeakFixedArray 292 : public TorqueGeneratedWeakFixedArray<WeakFixedArray, HeapObject> { 293 public: 294 inline MaybeObject Get(int index) const; 295 inline MaybeObject Get(PtrComprCageBase cage_base, int index) const; 296 297 inline void Set( 298 int index, MaybeObject value, 299 WriteBarrierMode mode = WriteBarrierMode::UPDATE_WRITE_BARRIER); 300 301 static inline Handle<WeakFixedArray> EnsureSpace(Isolate* isolate, 302 Handle<WeakFixedArray> array, 303 int length); 304 305 // Forward declare the non-atomic (set_)length defined in torque. 306 using TorqueGeneratedWeakFixedArray::length; 307 using TorqueGeneratedWeakFixedArray::set_length; 308 DECL_RELEASE_ACQUIRE_INT_ACCESSORS(length) 309 310 // Gives access to raw memory which stores the array's data. 311 inline MaybeObjectSlot data_start(); 312 313 inline MaybeObjectSlot RawFieldOfElementAt(int index); 314 315 inline void CopyElements(Isolate* isolate, int dst_index, WeakFixedArray src, 316 int src_index, int len, WriteBarrierMode mode); 317 318 DECL_PRINTER(WeakFixedArray) 319 DECL_VERIFIER(WeakFixedArray) 320 321 class BodyDescriptor; 322 323 static const int kMaxLength = 324 (FixedArray::kMaxSize - kHeaderSize) / kTaggedSize; 325 static_assert(Internals::IsValidSmi(kMaxLength), 326 "WeakFixedArray maxLength not a Smi"); 327 328 int AllocatedSize(); 329 OffsetOfElementAt(int index)330 static int OffsetOfElementAt(int index) { 331 STATIC_ASSERT(kObjectsOffset == SizeFor(0)); 332 return SizeFor(index); 333 } 334 335 private: 336 friend class Heap; 337 338 static const int kFirstIndex = 1; 339 340 TQ_OBJECT_CONSTRUCTORS(WeakFixedArray) 341 }; 342 343 // WeakArrayList is like a WeakFixedArray with static convenience methods for 344 // adding more elements. length() returns the number of elements in the list and 345 // capacity() returns the allocated size. The number of elements is stored at 346 // kLengthOffset and is updated with every insertion. The array grows 347 // dynamically with O(1) amortized insertion. 348 class WeakArrayList 349 : public TorqueGeneratedWeakArrayList<WeakArrayList, HeapObject> { 350 public: 351 NEVER_READ_ONLY_SPACE 352 DECL_PRINTER(WeakArrayList) 353 354 V8_EXPORT_PRIVATE static Handle<WeakArrayList> AddToEnd( 355 Isolate* isolate, Handle<WeakArrayList> array, 356 const MaybeObjectHandle& value); 357 358 // A version that adds to elements. This ensures that the elements are 359 // inserted atomically w.r.t GC. 360 V8_EXPORT_PRIVATE static Handle<WeakArrayList> AddToEnd( 361 Isolate* isolate, Handle<WeakArrayList> array, 362 const MaybeObjectHandle& value1, const MaybeObjectHandle& value2); 363 364 // Appends an element to the array and possibly compacts and shrinks live weak 365 // references to the start of the collection. Only use this method when 366 // indices to elements can change. 367 static Handle<WeakArrayList> Append( 368 Isolate* isolate, Handle<WeakArrayList> array, 369 const MaybeObjectHandle& value, 370 AllocationType allocation = AllocationType::kYoung); 371 372 // Compact weak references to the beginning of the array. 373 V8_EXPORT_PRIVATE void Compact(Isolate* isolate); 374 375 inline MaybeObject Get(int index) const; 376 inline MaybeObject Get(PtrComprCageBase cage_base, int index) const; 377 378 // Set the element at index to obj. The underlying array must be large enough. 379 // If you need to grow the WeakArrayList, use the static AddToEnd() method 380 // instead. 381 inline void Set(int index, MaybeObject value, 382 WriteBarrierMode mode = UPDATE_WRITE_BARRIER); 383 inline void Set(int index, Smi value); 384 SizeForCapacity(int capacity)385 static constexpr int SizeForCapacity(int capacity) { 386 return SizeFor(capacity); 387 } 388 CapacityForLength(int length)389 static constexpr int CapacityForLength(int length) { 390 return length + std::max(length / 2, 2); 391 } 392 393 // Gives access to raw memory which stores the array's data. 394 inline MaybeObjectSlot data_start(); 395 396 inline void CopyElements(Isolate* isolate, int dst_index, WeakArrayList src, 397 int src_index, int len, WriteBarrierMode mode); 398 399 V8_EXPORT_PRIVATE bool IsFull() const; 400 401 int AllocatedSize(); 402 403 class BodyDescriptor; 404 405 static const int kMaxCapacity = 406 (FixedArray::kMaxSize - kHeaderSize) / kTaggedSize; 407 408 static Handle<WeakArrayList> EnsureSpace( 409 Isolate* isolate, Handle<WeakArrayList> array, int length, 410 AllocationType allocation = AllocationType::kYoung); 411 412 // Returns the number of non-cleaned weak references in the array. 413 int CountLiveWeakReferences() const; 414 415 // Returns the number of non-cleaned elements in the array. 416 int CountLiveElements() const; 417 418 // Returns whether an entry was found and removed. Will move the elements 419 // around in the array - this method can only be used in cases where the user 420 // doesn't care about the indices! Users should make sure there are no 421 // duplicates. 422 V8_EXPORT_PRIVATE bool RemoveOne(const MaybeObjectHandle& value); 423 424 class Iterator; 425 426 private: OffsetOfElementAt(int index)427 static int OffsetOfElementAt(int index) { 428 return kHeaderSize + index * kTaggedSize; 429 } 430 431 TQ_OBJECT_CONSTRUCTORS(WeakArrayList) 432 }; 433 434 class WeakArrayList::Iterator { 435 public: Iterator(WeakArrayList array)436 explicit Iterator(WeakArrayList array) : index_(0), array_(array) {} 437 Iterator(const Iterator&) = delete; 438 Iterator& operator=(const Iterator&) = delete; 439 440 inline HeapObject Next(); 441 442 private: 443 int index_; 444 WeakArrayList array_; 445 DISALLOW_GARBAGE_COLLECTION(no_gc_) 446 }; 447 448 // Generic array grows dynamically with O(1) amortized insertion. 449 // 450 // ArrayList is a FixedArray with static convenience methods for adding more 451 // elements. The Length() method returns the number of elements in the list, not 452 // the allocated size. The number of elements is stored at kLengthIndex and is 453 // updated with every insertion. The elements of the ArrayList are stored in the 454 // underlying FixedArray starting at kFirstIndex. 455 class ArrayList : public TorqueGeneratedArrayList<ArrayList, FixedArray> { 456 public: 457 V8_EXPORT_PRIVATE static Handle<ArrayList> Add(Isolate* isolate, 458 Handle<ArrayList> array, 459 Handle<Object> obj); 460 V8_EXPORT_PRIVATE static Handle<ArrayList> Add(Isolate* isolate, 461 Handle<ArrayList> array, 462 Handle<Object> obj1, 463 Handle<Object> obj2); 464 V8_EXPORT_PRIVATE static Handle<ArrayList> Add(Isolate* isolate, 465 Handle<ArrayList> array, 466 Handle<Object> obj1, Smi obj2, 467 Smi obj3, Smi obj4); 468 static Handle<ArrayList> New(Isolate* isolate, int size); 469 470 // Returns the number of elements in the list, not the allocated size, which 471 // is length(). Lower and upper case length() return different results! 472 inline int Length() const; 473 474 // Sets the Length() as used by Elements(). Does not change the underlying 475 // storage capacity, i.e., length(). 476 inline void SetLength(int length); 477 inline Object Get(int index) const; 478 inline Object Get(PtrComprCageBase cage_base, int index) const; 479 inline ObjectSlot Slot(int index); 480 481 // Set the element at index to obj. The underlying array must be large enough. 482 // If you need to grow the ArrayList, use the static Add() methods instead. 483 inline void Set(int index, Object obj, 484 WriteBarrierMode mode = UPDATE_WRITE_BARRIER); 485 486 inline void Set(int index, Smi obj); 487 488 // Set the element at index to undefined. This does not change the Length(). 489 inline void Clear(int index, Object undefined); 490 491 // Return a copy of the list of size Length() without the first entry. The 492 // number returned by Length() is stored in the first entry. 493 static Handle<FixedArray> Elements(Isolate* isolate, Handle<ArrayList> array); 494 495 static const int kHeaderFields = 1; 496 497 static const int kLengthIndex = 0; 498 static const int kFirstIndex = 1; 499 STATIC_ASSERT(kHeaderFields == kFirstIndex); 500 501 DECL_VERIFIER(ArrayList) 502 503 private: 504 static Handle<ArrayList> EnsureSpace(Isolate* isolate, 505 Handle<ArrayList> array, int length); 506 TQ_OBJECT_CONSTRUCTORS(ArrayList) 507 }; 508 509 enum SearchMode { ALL_ENTRIES, VALID_ENTRIES }; 510 511 template <SearchMode search_mode, typename T> 512 inline int Search(T* array, Name name, int valid_entries = 0, 513 int* out_insertion_index = nullptr, 514 bool concurrent_search = false); 515 516 // ByteArray represents fixed sized byte arrays. Used for the relocation info 517 // that is attached to code objects. 518 class ByteArray : public TorqueGeneratedByteArray<ByteArray, FixedArrayBase> { 519 public: 520 inline int Size(); 521 522 // Setter and getter. 523 inline byte get(int index) const; 524 inline void set(int index, byte value); 525 526 // Copy in / copy out whole byte slices. 527 inline void copy_out(int index, byte* buffer, int slice_length); 528 inline void copy_in(int index, const byte* buffer, int slice_length); 529 530 // Treat contents as an int array. 531 inline int get_int(int index) const; 532 inline void set_int(int index, int value); 533 534 inline uint32_t get_uint32(int index) const; 535 inline void set_uint32(int index, uint32_t value); 536 537 inline uint32_t get_uint32_relaxed(int index) const; 538 inline void set_uint32_relaxed(int index, uint32_t value); 539 540 inline uint16_t get_uint16(int index) const; 541 inline void set_uint16(int index, uint16_t value); 542 543 // Clear uninitialized padding space. This ensures that the snapshot content 544 // is deterministic. 545 inline void clear_padding(); 546 SizeFor(int length)547 static int SizeFor(int length) { 548 return OBJECT_POINTER_ALIGN(kHeaderSize + length); 549 } 550 // We use byte arrays for free blocks in the heap. Given a desired size in 551 // bytes that is a multiple of the word size and big enough to hold a byte 552 // array, this function returns the number of elements a byte array should 553 // have. LengthFor(int size_in_bytes)554 static int LengthFor(int size_in_bytes) { 555 DCHECK(IsAligned(size_in_bytes, kTaggedSize)); 556 DCHECK_GE(size_in_bytes, kHeaderSize); 557 return size_in_bytes - kHeaderSize; 558 } 559 560 // Returns data start address. 561 inline byte* GetDataStartAddress(); 562 // Returns address of the past-the-end element. 563 inline byte* GetDataEndAddress(); 564 565 inline int DataSize() const; 566 567 // Returns a pointer to the ByteArray object for a given data start address. 568 static inline ByteArray FromDataStartAddress(Address address); 569 570 // Dispatched behavior. 571 inline int ByteArraySize(); 572 DECL_PRINTER(ByteArray) 573 574 // Layout description. 575 static const int kAlignedSize = OBJECT_POINTER_ALIGN(kHeaderSize); 576 577 // Maximal length of a single ByteArray. 578 static const int kMaxLength = kMaxSize - kHeaderSize; 579 static_assert(Internals::IsValidSmi(kMaxLength), 580 "ByteArray maxLength not a Smi"); 581 582 class BodyDescriptor; 583 584 protected: 585 TQ_OBJECT_CONSTRUCTORS(ByteArray) 586 inline ByteArray(Address ptr, HeapObject::AllowInlineSmiStorage allow_smi); 587 }; 588 589 // Wrapper class for ByteArray which can store arbitrary C++ classes, as long 590 // as they can be copied with memcpy. 591 template <class T> 592 class PodArray : public ByteArray { 593 public: 594 static Handle<PodArray<T>> New( 595 Isolate* isolate, int length, 596 AllocationType allocation = AllocationType::kYoung); copy_out(int index,T * result,int length)597 void copy_out(int index, T* result, int length) { 598 ByteArray::copy_out(index * sizeof(T), reinterpret_cast<byte*>(result), 599 length * sizeof(T)); 600 } 601 copy_in(int index,const T * buffer,int length)602 void copy_in(int index, const T* buffer, int length) { 603 ByteArray::copy_in(index * sizeof(T), reinterpret_cast<const byte*>(buffer), 604 length * sizeof(T)); 605 } 606 matches(const T * buffer,int length)607 bool matches(const T* buffer, int length) { 608 DCHECK_LE(length, this->length()); 609 return memcmp(GetDataStartAddress(), buffer, length * sizeof(T)) == 0; 610 } 611 matches(int offset,const T * buffer,int length)612 bool matches(int offset, const T* buffer, int length) { 613 DCHECK_LE(offset, this->length()); 614 DCHECK_LE(offset + length, this->length()); 615 return memcmp(GetDataStartAddress() + sizeof(T) * offset, buffer, 616 length * sizeof(T)) == 0; 617 } 618 get(int index)619 T get(int index) { 620 T result; 621 copy_out(index, &result, 1); 622 return result; 623 } 624 set(int index,const T & value)625 void set(int index, const T& value) { copy_in(index, &value, 1); } 626 627 inline int length() const; 628 DECL_CAST(PodArray<T>) 629 630 OBJECT_CONSTRUCTORS(PodArray<T>, ByteArray); 631 }; 632 633 class TemplateList 634 : public TorqueGeneratedTemplateList<TemplateList, FixedArray> { 635 public: 636 static Handle<TemplateList> New(Isolate* isolate, int size); 637 inline int length() const; 638 inline Object get(int index) const; 639 inline Object get(PtrComprCageBase cage_base, int index) const; 640 inline void set(int index, Object value); 641 static Handle<TemplateList> Add(Isolate* isolate, Handle<TemplateList> list, 642 Handle<Object> value); 643 private: 644 static const int kLengthIndex = 0; 645 static const int kFirstElementIndex = kLengthIndex + 1; 646 647 TQ_OBJECT_CONSTRUCTORS(TemplateList) 648 }; 649 650 } // namespace internal 651 } // namespace v8 652 653 #include "src/objects/object-macros-undef.h" 654 655 #endif // V8_OBJECTS_FIXED_ARRAY_H_ 656