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