1 /* 2 * Copyright (c) 2022 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #ifndef ECMASCRIPT_MEM_VISITOR_H 17 #define ECMASCRIPT_MEM_VISITOR_H 18 19 #include <functional> 20 21 #include <ecmascript/mem/slots.h> 22 #include <ecmascript/mem/tagged_object.h> 23 24 namespace panda::ecmascript { 25 enum class Root { 26 ROOT_FRAME, 27 ROOT_HANDLE, 28 ROOT_VM, 29 ROOT_STRING, 30 ROOT_INTERNAL_CALL_PARAMS, 31 }; 32 33 enum class VisitObjectArea { 34 NORMAL, 35 NATIVE_POINTER, 36 IN_OBJECT, 37 RAW_DATA 38 }; 39 40 enum class VisitType : size_t { SEMI_GC_VISIT, OLD_GC_VISIT, SNAPSHOT_VISIT, ALL_VISIT }; 41 42 using RootVisitor = std::function<void(Root type, ObjectSlot p)>; 43 using RootRangeVisitor = std::function<void(Root type, ObjectSlot start, ObjectSlot end)>; 44 using RootBaseAndDerivedVisitor = 45 std::function<void(Root type, ObjectSlot base, ObjectSlot derived, uintptr_t baseOldObject)>; 46 using EcmaObjectRangeVisitor = std::function<void(TaggedObject *root, ObjectSlot start, ObjectSlot end, 47 VisitObjectArea area)>; 48 using WeakRootVisitor = std::function<TaggedObject *(TaggedObject *p)>; 49 50 template <VisitType visitType, size_t size> 51 class PrimitiveObjectBodyIterator { 52 public: IterateBody(TaggedObject * root,const EcmaObjectRangeVisitor & visitor)53 static inline void IterateBody(TaggedObject *root, const EcmaObjectRangeVisitor& visitor) 54 { 55 if (visitType == VisitType::ALL_VISIT) { 56 size_t hclassEnd = sizeof(JSTaggedType); 57 visitor(root, ObjectSlot(ToUintPtr(root)), 58 ObjectSlot(ToUintPtr(root) + hclassEnd), VisitObjectArea::NORMAL); 59 if (size > hclassEnd) { 60 visitor(root, ObjectSlot(ToUintPtr(root) + hclassEnd), 61 ObjectSlot(ToUintPtr(root) + size), VisitObjectArea::RAW_DATA); 62 } 63 } 64 } 65 }; 66 67 template <VisitType visitType, size_t startOffset, size_t endOffset, size_t size> 68 class ObjectBodyIterator { 69 public: 70 template <VisitObjectArea area, bool visitHClass> IterateBody(TaggedObject * root,const EcmaObjectRangeVisitor & visitor,size_t startSize)71 static inline void IterateBody(TaggedObject *root, const EcmaObjectRangeVisitor& visitor, size_t startSize) 72 { 73 if (visitType == VisitType::ALL_VISIT) { 74 if (visitHClass) { 75 IterateHClass(root, visitor); 76 } 77 IterateBefore(root, visitor, startSize); 78 } 79 visitor(root, ObjectSlot(ToUintPtr(root) + startOffset), 80 ObjectSlot(ToUintPtr(root) + endOffset), area); 81 if (visitType == VisitType::ALL_VISIT) { 82 IterateAfter(root, visitor); 83 } 84 } 85 IterateRefBody(TaggedObject * root,const EcmaObjectRangeVisitor & visitor)86 static inline void IterateRefBody(TaggedObject *root, const EcmaObjectRangeVisitor& visitor) 87 { 88 IterateBody<VisitObjectArea::NORMAL, true>(root, visitor, sizeof(JSTaggedType)); 89 } 90 IterateNativeBody(TaggedObject * root,const EcmaObjectRangeVisitor & visitor)91 static inline void IterateNativeBody(TaggedObject *root, const EcmaObjectRangeVisitor& visitor) 92 { 93 IterateBody<VisitObjectArea::NATIVE_POINTER, true>(root, visitor, sizeof(JSTaggedType)); 94 } 95 IterateRefBody(TaggedObject * root,const EcmaObjectRangeVisitor & visitor,size_t parentSize)96 static inline void IterateRefBody(TaggedObject *root, const EcmaObjectRangeVisitor& visitor, size_t parentSize) 97 { 98 IterateBody<VisitObjectArea::NORMAL, false>(root, visitor, parentSize); 99 } 100 IterateHClass(TaggedObject * root,const EcmaObjectRangeVisitor & visitor)101 static inline void IterateHClass(TaggedObject *root, const EcmaObjectRangeVisitor& visitor) 102 { 103 size_t hclassEnd = sizeof(JSTaggedType); 104 visitor(root, ObjectSlot(ToUintPtr(root)), 105 ObjectSlot(ToUintPtr(root) + hclassEnd), VisitObjectArea::NORMAL); 106 } 107 IterateBefore(TaggedObject * root,const EcmaObjectRangeVisitor & visitor,size_t startSize)108 static inline void IterateBefore(TaggedObject *root, const EcmaObjectRangeVisitor& visitor, size_t startSize) 109 { 110 if (startOffset > startSize) { 111 IteratorRange(root, visitor, startSize, startOffset); 112 } 113 } 114 IterateAfter(TaggedObject * root,const EcmaObjectRangeVisitor & visitor)115 static inline void IterateAfter(TaggedObject *root, const EcmaObjectRangeVisitor& visitor) 116 { 117 if (size > endOffset) { 118 IteratorRange(root, visitor, endOffset, size); 119 } 120 } 121 IteratorRange(TaggedObject * root,const EcmaObjectRangeVisitor & visitor,size_t start,size_t end)122 static inline void IteratorRange(TaggedObject *root, const EcmaObjectRangeVisitor& visitor, 123 size_t start, size_t end) 124 { 125 visitor(root, ObjectSlot(ToUintPtr(root) + start), 126 ObjectSlot(ToUintPtr(root) + end), VisitObjectArea::RAW_DATA); 127 } 128 }; 129 130 template <VisitType visitType, size_t startOffset> 131 class ArrayBodyIterator { 132 public: IterateBody(TaggedObject * root,const EcmaObjectRangeVisitor & visitor,size_t refLength,size_t length)133 static inline void IterateBody(TaggedObject *root, const EcmaObjectRangeVisitor& visitor, 134 size_t refLength, size_t length) 135 { 136 if (visitType == VisitType::ALL_VISIT) { 137 IterateBefore(root, visitor); 138 } 139 if (LIKELY(refLength != 0)) { 140 size_t endOffset = startOffset + refLength * JSTaggedValue::TaggedTypeSize(); 141 visitor(root, ObjectSlot(ToUintPtr(root) + startOffset), 142 ObjectSlot(ToUintPtr(root) + endOffset), VisitObjectArea::NORMAL); 143 } 144 if (visitType == VisitType::ALL_VISIT) { 145 IterateAfter(root, visitor, refLength, length); 146 } 147 } 148 IterateBefore(TaggedObject * root,const EcmaObjectRangeVisitor & visitor)149 static inline void IterateBefore(TaggedObject *root, const EcmaObjectRangeVisitor& visitor) 150 { 151 size_t hclassEnd = sizeof(JSTaggedType); 152 ASSERT(startOffset > hclassEnd); 153 visitor(root, ObjectSlot(ToUintPtr(root)), ObjectSlot(ToUintPtr(root) + hclassEnd), VisitObjectArea::NORMAL); 154 IteratorRange(root, visitor, hclassEnd, startOffset); 155 } 156 IterateAfter(TaggedObject * root,const EcmaObjectRangeVisitor & visitor,size_t refLength,size_t length)157 static inline void IterateAfter(TaggedObject *root, const EcmaObjectRangeVisitor& visitor, 158 size_t refLength, size_t length) 159 { 160 if (length > refLength) { 161 size_t endOffset = startOffset + refLength * JSTaggedValue::TaggedTypeSize(); 162 size_t size = startOffset + length * JSTaggedValue::TaggedTypeSize(); 163 IteratorRange(root, visitor, endOffset, size); 164 } 165 } 166 IteratorRange(TaggedObject * root,const EcmaObjectRangeVisitor & visitor,size_t start,size_t end)167 static inline void IteratorRange(TaggedObject *root, const EcmaObjectRangeVisitor& visitor, 168 size_t start, size_t end) 169 { 170 visitor(root, ObjectSlot(ToUintPtr(root) + start), 171 ObjectSlot(ToUintPtr(root) + end), VisitObjectArea::RAW_DATA); 172 } 173 }; 174 } // namespace panda::ecmascript 175 #endif // ECMASCRIPT_MEM_VISITOR_H 176