• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_BODY_DESCRIPTORS_INL_H_
6 #define V8_OBJECTS_BODY_DESCRIPTORS_INL_H_
7 
8 #include "src/assembler-inl.h"
9 #include "src/feedback-vector.h"
10 #include "src/objects-body-descriptors.h"
11 #include "src/objects/hash-table.h"
12 #include "src/objects/js-collection.h"
13 #include "src/transitions.h"
14 #include "src/wasm/wasm-objects-inl.h"
15 
16 namespace v8 {
17 namespace internal {
18 
19 template <int start_offset>
SizeOf(Map * map,HeapObject * object)20 int FlexibleBodyDescriptor<start_offset>::SizeOf(Map* map, HeapObject* object) {
21   return object->SizeFromMap(map);
22 }
23 
IsValidSlotImpl(Map * map,HeapObject * obj,int offset)24 bool BodyDescriptorBase::IsValidSlotImpl(Map* map, HeapObject* obj,
25                                          int offset) {
26   if (!FLAG_unbox_double_fields || map->HasFastPointerLayout()) {
27     return true;
28   } else {
29     DCHECK(FLAG_unbox_double_fields);
30     DCHECK(IsAligned(offset, kPointerSize));
31 
32     LayoutDescriptorHelper helper(map);
33     DCHECK(!helper.all_fields_tagged());
34     return helper.IsTagged(offset);
35   }
36 }
37 
38 template <typename ObjectVisitor>
IterateBodyImpl(Map * map,HeapObject * obj,int start_offset,int end_offset,ObjectVisitor * v)39 void BodyDescriptorBase::IterateBodyImpl(Map* map, HeapObject* obj,
40                                          int start_offset, int end_offset,
41                                          ObjectVisitor* v) {
42   if (!FLAG_unbox_double_fields || map->HasFastPointerLayout()) {
43     IteratePointers(obj, start_offset, end_offset, v);
44   } else {
45     DCHECK(FLAG_unbox_double_fields);
46     DCHECK(IsAligned(start_offset, kPointerSize) &&
47            IsAligned(end_offset, kPointerSize));
48 
49     LayoutDescriptorHelper helper(map);
50     DCHECK(!helper.all_fields_tagged());
51     for (int offset = start_offset; offset < end_offset;) {
52       int end_of_region_offset;
53       if (helper.IsTagged(offset, end_offset, &end_of_region_offset)) {
54         IteratePointers(obj, offset, end_of_region_offset, v);
55       }
56       offset = end_of_region_offset;
57     }
58   }
59 }
60 
61 template <typename ObjectVisitor>
IteratePointers(HeapObject * obj,int start_offset,int end_offset,ObjectVisitor * v)62 DISABLE_CFI_PERF void BodyDescriptorBase::IteratePointers(HeapObject* obj,
63                                                           int start_offset,
64                                                           int end_offset,
65                                                           ObjectVisitor* v) {
66   v->VisitPointers(obj, HeapObject::RawField(obj, start_offset),
67                    HeapObject::RawField(obj, end_offset));
68 }
69 
70 template <typename ObjectVisitor>
IteratePointer(HeapObject * obj,int offset,ObjectVisitor * v)71 void BodyDescriptorBase::IteratePointer(HeapObject* obj, int offset,
72                                         ObjectVisitor* v) {
73   v->VisitPointer(obj, HeapObject::RawField(obj, offset));
74 }
75 
76 template <typename ObjectVisitor>
IterateMaybeWeakPointers(HeapObject * obj,int start_offset,int end_offset,ObjectVisitor * v)77 DISABLE_CFI_PERF void BodyDescriptorBase::IterateMaybeWeakPointers(
78     HeapObject* obj, int start_offset, int end_offset, ObjectVisitor* v) {
79   v->VisitPointers(obj, HeapObject::RawMaybeWeakField(obj, start_offset),
80                    HeapObject::RawMaybeWeakField(obj, end_offset));
81 }
82 
83 template <typename ObjectVisitor>
IterateMaybeWeakPointer(HeapObject * obj,int offset,ObjectVisitor * v)84 void BodyDescriptorBase::IterateMaybeWeakPointer(HeapObject* obj, int offset,
85                                                  ObjectVisitor* v) {
86   v->VisitPointer(obj, HeapObject::RawMaybeWeakField(obj, offset));
87 }
88 
89 class JSObject::BodyDescriptor final : public BodyDescriptorBase {
90  public:
91   static const int kStartOffset = JSReceiver::kPropertiesOrHashOffset;
92 
IsValidSlot(Map * map,HeapObject * obj,int offset)93   static bool IsValidSlot(Map* map, HeapObject* obj, int offset) {
94     if (offset < kStartOffset) return false;
95     return IsValidSlotImpl(map, obj, offset);
96   }
97 
98   template <typename ObjectVisitor>
IterateBody(Map * map,HeapObject * obj,int object_size,ObjectVisitor * v)99   static inline void IterateBody(Map* map, HeapObject* obj, int object_size,
100                                  ObjectVisitor* v) {
101     IterateBodyImpl(map, obj, kStartOffset, object_size, v);
102   }
103 
SizeOf(Map * map,HeapObject * object)104   static inline int SizeOf(Map* map, HeapObject* object) {
105     return map->instance_size();
106   }
107 };
108 
109 class JSObject::FastBodyDescriptor final : public BodyDescriptorBase {
110  public:
111   static const int kStartOffset = JSReceiver::kPropertiesOrHashOffset;
112 
IsValidSlot(Map * map,HeapObject * obj,int offset)113   static bool IsValidSlot(Map* map, HeapObject* obj, int offset) {
114     return offset >= kStartOffset;
115   }
116 
117   template <typename ObjectVisitor>
IterateBody(Map * map,HeapObject * obj,int object_size,ObjectVisitor * v)118   static inline void IterateBody(Map* map, HeapObject* obj, int object_size,
119                                  ObjectVisitor* v) {
120     IteratePointers(obj, kStartOffset, object_size, v);
121   }
122 
SizeOf(Map * map,HeapObject * object)123   static inline int SizeOf(Map* map, HeapObject* object) {
124     return map->instance_size();
125   }
126 };
127 
128 class JSFunction::BodyDescriptor final : public BodyDescriptorBase {
129  public:
IsValidSlot(Map * map,HeapObject * obj,int offset)130   static bool IsValidSlot(Map* map, HeapObject* obj, int offset) {
131     if (offset < kSizeWithoutPrototype) return true;
132     if (offset < kSizeWithPrototype && map->has_prototype_slot()) {
133       return true;
134     }
135     return IsValidSlotImpl(map, obj, offset);
136   }
137 
138   template <typename ObjectVisitor>
IterateBody(Map * map,HeapObject * obj,int object_size,ObjectVisitor * v)139   static inline void IterateBody(Map* map, HeapObject* obj, int object_size,
140                                  ObjectVisitor* v) {
141     int header_size = JSFunction::GetHeaderSize(map->has_prototype_slot());
142     DCHECK_EQ(header_size, JSObject::GetHeaderSize(map));
143     IteratePointers(obj, kPropertiesOrHashOffset, header_size, v);
144     IterateBodyImpl(map, obj, header_size, object_size, v);
145   }
146 
SizeOf(Map * map,HeapObject * object)147   static inline int SizeOf(Map* map, HeapObject* object) {
148     return map->instance_size();
149   }
150 };
151 
152 template <bool includeWeakNext>
153 class AllocationSite::BodyDescriptorImpl final : public BodyDescriptorBase {
154  public:
155   STATIC_ASSERT(AllocationSite::kCommonPointerFieldEndOffset ==
156                 AllocationSite::kPretenureDataOffset);
157   STATIC_ASSERT(AllocationSite::kPretenureDataOffset + kInt32Size ==
158                 AllocationSite::kPretenureCreateCountOffset);
159   STATIC_ASSERT(AllocationSite::kPretenureCreateCountOffset + kInt32Size ==
160                 AllocationSite::kWeakNextOffset);
161 
IsValidSlot(Map * map,HeapObject * obj,int offset)162   static bool IsValidSlot(Map* map, HeapObject* obj, int offset) {
163     if (offset >= AllocationSite::kStartOffset &&
164         offset < AllocationSite::kCommonPointerFieldEndOffset) {
165       return true;
166     }
167     // check for weak_next offset
168     if (includeWeakNext &&
169         map->instance_size() == AllocationSite::kSizeWithWeakNext &&
170         offset == AllocationSite::kWeakNextOffset) {
171       return true;
172     }
173     return false;
174   }
175 
176   template <typename ObjectVisitor>
IterateBody(Map * map,HeapObject * obj,int object_size,ObjectVisitor * v)177   static inline void IterateBody(Map* map, HeapObject* obj, int object_size,
178                                  ObjectVisitor* v) {
179     // Iterate over all the common pointer fields
180     IteratePointers(obj, AllocationSite::kStartOffset,
181                     AllocationSite::kCommonPointerFieldEndOffset, v);
182     // Skip PretenureDataOffset and PretenureCreateCount which are Int32 fields
183     // Visit weak_next only for full body descriptor and if it has weak_next
184     // field
185     if (includeWeakNext && object_size == AllocationSite::kSizeWithWeakNext)
186       IteratePointers(obj, AllocationSite::kWeakNextOffset,
187                       AllocationSite::kSizeWithWeakNext, v);
188   }
189 
SizeOf(Map * map,HeapObject * object)190   static inline int SizeOf(Map* map, HeapObject* object) {
191     return map->instance_size();
192   }
193 };
194 
195 class JSArrayBuffer::BodyDescriptor final : public BodyDescriptorBase {
196  public:
197   STATIC_ASSERT(kByteLengthOffset + kPointerSize == kBackingStoreOffset);
198   STATIC_ASSERT(kBackingStoreOffset + kPointerSize == kBitFieldSlot);
199   STATIC_ASSERT(kBitFieldSlot + kPointerSize == kSize);
200 
IsValidSlot(Map * map,HeapObject * obj,int offset)201   static bool IsValidSlot(Map* map, HeapObject* obj, int offset) {
202     if (offset < kBitFieldSlot) return true;
203     if (offset < kSize) return false;
204     return IsValidSlotImpl(map, obj, offset);
205   }
206 
207   template <typename ObjectVisitor>
IterateBody(Map * map,HeapObject * obj,int object_size,ObjectVisitor * v)208   static inline void IterateBody(Map* map, HeapObject* obj, int object_size,
209                                  ObjectVisitor* v) {
210     // Array buffers contain raw pointers that the GC does not know about. These
211     // are stored at kBackStoreOffset and later, so we do not iterate over
212     // those.
213     IteratePointers(obj, kPropertiesOrHashOffset, kBackingStoreOffset, v);
214     IterateBodyImpl(map, obj, kSize, object_size, v);
215   }
216 
SizeOf(Map * map,HeapObject * object)217   static inline int SizeOf(Map* map, HeapObject* object) {
218     return map->instance_size();
219   }
220 };
221 
222 template <typename Derived>
223 class SmallOrderedHashTable<Derived>::BodyDescriptor final
224     : public BodyDescriptorBase {
225  public:
IsValidSlot(Map * map,HeapObject * obj,int offset)226   static bool IsValidSlot(Map* map, HeapObject* obj, int offset) {
227     Derived* table = reinterpret_cast<Derived*>(obj);
228     if (offset < kDataTableStartOffset) return false;
229     if (offset >= table->GetBucketsStartOffset()) return false;
230     return IsValidSlotImpl(map, obj, offset);
231   }
232 
233   template <typename ObjectVisitor>
IterateBody(Map * map,HeapObject * obj,int object_size,ObjectVisitor * v)234   static inline void IterateBody(Map* map, HeapObject* obj, int object_size,
235                                  ObjectVisitor* v) {
236     Derived* table = reinterpret_cast<Derived*>(obj);
237 
238     int offset = kDataTableStartOffset;
239     int entry = 0;
240     for (int i = 0; i < table->Capacity(); i++) {
241       for (int j = 0; j < Derived::kEntrySize; j++) {
242         IteratePointer(obj, offset + (entry * kPointerSize), v);
243         entry++;
244       }
245     }
246   }
247 
SizeOf(Map * map,HeapObject * obj)248   static inline int SizeOf(Map* map, HeapObject* obj) {
249     Derived* table = reinterpret_cast<Derived*>(obj);
250     return table->SizeFor(table->Capacity());
251   }
252 };
253 
254 class ByteArray::BodyDescriptor final : public BodyDescriptorBase {
255  public:
IsValidSlot(Map * map,HeapObject * obj,int offset)256   static bool IsValidSlot(Map* map, HeapObject* obj, int offset) {
257     return false;
258   }
259 
260   template <typename ObjectVisitor>
IterateBody(Map * map,HeapObject * obj,int object_size,ObjectVisitor * v)261   static inline void IterateBody(Map* map, HeapObject* obj, int object_size,
262                                  ObjectVisitor* v) {}
263 
SizeOf(Map * map,HeapObject * obj)264   static inline int SizeOf(Map* map, HeapObject* obj) {
265     return ByteArray::SizeFor(ByteArray::cast(obj)->synchronized_length());
266   }
267 };
268 
269 class BytecodeArray::BodyDescriptor final : public BodyDescriptorBase {
270  public:
IsValidSlot(Map * map,HeapObject * obj,int offset)271   static bool IsValidSlot(Map* map, HeapObject* obj, int offset) {
272     return offset >= kConstantPoolOffset &&
273            offset <= kSourcePositionTableOffset;
274   }
275 
276   template <typename ObjectVisitor>
IterateBody(Map * map,HeapObject * obj,int object_size,ObjectVisitor * v)277   static inline void IterateBody(Map* map, HeapObject* obj, int object_size,
278                                  ObjectVisitor* v) {
279     IteratePointer(obj, kConstantPoolOffset, v);
280     IteratePointer(obj, kHandlerTableOffset, v);
281     IteratePointer(obj, kSourcePositionTableOffset, v);
282   }
283 
SizeOf(Map * map,HeapObject * obj)284   static inline int SizeOf(Map* map, HeapObject* obj) {
285     return BytecodeArray::SizeFor(
286         BytecodeArray::cast(obj)->synchronized_length());
287   }
288 };
289 
290 class BigInt::BodyDescriptor final : public BodyDescriptorBase {
291  public:
IsValidSlot(Map * map,HeapObject * obj,int offset)292   static bool IsValidSlot(Map* map, HeapObject* obj, int offset) {
293     return false;
294   }
295 
296   template <typename ObjectVisitor>
IterateBody(Map * map,HeapObject * obj,int object_size,ObjectVisitor * v)297   static inline void IterateBody(Map* map, HeapObject* obj, int object_size,
298                                  ObjectVisitor* v) {}
299 
SizeOf(Map * map,HeapObject * obj)300   static inline int SizeOf(Map* map, HeapObject* obj) {
301     return BigInt::SizeFor(BigInt::cast(obj)->length());
302   }
303 };
304 
305 class FixedDoubleArray::BodyDescriptor final : public BodyDescriptorBase {
306  public:
IsValidSlot(Map * map,HeapObject * obj,int offset)307   static bool IsValidSlot(Map* map, HeapObject* obj, int offset) {
308     return false;
309   }
310 
311   template <typename ObjectVisitor>
IterateBody(Map * map,HeapObject * obj,int object_size,ObjectVisitor * v)312   static inline void IterateBody(Map* map, HeapObject* obj, int object_size,
313                                  ObjectVisitor* v) {}
314 
SizeOf(Map * map,HeapObject * obj)315   static inline int SizeOf(Map* map, HeapObject* obj) {
316     return FixedDoubleArray::SizeFor(
317         FixedDoubleArray::cast(obj)->synchronized_length());
318   }
319 };
320 
321 class FixedTypedArrayBase::BodyDescriptor final : public BodyDescriptorBase {
322  public:
IsValidSlot(Map * map,HeapObject * obj,int offset)323   static bool IsValidSlot(Map* map, HeapObject* obj, int offset) {
324     return offset == kBasePointerOffset;
325   }
326 
327   template <typename ObjectVisitor>
IterateBody(Map * map,HeapObject * obj,int object_size,ObjectVisitor * v)328   static inline void IterateBody(Map* map, HeapObject* obj, int object_size,
329                                  ObjectVisitor* v) {
330     IteratePointer(obj, kBasePointerOffset, v);
331   }
332 
SizeOf(Map * map,HeapObject * object)333   static inline int SizeOf(Map* map, HeapObject* object) {
334     return FixedTypedArrayBase::cast(object)->size();
335   }
336 };
337 
338 class WeakArrayBodyDescriptor final : public BodyDescriptorBase {
339  public:
IsValidSlot(Map * map,HeapObject * obj,int offset)340   static bool IsValidSlot(Map* map, HeapObject* obj, int offset) {
341     return true;
342   }
343 
344   template <typename ObjectVisitor>
IterateBody(Map * map,HeapObject * obj,int object_size,ObjectVisitor * v)345   static inline void IterateBody(Map* map, HeapObject* obj, int object_size,
346                                  ObjectVisitor* v) {
347     IterateMaybeWeakPointers(obj, HeapObject::kHeaderSize, object_size, v);
348   }
349 
SizeOf(Map * map,HeapObject * object)350   static inline int SizeOf(Map* map, HeapObject* object) {
351     return object->SizeFromMap(map);
352   }
353 };
354 
355 class FeedbackMetadata::BodyDescriptor final : public BodyDescriptorBase {
356  public:
IsValidSlot(Map * map,HeapObject * obj,int offset)357   static bool IsValidSlot(Map* map, HeapObject* obj, int offset) {
358     return false;
359   }
360 
361   template <typename ObjectVisitor>
IterateBody(Map * map,HeapObject * obj,int object_size,ObjectVisitor * v)362   static inline void IterateBody(Map* map, HeapObject* obj, int object_size,
363                                  ObjectVisitor* v) {}
364 
SizeOf(Map * map,HeapObject * obj)365   static inline int SizeOf(Map* map, HeapObject* obj) {
366     return FeedbackMetadata::SizeFor(
367         FeedbackMetadata::cast(obj)->synchronized_slot_count());
368   }
369 };
370 
371 class FeedbackVector::BodyDescriptor final : public BodyDescriptorBase {
372  public:
IsValidSlot(Map * map,HeapObject * obj,int offset)373   static bool IsValidSlot(Map* map, HeapObject* obj, int offset) {
374     return offset == kSharedFunctionInfoOffset ||
375            offset == kOptimizedCodeOffset || offset >= kFeedbackSlotsOffset;
376   }
377 
378   template <typename ObjectVisitor>
IterateBody(Map * map,HeapObject * obj,int object_size,ObjectVisitor * v)379   static inline void IterateBody(Map* map, HeapObject* obj, int object_size,
380                                  ObjectVisitor* v) {
381     IteratePointer(obj, kSharedFunctionInfoOffset, v);
382     IterateMaybeWeakPointer(obj, kOptimizedCodeOffset, v);
383     IterateMaybeWeakPointers(obj, kFeedbackSlotsOffset, object_size, v);
384   }
385 
SizeOf(Map * map,HeapObject * obj)386   static inline int SizeOf(Map* map, HeapObject* obj) {
387     return FeedbackVector::SizeFor(FeedbackVector::cast(obj)->length());
388   }
389 };
390 
391 class PreParsedScopeData::BodyDescriptor final : public BodyDescriptorBase {
392  public:
IsValidSlot(Map * map,HeapObject * obj,int offset)393   static bool IsValidSlot(Map* map, HeapObject* obj, int offset) {
394     return offset == kScopeDataOffset || offset >= kChildDataStartOffset;
395   }
396 
397   template <typename ObjectVisitor>
IterateBody(Map * map,HeapObject * obj,int object_size,ObjectVisitor * v)398   static inline void IterateBody(Map* map, HeapObject* obj, int object_size,
399                                  ObjectVisitor* v) {
400     IteratePointer(obj, kScopeDataOffset, v);
401     IteratePointers(obj, kChildDataStartOffset, object_size, v);
402   }
403 
SizeOf(Map * map,HeapObject * obj)404   static inline int SizeOf(Map* map, HeapObject* obj) {
405     return PreParsedScopeData::SizeFor(PreParsedScopeData::cast(obj)->length());
406   }
407 };
408 
409 class PrototypeInfo::BodyDescriptor final : public BodyDescriptorBase {
410  public:
IsValidSlot(Map * map,HeapObject * obj,int offset)411   static bool IsValidSlot(Map* map, HeapObject* obj, int offset) {
412     return offset >= HeapObject::kHeaderSize;
413   }
414 
415   template <typename ObjectVisitor>
IterateBody(Map * map,HeapObject * obj,int object_size,ObjectVisitor * v)416   static inline void IterateBody(Map* map, HeapObject* obj, int object_size,
417                                  ObjectVisitor* v) {
418     IteratePointers(obj, HeapObject::kHeaderSize, kObjectCreateMapOffset, v);
419     IterateMaybeWeakPointer(obj, kObjectCreateMapOffset, v);
420     IteratePointers(obj, kObjectCreateMapOffset + kPointerSize, object_size, v);
421   }
422 
SizeOf(Map * map,HeapObject * obj)423   static inline int SizeOf(Map* map, HeapObject* obj) {
424     return obj->SizeFromMap(map);
425   }
426 };
427 
428 class JSWeakCollection::BodyDescriptorImpl final : public BodyDescriptorBase {
429  public:
430   STATIC_ASSERT(kTableOffset + kPointerSize == kSize);
431 
IsValidSlot(Map * map,HeapObject * obj,int offset)432   static bool IsValidSlot(Map* map, HeapObject* obj, int offset) {
433     return IsValidSlotImpl(map, obj, offset);
434   }
435 
436   template <typename ObjectVisitor>
IterateBody(Map * map,HeapObject * obj,int object_size,ObjectVisitor * v)437   static inline void IterateBody(Map* map, HeapObject* obj, int object_size,
438                                  ObjectVisitor* v) {
439     IterateBodyImpl(map, obj, kPropertiesOrHashOffset, object_size, v);
440   }
441 
SizeOf(Map * map,HeapObject * object)442   static inline int SizeOf(Map* map, HeapObject* object) {
443     return map->instance_size();
444   }
445 };
446 
447 class Foreign::BodyDescriptor final : public BodyDescriptorBase {
448  public:
IsValidSlot(Map * map,HeapObject * obj,int offset)449   static bool IsValidSlot(Map* map, HeapObject* obj, int offset) {
450     return false;
451   }
452 
453   template <typename ObjectVisitor>
IterateBody(Map * map,HeapObject * obj,int object_size,ObjectVisitor * v)454   static inline void IterateBody(Map* map, HeapObject* obj, int object_size,
455                                  ObjectVisitor* v) {
456     v->VisitExternalReference(Foreign::cast(obj),
457                               reinterpret_cast<Address*>(HeapObject::RawField(
458                                   obj, kForeignAddressOffset)));
459   }
460 
SizeOf(Map * map,HeapObject * object)461   static inline int SizeOf(Map* map, HeapObject* object) { return kSize; }
462 };
463 
464 class ExternalOneByteString::BodyDescriptor final : public BodyDescriptorBase {
465  public:
IsValidSlot(Map * map,HeapObject * obj,int offset)466   static bool IsValidSlot(Map* map, HeapObject* obj, int offset) {
467     return false;
468   }
469 
470   template <typename ObjectVisitor>
IterateBody(Map * map,HeapObject * obj,int object_size,ObjectVisitor * v)471   static inline void IterateBody(Map* map, HeapObject* obj, int object_size,
472                                  ObjectVisitor* v) {}
473 
SizeOf(Map * map,HeapObject * object)474   static inline int SizeOf(Map* map, HeapObject* object) { return kSize; }
475 };
476 
477 class ExternalTwoByteString::BodyDescriptor final : public BodyDescriptorBase {
478  public:
IsValidSlot(Map * map,HeapObject * obj,int offset)479   static bool IsValidSlot(Map* map, HeapObject* obj, int offset) {
480     return false;
481   }
482 
483   template <typename ObjectVisitor>
IterateBody(Map * map,HeapObject * obj,int object_size,ObjectVisitor * v)484   static inline void IterateBody(Map* map, HeapObject* obj, int object_size,
485                                  ObjectVisitor* v) {}
486 
SizeOf(Map * map,HeapObject * object)487   static inline int SizeOf(Map* map, HeapObject* object) { return kSize; }
488 };
489 
490 class Code::BodyDescriptor final : public BodyDescriptorBase {
491  public:
492   STATIC_ASSERT(kRelocationInfoOffset + kPointerSize ==
493                 kDeoptimizationDataOffset);
494   STATIC_ASSERT(kDeoptimizationDataOffset + kPointerSize ==
495                 kSourcePositionTableOffset);
496   STATIC_ASSERT(kSourcePositionTableOffset + kPointerSize ==
497                 kCodeDataContainerOffset);
498   STATIC_ASSERT(kCodeDataContainerOffset + kPointerSize == kDataStart);
499 
IsValidSlot(Map * map,HeapObject * obj,int offset)500   static bool IsValidSlot(Map* map, HeapObject* obj, int offset) {
501     // Slots in code can't be invalid because we never trim code objects.
502     return true;
503   }
504 
505   template <typename ObjectVisitor>
IterateBody(Map * map,HeapObject * obj,ObjectVisitor * v)506   static inline void IterateBody(Map* map, HeapObject* obj, ObjectVisitor* v) {
507     int mode_mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET) |
508                     RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
509                     RelocInfo::ModeMask(RelocInfo::EXTERNAL_REFERENCE) |
510                     RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE) |
511                     RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE_ENCODED) |
512                     RelocInfo::ModeMask(RelocInfo::OFF_HEAP_TARGET) |
513                     RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY);
514 
515     // GC does not visit data/code in the header and in the body directly.
516     IteratePointers(obj, kRelocationInfoOffset, kDataStart, v);
517 
518     RelocIterator it(Code::cast(obj), mode_mask);
519     v->VisitRelocInfo(&it);
520   }
521 
522   template <typename ObjectVisitor>
IterateBody(Map * map,HeapObject * obj,int object_size,ObjectVisitor * v)523   static inline void IterateBody(Map* map, HeapObject* obj, int object_size,
524                                  ObjectVisitor* v) {
525     IterateBody(map, obj, v);
526   }
527 
SizeOf(Map * map,HeapObject * object)528   static inline int SizeOf(Map* map, HeapObject* object) {
529     return reinterpret_cast<Code*>(object)->CodeSize();
530   }
531 };
532 
533 class SeqOneByteString::BodyDescriptor final : public BodyDescriptorBase {
534  public:
IsValidSlot(Map * map,HeapObject * obj,int offset)535   static bool IsValidSlot(Map* map, HeapObject* obj, int offset) {
536     return false;
537   }
538 
539   template <typename ObjectVisitor>
IterateBody(Map * map,HeapObject * obj,int object_size,ObjectVisitor * v)540   static inline void IterateBody(Map* map, HeapObject* obj, int object_size,
541                                  ObjectVisitor* v) {}
542 
SizeOf(Map * map,HeapObject * obj)543   static inline int SizeOf(Map* map, HeapObject* obj) {
544     SeqOneByteString* string = SeqOneByteString::cast(obj);
545     return string->SizeFor(string->synchronized_length());
546   }
547 };
548 
549 class SeqTwoByteString::BodyDescriptor final : public BodyDescriptorBase {
550  public:
IsValidSlot(Map * map,HeapObject * obj,int offset)551   static bool IsValidSlot(Map* map, HeapObject* obj, int offset) {
552     return false;
553   }
554 
555   template <typename ObjectVisitor>
IterateBody(Map * map,HeapObject * obj,int object_size,ObjectVisitor * v)556   static inline void IterateBody(Map* map, HeapObject* obj, int object_size,
557                                  ObjectVisitor* v) {}
558 
SizeOf(Map * map,HeapObject * obj)559   static inline int SizeOf(Map* map, HeapObject* obj) {
560     SeqTwoByteString* string = SeqTwoByteString::cast(obj);
561     return string->SizeFor(string->synchronized_length());
562   }
563 };
564 
565 class WasmInstanceObject::BodyDescriptor final : public BodyDescriptorBase {
566  public:
IsValidSlot(Map * map,HeapObject * obj,int offset)567   static bool IsValidSlot(Map* map, HeapObject* obj, int offset) {
568     if (offset < kMemoryStartOffset) return true;
569     if (offset < kModuleObjectOffset) return false;
570     return IsValidSlotImpl(map, obj, offset);
571   }
572 
573   template <typename ObjectVisitor>
IterateBody(Map * map,HeapObject * obj,int object_size,ObjectVisitor * v)574   static inline void IterateBody(Map* map, HeapObject* obj, int object_size,
575                                  ObjectVisitor* v) {
576     IteratePointers(obj, kPropertiesOrHashOffset, kFirstUntaggedOffset, v);
577     IterateBodyImpl(map, obj, kSize, object_size, v);
578   }
579 
SizeOf(Map * map,HeapObject * object)580   static inline int SizeOf(Map* map, HeapObject* object) {
581     return map->instance_size();
582   }
583 };
584 
585 class Map::BodyDescriptor final : public BodyDescriptorBase {
586  public:
IsValidSlot(Map * map,HeapObject * obj,int offset)587   static bool IsValidSlot(Map* map, HeapObject* obj, int offset) {
588     return offset >= Map::kPointerFieldsBeginOffset &&
589            offset < Map::kPointerFieldsEndOffset;
590   }
591 
592   template <typename ObjectVisitor>
IterateBody(Map * map,HeapObject * obj,int object_size,ObjectVisitor * v)593   static inline void IterateBody(Map* map, HeapObject* obj, int object_size,
594                                  ObjectVisitor* v) {
595     IteratePointers(obj, Map::kPointerFieldsBeginOffset,
596                     Map::kTransitionsOrPrototypeInfoOffset, v);
597     IterateMaybeWeakPointer(obj, kTransitionsOrPrototypeInfoOffset, v);
598     IteratePointers(obj, Map::kTransitionsOrPrototypeInfoOffset + kPointerSize,
599                     Map::kPointerFieldsEndOffset, v);
600   }
601 
SizeOf(Map * map,HeapObject * obj)602   static inline int SizeOf(Map* map, HeapObject* obj) { return Map::kSize; }
603 };
604 
605 class DataHandler::BodyDescriptor final : public BodyDescriptorBase {
606  public:
IsValidSlot(Map * map,HeapObject * obj,int offset)607   static bool IsValidSlot(Map* map, HeapObject* obj, int offset) {
608     return offset >= HeapObject::kHeaderSize;
609   }
610 
611   template <typename ObjectVisitor>
IterateBody(Map * map,HeapObject * obj,int object_size,ObjectVisitor * v)612   static inline void IterateBody(Map* map, HeapObject* obj, int object_size,
613                                  ObjectVisitor* v) {
614     static_assert(kSmiHandlerOffset < kData1Offset,
615                   "Field order must be in sync with this iteration code");
616     static_assert(kData1Offset < kSizeWithData1,
617                   "Field order must be in sync with this iteration code");
618     IteratePointers(obj, kSmiHandlerOffset, kData1Offset, v);
619     IterateMaybeWeakPointers(obj, kData1Offset, object_size, v);
620   }
621 
SizeOf(Map * map,HeapObject * object)622   static inline int SizeOf(Map* map, HeapObject* object) {
623     return object->SizeFromMap(map);
624   }
625 };
626 
627 template <typename Op, typename ReturnType, typename T1, typename T2,
628           typename T3, typename T4>
BodyDescriptorApply(InstanceType type,T1 p1,T2 p2,T3 p3,T4 p4)629 ReturnType BodyDescriptorApply(InstanceType type, T1 p1, T2 p2, T3 p3, T4 p4) {
630   if (type < FIRST_NONSTRING_TYPE) {
631     switch (type & kStringRepresentationMask) {
632       case kSeqStringTag:
633         return ReturnType();
634       case kConsStringTag:
635         return Op::template apply<ConsString::BodyDescriptor>(p1, p2, p3, p4);
636       case kThinStringTag:
637         return Op::template apply<ThinString::BodyDescriptor>(p1, p2, p3, p4);
638       case kSlicedStringTag:
639         return Op::template apply<SlicedString::BodyDescriptor>(p1, p2, p3, p4);
640       case kExternalStringTag:
641         if ((type & kStringEncodingMask) == kOneByteStringTag) {
642           return Op::template apply<ExternalOneByteString::BodyDescriptor>(
643               p1, p2, p3, p4);
644         } else {
645           return Op::template apply<ExternalTwoByteString::BodyDescriptor>(
646               p1, p2, p3, p4);
647         }
648     }
649     UNREACHABLE();
650   }
651 
652   switch (type) {
653     case FIXED_ARRAY_TYPE:
654     case OBJECT_BOILERPLATE_DESCRIPTION_TYPE:
655     case HASH_TABLE_TYPE:
656     case ORDERED_HASH_MAP_TYPE:
657     case ORDERED_HASH_SET_TYPE:
658     case NAME_DICTIONARY_TYPE:
659     case GLOBAL_DICTIONARY_TYPE:
660     case NUMBER_DICTIONARY_TYPE:
661     case SIMPLE_NUMBER_DICTIONARY_TYPE:
662     case STRING_TABLE_TYPE:
663     case EPHEMERON_HASH_TABLE_TYPE:
664     case SCOPE_INFO_TYPE:
665     case SCRIPT_CONTEXT_TABLE_TYPE:
666     case BLOCK_CONTEXT_TYPE:
667     case CATCH_CONTEXT_TYPE:
668     case DEBUG_EVALUATE_CONTEXT_TYPE:
669     case EVAL_CONTEXT_TYPE:
670     case FUNCTION_CONTEXT_TYPE:
671     case MODULE_CONTEXT_TYPE:
672     case NATIVE_CONTEXT_TYPE:
673     case SCRIPT_CONTEXT_TYPE:
674     case WITH_CONTEXT_TYPE:
675       return Op::template apply<FixedArray::BodyDescriptor>(p1, p2, p3, p4);
676     case WEAK_FIXED_ARRAY_TYPE:
677       return Op::template apply<WeakFixedArray::BodyDescriptor>(p1, p2, p3, p4);
678     case WEAK_ARRAY_LIST_TYPE:
679       return Op::template apply<WeakArrayList::BodyDescriptor>(p1, p2, p3, p4);
680     case FIXED_DOUBLE_ARRAY_TYPE:
681       return ReturnType();
682     case FEEDBACK_METADATA_TYPE:
683       return Op::template apply<FeedbackMetadata::BodyDescriptor>(p1, p2, p3,
684                                                                   p4);
685     case PROPERTY_ARRAY_TYPE:
686       return Op::template apply<PropertyArray::BodyDescriptor>(p1, p2, p3, p4);
687     case DESCRIPTOR_ARRAY_TYPE:
688       return Op::template apply<DescriptorArray::BodyDescriptor>(p1, p2, p3,
689                                                                  p4);
690     case TRANSITION_ARRAY_TYPE:
691       return Op::template apply<TransitionArray::BodyDescriptor>(p1, p2, p3,
692                                                                  p4);
693     case FEEDBACK_CELL_TYPE:
694       return Op::template apply<FeedbackCell::BodyDescriptor>(p1, p2, p3, p4);
695     case FEEDBACK_VECTOR_TYPE:
696       return Op::template apply<FeedbackVector::BodyDescriptor>(p1, p2, p3, p4);
697     case JS_OBJECT_TYPE:
698     case JS_ERROR_TYPE:
699     case JS_ARGUMENTS_TYPE:
700     case JS_ASYNC_FROM_SYNC_ITERATOR_TYPE:
701     case JS_PROMISE_TYPE:
702     case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
703     case JS_GENERATOR_OBJECT_TYPE:
704     case JS_ASYNC_GENERATOR_OBJECT_TYPE:
705     case JS_VALUE_TYPE:
706     case JS_DATE_TYPE:
707     case JS_ARRAY_TYPE:
708     case JS_ARRAY_ITERATOR_TYPE:
709     case JS_MODULE_NAMESPACE_TYPE:
710     case JS_TYPED_ARRAY_TYPE:
711     case JS_DATA_VIEW_TYPE:
712     case JS_SET_TYPE:
713     case JS_MAP_TYPE:
714     case JS_SET_KEY_VALUE_ITERATOR_TYPE:
715     case JS_SET_VALUE_ITERATOR_TYPE:
716     case JS_MAP_KEY_ITERATOR_TYPE:
717     case JS_MAP_KEY_VALUE_ITERATOR_TYPE:
718     case JS_MAP_VALUE_ITERATOR_TYPE:
719     case JS_STRING_ITERATOR_TYPE:
720     case JS_REGEXP_STRING_ITERATOR_TYPE:
721     case JS_REGEXP_TYPE:
722     case JS_GLOBAL_PROXY_TYPE:
723     case JS_GLOBAL_OBJECT_TYPE:
724     case JS_API_OBJECT_TYPE:
725     case JS_SPECIAL_API_OBJECT_TYPE:
726     case JS_MESSAGE_OBJECT_TYPE:
727     case JS_BOUND_FUNCTION_TYPE:
728 #ifdef V8_INTL_SUPPORT
729     case JS_INTL_COLLATOR_TYPE:
730     case JS_INTL_LIST_FORMAT_TYPE:
731     case JS_INTL_LOCALE_TYPE:
732     case JS_INTL_PLURAL_RULES_TYPE:
733     case JS_INTL_RELATIVE_TIME_FORMAT_TYPE:
734 #endif  // V8_INTL_SUPPORT
735     case WASM_GLOBAL_TYPE:
736     case WASM_MEMORY_TYPE:
737     case WASM_MODULE_TYPE:
738     case WASM_TABLE_TYPE:
739       return Op::template apply<JSObject::BodyDescriptor>(p1, p2, p3, p4);
740     case WASM_INSTANCE_TYPE:
741       return Op::template apply<WasmInstanceObject::BodyDescriptor>(p1, p2, p3,
742                                                                     p4);
743     case JS_WEAK_MAP_TYPE:
744     case JS_WEAK_SET_TYPE:
745       return Op::template apply<JSWeakCollection::BodyDescriptor>(p1, p2, p3,
746                                                                   p4);
747     case JS_ARRAY_BUFFER_TYPE:
748       return Op::template apply<JSArrayBuffer::BodyDescriptor>(p1, p2, p3, p4);
749     case JS_FUNCTION_TYPE:
750       return Op::template apply<JSFunction::BodyDescriptor>(p1, p2, p3, p4);
751     case ODDBALL_TYPE:
752       return Op::template apply<Oddball::BodyDescriptor>(p1, p2, p3, p4);
753     case JS_PROXY_TYPE:
754       return Op::template apply<JSProxy::BodyDescriptor>(p1, p2, p3, p4);
755     case FOREIGN_TYPE:
756       return Op::template apply<Foreign::BodyDescriptor>(p1, p2, p3, p4);
757     case MAP_TYPE:
758       return Op::template apply<Map::BodyDescriptor>(p1, p2, p3, p4);
759     case CODE_TYPE:
760       return Op::template apply<Code::BodyDescriptor>(p1, p2, p3, p4);
761     case CELL_TYPE:
762       return Op::template apply<Cell::BodyDescriptor>(p1, p2, p3, p4);
763     case PROPERTY_CELL_TYPE:
764       return Op::template apply<PropertyCell::BodyDescriptor>(p1, p2, p3, p4);
765     case SYMBOL_TYPE:
766       return Op::template apply<Symbol::BodyDescriptor>(p1, p2, p3, p4);
767     case BYTECODE_ARRAY_TYPE:
768       return Op::template apply<BytecodeArray::BodyDescriptor>(p1, p2, p3, p4);
769     case SMALL_ORDERED_HASH_SET_TYPE:
770       return Op::template apply<
771           SmallOrderedHashTable<SmallOrderedHashSet>::BodyDescriptor>(p1, p2,
772                                                                       p3, p4);
773     case SMALL_ORDERED_HASH_MAP_TYPE:
774       return Op::template apply<
775           SmallOrderedHashTable<SmallOrderedHashMap>::BodyDescriptor>(p1, p2,
776                                                                       p3, p4);
777     case CODE_DATA_CONTAINER_TYPE:
778       return Op::template apply<CodeDataContainer::BodyDescriptor>(p1, p2, p3,
779                                                                    p4);
780     case PRE_PARSED_SCOPE_DATA_TYPE:
781       return Op::template apply<PreParsedScopeData::BodyDescriptor>(p1, p2, p3,
782                                                                     p4);
783     case UNCOMPILED_DATA_WITHOUT_PRE_PARSED_SCOPE_TYPE:
784       return Op::template apply<
785           UncompiledDataWithoutPreParsedScope::BodyDescriptor>(p1, p2, p3, p4);
786     case UNCOMPILED_DATA_WITH_PRE_PARSED_SCOPE_TYPE:
787       return Op::template apply<
788           UncompiledDataWithPreParsedScope::BodyDescriptor>(p1, p2, p3, p4);
789     case HEAP_NUMBER_TYPE:
790     case MUTABLE_HEAP_NUMBER_TYPE:
791     case FILLER_TYPE:
792     case BYTE_ARRAY_TYPE:
793     case FREE_SPACE_TYPE:
794     case BIGINT_TYPE:
795       return ReturnType();
796 
797 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype)                              \
798   case FIXED_##TYPE##_ARRAY_TYPE:                                              \
799     return Op::template apply<FixedTypedArrayBase::BodyDescriptor>(p1, p2, p3, \
800                                                                    p4);
801       TYPED_ARRAYS(TYPED_ARRAY_CASE)
802 #undef TYPED_ARRAY_CASE
803 
804     case SHARED_FUNCTION_INFO_TYPE: {
805       return Op::template apply<SharedFunctionInfo::BodyDescriptor>(p1, p2, p3,
806                                                                     p4);
807     }
808     case ALLOCATION_SITE_TYPE:
809       return Op::template apply<AllocationSite::BodyDescriptor>(p1, p2, p3, p4);
810 
811 #define MAKE_STRUCT_CASE(NAME, Name, name) case NAME##_TYPE:
812       STRUCT_LIST(MAKE_STRUCT_CASE)
813 #undef MAKE_STRUCT_CASE
814       if (type == PROTOTYPE_INFO_TYPE) {
815         return Op::template apply<PrototypeInfo::BodyDescriptor>(p1, p2, p3,
816                                                                  p4);
817       } else {
818         return Op::template apply<StructBodyDescriptor>(p1, p2, p3, p4);
819       }
820     case CALL_HANDLER_INFO_TYPE:
821       return Op::template apply<StructBodyDescriptor>(p1, p2, p3, p4);
822     case LOAD_HANDLER_TYPE:
823     case STORE_HANDLER_TYPE:
824       return Op::template apply<DataHandler::BodyDescriptor>(p1, p2, p3, p4);
825     default:
826       PrintF("Unknown type: %d\n", type);
827       UNREACHABLE();
828   }
829 }
830 
831 
832 template <typename ObjectVisitor>
IterateFast(ObjectVisitor * v)833 void HeapObject::IterateFast(ObjectVisitor* v) {
834   BodyDescriptorBase::IteratePointer(this, kMapOffset, v);
835   IterateBodyFast(v);
836 }
837 
838 
839 template <typename ObjectVisitor>
IterateBodyFast(ObjectVisitor * v)840 void HeapObject::IterateBodyFast(ObjectVisitor* v) {
841   Map* m = map();
842   IterateBodyFast(m, SizeFromMap(m), v);
843 }
844 
845 
846 struct CallIterateBody {
847   template <typename BodyDescriptor, typename ObjectVisitor>
applyCallIterateBody848   static void apply(Map* map, HeapObject* obj, int object_size,
849                     ObjectVisitor* v) {
850     BodyDescriptor::IterateBody(map, obj, object_size, v);
851   }
852 };
853 
854 template <typename ObjectVisitor>
IterateBodyFast(Map * map,int object_size,ObjectVisitor * v)855 void HeapObject::IterateBodyFast(Map* map, int object_size, ObjectVisitor* v) {
856   BodyDescriptorApply<CallIterateBody, void>(map->instance_type(), map, this,
857                                              object_size, v);
858 }
859 }  // namespace internal
860 }  // namespace v8
861 
862 #endif  // V8_OBJECTS_BODY_DESCRIPTORS_INL_H_
863