1 /**
2 * Copyright (c) 2024 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 #include "runtime/mem/gc/gc_adaptive_marking_stack.h"
17 #include "runtime/mem/gc/gc.h"
18 #include "runtime/mem/gc/workers/gc_workers_task_pool.h"
19 #include "runtime/mem/gc/gc_adaptive_stack_inl.h"
20
21 namespace ark::mem {
22
~GCAdaptiveMarkingStack()23 GCAdaptiveMarkingStack::~GCAdaptiveMarkingStack()
24 {
25 auto allocator = GetGC()->GetInternalAllocator();
26 allocator->Delete(additionalMarkingInfo_);
27 }
28
PushToStack(const ObjectHeader * fromObject,ObjectHeader * object)29 void GCAdaptiveMarkingStack::PushToStack(const ObjectHeader *fromObject, ObjectHeader *object)
30 {
31 LOG(DEBUG, GC) << "Add object to stack: " << GetDebugInfoAboutObject(object)
32 << " accessed from object: " << fromObject;
33 ValidateObject(fromObject, object);
34 GCAdaptiveStack<ObjectHeader *>::PushToStack(object);
35 }
36
PushToStack(RootType rootType,ObjectHeader * object)37 void GCAdaptiveMarkingStack::PushToStack(RootType rootType, ObjectHeader *object)
38 {
39 LOG(DEBUG, GC) << "Add object to stack: " << GetDebugInfoAboutObject(object) << " accessed as a root: " << rootType;
40 ValidateObject(rootType, object);
41 GCAdaptiveStack<ObjectHeader *>::PushToStack(object);
42 }
43
CreateStack()44 GCAdaptiveMarkingStack *GCAdaptiveMarkingStack::CreateStack()
45 {
46 auto *gc = GetGC();
47 auto allocator = gc->GetInternalAllocator();
48 // New tasks will be created with the same new_task_stack_size_limit_ and stack_size_limit_
49 return allocator->New<GCAdaptiveMarkingStack>(gc, GetNewTaskStackSizeLimit(), GetNewTaskStackSizeLimit(),
50 GetTaskType(), GetTimeLimitForNewTaskCreation(), GetStackDst());
51 }
52
CreateTask(GCAdaptiveStack<ObjectHeader * > * stack)53 GCWorkersTask GCAdaptiveMarkingStack::CreateTask(GCAdaptiveStack<ObjectHeader *> *stack)
54 {
55 return GCMarkWorkersTask(GetTaskType(), static_cast<GCAdaptiveMarkingStack *>(stack));
56 }
57
MarkObjects(const GCAdaptiveMarkingStack::ObjectVisitor & visitor)58 GCAdaptiveMarkingStack::MarkedObjects GCAdaptiveMarkingStack::MarkObjects(
59 const GCAdaptiveMarkingStack::ObjectVisitor &visitor)
60 {
61 // We need this to avoid allocation of new stack and fragmentation
62 static constexpr size_t BUCKET_SIZE = 16;
63 auto *gc = GetGC();
64 auto allocator = gc->GetInternalAllocator();
65 MarkedObjects markedObjects;
66 PandaDeque<ObjectHeader *> *tailMarkedObjects =
67 allocator->template New<PandaDeque<ObjectHeader *>>(allocator->Adapter());
68 if (GetStackSrc()->empty()) {
69 std::swap(GetStackSrc(), GetStackDst());
70 }
71 while (!Empty()) {
72 [[maybe_unused]] auto stackSrcSize = GetStackSrc()->size();
73 for (auto *object : *GetStackSrc()) {
74 visitor(object);
75 // visitor mustn't pop from stack
76 ASSERT(stackSrcSize == GetStackSrc()->size());
77 }
78 if (LIKELY(GetStackSrc()->size() > BUCKET_SIZE)) {
79 markedObjects.push_back(GetStackSrc());
80 GetStackSrc() = allocator->template New<PandaDeque<ObjectHeader *>>(allocator->Adapter());
81 } else {
82 tailMarkedObjects->insert(tailMarkedObjects->end(), GetStackSrc()->begin(), GetStackSrc()->end());
83 GetStackSrc()->clear();
84 }
85 std::swap(GetStackSrc(), GetStackDst());
86 }
87 if (!tailMarkedObjects->empty()) {
88 markedObjects.push_back(tailMarkedObjects);
89 } else {
90 allocator->Delete(tailMarkedObjects);
91 }
92 return markedObjects;
93 }
94 } // namespace ark::mem
95