• 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 
16 #ifndef PANDA_RUNTIME_MEM_OBJECT_HELPERS_INL_H
17 #define PANDA_RUNTIME_MEM_OBJECT_HELPERS_INL_H
18 
19 #include "runtime/mem/object_helpers.h"
20 #include "runtime/include/class.h"
21 #include "runtime/include/coretypes/array-inl.h"
22 #include "runtime/include/coretypes/dyn_objects.h"
23 #include "runtime/include/coretypes/string.h"
24 #include "runtime/include/coretypes/class.h"
25 #include "runtime/include/hclass.h"
26 
27 namespace panda::mem {
28 
29 template <typename Handler>
TraverseClass(Class * cls,Handler & handler)30 void GCStaticObjectHelpers::TraverseClass(Class *cls, Handler &handler)
31 {
32     // Iterate over static fields
33     uint32_t ref_num = cls->GetRefFieldsNum<true>();
34     if (ref_num > 0) {
35         uint32_t offset = cls->GetRefFieldsOffset<true>();
36         ObjectHeader *object = cls->GetManagedObject();
37         ASSERT(ToUintPtr(cls) + offset >= ToUintPtr(object));
38         // The offset is relative to the class. Adjust it to make relative to the managed object
39         uint32_t obj_offset = ToUintPtr(cls) + offset - ToUintPtr(object);
40         uint32_t ref_volatile_num = cls->GetVolatileRefFieldsNum<true>();
41         for (uint32_t i = 0; i < ref_num;
42              i++, offset += ClassHelper::OBJECT_POINTER_SIZE, obj_offset += ClassHelper::OBJECT_POINTER_SIZE) {
43             bool is_volatile = (i < ref_volatile_num);
44             auto *field_object = is_volatile ? cls->GetFieldObject<true>(offset) : cls->GetFieldObject<false>(offset);
45             if (field_object == nullptr) {
46                 continue;
47             }
48             bool res = handler(object, field_object, obj_offset, is_volatile);
49             if (!res) {
50                 return;
51             }
52         }
53     }
54 }
55 
56 template <typename Handler>
TraverseObject(ObjectHeader * object,Class * cls,Handler & handler)57 void GCStaticObjectHelpers::TraverseObject(ObjectHeader *object, Class *cls, Handler &handler)
58 {
59     ASSERT(cls != nullptr && !cls->IsDynamicClass());
60     while (cls != nullptr) {
61         // Iterate over instance fields
62         uint32_t ref_num = cls->GetRefFieldsNum<false>();
63         if (ref_num == 0) {
64             cls = cls->GetBase();
65             continue;
66         }
67 
68         uint32_t offset = cls->GetRefFieldsOffset<false>();
69         uint32_t ref_volatile_num = cls->GetVolatileRefFieldsNum<false>();
70         for (uint32_t i = 0; i < ref_num; i++, offset += ClassHelper::OBJECT_POINTER_SIZE) {
71             bool is_volatile = (i < ref_volatile_num);
72             auto *field_object =
73                 is_volatile ? object->GetFieldObject<true>(offset) : object->GetFieldObject<false>(offset);
74             if (field_object == nullptr) {
75                 continue;
76             }
77             ValidateObject(object, field_object);
78             bool res = handler(object, field_object, offset, is_volatile);
79             if (!res) {
80                 return;
81             }
82         }
83 
84         cls = cls->GetBase();
85     }
86 }
87 
88 template <typename Handler>
TraverseArray(coretypes::Array * array,Class * cls,Handler & handler)89 void GCStaticObjectHelpers::TraverseArray(coretypes::Array *array, [[maybe_unused]] Class *cls, Handler &handler)
90 {
91     ASSERT(!cls->IsDynamicClass());
92     ASSERT(cls != nullptr);
93     ASSERT(cls->IsObjectArrayClass());
94     auto array_length = array->GetLength();
95     for (coretypes::array_size_t i = 0; i < array_length; i++) {
96         auto *array_element = array->Get<ObjectHeader *>(i);
97         if (array_element != nullptr) {
98             bool res = handler(array, array_element, array->GetElementOffset<false>(i), false);
99             if (!res) {
100                 return;
101             }
102         }
103     }
104 }
105 
106 template <typename Handler>
TraverseAllObjectsWithInfo(ObjectHeader * object_header,Handler & handler)107 void GCStaticObjectHelpers::TraverseAllObjectsWithInfo(ObjectHeader *object_header, Handler &handler)
108 {
109     auto *cls = object_header->ClassAddr<Class>();
110     ASSERT(cls != nullptr);
111 
112     if (cls->IsObjectArrayClass()) {
113         TraverseArray(static_cast<coretypes::Array *>(object_header), cls, handler);
114     } else {
115         if (cls->IsClassClass()) {
116             auto object_cls = panda::Class::FromClassObject(object_header);
117             if (object_cls->IsInitializing() || object_cls->IsInitialized()) {
118                 TraverseClass(object_cls, handler);
119             }
120         }
121         TraverseObject(object_header, cls, handler);
122     }
123 }
124 
125 template <typename Handler>
TraverseClass(coretypes::DynClass * dyn_class,Handler & handler)126 void GCDynamicObjectHelpers::TraverseClass(coretypes::DynClass *dyn_class, Handler &handler)
127 {
128     size_t hklass_size = dyn_class->ClassAddr<HClass>()->GetObjectSize() - sizeof(coretypes::DynClass);
129     size_t body_size = hklass_size - sizeof(HClass);
130     size_t num_of_fields = body_size / TaggedValue::TaggedTypeSize();
131     for (size_t i = 0; i < num_of_fields; i++) {
132         size_t field_offset = sizeof(ObjectHeader) + sizeof(HClass) + i * TaggedValue::TaggedTypeSize();
133         auto tagged_value = ObjectAccessor::GetDynValue<TaggedValue>(dyn_class, field_offset);
134         if (tagged_value.IsHeapObject()) {
135             bool res = handler(dyn_class, tagged_value.GetHeapObject(), field_offset, false);
136             if (!res) {
137                 return;
138             }
139         }
140     }
141 }
142 
143 template <typename Handler>
TraverseObject(ObjectHeader * object,HClass * cls,Handler & handler)144 void GCDynamicObjectHelpers::TraverseObject(ObjectHeader *object, HClass *cls, Handler &handler)
145 {
146     ASSERT(cls->IsDynamicClass());
147     LOG(DEBUG, GC) << "TraverseObject Current object: " << GetDebugInfoAboutObject(object);
148     // handle object data
149     uint32_t obj_body_size = cls->GetObjectSize() - ObjectHeader::ObjectHeaderSize();
150     ASSERT(obj_body_size % TaggedValue::TaggedTypeSize() == 0);
151     uint32_t num_of_fields = obj_body_size / TaggedValue::TaggedTypeSize();
152     size_t data_offset = ObjectHeader::ObjectHeaderSize();
153     for (uint32_t i = 0; i < num_of_fields; i++) {
154         size_t field_offset = data_offset + i * TaggedValue::TaggedTypeSize();
155         if (cls->IsNativeField(field_offset)) {
156             continue;
157         }
158         auto tagged_value = ObjectAccessor::GetDynValue<TaggedValue>(object, field_offset);
159         if (tagged_value.IsHeapObject()) {
160             bool res = handler(object, tagged_value.GetHeapObject(), field_offset, false);
161             if (!res) {
162                 return;
163             }
164         }
165     }
166 }
167 
168 template <typename Handler>
TraverseArray(coretypes::Array * array,HClass * cls,Handler & handler)169 void GCDynamicObjectHelpers::TraverseArray(coretypes::Array *array, [[maybe_unused]] HClass *cls, Handler &handler)
170 {
171     ASSERT(cls != nullptr);
172     ASSERT(cls->IsDynamicClass());
173 
174     ASSERT(cls->IsArray());
175     auto array_length = array->GetLength();
176     for (coretypes::array_size_t i = 0; i < array_length; i++) {
177         TaggedValue array_element(array->Get<TaggedType, false, true>(i));
178         uint32_t offset = array->GetElementOffset<true>(i);
179         if (array_element.IsHeapObject()) {
180             bool res = handler(array, array_element.GetHeapObject(), offset, false);
181             if (!res) {
182                 return;
183             }
184         }
185     }
186 }
187 
188 template <typename Handler>
TraverseAllObjectsWithInfo(ObjectHeader * object_header,Handler & handler)189 void GCDynamicObjectHelpers::TraverseAllObjectsWithInfo(ObjectHeader *object_header, Handler &handler)
190 {
191     auto *cls = object_header->ClassAddr<HClass>();
192     ASSERT(cls != nullptr && cls->IsDynamicClass());
193     if (cls->IsString() || cls->IsNativePointer()) {
194         return;
195     }
196     if (cls->IsArray()) {
197         TraverseArray(static_cast<coretypes::Array *>(object_header), cls, handler);
198     } else {
199         if (cls->IsHClass()) {
200             TraverseClass(coretypes::DynClass::Cast(object_header), handler);
201         } else {
202             TraverseObject(object_header, cls, handler);
203         }
204     }
205 }
206 
207 }  // namespace panda::mem
208 
209 #endif  // PANDA_RUNTIME_MEM_OBJECT_HELPERS_INL_H
210