• 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 
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