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 "ecmascript/mem/shared_heap/shared_concurrent_marker.h"
17
18 #include "ecmascript/checkpoint/thread_state_transition.h"
19 #include "ecmascript/mem/shared_heap/shared_gc_marker-inl.h"
20 #include "ecmascript/mem/shared_heap/shared_gc_visitor-inl.h"
21 #include "ecmascript/mem/verification.h"
22
23 namespace panda::ecmascript {
SharedConcurrentMarker(EnableConcurrentMarkType type)24 SharedConcurrentMarker::SharedConcurrentMarker(EnableConcurrentMarkType type)
25 : sHeap_(SharedHeap::GetInstance()),
26 dThread_(DaemonThread::GetInstance()),
27 sWorkManager_(sHeap_->GetWorkManager()),
28 enableMarkType_(type) {}
29
EnableConcurrentMarking(EnableConcurrentMarkType type)30 void SharedConcurrentMarker::EnableConcurrentMarking(EnableConcurrentMarkType type)
31 {
32 if (IsConfigDisabled()) {
33 return;
34 }
35 if (IsEnabled() && !dThread_->IsReadyToConcurrentMark() && type == EnableConcurrentMarkType::DISABLE) {
36 enableMarkType_ = EnableConcurrentMarkType::REQUEST_DISABLE;
37 } else {
38 enableMarkType_ = type;
39 }
40 }
41
MarkRoots(SharedMarkType markType)42 void SharedConcurrentMarker::MarkRoots(SharedMarkType markType)
43 {
44 SharedGCMarkRootVisitor sharedGCMarkRootVisitor(sWorkManager_, DAEMON_THREAD_INDEX);
45 sHeap_->GetSharedGCMarker()->MarkRoots(sharedGCMarkRootVisitor, markType);
46 }
47
Mark(TriggerGCType gcType,GCReason gcReason)48 void SharedConcurrentMarker::Mark(TriggerGCType gcType, GCReason gcReason)
49 {
50 RecursionScope recurScope(this);
51 gcType_ = gcType;
52 gcReason_ = gcReason;
53 sHeap_->WaitSensitiveStatusFinished();
54 {
55 ThreadManagedScope runningScope(dThread_);
56 SuspendAllScope scope(dThread_);
57 TRACE_GC(GCStats::Scope::ScopeId::ConcurrentMark, sHeap_->GetEcmaGCStats());
58 LOG_GC(DEBUG) << "SharedConcurrentMarker: Concurrent Marking Begin";
59 ECMA_BYTRACE_NAME(HITRACE_TAG_ARK, "SharedConcurrentMarker::Mark;Reason"
60 + std::to_string(static_cast<int>(gcReason))
61 + ";Sensitive" + std::to_string(static_cast<int>(sHeap_->GetSensitiveStatus()))
62 + ";IsInBackground" + std::to_string(sHeap_->IsInBackground())
63 + ";Startup" + std::to_string(static_cast<int>(sHeap_->GetStartupStatus()))
64 + ";Old" + std::to_string(sHeap_->GetOldSpace()->GetCommittedSize())
65 + ";huge" + std::to_string(sHeap_->GetHugeObjectSpace()->GetCommittedSize())
66 + ";NonMov" + std::to_string(sHeap_->GetNonMovableSpace()->GetCommittedSize())
67 + ";TotCommit" + std::to_string(sHeap_->GetCommittedSize())
68 + ";NativeBindingSize" + std::to_string(sHeap_->GetNativeSizeAfterLastGC())
69 + ";NativeLimitGC" + std::to_string(sHeap_->GetNativeSizeTriggerSharedGC())
70 + ";NativeLimitCM" + std::to_string(sHeap_->GetNativeSizeTriggerSharedCM()));
71 CHECK_DAEMON_THREAD();
72 // TODO: support shared runtime state
73 if (UNLIKELY(sHeap_->ShouldVerifyHeap())) {
74 SharedHeapVerification(sHeap_, VerifyKind::VERIFY_PRE_SHARED_GC).VerifyAll();
75 }
76 InitializeMarking();
77 }
78 // Daemon thread do not need to post task to GC_Thread
79 ASSERT(!dThread_->IsInRunningState());
80 DoMarking();
81 HandleMarkingFinished();
82 }
83
Finish()84 void SharedConcurrentMarker::Finish()
85 {
86 sWorkManager_->Finish();
87 }
88
ReMark()89 void SharedConcurrentMarker::ReMark()
90 {
91 CHECK_DAEMON_THREAD();
92 #ifndef NDEBUG
93 ASSERT(dThread_->HasLaunchedSuspendAll());
94 #endif
95 TRACE_GC(GCStats::Scope::ScopeId::ReMark, sHeap_->GetEcmaGCStats());
96 LOG_GC(DEBUG) << "SharedConcurrentMarker: Remarking Begin";
97 // TODO: support shared runtime state
98 SharedGCMarker *sharedGCMarker = sHeap_->GetSharedGCMarker();
99 // If enable shared concurrent mark, the recorded weak reference slots from local to share may be changed
100 // during LocalGC. For now just re-scan the local_to_share bit to record and update these weak references.
101 MarkRoots(SharedMarkType::CONCURRENT_MARK_REMARK);
102 sharedGCMarker->DoMark<SharedMarkType::CONCURRENT_MARK_REMARK>(DAEMON_THREAD_INDEX);
103 sharedGCMarker->MergeBackAndResetRSetWorkListHandler();
104 sHeap_->WaitRunningTaskFinished();
105 }
106
Reset(bool clearGCBits)107 void SharedConcurrentMarker::Reset(bool clearGCBits)
108 {
109 Finish();
110 dThread_->SetSharedMarkStatus(SharedMarkStatus::READY_TO_CONCURRENT_MARK);
111 isConcurrentMarking_ = false;
112 if (clearGCBits) {
113 sHeap_->GetOldSpace()->RevertCSets();
114 // Shared gc clear GC bits in ReclaimRegions after GC
115 auto callback = [](Region *region) {
116 region->ClearMarkGCBitset();
117 region->ResetAliveObject();
118 region->ClearCrossRegionRSet();
119 };
120 sHeap_->EnumerateOldSpaceRegions(callback);
121 }
122 }
123
ResetWorkManager(SharedGCWorkManager * sWorkManager)124 void SharedConcurrentMarker::ResetWorkManager(SharedGCWorkManager *sWorkManager)
125 {
126 sWorkManager_ = sWorkManager;
127 }
128
InitializeMarking()129 void SharedConcurrentMarker::InitializeMarking()
130 {
131 CHECK_DAEMON_THREAD();
132 // TODO: support shared runtime state
133 sHeap_->Prepare(true);
134 if (gcType_ == TriggerGCType::SHARED_PARTIAL_GC) {
135 sHeap_->GetOldSpace()->SelectCSets();
136 }
137 isConcurrentMarking_ = true;
138 dThread_->SetSharedMarkStatus(SharedMarkStatus::CONCURRENT_MARKING_OR_FINISHED);
139
140 sHeapObjectSize_ = sHeap_->GetHeapObjectSize();
141 sHeap_->GetAppSpawnSpace()->EnumerateRegions([](Region *current) {
142 current->ClearMarkGCBitset();
143 current->ClearCrossRegionRSet();
144 });
145 sHeap_->EnumerateOldSpaceRegions([](Region *current) {
146 ASSERT(current->InSharedSweepableSpace());
147 current->ResetAliveObject();
148 });
149 sWorkManager_->Initialize(TriggerGCType::SHARED_GC, SharedParallelMarkPhase::SHARED_MARK_TASK);
150 MarkRoots(SharedMarkType::CONCURRENT_MARK_INITIAL_MARK);
151 }
152
DoMarking()153 void SharedConcurrentMarker::DoMarking()
154 {
155 ClockScope clockScope;
156 sHeap_->GetSharedGCMarker()->DoMark<SharedMarkType::CONCURRENT_MARK_INITIAL_MARK>(DAEMON_THREAD_INDEX);
157 sHeap_->WaitRunningTaskFinished();
158 FinishMarking(clockScope.TotalSpentTime());
159 }
160
FinishMarking(float spendTime)161 void SharedConcurrentMarker::FinishMarking(float spendTime)
162 {
163 sHeapObjectSize_ = sHeap_->GetHeapObjectSize();
164 SetDuration(spendTime);
165 }
166
HandleMarkingFinished()167 void SharedConcurrentMarker::HandleMarkingFinished()
168 {
169 sHeap_->WaitSensitiveStatusFinished();
170 sHeap_->DaemonCollectGarbage(gcType_, gcReason_);
171 }
172 } // namespace panda::ecmascript
173