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_gc_marker-inl.h"
17
18 #include "ecmascript/mem/object_xray.h"
19 #include "ecmascript/mem/shared_heap/shared_full_gc.h"
20 #include "ecmascript/mem/shared_heap/shared_gc_visitor-inl.h"
21 #include "ecmascript/mem/shared_heap/shared_full_gc-inl.h"
22
23 namespace panda::ecmascript {
MarkRoots(RootVisitor & visitor,SharedMarkType markType)24 void SharedGCMarkerBase::MarkRoots(RootVisitor &visitor, SharedMarkType markType)
25 {
26 ECMA_BYTRACE_NAME(HITRACE_LEVEL_COMMERCIAL, HITRACE_TAG_ARK, "SharedGCMarkerBase::MarkRoots", "");
27 MarkSerializeRoots(visitor);
28 MarkSharedModule(visitor);
29 MarkStringCache(visitor);
30 Runtime *runtime = Runtime::GetInstance();
31 if (markType != SharedMarkType::CONCURRENT_MARK_REMARK) {
32 // The approximate size is enough, because even if some thread creates and registers after here, it will keep
33 // waiting in transition to RUNNING state before JSThread::SetReadyForGCIterating.
34 rSetHandlers_.reserve(runtime->ApproximateThreadListSize());
35 ASSERT(rSetHandlers_.empty());
36 }
37 runtime->GCIterateThreadList([&](JSThread *thread) {
38 ASSERT(!thread->IsInRunningState());
39 auto vm = thread->GetEcmaVM();
40 MarkLocalVMRoots(visitor, vm, markType);
41 if (markType != SharedMarkType::CONCURRENT_MARK_REMARK) {
42 CollectLocalVMRSet(vm);
43 }
44 });
45 }
46
MarkLocalVMRoots(RootVisitor & visitor,EcmaVM * localVm,SharedMarkType markType)47 void SharedGCMarkerBase::MarkLocalVMRoots(RootVisitor &visitor, EcmaVM *localVm, SharedMarkType markType)
48 {
49 ECMA_BYTRACE_NAME(HITRACE_LEVEL_COMMERCIAL, HITRACE_TAG_ARK, "SharedGCMarkerBase::MarkLocalVMRoots", "");
50 Heap *heap = const_cast<Heap*>(localVm->GetHeap());
51 if (markType != SharedMarkType::CONCURRENT_MARK_REMARK) {
52 heap->GetSweeper()->EnsureAllTaskFinished();
53 }
54 ObjectXRay::VisitVMRoots(localVm, visitor);
55 heap->ProcessSharedGCMarkingLocalBuffer();
56 }
57
CollectLocalVMRSet(EcmaVM * localVm)58 void SharedGCMarkerBase::CollectLocalVMRSet(EcmaVM *localVm)
59 {
60 ECMA_BYTRACE_NAME(HITRACE_LEVEL_COMMERCIAL, HITRACE_TAG_ARK, "SharedGCMarkerBase::CollectLocalVMRSet", "");
61 Heap *heap = const_cast<Heap*>(localVm->GetHeap());
62 RSetWorkListHandler *handler = new RSetWorkListHandler(heap, localVm->GetJSThreadNoCheck());
63 heap->SetRSetWorkListHandler(handler);
64 NotifyThreadProcessRsetStart(handler->GetOwnerThreadUnsafe());
65 rSetHandlers_.emplace_back(handler);
66 }
67
MarkSerializeRoots(RootVisitor & visitor)68 void SharedGCMarkerBase::MarkSerializeRoots(RootVisitor &visitor)
69 {
70 ECMA_BYTRACE_NAME(HITRACE_LEVEL_COMMERCIAL, HITRACE_TAG_ARK, "SharedGCMarkerBase::MarkSerializeRoots", "");
71 Runtime::GetInstance()->IterateSerializeRoot(visitor);
72 }
73
MarkStringCache(RootVisitor & visitor)74 void SharedGCMarkerBase::MarkStringCache(RootVisitor &visitor)
75 {
76 ECMA_BYTRACE_NAME(HITRACE_LEVEL_COMMERCIAL, HITRACE_TAG_ARK, "SharedGCMarkerBase::MarkStringCache", "");
77 Runtime::GetInstance()->IterateCachedStringRoot(visitor);
78 }
79
MarkSharedModule(RootVisitor & visitor)80 void SharedGCMarkerBase::MarkSharedModule(RootVisitor &visitor)
81 {
82 ECMA_BYTRACE_NAME(HITRACE_LEVEL_COMMERCIAL, HITRACE_TAG_ARK, "SharedGCMarkerBase::MarkSharedModule", "");
83 SharedModuleManager::GetInstance()->Iterate(visitor);
84 }
85
ProcessMarkStack(uint32_t threadId)86 void SharedGCMarker::ProcessMarkStack(uint32_t threadId)
87 {
88 #ifndef NDEBUG
89 DaemonThread *dThread = DaemonThread::GetInstance();
90 if (UNLIKELY(!dThread->IsRunning())) {
91 // This DAEMON_THREAD_INDEX not means in daemon thread, but the daemon thread is terminated, and
92 // SharedGC is directly running in the current js thread, this maybe happen only AppSpawn
93 // trigger GC after PreFork (which is not expected), and at this time ParallelGC is disabled
94 ASSERT(threadId == DAEMON_THREAD_INDEX);
95 } else {
96 if (os::thread::GetCurrentThreadId() != dThread->GetThreadId()) {
97 ASSERT(threadId != 0);
98 } else {
99 ASSERT(threadId == 0);
100 }
101 }
102 #endif
103 SharedGCMarkObjectVisitor sharedGCMarkObjectVisitor(sWorkManager_, threadId);
104 TaggedObject *obj = nullptr;
105 while (sWorkManager_->Pop(threadId, &obj)) {
106 JSHClass *hclass = obj->SynchronizedGetClass();
107 auto size = hclass->SizeFromJSHClass(obj);
108 Region *region = Region::ObjectAddressToRange(obj);
109 ASSERT(region->InSharedSweepableSpace());
110 region->IncreaseAliveObject(size);
111
112 sharedGCMarkObjectVisitor.VisitHClass(hclass);
113 ObjectXRay::VisitObjectBody<VisitType::OLD_GC_VISIT>(obj, hclass, sharedGCMarkObjectVisitor);
114 }
115 }
116
ProcessMarkStack(uint32_t threadId)117 void SharedGCMovableMarker::ProcessMarkStack(uint32_t threadId)
118 {
119 #ifndef NDEBUG
120 DaemonThread *dThread = DaemonThread::GetInstance();
121 if (UNLIKELY(!dThread->IsRunning())) {
122 // This DAEMON_THREAD_INDEX not means in daemon thread, but the daemon thread is terminated, and
123 // SharedGC is directly running in the current js thread, this maybe happen only AppSpawn
124 // trigger GC after PreFork (which is not expected), and at this time ParallelGC is disabled
125 ASSERT(threadId == DAEMON_THREAD_INDEX);
126 } else {
127 if (os::thread::GetCurrentThreadId() != dThread->GetThreadId()) {
128 ASSERT(threadId != 0);
129 } else {
130 ASSERT(threadId == 0);
131 }
132 }
133 #endif
134 SharedFullGCMarkObjectVisitor sharedFullGCMarkObjectVisitor(this, threadId);
135 TaggedObject *obj = nullptr;
136 while (sWorkManager_->Pop(threadId, &obj)) {
137 JSHClass *hclass = obj->SynchronizedGetClass();
138 ObjectSlot objectSlot(ToUintPtr(obj));
139 MarkObject(threadId, hclass, objectSlot);
140 ObjectXRay::VisitObjectBody<VisitType::OLD_GC_VISIT>(obj, hclass, sharedFullGCMarkObjectVisitor);
141 }
142 }
143
MergeBackAndResetRSetWorkListHandler()144 void SharedGCMarkerBase::MergeBackAndResetRSetWorkListHandler()
145 {
146 for (RSetWorkListHandler *handler : rSetHandlers_) {
147 handler->MergeBack();
148 delete handler;
149 }
150 rSetHandlers_.clear();
151 }
152
ResetWorkManager(SharedGCWorkManager * workManager)153 void SharedGCMarkerBase::ResetWorkManager(SharedGCWorkManager *workManager)
154 {
155 sWorkManager_ = workManager;
156 }
157
SharedGCMarker(SharedGCWorkManager * workManger)158 SharedGCMarker::SharedGCMarker(SharedGCWorkManager *workManger)
159 : SharedGCMarkerBase(workManger) {}
160
SharedGCMovableMarker(SharedGCWorkManager * workManger,SharedHeap * sHeap)161 SharedGCMovableMarker::SharedGCMovableMarker(SharedGCWorkManager *workManger, SharedHeap *sHeap)
162 : SharedGCMarkerBase(workManger), sHeap_(sHeap) {}
163
164 } // namespace panda::ecmascript
165