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_GC_STATIC_GC_MARKER_STATIC_INL_H
17 #define PANDA_RUNTIME_MEM_GC_STATIC_GC_MARKER_STATIC_INL_H
18
19 #include "runtime/mem/gc/gc_marker.h"
20
21 namespace panda::mem {
22
23 template <typename Marker>
HandleObject(GCMarkingStackType * objects_stack,const ObjectHeader * object,const Class * cls)24 void GCMarker<Marker, LANG_TYPE_STATIC, false>::HandleObject(GCMarkingStackType *objects_stack,
25 const ObjectHeader *object, const Class *cls)
26 {
27 while (cls != nullptr) {
28 // Iterate over instance fields
29 uint32_t ref_num = cls->GetRefFieldsNum<false>();
30 if (ref_num > 0) {
31 uint32_t offset = cls->GetRefFieldsOffset<false>();
32 uint32_t ref_volatile_num = cls->GetVolatileRefFieldsNum<false>();
33 for (uint32_t i = 0; i < ref_num; i++, offset += ClassHelper::OBJECT_POINTER_SIZE) {
34 auto *field_object = (i < ref_volatile_num) ? object->GetFieldObject<true>(offset)
35 : object->GetFieldObject<false>(offset);
36 ValidateObject(object, field_object);
37 if (field_object != nullptr && AsMarker()->MarkIfNotMarked(field_object)) {
38 objects_stack->PushToStack(object, field_object);
39 }
40 }
41 }
42 cls = cls->GetBase();
43 }
44 }
45 template <typename Marker>
HandleClass(GCMarkingStackType * objects_stack,const Class * cls)46 void GCMarker<Marker, LANG_TYPE_STATIC, false>::HandleClass(GCMarkingStackType *objects_stack, const Class *cls)
47 {
48 // Iterate over static fields
49 uint32_t ref_num = cls->GetRefFieldsNum<true>();
50 if (ref_num > 0) {
51 uint32_t offset = cls->GetRefFieldsOffset<true>();
52 uint32_t ref_volatile_num = cls->GetVolatileRefFieldsNum<true>();
53 for (uint32_t i = 0; i < ref_num; i++, offset += ClassHelper::OBJECT_POINTER_SIZE) {
54 auto *field_object =
55 (i < ref_volatile_num) ? cls->GetFieldObject<true>(offset) : cls->GetFieldObject<false>(offset);
56 if (field_object != nullptr && AsMarker()->MarkIfNotMarked(field_object)) {
57 objects_stack->PushToStack(cls->GetManagedObject(), field_object);
58 }
59 }
60 }
61 }
62
63 template <typename Marker>
HandleArrayClass(GCMarkingStackType * objects_stack,const coretypes::Array * array_object,const Class * cls)64 void GCMarker<Marker, LANG_TYPE_STATIC, false>::HandleArrayClass(GCMarkingStackType *objects_stack,
65 const coretypes::Array *array_object,
66 [[maybe_unused]] const Class *cls)
67 {
68 LOG(DEBUG, GC) << "Array object: " << GetDebugInfoAboutObject(array_object);
69 auto array_length = array_object->GetLength();
70
71 ASSERT(cls->IsObjectArrayClass());
72
73 LOG(DEBUG, GC) << "Iterate over: " << array_length << " elements in array";
74 for (coretypes::array_size_t i = 0; i < array_length; i++) {
75 auto *array_element = array_object->Get<ObjectHeader *>(i);
76 if (array_element == nullptr) {
77 continue;
78 }
79 #ifndef NDEBUG
80 auto array_element_cls = array_element->ClassAddr<Class>();
81 LOG_IF(array_element_cls == nullptr, DEBUG, GC)
82 << " object's class is nullptr: " << array_element << " from array: " << array_object;
83 ASSERT(array_element_cls != nullptr);
84 #endif
85 if (AsMarker()->MarkIfNotMarked(array_element)) {
86 objects_stack->PushToStack(array_object, array_element);
87 }
88 }
89 }
90
91 template <typename Marker>
MarkInstance(GCMarkingStackType * objects_stack,const ReferenceCheckPredicateT & ref_pred,const ObjectHeader * object,const BaseClass * base_cls)92 void GCMarker<Marker, LANG_TYPE_STATIC, false>::MarkInstance(GCMarkingStackType *objects_stack,
93 const ReferenceCheckPredicateT &ref_pred,
94 const ObjectHeader *object, const BaseClass *base_cls)
95 {
96 ASSERT(!base_cls->IsDynamicClass());
97 auto cls = static_cast<const Class *>(base_cls);
98 if (GetGC()->IsReference(cls, object, ref_pred)) {
99 GetGC()->ProcessReference(objects_stack, cls, object, GC::EmptyReferenceProcessPredicate);
100 } else if (cls->IsObjectArrayClass()) {
101 auto *array_object = static_cast<const panda::coretypes::Array *>(object);
102 HandleArrayClass(objects_stack, array_object, cls);
103 } else if (cls->IsClassClass()) {
104 // Handle Class handles static fields only, so we need to Handle regular fields explicitly too
105 auto object_cls = panda::Class::FromClassObject(object);
106 if (object_cls->IsInitializing() || object_cls->IsInitialized()) {
107 HandleClass(objects_stack, object_cls);
108 }
109 HandleObject(objects_stack, object, cls);
110 } else if (cls->IsInstantiable()) {
111 HandleObject(objects_stack, object, cls);
112 } else {
113 if (!cls->IsPrimitive()) {
114 LOG(FATAL, GC) << "Wrong handling, missed type: " << cls->GetDescriptor();
115 }
116 }
117 }
118
119 } // namespace panda::mem
120
121 #endif // PANDA_RUNTIME_MEM_GC_STATIC_GC_MARKER_STATIC_INL_H
122