• 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 <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 enum class VMRootVisitType : uint8_t { MARK, UPDATE_ROOT, VERIFY, HEAP_SNAPSHOT };
42 
43 class RootVisitor {
44 public:
45     RootVisitor() = default;
46     virtual ~RootVisitor() = default;
47 
48     NO_MOVE_SEMANTIC(RootVisitor);
49     NO_COPY_SEMANTIC(RootVisitor);
50 
51     virtual void VisitRoot([[maybe_unused]] Root type, [[maybe_unused]] ObjectSlot slot) = 0;
52 
53     virtual void VisitRangeRoot([[maybe_unused]] Root type, [[maybe_unused]] ObjectSlot start,
54         [[maybe_unused]] ObjectSlot end) = 0;
55 
56     virtual void VisitBaseAndDerivedRoot([[maybe_unused]] Root type, [[maybe_unused]] ObjectSlot base,
57         [[maybe_unused]] ObjectSlot derived, [[maybe_unused]] uintptr_t baseOldObject) = 0;
58 };
59 using WeakRootVisitor = std::function<TaggedObject *(TaggedObject *p)>;
60 
61 template <class DerivedVisitor>
62 class EcmaObjectRangeVisitor {
63 public:
64     EcmaObjectRangeVisitor() = default;
65     virtual ~EcmaObjectRangeVisitor() = default;
66 
67     NO_MOVE_SEMANTIC(EcmaObjectRangeVisitor);
68     NO_COPY_SEMANTIC(EcmaObjectRangeVisitor);
69 
operator()70     void operator()(TaggedObject *root, ObjectSlot start, ObjectSlot end, VisitObjectArea area)
71     {
72         static_cast<DerivedVisitor*>(this)->VisitObjectRangeImpl(root, start, end, area);
73     }
74 
VisitHClass(TaggedObject * hclass)75     void VisitHClass(TaggedObject *hclass)
76     {
77         static_cast<DerivedVisitor*>(this)->VisitObjectHClassImpl(hclass);
78     }
79 
VisitObjectRangeImpl(TaggedObject * root,ObjectSlot start,ObjectSlot end,VisitObjectArea area)80     virtual void VisitObjectRangeImpl([[maybe_unused]] TaggedObject *root, [[maybe_unused]] ObjectSlot start,
81                                       [[maybe_unused]] ObjectSlot end, [[maybe_unused]] VisitObjectArea area)
82     {
83         UNREACHABLE();
84     }
85 
VisitObjectHClassImpl(TaggedObject * hclass)86     virtual void VisitObjectHClassImpl([[maybe_unused]] TaggedObject *hclass)
87     {
88         UNREACHABLE();
89     }
90 };
91 
92 template <VisitType visitType, size_t size>
93 class PrimitiveObjectBodyIterator {
94 public:
95     template<class DerivedVisitor>
IterateBody(TaggedObject * root,EcmaObjectRangeVisitor<DerivedVisitor> & visitor)96     static inline void IterateBody(TaggedObject *root, EcmaObjectRangeVisitor<DerivedVisitor> &visitor)
97     {
98         if constexpr (visitType == VisitType::ALL_VISIT) {
99             constexpr size_t hclassEnd = sizeof(JSTaggedType);
100             visitor(root, ObjectSlot(ToUintPtr(root)),
101                 ObjectSlot(ToUintPtr(root) + hclassEnd), VisitObjectArea::NORMAL);
102             if constexpr (size > hclassEnd) {
103                 visitor(root, ObjectSlot(ToUintPtr(root) + hclassEnd),
104                     ObjectSlot(ToUintPtr(root) + size), VisitObjectArea::RAW_DATA);
105             }
106         }
107     }
108 };
109 
110 template <VisitType visitType, size_t startOffset, size_t endOffset,
111           size_t size, size_t startSize = sizeof(JSTaggedType)>
112 class ObjectBodyIterator {
113 public:
114     template <VisitObjectArea area, bool visitHClass, class DerivedVisitor>
IterateBody(TaggedObject * root,EcmaObjectRangeVisitor<DerivedVisitor> & visitor)115     static inline void IterateBody(TaggedObject *root, EcmaObjectRangeVisitor<DerivedVisitor> &visitor)
116     {
117         if constexpr (visitType == VisitType::ALL_VISIT) {
118             if constexpr (visitHClass) {
119                 IterateHClass(root, visitor);
120             }
121             IterateBefore(root, visitor);
122         }
123         if constexpr (startOffset < endOffset) {
124             visitor(root, ObjectSlot(ToUintPtr(root) + startOffset),
125                 ObjectSlot(ToUintPtr(root) + endOffset), area);
126         }
127 
128         if constexpr (visitType == VisitType::ALL_VISIT) {
129             IterateAfter(root, visitor);
130         }
131     }
132 
133     template <class DerivedVisitor>
IterateRefBody(TaggedObject * root,EcmaObjectRangeVisitor<DerivedVisitor> & visitor)134     static inline void IterateRefBody(TaggedObject *root, EcmaObjectRangeVisitor<DerivedVisitor> &visitor)
135     {
136         IterateBody<VisitObjectArea::NORMAL, true>(root, visitor);
137     }
138 
139     template <class DerivedVisitor>
IterateNativeBody(TaggedObject * root,EcmaObjectRangeVisitor<DerivedVisitor> & visitor)140     static inline void IterateNativeBody(TaggedObject *root, EcmaObjectRangeVisitor<DerivedVisitor> &visitor)
141     {
142         IterateBody<VisitObjectArea::NATIVE_POINTER, true>(root, visitor);
143     }
144 
145     template <class DerivedVisitor>
IterateDerivedRefBody(TaggedObject * root,EcmaObjectRangeVisitor<DerivedVisitor> & visitor)146     static inline void IterateDerivedRefBody(TaggedObject *root, EcmaObjectRangeVisitor<DerivedVisitor> &visitor)
147     {
148         IterateBody<VisitObjectArea::NORMAL, false>(root, visitor);
149     }
150 
151     template <class DerivedVisitor>
IterateHClass(TaggedObject * root,EcmaObjectRangeVisitor<DerivedVisitor> & visitor)152     static inline void IterateHClass(TaggedObject *root, EcmaObjectRangeVisitor<DerivedVisitor> &visitor)
153     {
154         size_t hclassEnd = sizeof(JSTaggedType);
155         visitor(root, ObjectSlot(ToUintPtr(root)),
156             ObjectSlot(ToUintPtr(root) + hclassEnd), VisitObjectArea::NORMAL);
157     }
158 
159     template <class DerivedVisitor>
IterateBefore(TaggedObject * root,EcmaObjectRangeVisitor<DerivedVisitor> & visitor)160     static inline void IterateBefore(TaggedObject *root, EcmaObjectRangeVisitor<DerivedVisitor> &visitor)
161     {
162         if constexpr (startOffset > startSize) {
163             ASSERT(startOffset != endOffset);
164             IteratorRange(root, visitor, startSize, startOffset);
165         }
166     }
167 
168     template <class DerivedVisitor>
IterateAfter(TaggedObject * root,EcmaObjectRangeVisitor<DerivedVisitor> & visitor)169     static inline void IterateAfter(TaggedObject *root, EcmaObjectRangeVisitor<DerivedVisitor> &visitor)
170     {
171         if constexpr (size > endOffset) {
172             IteratorRange(root, visitor, endOffset, size);
173         }
174     }
175 
176     template <class DerivedVisitor>
IteratorRange(TaggedObject * root,EcmaObjectRangeVisitor<DerivedVisitor> & visitor,size_t start,size_t end)177     static inline void IteratorRange(TaggedObject *root, EcmaObjectRangeVisitor<DerivedVisitor> &visitor,
178         size_t start, size_t end)
179     {
180         visitor(root, ObjectSlot(ToUintPtr(root) + start),
181                 ObjectSlot(ToUintPtr(root) + end), VisitObjectArea::RAW_DATA);
182     }
183 };
184 
185 template <VisitType visitType, size_t startOffset>
186 class ArrayBodyIterator {
187 public:
188     template <class DerivedVisitor>
IterateBody(TaggedObject * root,EcmaObjectRangeVisitor<DerivedVisitor> & visitor,size_t refLength,size_t length)189     static inline void IterateBody(TaggedObject *root, EcmaObjectRangeVisitor<DerivedVisitor> &visitor,
190         size_t refLength, size_t length)
191     {
192         if constexpr (visitType == VisitType::ALL_VISIT) {
193             IterateBefore(root, visitor);
194         }
195         if (LIKELY(refLength != 0)) {
196             size_t endOffset = startOffset + refLength * JSTaggedValue::TaggedTypeSize();
197             visitor(root, ObjectSlot(ToUintPtr(root) + startOffset),
198                 ObjectSlot(ToUintPtr(root) + endOffset), VisitObjectArea::NORMAL);
199         }
200         if constexpr (visitType == VisitType::ALL_VISIT) {
201             IterateAfter(root, visitor, refLength, length);
202         }
203     }
204 
205     template <class DerivedVisitor>
IterateBefore(TaggedObject * root,EcmaObjectRangeVisitor<DerivedVisitor> & visitor)206     static inline void IterateBefore(TaggedObject *root, EcmaObjectRangeVisitor<DerivedVisitor> &visitor)
207     {
208         size_t hclassEnd = sizeof(JSTaggedType);
209         ASSERT(startOffset > hclassEnd);
210         visitor(root, ObjectSlot(ToUintPtr(root)), ObjectSlot(ToUintPtr(root) + hclassEnd), VisitObjectArea::NORMAL);
211         IteratorRange(root, visitor, hclassEnd, startOffset);
212     }
213 
214     template <class DerivedVisitor>
IterateAfter(TaggedObject * root,EcmaObjectRangeVisitor<DerivedVisitor> & visitor,size_t refLength,size_t length)215     static inline void IterateAfter(TaggedObject *root, EcmaObjectRangeVisitor<DerivedVisitor> &visitor,
216         size_t refLength, size_t length)
217     {
218         if (length > refLength) {
219             size_t endOffset = startOffset + refLength * JSTaggedValue::TaggedTypeSize();
220             size_t size = startOffset + length * JSTaggedValue::TaggedTypeSize();
221             IteratorRange(root, visitor, endOffset, size);
222         }
223     }
224 
225     template <class DerivedVisitor>
IteratorRange(TaggedObject * root,EcmaObjectRangeVisitor<DerivedVisitor> & visitor,size_t start,size_t end)226     static inline void IteratorRange(TaggedObject *root, EcmaObjectRangeVisitor<DerivedVisitor> &visitor,
227         size_t start, size_t end)
228     {
229         visitor(root, ObjectSlot(ToUintPtr(root) + start),
230                 ObjectSlot(ToUintPtr(root) + end), VisitObjectArea::RAW_DATA);
231     }
232 };
233 }  // namespace panda::ecmascript
234 #endif  // ECMASCRIPT_MEM_VISITOR_H
235