• 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 #ifndef ECMASCRIPT_TESTS_UNIFIED_GC_TEST_HELPER_H
17 #define ECMASCRIPT_TESTS_UNIFIED_GC_TEST_HELPER_H
18 
19 #include <vector>
20 
21 #ifdef PANDA_JS_ETS_HYBRID_MODE
22 #include "ecmascript/cross_vm/cross_vm_operator.h"
23 #endif  // PANDA_JS_ETS_HYBRID_MODE
24 #include "ecmascript/ecma_vm.h"
25 #include "ecmascript/js_array.h"
26 #include "ecmascript/js_handle.h"
27 #include "ecmascript/js_tagged_value.h"
28 #include "ecmascript/js_thread.h"
29 #include "ecmascript/mem/heap-inl.h"
30 #include "ecmascript/object_factory.h"
31 #include "ecmascript/tests/test_helper.h"
32 
33 constexpr int32_t INT_VALUE_0 = 0;
34 constexpr int32_t INT_VALUE_1 = 1;
35 constexpr int32_t INT_VALUE_2 = 2;
36 constexpr int32_t INT_VALUE_4 = 4;
37 
38 namespace panda::test {
39 using panda::ecmascript::EcmaVM;
40 using panda::ecmascript::JSArray;
41 using panda::ecmascript::JSTaggedNumber;
42 using panda::ecmascript::JSObject;
43 using panda::ecmascript::ECMAObject;
44 using panda::ecmascript::JSTaggedType;
45 using panda::ecmascript::JSTaggedValue;
46 using panda::ecmascript::JSThread;
47 
48 #ifdef PANDA_JS_ETS_HYBRID_MODE
49 // Fake SharedReference implement for Unified GC test
50 class SharedReferenceTest {
51 public:
MarkIfNotMarked()52     bool MarkIfNotMarked()
53     {
54         if (!isMarked_) {
55             isMarked_ = true;
56             return true;
57         }
58         return false;
59     }
60 
isMarked()61     bool isMarked()
62     {
63         return isMarked_;
64     }
65 
66 private:
67     bool isMarked_ {false};
68 };
69 
70 // Fake STSVMInterface implement for Unified GC test
71 class STSVMInterfaceTest final : public arkplatform::STSVMInterface {
72 public:
73     NO_COPY_SEMANTIC(STSVMInterfaceTest);
74     NO_MOVE_SEMANTIC(STSVMInterfaceTest);
75     STSVMInterfaceTest() = default;
76     ~STSVMInterfaceTest() override = default;
77 
MarkFromObject(void * ref)78     void MarkFromObject(void *ref) override
79     {
80         ASSERT(ref != nullptr);
81         auto *sharedRef = static_cast<SharedReferenceTest *>(ref);
82         sharedRef->MarkIfNotMarked();
83     };
84 
OnVMAttach()85     void OnVMAttach() override {}
OnVMDetach()86     void OnVMDetach() override {}
87 
StartXGCBarrier(const NoWorkPred & func)88     bool StartXGCBarrier(const NoWorkPred &func) override
89     {
90         return !func || func();
91     }
WaitForConcurrentMark(const NoWorkPred & func)92     bool WaitForConcurrentMark(const NoWorkPred &func) override
93     {
94         return !func || func();
95     }
RemarkStartBarrier()96     void RemarkStartBarrier() override {}
WaitForRemark(const NoWorkPred & func)97     bool WaitForRemark(const NoWorkPred &func) override
98     {
99         return !func || func();
100     }
FinishXGCBarrier()101     void FinishXGCBarrier() override {}
102 };
103 
104 // Fake Cross Reference Object for Unified GC test
105 class CrossReferenceObjectBuilder {
106 public:
CrossReferenceObjectBuilder(EcmaVM * vm,JSThread * thread)107     CrossReferenceObjectBuilder(EcmaVM *vm, JSThread *thread)
108     {
109         [[maybe_unused]] EcmaHandleScope ecmaHandleScope(thread);
110         size_t nativeBindingSize = INT_VALUE_0;
111 
112         // |JSObject in ArkTS               |SharedReference in STS  |
113         // |--------------------------------|------------------------|
114         // |RootSet(GlobalNodeList)         |                        |
115         // |    |                           |                        |
116         // |    v                           |                        |
117         // |arrayInRoot                     |                        |
118         // |    |                           |                        |
119         // |    v                           |                        |
120         // |jsXRefObjectRefByRoot --------- |--> sharedRefRoot       |
121         // |                                |                        |
122         // |jsXRefObjectNormal -------------|--> sharedRefNormal     |
123         // |                                |                        |
124         // |XRefRootSet(XRefGlobalNodeList) |                        |
125         // |    |                           |                        |
126         // |    v                           |                        |
127         // |arrayInXRefRoot                 |                        |
128         // |    |                           |                        |
129         // |    v                           |                        |
130         // |jsXRefObjectRefByXRefRoot ------|--> sharedRefXRefRoot   |
131         // |--------------------------------|------------------------|
132         SharedReferenceTest* sharedRefRoot = new SharedReferenceTest();
133         SharedReferenceTest* sharedRefNormal = new SharedReferenceTest();
134         SharedReferenceTest* sharedRefXRefRoot = new SharedReferenceTest();
135         sharedRefsNeedMark_.push_back(sharedRefRoot);
136         sharedRefsNoNeedMark_.push_back(sharedRefNormal);
137         sharedRefsNoNeedMark_.push_back(sharedRefXRefRoot);
138 
139         JSHandle<JSTaggedValue> arrayInRoot = JSArray::ArrayCreate(thread, JSTaggedNumber(INT_VALUE_1));
140         thread->NewGlobalHandle(arrayInRoot.GetTaggedType());
141         JSHandle<JSObject> jsXRefObjectRefByRoot = vm->GetFactory()->NewJSXRefObject();
142         JSArray::FastSetPropertyByValue(thread, arrayInRoot, INT_VALUE_0,
143             JSHandle<JSTaggedValue>(jsXRefObjectRefByRoot));
144         ECMAObject::SetNativePointerFieldCount(thread, jsXRefObjectRefByRoot, INT_VALUE_1);
145         ECMAObject::SetNativePointerField(thread, jsXRefObjectRefByRoot, INT_VALUE_0,
146             sharedRefRoot, nullptr, nullptr, nativeBindingSize);
147 
148         JSHandle<JSObject> jsXRefObjectNormal = vm->GetFactory()->NewJSXRefObject();
149         ECMAObject::SetNativePointerFieldCount(thread, jsXRefObjectNormal, INT_VALUE_1);
150         ECMAObject::SetNativePointerField(thread, jsXRefObjectNormal, INT_VALUE_0,
151             sharedRefNormal, nullptr, nullptr, nativeBindingSize);
152 
153         JSHandle<JSTaggedValue> arrayInXRefRoot = JSArray::ArrayCreate(thread, JSTaggedNumber(INT_VALUE_1));
154         thread->NewXRefGlobalHandle(arrayInXRefRoot.GetTaggedType());
155         JSHandle<JSObject> jsXRefObjectRefByXRefRoot = vm->GetFactory()->NewJSXRefObject();
156         JSArray::FastSetPropertyByValue(thread, arrayInXRefRoot, INT_VALUE_0,
157             JSHandle<JSTaggedValue>(jsXRefObjectRefByXRefRoot));
158         ECMAObject::SetNativePointerFieldCount(thread, jsXRefObjectRefByXRefRoot, INT_VALUE_1);
159         ECMAObject::SetNativePointerField(thread, jsXRefObjectRefByXRefRoot, INT_VALUE_0,
160             sharedRefXRefRoot, nullptr, nullptr, nativeBindingSize);
161     }
162 
~CrossReferenceObjectBuilder()163     ~CrossReferenceObjectBuilder()
164     {
165         for (auto sharedRef : sharedRefsNeedMark_) {
166             delete sharedRef;
167         }
168         for (auto sharedRef : sharedRefsNoNeedMark_) {
169             delete sharedRef;
170         }
171     }
172 
CheckResultAfterUnifiedGC()173     void CheckResultAfterUnifiedGC()
174     {
175         for (auto sharedRef : sharedRefsNeedMark_) {
176             EXPECT_TRUE(sharedRef->isMarked());
177         }
178         for (auto sharedRef : sharedRefsNoNeedMark_) {
179             EXPECT_TRUE(!sharedRef->isMarked());
180         }
181     }
182 
CheckResultAfterUnifiedGCTriggerFail()183     void CheckResultAfterUnifiedGCTriggerFail()
184     {
185         for (auto sharedRef : sharedRefsNeedMark_) {
186             EXPECT_TRUE(!sharedRef->isMarked());
187         }
188         for (auto sharedRef : sharedRefsNoNeedMark_) {
189             EXPECT_TRUE(!sharedRef->isMarked());
190         }
191     }
192 
193 private:
194     std::vector<SharedReferenceTest*> sharedRefsNeedMark_;
195     std::vector<SharedReferenceTest*> sharedRefsNoNeedMark_;
196 };
197 #endif  // PANDA_JS_ETS_HYBRID_MODE
198 }  // namespace panda::test
199 
200 #endif  // ECMASCRIPT_TESTS_UNIFIED_GC_TEST_HELPER_H