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/ecma_vm.h"
17 #include "ecmascript/mem/idle_gc_trigger.h"
18 #include "ecmascript/mem/heap.h"
19 #include "ecmascript/mem/heap-inl.h"
20 #include "ecmascript/tests/test_helper.h"
21 #include "ecmascript/mem/concurrent_marker.h"
22 #include "ecmascript/mem/partial_gc.h"
23 
24 using namespace panda::ecmascript;
25 using namespace panda::ecmascript::base;
26 using TRIGGER_IDLE_GC_TYPE = panda::JSNApi::TRIGGER_IDLE_GC_TYPE;
27 using TriggerGCData = std::pair<void*, uint8_t>;
28 using TriggerGCTaskCallback = std::function<void(TriggerGCData& data)>;
29 
30 namespace panda::test {
31 class IdleGCTriggerTest :  public BaseTestWithScope<false> {
32 public:
33     void SetUp() override
34     {
35         JSRuntimeOptions options;
36         options.SetEnableEdenGC(true);
37         instance = JSNApi::CreateEcmaVM(options);
38         ASSERT_TRUE(instance != nullptr) << "Cannot create EcmaVM";
39         thread = instance->GetJSThread();
40         thread->ManagedCodeBegin();
41         scope = new EcmaHandleScope(thread);
42         auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
43         heap->GetConcurrentMarker()->EnableConcurrentMarking(EnableConcurrentMarkType::ENABLE);
44         heap->GetSweeper()->EnableConcurrentSweep(EnableConcurrentSweepType::ENABLE);
45     }
46 };
47 
HWTEST_F_L0(IdleGCTriggerTest, NotifyLooperIdleStartTest001)48 HWTEST_F_L0(IdleGCTriggerTest, NotifyLooperIdleStartTest001)
49 {
50     auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
51     SharedHeap *sheap = SharedHeap::GetInstance();
52     IdleGCTrigger *trigger = new IdleGCTrigger(heap, sheap, thread);
53     trigger->NotifyLooperIdleStart(1, 1);
54 }
55 
HWTEST_F_L0(IdleGCTriggerTest, NotifyLooperIdleStartTest002)56 HWTEST_F_L0(IdleGCTriggerTest, NotifyLooperIdleStartTest002)
57 {
58     auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
59     SharedHeap *sheap = SharedHeap::GetInstance();
60     heap->GetConcurrentMarker()->Mark();
61     heap->GetJSThread()->SetMarkStatus(MarkStatus::MARK_FINISHED);
62     IdleGCTrigger *trigger = new IdleGCTrigger(heap, sheap, thread);
63     trigger->ClearPostGCTask(TRIGGER_IDLE_GC_TYPE::LOCAL_CONCURRENT_MARK);
64     trigger->SetPostGCTask(TRIGGER_IDLE_GC_TYPE::LOCAL_CONCURRENT_MARK);
65     trigger->NotifyLooperIdleStart(1, 1);
66 }
67 
HWTEST_F_L0(IdleGCTriggerTest, NotifyLooperIdleEndTest001)68 HWTEST_F_L0(IdleGCTriggerTest, NotifyLooperIdleEndTest001)
69 {
70     auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
71     SharedHeap *sheap = SharedHeap::GetInstance();
72     IdleGCTrigger *trigger = new IdleGCTrigger(heap, sheap, thread);
73     trigger->NotifyLooperIdleEnd(1);
74 }
75 
HWTEST_F_L0(IdleGCTriggerTest, TryTriggerHandleMarkFinishedTest001)76 HWTEST_F_L0(IdleGCTriggerTest, TryTriggerHandleMarkFinishedTest001)
77 {
78     auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
79     SharedHeap *sheap = SharedHeap::GetInstance();
80 
81     heap->GetConcurrentMarker()->Mark();
82     heap->GetConcurrentMarker()->ProcessConcurrentMarkTask(0);
83 
84     IdleGCTrigger *trigger = new IdleGCTrigger(heap, sheap, thread);
85     trigger->TryTriggerHandleMarkFinished();
86 }
87 
HWTEST_F_L0(IdleGCTriggerTest, TryTriggerLocalConcurrentMarkTest001)88 HWTEST_F_L0(IdleGCTriggerTest, TryTriggerLocalConcurrentMarkTest001)
89 {
90     auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
91     SharedHeap *sheap = SharedHeap::GetInstance();
92     heap->SetIdleTask(IdleTaskType::NO_TASK);
93 
94     IdleGCTrigger *trigger = new IdleGCTrigger(heap, sheap, thread);
95     trigger->TryTriggerLocalConcurrentMark();
96 }
97 
HWTEST_F_L0(IdleGCTriggerTest, TryTriggerLocalConcurrentMarkTest002)98 HWTEST_F_L0(IdleGCTriggerTest, TryTriggerLocalConcurrentMarkTest002)
99 {
100     auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
101     SharedHeap *sheap = SharedHeap::GetInstance();
102     heap->SetIdleTask(IdleTaskType::NO_TASK);
103     heap->GetConcurrentMarker()->ConfigConcurrentMark(false);
104     IdleGCTrigger *trigger = new IdleGCTrigger(heap, sheap, thread);
105     trigger->TryTriggerLocalConcurrentMark();
106 }
107 
HWTEST_F_L0(IdleGCTriggerTest, TryTriggerLocalConcurrentMarkTest003)108 HWTEST_F_L0(IdleGCTriggerTest, TryTriggerLocalConcurrentMarkTest003)
109 {
110     auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
111     SharedHeap *sheap = SharedHeap::GetInstance();
112     heap->SetIdleTask(IdleTaskType::NO_TASK);
113     thread->SetMarkStatus(MarkStatus::MARK_FINISHED);
114     IdleGCTrigger *trigger = new IdleGCTrigger(heap, sheap, thread);
115     trigger->TryTriggerLocalConcurrentMark();
116 }
117 
HWTEST_F_L0(IdleGCTriggerTest, TryTriggerIdleSharedOldGCTest001)118 HWTEST_F_L0(IdleGCTriggerTest, TryTriggerIdleSharedOldGCTest001)
119 {
120     auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
121     SharedHeap *sheap = SharedHeap::GetInstance();
122 
123     IdleGCTrigger *trigger = new IdleGCTrigger(heap, sheap, thread);
124     ASSERT_EQ(trigger->TryTriggerIdleSharedOldGC(), false);
125 }
126 
HWTEST_F_L0(IdleGCTriggerTest, TryTriggerIdleSharedOldGCTest002)127 HWTEST_F_L0(IdleGCTriggerTest, TryTriggerIdleSharedOldGCTest002)
128 {
129     auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
130     SharedHeap *sheap = SharedHeap::GetInstance();
131     sheap->GetOldSpace()->SetInitialCapacity(10000);
132     sheap->GetOldSpace()->IncreaseLiveObjectSize(5242889);
133     sheap->NotifyHeapAliveSizeAfterGC(1);
134     IdleGCTrigger *trigger = new IdleGCTrigger(heap, sheap, thread);
135     ASSERT_EQ(trigger->TryTriggerIdleSharedOldGC(), true);
136 }
137 
HWTEST_F_L0(IdleGCTriggerTest, TryTriggerIdleSharedOldGCTest003)138 HWTEST_F_L0(IdleGCTriggerTest, TryTriggerIdleSharedOldGCTest003)
139 {
140     auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
141     SharedHeap *sheap = SharedHeap::GetInstance();
142     sheap->GetOldSpace()->SetInitialCapacity(10000);
143     sheap->GetOldSpace()->IncreaseLiveObjectSize(5242889);
144     sheap->NotifyHeapAliveSizeAfterGC(1);
145     IdleGCTrigger *trigger = new IdleGCTrigger(heap, sheap, thread);
146     trigger->ClearPostGCTask(TRIGGER_IDLE_GC_TYPE::SHARED_CONCURRENT_MARK);
147     trigger->SetPostGCTask(TRIGGER_IDLE_GC_TYPE::SHARED_CONCURRENT_MARK);
148     ASSERT_EQ(trigger->TryTriggerIdleSharedOldGC(), true);
149 }
150 
HWTEST_F_L0(IdleGCTriggerTest, TryTriggerIdleSharedOldGCTest004)151 HWTEST_F_L0(IdleGCTriggerTest, TryTriggerIdleSharedOldGCTest004)
152 {
153     auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
154     SharedHeap *sheap = SharedHeap::GetInstance();
155     heap->SetOnSerializeEvent(true);
156 
157     IdleGCTrigger *trigger = new IdleGCTrigger(heap, sheap, thread);
158     ASSERT_EQ(trigger->TryTriggerIdleSharedOldGC(), false);
159 }
160 
HWTEST_F_L0(IdleGCTriggerTest, TryTriggerIdleLocalOldGCTest001)161 HWTEST_F_L0(IdleGCTriggerTest, TryTriggerIdleLocalOldGCTest001)
162 {
163     auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
164     SharedHeap *sheap = SharedHeap::GetInstance();
165     heap->SetIdleTask(IdleTaskType::NO_TASK);
166     heap->GetOldSpace()->SetInitialCapacity(10000);
167     heap->GetOldSpace()->IncreaseLiveObjectSize(5242889);
168     heap->NotifyHeapAliveSizeAfterGC(1);
169     IdleGCTrigger *trigger = new IdleGCTrigger(heap, sheap, thread);
170     ASSERT_EQ(trigger->TryTriggerIdleLocalOldGC(), true);
171 }
172 
HWTEST_F_L0(IdleGCTriggerTest, TryTriggerIdleLocalOldGCTest002)173 HWTEST_F_L0(IdleGCTriggerTest, TryTriggerIdleLocalOldGCTest002)
174 {
175     auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
176     SharedHeap *sheap = SharedHeap::GetInstance();
177     IdleGCTrigger *trigger = new IdleGCTrigger(heap, sheap, thread);
178     trigger->ClearPostGCTask(TRIGGER_IDLE_GC_TYPE::LOCAL_CONCURRENT_MARK);
179     trigger->SetPostGCTask(TRIGGER_IDLE_GC_TYPE::LOCAL_CONCURRENT_MARK);
180     ASSERT_EQ(trigger->TryTriggerIdleLocalOldGC(), true);
181 }
182 
HWTEST_F_L0(IdleGCTriggerTest, TryTriggerIdleLocalOldGCTest003)183 HWTEST_F_L0(IdleGCTriggerTest, TryTriggerIdleLocalOldGCTest003)
184 {
185     auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
186     SharedHeap *sheap = SharedHeap::GetInstance();
187     heap->GetConcurrentMarker()->Mark();
188     heap->GetJSThread()->SetMarkStatus(MarkStatus::MARK_FINISHED);
189     IdleGCTrigger *trigger = new IdleGCTrigger(heap, sheap, thread);
190     trigger->ClearPostGCTask(TRIGGER_IDLE_GC_TYPE::LOCAL_REMARK);
191     trigger->SetPostGCTask(TRIGGER_IDLE_GC_TYPE::LOCAL_REMARK);
192     ASSERT_EQ(trigger->TryTriggerIdleLocalOldGC(), true);
193 }
194 
HWTEST_F_L0(IdleGCTriggerTest, TryTriggerIdleLocalOldGCTest004)195 HWTEST_F_L0(IdleGCTriggerTest, TryTriggerIdleLocalOldGCTest004)
196 {
197     auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
198     SharedHeap *sheap = SharedHeap::GetInstance();
199     heap->SetIdleTask(IdleTaskType::NO_TASK);
200     heap->GetOldSpace()->SetInitialCapacity(10000);
201     heap->GetOldSpace()->IncreaseLiveObjectSize(5242889);
202     heap->NotifyHeapAliveSizeAfterGC(1);
203     IdleGCTrigger *trigger = new IdleGCTrigger(heap, sheap, thread);
204     TriggerGCTaskCallback callback = [](TriggerGCData& data) {
205         data.second = 1;
206     };
207     trigger->SetTriggerGCTaskCallback(callback);
208     ASSERT_EQ(trigger->TryTriggerIdleLocalOldGC(), true);
209 }
210 
HWTEST_F_L0(IdleGCTriggerTest, TryTriggerIdleLocalOldGCTest005)211 HWTEST_F_L0(IdleGCTriggerTest, TryTriggerIdleLocalOldGCTest005)
212 {
213     auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
214     SharedHeap *sheap = SharedHeap::GetInstance();
215     heap->GetConcurrentMarker()->Mark();
216     heap->GetJSThread()->SetMarkStatus(MarkStatus::MARK_FINISHED);
217     IdleGCTrigger *trigger = new IdleGCTrigger(heap, sheap, thread);
218     trigger->ClearPostGCTask(TRIGGER_IDLE_GC_TYPE::LOCAL_CONCURRENT_MARK);
219     trigger->SetPostGCTask(TRIGGER_IDLE_GC_TYPE::LOCAL_CONCURRENT_MARK);
220     ASSERT_EQ(trigger->TryTriggerIdleLocalOldGC(), true);
221 }
222 
HWTEST_F_L0(IdleGCTriggerTest, TryTriggerIdleLocalOldGCTest006)223 HWTEST_F_L0(IdleGCTriggerTest, TryTriggerIdleLocalOldGCTest006)
224 {
225     auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
226     SharedHeap *sheap = SharedHeap::GetInstance();
227     heap->SetIdleTask(IdleTaskType::FINISH_MARKING);
228     heap->GetOldSpace()->SetInitialCapacity(10000);
229     heap->GetOldSpace()->IncreaseLiveObjectSize(5242889);
230     heap->NotifyHeapAliveSizeAfterGC(1);
231     IdleGCTrigger *trigger = new IdleGCTrigger(heap, sheap, thread);
232     TriggerGCTaskCallback callback = [](TriggerGCData& data) {
233         data.second = 1;
234     };
235     trigger->SetTriggerGCTaskCallback(callback);
236     ASSERT_EQ(trigger->TryTriggerIdleLocalOldGC(), true);
237 }
238 
HWTEST_F_L0(IdleGCTriggerTest, ReachIdleLocalOldGCThresholdsTest001)239 HWTEST_F_L0(IdleGCTriggerTest, ReachIdleLocalOldGCThresholdsTest001)
240 {
241     auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
242     SharedHeap *sheap = SharedHeap::GetInstance();
243     heap->GetNativeAreaAllocator()->IncreaseNativeMemoryUsage(83886100);
244     IdleGCTrigger *trigger = new IdleGCTrigger(heap, sheap, thread);
245     ASSERT_EQ(trigger->ReachIdleLocalOldGCThresholds(), true);
246 }
247 
HWTEST_F_L0(IdleGCTriggerTest, ReachIdleLocalOldGCThresholdsTest002)248 HWTEST_F_L0(IdleGCTriggerTest, ReachIdleLocalOldGCThresholdsTest002)
249 {
250     auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
251     SharedHeap *sheap = SharedHeap::GetInstance();
252     heap->GetNativeAreaAllocator()->IncreaseNativeMemoryUsage(1);
253     heap->GetOldSpace()->IncreaseCommitted(83886100);
254     heap->GetOldSpace()->SetMaximumCapacity(100000);
255     heap->GetOldSpace()->SetOvershootSize(100000);
256     heap->GetOldSpace()->SetOvershootSize(100000);
257     IdleGCTrigger *trigger = new IdleGCTrigger(heap, sheap, thread);
258     ASSERT_EQ(trigger->ReachIdleLocalOldGCThresholds(), true);
259 }
260 
HWTEST_F_L0(IdleGCTriggerTest, TryPostHandleMarkFinishedTest001)261 HWTEST_F_L0(IdleGCTriggerTest, TryPostHandleMarkFinishedTest001)
262 {
263     auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
264     SharedHeap *sheap = SharedHeap::GetInstance();
265     IdleGCTrigger *trigger = new IdleGCTrigger(heap, sheap, thread);
266     trigger->NotifyLooperIdleStart(1, 1);
267     trigger->TryPostHandleMarkFinished();
268 }
269 
HWTEST_F_L0(IdleGCTriggerTest, TryPostHandleMarkFinishedTest002)270 HWTEST_F_L0(IdleGCTriggerTest, TryPostHandleMarkFinishedTest002)
271 {
272     auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
273     SharedHeap *sheap = SharedHeap::GetInstance();
274     IdleGCTrigger *trigger = new IdleGCTrigger(heap, sheap, thread);
275     trigger->TryPostHandleMarkFinished();
276 }
277 
HWTEST_F_L0(IdleGCTriggerTest, TryTriggerIdleGCTest002)278 HWTEST_F_L0(IdleGCTriggerTest, TryTriggerIdleGCTest002)
279 {
280     auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
281     SharedHeap *sheap = SharedHeap::GetInstance();
282     sheap->NotifyHeapAliveSizeAfterGC(1);
283     sheap->GetOldSpace()->SetInitialCapacity(10000);
284     sheap->GetOldSpace()->IncreaseLiveObjectSize(5242889);
285     IdleGCTrigger *trigger = new IdleGCTrigger(heap, sheap, thread);
286     trigger->TryTriggerIdleGC(TRIGGER_IDLE_GC_TYPE::SHARED_CONCURRENT_MARK);
287 }
288 
HWTEST_F_L0(IdleGCTriggerTest, TryTriggerIdleGCTest003)289 HWTEST_F_L0(IdleGCTriggerTest, TryTriggerIdleGCTest003)
290 {
291     auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
292     SharedHeap *sheap = SharedHeap::GetInstance();
293     heap->NotifyHeapAliveSizeAfterGC(1);
294     heap->GetOldSpace()->SetInitialCapacity(10000);
295     heap->GetOldSpace()->IncreaseLiveObjectSize(5242889);
296     IdleGCTrigger *trigger = new IdleGCTrigger(heap, sheap, thread);
297     trigger->TryTriggerIdleGC(TRIGGER_IDLE_GC_TYPE::LOCAL_CONCURRENT_MARK);
298 }
299 
HWTEST_F_L0(IdleGCTriggerTest, TryTriggerIdleGCTest004)300 HWTEST_F_L0(IdleGCTriggerTest, TryTriggerIdleGCTest004)
301 {
302     auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
303     SharedHeap *sheap = SharedHeap::GetInstance();
304     IdleGCTrigger *trigger = new IdleGCTrigger(heap, sheap, thread);
305     trigger->TryTriggerIdleGC(TRIGGER_IDLE_GC_TYPE::LOCAL_REMARK);
306 }
307 
HWTEST_F_L0(IdleGCTriggerTest, TryTriggerIdleGCTest011)308 HWTEST_F_L0(IdleGCTriggerTest, TryTriggerIdleGCTest011)
309 {
310     auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
311     SharedHeap *sheap = SharedHeap::GetInstance();
312     heap->SetOnSerializeEvent(true);
313     IdleGCTrigger *trigger = new IdleGCTrigger(heap, sheap, thread);
314     trigger->TryTriggerIdleGC(TRIGGER_IDLE_GC_TYPE::LOCAL_REMARK);
315 }
316 
HWTEST_F_L0(IdleGCTriggerTest, TryTriggerIdleGCTest012)317 HWTEST_F_L0(IdleGCTriggerTest, TryTriggerIdleGCTest012)
318 {
319     auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
320     SharedHeap *sheap = SharedHeap::GetInstance();
321     sheap->NotifyHeapAliveSizeAfterGC(0);
322     sheap->GetOldSpace()->SetInitialCapacity(10000);
323     sheap->GetOldSpace()->IncreaseLiveObjectSize(5242889);
324     IdleGCTrigger *trigger = new IdleGCTrigger(heap, sheap, thread);
325     trigger->TryTriggerIdleGC(TRIGGER_IDLE_GC_TYPE::FULL_GC);
326 }
327 
HWTEST_F_L0(IdleGCTriggerTest, TryTriggerIdleGCTest013)328 HWTEST_F_L0(IdleGCTriggerTest, TryTriggerIdleGCTest013)
329 {
330     auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
331     SharedHeap *sheap = SharedHeap::GetInstance();
332     sheap->NotifyHeapAliveSizeAfterGC(0);
333     sheap->GetOldSpace()->SetInitialCapacity(10000);
334     sheap->GetOldSpace()->IncreaseLiveObjectSize(5242889);
335     IdleGCTrigger *trigger = new IdleGCTrigger(heap, sheap, thread);
336     trigger->TryTriggerIdleGC(TRIGGER_IDLE_GC_TYPE::SHARED_FULL_GC);
337 }
338 
HWTEST_F_L0(IdleGCTriggerTest, ShouldCheckIdleOldGCTest001)339 HWTEST_F_L0(IdleGCTriggerTest, ShouldCheckIdleOldGCTest001)
340 {
341     auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
342     SharedHeap *sheap = SharedHeap::GetInstance();
343     heap->NotifyHeapAliveSizeAfterGC(0);
344     heap->GetOldSpace()->SetInitialCapacity(10000);
345     heap->GetOldSpace()->IncreaseLiveObjectSize(5242889);
346     IdleGCTrigger *trigger = new IdleGCTrigger(heap, sheap, thread);
347     trigger->TryTriggerIdleGC(TRIGGER_IDLE_GC_TYPE::LOCAL_CONCURRENT_MARK);
348 }
349 
350 }  // namespace panda::test