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/objects-body-descriptors.h"
9 
10 namespace v8 {
11 namespace internal {
12 
13 template <int start_offset>
SizeOf(Map * map,HeapObject * object)14 int FlexibleBodyDescriptor<start_offset>::SizeOf(Map* map, HeapObject* object) {
15   return object->SizeFromMap(map);
16 }
17 
18 
IsValidSlotImpl(HeapObject * obj,int offset)19 bool BodyDescriptorBase::IsValidSlotImpl(HeapObject* obj, int offset) {
20   if (!FLAG_unbox_double_fields || obj->map()->HasFastPointerLayout()) {
21     return true;
22   } else {
23     DCHECK(FLAG_unbox_double_fields);
24     DCHECK(IsAligned(offset, kPointerSize));
25 
26     LayoutDescriptorHelper helper(obj->map());
27     DCHECK(!helper.all_fields_tagged());
28     return helper.IsTagged(offset);
29   }
30 }
31 
32 template <typename ObjectVisitor>
IterateBodyImpl(HeapObject * obj,int start_offset,int end_offset,ObjectVisitor * v)33 void BodyDescriptorBase::IterateBodyImpl(HeapObject* obj, int start_offset,
34                                          int end_offset, ObjectVisitor* v) {
35   if (!FLAG_unbox_double_fields || obj->map()->HasFastPointerLayout()) {
36     IteratePointers(obj, start_offset, end_offset, v);
37   } else {
38     DCHECK(FLAG_unbox_double_fields);
39     DCHECK(IsAligned(start_offset, kPointerSize) &&
40            IsAligned(end_offset, kPointerSize));
41 
42     LayoutDescriptorHelper helper(obj->map());
43     DCHECK(!helper.all_fields_tagged());
44     for (int offset = start_offset; offset < end_offset;) {
45       int end_of_region_offset;
46       if (helper.IsTagged(offset, end_offset, &end_of_region_offset)) {
47         IteratePointers(obj, offset, end_of_region_offset, v);
48       }
49       offset = end_of_region_offset;
50     }
51   }
52 }
53 
54 
55 template <typename StaticVisitor>
IterateBodyImpl(Heap * heap,HeapObject * obj,int start_offset,int end_offset)56 void BodyDescriptorBase::IterateBodyImpl(Heap* heap, HeapObject* obj,
57                                          int start_offset, int end_offset) {
58   if (!FLAG_unbox_double_fields || obj->map()->HasFastPointerLayout()) {
59     IteratePointers<StaticVisitor>(heap, obj, start_offset, end_offset);
60   } else {
61     DCHECK(FLAG_unbox_double_fields);
62     DCHECK(IsAligned(start_offset, kPointerSize) &&
63            IsAligned(end_offset, kPointerSize));
64 
65     LayoutDescriptorHelper helper(obj->map());
66     DCHECK(!helper.all_fields_tagged());
67     for (int offset = start_offset; offset < end_offset;) {
68       int end_of_region_offset;
69       if (helper.IsTagged(offset, end_offset, &end_of_region_offset)) {
70         IteratePointers<StaticVisitor>(heap, obj, offset, end_of_region_offset);
71       }
72       offset = end_of_region_offset;
73     }
74   }
75 }
76 
77 
78 template <typename ObjectVisitor>
IteratePointers(HeapObject * obj,int start_offset,int end_offset,ObjectVisitor * v)79 void BodyDescriptorBase::IteratePointers(HeapObject* obj, int start_offset,
80                                          int end_offset, ObjectVisitor* v) {
81   v->VisitPointers(HeapObject::RawField(obj, start_offset),
82                    HeapObject::RawField(obj, end_offset));
83 }
84 
85 
86 template <typename StaticVisitor>
IteratePointers(Heap * heap,HeapObject * obj,int start_offset,int end_offset)87 void BodyDescriptorBase::IteratePointers(Heap* heap, HeapObject* obj,
88                                          int start_offset, int end_offset) {
89   StaticVisitor::VisitPointers(heap, obj,
90                                HeapObject::RawField(obj, start_offset),
91                                HeapObject::RawField(obj, end_offset));
92 }
93 
94 
95 template <typename ObjectVisitor>
IteratePointer(HeapObject * obj,int offset,ObjectVisitor * v)96 void BodyDescriptorBase::IteratePointer(HeapObject* obj, int offset,
97                                         ObjectVisitor* v) {
98   v->VisitPointer(HeapObject::RawField(obj, offset));
99 }
100 
101 
102 template <typename StaticVisitor>
IteratePointer(Heap * heap,HeapObject * obj,int offset)103 void BodyDescriptorBase::IteratePointer(Heap* heap, HeapObject* obj,
104                                         int offset) {
105   StaticVisitor::VisitPointer(heap, obj, HeapObject::RawField(obj, offset));
106 }
107 
108 
109 // Iterates the function object according to the visiting policy.
110 template <JSFunction::BodyVisitingPolicy body_visiting_policy>
111 class JSFunction::BodyDescriptorImpl final : public BodyDescriptorBase {
112  public:
113   STATIC_ASSERT(kNonWeakFieldsEndOffset == kCodeEntryOffset);
114   STATIC_ASSERT(kCodeEntryOffset + kPointerSize == kNextFunctionLinkOffset);
115   STATIC_ASSERT(kNextFunctionLinkOffset + kPointerSize == kSize);
116 
IsValidSlot(HeapObject * obj,int offset)117   static bool IsValidSlot(HeapObject* obj, int offset) {
118     if (offset < kSize) return true;
119     return IsValidSlotImpl(obj, offset);
120   }
121 
122   template <typename ObjectVisitor>
IterateBody(HeapObject * obj,int object_size,ObjectVisitor * v)123   static inline void IterateBody(HeapObject* obj, int object_size,
124                                  ObjectVisitor* v) {
125     IteratePointers(obj, kPropertiesOffset, kNonWeakFieldsEndOffset, v);
126 
127     if (body_visiting_policy & kVisitCodeEntry) {
128       v->VisitCodeEntry(obj->address() + kCodeEntryOffset);
129     }
130 
131     if (body_visiting_policy & kVisitNextFunction) {
132       IteratePointers(obj, kNextFunctionLinkOffset, kSize, v);
133     }
134     IterateBodyImpl(obj, kSize, object_size, v);
135   }
136 
137   template <typename StaticVisitor>
IterateBody(HeapObject * obj,int object_size)138   static inline void IterateBody(HeapObject* obj, int object_size) {
139     Heap* heap = obj->GetHeap();
140     IteratePointers<StaticVisitor>(heap, obj, kPropertiesOffset,
141                                    kNonWeakFieldsEndOffset);
142 
143     if (body_visiting_policy & kVisitCodeEntry) {
144       StaticVisitor::VisitCodeEntry(heap, obj,
145                                     obj->address() + kCodeEntryOffset);
146     }
147 
148     if (body_visiting_policy & kVisitNextFunction) {
149       IteratePointers<StaticVisitor>(heap, obj, kNextFunctionLinkOffset, kSize);
150     }
151     IterateBodyImpl<StaticVisitor>(heap, obj, kSize, object_size);
152   }
153 
SizeOf(Map * map,HeapObject * object)154   static inline int SizeOf(Map* map, HeapObject* object) {
155     return map->instance_size();
156   }
157 };
158 
159 
160 class JSArrayBuffer::BodyDescriptor final : public BodyDescriptorBase {
161  public:
162   STATIC_ASSERT(kByteLengthOffset + kPointerSize == kBackingStoreOffset);
163   STATIC_ASSERT(kBackingStoreOffset + kPointerSize == kBitFieldSlot);
164   STATIC_ASSERT(kBitFieldSlot + kPointerSize == kSize);
165 
IsValidSlot(HeapObject * obj,int offset)166   static bool IsValidSlot(HeapObject* obj, int offset) {
167     if (offset < kBackingStoreOffset) return true;
168     if (offset < kSize) return false;
169     return IsValidSlotImpl(obj, offset);
170   }
171 
172   template <typename ObjectVisitor>
IterateBody(HeapObject * obj,int object_size,ObjectVisitor * v)173   static inline void IterateBody(HeapObject* obj, int object_size,
174                                  ObjectVisitor* v) {
175     IteratePointers(obj, kPropertiesOffset, kBackingStoreOffset, v);
176     IterateBodyImpl(obj, kSize, object_size, v);
177   }
178 
179   template <typename StaticVisitor>
IterateBody(HeapObject * obj,int object_size)180   static inline void IterateBody(HeapObject* obj, int object_size) {
181     Heap* heap = obj->GetHeap();
182     IteratePointers<StaticVisitor>(heap, obj, kPropertiesOffset,
183                                    kBackingStoreOffset);
184     IterateBodyImpl<StaticVisitor>(heap, obj, kSize, object_size);
185   }
186 
SizeOf(Map * map,HeapObject * object)187   static inline int SizeOf(Map* map, HeapObject* object) {
188     return map->instance_size();
189   }
190 };
191 
192 
193 class BytecodeArray::BodyDescriptor final : public BodyDescriptorBase {
194  public:
IsValidSlot(HeapObject * obj,int offset)195   static bool IsValidSlot(HeapObject* obj, int offset) {
196     return offset == kConstantPoolOffset;
197   }
198 
199   template <typename ObjectVisitor>
IterateBody(HeapObject * obj,int object_size,ObjectVisitor * v)200   static inline void IterateBody(HeapObject* obj, int object_size,
201                                  ObjectVisitor* v) {
202     IteratePointer(obj, kConstantPoolOffset, v);
203   }
204 
205   template <typename StaticVisitor>
IterateBody(HeapObject * obj,int object_size)206   static inline void IterateBody(HeapObject* obj, int object_size) {
207     Heap* heap = obj->GetHeap();
208     IteratePointer<StaticVisitor>(heap, obj, kConstantPoolOffset);
209   }
210 
SizeOf(Map * map,HeapObject * obj)211   static inline int SizeOf(Map* map, HeapObject* obj) {
212     return reinterpret_cast<BytecodeArray*>(obj)->BytecodeArraySize();
213   }
214 };
215 
216 
217 class FixedTypedArrayBase::BodyDescriptor final : public BodyDescriptorBase {
218  public:
IsValidSlot(HeapObject * obj,int offset)219   static bool IsValidSlot(HeapObject* obj, int offset) {
220     return offset == kBasePointerOffset;
221   }
222 
223   template <typename ObjectVisitor>
IterateBody(HeapObject * obj,int object_size,ObjectVisitor * v)224   static inline void IterateBody(HeapObject* obj, int object_size,
225                                  ObjectVisitor* v) {
226     IteratePointer(obj, kBasePointerOffset, v);
227   }
228 
229   template <typename StaticVisitor>
IterateBody(HeapObject * obj,int object_size)230   static inline void IterateBody(HeapObject* obj, int object_size) {
231     Heap* heap = obj->GetHeap();
232     IteratePointer<StaticVisitor>(heap, obj, kBasePointerOffset);
233   }
234 
SizeOf(Map * map,HeapObject * object)235   static inline int SizeOf(Map* map, HeapObject* object) {
236     return reinterpret_cast<FixedTypedArrayBase*>(object)->size();
237   }
238 };
239 
240 
241 template <JSWeakCollection::BodyVisitingPolicy body_visiting_policy>
242 class JSWeakCollection::BodyDescriptorImpl final : public BodyDescriptorBase {
243  public:
244   STATIC_ASSERT(kTableOffset + kPointerSize == kNextOffset);
245   STATIC_ASSERT(kNextOffset + kPointerSize == kSize);
246 
IsValidSlot(HeapObject * obj,int offset)247   static bool IsValidSlot(HeapObject* obj, int offset) {
248     return IsValidSlotImpl(obj, offset);
249   }
250 
251   template <typename ObjectVisitor>
IterateBody(HeapObject * obj,int object_size,ObjectVisitor * v)252   static inline void IterateBody(HeapObject* obj, int object_size,
253                                  ObjectVisitor* v) {
254     if (body_visiting_policy == kVisitStrong) {
255       IterateBodyImpl(obj, kPropertiesOffset, object_size, v);
256     } else {
257       IteratePointers(obj, kPropertiesOffset, kTableOffset, v);
258       IterateBodyImpl(obj, kSize, object_size, v);
259     }
260   }
261 
262   template <typename StaticVisitor>
IterateBody(HeapObject * obj,int object_size)263   static inline void IterateBody(HeapObject* obj, int object_size) {
264     Heap* heap = obj->GetHeap();
265     if (body_visiting_policy == kVisitStrong) {
266       IterateBodyImpl<StaticVisitor>(heap, obj, kPropertiesOffset, object_size);
267     } else {
268       IteratePointers<StaticVisitor>(heap, obj, kPropertiesOffset,
269                                      kTableOffset);
270       IterateBodyImpl<StaticVisitor>(heap, obj, kSize, object_size);
271     }
272   }
273 
SizeOf(Map * map,HeapObject * object)274   static inline int SizeOf(Map* map, HeapObject* object) {
275     return map->instance_size();
276   }
277 };
278 
279 
280 class Foreign::BodyDescriptor final : public BodyDescriptorBase {
281  public:
IsValidSlot(HeapObject * obj,int offset)282   static bool IsValidSlot(HeapObject* obj, int offset) { return false; }
283 
284   template <typename ObjectVisitor>
IterateBody(HeapObject * obj,int object_size,ObjectVisitor * v)285   static inline void IterateBody(HeapObject* obj, int object_size,
286                                  ObjectVisitor* v) {
287     v->VisitExternalReference(reinterpret_cast<Address*>(
288         HeapObject::RawField(obj, kForeignAddressOffset)));
289   }
290 
291   template <typename StaticVisitor>
IterateBody(HeapObject * obj,int object_size)292   static inline void IterateBody(HeapObject* obj, int object_size) {
293     StaticVisitor::VisitExternalReference(reinterpret_cast<Address*>(
294         HeapObject::RawField(obj, kForeignAddressOffset)));
295   }
296 
SizeOf(Map * map,HeapObject * object)297   static inline int SizeOf(Map* map, HeapObject* object) { return kSize; }
298 };
299 
300 
301 class ExternalOneByteString::BodyDescriptor final : public BodyDescriptorBase {
302  public:
IsValidSlot(HeapObject * obj,int offset)303   static bool IsValidSlot(HeapObject* obj, int offset) { return false; }
304 
305   template <typename ObjectVisitor>
IterateBody(HeapObject * obj,int object_size,ObjectVisitor * v)306   static inline void IterateBody(HeapObject* obj, int object_size,
307                                  ObjectVisitor* v) {
308     typedef v8::String::ExternalOneByteStringResource Resource;
309     v->VisitExternalOneByteString(reinterpret_cast<Resource**>(
310         HeapObject::RawField(obj, kResourceOffset)));
311   }
312 
313   template <typename StaticVisitor>
IterateBody(HeapObject * obj,int object_size)314   static inline void IterateBody(HeapObject* obj, int object_size) {
315     typedef v8::String::ExternalOneByteStringResource Resource;
316     StaticVisitor::VisitExternalOneByteString(reinterpret_cast<Resource**>(
317         HeapObject::RawField(obj, kResourceOffset)));
318   }
319 
SizeOf(Map * map,HeapObject * object)320   static inline int SizeOf(Map* map, HeapObject* object) { return kSize; }
321 };
322 
323 
324 class ExternalTwoByteString::BodyDescriptor final : public BodyDescriptorBase {
325  public:
IsValidSlot(HeapObject * obj,int offset)326   static bool IsValidSlot(HeapObject* obj, int offset) { return false; }
327 
328   template <typename ObjectVisitor>
IterateBody(HeapObject * obj,int object_size,ObjectVisitor * v)329   static inline void IterateBody(HeapObject* obj, int object_size,
330                                  ObjectVisitor* v) {
331     typedef v8::String::ExternalStringResource Resource;
332     v->VisitExternalTwoByteString(reinterpret_cast<Resource**>(
333         HeapObject::RawField(obj, kResourceOffset)));
334   }
335 
336   template <typename StaticVisitor>
IterateBody(HeapObject * obj,int object_size)337   static inline void IterateBody(HeapObject* obj, int object_size) {
338     typedef v8::String::ExternalStringResource Resource;
339     StaticVisitor::VisitExternalTwoByteString(reinterpret_cast<Resource**>(
340         HeapObject::RawField(obj, kResourceOffset)));
341   }
342 
SizeOf(Map * map,HeapObject * object)343   static inline int SizeOf(Map* map, HeapObject* object) { return kSize; }
344 };
345 
346 
347 class Code::BodyDescriptor final : public BodyDescriptorBase {
348  public:
349   STATIC_ASSERT(kRelocationInfoOffset + kPointerSize == kHandlerTableOffset);
350   STATIC_ASSERT(kHandlerTableOffset + kPointerSize ==
351                 kDeoptimizationDataOffset);
352   STATIC_ASSERT(kDeoptimizationDataOffset + kPointerSize ==
353                 kTypeFeedbackInfoOffset);
354   STATIC_ASSERT(kTypeFeedbackInfoOffset + kPointerSize == kNextCodeLinkOffset);
355 
IsValidSlot(HeapObject * obj,int offset)356   static bool IsValidSlot(HeapObject* obj, int offset) {
357     // Slots in code can't be invalid because we never trim code objects.
358     return true;
359   }
360 
361   template <typename ObjectVisitor>
IterateBody(HeapObject * obj,ObjectVisitor * v)362   static inline void IterateBody(HeapObject* obj, ObjectVisitor* v) {
363     int mode_mask = RelocInfo::kCodeTargetMask |
364                     RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
365                     RelocInfo::ModeMask(RelocInfo::CELL) |
366                     RelocInfo::ModeMask(RelocInfo::EXTERNAL_REFERENCE) |
367                     RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE) |
368                     RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE_ENCODED) |
369                     RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY) |
370                     RelocInfo::kDebugBreakSlotMask;
371 
372     IteratePointers(obj, kRelocationInfoOffset, kNextCodeLinkOffset, v);
373     v->VisitNextCodeLink(HeapObject::RawField(obj, kNextCodeLinkOffset));
374 
375     RelocIterator it(reinterpret_cast<Code*>(obj), mode_mask);
376     Isolate* isolate = obj->GetIsolate();
377     for (; !it.done(); it.next()) {
378       it.rinfo()->Visit(isolate, v);
379     }
380   }
381 
382   template <typename ObjectVisitor>
IterateBody(HeapObject * obj,int object_size,ObjectVisitor * v)383   static inline void IterateBody(HeapObject* obj, int object_size,
384                                  ObjectVisitor* v) {
385     IterateBody(obj, v);
386   }
387 
388   template <typename StaticVisitor>
IterateBody(HeapObject * obj)389   static inline void IterateBody(HeapObject* obj) {
390     int mode_mask = RelocInfo::kCodeTargetMask |
391                     RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
392                     RelocInfo::ModeMask(RelocInfo::CELL) |
393                     RelocInfo::ModeMask(RelocInfo::EXTERNAL_REFERENCE) |
394                     RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE) |
395                     RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE_ENCODED) |
396                     RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY) |
397                     RelocInfo::kDebugBreakSlotMask;
398 
399     Heap* heap = obj->GetHeap();
400     IteratePointers<StaticVisitor>(heap, obj, kRelocationInfoOffset,
401                                    kNextCodeLinkOffset);
402     StaticVisitor::VisitNextCodeLink(
403         heap, HeapObject::RawField(obj, kNextCodeLinkOffset));
404 
405     RelocIterator it(reinterpret_cast<Code*>(obj), mode_mask);
406     for (; !it.done(); it.next()) {
407       it.rinfo()->template Visit<StaticVisitor>(heap);
408     }
409   }
410 
411   template <typename StaticVisitor>
IterateBody(HeapObject * obj,int object_size)412   static inline void IterateBody(HeapObject* obj, int object_size) {
413     IterateBody<StaticVisitor>(obj);
414   }
415 
SizeOf(Map * map,HeapObject * object)416   static inline int SizeOf(Map* map, HeapObject* object) {
417     return reinterpret_cast<Code*>(object)->CodeSize();
418   }
419 };
420 
421 
422 template <typename Op, typename ReturnType, typename T1, typename T2,
423           typename T3>
BodyDescriptorApply(InstanceType type,T1 p1,T2 p2,T3 p3)424 ReturnType BodyDescriptorApply(InstanceType type, T1 p1, T2 p2, T3 p3) {
425   if (type < FIRST_NONSTRING_TYPE) {
426     switch (type & kStringRepresentationMask) {
427       case kSeqStringTag:
428         return ReturnType();
429       case kConsStringTag:
430         return Op::template apply<ConsString::BodyDescriptor>(p1, p2, p3);
431       case kSlicedStringTag:
432         return Op::template apply<SlicedString::BodyDescriptor>(p1, p2, p3);
433       case kExternalStringTag:
434         if ((type & kStringEncodingMask) == kOneByteStringTag) {
435           return Op::template apply<ExternalOneByteString::BodyDescriptor>(
436               p1, p2, p3);
437         } else {
438           return Op::template apply<ExternalTwoByteString::BodyDescriptor>(
439               p1, p2, p3);
440         }
441     }
442     UNREACHABLE();
443     return ReturnType();
444   }
445 
446   switch (type) {
447     case FIXED_ARRAY_TYPE:
448       return Op::template apply<FixedArray::BodyDescriptor>(p1, p2, p3);
449     case FIXED_DOUBLE_ARRAY_TYPE:
450       return ReturnType();
451     case TRANSITION_ARRAY_TYPE:
452       return Op::template apply<TransitionArray::BodyDescriptor>(p1, p2, p3);
453     case JS_OBJECT_TYPE:
454     case JS_PROMISE_TYPE:
455     case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
456     case JS_GENERATOR_OBJECT_TYPE:
457     case JS_MODULE_TYPE:
458     case JS_VALUE_TYPE:
459     case JS_DATE_TYPE:
460     case JS_ARRAY_TYPE:
461     case JS_TYPED_ARRAY_TYPE:
462     case JS_DATA_VIEW_TYPE:
463     case JS_SET_TYPE:
464     case JS_MAP_TYPE:
465     case JS_SET_ITERATOR_TYPE:
466     case JS_MAP_ITERATOR_TYPE:
467     case JS_ITERATOR_RESULT_TYPE:
468     case JS_REGEXP_TYPE:
469     case JS_GLOBAL_PROXY_TYPE:
470     case JS_GLOBAL_OBJECT_TYPE:
471     case JS_MESSAGE_OBJECT_TYPE:
472     case JS_BOUND_FUNCTION_TYPE:
473       return Op::template apply<JSObject::BodyDescriptor>(p1, p2, p3);
474     case JS_WEAK_MAP_TYPE:
475     case JS_WEAK_SET_TYPE:
476       return Op::template apply<JSWeakCollection::BodyDescriptor>(p1, p2, p3);
477     case JS_ARRAY_BUFFER_TYPE:
478       return Op::template apply<JSArrayBuffer::BodyDescriptor>(p1, p2, p3);
479     case JS_FUNCTION_TYPE:
480       return Op::template apply<JSFunction::BodyDescriptor>(p1, p2, p3);
481     case ODDBALL_TYPE:
482       return Op::template apply<Oddball::BodyDescriptor>(p1, p2, p3);
483     case JS_PROXY_TYPE:
484       return Op::template apply<JSProxy::BodyDescriptor>(p1, p2, p3);
485     case FOREIGN_TYPE:
486       return Op::template apply<Foreign::BodyDescriptor>(p1, p2, p3);
487     case MAP_TYPE:
488       return Op::template apply<Map::BodyDescriptor>(p1, p2, p3);
489     case CODE_TYPE:
490       return Op::template apply<Code::BodyDescriptor>(p1, p2, p3);
491     case CELL_TYPE:
492       return Op::template apply<Cell::BodyDescriptor>(p1, p2, p3);
493     case PROPERTY_CELL_TYPE:
494       return Op::template apply<PropertyCell::BodyDescriptor>(p1, p2, p3);
495     case WEAK_CELL_TYPE:
496       return Op::template apply<WeakCell::BodyDescriptor>(p1, p2, p3);
497     case SYMBOL_TYPE:
498       return Op::template apply<Symbol::BodyDescriptor>(p1, p2, p3);
499     case BYTECODE_ARRAY_TYPE:
500       return Op::template apply<BytecodeArray::BodyDescriptor>(p1, p2, p3);
501 
502     case HEAP_NUMBER_TYPE:
503     case MUTABLE_HEAP_NUMBER_TYPE:
504     case SIMD128_VALUE_TYPE:
505     case FILLER_TYPE:
506     case BYTE_ARRAY_TYPE:
507     case FREE_SPACE_TYPE:
508       return ReturnType();
509 
510 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
511   case FIXED_##TYPE##_ARRAY_TYPE:                       \
512     return Op::template apply<FixedTypedArrayBase::BodyDescriptor>(p1, p2, p3);
513       TYPED_ARRAYS(TYPED_ARRAY_CASE)
514 #undef TYPED_ARRAY_CASE
515 
516     case SHARED_FUNCTION_INFO_TYPE: {
517       return Op::template apply<SharedFunctionInfo::BodyDescriptor>(p1, p2, p3);
518     }
519 
520 #define MAKE_STRUCT_CASE(NAME, Name, name) case NAME##_TYPE:
521       STRUCT_LIST(MAKE_STRUCT_CASE)
522 #undef MAKE_STRUCT_CASE
523       if (type == ALLOCATION_SITE_TYPE) {
524         return Op::template apply<AllocationSite::BodyDescriptor>(p1, p2, p3);
525       } else {
526         return Op::template apply<StructBodyDescriptor>(p1, p2, p3);
527       }
528     default:
529       PrintF("Unknown type: %d\n", type);
530       UNREACHABLE();
531       return ReturnType();
532   }
533 }
534 
535 
536 template <typename ObjectVisitor>
IterateFast(ObjectVisitor * v)537 void HeapObject::IterateFast(ObjectVisitor* v) {
538   BodyDescriptorBase::IteratePointer(this, kMapOffset, v);
539   IterateBodyFast(v);
540 }
541 
542 
543 template <typename ObjectVisitor>
IterateBodyFast(ObjectVisitor * v)544 void HeapObject::IterateBodyFast(ObjectVisitor* v) {
545   Map* m = map();
546   IterateBodyFast(m->instance_type(), SizeFromMap(m), v);
547 }
548 
549 
550 struct CallIterateBody {
551   template <typename BodyDescriptor, typename ObjectVisitor>
applyCallIterateBody552   static void apply(HeapObject* obj, int object_size, ObjectVisitor* v) {
553     BodyDescriptor::IterateBody(obj, object_size, v);
554   }
555 };
556 
557 template <typename ObjectVisitor>
IterateBodyFast(InstanceType type,int object_size,ObjectVisitor * v)558 void HeapObject::IterateBodyFast(InstanceType type, int object_size,
559                                  ObjectVisitor* v) {
560   BodyDescriptorApply<CallIterateBody, void>(type, this, object_size, v);
561 }
562 }  // namespace internal
563 }  // namespace v8
564 
565 #endif  // V8_OBJECTS_BODY_DESCRIPTORS_INL_H_
566