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
10namespace v8 {
11namespace internal {
12
13template <int start_offset>
14int FlexibleBodyDescriptor<start_offset>::SizeOf(Map* map, HeapObject* object) {
15  return object->SizeFromMap(map);
16}
17
18
19bool 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
32template <typename ObjectVisitor>
33void 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
55template <typename StaticVisitor>
56void 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
78template <typename ObjectVisitor>
79void 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
86template <typename StaticVisitor>
87void 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
95template <typename ObjectVisitor>
96void BodyDescriptorBase::IteratePointer(HeapObject* obj, int offset,
97                                        ObjectVisitor* v) {
98  v->VisitPointer(HeapObject::RawField(obj, offset));
99}
100
101
102template <typename StaticVisitor>
103void 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.
110template <JSFunction::BodyVisitingPolicy body_visiting_policy>
111class 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
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>
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>
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
154  static inline int SizeOf(Map* map, HeapObject* object) {
155    return map->instance_size();
156  }
157};
158
159
160class 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
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>
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>
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
187  static inline int SizeOf(Map* map, HeapObject* object) {
188    return map->instance_size();
189  }
190};
191
192
193class BytecodeArray::BodyDescriptor final : public BodyDescriptorBase {
194 public:
195  static bool IsValidSlot(HeapObject* obj, int offset) {
196    return offset >= kConstantPoolOffset &&
197           offset <= kSourcePositionTableOffset;
198  }
199
200  template <typename ObjectVisitor>
201  static inline void IterateBody(HeapObject* obj, int object_size,
202                                 ObjectVisitor* v) {
203    IteratePointer(obj, kConstantPoolOffset, v);
204    IteratePointer(obj, kHandlerTableOffset, v);
205    IteratePointer(obj, kSourcePositionTableOffset, v);
206  }
207
208  template <typename StaticVisitor>
209  static inline void IterateBody(HeapObject* obj, int object_size) {
210    Heap* heap = obj->GetHeap();
211    IteratePointer<StaticVisitor>(heap, obj, kConstantPoolOffset);
212    IteratePointer<StaticVisitor>(heap, obj, kHandlerTableOffset);
213    IteratePointer<StaticVisitor>(heap, obj, kSourcePositionTableOffset);
214  }
215
216  static inline int SizeOf(Map* map, HeapObject* obj) {
217    return reinterpret_cast<BytecodeArray*>(obj)->BytecodeArraySize();
218  }
219};
220
221
222class FixedTypedArrayBase::BodyDescriptor final : public BodyDescriptorBase {
223 public:
224  static bool IsValidSlot(HeapObject* obj, int offset) {
225    return offset == kBasePointerOffset;
226  }
227
228  template <typename ObjectVisitor>
229  static inline void IterateBody(HeapObject* obj, int object_size,
230                                 ObjectVisitor* v) {
231    IteratePointer(obj, kBasePointerOffset, v);
232  }
233
234  template <typename StaticVisitor>
235  static inline void IterateBody(HeapObject* obj, int object_size) {
236    Heap* heap = obj->GetHeap();
237    IteratePointer<StaticVisitor>(heap, obj, kBasePointerOffset);
238  }
239
240  static inline int SizeOf(Map* map, HeapObject* object) {
241    return reinterpret_cast<FixedTypedArrayBase*>(object)->size();
242  }
243};
244
245
246template <JSWeakCollection::BodyVisitingPolicy body_visiting_policy>
247class JSWeakCollection::BodyDescriptorImpl final : public BodyDescriptorBase {
248 public:
249  STATIC_ASSERT(kTableOffset + kPointerSize == kNextOffset);
250  STATIC_ASSERT(kNextOffset + kPointerSize == kSize);
251
252  static bool IsValidSlot(HeapObject* obj, int offset) {
253    return IsValidSlotImpl(obj, offset);
254  }
255
256  template <typename ObjectVisitor>
257  static inline void IterateBody(HeapObject* obj, int object_size,
258                                 ObjectVisitor* v) {
259    if (body_visiting_policy == kVisitStrong) {
260      IterateBodyImpl(obj, kPropertiesOffset, object_size, v);
261    } else {
262      IteratePointers(obj, kPropertiesOffset, kTableOffset, v);
263      IterateBodyImpl(obj, kSize, object_size, v);
264    }
265  }
266
267  template <typename StaticVisitor>
268  static inline void IterateBody(HeapObject* obj, int object_size) {
269    Heap* heap = obj->GetHeap();
270    if (body_visiting_policy == kVisitStrong) {
271      IterateBodyImpl<StaticVisitor>(heap, obj, kPropertiesOffset, object_size);
272    } else {
273      IteratePointers<StaticVisitor>(heap, obj, kPropertiesOffset,
274                                     kTableOffset);
275      IterateBodyImpl<StaticVisitor>(heap, obj, kSize, object_size);
276    }
277  }
278
279  static inline int SizeOf(Map* map, HeapObject* object) {
280    return map->instance_size();
281  }
282};
283
284
285class Foreign::BodyDescriptor final : public BodyDescriptorBase {
286 public:
287  static bool IsValidSlot(HeapObject* obj, int offset) { return false; }
288
289  template <typename ObjectVisitor>
290  static inline void IterateBody(HeapObject* obj, int object_size,
291                                 ObjectVisitor* v) {
292    v->VisitExternalReference(reinterpret_cast<Address*>(
293        HeapObject::RawField(obj, kForeignAddressOffset)));
294  }
295
296  template <typename StaticVisitor>
297  static inline void IterateBody(HeapObject* obj, int object_size) {
298    StaticVisitor::VisitExternalReference(reinterpret_cast<Address*>(
299        HeapObject::RawField(obj, kForeignAddressOffset)));
300  }
301
302  static inline int SizeOf(Map* map, HeapObject* object) { return kSize; }
303};
304
305
306class ExternalOneByteString::BodyDescriptor final : public BodyDescriptorBase {
307 public:
308  static bool IsValidSlot(HeapObject* obj, int offset) { return false; }
309
310  template <typename ObjectVisitor>
311  static inline void IterateBody(HeapObject* obj, int object_size,
312                                 ObjectVisitor* v) {
313    typedef v8::String::ExternalOneByteStringResource Resource;
314    v->VisitExternalOneByteString(reinterpret_cast<Resource**>(
315        HeapObject::RawField(obj, kResourceOffset)));
316  }
317
318  template <typename StaticVisitor>
319  static inline void IterateBody(HeapObject* obj, int object_size) {
320    typedef v8::String::ExternalOneByteStringResource Resource;
321    StaticVisitor::VisitExternalOneByteString(reinterpret_cast<Resource**>(
322        HeapObject::RawField(obj, kResourceOffset)));
323  }
324
325  static inline int SizeOf(Map* map, HeapObject* object) { return kSize; }
326};
327
328
329class ExternalTwoByteString::BodyDescriptor final : public BodyDescriptorBase {
330 public:
331  static bool IsValidSlot(HeapObject* obj, int offset) { return false; }
332
333  template <typename ObjectVisitor>
334  static inline void IterateBody(HeapObject* obj, int object_size,
335                                 ObjectVisitor* v) {
336    typedef v8::String::ExternalStringResource Resource;
337    v->VisitExternalTwoByteString(reinterpret_cast<Resource**>(
338        HeapObject::RawField(obj, kResourceOffset)));
339  }
340
341  template <typename StaticVisitor>
342  static inline void IterateBody(HeapObject* obj, int object_size) {
343    typedef v8::String::ExternalStringResource Resource;
344    StaticVisitor::VisitExternalTwoByteString(reinterpret_cast<Resource**>(
345        HeapObject::RawField(obj, kResourceOffset)));
346  }
347
348  static inline int SizeOf(Map* map, HeapObject* object) { return kSize; }
349};
350
351
352class Code::BodyDescriptor final : public BodyDescriptorBase {
353 public:
354  STATIC_ASSERT(kRelocationInfoOffset + kPointerSize == kHandlerTableOffset);
355  STATIC_ASSERT(kHandlerTableOffset + kPointerSize ==
356                kDeoptimizationDataOffset);
357  STATIC_ASSERT(kDeoptimizationDataOffset + kPointerSize ==
358                kTypeFeedbackInfoOffset);
359  STATIC_ASSERT(kTypeFeedbackInfoOffset + kPointerSize == kNextCodeLinkOffset);
360
361  static bool IsValidSlot(HeapObject* obj, int offset) {
362    // Slots in code can't be invalid because we never trim code objects.
363    return true;
364  }
365
366  template <typename ObjectVisitor>
367  static inline void IterateBody(HeapObject* obj, ObjectVisitor* v) {
368    int mode_mask = RelocInfo::kCodeTargetMask |
369                    RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
370                    RelocInfo::ModeMask(RelocInfo::CELL) |
371                    RelocInfo::ModeMask(RelocInfo::EXTERNAL_REFERENCE) |
372                    RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE) |
373                    RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE_ENCODED) |
374                    RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY) |
375                    RelocInfo::kDebugBreakSlotMask;
376
377    IteratePointers(obj, kRelocationInfoOffset, kNextCodeLinkOffset, v);
378    v->VisitNextCodeLink(HeapObject::RawField(obj, kNextCodeLinkOffset));
379
380    RelocIterator it(reinterpret_cast<Code*>(obj), mode_mask);
381    Isolate* isolate = obj->GetIsolate();
382    for (; !it.done(); it.next()) {
383      it.rinfo()->Visit(isolate, v);
384    }
385  }
386
387  template <typename ObjectVisitor>
388  static inline void IterateBody(HeapObject* obj, int object_size,
389                                 ObjectVisitor* v) {
390    IterateBody(obj, v);
391  }
392
393  template <typename StaticVisitor>
394  static inline void IterateBody(HeapObject* obj) {
395    int mode_mask = RelocInfo::kCodeTargetMask |
396                    RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
397                    RelocInfo::ModeMask(RelocInfo::CELL) |
398                    RelocInfo::ModeMask(RelocInfo::EXTERNAL_REFERENCE) |
399                    RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE) |
400                    RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE_ENCODED) |
401                    RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY) |
402                    RelocInfo::kDebugBreakSlotMask;
403
404    Heap* heap = obj->GetHeap();
405    IteratePointers<StaticVisitor>(heap, obj, kRelocationInfoOffset,
406                                   kNextCodeLinkOffset);
407    StaticVisitor::VisitNextCodeLink(
408        heap, HeapObject::RawField(obj, kNextCodeLinkOffset));
409
410    RelocIterator it(reinterpret_cast<Code*>(obj), mode_mask);
411    for (; !it.done(); it.next()) {
412      it.rinfo()->template Visit<StaticVisitor>(heap);
413    }
414  }
415
416  template <typename StaticVisitor>
417  static inline void IterateBody(HeapObject* obj, int object_size) {
418    IterateBody<StaticVisitor>(obj);
419  }
420
421  static inline int SizeOf(Map* map, HeapObject* object) {
422    return reinterpret_cast<Code*>(object)->CodeSize();
423  }
424};
425
426
427template <typename Op, typename ReturnType, typename T1, typename T2,
428          typename T3>
429ReturnType BodyDescriptorApply(InstanceType type, T1 p1, T2 p2, T3 p3) {
430  if (type < FIRST_NONSTRING_TYPE) {
431    switch (type & kStringRepresentationMask) {
432      case kSeqStringTag:
433        return ReturnType();
434      case kConsStringTag:
435        return Op::template apply<ConsString::BodyDescriptor>(p1, p2, p3);
436      case kSlicedStringTag:
437        return Op::template apply<SlicedString::BodyDescriptor>(p1, p2, p3);
438      case kExternalStringTag:
439        if ((type & kStringEncodingMask) == kOneByteStringTag) {
440          return Op::template apply<ExternalOneByteString::BodyDescriptor>(
441              p1, p2, p3);
442        } else {
443          return Op::template apply<ExternalTwoByteString::BodyDescriptor>(
444              p1, p2, p3);
445        }
446    }
447    UNREACHABLE();
448    return ReturnType();
449  }
450
451  switch (type) {
452    case FIXED_ARRAY_TYPE:
453      return Op::template apply<FixedArray::BodyDescriptor>(p1, p2, p3);
454    case FIXED_DOUBLE_ARRAY_TYPE:
455      return ReturnType();
456    case TRANSITION_ARRAY_TYPE:
457      return Op::template apply<TransitionArray::BodyDescriptor>(p1, p2, p3);
458    case JS_OBJECT_TYPE:
459    case JS_ERROR_TYPE:
460    case JS_ARGUMENTS_TYPE:
461    case JS_PROMISE_TYPE:
462    case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
463    case JS_GENERATOR_OBJECT_TYPE:
464    case JS_MODULE_TYPE:
465    case JS_VALUE_TYPE:
466    case JS_DATE_TYPE:
467    case JS_ARRAY_TYPE:
468    case JS_TYPED_ARRAY_TYPE:
469    case JS_DATA_VIEW_TYPE:
470    case JS_SET_TYPE:
471    case JS_MAP_TYPE:
472    case JS_SET_ITERATOR_TYPE:
473    case JS_MAP_ITERATOR_TYPE:
474    case JS_REGEXP_TYPE:
475    case JS_GLOBAL_PROXY_TYPE:
476    case JS_GLOBAL_OBJECT_TYPE:
477    case JS_API_OBJECT_TYPE:
478    case JS_SPECIAL_API_OBJECT_TYPE:
479    case JS_MESSAGE_OBJECT_TYPE:
480    case JS_BOUND_FUNCTION_TYPE:
481      return Op::template apply<JSObject::BodyDescriptor>(p1, p2, p3);
482    case JS_WEAK_MAP_TYPE:
483    case JS_WEAK_SET_TYPE:
484      return Op::template apply<JSWeakCollection::BodyDescriptor>(p1, p2, p3);
485    case JS_ARRAY_BUFFER_TYPE:
486      return Op::template apply<JSArrayBuffer::BodyDescriptor>(p1, p2, p3);
487    case JS_FUNCTION_TYPE:
488      return Op::template apply<JSFunction::BodyDescriptor>(p1, p2, p3);
489    case ODDBALL_TYPE:
490      return Op::template apply<Oddball::BodyDescriptor>(p1, p2, p3);
491    case JS_PROXY_TYPE:
492      return Op::template apply<JSProxy::BodyDescriptor>(p1, p2, p3);
493    case FOREIGN_TYPE:
494      return Op::template apply<Foreign::BodyDescriptor>(p1, p2, p3);
495    case MAP_TYPE:
496      return Op::template apply<Map::BodyDescriptor>(p1, p2, p3);
497    case CODE_TYPE:
498      return Op::template apply<Code::BodyDescriptor>(p1, p2, p3);
499    case CELL_TYPE:
500      return Op::template apply<Cell::BodyDescriptor>(p1, p2, p3);
501    case PROPERTY_CELL_TYPE:
502      return Op::template apply<PropertyCell::BodyDescriptor>(p1, p2, p3);
503    case WEAK_CELL_TYPE:
504      return Op::template apply<WeakCell::BodyDescriptor>(p1, p2, p3);
505    case SYMBOL_TYPE:
506      return Op::template apply<Symbol::BodyDescriptor>(p1, p2, p3);
507    case BYTECODE_ARRAY_TYPE:
508      return Op::template apply<BytecodeArray::BodyDescriptor>(p1, p2, p3);
509
510    case HEAP_NUMBER_TYPE:
511    case MUTABLE_HEAP_NUMBER_TYPE:
512    case SIMD128_VALUE_TYPE:
513    case FILLER_TYPE:
514    case BYTE_ARRAY_TYPE:
515    case FREE_SPACE_TYPE:
516      return ReturnType();
517
518#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
519  case FIXED_##TYPE##_ARRAY_TYPE:                       \
520    return Op::template apply<FixedTypedArrayBase::BodyDescriptor>(p1, p2, p3);
521      TYPED_ARRAYS(TYPED_ARRAY_CASE)
522#undef TYPED_ARRAY_CASE
523
524    case SHARED_FUNCTION_INFO_TYPE: {
525      return Op::template apply<SharedFunctionInfo::BodyDescriptor>(p1, p2, p3);
526    }
527
528#define MAKE_STRUCT_CASE(NAME, Name, name) case NAME##_TYPE:
529      STRUCT_LIST(MAKE_STRUCT_CASE)
530#undef MAKE_STRUCT_CASE
531      if (type == ALLOCATION_SITE_TYPE) {
532        return Op::template apply<AllocationSite::BodyDescriptor>(p1, p2, p3);
533      } else {
534        return Op::template apply<StructBodyDescriptor>(p1, p2, p3);
535      }
536    default:
537      PrintF("Unknown type: %d\n", type);
538      UNREACHABLE();
539      return ReturnType();
540  }
541}
542
543
544template <typename ObjectVisitor>
545void HeapObject::IterateFast(ObjectVisitor* v) {
546  BodyDescriptorBase::IteratePointer(this, kMapOffset, v);
547  IterateBodyFast(v);
548}
549
550
551template <typename ObjectVisitor>
552void HeapObject::IterateBodyFast(ObjectVisitor* v) {
553  Map* m = map();
554  IterateBodyFast(m->instance_type(), SizeFromMap(m), v);
555}
556
557
558struct CallIterateBody {
559  template <typename BodyDescriptor, typename ObjectVisitor>
560  static void apply(HeapObject* obj, int object_size, ObjectVisitor* v) {
561    BodyDescriptor::IterateBody(obj, object_size, v);
562  }
563};
564
565template <typename ObjectVisitor>
566void HeapObject::IterateBodyFast(InstanceType type, int object_size,
567                                 ObjectVisitor* v) {
568  BodyDescriptorApply<CallIterateBody, void>(type, this, object_size, v);
569}
570}  // namespace internal
571}  // namespace v8
572
573#endif  // V8_OBJECTS_BODY_DESCRIPTORS_INL_H_
574