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