• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2021-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 #ifndef PANDA_RUNTIME_MEM_OBJECT_HELPERS_H
16 #define PANDA_RUNTIME_MEM_OBJECT_HELPERS_H
17 
18 #include <functional>
19 
20 #include "libpandabase/utils/logger.h"
21 #include "libpandabase/mem/mem.h"
22 
23 #include "runtime/mem/gc/gc_root_type.h"
24 #include "runtime/include/object_header.h"
25 
26 namespace panda {
27 class Class;
28 class HClass;
29 class Field;
30 class ManagedThread;
31 class PandaVM;
32 }  // namespace panda
33 
34 namespace panda::coretypes {
35 class DynClass;
36 class Array;
37 }  // namespace panda::coretypes
38 
39 namespace panda::mem {
40 
41 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
42 #define LOG_DEBUG_OBJ_HELPERS LOG(DEBUG, GC) << vm->GetGC()->GetLogPrefix()
43 
44 class GC;
45 
GetObjectSize(const void * mem)46 inline size_t GetObjectSize(const void *mem)
47 {
48     return static_cast<const ObjectHeader *>(mem)->ObjectSize();
49 }
50 
51 Logger::Buffer GetDebugInfoAboutObject(const ObjectHeader *header);
52 
GetMinimalObjectSize()53 constexpr size_t GetMinimalObjectSize()
54 {
55     return GetAlignedObjectSize(ObjectHeader::ObjectHeaderSize());
56 }
57 
58 /**
59  * Validate that object is correct from point of view of GC.
60  * For example it checks that class of the object is not nullptr.
61  * @param from_object object from which we found object by reference
62  * @param object object which we want to validate
63  */
ValidateObject(const ObjectHeader * from_object,const ObjectHeader * object)64 inline void ValidateObject([[maybe_unused]] const ObjectHeader *from_object,
65                            [[maybe_unused]] const ObjectHeader *object)
66 {
67 #ifndef NDEBUG
68     if (object == nullptr) {
69         return;
70     }
71     // from_object can be null, because sometimes we call Validate when we don't know previous object (for example when
72     // we extract it from stack)
73     if (object->template ClassAddr<BaseClass>() == nullptr) {
74         LOG(ERROR, GC) << " Broken object doesn't have class: " << object << " accessed from object: " << from_object;
75         UNREACHABLE();
76     }
77 #endif  // !NDEBUG
78 }
79 
80 /**
81  * Validate that object (which is gc-root) is correct from point of view of GC
82  * See ValidateObject(from_object, object) for further explanation
83  * @param root_type type of the root
84  * @param object object (root) which we want to validate
85  */
ValidateObject(RootType root_type,const ObjectHeader * object)86 inline void ValidateObject([[maybe_unused]] RootType root_type, [[maybe_unused]] const ObjectHeader *object)
87 {
88 #ifndef NDEBUG
89     if (object == nullptr) {
90         return;
91     }
92     ASSERT_DO(object->template ClassAddr<BaseClass>() != nullptr, LOG(FATAL, GC)
93                                                                       << " Broken object doesn't have class: " << object
94                                                                       << " accessed from root: " << root_type);
95 #endif  // !NDEBUG
96 }
97 
98 void DumpObject(ObjectHeader *object_header, std::basic_ostream<char, std::char_traits<char>> *o_stream = &std::cerr);
99 
100 void DumpClass(const Class *cls, std::basic_ostream<char, std::char_traits<char>> *o_stream = &std::cerr);
101 
102 [[nodiscard]] ObjectHeader *GetForwardAddress(ObjectHeader *object_header);
103 
104 const char *GetFieldName(const Field &field);
105 
106 size_t GetDynClassInstanceSize(coretypes::DynClass *object);
107 
108 class GCStaticObjectHelpers {
109 public:
110     /**
111      * Traverse all kinds of object_header and call obj_visitor for each reference field.
112      */
113     static void TraverseAllObjects(ObjectHeader *object_header,
114                                    const std::function<void(ObjectHeader *, ObjectHeader *)> &obj_visitor);
115 
116     /**
117      * Traverse all kinds of object_header and call handler for each reference field.
118      * The handler accepts the object, the reference value, offset to the reference in the object and
119      * the flag whether the field is volatile.
120      */
121     template <typename Handler>
122     static void TraverseAllObjectsWithInfo(ObjectHeader *object, Handler &handler);
123 
124     static void UpdateRefsToMovedObjects(ObjectHeader *object);
125 
126     /**
127      * Update a single reference field in the object to the moved value.
128      * Return the moved value.
129      */
130     static ObjectHeader *UpdateRefToMovedObject(ObjectHeader *object, ObjectHeader *ref, uint32_t offset,
131                                                 bool is_volatile);
132 
133 private:
134     template <typename Handler>
135     static void TraverseClass(Class *cls, Handler &handler);
136     template <typename Handler>
137     static void TraverseArray(coretypes::Array *array, Class *cls, Handler &handler);
138     template <typename Handler>
139     static void TraverseObject(ObjectHeader *object_header, Class *cls, Handler &handler);
140 };
141 
142 class GCDynamicObjectHelpers {
143 public:
144     /**
145      * Traverse all kinds of object_header and call obj_visitor for each reference field.
146      */
147     static void TraverseAllObjects(ObjectHeader *object_header,
148                                    const std::function<void(ObjectHeader *, ObjectHeader *)> &obj_visitor);
149 
150     /**
151      * Traverse all kinds of object_header and call handler for each reference field.
152      * The handler accepts the object, the reference value, offset to the reference in the object and
153      * the flag whether the field is volatile.
154      */
155     template <typename Handler>
156     static void TraverseAllObjectsWithInfo(ObjectHeader *object_header, Handler &handler);
157 
158     static void UpdateRefsToMovedObjects(ObjectHeader *object);
159 
160     /**
161      * Update a single reference field in the object to the moved value.
162      * Return the moved value.
163      */
164     static ObjectHeader *UpdateRefToMovedObject(ObjectHeader *object, ObjectHeader *ref, uint32_t offset,
165                                                 bool is_volatile);
166 
167     static void RecordDynWeakReference(GC *gc, coretypes::TaggedType *value);
168     static void HandleDynWeakReferences(GC *gc);
169 
170 private:
171     template <typename Handler>
172     static void TraverseArray(coretypes::Array *array, HClass *cls, Handler &handler);
173     template <typename Handler>
174     static void TraverseClass(coretypes::DynClass *dyn_class, Handler &handler);
175     template <typename Handler>
176     static void TraverseObject(ObjectHeader *object_header, HClass *cls, Handler &handler);
177 
178     static void UpdateDynArray(PandaVM *vm, coretypes::Array *array, array_size_t index, ObjectHeader *obj_ref);
179 
180     static void UpdateDynObjectRef(PandaVM *vm, ObjectHeader *object_header, size_t offset,
181                                    ObjectHeader *field_obj_ref);
182 };
183 
184 template <LangTypeT LangType>
185 class GCObjectHelpers {
186 };
187 
188 template <>
189 class GCObjectHelpers<LANG_TYPE_STATIC> {
190 public:
191     using Value = GCStaticObjectHelpers;
192 };
193 
194 template <>
195 class GCObjectHelpers<LANG_TYPE_DYNAMIC> {
196 public:
197     using Value = GCDynamicObjectHelpers;
198 };
199 
200 template <LangTypeT LangType>
201 using ObjectHelpers = typename GCObjectHelpers<LangType>::Value;
202 
203 }  // namespace panda::mem
204 
205 #endif  // PANDA_OBJECT_HELPERS_H
206