• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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