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