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/object_xray-inl.h"
22 #include "ecmascript/mem/mark_stack.h"
23 #include "ecmascript/mem/mem.h"
24 #include "ecmascript/mem/parallel_marker-inl.h"
25 #include "ecmascript/mem/space-inl.h"
26 #include "ecmascript/runtime_call_id.h"
27
28 namespace panda::ecmascript {
FullGC(Heap * heap)29 FullGC::FullGC(Heap *heap) : heap_(heap), workList_(heap->GetWorkList()) {}
30
RunPhases()31 void FullGC::RunPhases()
32 {
33 ECMA_BYTRACE_NAME(BYTRACE_TAG_ARK, "FullGC::RunPhases");
34 MEM_ALLOCATE_AND_GC_TRACE(heap_->GetEcmaVM(), FullGC_RunPhases);
35 ClockScope clockScope;
36
37 bool concurrentMark = heap_->CheckConcurrentMark();
38 if (concurrentMark) {
39 ECMA_GC_LOG() << "FullGC after ConcurrentMarking";
40 heap_->GetConcurrentMarker()->Reset(); // HPPGC use mark result to move TaggedObject.
41 }
42 InitializePhase();
43 MarkingPhase();
44 SweepPhases();
45 FinishPhase();
46 heap_->GetEcmaVM()->GetEcmaGCStats()->StatisticFullGC(clockScope.GetPauseTime(), youngAndOldAliveSize_,
47 youngSpaceCommitSize_, oldSpaceCommitSize_,
48 nonMoveSpaceFreeSize_, nonMoveSpaceCommitSize_);
49 ECMA_GC_LOG() << "FullGC::RunPhases " << clockScope.TotalSpentTime();
50 }
51
InitializePhase()52 void FullGC::InitializePhase()
53 {
54 ECMA_BYTRACE_NAME(BYTRACE_TAG_ARK, "FullGC::InitializePhase");
55 heap_->Prepare();
56 auto callback = [](Region *current) {
57 // ensure mark bitmap
58 auto rememberset = current->GetOldToNewRememberedSet();
59 if (rememberset != nullptr) {
60 rememberset->ClearAllBits();
61 }
62 };
63 heap_->EnumerateNonMovableRegions(callback);
64 heap_->SwapNewSpace();
65 workList_->Initialize(TriggerGCType::FULL_GC, ParallelGCTaskPhase::COMPRESS_HANDLE_GLOBAL_POOL_TASK);
66 heap_->GetCompressGcMarker()->Initialized();
67
68 youngAndOldAliveSize_ = 0;
69 nonMoveSpaceFreeSize_ = 0;
70 oldSpaceCommitSize_ = heap_->GetOldSpace()->GetCommittedSize();
71 youngSpaceCommitSize_ = heap_->GetFromSpace()->GetCommittedSize();
72 nonMoveSpaceCommitSize_ = heap_->GetNonMovableSpace()->GetCommittedSize();
73 }
74
MarkingPhase()75 void FullGC::MarkingPhase()
76 {
77 ECMA_BYTRACE_NAME(BYTRACE_TAG_ARK, "FullGC::MarkingPhase");
78 heap_->GetCompressGcMarker()->MarkRoots(0);
79 heap_->GetCompressGcMarker()->ProcessMarkStack(0);
80 heap_->WaitRunningTaskFinished();
81 }
82
SweepPhases()83 void FullGC::SweepPhases()
84 {
85 ECMA_BYTRACE_NAME(BYTRACE_TAG_ARK, "FullGC::SweepPhases");
86 // process weak reference
87 auto totalThreadCount = Platform::GetCurrentPlatform()->GetTotalThreadNum() + 1; // gc thread and main thread
88 for (uint32_t i = 0; i < totalThreadCount; i++) {
89 ProcessQueue *queue = workList_->GetWeakReferenceQueue(i);
90
91 while (true) {
92 auto obj = queue->PopBack();
93 if (UNLIKELY(obj == nullptr)) {
94 break;
95 }
96 ObjectSlot slot(ToUintPtr(obj));
97 JSTaggedValue value(slot.GetTaggedType());
98 auto header = value.GetTaggedWeakRef();
99
100 Region *objectRegion = Region::ObjectAddressToRange(header);
101 if (!objectRegion->InYoungAndOldGeneration()) {
102 auto markBitmap = objectRegion->GetMarkBitmap();
103 if (!markBitmap->Test(header)) {
104 slot.Update(static_cast<JSTaggedType>(JSTaggedValue::Undefined().GetRawData()));
105 }
106 } else {
107 MarkWord markWord(header);
108 if (markWord.IsForwardingAddress()) {
109 TaggedObject *dst = markWord.ToForwardingAddress();
110 auto weakRef = JSTaggedValue(JSTaggedValue(dst).CreateAndGetWeakRef()).GetRawTaggedObject();
111 slot.Update(weakRef);
112 } else {
113 slot.Update(static_cast<JSTaggedType>(JSTaggedValue::Undefined().GetRawData()));
114 }
115 }
116 }
117 }
118
119 auto stringTable = heap_->GetEcmaVM()->GetEcmaStringTable();
120 WeakRootVisitor gcUpdateWeak = [](TaggedObject *header) {
121 Region *objectRegion = Region::ObjectAddressToRange(header);
122 if (!objectRegion->InYoungAndOldGeneration()) {
123 auto markBitmap = objectRegion->GetMarkBitmap();
124 if (markBitmap->Test(header)) {
125 return header;
126 }
127 return reinterpret_cast<TaggedObject *>(ToUintPtr(nullptr));
128 }
129
130 MarkWord markWord(header);
131 if (markWord.IsForwardingAddress()) {
132 return markWord.ToForwardingAddress();
133 }
134 return reinterpret_cast<TaggedObject *>(ToUintPtr(nullptr));
135 };
136 stringTable->SweepWeakReference(gcUpdateWeak);
137 heap_->GetEcmaVM()->GetJSThread()->IterateWeakEcmaGlobalStorage(gcUpdateWeak);
138 heap_->GetEcmaVM()->ProcessReferences(gcUpdateWeak);
139
140 heap_->UpdateDerivedObjectInStack();
141 heap_->GetSweeper()->SweepPhases(true);
142 }
143
FinishPhase()144 void FullGC::FinishPhase()
145 {
146 ECMA_BYTRACE_NAME(BYTRACE_TAG_ARK, "FullGC::FinishPhase");
147 heap_->GetSweeper()->PostConcurrentSweepTasks(true);
148 heap_->Resume(FULL_GC);
149 workList_->Finish(youngAndOldAliveSize_);
150 }
151 } // namespace panda::ecmascript
152