1// Copyright 2015 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_OBJECTS_BODY_DESCRIPTORS_INL_H_ 6#define V8_OBJECTS_OBJECTS_BODY_DESCRIPTORS_INL_H_ 7 8#include <algorithm> 9 10#include "src/codegen/reloc-info.h" 11#include "src/ic/handler-configuration.h" 12#include "src/objects/arguments-inl.h" 13#include "src/objects/bigint.h" 14#include "src/objects/call-site-info.h" 15#include "src/objects/cell.h" 16#include "src/objects/data-handler.h" 17#include "src/objects/embedder-data-array-inl.h" 18#include "src/objects/fixed-array.h" 19#include "src/objects/foreign-inl.h" 20#include "src/objects/free-space-inl.h" 21#include "src/objects/hash-table.h" 22#include "src/objects/heap-number.h" 23#include "src/objects/js-collection.h" 24#include "src/objects/js-weak-refs.h" 25#include "src/objects/literal-objects.h" 26#include "src/objects/megadom-handler-inl.h" 27#include "src/objects/objects-body-descriptors.h" 28#include "src/objects/ordered-hash-table-inl.h" 29#include "src/objects/property-descriptor-object.h" 30#include "src/objects/source-text-module.h" 31#include "src/objects/swiss-name-dictionary-inl.h" 32#include "src/objects/synthetic-module.h" 33#include "src/objects/template-objects.h" 34#include "src/objects/torque-defined-classes-inl.h" 35#include "src/objects/transitions.h" 36#include "src/objects/turbofan-types-inl.h" 37 38#if V8_ENABLE_WEBASSEMBLY 39#include "src/wasm/wasm-objects-inl.h" 40#endif // V8_ENABLE_WEBASSEMBLY 41 42namespace v8 { 43namespace internal { 44 45template <int start_offset> 46int FlexibleBodyDescriptor<start_offset>::SizeOf(Map map, HeapObject object) { 47 return object.SizeFromMap(map); 48} 49 50template <int start_offset> 51int FlexibleWeakBodyDescriptor<start_offset>::SizeOf(Map map, 52 HeapObject object) { 53 return object.SizeFromMap(map); 54} 55 56bool BodyDescriptorBase::IsValidJSObjectSlotImpl(Map map, HeapObject obj, 57 int offset) { 58#ifdef V8_COMPRESS_POINTERS 59 STATIC_ASSERT(kEmbedderDataSlotSize == 2 * kTaggedSize); 60 int embedder_fields_offset = JSObject::GetEmbedderFieldsStartOffset(map); 61 int inobject_fields_offset = map.GetInObjectPropertyOffset(0); 62 // |embedder_fields_offset| may be greater than |inobject_fields_offset| if 63 // the object does not have embedder fields but the check handles this 64 // case properly. 65 if (embedder_fields_offset <= offset && offset < inobject_fields_offset) { 66 // offset points to embedder fields area: 67 // [embedder_fields_offset, inobject_fields_offset). 68 STATIC_ASSERT(base::bits::IsPowerOfTwo(kEmbedderDataSlotSize)); 69 return ((offset - embedder_fields_offset) & (kEmbedderDataSlotSize - 1)) == 70 EmbedderDataSlot::kTaggedPayloadOffset; 71 } 72#else 73 // We store raw aligned pointers as Smis, so it's safe to treat the whole 74 // embedder field area as tagged slots. 75 STATIC_ASSERT(kEmbedderDataSlotSize == kTaggedSize); 76#endif 77 return true; 78} 79 80template <typename ObjectVisitor> 81void BodyDescriptorBase::IterateJSObjectBodyImpl(Map map, HeapObject obj, 82 int start_offset, 83 int end_offset, 84 ObjectVisitor* v) { 85#ifdef V8_COMPRESS_POINTERS 86 STATIC_ASSERT(kEmbedderDataSlotSize == 2 * kTaggedSize); 87 int header_end_offset = JSObject::GetHeaderSize(map); 88 int inobject_fields_start_offset = map.GetInObjectPropertyOffset(0); 89 // We are always requested to process header and embedder fields. 90 DCHECK_LE(inobject_fields_start_offset, end_offset); 91 // Embedder fields are located between header and inobject properties. 92 if (header_end_offset < inobject_fields_start_offset) { 93 // There are embedder fields. 94 DCHECK_EQ(header_end_offset, JSObject::GetEmbedderFieldsStartOffset(map)); 95 IteratePointers(obj, start_offset, header_end_offset, v); 96 for (int offset = header_end_offset; offset < inobject_fields_start_offset; 97 offset += kEmbedderDataSlotSize) { 98 IteratePointer(obj, offset + EmbedderDataSlot::kTaggedPayloadOffset, v); 99 v->VisitExternalPointer( 100 obj, obj.RawExternalPointerField( 101 offset + EmbedderDataSlot::kExternalPointerOffset)); 102 } 103 // Proceed processing inobject properties. 104 start_offset = inobject_fields_start_offset; 105 } 106#else 107 // We store raw aligned pointers as Smis, so it's safe to iterate the whole 108 // embedder field area as tagged slots. 109 STATIC_ASSERT(kEmbedderDataSlotSize == kTaggedSize); 110#endif 111 IteratePointers(obj, start_offset, end_offset, v); 112} 113 114template <typename ObjectVisitor> 115DISABLE_CFI_PERF void BodyDescriptorBase::IteratePointers(HeapObject obj, 116 int start_offset, 117 int end_offset, 118 ObjectVisitor* v) { 119 if (start_offset == HeapObject::kMapOffset) { 120 v->VisitMapPointer(obj); 121 start_offset += kTaggedSize; 122 } 123 v->VisitPointers(obj, obj.RawField(start_offset), obj.RawField(end_offset)); 124} 125 126template <typename ObjectVisitor> 127void BodyDescriptorBase::IteratePointer(HeapObject obj, int offset, 128 ObjectVisitor* v) { 129 DCHECK_NE(offset, HeapObject::kMapOffset); 130 v->VisitPointer(obj, obj.RawField(offset)); 131} 132 133template <typename ObjectVisitor> 134DISABLE_CFI_PERF void BodyDescriptorBase::IterateMaybeWeakPointers( 135 HeapObject obj, int start_offset, int end_offset, ObjectVisitor* v) { 136 v->VisitPointers(obj, obj.RawMaybeWeakField(start_offset), 137 obj.RawMaybeWeakField(end_offset)); 138} 139 140template <typename ObjectVisitor> 141void BodyDescriptorBase::IterateMaybeWeakPointer(HeapObject obj, int offset, 142 ObjectVisitor* v) { 143 DCHECK_NE(offset, HeapObject::kMapOffset); 144 v->VisitPointer(obj, obj.RawMaybeWeakField(offset)); 145} 146 147template <typename ObjectVisitor> 148DISABLE_CFI_PERF void BodyDescriptorBase::IterateCustomWeakPointers( 149 HeapObject obj, int start_offset, int end_offset, ObjectVisitor* v) { 150 v->VisitCustomWeakPointers(obj, obj.RawField(start_offset), 151 obj.RawField(end_offset)); 152} 153 154template <typename ObjectVisitor> 155DISABLE_CFI_PERF void BodyDescriptorBase::IterateEphemeron(HeapObject obj, 156 int index, 157 int key_offset, 158 int value_offset, 159 ObjectVisitor* v) { 160 v->VisitEphemeron(obj, index, obj.RawField(key_offset), 161 obj.RawField(value_offset)); 162} 163 164template <typename ObjectVisitor> 165void BodyDescriptorBase::IterateCustomWeakPointer(HeapObject obj, int offset, 166 ObjectVisitor* v) { 167 v->VisitCustomWeakPointer(obj, obj.RawField(offset)); 168} 169 170class HeapNumber::BodyDescriptor final : public BodyDescriptorBase { 171 public: 172 static bool IsValidSlot(Map map, HeapObject obj, int offset) { return false; } 173 174 template <typename ObjectVisitor> 175 static inline void IterateBody(Map map, HeapObject obj, int object_size, 176 ObjectVisitor* v) {} 177 178 static inline int SizeOf(Map map, HeapObject object) { 179 return HeapNumber::kSize; 180 } 181}; 182 183// This is a descriptor for one/two pointer fillers. 184class FreeSpaceFillerBodyDescriptor final : public DataOnlyBodyDescriptor { 185 public: 186 static inline int SizeOf(Map map, HeapObject raw_object) { 187 return map.instance_size(); 188 } 189}; 190 191class FreeSpace::BodyDescriptor final : public DataOnlyBodyDescriptor { 192 public: 193 static inline int SizeOf(Map map, HeapObject raw_object) { 194 return FreeSpace::unchecked_cast(raw_object).Size(); 195 } 196}; 197 198class JSObject::BodyDescriptor final : public BodyDescriptorBase { 199 public: 200 static const int kStartOffset = JSReceiver::kPropertiesOrHashOffset; 201 202 static bool IsValidSlot(Map map, HeapObject obj, int offset) { 203 if (offset < kStartOffset) return false; 204 return IsValidJSObjectSlotImpl(map, obj, offset); 205 } 206 207 template <typename ObjectVisitor> 208 static inline void IterateBody(Map map, HeapObject obj, int object_size, 209 ObjectVisitor* v) { 210 IterateJSObjectBodyImpl(map, obj, kStartOffset, object_size, v); 211 } 212 213 static inline int SizeOf(Map map, HeapObject object) { 214 return map.instance_size(); 215 } 216}; 217 218class JSObject::FastBodyDescriptor final : public BodyDescriptorBase { 219 public: 220 static const int kStartOffset = JSReceiver::kPropertiesOrHashOffset; 221 222 static bool IsValidSlot(Map map, HeapObject obj, int offset) { 223 return offset >= kStartOffset; 224 } 225 226 template <typename ObjectVisitor> 227 static inline void IterateBody(Map map, HeapObject obj, int object_size, 228 ObjectVisitor* v) { 229 IteratePointers(obj, kStartOffset, object_size, v); 230 } 231 232 static inline int SizeOf(Map map, HeapObject object) { 233 return map.instance_size(); 234 } 235}; 236 237class WeakCell::BodyDescriptor final : public BodyDescriptorBase { 238 public: 239 static bool IsValidSlot(Map map, HeapObject obj, int offset) { 240 return offset >= HeapObject::kHeaderSize; 241 } 242 243 template <typename ObjectVisitor> 244 static inline void IterateBody(Map map, HeapObject obj, int object_size, 245 ObjectVisitor* v) { 246 IteratePointers(obj, HeapObject::kHeaderSize, kTargetOffset, v); 247 IterateCustomWeakPointer(obj, kTargetOffset, v); 248 IterateCustomWeakPointer(obj, kUnregisterTokenOffset, v); 249 IteratePointers(obj, kUnregisterTokenOffset + kTaggedSize, object_size, v); 250 } 251 252 static inline int SizeOf(Map map, HeapObject object) { 253 return map.instance_size(); 254 } 255}; 256 257class JSWeakRef::BodyDescriptor final : public BodyDescriptorBase { 258 public: 259 static bool IsValidSlot(Map map, HeapObject obj, int offset) { 260 return IsValidJSObjectSlotImpl(map, obj, offset); 261 } 262 263 template <typename ObjectVisitor> 264 static inline void IterateBody(Map map, HeapObject obj, int object_size, 265 ObjectVisitor* v) { 266 IteratePointers(obj, JSReceiver::kPropertiesOrHashOffset, kTargetOffset, v); 267 IterateCustomWeakPointer(obj, kTargetOffset, v); 268 IterateJSObjectBodyImpl(map, obj, kTargetOffset + kTaggedSize, object_size, 269 v); 270 } 271 272 static inline int SizeOf(Map map, HeapObject object) { 273 return map.instance_size(); 274 } 275}; 276 277class JSFinalizationRegistry::BodyDescriptor final : public BodyDescriptorBase { 278 public: 279 static bool IsValidSlot(Map map, HeapObject obj, int offset) { 280 return IsValidJSObjectSlotImpl(map, obj, offset); 281 } 282 283 template <typename ObjectVisitor> 284 static inline void IterateBody(Map map, HeapObject obj, int object_size, 285 ObjectVisitor* v) { 286 IteratePointers(obj, JSObject::BodyDescriptor::kStartOffset, 287 kNextDirtyOffset, v); 288 IterateCustomWeakPointer(obj, kNextDirtyOffset, v); 289 IterateJSObjectBodyImpl(map, obj, kNextDirtyOffset + kTaggedSize, 290 object_size, v); 291 } 292 293 static inline int SizeOf(Map map, HeapObject object) { 294 return map.instance_size(); 295 } 296}; 297 298class AllocationSite::BodyDescriptor final : public BodyDescriptorBase { 299 public: 300 STATIC_ASSERT(AllocationSite::kCommonPointerFieldEndOffset == 301 AllocationSite::kPretenureDataOffset); 302 STATIC_ASSERT(AllocationSite::kPretenureDataOffset + kInt32Size == 303 AllocationSite::kPretenureCreateCountOffset); 304 STATIC_ASSERT(AllocationSite::kPretenureCreateCountOffset + kInt32Size == 305 AllocationSite::kWeakNextOffset); 306 307 static bool IsValidSlot(Map map, HeapObject obj, int offset) { 308 if (offset >= AllocationSite::kStartOffset && 309 offset < AllocationSite::kCommonPointerFieldEndOffset) { 310 return true; 311 } 312 // check for weak_next offset 313 if (map.instance_size() == AllocationSite::kSizeWithWeakNext && 314 offset == AllocationSite::kWeakNextOffset) { 315 return true; 316 } 317 return false; 318 } 319 320 template <typename ObjectVisitor> 321 static inline void IterateBody(Map map, HeapObject obj, int object_size, 322 ObjectVisitor* v) { 323 // Iterate over all the common pointer fields 324 IteratePointers(obj, AllocationSite::kStartOffset, 325 AllocationSite::kCommonPointerFieldEndOffset, v); 326 // Skip PretenureDataOffset and PretenureCreateCount which are Int32 fields. 327 // Visit weak_next only if it has weak_next field. 328 if (object_size == AllocationSite::kSizeWithWeakNext) { 329 IterateCustomWeakPointers(obj, AllocationSite::kWeakNextOffset, 330 AllocationSite::kSizeWithWeakNext, v); 331 } 332 } 333 334 static inline int SizeOf(Map map, HeapObject object) { 335 return map.instance_size(); 336 } 337}; 338 339class JSFunction::BodyDescriptor final : public BodyDescriptorBase { 340 public: 341 static const int kStartOffset = JSObject::BodyDescriptor::kStartOffset; 342 343 static bool IsValidSlot(Map map, HeapObject obj, int offset) { 344 if (offset < kStartOffset) return false; 345 return IsValidJSObjectSlotImpl(map, obj, offset); 346 } 347 348 template <typename ObjectVisitor> 349 static inline void IterateBody(Map map, HeapObject obj, int object_size, 350 ObjectVisitor* v) { 351 // Iterate JSFunction header fields first. 352 int header_size = JSFunction::GetHeaderSize(map.has_prototype_slot()); 353 DCHECK_GE(object_size, header_size); 354 IteratePointers(obj, kStartOffset, kCodeOffset, v); 355 // Code field is treated as a custom weak pointer. This field is visited as 356 // a weak pointer if the Code is baseline code and the bytecode array 357 // corresponding to this function is old. In the rest of the cases this 358 // field is treated as strong pointer. 359 IterateCustomWeakPointer(obj, kCodeOffset, v); 360 // Iterate rest of the header fields 361 DCHECK_GE(header_size, kCodeOffset); 362 IteratePointers(obj, kCodeOffset + kTaggedSize, header_size, v); 363 // Iterate rest of the fields starting after the header. 364 IterateJSObjectBodyImpl(map, obj, header_size, object_size, v); 365 } 366 367 static inline int SizeOf(Map map, HeapObject object) { 368 return map.instance_size(); 369 } 370}; 371 372class JSArrayBuffer::BodyDescriptor final : public BodyDescriptorBase { 373 public: 374 static bool IsValidSlot(Map map, HeapObject obj, int offset) { 375 if (offset < kEndOfTaggedFieldsOffset) return true; 376 if (offset < kHeaderSize) return false; 377 return IsValidJSObjectSlotImpl(map, obj, offset); 378 } 379 380 template <typename ObjectVisitor> 381 static inline void IterateBody(Map map, HeapObject obj, int object_size, 382 ObjectVisitor* v) { 383 // JSArrayBuffer instances contain raw data that the GC does not know about. 384 IteratePointers(obj, kPropertiesOrHashOffset, kEndOfTaggedFieldsOffset, v); 385 IterateJSObjectBodyImpl(map, obj, kHeaderSize, object_size, v); 386 } 387 388 static inline int SizeOf(Map map, HeapObject object) { 389 return map.instance_size(); 390 } 391}; 392 393class JSTypedArray::BodyDescriptor final : public BodyDescriptorBase { 394 public: 395 static bool IsValidSlot(Map map, HeapObject obj, int offset) { 396 if (offset < kEndOfTaggedFieldsOffset) return true; 397 // TODO(v8:4153): Remove this. 398 if (offset == kBasePointerOffset) return true; 399 if (offset < kHeaderSize) return false; 400 return IsValidJSObjectSlotImpl(map, obj, offset); 401 } 402 403 template <typename ObjectVisitor> 404 static inline void IterateBody(Map map, HeapObject obj, int object_size, 405 ObjectVisitor* v) { 406 // JSTypedArray contains raw data that the GC does not know about. 407 IteratePointers(obj, kPropertiesOrHashOffset, kEndOfTaggedFieldsOffset, v); 408 // TODO(v8:4153): Remove this. 409 IteratePointer(obj, kBasePointerOffset, v); 410 IterateJSObjectBodyImpl(map, obj, kHeaderSize, object_size, v); 411 } 412 413 static inline int SizeOf(Map map, HeapObject object) { 414 return map.instance_size(); 415 } 416}; 417 418class JSDataView::BodyDescriptor final : public BodyDescriptorBase { 419 public: 420 static bool IsValidSlot(Map map, HeapObject obj, int offset) { 421 if (offset < kEndOfTaggedFieldsOffset) return true; 422 if (offset < kHeaderSize) return false; 423 return IsValidJSObjectSlotImpl(map, obj, offset); 424 } 425 426 template <typename ObjectVisitor> 427 static inline void IterateBody(Map map, HeapObject obj, int object_size, 428 ObjectVisitor* v) { 429 // JSDataView contains raw data that the GC does not know about. 430 IteratePointers(obj, kPropertiesOrHashOffset, kEndOfTaggedFieldsOffset, v); 431 IterateJSObjectBodyImpl(map, obj, kHeaderSize, object_size, v); 432 } 433 434 static inline int SizeOf(Map map, HeapObject object) { 435 return map.instance_size(); 436 } 437}; 438 439class JSExternalObject::BodyDescriptor final : public BodyDescriptorBase { 440 public: 441 static bool IsValidSlot(Map map, HeapObject obj, int offset) { return false; } 442 443 template <typename ObjectVisitor> 444 static inline void IterateBody(Map map, HeapObject obj, int object_size, 445 ObjectVisitor* v) { 446 IteratePointers(obj, kPropertiesOrHashOffset, kEndOfTaggedFieldsOffset, v); 447 v->VisitExternalPointer(obj, obj.RawExternalPointerField(kValueOffset)); 448 } 449 450 static inline int SizeOf(Map map, HeapObject object) { 451 return map.instance_size(); 452 } 453}; 454 455template <typename Derived> 456class V8_EXPORT_PRIVATE SmallOrderedHashTable<Derived>::BodyDescriptor final 457 : public BodyDescriptorBase { 458 public: 459 static bool IsValidSlot(Map map, HeapObject obj, int offset) { 460 Derived table = Derived::cast(obj); 461 // Only data table part contains tagged values. 462 return (offset >= DataTableStartOffset()) && 463 (offset < table.GetBucketsStartOffset()); 464 } 465 466 template <typename ObjectVisitor> 467 static inline void IterateBody(Map map, HeapObject obj, int object_size, 468 ObjectVisitor* v) { 469 Derived table = Derived::cast(obj); 470 int start_offset = DataTableStartOffset(); 471 int end_offset = table.GetBucketsStartOffset(); 472 IteratePointers(obj, start_offset, end_offset, v); 473 } 474 475 static inline int SizeOf(Map map, HeapObject obj) { 476 Derived table = Derived::cast(obj); 477 return Derived::SizeFor(table.Capacity()); 478 } 479}; 480 481class V8_EXPORT_PRIVATE SwissNameDictionary::BodyDescriptor final 482 : public BodyDescriptorBase { 483 public: 484 static bool IsValidSlot(Map map, HeapObject obj, int offset) { 485 // Using |unchecked_cast| here and elsewhere in this class because the 486 // Scavenger may be calling us while the map word contains the forwarding 487 // address (a Smi) rather than a map. 488 489 SwissNameDictionary table = SwissNameDictionary::unchecked_cast(obj); 490 STATIC_ASSERT(MetaTablePointerOffset() + kTaggedSize == 491 DataTableStartOffset()); 492 return offset >= MetaTablePointerOffset() && 493 (offset < table.DataTableEndOffset(table.Capacity())); 494 } 495 496 template <typename ObjectVisitor> 497 static inline void IterateBody(Map map, HeapObject obj, int object_size, 498 ObjectVisitor* v) { 499 SwissNameDictionary table = SwissNameDictionary::unchecked_cast(obj); 500 STATIC_ASSERT(MetaTablePointerOffset() + kTaggedSize == 501 DataTableStartOffset()); 502 int start_offset = MetaTablePointerOffset(); 503 int end_offset = table.DataTableEndOffset(table.Capacity()); 504 IteratePointers(obj, start_offset, end_offset, v); 505 } 506 507 static inline int SizeOf(Map map, HeapObject obj) { 508 SwissNameDictionary table = SwissNameDictionary::unchecked_cast(obj); 509 return SwissNameDictionary::SizeFor(table.Capacity()); 510 } 511}; 512 513class ByteArray::BodyDescriptor final : public BodyDescriptorBase { 514 public: 515 static bool IsValidSlot(Map map, HeapObject obj, int offset) { return false; } 516 517 template <typename ObjectVisitor> 518 static inline void IterateBody(Map map, HeapObject obj, int object_size, 519 ObjectVisitor* v) {} 520 521 static inline int SizeOf(Map map, HeapObject obj) { 522 return ByteArray::SizeFor(ByteArray::cast(obj).length(kAcquireLoad)); 523 } 524}; 525 526class BytecodeArray::BodyDescriptor final : public BodyDescriptorBase { 527 public: 528 static bool IsValidSlot(Map map, HeapObject obj, int offset) { 529 return offset >= kConstantPoolOffset && 530 offset <= kSourcePositionTableOffset; 531 } 532 533 template <typename ObjectVisitor> 534 static inline void IterateBody(Map map, HeapObject obj, int object_size, 535 ObjectVisitor* v) { 536 IteratePointer(obj, kConstantPoolOffset, v); 537 IteratePointer(obj, kHandlerTableOffset, v); 538 IteratePointer(obj, kSourcePositionTableOffset, v); 539 } 540 541 static inline int SizeOf(Map map, HeapObject obj) { 542 return BytecodeArray::SizeFor( 543 BytecodeArray::cast(obj).length(kAcquireLoad)); 544 } 545}; 546 547class BigInt::BodyDescriptor final : public BodyDescriptorBase { 548 public: 549 static bool IsValidSlot(Map map, HeapObject obj, int offset) { return false; } 550 551 template <typename ObjectVisitor> 552 static inline void IterateBody(Map map, HeapObject obj, int object_size, 553 ObjectVisitor* v) {} 554 555 static inline int SizeOf(Map map, HeapObject obj) { 556 return BigInt::SizeFor(BigInt::cast(obj).length(kAcquireLoad)); 557 } 558}; 559 560class FixedDoubleArray::BodyDescriptor final : public BodyDescriptorBase { 561 public: 562 static bool IsValidSlot(Map map, HeapObject obj, int offset) { return false; } 563 564 template <typename ObjectVisitor> 565 static inline void IterateBody(Map map, HeapObject obj, int object_size, 566 ObjectVisitor* v) {} 567 568 static inline int SizeOf(Map map, HeapObject obj) { 569 return FixedDoubleArray::SizeFor( 570 FixedDoubleArray::cast(obj).length(kAcquireLoad)); 571 } 572}; 573 574class FeedbackMetadata::BodyDescriptor final : public BodyDescriptorBase { 575 public: 576 static bool IsValidSlot(Map map, HeapObject obj, int offset) { return false; } 577 578 template <typename ObjectVisitor> 579 static inline void IterateBody(Map map, HeapObject obj, int object_size, 580 ObjectVisitor* v) {} 581 582 static inline int SizeOf(Map map, HeapObject obj) { 583 return FeedbackMetadata::SizeFor( 584 FeedbackMetadata::cast(obj).slot_count(kAcquireLoad)); 585 } 586}; 587 588class PreparseData::BodyDescriptor final : public BodyDescriptorBase { 589 public: 590 static bool IsValidSlot(Map map, HeapObject obj, int offset) { 591 return offset >= PreparseData::cast(obj).inner_start_offset(); 592 } 593 594 template <typename ObjectVisitor> 595 static inline void IterateBody(Map map, HeapObject obj, int object_size, 596 ObjectVisitor* v) { 597 PreparseData data = PreparseData::cast(obj); 598 int start_offset = data.inner_start_offset(); 599 int end_offset = start_offset + data.children_length() * kTaggedSize; 600 IteratePointers(obj, start_offset, end_offset, v); 601 } 602 603 static inline int SizeOf(Map map, HeapObject obj) { 604 PreparseData data = PreparseData::cast(obj); 605 return PreparseData::SizeFor(data.data_length(), data.children_length()); 606 } 607}; 608 609class PromiseOnStack::BodyDescriptor final : public BodyDescriptorBase { 610 public: 611 static bool IsValidSlot(Map map, HeapObject obj, int offset) { 612 return offset >= HeapObject::kHeaderSize; 613 } 614 615 template <typename ObjectVisitor> 616 static inline void IterateBody(Map map, HeapObject obj, int object_size, 617 ObjectVisitor* v) { 618 IteratePointers(obj, Struct::kHeaderSize, kPromiseOffset, v); 619 IterateMaybeWeakPointer(obj, kPromiseOffset, v); 620 STATIC_ASSERT(kPromiseOffset + kTaggedSize == kHeaderSize); 621 } 622 623 static inline int SizeOf(Map map, HeapObject obj) { 624 return obj.SizeFromMap(map); 625 } 626}; 627 628class PrototypeInfo::BodyDescriptor final : public BodyDescriptorBase { 629 public: 630 static bool IsValidSlot(Map map, HeapObject obj, int offset) { 631 return offset >= HeapObject::kHeaderSize; 632 } 633 634 template <typename ObjectVisitor> 635 static inline void IterateBody(Map map, HeapObject obj, int object_size, 636 ObjectVisitor* v) { 637 IteratePointers(obj, HeapObject::kHeaderSize, kObjectCreateMapOffset, v); 638 IterateMaybeWeakPointer(obj, kObjectCreateMapOffset, v); 639 STATIC_ASSERT(kObjectCreateMapOffset + kTaggedSize == kHeaderSize); 640 } 641 642 static inline int SizeOf(Map map, HeapObject obj) { 643 return obj.SizeFromMap(map); 644 } 645}; 646 647class JSWeakCollection::BodyDescriptorImpl final : public BodyDescriptorBase { 648 public: 649 STATIC_ASSERT(kTableOffset + kTaggedSize == kHeaderSizeOfAllWeakCollections); 650 651 static bool IsValidSlot(Map map, HeapObject obj, int offset) { 652 return IsValidJSObjectSlotImpl(map, obj, offset); 653 } 654 655 template <typename ObjectVisitor> 656 static inline void IterateBody(Map map, HeapObject obj, int object_size, 657 ObjectVisitor* v) { 658 IterateJSObjectBodyImpl(map, obj, kPropertiesOrHashOffset, object_size, v); 659 } 660 661 static inline int SizeOf(Map map, HeapObject object) { 662 return map.instance_size(); 663 } 664}; 665 666class Foreign::BodyDescriptor final : public BodyDescriptorBase { 667 public: 668 static bool IsValidSlot(Map map, HeapObject obj, int offset) { return false; } 669 670 template <typename ObjectVisitor> 671 static inline void IterateBody(Map map, HeapObject obj, int object_size, 672 ObjectVisitor* v) { 673 v->VisitExternalReference( 674 Foreign::cast(obj), reinterpret_cast<Address*>( 675 obj.RawField(kForeignAddressOffset).address())); 676 v->VisitExternalPointer(obj, 677 obj.RawExternalPointerField(kForeignAddressOffset)); 678 } 679 680 static inline int SizeOf(Map map, HeapObject object) { return kSize; } 681}; 682 683#if V8_ENABLE_WEBASSEMBLY 684class WasmTypeInfo::BodyDescriptor final : public BodyDescriptorBase { 685 public: 686 static bool IsValidSlot(Map map, HeapObject obj, int offset) { 687 UNREACHABLE(); 688 } 689 690 template <typename ObjectVisitor> 691 static inline void IterateBody(Map map, HeapObject obj, int object_size, 692 ObjectVisitor* v) { 693 Foreign::BodyDescriptor::IterateBody<ObjectVisitor>(map, obj, object_size, 694 v); 695 IteratePointer(obj, kSupertypesOffset, v); 696 IteratePointer(obj, kSubtypesOffset, v); 697 IteratePointer(obj, kInstanceOffset, v); 698 } 699 700 static inline int SizeOf(Map map, HeapObject object) { return kSize; } 701}; 702 703class WasmApiFunctionRef::BodyDescriptor final : public BodyDescriptorBase { 704 public: 705 static bool IsValidSlot(Map map, HeapObject obj, int offset) { 706 UNREACHABLE(); 707 } 708 709 template <typename ObjectVisitor> 710 static inline void IterateBody(Map map, HeapObject obj, int object_size, 711 ObjectVisitor* v) { 712 IteratePointers(obj, kStartOfStrongFieldsOffset, kEndOfStrongFieldsOffset, 713 v); 714 } 715 716 static inline int SizeOf(Map map, HeapObject object) { return kSize; } 717}; 718 719class WasmInternalFunction::BodyDescriptor final : public BodyDescriptorBase { 720 public: 721 static bool IsValidSlot(Map map, HeapObject obj, int offset) { 722 UNREACHABLE(); 723 } 724 725 template <typename ObjectVisitor> 726 static inline void IterateBody(Map map, HeapObject obj, int object_size, 727 ObjectVisitor* v) { 728 Foreign::BodyDescriptor::IterateBody<ObjectVisitor>(map, obj, object_size, 729 v); 730 IteratePointers(obj, kStartOfStrongFieldsOffset, kEndOfStrongFieldsOffset, 731 v); 732 } 733 734 static inline int SizeOf(Map map, HeapObject object) { return kSize; } 735}; 736 737class WasmInstanceObject::BodyDescriptor final : public BodyDescriptorBase { 738 public: 739 static bool IsValidSlot(Map map, HeapObject obj, int offset) { 740 SLOW_DCHECK(std::is_sorted(std::begin(kTaggedFieldOffsets), 741 std::end(kTaggedFieldOffsets))); 742 STATIC_ASSERT(sizeof(*kTaggedFieldOffsets) == sizeof(uint16_t)); 743 if (offset < int{8 * sizeof(*kTaggedFieldOffsets)} && 744 std::binary_search(std::begin(kTaggedFieldOffsets), 745 std::end(kTaggedFieldOffsets), 746 static_cast<uint16_t>(offset))) { 747 return true; 748 } 749 return IsValidJSObjectSlotImpl(map, obj, offset); 750 } 751 752 template <typename ObjectVisitor> 753 static inline void IterateBody(Map map, HeapObject obj, int object_size, 754 ObjectVisitor* v) { 755 IteratePointers(obj, kPropertiesOrHashOffset, JSObject::kHeaderSize, v); 756 for (uint16_t offset : kTaggedFieldOffsets) { 757 IteratePointer(obj, offset, v); 758 } 759 IterateJSObjectBodyImpl(map, obj, kHeaderSize, object_size, v); 760 } 761 762 static inline int SizeOf(Map map, HeapObject object) { 763 return map.instance_size(); 764 } 765}; 766 767class WasmArray::BodyDescriptor final : public BodyDescriptorBase { 768 public: 769 static bool IsValidSlot(Map map, HeapObject obj, int offset) { 770 // Fields in WasmArrays never change their types in place, so 771 // there should never be a need to call this function. 772 UNREACHABLE(); 773 return false; 774 } 775 776 template <typename ObjectVisitor> 777 static inline void IterateBody(Map map, HeapObject obj, int object_size, 778 ObjectVisitor* v) { 779 // The type is safe to use because it's kept alive by the {map}'s 780 // WasmTypeInfo. 781 if (!WasmArray::GcSafeType(map)->element_type().is_reference()) return; 782 IteratePointers(obj, WasmArray::kHeaderSize, object_size, v); 783 } 784 785 static inline int SizeOf(Map map, HeapObject object) { 786 return WasmArray::SizeFor(map, WasmArray::cast(object).length()); 787 } 788}; 789 790class WasmStruct::BodyDescriptor final : public BodyDescriptorBase { 791 public: 792 static bool IsValidSlot(Map map, HeapObject obj, int offset) { 793 // Fields in WasmStructs never change their types in place, so 794 // there should never be a need to call this function. 795 UNREACHABLE(); 796 return false; 797 } 798 799 template <typename ObjectVisitor> 800 static inline void IterateBody(Map map, HeapObject obj, int object_size, 801 ObjectVisitor* v) { 802 WasmStruct wasm_struct = WasmStruct::cast(obj); 803 // The {type} is safe to use because it's kept alive by the {map}'s 804 // WasmTypeInfo. 805 wasm::StructType* type = WasmStruct::GcSafeType(map); 806 for (uint32_t i = 0; i < type->field_count(); i++) { 807 if (!type->field(i).is_reference()) continue; 808 int offset = static_cast<int>(type->field_offset(i)); 809 v->VisitPointer(wasm_struct, wasm_struct.RawField(offset)); 810 } 811 } 812 813 static inline int SizeOf(Map map, HeapObject object) { 814 return WasmStruct::GcSafeSize(map); 815 } 816}; 817 818#endif // V8_ENABLE_WEBASSEMBLY 819 820class ExternalOneByteString::BodyDescriptor final : public BodyDescriptorBase { 821 public: 822 static bool IsValidSlot(Map map, HeapObject obj, int offset) { return false; } 823 824 template <typename ObjectVisitor> 825 static inline void IterateBody(Map map, HeapObject obj, int object_size, 826 ObjectVisitor* v) { 827 ExternalString string = ExternalString::cast(obj); 828 v->VisitExternalPointer(obj, 829 string.RawExternalPointerField(kResourceOffset)); 830 if (string.is_uncached()) return; 831 v->VisitExternalPointer( 832 obj, string.RawExternalPointerField(kResourceDataOffset)); 833 } 834 835 static inline int SizeOf(Map map, HeapObject object) { return kSize; } 836}; 837 838class ExternalTwoByteString::BodyDescriptor final : public BodyDescriptorBase { 839 public: 840 static bool IsValidSlot(Map map, HeapObject obj, int offset) { return false; } 841 842 template <typename ObjectVisitor> 843 static inline void IterateBody(Map map, HeapObject obj, int object_size, 844 ObjectVisitor* v) { 845 ExternalString string = ExternalString::cast(obj); 846 v->VisitExternalPointer(obj, 847 string.RawExternalPointerField(kResourceOffset)); 848 if (string.is_uncached()) return; 849 v->VisitExternalPointer( 850 obj, string.RawExternalPointerField(kResourceDataOffset)); 851 } 852 853 static inline int SizeOf(Map map, HeapObject object) { return kSize; } 854}; 855 856class CoverageInfo::BodyDescriptor final : public BodyDescriptorBase { 857 public: 858 static bool IsValidSlot(Map map, HeapObject obj, int offset) { return false; } 859 860 template <typename ObjectVisitor> 861 static inline void IterateBody(Map map, HeapObject obj, int object_size, 862 ObjectVisitor* v) {} 863 864 static inline int SizeOf(Map map, HeapObject object) { 865 CoverageInfo info = CoverageInfo::cast(object); 866 return CoverageInfo::SizeFor(info.slot_count()); 867 } 868}; 869 870class Code::BodyDescriptor final : public BodyDescriptorBase { 871 public: 872 STATIC_ASSERT(kRelocationInfoOffset + kTaggedSize == 873 kDeoptimizationDataOrInterpreterDataOffset); 874 STATIC_ASSERT(kDeoptimizationDataOrInterpreterDataOffset + kTaggedSize == 875 kPositionTableOffset); 876 STATIC_ASSERT(kPositionTableOffset + kTaggedSize == kCodeDataContainerOffset); 877 STATIC_ASSERT(kCodeDataContainerOffset + kTaggedSize == kDataStart); 878 879 static bool IsValidSlot(Map map, HeapObject obj, int offset) { 880 // Slots in code can't be invalid because we never trim code objects. 881 return true; 882 } 883 884 static constexpr int kRelocModeMask = 885 RelocInfo::ModeMask(RelocInfo::CODE_TARGET) | 886 RelocInfo::ModeMask(RelocInfo::RELATIVE_CODE_TARGET) | 887 RelocInfo::ModeMask(RelocInfo::FULL_EMBEDDED_OBJECT) | 888 RelocInfo::ModeMask(RelocInfo::COMPRESSED_EMBEDDED_OBJECT) | 889 RelocInfo::ModeMask(RelocInfo::DATA_EMBEDDED_OBJECT) | 890 RelocInfo::ModeMask(RelocInfo::EXTERNAL_REFERENCE) | 891 RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE) | 892 RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE_ENCODED) | 893 RelocInfo::ModeMask(RelocInfo::OFF_HEAP_TARGET) | 894 RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY); 895 896 template <typename ObjectVisitor> 897 static inline void IterateBody(Map map, HeapObject obj, ObjectVisitor* v) { 898 // GC does not visit data/code in the header and in the body directly. 899 IteratePointers(obj, kRelocationInfoOffset, kDataStart, v); 900 901 RelocIterator it(Code::cast(obj), kRelocModeMask); 902 v->VisitRelocInfo(&it); 903 } 904 905 template <typename ObjectVisitor> 906 static inline void IterateBody(Map map, HeapObject obj, int object_size, 907 ObjectVisitor* v) { 908 IterateBody(map, obj, v); 909 } 910 911 static inline int SizeOf(Map map, HeapObject object) { 912 return Code::unchecked_cast(object).CodeSize(); 913 } 914}; 915 916class Map::BodyDescriptor final : public BodyDescriptorBase { 917 public: 918 static bool IsValidSlot(Map map, HeapObject obj, int offset) { 919 static_assert( 920 Map::kEndOfStrongFieldsOffset == Map::kStartOfWeakFieldsOffset, 921 "Leverage that weak fields directly follow strong fields for the " 922 "check below"); 923 return offset >= Map::kStartOfStrongFieldsOffset && 924 offset < Map::kEndOfWeakFieldsOffset; 925 } 926 927 template <typename ObjectVisitor> 928 static inline void IterateBody(Map map, HeapObject obj, int object_size, 929 ObjectVisitor* v) { 930 IteratePointers(obj, Map::kStartOfStrongFieldsOffset, 931 Map::kEndOfStrongFieldsOffset, v); 932 IterateMaybeWeakPointer(obj, kTransitionsOrPrototypeInfoOffset, v); 933 } 934 935 static inline int SizeOf(Map map, HeapObject obj) { return Map::kSize; } 936}; 937 938class DataHandler::BodyDescriptor final : public BodyDescriptorBase { 939 public: 940 static bool IsValidSlot(Map map, HeapObject obj, int offset) { 941 return offset >= HeapObject::kHeaderSize; 942 } 943 944 template <typename ObjectVisitor> 945 static inline void IterateBody(Map map, HeapObject obj, int object_size, 946 ObjectVisitor* v) { 947 static_assert(kSmiHandlerOffset < kData1Offset, 948 "Field order must be in sync with this iteration code"); 949 static_assert(kData1Offset < kSizeWithData1, 950 "Field order must be in sync with this iteration code"); 951 IteratePointers(obj, kSmiHandlerOffset, kData1Offset, v); 952 IterateMaybeWeakPointers(obj, kData1Offset, object_size, v); 953 } 954 955 static inline int SizeOf(Map map, HeapObject object) { 956 return object.SizeFromMap(map); 957 } 958}; 959 960class NativeContext::BodyDescriptor final : public BodyDescriptorBase { 961 public: 962 static bool IsValidSlot(Map map, HeapObject obj, int offset) { 963 return offset < NativeContext::kEndOfTaggedFieldsOffset; 964 } 965 966 template <typename ObjectVisitor> 967 static inline void IterateBody(Map map, HeapObject obj, int object_size, 968 ObjectVisitor* v) { 969 IteratePointers(obj, NativeContext::kStartOfStrongFieldsOffset, 970 NativeContext::kEndOfStrongFieldsOffset, v); 971 IterateCustomWeakPointers(obj, NativeContext::kStartOfWeakFieldsOffset, 972 NativeContext::kEndOfWeakFieldsOffset, v); 973 v->VisitExternalPointer(obj, 974 obj.RawExternalPointerField(kMicrotaskQueueOffset)); 975 } 976 977 static inline int SizeOf(Map map, HeapObject object) { 978 return NativeContext::kSize; 979 } 980}; 981 982class CodeDataContainer::BodyDescriptor final : public BodyDescriptorBase { 983 public: 984 static bool IsValidSlot(Map map, HeapObject obj, int offset) { 985 return offset >= CodeDataContainer::kHeaderSize && 986 offset <= CodeDataContainer::kPointerFieldsWeakEndOffset; 987 } 988 989 template <typename ObjectVisitor> 990 static inline void IterateBody(Map map, HeapObject obj, int object_size, 991 ObjectVisitor* v) { 992 IteratePointers(obj, CodeDataContainer::kHeaderSize, 993 CodeDataContainer::kPointerFieldsStrongEndOffset, v); 994 IterateCustomWeakPointers( 995 obj, CodeDataContainer::kPointerFieldsStrongEndOffset, 996 CodeDataContainer::kPointerFieldsWeakEndOffset, v); 997 998 if (V8_EXTERNAL_CODE_SPACE_BOOL) { 999 v->VisitCodePointer(obj, obj.RawCodeField(kCodeOffset)); 1000 v->VisitExternalPointer( 1001 obj, obj.RawExternalPointerField(kCodeEntryPointOffset)); 1002 } 1003 } 1004 1005 static inline int SizeOf(Map map, HeapObject object) { 1006 return CodeDataContainer::kSize; 1007 } 1008}; 1009 1010class EmbedderDataArray::BodyDescriptor final : public BodyDescriptorBase { 1011 public: 1012 static bool IsValidSlot(Map map, HeapObject obj, int offset) { 1013#ifdef V8_COMPRESS_POINTERS 1014 STATIC_ASSERT(kEmbedderDataSlotSize == 2 * kTaggedSize); 1015 STATIC_ASSERT(base::bits::IsPowerOfTwo(kEmbedderDataSlotSize)); 1016 return (offset < EmbedderDataArray::kHeaderSize) || 1017 (((offset - EmbedderDataArray::kHeaderSize) & 1018 (kEmbedderDataSlotSize - 1)) == 1019 EmbedderDataSlot::kTaggedPayloadOffset); 1020#else 1021 STATIC_ASSERT(kEmbedderDataSlotSize == kTaggedSize); 1022 // We store raw aligned pointers as Smis, so it's safe to iterate the whole 1023 // array. 1024 return true; 1025#endif 1026 } 1027 1028 template <typename ObjectVisitor> 1029 static inline void IterateBody(Map map, HeapObject obj, int object_size, 1030 ObjectVisitor* v) { 1031#ifdef V8_COMPRESS_POINTERS 1032 STATIC_ASSERT(kEmbedderDataSlotSize == 2 * kTaggedSize); 1033 for (int offset = EmbedderDataArray::OffsetOfElementAt(0); 1034 offset < object_size; offset += kEmbedderDataSlotSize) { 1035 IteratePointer(obj, offset + EmbedderDataSlot::kTaggedPayloadOffset, v); 1036 v->VisitExternalPointer( 1037 obj, obj.RawExternalPointerField( 1038 offset + EmbedderDataSlot::kExternalPointerOffset)); 1039 } 1040 1041#else 1042 // We store raw aligned pointers as Smis, so it's safe to iterate the whole 1043 // array. 1044 STATIC_ASSERT(kEmbedderDataSlotSize == kTaggedSize); 1045 IteratePointers(obj, EmbedderDataArray::kHeaderSize, object_size, v); 1046#endif 1047 } 1048 1049 static inline int SizeOf(Map map, HeapObject object) { 1050 return object.SizeFromMap(map); 1051 } 1052}; 1053 1054template <typename Op, typename... Args> 1055auto BodyDescriptorApply(InstanceType type, Args&&... args) { 1056#define CALL_APPLY(ClassName) \ 1057 Op::template apply<ClassName::BodyDescriptor>(std::forward<Args>(args)...) 1058 1059 if (type < FIRST_NONSTRING_TYPE) { 1060 switch (type & kStringRepresentationMask) { 1061 case kSeqStringTag: 1062 if ((type & kStringEncodingMask) == kOneByteStringTag) { 1063 return CALL_APPLY(SeqOneByteString); 1064 } else { 1065 return CALL_APPLY(SeqTwoByteString); 1066 } 1067 case kConsStringTag: 1068 return CALL_APPLY(ConsString); 1069 case kThinStringTag: 1070 return CALL_APPLY(ThinString); 1071 case kSlicedStringTag: 1072 return CALL_APPLY(SlicedString); 1073 case kExternalStringTag: 1074 if ((type & kStringEncodingMask) == kOneByteStringTag) { 1075 return CALL_APPLY(ExternalOneByteString); 1076 } else { 1077 return CALL_APPLY(ExternalTwoByteString); 1078 } 1079 } 1080 UNREACHABLE(); 1081 } 1082 if (InstanceTypeChecker::IsJSApiObject(type)) { 1083 return CALL_APPLY(JSObject); 1084 } 1085 1086 switch (type) { 1087 case EMBEDDER_DATA_ARRAY_TYPE: 1088 return CALL_APPLY(EmbedderDataArray); 1089 case OBJECT_BOILERPLATE_DESCRIPTION_TYPE: 1090 case CLOSURE_FEEDBACK_CELL_ARRAY_TYPE: 1091 case HASH_TABLE_TYPE: 1092 case ORDERED_HASH_MAP_TYPE: 1093 case ORDERED_HASH_SET_TYPE: 1094 case ORDERED_NAME_DICTIONARY_TYPE: 1095 case NAME_DICTIONARY_TYPE: 1096 case GLOBAL_DICTIONARY_TYPE: 1097 case NUMBER_DICTIONARY_TYPE: 1098 case SIMPLE_NUMBER_DICTIONARY_TYPE: 1099 case NAME_TO_INDEX_HASH_TABLE_TYPE: 1100 case REGISTERED_SYMBOL_TABLE_TYPE: 1101 case SCRIPT_CONTEXT_TABLE_TYPE: 1102 return CALL_APPLY(FixedArray); 1103 case EPHEMERON_HASH_TABLE_TYPE: 1104 return CALL_APPLY(EphemeronHashTable); 1105 case AWAIT_CONTEXT_TYPE: 1106 case BLOCK_CONTEXT_TYPE: 1107 case CATCH_CONTEXT_TYPE: 1108 case DEBUG_EVALUATE_CONTEXT_TYPE: 1109 case EVAL_CONTEXT_TYPE: 1110 case FUNCTION_CONTEXT_TYPE: 1111 case MODULE_CONTEXT_TYPE: 1112 case SCRIPT_CONTEXT_TYPE: 1113 case WITH_CONTEXT_TYPE: 1114 return CALL_APPLY(Context); 1115 case NATIVE_CONTEXT_TYPE: 1116 return CALL_APPLY(NativeContext); 1117 case FIXED_DOUBLE_ARRAY_TYPE: 1118 return CALL_APPLY(FixedDoubleArray); 1119 case FEEDBACK_METADATA_TYPE: 1120 return CALL_APPLY(FeedbackMetadata); 1121 case PROPERTY_ARRAY_TYPE: 1122 return CALL_APPLY(PropertyArray); 1123 case TRANSITION_ARRAY_TYPE: 1124 return CALL_APPLY(TransitionArray); 1125 case FEEDBACK_CELL_TYPE: 1126 return CALL_APPLY(FeedbackCell); 1127 case COVERAGE_INFO_TYPE: 1128 return CALL_APPLY(CoverageInfo); 1129#if V8_ENABLE_WEBASSEMBLY 1130 case WASM_API_FUNCTION_REF_TYPE: 1131 return CALL_APPLY(WasmApiFunctionRef); 1132 case WASM_ARRAY_TYPE: 1133 return CALL_APPLY(WasmArray); 1134 case WASM_CAPI_FUNCTION_DATA_TYPE: 1135 return CALL_APPLY(WasmCapiFunctionData); 1136 case WASM_EXPORTED_FUNCTION_DATA_TYPE: 1137 return CALL_APPLY(WasmExportedFunctionData); 1138 case WASM_INTERNAL_FUNCTION_TYPE: 1139 return CALL_APPLY(WasmInternalFunction); 1140 case WASM_JS_FUNCTION_DATA_TYPE: 1141 return CALL_APPLY(WasmJSFunctionData); 1142 case WASM_ON_FULFILLED_DATA_TYPE: 1143 return CALL_APPLY(WasmOnFulfilledData); 1144 case WASM_STRUCT_TYPE: 1145 return CALL_APPLY(WasmStruct); 1146 case WASM_TYPE_INFO_TYPE: 1147 return CALL_APPLY(WasmTypeInfo); 1148#endif // V8_ENABLE_WEBASSEMBLY 1149 case JS_API_OBJECT_TYPE: 1150 case JS_ARGUMENTS_OBJECT_TYPE: 1151 case JS_ARRAY_ITERATOR_PROTOTYPE_TYPE: 1152 case JS_ARRAY_ITERATOR_TYPE: 1153 case JS_ARRAY_TYPE: 1154 case JS_ASYNC_FROM_SYNC_ITERATOR_TYPE: 1155 case JS_ASYNC_FUNCTION_OBJECT_TYPE: 1156 case JS_ASYNC_GENERATOR_OBJECT_TYPE: 1157 case JS_BOUND_FUNCTION_TYPE: 1158 case JS_CONTEXT_EXTENSION_OBJECT_TYPE: 1159 case JS_DATE_TYPE: 1160 case JS_ERROR_TYPE: 1161 case JS_FINALIZATION_REGISTRY_TYPE: 1162 case JS_GENERATOR_OBJECT_TYPE: 1163 case JS_GLOBAL_OBJECT_TYPE: 1164 case JS_GLOBAL_PROXY_TYPE: 1165 case JS_ITERATOR_PROTOTYPE_TYPE: 1166 case JS_MAP_ITERATOR_PROTOTYPE_TYPE: 1167 case JS_MAP_KEY_ITERATOR_TYPE: 1168 case JS_MAP_KEY_VALUE_ITERATOR_TYPE: 1169 case JS_MAP_TYPE: 1170 case JS_MAP_VALUE_ITERATOR_TYPE: 1171 case JS_MESSAGE_OBJECT_TYPE: 1172 case JS_MODULE_NAMESPACE_TYPE: 1173 case JS_OBJECT_PROTOTYPE_TYPE: 1174 case JS_OBJECT_TYPE: 1175 case JS_PRIMITIVE_WRAPPER_TYPE: 1176 case JS_PROMISE_PROTOTYPE_TYPE: 1177 case JS_PROMISE_TYPE: 1178 case JS_REG_EXP_PROTOTYPE_TYPE: 1179 case JS_REG_EXP_STRING_ITERATOR_TYPE: 1180 case JS_REG_EXP_TYPE: 1181 case JS_SET_ITERATOR_PROTOTYPE_TYPE: 1182 case JS_SET_KEY_VALUE_ITERATOR_TYPE: 1183 case JS_SET_PROTOTYPE_TYPE: 1184 case JS_SET_TYPE: 1185 case JS_SET_VALUE_ITERATOR_TYPE: 1186 case JS_SPECIAL_API_OBJECT_TYPE: 1187 case JS_SHADOW_REALM_TYPE: 1188 case JS_SHARED_STRUCT_TYPE: 1189 case JS_STRING_ITERATOR_PROTOTYPE_TYPE: 1190 case JS_STRING_ITERATOR_TYPE: 1191 case JS_TEMPORAL_CALENDAR_TYPE: 1192 case JS_TEMPORAL_DURATION_TYPE: 1193 case JS_TEMPORAL_INSTANT_TYPE: 1194 case JS_TEMPORAL_PLAIN_DATE_TYPE: 1195 case JS_TEMPORAL_PLAIN_DATE_TIME_TYPE: 1196 case JS_TEMPORAL_PLAIN_MONTH_DAY_TYPE: 1197 case JS_TEMPORAL_PLAIN_TIME_TYPE: 1198 case JS_TEMPORAL_PLAIN_YEAR_MONTH_TYPE: 1199 case JS_TEMPORAL_TIME_ZONE_TYPE: 1200 case JS_TEMPORAL_ZONED_DATE_TIME_TYPE: 1201 case JS_TYPED_ARRAY_PROTOTYPE_TYPE: 1202 case JS_FUNCTION_TYPE: 1203 case JS_CLASS_CONSTRUCTOR_TYPE: 1204 case JS_PROMISE_CONSTRUCTOR_TYPE: 1205 case JS_REG_EXP_CONSTRUCTOR_TYPE: 1206 case JS_WRAPPED_FUNCTION_TYPE: 1207 case JS_ARRAY_CONSTRUCTOR_TYPE: 1208#define TYPED_ARRAY_CONSTRUCTORS_SWITCH(Type, type, TYPE, Ctype) \ 1209 case TYPE##_TYPED_ARRAY_CONSTRUCTOR_TYPE: 1210 TYPED_ARRAYS(TYPED_ARRAY_CONSTRUCTORS_SWITCH) 1211#undef TYPED_ARRAY_CONSTRUCTORS_SWITCH 1212#ifdef V8_INTL_SUPPORT 1213 case JS_V8_BREAK_ITERATOR_TYPE: 1214 case JS_COLLATOR_TYPE: 1215 case JS_DATE_TIME_FORMAT_TYPE: 1216 case JS_DISPLAY_NAMES_TYPE: 1217 case JS_LIST_FORMAT_TYPE: 1218 case JS_LOCALE_TYPE: 1219 case JS_NUMBER_FORMAT_TYPE: 1220 case JS_PLURAL_RULES_TYPE: 1221 case JS_RELATIVE_TIME_FORMAT_TYPE: 1222 case JS_SEGMENT_ITERATOR_TYPE: 1223 case JS_SEGMENTER_TYPE: 1224 case JS_SEGMENTS_TYPE: 1225#endif // V8_INTL_SUPPORT 1226#if V8_ENABLE_WEBASSEMBLY 1227 case WASM_GLOBAL_OBJECT_TYPE: 1228 case WASM_MEMORY_OBJECT_TYPE: 1229 case WASM_MODULE_OBJECT_TYPE: 1230 case WASM_SUSPENDER_OBJECT_TYPE: 1231 case WASM_TABLE_OBJECT_TYPE: 1232 case WASM_TAG_OBJECT_TYPE: 1233 case WASM_VALUE_OBJECT_TYPE: 1234#endif // V8_ENABLE_WEBASSEMBLY 1235 return CALL_APPLY(JSObject); 1236#if V8_ENABLE_WEBASSEMBLY 1237 case WASM_INSTANCE_OBJECT_TYPE: 1238 return CALL_APPLY(WasmInstanceObject); 1239#endif // V8_ENABLE_WEBASSEMBLY 1240 case JS_WEAK_MAP_TYPE: 1241 case JS_WEAK_SET_TYPE: 1242 return CALL_APPLY(JSWeakCollection); 1243 case JS_ARRAY_BUFFER_TYPE: 1244 return CALL_APPLY(JSArrayBuffer); 1245 case JS_DATA_VIEW_TYPE: 1246 return CALL_APPLY(JSDataView); 1247 case JS_TYPED_ARRAY_TYPE: 1248 return CALL_APPLY(JSTypedArray); 1249 case JS_EXTERNAL_OBJECT_TYPE: 1250 return CALL_APPLY(JSExternalObject); 1251 case WEAK_CELL_TYPE: 1252 return CALL_APPLY(WeakCell); 1253 case JS_WEAK_REF_TYPE: 1254 return CALL_APPLY(JSWeakRef); 1255 case JS_PROXY_TYPE: 1256 return CALL_APPLY(JSProxy); 1257 case FOREIGN_TYPE: 1258 return CALL_APPLY(Foreign); 1259 case MAP_TYPE: 1260 return CALL_APPLY(Map); 1261 case CODE_TYPE: 1262 return CALL_APPLY(Code); 1263 case CELL_TYPE: 1264 return CALL_APPLY(Cell); 1265 case PROPERTY_CELL_TYPE: 1266 return CALL_APPLY(PropertyCell); 1267 case SYMBOL_TYPE: 1268 return CALL_APPLY(Symbol); 1269 case BYTECODE_ARRAY_TYPE: 1270 return CALL_APPLY(BytecodeArray); 1271 case SMALL_ORDERED_HASH_SET_TYPE: 1272 return CALL_APPLY(SmallOrderedHashTable<SmallOrderedHashSet>); 1273 case SMALL_ORDERED_HASH_MAP_TYPE: 1274 return CALL_APPLY(SmallOrderedHashTable<SmallOrderedHashMap>); 1275 case SMALL_ORDERED_NAME_DICTIONARY_TYPE: 1276 return CALL_APPLY(SmallOrderedHashTable<SmallOrderedNameDictionary>); 1277 case SWISS_NAME_DICTIONARY_TYPE: 1278 return CALL_APPLY(SwissNameDictionary); 1279 case CODE_DATA_CONTAINER_TYPE: 1280 return CALL_APPLY(CodeDataContainer); 1281 case PREPARSE_DATA_TYPE: 1282 return CALL_APPLY(PreparseData); 1283 case HEAP_NUMBER_TYPE: 1284 return CALL_APPLY(HeapNumber); 1285 case BYTE_ARRAY_TYPE: 1286 return CALL_APPLY(ByteArray); 1287 case BIGINT_TYPE: 1288 return CALL_APPLY(BigInt); 1289 case ALLOCATION_SITE_TYPE: 1290 return CALL_APPLY(AllocationSite); 1291 case ODDBALL_TYPE: 1292 return CALL_APPLY(Oddball); 1293 1294#define MAKE_STRUCT_CASE(TYPE, Name, name) \ 1295 case TYPE: \ 1296 return CALL_APPLY(Name); 1297 STRUCT_LIST(MAKE_STRUCT_CASE) 1298#undef MAKE_STRUCT_CASE 1299 case CALL_HANDLER_INFO_TYPE: 1300 return CALL_APPLY(CallHandlerInfo); 1301 case LOAD_HANDLER_TYPE: 1302 return CALL_APPLY(LoadHandler); 1303 case STORE_HANDLER_TYPE: 1304 return CALL_APPLY(StoreHandler); 1305 case SOURCE_TEXT_MODULE_TYPE: 1306 return CALL_APPLY(SourceTextModule); 1307 case SYNTHETIC_MODULE_TYPE: 1308 return CALL_APPLY(SyntheticModule); 1309// TODO(turbofan): Avoid duplicated cases when the body descriptors are 1310// identical. 1311#define MAKE_TORQUE_BODY_DESCRIPTOR_APPLY(TYPE, TypeName) \ 1312 case TYPE: \ 1313 return CALL_APPLY(TypeName); 1314 TORQUE_INSTANCE_TYPE_TO_BODY_DESCRIPTOR_LIST( 1315 MAKE_TORQUE_BODY_DESCRIPTOR_APPLY) 1316#undef MAKE_TORQUE_BODY_DESCRIPTOR_APPLY 1317 1318 case FILLER_TYPE: 1319 return Op::template apply<FreeSpaceFillerBodyDescriptor>( 1320 std::forward<Args>(args)...); 1321 1322 case FREE_SPACE_TYPE: 1323 return CALL_APPLY(FreeSpace); 1324 1325 default: 1326 PrintF("Unknown type: %d\n", type); 1327 UNREACHABLE(); 1328 } 1329#undef CALL_APPLY 1330} 1331 1332template <typename ObjectVisitor> 1333void HeapObject::IterateFast(PtrComprCageBase cage_base, ObjectVisitor* v) { 1334 v->VisitMapPointer(*this); 1335 IterateBodyFast(cage_base, v); 1336} 1337 1338template <typename ObjectVisitor> 1339void HeapObject::IterateFast(Map map, int object_size, ObjectVisitor* v) { 1340 v->VisitMapPointer(*this); 1341 IterateBodyFast(map, object_size, v); 1342} 1343 1344template <typename ObjectVisitor> 1345void HeapObject::IterateBodyFast(PtrComprCageBase cage_base, ObjectVisitor* v) { 1346 Map m = map(cage_base); 1347 IterateBodyFast(m, SizeFromMap(m), v); 1348} 1349 1350struct CallIterateBody { 1351 template <typename BodyDescriptor, typename ObjectVisitor> 1352 static void apply(Map map, HeapObject obj, int object_size, 1353 ObjectVisitor* v) { 1354 BodyDescriptor::IterateBody(map, obj, object_size, v); 1355 } 1356}; 1357 1358template <typename ObjectVisitor> 1359void HeapObject::IterateBodyFast(Map map, int object_size, ObjectVisitor* v) { 1360 BodyDescriptorApply<CallIterateBody>(map.instance_type(), map, *this, 1361 object_size, v); 1362} 1363 1364class EphemeronHashTable::BodyDescriptor final : public BodyDescriptorBase { 1365 public: 1366 static bool IsValidSlot(Map map, HeapObject obj, int offset) { 1367 return (offset >= EphemeronHashTable::kHeaderSize); 1368 } 1369 1370 template <typename ObjectVisitor> 1371 static inline void IterateBody(Map map, HeapObject obj, int object_size, 1372 ObjectVisitor* v) { 1373 int entries_start = EphemeronHashTable::kHeaderSize + 1374 EphemeronHashTable::kElementsStartIndex * kTaggedSize; 1375 IteratePointers(obj, EphemeronHashTable::kHeaderSize, entries_start, v); 1376 EphemeronHashTable table = EphemeronHashTable::unchecked_cast(obj); 1377 for (InternalIndex i : table.IterateEntries()) { 1378 const int key_index = EphemeronHashTable::EntryToIndex(i); 1379 const int value_index = EphemeronHashTable::EntryToValueIndex(i); 1380 IterateEphemeron(obj, i.as_int(), OffsetOfElementAt(key_index), 1381 OffsetOfElementAt(value_index), v); 1382 } 1383 } 1384 1385 static inline int SizeOf(Map map, HeapObject object) { 1386 return object.SizeFromMap(map); 1387 } 1388}; 1389 1390#include "torque-generated/objects-body-descriptors-inl.inc" 1391 1392} // namespace internal 1393} // namespace v8 1394 1395#endif // V8_OBJECTS_OBJECTS_BODY_DESCRIPTORS_INL_H_ 1396