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