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
24using namespace panda::ecmascript;
25using namespace panda::ecmascript::base;
26using TRIGGER_IDLE_GC_TYPE = panda::JSNApi::TRIGGER_IDLE_GC_TYPE;
27using TriggerGCData = std::pair<void*, uint8_t>;
28using TriggerGCTaskCallback = std::function<void(TriggerGCData& data)>;
29
30namespace panda::test {
31class IdleGCTriggerTest :  public BaseTestWithScope<false> {
32public:
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
48HWTEST_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
56HWTEST_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
68HWTEST_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
76HWTEST_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
88HWTEST_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
98HWTEST_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
108HWTEST_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
118HWTEST_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
127HWTEST_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
138HWTEST_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
151HWTEST_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
161HWTEST_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
173HWTEST_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
183HWTEST_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
195HWTEST_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
211HWTEST_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
223HWTEST_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
239HWTEST_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
248HWTEST_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
261HWTEST_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
270HWTEST_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
278HWTEST_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
289HWTEST_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
300HWTEST_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
308HWTEST_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
317HWTEST_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
328HWTEST_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
339HWTEST_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