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 // A forward-declacable descriptor body alias for most of the Struct successors. 156 class StructBodyDescriptor 157 : public FlexibleBodyDescriptor<HeapObject::kHeaderSize> { 158 public: 159 }; 160 161 // This class describes a body of an object in which all pointer fields are 162 // located in the [start_offset, object_size) interval. 163 // Pointers may be strong or may be MaybeObject-style weak pointers. 164 template <int start_offset> 165 class SuffixRangeWeakBodyDescriptor : public BodyDescriptorBase { 166 public: 167 static const int kStartOffset = start_offset; 168 IsValidSlot(Map map,HeapObject obj,int offset)169 static bool IsValidSlot(Map map, HeapObject obj, int offset) { 170 return (offset >= kStartOffset); 171 } 172 173 template <typename ObjectVisitor> IterateBody(Map map,HeapObject obj,int object_size,ObjectVisitor * v)174 static inline void IterateBody(Map map, HeapObject obj, int object_size, 175 ObjectVisitor* v) { 176 IterateMaybeWeakPointers(obj, start_offset, object_size, v); 177 } 178 179 private: SizeOf(Map map,HeapObject object)180 static inline int SizeOf(Map map, HeapObject object) { 181 // Has to be implemented by the subclass. 182 UNREACHABLE(); 183 } 184 }; 185 186 // This class describes a body of an object of a variable size 187 // in which all pointer fields are located in the [start_offset, object_size) 188 // interval. 189 // Pointers may be strong or may be MaybeObject-style weak pointers. 190 template <int start_offset> 191 class FlexibleWeakBodyDescriptor 192 : public SuffixRangeWeakBodyDescriptor<start_offset> { 193 public: 194 static inline int SizeOf(Map map, HeapObject object); 195 }; 196 197 // This class describes a body of an object without any pointers. 198 class DataOnlyBodyDescriptor : public BodyDescriptorBase { 199 public: IsValidSlot(Map map,HeapObject obj,int offset)200 static bool IsValidSlot(Map map, HeapObject obj, int offset) { return false; } 201 202 template <typename ObjectVisitor> IterateBody(Map map,HeapObject obj,int object_size,ObjectVisitor * v)203 static inline void IterateBody(Map map, HeapObject obj, int object_size, 204 ObjectVisitor* v) {} 205 206 private: SizeOf(Map map,HeapObject object)207 static inline int SizeOf(Map map, HeapObject object) { 208 // Has to be implemented by the subclass. 209 UNREACHABLE(); 210 } 211 }; 212 213 // This class describes a body of an object which has a parent class that also 214 // has a body descriptor. This represents a union of the parent's body 215 // descriptor, and a new descriptor for the child -- so, both parent and child's 216 // slots are iterated. The parent must be fixed size, and its slots be disjoint 217 // with the child's. 218 template <class ParentBodyDescriptor, class ChildBodyDescriptor> 219 class SubclassBodyDescriptor final : public BodyDescriptorBase { 220 public: 221 // The parent must end be before the child's start offset, to make sure that 222 // their slots are disjoint. 223 STATIC_ASSERT(ParentBodyDescriptor::kSize <= 224 ChildBodyDescriptor::kStartOffset); 225 IsValidSlot(Map map,HeapObject obj,int offset)226 static bool IsValidSlot(Map map, HeapObject obj, int offset) { 227 return ParentBodyDescriptor::IsValidSlot(map, obj, offset) || 228 ChildBodyDescriptor::IsValidSlot(map, obj, offset); 229 } 230 231 template <typename ObjectVisitor> IterateBody(Map map,HeapObject obj,ObjectVisitor * v)232 static inline void IterateBody(Map map, HeapObject obj, ObjectVisitor* v) { 233 ParentBodyDescriptor::IterateBody(map, obj, v); 234 ChildBodyDescriptor::IterateBody(map, obj, v); 235 } 236 237 template <typename ObjectVisitor> IterateBody(Map map,HeapObject obj,int object_size,ObjectVisitor * v)238 static inline void IterateBody(Map map, HeapObject obj, int object_size, 239 ObjectVisitor* v) { 240 ParentBodyDescriptor::IterateBody(map, obj, object_size, v); 241 ChildBodyDescriptor::IterateBody(map, obj, object_size, v); 242 } 243 SizeOf(Map map,HeapObject object)244 static inline int SizeOf(Map map, HeapObject object) { 245 // The child should know its full size. 246 return ChildBodyDescriptor::SizeOf(map, object); 247 } 248 }; 249 250 } // namespace internal 251 } // namespace v8 252 253 #endif // V8_OBJECTS_OBJECTS_BODY_DESCRIPTORS_H_ 254