• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "common_interfaces/heap/heap_visitor.h"
22 #include "ecmascript/mem/slots.h"
23 #include "ecmascript/mem/tagged_object.h"
24 
25 namespace panda::ecmascript {
26 enum class Root {
27     ROOT_FRAME,
28     ROOT_HANDLE,
29     ROOT_VM,
30     ROOT_STRING,
31     ROOT_INTERNAL_CALL_PARAMS,
32 };
33 
34 enum class VisitObjectArea {
35     NORMAL,
36     NATIVE_POINTER,
37     IN_OBJECT,
38     RAW_DATA
39 };
40 
41 enum class VisitType : size_t { SEMI_GC_VISIT, OLD_GC_VISIT, SNAPSHOT_VISIT, ALL_VISIT };
42 enum class VMRootVisitType : uint8_t { MARK, UPDATE_ROOT, VERIFY, HEAP_SNAPSHOT };
43 
44 template <class DerivedVisitor>
45 class BaseObjectVisitor {
46 public:
47     BaseObjectVisitor() = default;
48     virtual ~BaseObjectVisitor() = default;
49 
50     NO_MOVE_SEMANTIC(BaseObjectVisitor);
51     NO_COPY_SEMANTIC(BaseObjectVisitor);
52 
operator()53     void operator()(BaseObject *rootObject, uintptr_t startAddr, uintptr_t endAddr, VisitObjectArea area)
54     {
55         static_cast<DerivedVisitor*>(this)->VisitObjectRangeImpl(rootObject, startAddr, endAddr, area);
56     }
57 
VisitHClass(BaseObject * hclass)58     void VisitHClass(BaseObject *hclass)
59     {
60         static_cast<DerivedVisitor*>(this)->VisitObjectHClassImpl(hclass);
61     }
62 
63     // A temporary impl to collect JSWeakMap, need to refactor and fix
VisitJSWeakMap(BaseObject * rootObject)64     void VisitJSWeakMap(BaseObject *rootObject)
65     {
66         ASSERT(JSTaggedValue(TaggedObject::Cast(rootObject)).IsJSWeakMap());
67         static_cast<DerivedVisitor*>(this)->VisitJSWeakMapImpl(rootObject);
68     }
69 
VisitObjectRangeImpl(BaseObject * rootObject,uintptr_t startAddr,uintptr_t endAddr,VisitObjectArea area)70     virtual void VisitObjectRangeImpl([[maybe_unused]] BaseObject *rootObject, [[maybe_unused]] uintptr_t startAddr,
71                                       [[maybe_unused]] uintptr_t endAddr, [[maybe_unused]] VisitObjectArea area)
72     {}
73 
VisitObjectHClassImpl(BaseObject * hclass)74     virtual void VisitObjectHClassImpl([[maybe_unused]] BaseObject *hclass)
75     {}
76 
VisitJSWeakMapImpl(BaseObject * rootObject)77     virtual void VisitJSWeakMapImpl([[maybe_unused]] BaseObject *rootObject)
78     {}
79 };
80 
81 class RootVisitor {
82 public:
83     RootVisitor() = default;
84     virtual ~RootVisitor() = default;
85 
86     NO_MOVE_SEMANTIC(RootVisitor);
87     NO_COPY_SEMANTIC(RootVisitor);
88 
89     virtual void VisitRoot([[maybe_unused]] Root type, [[maybe_unused]] ObjectSlot slot) = 0;
90 
91     virtual void VisitRangeRoot([[maybe_unused]] Root type, [[maybe_unused]] ObjectSlot start,
92         [[maybe_unused]] ObjectSlot end) = 0;
93 
94     virtual void VisitBaseAndDerivedRoot([[maybe_unused]] Root type, [[maybe_unused]] ObjectSlot base,
95         [[maybe_unused]] ObjectSlot derived, [[maybe_unused]] uintptr_t baseOldObject) = 0;
96 };
97 
98 class WeakVisitor {
99 public:
100     WeakVisitor() = default;
101     virtual ~WeakVisitor() = default;
102 
103     NO_MOVE_SEMANTIC(WeakVisitor);
104     NO_COPY_SEMANTIC(WeakVisitor);
105 
106     virtual bool VisitRoot([[maybe_unused]] Root type, [[maybe_unused]] ObjectSlot slot) = 0;
107 };
108 
109 using WeakRootVisitor = std::function<TaggedObject *(TaggedObject *p)>;
110 
111 template <VisitType visitType, size_t size>
112 class PrimitiveObjectBodyIterator {
113 public:
114     template <class DerivedVisitor>
IterateBody(TaggedObject * root,BaseObjectVisitor<DerivedVisitor> & visitor)115     static inline void IterateBody(TaggedObject *root, BaseObjectVisitor<DerivedVisitor> &visitor)
116     {
117         if constexpr (visitType == VisitType::ALL_VISIT) {
118             constexpr size_t hclassEnd = sizeof(JSTaggedType);
119             visitor(root, ToUintPtr(root),
120                 ToUintPtr(root) + hclassEnd, VisitObjectArea::NORMAL);
121             if constexpr (size > hclassEnd) {
122                 visitor(root, ToUintPtr(root) + hclassEnd,
123                     ToUintPtr(root) + size, VisitObjectArea::RAW_DATA);
124             }
125         }
126     }
127 };
128 
129 template <VisitType visitType, size_t startOffset, size_t endOffset,
130           size_t size, size_t startSize = sizeof(JSTaggedType)>
131 class ObjectBodyIterator {
132 public:
133     template <VisitObjectArea area, bool visitHClass, class DerivedVisitor>
IterateBody(TaggedObject * root,BaseObjectVisitor<DerivedVisitor> & visitor)134     static inline void IterateBody(TaggedObject *root, BaseObjectVisitor<DerivedVisitor> &visitor)
135     {
136         if constexpr (visitType == VisitType::ALL_VISIT) {
137             if constexpr (visitHClass) {
138                 IterateHClass(root, visitor);
139             }
140             IterateBefore(root, visitor);
141         }
142         if constexpr (startOffset < endOffset) {
143             visitor(root, ToUintPtr(root) + startOffset,
144                 ToUintPtr(root) + endOffset, area);
145         }
146 
147         if constexpr (visitType == VisitType::ALL_VISIT) {
148             IterateAfter(root, visitor);
149         }
150     }
151 
152     template <class DerivedVisitor>
IterateRefBody(TaggedObject * root,BaseObjectVisitor<DerivedVisitor> & visitor)153     static inline void IterateRefBody(TaggedObject *root, BaseObjectVisitor<DerivedVisitor> &visitor)
154     {
155         IterateBody<VisitObjectArea::NORMAL, true>(root, visitor);
156     }
157 
158     template <class DerivedVisitor>
IterateNativeBody(TaggedObject * root,BaseObjectVisitor<DerivedVisitor> & visitor)159     static inline void IterateNativeBody(TaggedObject *root, BaseObjectVisitor<DerivedVisitor> &visitor)
160     {
161         IterateBody<VisitObjectArea::NATIVE_POINTER, true>(root, visitor);
162     }
163 
164     template <class DerivedVisitor>
IterateDerivedRefBody(TaggedObject * root,BaseObjectVisitor<DerivedVisitor> & visitor)165     static inline void IterateDerivedRefBody(TaggedObject *root, BaseObjectVisitor<DerivedVisitor> &visitor)
166     {
167         IterateBody<VisitObjectArea::NORMAL, false>(root, visitor);
168     }
169 
170     template <class DerivedVisitor>
IterateHClass(TaggedObject * root,BaseObjectVisitor<DerivedVisitor> & visitor)171     static inline void IterateHClass(TaggedObject *root, BaseObjectVisitor<DerivedVisitor> &visitor)
172     {
173         visitor.VisitHClass(root->GetClass());
174     }
175 
176     template <class DerivedVisitor>
IterateBefore(TaggedObject * root,BaseObjectVisitor<DerivedVisitor> & visitor)177     static inline void IterateBefore(TaggedObject *root, BaseObjectVisitor<DerivedVisitor> &visitor)
178     {
179         if constexpr (startOffset > startSize) {
180             ASSERT(startOffset != endOffset);
181             IteratorRange(root, visitor, startSize, startOffset);
182         }
183     }
184 
185     template <class DerivedVisitor>
IterateAfter(TaggedObject * root,BaseObjectVisitor<DerivedVisitor> & visitor)186     static inline void IterateAfter(TaggedObject *root, BaseObjectVisitor<DerivedVisitor> &visitor)
187     {
188         if constexpr (size > endOffset) {
189             IteratorRange(root, visitor, endOffset, size);
190         }
191     }
192 
193     template <class DerivedVisitor>
IteratorRange(TaggedObject * root,BaseObjectVisitor<DerivedVisitor> & visitor,size_t start,size_t end)194     static inline void IteratorRange(TaggedObject *root, BaseObjectVisitor<DerivedVisitor> &visitor,
195         size_t start, size_t end)
196     {
197         visitor(root, ToUintPtr(root) + start,
198                 ToUintPtr(root) + end, VisitObjectArea::RAW_DATA);
199     }
200 };
201 
202 template <VisitType visitType, size_t startOffset>
203 class ArrayBodyIterator {
204 public:
205     template <class DerivedVisitor>
IterateBody(TaggedObject * root,BaseObjectVisitor<DerivedVisitor> & visitor,size_t refLength,size_t length)206     static inline void IterateBody(TaggedObject *root, BaseObjectVisitor<DerivedVisitor> &visitor,
207         size_t refLength, size_t length)
208     {
209         if constexpr (visitType == VisitType::ALL_VISIT) {
210             IterateBefore(root, visitor);
211         }
212         if (LIKELY(refLength != 0)) {
213             size_t endOffset = startOffset + refLength * JSTaggedValue::TaggedTypeSize();
214             visitor(root, ToUintPtr(root) + startOffset,
215                 ToUintPtr(root) + endOffset, VisitObjectArea::NORMAL);
216         }
217         if constexpr (visitType == VisitType::ALL_VISIT) {
218             IterateAfter(root, visitor, refLength, length);
219         }
220     }
221 
222     template <class DerivedVisitor>
IterateBefore(TaggedObject * root,BaseObjectVisitor<DerivedVisitor> & visitor)223     static inline void IterateBefore(TaggedObject *root, BaseObjectVisitor<DerivedVisitor> &visitor)
224     {
225         size_t hclassEnd = sizeof(JSTaggedType);
226         ASSERT(startOffset > hclassEnd);
227         visitor.VisitHClass(root->GetClass());
228         IteratorRange(root, visitor, hclassEnd, startOffset);
229     }
230 
231     template <class DerivedVisitor>
IterateAfter(TaggedObject * root,BaseObjectVisitor<DerivedVisitor> & visitor,size_t refLength,size_t length)232     static inline void IterateAfter(TaggedObject *root, BaseObjectVisitor<DerivedVisitor> &visitor,
233         size_t refLength, size_t length)
234     {
235         if (length > refLength) {
236             size_t endOffset = startOffset + refLength * JSTaggedValue::TaggedTypeSize();
237             size_t size = startOffset + length * JSTaggedValue::TaggedTypeSize();
238             IteratorRange(root, visitor, endOffset, size);
239         }
240     }
241 
242     template <class DerivedVisitor>
IteratorRange(TaggedObject * root,BaseObjectVisitor<DerivedVisitor> & visitor,size_t start,size_t end)243     static inline void IteratorRange(TaggedObject *root, BaseObjectVisitor<DerivedVisitor> &visitor,
244         size_t start, size_t end)
245     {
246         visitor(root, ToUintPtr(root) + start,
247                 ToUintPtr(root) + end, VisitObjectArea::RAW_DATA);
248     }
249 };
250 }  // namespace panda::ecmascript
251 #endif  // ECMASCRIPT_MEM_VISITOR_H
252