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/stw_young_gc.h"
17 #include "ecmascript/mem/concurrent_marker.h"
18 #include "ecmascript/mem/parallel_marker-inl.h"
19 #include "ecmascript/runtime_call_id.h"
20
21 namespace panda::ecmascript {
STWYoungGC(Heap * heap,bool parallelGC)22 STWYoungGC::STWYoungGC(Heap *heap, bool parallelGC)
23 : heap_(heap), parallelGC_(parallelGC), workManager_(heap->GetWorkManager())
24 {
25 }
26
RunPhases()27 void STWYoungGC::RunPhases()
28 {
29 MEM_ALLOCATE_AND_GC_TRACE(heap_->GetEcmaVM(), STWYoungGC_RunPhases);
30 TRACE_GC(GCStats::Scope::ScopeId::TotalGC, heap_->GetEcmaVM()->GetEcmaGCStats());
31
32 ECMA_BYTRACE_NAME(HITRACE_TAG_ARK, "STWYoungGC::RunPhases");
33 if (heap_->CheckOngoingConcurrentMarking()) {
34 LOG_GC(DEBUG) << "STWYoungGC after ConcurrentMarking";
35 heap_->GetConcurrentMarker()->Reset(); // HPPGC use mark result to move TaggedObject.
36 }
37 Initialize();
38 Mark();
39 Sweep();
40 Finish();
41 }
42
Initialize()43 void STWYoungGC::Initialize()
44 {
45 ECMA_BYTRACE_NAME(HITRACE_TAG_ARK, "STWYoungGC::Initialize");
46 TRACE_GC(GCStats::Scope::ScopeId::Initialize, heap_->GetEcmaVM()->GetEcmaGCStats());
47 heap_->Prepare();
48 commitSize_ = heap_->GetNewSpace()->GetCommittedSize();
49 heap_->SwapNewSpace();
50 workManager_->Initialize(TriggerGCType::YOUNG_GC, ParallelGCTaskPhase::SEMI_HANDLE_GLOBAL_POOL_TASK);
51 heap_->GetSemiGCMarker()->Initialize();
52 promotedSize_ = 0;
53 semiCopiedSize_ = 0;
54 }
55
Mark()56 void STWYoungGC::Mark()
57 {
58 ECMA_BYTRACE_NAME(HITRACE_TAG_ARK, "STWYoungGC::Mark");
59 TRACE_GC(GCStats::Scope::ScopeId::Mark, heap_->GetEcmaVM()->GetEcmaGCStats());
60 auto region = heap_->GetOldSpace()->GetCurrentRegion();
61
62 if (parallelGC_) {
63 heap_->PostParallelGCTask(ParallelGCTaskPhase::SEMI_HANDLE_THREAD_ROOTS_TASK);
64 heap_->PostParallelGCTask(ParallelGCTaskPhase::SEMI_HANDLE_SNAPSHOT_TASK);
65 heap_->GetSemiGCMarker()->ProcessOldToNew(0, region);
66 } else {
67 heap_->GetSemiGCMarker()->ProcessOldToNew(0, region);
68 heap_->GetSemiGCMarker()->ProcessSnapshotRSet(MAIN_THREAD_INDEX);
69 heap_->GetSemiGCMarker()->MarkRoots(MAIN_THREAD_INDEX, VMRootVisitType::UPDATE_ROOT);
70 heap_->GetSemiGCMarker()->ProcessMarkStack(MAIN_THREAD_INDEX);
71 }
72 heap_->WaitRunningTaskFinished();
73
74 auto totalThreadCount = Taskpool::GetCurrentTaskpool()->GetTotalThreadNum() + 1; // gc thread and main thread
75 for (uint32_t i = 0; i < totalThreadCount; i++) {
76 SlotNeedUpdate needUpdate(nullptr, ObjectSlot(0));
77 while (workManager_->GetSlotNeedUpdate(i, &needUpdate)) {
78 UpdatePromotedSlot(needUpdate.first, needUpdate.second);
79 }
80 }
81 }
82
Sweep()83 void STWYoungGC::Sweep()
84 {
85 ECMA_BYTRACE_NAME(HITRACE_TAG_ARK, "STWYoungGC::Sweep");
86 TRACE_GC(GCStats::Scope::ScopeId::Sweep, heap_->GetEcmaVM()->GetEcmaGCStats());
87 auto totalThreadCount = static_cast<uint32_t>(
88 Taskpool::GetCurrentTaskpool()->GetTotalThreadNum() + 1); // gc thread and main thread
89 for (uint32_t i = 0; i < totalThreadCount; i++) {
90 ProcessQueue *queue = workManager_->GetWeakReferenceQueue(i);
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 MarkWord markWord(header);
100 if (markWord.IsForwardingAddress()) {
101 TaggedObject *dst = markWord.ToForwardingAddress();
102 auto weakRef = JSTaggedValue(JSTaggedValue(dst).CreateAndGetWeakRef()).GetRawTaggedObject();
103 slot.Update(weakRef);
104 } else {
105 slot.Clear();
106 }
107 }
108 }
109 WeakRootVisitor gcUpdateWeak = [](TaggedObject *header) -> TaggedObject* {
110 Region *objectRegion = Region::ObjectAddressToRange(reinterpret_cast<TaggedObject *>(header));
111 if (objectRegion->InGeneralOldSpace()) {
112 return header;
113 }
114
115 MarkWord markWord(header);
116 if (markWord.IsForwardingAddress()) {
117 TaggedObject *dst = markWord.ToForwardingAddress();
118 return dst;
119 }
120 return nullptr;
121 };
122 heap_->GetEcmaVM()->GetJSThread()->IterateWeakEcmaGlobalStorage(gcUpdateWeak);
123 heap_->GetEcmaVM()->ProcessReferences(gcUpdateWeak);
124 }
125
Finish()126 void STWYoungGC::Finish()
127 {
128 ECMA_BYTRACE_NAME(HITRACE_TAG_ARK, "STWYoungGC::Finish");
129 TRACE_GC(GCStats::Scope::ScopeId::Finish, heap_->GetEcmaVM()->GetEcmaGCStats());
130 workManager_->Finish(semiCopiedSize_, promotedSize_);
131 heap_->Resume(YOUNG_GC);
132 }
133 } // namespace panda::ecmascript
134