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_OBJECTS_BODY_DESCRIPTORS_H_ 6 #define V8_OBJECTS_OBJECTS_BODY_DESCRIPTORS_H_ 7 8 #include "src/objects/map.h" 9 #include "src/objects/objects.h" 10 11 namespace v8 { 12 namespace internal { 13 14 // This is the base class for object's body descriptors. 15 // 16 // Each BodyDescriptor subclass must provide the following methods: 17 // 18 // 1) Returns true if the object contains a tagged value at given offset. 19 // It is used for invalid slots filtering. If the offset points outside 20 // of the object or to the map word, the result is UNDEFINED (!!!). 21 // 22 // static bool IsValidSlot(Map map, HeapObject obj, int offset); 23 // 24 // 25 // 2) Iterate object's body using stateful object visitor. 26 // 27 // template <typename ObjectVisitor> 28 // static inline void IterateBody(Map map, HeapObject obj, int object_size, 29 // ObjectVisitor* v); 30 class BodyDescriptorBase { 31 public: 32 template <typename ObjectVisitor> 33 static inline void IteratePointers(HeapObject obj, int start_offset, 34 int end_offset, ObjectVisitor* v); 35 36 template <typename ObjectVisitor> 37 static inline void IteratePointer(HeapObject obj, int offset, 38 ObjectVisitor* v); 39 40 template <typename ObjectVisitor> 41 static inline void IterateCustomWeakPointers(HeapObject obj, int start_offset, 42 int end_offset, 43 ObjectVisitor* v); 44 45 template <typename ObjectVisitor> 46 static inline void IterateCustomWeakPointer(HeapObject obj, int offset, 47 ObjectVisitor* v); 48 49 template <typename ObjectVisitor> 50 static inline void IterateEphemeron(HeapObject obj, int index, int key_offset, 51 int value_offset, ObjectVisitor* v); 52 53 template <typename ObjectVisitor> 54 static inline void IterateMaybeWeakPointers(HeapObject obj, int start_offset, 55 int end_offset, ObjectVisitor* v); 56 57 template <typename ObjectVisitor> 58 static inline void IterateMaybeWeakPointer(HeapObject obj, int offset, 59 ObjectVisitor* v); 60 61 protected: 62 // Returns true for all header and embedder fields. 63 static inline bool IsValidJSObjectSlotImpl(Map map, HeapObject obj, 64 int offset); 65 66 // Returns true for all header and embedder fields. 67 static inline bool IsValidEmbedderJSObjectSlotImpl(Map map, HeapObject obj, 68 int offset); 69 70 // Treats all header and embedder fields in the range as tagged. 71 template <typename ObjectVisitor> 72 static inline void IterateJSObjectBodyImpl(Map map, HeapObject obj, 73 int start_offset, int end_offset, 74 ObjectVisitor* v); 75 }; 76 77 // This class describes a body of an object in which all pointer fields are 78 // located in the [start_offset, end_offset) interval. 79 // All pointers have to be strong. 80 template <int start_offset, int end_offset> 81 class FixedRangeBodyDescriptor : public BodyDescriptorBase { 82 public: 83 static const int kStartOffset = start_offset; 84 static const int kEndOffset = end_offset; 85 IsValidSlot(Map map,HeapObject obj,int offset)86 static bool IsValidSlot(Map map, HeapObject obj, int offset) { 87 return offset >= kStartOffset && offset < kEndOffset; 88 } 89 90 template <typename ObjectVisitor> IterateBody(Map map,HeapObject obj,ObjectVisitor * v)91 static inline void IterateBody(Map map, HeapObject obj, ObjectVisitor* v) { 92 IteratePointers(obj, start_offset, end_offset, v); 93 } 94 95 template <typename ObjectVisitor> IterateBody(Map map,HeapObject obj,int object_size,ObjectVisitor * v)96 static inline void IterateBody(Map map, HeapObject obj, int object_size, 97 ObjectVisitor* v) { 98 IterateBody(map, obj, v); 99 } 100 101 private: SizeOf(Map map,HeapObject object)102 static inline int SizeOf(Map map, HeapObject object) { 103 // Has to be implemented by the subclass. 104 UNREACHABLE(); 105 } 106 }; 107 108 // This class describes a body of an object of a fixed size 109 // in which all pointer fields are located in the [start_offset, end_offset) 110 // interval. 111 // All pointers have to be strong. 112 template <int start_offset, int end_offset, int size> 113 class FixedBodyDescriptor 114 : public FixedRangeBodyDescriptor<start_offset, end_offset> { 115 public: 116 static const int kSize = size; SizeOf(Map map,HeapObject object)117 static inline int SizeOf(Map map, HeapObject object) { return kSize; } 118 }; 119 120 // This class describes a body of an object in which all pointer fields are 121 // located in the [start_offset, object_size) interval. 122 // All pointers have to be strong. 123 template <int start_offset> 124 class SuffixRangeBodyDescriptor : public BodyDescriptorBase { 125 public: 126 static const int kStartOffset = start_offset; 127 IsValidSlot(Map map,HeapObject obj,int offset)128 static bool IsValidSlot(Map map, HeapObject obj, int offset) { 129 return (offset >= kStartOffset); 130 } 131 132 template <typename ObjectVisitor> IterateBody(Map map,HeapObject obj,int object_size,ObjectVisitor * v)133 static inline void IterateBody(Map map, HeapObject obj, int object_size, 134 ObjectVisitor* v) { 135 IteratePointers(obj, start_offset, object_size, v); 136 } 137 138 private: SizeOf(Map map,HeapObject object)139 static inline int SizeOf(Map map, HeapObject object) { 140 // Has to be implemented by the subclass. 141 UNREACHABLE(); 142 } 143 }; 144 145 // This class describes a body of an object of a variable size 146 // in which all pointer fields are located in the [start_offset, object_size) 147 // interval. 148 // All pointers have to be strong. 149 template <int start_offset> 150 class FlexibleBodyDescriptor : public SuffixRangeBodyDescriptor<start_offset> { 151 public: 152 static inline int SizeOf(Map map, HeapObject object); 153 }; 154 155 using StructBodyDescriptor = FlexibleBodyDescriptor<HeapObject::kHeaderSize>; 156 157 // This class describes a body of an object in which all pointer fields are 158 // located in the [start_offset, object_size) interval. 159 // Pointers may be strong or may be MaybeObject-style weak pointers. 160 template <int start_offset> 161 class SuffixRangeWeakBodyDescriptor : public BodyDescriptorBase { 162 public: 163 static const int kStartOffset = start_offset; 164 IsValidSlot(Map map,HeapObject obj,int offset)165 static bool IsValidSlot(Map map, HeapObject obj, int offset) { 166 return (offset >= kStartOffset); 167 } 168 169 template <typename ObjectVisitor> IterateBody(Map map,HeapObject obj,int object_size,ObjectVisitor * v)170 static inline void IterateBody(Map map, HeapObject obj, int object_size, 171 ObjectVisitor* v) { 172 IterateMaybeWeakPointers(obj, start_offset, object_size, v); 173 } 174 175 private: SizeOf(Map map,HeapObject object)176 static inline int SizeOf(Map map, HeapObject object) { 177 // Has to be implemented by the subclass. 178 UNREACHABLE(); 179 } 180 }; 181 182 // This class describes a body of an object of a variable size 183 // in which all pointer fields are located in the [start_offset, object_size) 184 // interval. 185 // Pointers may be strong or may be MaybeObject-style weak pointers. 186 template <int start_offset> 187 class FlexibleWeakBodyDescriptor 188 : public SuffixRangeWeakBodyDescriptor<start_offset> { 189 public: 190 static inline int SizeOf(Map map, HeapObject object); 191 }; 192 193 // This class describes a body of an object without any pointers. 194 class DataOnlyBodyDescriptor : public BodyDescriptorBase { 195 public: IsValidSlot(Map map,HeapObject obj,int offset)196 static bool IsValidSlot(Map map, HeapObject obj, int offset) { return false; } 197 198 template <typename ObjectVisitor> IterateBody(Map map,HeapObject obj,int object_size,ObjectVisitor * v)199 static inline void IterateBody(Map map, HeapObject obj, int object_size, 200 ObjectVisitor* v) {} 201 202 private: SizeOf(Map map,HeapObject object)203 static inline int SizeOf(Map map, HeapObject object) { 204 // Has to be implemented by the subclass. 205 UNREACHABLE(); 206 } 207 }; 208 209 // This class describes a body of an object which has a parent class that also 210 // has a body descriptor. This represents a union of the parent's body 211 // descriptor, and a new descriptor for the child -- so, both parent and child's 212 // slots are iterated. The parent must be fixed size, and its slots be disjoint 213 // with the child's. 214 template <class ParentBodyDescriptor, class ChildBodyDescriptor> 215 class SubclassBodyDescriptor final : public BodyDescriptorBase { 216 public: 217 // The parent must end be before the child's start offset, to make sure that 218 // their slots are disjoint. 219 STATIC_ASSERT(ParentBodyDescriptor::kSize <= 220 ChildBodyDescriptor::kStartOffset); 221 IsValidSlot(Map map,HeapObject obj,int offset)222 static bool IsValidSlot(Map map, HeapObject obj, int offset) { 223 return ParentBodyDescriptor::IsValidSlot(map, obj, offset) || 224 ChildBodyDescriptor::IsValidSlot(map, obj, offset); 225 } 226 227 template <typename ObjectVisitor> IterateBody(Map map,HeapObject obj,ObjectVisitor * v)228 static inline void IterateBody(Map map, HeapObject obj, ObjectVisitor* v) { 229 ParentBodyDescriptor::IterateBody(map, obj, v); 230 ChildBodyDescriptor::IterateBody(map, obj, v); 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 ParentBodyDescriptor::IterateBody(map, obj, object_size, v); 237 ChildBodyDescriptor::IterateBody(map, obj, object_size, v); 238 } 239 SizeOf(Map map,HeapObject object)240 static inline int SizeOf(Map map, HeapObject object) { 241 // The child should know its full size. 242 return ChildBodyDescriptor::SizeOf(map, object); 243 } 244 }; 245 246 } // namespace internal 247 } // namespace v8 248 249 #endif // V8_OBJECTS_OBJECTS_BODY_DESCRIPTORS_H_ 250