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