• 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)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