1 /*
2 * Copyright (c) 2025 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 <thread>
17
18 #include "ecmascript/mem/concurrent_marker.h"
19 #include "ecmascript/tests/unified_gc_test_helper.h"
20
21 using namespace panda::ecmascript;
22
23 namespace panda::test {
24 class UnifiedGCMultiVMTest : public BaseTestWithScope<false> {};
25
26 class UnifiedGCMultiVMVerificationTest : public UnifiedGCMultiVMTest {
27 public:
SetUp()28 void SetUp() override
29 {
30 JSRuntimeOptions options;
31 options.SetArkProperties(options.GetArkProperties() | ArkProperties::ENABLE_HEAP_VERIFY);
32 instance = JSNApi::CreateEcmaVM(options);
33 ASSERT_TRUE(instance != nullptr) << "Cannot create EcmaVM";
34 thread = instance->GetJSThread();
35 thread->ManagedCodeBegin();
36 scope = new EcmaHandleScope(thread);
37 }
38 };
39
40 #ifdef PANDA_JS_ETS_HYBRID_MODE
IsObjectMarked(TaggedObject * object)41 static inline bool IsObjectMarked(TaggedObject *object)
42 {
43 Region *objectRegion = Region::ObjectAddressToRange(object);
44 return objectRegion->Test(object);
45 }
46
47 class UnifiedGCMultiVMTestSuite {
48 public:
UnifiedGCMultiVMTestSuite(void * stsIface,SuspendBarrier * barrier)49 UnifiedGCMultiVMTestSuite(void *stsIface, SuspendBarrier *barrier)
50 : stsVMInterface(stsIface), suspendBarrier(barrier) {}
51 ~UnifiedGCMultiVMTestSuite() = default;
52
DoHandShakeTest()53 void DoHandShakeTest()
54 {
55 Init();
56
57 void *ecmaVMInterface = nullptr;
58 CrossVMOperator::DoHandshake(vm, stsVMInterface, &ecmaVMInterface);
59
60 EXPECT_TRUE(vm->GetCrossVMOperator()->GetSTSVMInterface() == stsVMInterface);
61 EXPECT_TRUE(vm->GetCrossVMOperator()->GetEcmaVMInterface() ==
62 static_cast<arkplatform::EcmaVMInterface *>(ecmaVMInterface));
63
64 Destroy();
65 }
66
NoHandshakeTest()67 void NoHandshakeTest()
68 {
69 Init();
70
71 while (!thread->HasSuspendRequest()) {}
72 thread->WaitSuspension();
73
74 Destroy();
75 }
76
CheckUnifiedGCResultTest()77 void CheckUnifiedGCResultTest()
78 {
79 Init();
80
81 void *ecmaVMInterface = nullptr;
82 CrossVMOperator::DoHandshake(vm, stsVMInterface, &ecmaVMInterface);
83
84 CrossReferenceObjectBuilder CrossReferenceObject(vm, thread);
85 while (!thread->HasSuspendRequest()) {}
86 thread->WaitSuspension();
87 CrossReferenceObject.CheckResultAfterUnifiedGC();
88
89 Destroy();
90 }
91
TriggerConcurrentMarkTest()92 void TriggerConcurrentMarkTest()
93 {
94 Init();
95
96 void *ecmaVMInterface = nullptr;
97 CrossVMOperator::DoHandshake(vm, stsVMInterface, &ecmaVMInterface);
98
99 CrossReferenceObjectBuilder CrossReferenceObject(vm, thread);
100 auto heap = vm->GetHeap();
101 heap->GetConcurrentMarker()->Mark();
102 while (!thread->HasSuspendRequest()) {}
103 thread->WaitSuspension();
104 CrossReferenceObject.CheckResultAfterUnifiedGC();
105
106 Destroy();
107 }
108
TriggerYoungGCTest()109 void TriggerYoungGCTest()
110 {
111 Init();
112
113 void *ecmaVMInterface = nullptr;
114 CrossVMOperator::DoHandshake(vm, stsVMInterface, &ecmaVMInterface);
115
116 CrossReferenceObjectBuilder CrossReferenceObject(vm, thread);
117 while (!thread->HasSuspendRequest()) {}
118 thread->WaitSuspension();
119 vm->CollectGarbage(TriggerGCType::YOUNG_GC);
120 CrossReferenceObject.CheckResultAfterUnifiedGC();
121
122 Destroy();
123 }
124
HeapVerifyTest()125 void HeapVerifyTest()
126 {
127 JSRuntimeOptions options;
128 options.SetArkProperties(options.GetArkProperties() | ArkProperties::ENABLE_HEAP_VERIFY);
129 vm = JSNApi::CreateEcmaVM(options);
130 ASSERT_TRUE(vm != nullptr) << "Cannot create EcmaVM";
131 thread = vm->GetJSThread();
132 thread->ManagedCodeBegin();
133 scope = new EcmaHandleScope(thread);
134 {
135 ThreadSuspensionScope suspensionScope(thread);
136 suspendBarrier->PassStrongly();
137 suspendBarrier->Wait();
138 }
139
140 void *ecmaVMInterface = nullptr;
141 CrossVMOperator::DoHandshake(vm, stsVMInterface, &ecmaVMInterface);
142
143 CrossReferenceObjectBuilder CrossReferenceObject(vm, thread);
144 auto heap = vm->GetHeap();
145 heap->GetConcurrentMarker()->Mark();
146 while (!thread->HasSuspendRequest()) {}
147 thread->WaitSuspension();
148 CrossReferenceObject.CheckResultAfterUnifiedGC();
149
150 Destroy();
151 }
152
MarkFromObjectTest()153 void MarkFromObjectTest()
154 {
155 Init();
156
157 JSHandle<JSTaggedValue> arrayInXRefRoot = JSArray::ArrayCreate(thread, JSTaggedNumber(INT_VALUE_1));
158 JSHandle<JSTaggedValue> arrayRefByXRefRoot = JSArray::ArrayCreate(thread, JSTaggedNumber(INT_VALUE_2));
159 thread->NewXRefGlobalHandle(arrayInXRefRoot.GetTaggedType());
160 JSArray::FastSetPropertyByValue(thread, arrayInXRefRoot, INT_VALUE_0, arrayRefByXRefRoot);
161
162 auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
163 vm->GetCrossVMOperator()->MarkFromObject(arrayInXRefRoot->GetRawData());
164 heap->WaitRunningTaskFinished();
165 EXPECT_TRUE(IsObjectMarked(arrayInXRefRoot->GetHeapObject()));
166 EXPECT_TRUE(IsObjectMarked(arrayRefByXRefRoot->GetHeapObject()));
167
168 // Clear mark bit
169 heap->Resume(TriggerGCType::UNIFIED_GC);
170 heap->WaitClearTaskFinished();
171 EXPECT_TRUE(!IsObjectMarked(arrayInXRefRoot->GetHeapObject()));
172 EXPECT_TRUE(!IsObjectMarked(arrayRefByXRefRoot->GetHeapObject()));
173
174 Destroy();
175 }
176
TriggerUnifiedGCFailTest()177 void TriggerUnifiedGCFailTest()
178 {
179 Init();
180
181 void *ecmaVMInterface = nullptr;
182 CrossVMOperator::DoHandshake(vm, stsVMInterface, &ecmaVMInterface);
183
184 CrossReferenceObjectBuilder CrossReferenceObject(vm, thread);
185 while (!thread->HasSuspendRequest()) {}
186 thread->WaitSuspension();
187 CrossReferenceObject.CheckResultAfterUnifiedGCTriggerFail();
188
189 Destroy();
190 }
191
192 private:
Init()193 void Init()
194 {
195 JSRuntimeOptions options;
196 vm = JSNApi::CreateEcmaVM(options);
197 vm->SetEnableForceGC(false);
198 ASSERT_TRUE(vm != nullptr) << "Cannot create EcmaVM";
199 thread = vm->GetJSThread();
200 thread->ManagedCodeBegin();
201 scope = new EcmaHandleScope(thread);
202 // RuntimeLockHolder will trigger SuspendAll GC(sharedGC) during the initialization of builtins in
203 // CreateEcmaVM. So switch the current jsThread to IS_SUSPENDED state to pass the SuspendAll barrier until
204 // all SuspendAll GC finished. The suspendBarrier is used to make sure all SuspendAll GC finished and
205 // sync all test vm for following unifiedGC test.
206 {
207 ThreadSuspensionScope suspensionScope(thread);
208 suspendBarrier->PassStrongly();
209 suspendBarrier->Wait();
210 }
211 }
212
Destroy()213 void Destroy()
214 {
215 TestHelper::DestroyEcmaVMWithScope(vm, scope);
216 }
217
218 EcmaVM *vm = nullptr;
219 EcmaHandleScope *scope = nullptr;
220 JSThread *thread = nullptr;
221 void *stsVMInterface = nullptr;
222 SuspendBarrier *suspendBarrier = nullptr;
223 };
224
HWTEST_F_L0(UnifiedGCMultiVMTest,MultiVMDoHandshakeTest)225 HWTEST_F_L0(UnifiedGCMultiVMTest, MultiVMDoHandshakeTest)
226 {
227 SuspendBarrier barrier(INT_VALUE_4);
228 EcmaVM *vm = thread->GetEcmaVM();
229 auto stsVMInterface = std::make_unique<STSVMInterfaceTest>();
230
231 UnifiedGCMultiVMTestSuite testVM1(stsVMInterface.get(), &barrier);
232 UnifiedGCMultiVMTestSuite testVM2(stsVMInterface.get(), &barrier);
233 UnifiedGCMultiVMTestSuite testVM3(stsVMInterface.get(), &barrier);
234 std::thread t1(&UnifiedGCMultiVMTestSuite::DoHandShakeTest, testVM1);
235 std::thread t2(&UnifiedGCMultiVMTestSuite::DoHandShakeTest, testVM2);
236 std::thread t3(&UnifiedGCMultiVMTestSuite::DoHandShakeTest, testVM3);
237 {
238 ThreadSuspensionScope suspensionScope(thread);
239 barrier.PassStrongly();
240 barrier.Wait();
241 }
242
243 void *ecmaVMInterface = nullptr;
244 CrossVMOperator::DoHandshake(vm, stsVMInterface.get(), &ecmaVMInterface);
245 EXPECT_TRUE(vm->GetCrossVMOperator()->GetSTSVMInterface() == stsVMInterface.get());
246 EXPECT_TRUE(vm->GetCrossVMOperator()->GetEcmaVMInterface() ==
247 static_cast<arkplatform::EcmaVMInterface *>(ecmaVMInterface));
248 t1.join();
249 t2.join();
250 t3.join();
251 }
252
HWTEST_F_L0(UnifiedGCMultiVMTest,MultiVMUnifiedGCMarkTest1)253 HWTEST_F_L0(UnifiedGCMultiVMTest, MultiVMUnifiedGCMarkTest1)
254 {
255 SuspendBarrier barrier(INT_VALUE_4);
256 EcmaVM *vm = thread->GetEcmaVM();
257 auto stsVMInterface = std::make_unique<STSVMInterfaceTest>();
258
259 UnifiedGCMultiVMTestSuite testVM1(stsVMInterface.get(), &barrier);
260 UnifiedGCMultiVMTestSuite testVM2(stsVMInterface.get(), &barrier);
261 UnifiedGCMultiVMTestSuite testVM3(stsVMInterface.get(), &barrier);
262 std::thread t1(&UnifiedGCMultiVMTestSuite::CheckUnifiedGCResultTest, testVM1);
263 std::thread t2(&UnifiedGCMultiVMTestSuite::CheckUnifiedGCResultTest, testVM2);
264 std::thread t3(&UnifiedGCMultiVMTestSuite::CheckUnifiedGCResultTest, testVM3);
265 {
266 ThreadSuspensionScope suspensionScope(thread);
267 barrier.PassStrongly();
268 barrier.Wait();
269 }
270
271 void *ecmaVMInterface = nullptr;
272 CrossVMOperator::DoHandshake(vm, stsVMInterface.get(), &ecmaVMInterface);
273 CrossReferenceObjectBuilder CrossReferenceObject(vm, thread);
274 SharedHeap::GetInstance()->TriggerUnifiedGCMark<TriggerGCType::UNIFIED_GC, GCReason::CROSSREF_CAUSE>(thread);
275 while (!thread->HasSuspendRequest()) {}
276 thread->WaitSuspension();
277 CrossReferenceObject.CheckResultAfterUnifiedGC();
278 t1.join();
279 t2.join();
280 t3.join();
281 }
282
HWTEST_F_L0(UnifiedGCMultiVMTest,MultiVMUnifiedGCMarkTest2)283 HWTEST_F_L0(UnifiedGCMultiVMTest, MultiVMUnifiedGCMarkTest2)
284 {
285 SuspendBarrier barrier(INT_VALUE_4);
286 EcmaVM *vm = thread->GetEcmaVM();
287 auto stsVMInterface = std::make_unique<STSVMInterfaceTest>();
288
289 UnifiedGCMultiVMTestSuite testVM1(stsVMInterface.get(), &barrier);
290 UnifiedGCMultiVMTestSuite testVM2(stsVMInterface.get(), &barrier);
291 UnifiedGCMultiVMTestSuite testVM3(stsVMInterface.get(), &barrier);
292 std::thread t1(&UnifiedGCMultiVMTestSuite::NoHandshakeTest, testVM1);
293 std::thread t2(&UnifiedGCMultiVMTestSuite::NoHandshakeTest, testVM2);
294 std::thread t3(&UnifiedGCMultiVMTestSuite::NoHandshakeTest, testVM3);
295 {
296 ThreadSuspensionScope suspensionScope(thread);
297 barrier.PassStrongly();
298 barrier.Wait();
299 }
300
301 void *ecmaVMInterface = nullptr;
302 CrossVMOperator::DoHandshake(vm, stsVMInterface.get(), &ecmaVMInterface);
303 CrossReferenceObjectBuilder CrossReferenceObject(vm, thread);
304 SharedHeap::GetInstance()->TriggerUnifiedGCMark<TriggerGCType::UNIFIED_GC, GCReason::CROSSREF_CAUSE>(thread);
305 while (!thread->HasSuspendRequest()) {}
306 thread->WaitSuspension();
307 CrossReferenceObject.CheckResultAfterUnifiedGC();
308 t1.join();
309 t2.join();
310 t3.join();
311 }
312
HWTEST_F_L0(UnifiedGCMultiVMTest,MultiVMUnifiedGCMarkTest3)313 HWTEST_F_L0(UnifiedGCMultiVMTest, MultiVMUnifiedGCMarkTest3)
314 {
315 SuspendBarrier barrier(INT_VALUE_4);
316 EcmaVM *vm = thread->GetEcmaVM();
317 auto stsVMInterface = std::make_unique<STSVMInterfaceTest>();
318
319 UnifiedGCMultiVMTestSuite testVM1(stsVMInterface.get(), &barrier);
320 UnifiedGCMultiVMTestSuite testVM2(stsVMInterface.get(), &barrier);
321 UnifiedGCMultiVMTestSuite testVM3(stsVMInterface.get(), &barrier);
322 std::thread t1(&UnifiedGCMultiVMTestSuite::TriggerConcurrentMarkTest, testVM1);
323 std::thread t2(&UnifiedGCMultiVMTestSuite::TriggerConcurrentMarkTest, testVM2);
324 std::thread t3(&UnifiedGCMultiVMTestSuite::TriggerConcurrentMarkTest, testVM3);
325 {
326 ThreadSuspensionScope suspensionScope(thread);
327 barrier.PassStrongly();
328 barrier.Wait();
329 }
330
331 void *ecmaVMInterface = nullptr;
332 CrossVMOperator::DoHandshake(vm, stsVMInterface.get(), &ecmaVMInterface);
333 CrossReferenceObjectBuilder CrossReferenceObject(vm, thread);
334 auto heap = vm->GetHeap();
335 heap->GetConcurrentMarker()->Mark();
336 SharedHeap::GetInstance()->TriggerUnifiedGCMark<TriggerGCType::UNIFIED_GC, GCReason::CROSSREF_CAUSE>(thread);
337 while (!thread->HasSuspendRequest()) {}
338 thread->WaitSuspension();
339 CrossReferenceObject.CheckResultAfterUnifiedGC();
340 t1.join();
341 t2.join();
342 t3.join();
343 }
344
HWTEST_F_L0(UnifiedGCMultiVMTest,MultiVMUnifiedGCMarkTest4)345 HWTEST_F_L0(UnifiedGCMultiVMTest, MultiVMUnifiedGCMarkTest4)
346 {
347 SuspendBarrier barrier(INT_VALUE_4);
348 EcmaVM *vm = thread->GetEcmaVM();
349 auto stsVMInterface = std::make_unique<STSVMInterfaceTest>();
350
351 UnifiedGCMultiVMTestSuite testVM1(stsVMInterface.get(), &barrier);
352 UnifiedGCMultiVMTestSuite testVM2(stsVMInterface.get(), &barrier);
353 UnifiedGCMultiVMTestSuite testVM3(stsVMInterface.get(), &barrier);
354 std::thread t1(&UnifiedGCMultiVMTestSuite::CheckUnifiedGCResultTest, testVM1);
355 std::thread t2(&UnifiedGCMultiVMTestSuite::NoHandshakeTest, testVM2);
356 std::thread t3(&UnifiedGCMultiVMTestSuite::TriggerConcurrentMarkTest, testVM3);
357 {
358 ThreadSuspensionScope suspensionScope(thread);
359 barrier.PassStrongly();
360 barrier.Wait();
361 }
362
363 void *ecmaVMInterface = nullptr;
364 CrossVMOperator::DoHandshake(vm, stsVMInterface.get(), &ecmaVMInterface);
365 CrossReferenceObjectBuilder CrossReferenceObject(vm, thread);
366 auto heap = vm->GetHeap();
367 heap->GetConcurrentMarker()->Mark();
368 SharedHeap::GetInstance()->TriggerUnifiedGCMark<TriggerGCType::UNIFIED_GC, GCReason::CROSSREF_CAUSE>(thread);
369 while (!thread->HasSuspendRequest()) {}
370 thread->WaitSuspension();
371 CrossReferenceObject.CheckResultAfterUnifiedGC();
372 t1.join();
373 t2.join();
374 t3.join();
375 }
376
HWTEST_F_L0(UnifiedGCMultiVMTest,MultiVMUnifiedGCMarkTest5)377 HWTEST_F_L0(UnifiedGCMultiVMTest, MultiVMUnifiedGCMarkTest5)
378 {
379 SuspendBarrier barrier(INT_VALUE_4);
380 EcmaVM *vm = thread->GetEcmaVM();
381 auto stsVMInterface = std::make_unique<STSVMInterfaceTest>();
382
383 UnifiedGCMultiVMTestSuite testVM1(stsVMInterface.get(), &barrier);
384 UnifiedGCMultiVMTestSuite testVM2(stsVMInterface.get(), &barrier);
385 UnifiedGCMultiVMTestSuite testVM3(stsVMInterface.get(), &barrier);
386 std::thread t1(&UnifiedGCMultiVMTestSuite::TriggerYoungGCTest, testVM1);
387 std::thread t2(&UnifiedGCMultiVMTestSuite::TriggerYoungGCTest, testVM2);
388 std::thread t3(&UnifiedGCMultiVMTestSuite::TriggerYoungGCTest, testVM3);
389 {
390 ThreadSuspensionScope suspensionScope(thread);
391 barrier.PassStrongly();
392 barrier.Wait();
393 }
394
395 void *ecmaVMInterface = nullptr;
396 CrossVMOperator::DoHandshake(vm, stsVMInterface.get(), &ecmaVMInterface);
397 CrossReferenceObjectBuilder CrossReferenceObject(vm, thread);
398 SharedHeap::GetInstance()->TriggerUnifiedGCMark<TriggerGCType::UNIFIED_GC, GCReason::CROSSREF_CAUSE>(thread);
399 while (!thread->HasSuspendRequest()) {}
400 thread->WaitSuspension();
401 vm->CollectGarbage(TriggerGCType::YOUNG_GC);
402 CrossReferenceObject.CheckResultAfterUnifiedGC();
403 t1.join();
404 t2.join();
405 t3.join();
406 }
407
HWTEST_F_L0(UnifiedGCMultiVMTest,MultiVMMarkFromObjectTest)408 HWTEST_F_L0(UnifiedGCMultiVMTest, MultiVMMarkFromObjectTest)
409 {
410 SuspendBarrier barrier(INT_VALUE_4);
411 EcmaVM *vm = thread->GetEcmaVM();
412 auto stsVMInterface = std::make_unique<STSVMInterfaceTest>();
413
414 UnifiedGCMultiVMTestSuite testVM1(stsVMInterface.get(), &barrier);
415 UnifiedGCMultiVMTestSuite testVM2(stsVMInterface.get(), &barrier);
416 UnifiedGCMultiVMTestSuite testVM3(stsVMInterface.get(), &barrier);
417 std::thread t1(&UnifiedGCMultiVMTestSuite::MarkFromObjectTest, testVM1);
418 std::thread t2(&UnifiedGCMultiVMTestSuite::MarkFromObjectTest, testVM2);
419 std::thread t3(&UnifiedGCMultiVMTestSuite::MarkFromObjectTest, testVM3);
420 {
421 ThreadSuspensionScope suspensionScope(thread);
422 barrier.PassStrongly();
423 barrier.Wait();
424 }
425
426 vm->SetEnableForceGC(false);
427 JSHandle<JSTaggedValue> arrayInXRefRoot = JSArray::ArrayCreate(thread, JSTaggedNumber(INT_VALUE_1));
428 JSHandle<JSTaggedValue> arrayRefByXRefRoot = JSArray::ArrayCreate(thread, JSTaggedNumber(INT_VALUE_2));
429 thread->NewXRefGlobalHandle(arrayInXRefRoot.GetTaggedType());
430 JSArray::FastSetPropertyByValue(thread, arrayInXRefRoot, INT_VALUE_0, arrayRefByXRefRoot);
431
432 auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
433 vm->GetCrossVMOperator()->MarkFromObject(arrayInXRefRoot->GetRawData());
434 heap->WaitRunningTaskFinished();
435 EXPECT_TRUE(IsObjectMarked(arrayInXRefRoot->GetHeapObject()));
436 EXPECT_TRUE(IsObjectMarked(arrayRefByXRefRoot->GetHeapObject()));
437
438 // Clear mark bit
439 heap->Resume(TriggerGCType::UNIFIED_GC);
440 heap->WaitClearTaskFinished();
441 EXPECT_TRUE(!IsObjectMarked(arrayInXRefRoot->GetHeapObject()));
442 EXPECT_TRUE(!IsObjectMarked(arrayRefByXRefRoot->GetHeapObject()));
443 vm->SetEnableForceGC(true);
444 t1.join();
445 t2.join();
446 t3.join();
447 }
448
HWTEST_F_L0(UnifiedGCMultiVMTest,MultiVMTriggerUnifiedGCFailTest)449 HWTEST_F_L0(UnifiedGCMultiVMTest, MultiVMTriggerUnifiedGCFailTest)
450 {
451 SuspendBarrier barrier(INT_VALUE_4);
452 EcmaVM *vm = thread->GetEcmaVM();
453 auto stsVMInterface = std::make_unique<STSVMInterfaceTest>();
454
455 UnifiedGCMultiVMTestSuite testVM1(stsVMInterface.get(), &barrier);
456 UnifiedGCMultiVMTestSuite testVM2(stsVMInterface.get(), &barrier);
457 UnifiedGCMultiVMTestSuite testVM3(stsVMInterface.get(), &barrier);
458 std::thread t1(&UnifiedGCMultiVMTestSuite::TriggerUnifiedGCFailTest, testVM1);
459 std::thread t2(&UnifiedGCMultiVMTestSuite::TriggerUnifiedGCFailTest, testVM2);
460 std::thread t3(&UnifiedGCMultiVMTestSuite::TriggerUnifiedGCFailTest, testVM3);
461 {
462 ThreadSuspensionScope suspensionScope(thread);
463 barrier.PassStrongly();
464 barrier.Wait();
465 }
466
467 void *ecmaVMInterface = nullptr;
468 CrossVMOperator::DoHandshake(vm, stsVMInterface.get(), &ecmaVMInterface);
469 CrossReferenceObjectBuilder CrossReferenceObject(vm, thread);
470 SharedHeap::GetInstance()->TriggerUnifiedGCMark<TriggerGCType::UNIFIED_GC, GCReason::CROSSREF_CAUSE>(thread);
471 vm->GetCrossVMOperator()->GetEcmaVMInterface()->NotifyXGCInterruption();
472 while (!thread->HasSuspendRequest()) {}
473 thread->WaitSuspension();
474 CrossReferenceObject.CheckResultAfterUnifiedGCTriggerFail();
475 t1.join();
476 t2.join();
477 t3.join();
478 }
479
HWTEST_F_L0(UnifiedGCMultiVMVerificationTest,VerifyMultiVMUnifiedGCMarkTest)480 HWTEST_F_L0(UnifiedGCMultiVMVerificationTest, VerifyMultiVMUnifiedGCMarkTest)
481 {
482 SuspendBarrier barrier(INT_VALUE_4);
483 EcmaVM *vm = thread->GetEcmaVM();
484 auto stsVMInterface = std::make_unique<STSVMInterfaceTest>();
485
486 UnifiedGCMultiVMTestSuite testVM1(stsVMInterface.get(), &barrier);
487 UnifiedGCMultiVMTestSuite testVM2(stsVMInterface.get(), &barrier);
488 UnifiedGCMultiVMTestSuite testVM3(stsVMInterface.get(), &barrier);
489 std::thread t1(&UnifiedGCMultiVMTestSuite::HeapVerifyTest, testVM1);
490 std::thread t2(&UnifiedGCMultiVMTestSuite::HeapVerifyTest, testVM2);
491 std::thread t3(&UnifiedGCMultiVMTestSuite::HeapVerifyTest, testVM3);
492 {
493 ThreadSuspensionScope suspensionScope(thread);
494 barrier.PassStrongly();
495 barrier.Wait();
496 }
497
498 void *ecmaVMInterface = nullptr;
499 CrossVMOperator::DoHandshake(vm, stsVMInterface.get(), &ecmaVMInterface);
500 CrossReferenceObjectBuilder CrossReferenceObject(vm, thread);
501 auto heap = vm->GetHeap();
502 heap->GetConcurrentMarker()->Mark();
503 SharedHeap::GetInstance()->TriggerUnifiedGCMark<TriggerGCType::UNIFIED_GC, GCReason::CROSSREF_CAUSE>(thread);
504 while (!thread->HasSuspendRequest()) {}
505 thread->WaitSuspension();
506 CrossReferenceObject.CheckResultAfterUnifiedGC();
507 t1.join();
508 t2.join();
509 t3.join();
510 }
511 #endif // PANDA_JS_ETS_HYBRID_MODE
512 } // namespace panda::test