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