• 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 #include "runtime/mem/gc/gc_adaptive_stack.h"
17 #include "runtime/mem/gc/gc.h"
18 #include "runtime/mem/gc/gc_workers_thread_pool.h"
19 
20 namespace panda::mem {
21 
GCAdaptiveStack(GC * gc,size_t stack_size_limit,size_t new_task_stack_size_limit,GCWorkersTaskTypes task,PandaStack<const ObjectHeader * > * stack_src)22 GCAdaptiveStack::GCAdaptiveStack(GC *gc, size_t stack_size_limit, size_t new_task_stack_size_limit,
23                                  GCWorkersTaskTypes task, PandaStack<const ObjectHeader *> *stack_src)
24     : stack_size_limit_(stack_size_limit),
25       new_task_stack_size_limit_(new_task_stack_size_limit),
26       task_type_(task),
27       gc_(gc)
28 {
29     initial_stack_size_limit_ = stack_size_limit_;
30     auto allocator = gc_->GetInternalAllocator();
31     ASSERT((stack_size_limit == 0) || (gc->GetWorkersPool() != nullptr));
32     if (stack_src != nullptr) {
33         stack_src_ = stack_src;
34     } else {
35         stack_src_ = allocator->template New<PandaStack<const ObjectHeader *>>(allocator->Adapter());
36     }
37     stack_dst_ = allocator->template New<PandaStack<const ObjectHeader *>>(allocator->Adapter());
38 }
39 
~GCAdaptiveStack()40 GCAdaptiveStack::~GCAdaptiveStack()
41 {
42     gc_->GetInternalAllocator()->Delete(stack_src_);
43     gc_->GetInternalAllocator()->Delete(stack_dst_);
44 }
45 
Empty()46 bool GCAdaptiveStack::Empty()
47 {
48     return stack_src_->empty() && stack_dst_->empty();
49 }
50 
Size()51 size_t GCAdaptiveStack::Size()
52 {
53     return stack_src_->size() + stack_dst_->size();
54 }
55 
MoveStacksPointers()56 PandaStack<const ObjectHeader *> *GCAdaptiveStack::MoveStacksPointers()
57 {
58     ASSERT(stack_src_ != nullptr);
59     PandaStack<const ObjectHeader *> *return_value = stack_src_;
60     stack_src_ = nullptr;
61     return return_value;
62 }
63 
PushToStack(const ObjectHeader * from_object,const ObjectHeader * object)64 void GCAdaptiveStack::PushToStack(const ObjectHeader *from_object, const ObjectHeader *object)
65 {
66     LOG(DEBUG, GC) << "Add object to stack: " << GetDebugInfoAboutObject(object)
67                    << " accessed from object: " << from_object;
68     ValidateObject(from_object, object);
69     PushToStack(object);
70 }
71 
PushToStack(RootType root_type,const ObjectHeader * object)72 void GCAdaptiveStack::PushToStack(RootType root_type, const ObjectHeader *object)
73 {
74     LOG(DEBUG, GC) << "Add object to stack: " << GetDebugInfoAboutObject(object)
75                    << " accessed as a root: " << root_type;
76     ValidateObject(root_type, object);
77     PushToStack(object);
78 }
79 
PushToStack(const ObjectHeader * element)80 void GCAdaptiveStack::PushToStack(const ObjectHeader *element)
81 {
82     ASSERT(element != nullptr);
83     ASSERT(IsInObjectsAddressSpace(ToUintPtr(element)));
84     if ((stack_size_limit_ > 0) && ((stack_dst_->size() + 1) == stack_size_limit_)) {
85         // Try to create a new task only once
86         // Create a new stack and send a new task to GC
87         LOG(DEBUG, GC) << "GCAdaptiveStack: Try to add new task " << GCWorkersTaskTypesToString(task_type_)
88                        << " for worker";
89         ASSERT(gc_->GetWorkersPool() != nullptr);
90         ASSERT(task_type_ != GCWorkersTaskTypes::TASK_EMPTY);
91         auto allocator = gc_->GetInternalAllocator();
92         // New tasks will be created with the same new_task_stack_size_limit_ and stack_size_limit_
93         auto new_stack = allocator->New<GCAdaptiveStack>(gc_, new_task_stack_size_limit_, new_task_stack_size_limit_,
94                                                          task_type_, stack_dst_);
95         if (gc_->GetWorkersPool()->AddTask(task_type_, new_stack)) {
96             LOG(DEBUG, GC) << "GCAdaptiveStack: Successfully add new task " << GCWorkersTaskTypesToString(task_type_)
97                            << " for worker";
98             stack_dst_ = allocator->template New<PandaStack<const ObjectHeader *>>(allocator->Adapter());
99         } else {
100             // We will try to create a new task later
101             stack_size_limit_ += stack_size_limit_;
102             LOG(DEBUG, GC) << "GCAdaptiveStack: Failed to add new task " << GCWorkersTaskTypesToString(task_type_)
103                            << " for worker";
104             [[maybe_unused]] auto src_stack = new_stack->MoveStacksPointers();
105             ASSERT(src_stack == stack_dst_);
106             allocator->Delete(new_stack);
107         }
108     }
109     stack_dst_->push(element);
110 }
111 
PopFromStack()112 const ObjectHeader *GCAdaptiveStack::PopFromStack()
113 {
114     if (stack_src_->empty()) {
115         ASSERT(!stack_dst_->empty());
116         auto temp = stack_src_;
117         stack_src_ = stack_dst_;
118         stack_dst_ = temp;
119         if (stack_size_limit_ != 0) {
120             // We may increase the current limit, so return it to the default value
121             stack_size_limit_ = initial_stack_size_limit_;
122         }
123     }
124     ASSERT(!stack_src_->empty());
125     const ObjectHeader *element = stack_src_->top();
126     stack_src_->pop();
127     return element;
128 }
129 
IsWorkersTaskSupported()130 bool GCAdaptiveStack::IsWorkersTaskSupported()
131 {
132     return task_type_ != GCWorkersTaskTypes::TASK_EMPTY;
133 }
134 
Clear()135 void GCAdaptiveStack::Clear()
136 {
137     *stack_src_ = PandaStack<const ObjectHeader *>();
138     *stack_dst_ = PandaStack<const ObjectHeader *>();
139 }
140 
141 }  // namespace panda::mem
142