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