• 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_gc_marker-inl.h"
17 
18 #include "ecmascript/mem/object_xray.h"
19 #include "ecmascript/runtime.h"
20 
21 namespace panda::ecmascript {
MarkRoots(uint32_t threadId,SharedMarkType markType,VMRootVisitType type)22 void SharedGCMarkerBase::MarkRoots(uint32_t threadId, SharedMarkType markType, VMRootVisitType type)
23 {
24     ECMA_BYTRACE_NAME(HITRACE_TAG_ARK, "SharedGCMarkerBase::MarkRoots");
25     MarkSerializeRoots(threadId);
26     MarkSharedModule(threadId);
27     MarkStringCache(threadId);
28     Runtime *runtime = Runtime::GetInstance();
29     if (markType != SharedMarkType::CONCURRENT_MARK_REMARK) {
30         // The approximate size is enough, because even if some thread creates and registers after here, it will keep
31         // waiting in transition to RUNNING state before JSThread::SetReadyForGCIterating.
32         rSetHandlers_.reserve(runtime->ApproximateThreadListSize());
33         ASSERT(rSetHandlers_.empty());
34     }
35     runtime->GCIterateThreadList([&](JSThread *thread) {
36         ASSERT(!thread->IsInRunningState());
37         auto vm = thread->GetEcmaVM();
38         MarkLocalVMRoots(threadId, vm, markType, type);
39         if (markType != SharedMarkType::CONCURRENT_MARK_REMARK) {
40             CollectLocalVMRSet(vm);
41         }
42     });
43 }
44 
MarkLocalVMRoots(uint32_t threadId,EcmaVM * localVm,SharedMarkType markType,VMRootVisitType type)45 void SharedGCMarkerBase::MarkLocalVMRoots(uint32_t threadId, EcmaVM *localVm, SharedMarkType markType,
46                                           VMRootVisitType type)
47 {
48     ECMA_BYTRACE_NAME(HITRACE_TAG_ARK, "SharedGCMarkerBase::MarkLocalVMRoots");
49     Heap *heap = const_cast<Heap*>(localVm->GetHeap());
50     if (markType != SharedMarkType::CONCURRENT_MARK_REMARK) {
51         heap->GetSweeper()->EnsureAllTaskFinished();
52     }
53     ObjectXRay::VisitVMRoots(
54         localVm,
55         [this, threadId](Root type, ObjectSlot slot) {this->HandleLocalRoots(threadId, type, slot);},
56         [this, threadId](Root type, ObjectSlot start, ObjectSlot end) {
57             this->HandleLocalRangeRoots(threadId, type, start, end);
58         },
59         [this](Root type, ObjectSlot base, ObjectSlot derived, uintptr_t baseOldObject) {
60             this->HandleLocalDerivedRoots(type, base, derived, baseOldObject);
61         }, type);
62     heap->ProcessSharedGCMarkingLocalBuffer();
63 }
64 
CollectLocalVMRSet(EcmaVM * localVm)65 void SharedGCMarkerBase::CollectLocalVMRSet(EcmaVM *localVm)
66 {
67     ECMA_BYTRACE_NAME(HITRACE_TAG_ARK, "SharedGCMarkerBase::CollectLocalVMRSet");
68     Heap *heap = const_cast<Heap*>(localVm->GetHeap());
69     RSetWorkListHandler *handler = new RSetWorkListHandler(heap, localVm->GetJSThreadNoCheck());
70     heap->SetRSetWorkListHandler(handler);
71     NotifyThreadProcessRsetStart(handler->GetOwnerThreadUnsafe());
72     rSetHandlers_.emplace_back(handler);
73 }
74 
MarkSerializeRoots(uint32_t threadId)75 void SharedGCMarkerBase::MarkSerializeRoots(uint32_t threadId)
76 {
77     ECMA_BYTRACE_NAME(HITRACE_TAG_ARK, "SharedGCMarkerBase::MarkSerializeRoots");
78     auto callback = [this, threadId](Root type, ObjectSlot slot) {this->HandleRoots(threadId, type, slot);};
79     Runtime::GetInstance()->IterateSerializeRoot(callback);
80 }
81 
MarkStringCache(uint32_t threadId)82 void SharedGCMarkerBase::MarkStringCache(uint32_t threadId)
83 {
84     ECMA_BYTRACE_NAME(HITRACE_TAG_ARK, "SharedGCMarkerBase::MarkStringCache");
85     auto cacheStringCallback = [this, threadId](Root type, ObjectSlot start, ObjectSlot end) {
86         this->HandleLocalRangeRoots(threadId, type, start, end);
87     };
88     Runtime::GetInstance()->IterateCachedStringRoot(cacheStringCallback);
89 }
90 
MarkSharedModule(uint32_t threadId)91 void SharedGCMarkerBase::MarkSharedModule(uint32_t threadId)
92 {
93     ECMA_BYTRACE_NAME(HITRACE_TAG_ARK, "SharedGCMarkerBase::MarkSharedModule");
94     auto visitor = [this, threadId](Root type, ObjectSlot slot) {this->HandleRoots(threadId, type, slot);};
95     SharedModuleManager::GetInstance()->Iterate(visitor);
96 }
97 
ProcessMarkStack(uint32_t threadId)98 void SharedGCMarker::ProcessMarkStack(uint32_t threadId)
99 {
100 #ifndef NDEBUG
101     DaemonThread *dThread = DaemonThread::GetInstance();
102     if (UNLIKELY(!dThread->IsRunning())) {
103         // This DAEMON_THREAD_INDEX not means in daemon thread, but the daemon thread is terminated, and
104         // SharedGC is directly running in the current js thread, this maybe happen only AppSpawn
105         // trigger GC after PreFork (which is not expected), and at this time ParallelGC is disabled
106         ASSERT(threadId == DAEMON_THREAD_INDEX);
107     } else {
108         if (os::thread::GetCurrentThreadId() != dThread->GetThreadId()) {
109             ASSERT(threadId != 0);
110         } else {
111             ASSERT(threadId == 0);
112         }
113     }
114 #endif
115     auto cb = [&](ObjectSlot slot) {
116         MarkValue(threadId, slot);
117     };
118     EcmaObjectRangeVisitor visitor = [this, threadId, cb](TaggedObject *root, ObjectSlot start, ObjectSlot end,
119                                         VisitObjectArea area) {
120         if (area == VisitObjectArea::IN_OBJECT) {
121             if (VisitBodyInObj(root, start, end, cb)) {
122                 return;
123             }
124         }
125         for (ObjectSlot slot = start; slot < end; slot++) {
126             MarkValue(threadId, slot);
127         }
128     };
129     TaggedObject *obj = nullptr;
130     while (true) {
131         obj = nullptr;
132         if (!sWorkManager_->Pop(threadId, &obj)) {
133             break;
134         }
135         JSHClass *hclass = obj->SynchronizedGetClass();
136         auto size = hclass->SizeFromJSHClass(obj);
137         Region *region = Region::ObjectAddressToRange(obj);
138         ASSERT(region->InSharedSweepableSpace());
139         region->IncreaseAliveObjectSafe(size);
140         ObjectSlot objectSlot(ToUintPtr(obj));
141         MarkObject(threadId, hclass, objectSlot);
142         ObjectXRay::VisitObjectBody<VisitType::OLD_GC_VISIT>(obj, hclass, visitor);
143     }
144 }
145 
ProcessMarkStack(uint32_t threadId)146 void SharedGCMovableMarker::ProcessMarkStack(uint32_t threadId)
147 {
148 #ifndef NDEBUG
149     DaemonThread *dThread = DaemonThread::GetInstance();
150     if (UNLIKELY(!dThread->IsRunning())) {
151         // This DAEMON_THREAD_INDEX not means in daemon thread, but the daemon thread is terminated, and
152         // SharedGC is directly running in the current js thread, this maybe happen only AppSpawn
153         // trigger GC after PreFork (which is not expected), and at this time ParallelGC is disabled
154         ASSERT(threadId == DAEMON_THREAD_INDEX);
155     } else {
156         if (os::thread::GetCurrentThreadId() != dThread->GetThreadId()) {
157             ASSERT(threadId != 0);
158         } else {
159             ASSERT(threadId == 0);
160         }
161     }
162 #endif
163     auto cb = [&](ObjectSlot slot) {
164         MarkValue(threadId, slot);
165     };
166     EcmaObjectRangeVisitor visitor = [this, threadId, cb](TaggedObject *root, ObjectSlot start, ObjectSlot end,
167                                         VisitObjectArea area) {
168         if (area == VisitObjectArea::IN_OBJECT) {
169             if (VisitBodyInObj(root, start, end, cb)) {
170                 return;
171             }
172         }
173         for (ObjectSlot slot = start; slot < end; slot++) {
174             MarkValue(threadId, slot);
175         }
176     };
177     TaggedObject *obj = nullptr;
178     while (true) {
179         obj = nullptr;
180         if (!sWorkManager_->Pop(threadId, &obj)) {
181             break;
182         }
183         JSHClass *hclass = obj->SynchronizedGetClass();
184         [[maybe_unused]] Region *region = Region::ObjectAddressToRange(obj);
185         ObjectSlot objectSlot(ToUintPtr(obj));
186         MarkObject(threadId, hclass, objectSlot);
187         ObjectXRay::VisitObjectBody<VisitType::OLD_GC_VISIT>(obj, hclass, visitor);
188     }
189 }
190 
MergeBackAndResetRSetWorkListHandler()191 void SharedGCMarkerBase::MergeBackAndResetRSetWorkListHandler()
192 {
193     for (RSetWorkListHandler *handler : rSetHandlers_) {
194         handler->MergeBack();
195         delete handler;
196     }
197     rSetHandlers_.clear();
198 }
199 
ResetWorkManager(SharedGCWorkManager * workManager)200 void SharedGCMarkerBase::ResetWorkManager(SharedGCWorkManager *workManager)
201 {
202     sWorkManager_ = workManager;
203 }
204 
SharedGCMarker(SharedGCWorkManager * workManger)205 SharedGCMarker::SharedGCMarker(SharedGCWorkManager *workManger)
206     : SharedGCMarkerBase(workManger) {}
207 
SharedGCMovableMarker(SharedGCWorkManager * workManger,SharedHeap * sHeap)208 SharedGCMovableMarker::SharedGCMovableMarker(SharedGCWorkManager *workManger, SharedHeap *sHeap)
209     : SharedGCMarkerBase(workManger), sHeap_(sHeap) {}
210 
211 }  // namespace panda::ecmascript