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