• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2021-2025 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 #include "runtime/mem/gc/workers/gc_workers_task_pool.h"
21 
22 namespace ark::mem {
23 
24 template <typename Marker>
HandleObject(GCMarkingStackType * objectsStack,const ObjectHeader * object,const Class * cls)25 void GCMarker<Marker, LANG_TYPE_STATIC>::HandleObject(GCMarkingStackType *objectsStack, const ObjectHeader *object,
26                                                       const Class *cls)
27 {
28     while (cls != nullptr) {
29         // Iterate over instance fields
30         uint32_t refNum = cls->GetRefFieldsNum<false>();
31         if (refNum == 0) {
32             cls = cls->GetBase();
33             continue;
34         }
35         uint32_t offset = cls->GetRefFieldsOffset<false>();
36         uint32_t refVolatileNum = cls->GetVolatileRefFieldsNum<false>();
37         for (uint32_t i = 0; i < refVolatileNum; i++, offset += ClassHelper::OBJECT_POINTER_SIZE) {
38             auto *fieldObject = object->GetFieldObject<true>(offset);
39             ValidateObject(object, fieldObject);
40             if (fieldObject != nullptr && AsMarker()->MarkIfNotMarked(fieldObject)) {
41                 objectsStack->PushToStack(object, fieldObject);
42             }
43         }
44         for (uint32_t i = refVolatileNum; i < refNum; i++, offset += ClassHelper::OBJECT_POINTER_SIZE) {
45             auto *fieldObject = object->GetFieldObject<false>(offset);
46             ValidateObject(object, fieldObject);
47             if (fieldObject != nullptr && AsMarker()->MarkIfNotMarked(fieldObject)) {
48                 objectsStack->PushToStack(object, fieldObject);
49             }
50         }
51         cls = cls->GetBase();
52     }
53 }
54 template <typename Marker>
HandleClass(GCMarkingStackType * objectsStack,const Class * cls)55 void GCMarker<Marker, LANG_TYPE_STATIC>::HandleClass(GCMarkingStackType *objectsStack, const Class *cls)
56 {
57     // Iterate over static fields
58     uint32_t refNum = cls->GetRefFieldsNum<true>();
59     if (refNum > 0) {
60         uint32_t offset = cls->GetRefFieldsOffset<true>();
61         uint32_t refVolatileNum = cls->GetVolatileRefFieldsNum<true>();
62         for (uint32_t i = 0; i < refVolatileNum; i++, offset += ClassHelper::OBJECT_POINTER_SIZE) {
63             auto *fieldObject = cls->GetFieldObject<true>(offset);
64             if (fieldObject != nullptr && AsMarker()->MarkIfNotMarked(fieldObject)) {
65                 objectsStack->PushToStack(cls->GetManagedObject(), fieldObject);
66             }
67         }
68         for (uint32_t i = refVolatileNum; i < refNum; i++, offset += ClassHelper::OBJECT_POINTER_SIZE) {
69             auto *fieldObject = cls->GetFieldObject<false>(offset);
70             if (fieldObject != nullptr && AsMarker()->MarkIfNotMarked(fieldObject)) {
71                 objectsStack->PushToStack(cls->GetManagedObject(), fieldObject);
72             }
73         }
74     }
75 }
76 
77 template <typename Marker>
HandleArrayClass(GCMarkingStackType * objectsStack,const coretypes::Array * arrayObject,const Class * cls)78 void GCMarker<Marker, LANG_TYPE_STATIC>::HandleArrayClass(GCMarkingStackType *objectsStack,
79                                                           const coretypes::Array *arrayObject,
80                                                           [[maybe_unused]] const Class *cls)
81 {
82     LOG(DEBUG, GC) << "Array object: " << GetDebugInfoAboutObject(arrayObject);
83     ArraySizeT arrayLength = arrayObject->GetLength();
84 
85     ASSERT(cls->IsObjectArrayClass());
86 
87     LOG(DEBUG, GC) << "Iterate over: " << arrayLength << " elements in array";
88     size_t currentPartition = 0;
89     size_t partitionSize = 0;
90     constexpr size_t THRESHOLD_ARRAY_SIZE = 50000U;
91     auto *gc = GetGC();
92     bool useGcWorkers = gc->GetSettings()->ParallelMarkingEnabled();
93     auto taskType = objectsStack->GetTaskType();
94     ASSERT(taskType != GCWorkersTaskTypes::TASK_HUGE_ARRAY_MARKING_REMARK);
95     if (arrayLength >= THRESHOLD_ARRAY_SIZE && useGcWorkers && taskType == GCWorkersTaskTypes::TASK_REMARK) {
96         size_t gcWorkersNum = Runtime::GetOptions().GetTaskmanagerWorkersCount();
97         ASSERT(gcWorkersNum > 0);
98         ArraySizeT arrayPartitionsNumber = gcWorkersNum;
99         partitionSize = arrayLength / arrayPartitionsNumber;
100         auto allocator = gc->GetInternalAllocator();
101         // The rest of the array (last partition till the end of the array) is going to be traversed in current worker
102         for (; currentPartition < arrayPartitionsNumber - 1; ++currentPartition) {
103             auto *newStack = allocator->template New<GCAdaptiveMarkingStack>(
104                 gc, useGcWorkers ? gc->GetSettings()->GCRootMarkingStackMaxSize() : 0,
105                 useGcWorkers ? gc->GetSettings()->GCWorkersMarkingStackMaxSize() : 0,
106                 GCWorkersTaskTypes::TASK_HUGE_ARRAY_MARKING_REMARK);
107             ASSERT(newStack != nullptr);
108             static_cast<GCAdaptiveStack<ObjectHeader *> *>(newStack)->PushToStack(
109                 const_cast<coretypes::Array *>(arrayObject));
110             size_t taskStartIndex = currentPartition * partitionSize;
111             void *markingRangeInfo =
112                 allocator->template New<std::pair<size_t, size_t>>(taskStartIndex, taskStartIndex + partitionSize);
113             newStack->SetAdditionalMarkingInfo(markingRangeInfo);
114             if (!gc->GetWorkersTaskPool()->AddTask(GCMarkWorkersTask(newStack->GetTaskType(), newStack))) {
115                 // Couldn't create a new task. Going to process the rest of the array here
116                 allocator->Delete(newStack);
117                 break;
118             }
119         }
120     }
121     for (coretypes::ArraySizeT i = currentPartition * partitionSize; i < arrayLength; i++) {
122         auto *arrayElement = arrayObject->Get<ObjectHeader *>(i);
123         if (arrayElement == nullptr) {
124             continue;
125         }
126 #ifndef NDEBUG
127         auto arrayElementCls = arrayElement->ClassAddr<Class>();
128         LOG_IF(arrayElementCls == nullptr, ERROR, GC)
129             << " object's class is nullptr: " << arrayElement << " from array: " << arrayObject;
130         ASSERT(arrayElementCls != nullptr);
131 #endif
132         if (AsMarker()->MarkIfNotMarked(arrayElement)) {
133             objectsStack->PushToStack(arrayObject, arrayElement);
134         }
135     }
136 }
137 
138 template <typename Marker>
MarkInstance(GCMarkingStackType * objectsStack,const ObjectHeader * object,const BaseClass * baseCls,const ReferenceCheckPredicateT & refPred)139 void GCMarker<Marker, LANG_TYPE_STATIC>::MarkInstance(GCMarkingStackType *objectsStack, const ObjectHeader *object,
140                                                       const BaseClass *baseCls, const ReferenceCheckPredicateT &refPred)
141 {
142     ASSERT(!baseCls->IsDynamicClass());
143     auto cls = static_cast<const Class *>(baseCls);
144     if (GetGC()->IsReference(cls, object, refPred)) {
145         GetGC()->ProcessReference(objectsStack, cls, object, GC::EmptyReferenceProcessPredicate);
146     } else {
147         MarkInstance(objectsStack, object, baseCls);
148     }
149 }
150 
151 template <typename Marker>
MarkInstance(GCMarkingStackType * objectsStack,const ObjectHeader * object,const BaseClass * baseCls)152 void GCMarker<Marker, LANG_TYPE_STATIC>::MarkInstance(GCMarkingStackType *objectsStack, const ObjectHeader *object,
153                                                       const BaseClass *baseCls)
154 {
155     ASSERT(!baseCls->IsDynamicClass());
156     const auto *cls = static_cast<const Class *>(baseCls);
157     if (cls->IsObjectArrayClass()) {
158         auto *arrayObject = static_cast<const ark::coretypes::Array *>(object);
159         HandleArrayClass(objectsStack, arrayObject, cls);
160     } else if (cls->IsClassClass()) {
161         // Handle Class handles static fields only, so we need to Handle regular fields explicitly too
162         auto objectCls = ark::Class::FromClassObject(object);
163         ASSERT(objectCls != nullptr);
164         if (objectCls->IsInitializing() || objectCls->IsInitialized()) {
165             HandleClass(objectsStack, objectCls);
166         }
167         HandleObject(objectsStack, object, cls);
168     } else if (cls->IsInstantiable()) {
169         HandleObject(objectsStack, object, cls);
170     } else {
171         if (!cls->IsPrimitive()) {
172             LOG(FATAL, GC) << "Wrong handling, missed type: " << cls->GetDescriptor();
173         }
174     }
175 }
176 
177 }  // namespace ark::mem
178 
179 #endif  // PANDA_RUNTIME_MEM_GC_STATIC_GC_MARKER_STATIC_INL_H
180