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