• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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