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