// Copyright 2015 the V8 project authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef V8_OBJECTS_BODY_DESCRIPTORS_H_ #define V8_OBJECTS_BODY_DESCRIPTORS_H_ #include "src/objects.h" #include "src/objects/map.h" namespace v8 { namespace internal { // This is the base class for object's body descriptors. // // Each BodyDescriptor subclass must provide the following methods: // // 1) Returns true if the object contains a tagged value at given offset. // It is used for invalid slots filtering. If the offset points outside // of the object or to the map word, the result is UNDEFINED (!!!). // // static bool IsValidSlot(Map map, HeapObject obj, int offset); // // // 2) Iterate object's body using stateful object visitor. // // template <typename ObjectVisitor> // static inline void IterateBody(Map map, HeapObject obj, int object_size, // ObjectVisitor* v); class BodyDescriptorBase { public: template <typename ObjectVisitor> static inline void IteratePointers(HeapObject obj, int start_offset, int end_offset, ObjectVisitor* v); template <typename ObjectVisitor> static inline void IteratePointer(HeapObject obj, int offset, ObjectVisitor* v); template <typename ObjectVisitor> static inline void IterateCustomWeakPointers(HeapObject obj, int start_offset, int end_offset, ObjectVisitor* v); template <typename ObjectVisitor> static inline void IterateCustomWeakPointer(HeapObject obj, int offset, ObjectVisitor* v); template <typename ObjectVisitor> static inline void IterateEphemeron(HeapObject obj, int index, int key_offset, int value_offset, ObjectVisitor* v); template <typename ObjectVisitor> static inline void IterateMaybeWeakPointers(HeapObject obj, int start_offset, int end_offset, ObjectVisitor* v); template <typename ObjectVisitor> static inline void IterateMaybeWeakPointer(HeapObject obj, int offset, ObjectVisitor* v); protected: // Returns true for all header and embedder fields. static inline bool IsValidJSObjectSlotImpl(Map map, HeapObject obj, int offset); // Returns true for all header and embedder fields. static inline bool IsValidEmbedderJSObjectSlotImpl(Map map, HeapObject obj, int offset); // Treats all header and embedder fields in the range as tagged. template <typename ObjectVisitor> static inline void IterateJSObjectBodyImpl(Map map, HeapObject obj, int start_offset, int end_offset, ObjectVisitor* v); }; // This class describes a body of an object of a fixed size // in which all pointer fields are located in the [start_offset, end_offset) // interval. template <int start_offset, int end_offset, int size> class FixedBodyDescriptor final : public BodyDescriptorBase { public: static const int kStartOffset = start_offset; static const int kEndOffset = end_offset; static const int kSize = size; static bool IsValidSlot(Map map, HeapObject obj, int offset) { return offset >= kStartOffset && offset < kEndOffset; } template <typename ObjectVisitor> static inline void IterateBody(Map map, HeapObject obj, ObjectVisitor* v) { IteratePointers(obj, start_offset, end_offset, v); } template <typename ObjectVisitor> static inline void IterateBody(Map map, HeapObject obj, int object_size, ObjectVisitor* v) { IterateBody(map, obj, v); } static inline int SizeOf(Map map, HeapObject object) { return kSize; } }; // This class describes a body of an object of a variable size // in which all pointer fields are located in the [start_offset, object_size) // interval. template <int start_offset> class FlexibleBodyDescriptor final : public BodyDescriptorBase { public: static const int kStartOffset = start_offset; static bool IsValidSlot(Map map, HeapObject obj, int offset) { return (offset >= kStartOffset); } template <typename ObjectVisitor> static inline void IterateBody(Map map, HeapObject obj, int object_size, ObjectVisitor* v) { IteratePointers(obj, start_offset, object_size, v); } static inline int SizeOf(Map map, HeapObject object); }; typedef FlexibleBodyDescriptor<HeapObject::kHeaderSize> StructBodyDescriptor; template <int start_offset> class FlexibleWeakBodyDescriptor final : public BodyDescriptorBase { public: static const int kStartOffset = start_offset; static bool IsValidSlot(Map map, HeapObject obj, int offset) { return (offset >= kStartOffset); } template <typename ObjectVisitor> static inline void IterateBody(Map map, HeapObject obj, int object_size, ObjectVisitor* v) { IterateMaybeWeakPointers(obj, start_offset, object_size, v); } static inline int SizeOf(Map map, HeapObject object); }; // This class describes a body of an object which has a parent class that also // has a body descriptor. This represents a union of the parent's body // descriptor, and a new descriptor for the child -- so, both parent and child's // slots are iterated. The parent must be fixed size, and its slots be disjoint // with the child's. template <class ParentBodyDescriptor, class ChildBodyDescriptor> class SubclassBodyDescriptor final : public BodyDescriptorBase { public: // The parent must end be before the child's start offset, to make sure that // their slots are disjoint. STATIC_ASSERT(ParentBodyDescriptor::kSize <= ChildBodyDescriptor::kStartOffset); static bool IsValidSlot(Map map, HeapObject obj, int offset) { return ParentBodyDescriptor::IsValidSlot(map, obj, offset) || ChildBodyDescriptor::IsValidSlot(map, obj, offset); } template <typename ObjectVisitor> static inline void IterateBody(Map map, HeapObject obj, ObjectVisitor* v) { ParentBodyDescriptor::IterateBody(map, obj, v); ChildBodyDescriptor::IterateBody(map, obj, v); } template <typename ObjectVisitor> static inline void IterateBody(Map map, HeapObject obj, int object_size, ObjectVisitor* v) { ParentBodyDescriptor::IterateBody(map, obj, object_size, v); ChildBodyDescriptor::IterateBody(map, obj, object_size, v); } static inline int SizeOf(Map map, HeapObject object) { // The child should know its full size. return ChildBodyDescriptor::SizeOf(map, object); } }; } // namespace internal } // namespace v8 #endif // V8_OBJECTS_BODY_DESCRIPTORS_H_