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