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