• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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/full_gc.h"
17 
18 #include "ecmascript/ecma_vm.h"
19 #include "ecmascript/mem/clock_scope.h"
20 #include "ecmascript/mem/concurrent_marker.h"
21 #include "ecmascript/mem/concurrent_sweeper.h"
22 #include "ecmascript/mem/heap-inl.h"
23 #include "ecmascript/mem/incremental_marker.h"
24 #include "ecmascript/mem/mark_stack.h"
25 #include "ecmascript/mem/mem.h"
26 #include "ecmascript/mem/parallel_marker-inl.h"
27 #include "ecmascript/mem/space-inl.h"
28 #include "ecmascript/mem/visitor.h"
29 #include "ecmascript/mem/gc_stats.h"
30 #include "ecmascript/ecma_string_table.h"
31 #include "ecmascript/runtime_call_id.h"
32 
33 namespace panda::ecmascript {
FullGC(Heap * heap)34 FullGC::FullGC(Heap *heap) : heap_(heap), workManager_(heap->GetWorkManager()) {}
35 
RunPhases()36 void FullGC::RunPhases()
37 {
38     GCStats *gcStats = heap_->GetEcmaVM()->GetEcmaGCStats();
39     ECMA_BYTRACE_NAME(HITRACE_TAG_ARK, "FullGC::RunPhases;Reason" +
40         std::to_string(static_cast<int>(gcStats->GetGCReason())));
41     TRACE_GC(GCStats::Scope::ScopeId::TotalGC, gcStats);
42     MEM_ALLOCATE_AND_GC_TRACE(heap_->GetEcmaVM(), FullGC_RunPhases);
43 
44     if (heap_->CheckOngoingConcurrentMarking()) {
45         LOG_GC(DEBUG) << "FullGC after ConcurrentMarking";
46         heap_->GetConcurrentMarker()->Reset();  // HPPGC use mark result to move TaggedObject.
47     }
48 
49     if (heap_->GetIncrementalMarker()->IsTriggeredIncrementalMark()) {
50         LOG_GC(DEBUG) << "FullGC after IncrementalMarking";
51         heap_->ClearIdleTask();
52         heap_->DisableNotifyIdle();
53         heap_->GetIncrementalMarker()->Reset();
54     }
55     Initialize();
56     Mark();
57     Sweep();
58     Finish();
59     heap_->NotifyHeapAliveSizeAfterGC(heap_->GetHeapObjectSize());
60 }
61 
RunPhasesForAppSpawn()62 void FullGC::RunPhasesForAppSpawn()
63 {
64     auto marker = reinterpret_cast<CompressGCMarker*>(heap_->GetCompressGCMarker());
65     marker->SetAppSpawn(true);
66     RunPhases();
67     marker->SetAppSpawn(false);
68 }
69 
Initialize()70 void FullGC::Initialize()
71 {
72     ECMA_BYTRACE_NAME(HITRACE_TAG_ARK, "FullGC::Initialize");
73     TRACE_GC(GCStats::Scope::ScopeId::Initialize, heap_->GetEcmaVM()->GetEcmaGCStats());
74     heap_->Prepare();
75     auto callback = [](Region *current) {
76         current->ResetAliveObject();
77         current->ClearOldToNewRSet();
78     };
79     heap_->EnumerateNonMovableRegions(callback);
80     heap_->GetAppSpawnSpace()->EnumerateRegions([](Region *current) {
81         current->ClearMarkGCBitset();
82         current->ClearCrossRegionRSet();
83     });
84     youngSpaceCommitSize_ = heap_->GetNewSpace()->GetCommittedSize();
85     heap_->SwapNewSpace();
86     workManager_->Initialize(TriggerGCType::FULL_GC, ParallelGCTaskPhase::COMPRESS_HANDLE_GLOBAL_POOL_TASK);
87     heap_->GetCompressGCMarker()->Initialize();
88 
89     youngAndOldAliveSize_ = 0;
90     nonMoveSpaceFreeSize_ = 0;
91     oldSpaceCommitSize_ = heap_->GetOldSpace()->GetCommittedSize();
92     nonMoveSpaceCommitSize_ = heap_->GetNonMovableSpace()->GetCommittedSize();
93 }
94 
Mark()95 void FullGC::Mark()
96 {
97     ECMA_BYTRACE_NAME(HITRACE_TAG_ARK, "FullGC::Mark");
98     TRACE_GC(GCStats::Scope::ScopeId::Mark, heap_->GetEcmaVM()->GetEcmaGCStats());
99     heap_->GetCompressGCMarker()->MarkRoots(MAIN_THREAD_INDEX);
100     heap_->GetCompressGCMarker()->ProcessMarkStack(MAIN_THREAD_INDEX);
101     heap_->WaitRunningTaskFinished();
102 }
103 
Sweep()104 void FullGC::Sweep()
105 {
106     ECMA_BYTRACE_NAME(HITRACE_TAG_ARK, "FullGC::Sweep");
107     TRACE_GC(GCStats::Scope::ScopeId::Sweep, heap_->GetEcmaVM()->GetEcmaGCStats());
108     // process weak reference
109     uint32_t totalThreadCount = 1; // 1 : mainthread
110     if (heap_->IsParallelGCEnabled()) {
111         totalThreadCount += Taskpool::GetCurrentTaskpool()->GetTotalThreadNum();
112     }
113     for (uint32_t i = 0; i < totalThreadCount; i++) {
114         ProcessQueue *queue = workManager_->GetWeakReferenceQueue(i);
115 
116         while (true) {
117             auto obj = queue->PopBack();
118             if (UNLIKELY(obj == nullptr)) {
119                 break;
120             }
121             ObjectSlot slot(ToUintPtr(obj));
122             JSTaggedValue value(slot.GetTaggedType());
123             auto header = value.GetTaggedWeakRef();
124 
125             Region *objectRegion = Region::ObjectAddressToRange(header);
126             if (!HasEvacuated(objectRegion)) {
127                 if (!objectRegion->Test(header)) {
128                     slot.Clear();
129                 }
130             } else {
131                 MarkWord markWord(header);
132                 if (markWord.IsForwardingAddress()) {
133                     TaggedObject *dst = markWord.ToForwardingAddress();
134                     auto weakRef = JSTaggedValue(JSTaggedValue(dst).CreateAndGetWeakRef()).GetRawTaggedObject();
135                     slot.Update(weakRef);
136                 } else {
137                     slot.Update(static_cast<JSTaggedType>(JSTaggedValue::Undefined().GetRawData()));
138                 }
139             }
140         }
141     }
142 
143     auto stringTable = heap_->GetEcmaVM()->GetEcmaStringTable();
144     WeakRootVisitor gcUpdateWeak = [this](TaggedObject *header) {
145         Region *objectRegion = Region::ObjectAddressToRange(header);
146         if (!objectRegion) {
147             LOG_GC(ERROR) << "FullGC updateWeakReference: region is nullptr, header is " << header;
148             return reinterpret_cast<TaggedObject *>(ToUintPtr(nullptr));
149         }
150         if (!HasEvacuated(objectRegion)) {
151             if (objectRegion->Test(header)) {
152                 return header;
153             }
154             return reinterpret_cast<TaggedObject *>(ToUintPtr(nullptr));
155         }
156 
157         MarkWord markWord(header);
158         if (markWord.IsForwardingAddress()) {
159             return markWord.ToForwardingAddress();
160         }
161         return reinterpret_cast<TaggedObject *>(ToUintPtr(nullptr));
162     };
163     stringTable->SweepWeakReference(gcUpdateWeak);
164     heap_->GetEcmaVM()->GetJSThread()->IterateWeakEcmaGlobalStorage(gcUpdateWeak);
165     heap_->GetEcmaVM()->ProcessReferences(gcUpdateWeak);
166 
167     heap_->GetSweeper()->Sweep(true);
168     heap_->GetSweeper()->PostTask(true);
169 }
170 
Finish()171 void FullGC::Finish()
172 {
173     ECMA_BYTRACE_NAME(HITRACE_TAG_ARK, "FullGC::Finish");
174     TRACE_GC(GCStats::Scope::ScopeId::Finish, heap_->GetEcmaVM()->GetEcmaGCStats());
175     if (!forAppSpawn_) {
176         heap_->SwapOldSpace();
177     }
178     youngAndOldAliveSize_ = workManager_->Finish();
179     if (forAppSpawn_) {
180         heap_->ResumeForAppSpawn();
181     } else {
182         heap_->Resume(FULL_GC);
183     }
184     heap_->GetSweeper()->TryFillSweptRegion();
185 }
186 
HasEvacuated(Region * region)187 bool FullGC::HasEvacuated(Region *region)
188 {
189     auto marker = reinterpret_cast<CompressGCMarker*>(heap_->GetCompressGCMarker());
190     return marker->NeedEvacuate(region);
191 }
192 
SetForAppSpawn(bool flag)193 void FullGC::SetForAppSpawn(bool flag)
194 {
195     forAppSpawn_ = flag;
196 }
197 }  // namespace panda::ecmascript
198