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_H_ 6 #define V8_OBJECTS_BODY_DESCRIPTORS_H_ 7 8 #include "src/objects.h" 9 10 namespace v8 { 11 namespace internal { 12 13 // This is the base class for object's body descriptors. 14 // 15 // Each BodyDescriptor subclass must provide the following methods: 16 // 17 // 1) Returns true if the object contains a tagged value at given offset. 18 // It is used for invalid slots filtering. If the offset points outside 19 // of the object or to the map word, the result is UNDEFINED (!!!). 20 // 21 // static bool IsValidSlot(Map* map, HeapObject* obj, int offset); 22 // 23 // 24 // 2) Iterate object's body using stateful object visitor. 25 // 26 // template <typename ObjectVisitor> 27 // static inline void IterateBody(Map* map, HeapObject* obj, int object_size, 28 // ObjectVisitor* v); 29 class BodyDescriptorBase BASE_EMBEDDED { 30 public: 31 template <typename ObjectVisitor> 32 static inline void IteratePointers(HeapObject* obj, int start_offset, 33 int end_offset, ObjectVisitor* v); 34 35 template <typename ObjectVisitor> 36 static inline void IteratePointer(HeapObject* obj, int offset, 37 ObjectVisitor* v); 38 39 template <typename ObjectVisitor> 40 static inline void IterateMaybeWeakPointers(HeapObject* obj, int start_offset, 41 int end_offset, ObjectVisitor* v); 42 43 template <typename ObjectVisitor> 44 static inline void IterateMaybeWeakPointer(HeapObject* obj, int offset, 45 ObjectVisitor* v); 46 47 protected: 48 // Returns true for all header and embedder fields. 49 static inline bool IsValidSlotImpl(Map* map, HeapObject* obj, int offset); 50 51 // Treats all header and embedder fields in the range as tagged. 52 template <typename ObjectVisitor> 53 static inline void IterateBodyImpl(Map* map, HeapObject* obj, 54 int start_offset, int end_offset, 55 ObjectVisitor* v); 56 }; 57 58 59 // This class describes a body of an object of a fixed size 60 // in which all pointer fields are located in the [start_offset, end_offset) 61 // interval. 62 template <int start_offset, int end_offset, int size> 63 class FixedBodyDescriptor final : public BodyDescriptorBase { 64 public: 65 static const int kStartOffset = start_offset; 66 static const int kEndOffset = end_offset; 67 static const int kSize = size; 68 IsValidSlot(Map * map,HeapObject * obj,int offset)69 static bool IsValidSlot(Map* map, HeapObject* obj, int offset) { 70 return offset >= kStartOffset && offset < kEndOffset; 71 } 72 73 template <typename ObjectVisitor> IterateBody(Map * map,HeapObject * obj,ObjectVisitor * v)74 static inline void IterateBody(Map* map, HeapObject* obj, ObjectVisitor* v) { 75 IteratePointers(obj, start_offset, end_offset, v); 76 } 77 78 template <typename ObjectVisitor> IterateBody(Map * map,HeapObject * obj,int object_size,ObjectVisitor * v)79 static inline void IterateBody(Map* map, HeapObject* obj, int object_size, 80 ObjectVisitor* v) { 81 IterateBody(map, obj, v); 82 } 83 SizeOf(Map * map,HeapObject * object)84 static inline int SizeOf(Map* map, HeapObject* object) { return kSize; } 85 }; 86 87 88 // This class describes a body of an object of a variable size 89 // in which all pointer fields are located in the [start_offset, object_size) 90 // interval. 91 template <int start_offset> 92 class FlexibleBodyDescriptor final : public BodyDescriptorBase { 93 public: 94 static const int kStartOffset = start_offset; 95 IsValidSlot(Map * map,HeapObject * obj,int offset)96 static bool IsValidSlot(Map* map, HeapObject* obj, int offset) { 97 return (offset >= kStartOffset); 98 } 99 100 template <typename ObjectVisitor> IterateBody(Map * map,HeapObject * obj,int object_size,ObjectVisitor * v)101 static inline void IterateBody(Map* map, HeapObject* obj, int object_size, 102 ObjectVisitor* v) { 103 IteratePointers(obj, start_offset, object_size, v); 104 } 105 106 static inline int SizeOf(Map* map, HeapObject* object); 107 }; 108 109 110 typedef FlexibleBodyDescriptor<HeapObject::kHeaderSize> StructBodyDescriptor; 111 112 // This class describes a body of an object which has a parent class that also 113 // has a body descriptor. This represents a union of the parent's body 114 // descriptor, and a new descriptor for the child -- so, both parent and child's 115 // slots are iterated. The parent must be fixed size, and its slots be disjoint 116 // with the child's. 117 template <class ParentBodyDescriptor, class ChildBodyDescriptor> 118 class SubclassBodyDescriptor final : public BodyDescriptorBase { 119 public: 120 // The parent must end be before the child's start offset, to make sure that 121 // their slots are disjoint. 122 STATIC_ASSERT(ParentBodyDescriptor::kSize <= 123 ChildBodyDescriptor::kStartOffset); 124 IsValidSlot(Map * map,HeapObject * obj,int offset)125 static bool IsValidSlot(Map* map, HeapObject* obj, int offset) { 126 return ParentBodyDescriptor::IsValidSlot(map, obj, offset) || 127 ChildBodyDescriptor::IsValidSlot(map, obj, offset); 128 } 129 130 template <typename ObjectVisitor> IterateBody(Map * map,HeapObject * obj,ObjectVisitor * v)131 static inline void IterateBody(Map* map, HeapObject* obj, ObjectVisitor* v) { 132 ParentBodyDescriptor::IterateBody(map, obj, v); 133 ChildBodyDescriptor::IterateBody(map, obj, v); 134 } 135 136 template <typename ObjectVisitor> IterateBody(Map * map,HeapObject * obj,int object_size,ObjectVisitor * v)137 static inline void IterateBody(Map* map, HeapObject* obj, int object_size, 138 ObjectVisitor* v) { 139 ParentBodyDescriptor::IterateBody(map, obj, object_size, v); 140 ChildBodyDescriptor::IterateBody(map, obj, object_size, v); 141 } 142 SizeOf(Map * map,HeapObject * object)143 static inline int SizeOf(Map* map, HeapObject* object) { 144 // The child should know its full size. 145 return ChildBodyDescriptor::SizeOf(map, object); 146 } 147 }; 148 149 } // namespace internal 150 } // namespace v8 151 152 #endif // V8_OBJECTS_BODY_DESCRIPTORS_H_ 153