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