1 /*
2 * Copyright (c) 2023-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_global_storage.h"
17 #include "ecmascript/ecma_vm.h"
18 #include "ecmascript/js_array.h"
19 #include "ecmascript/js_handle.h"
20 #include "ecmascript/js_tagged_value.h"
21 #include "ecmascript/js_thread.h"
22
23 #include "ecmascript/object_factory.h"
24 #include "ecmascript/tests/test_helper.h"
25
26 using namespace panda::ecmascript;
27 constexpr int32_t INT_VALUE_0 = 0;
28 constexpr int32_t INT_VALUE_1 = 1;
29 constexpr int32_t INT_VALUE_2 = 2;
30
31 namespace panda::test {
32 class EcmaGlobalStorageTest : public BaseTestWithScope<false> {
33 public:
CalculateGlobalNodeCount(uint64_t & allGlobalNodeCount,uint64_t & normalGlobalNodeCount,EcmaGlobalStorage<Node> * globalStorage)34 void CalculateGlobalNodeCount(uint64_t &allGlobalNodeCount, uint64_t &normalGlobalNodeCount,
35 EcmaGlobalStorage<Node> *globalStorage)
36 {
37 globalStorage->SetNodeKind(NodeKind::UNIFIED_NODE);
38 ASSERT(globalStorage->GetNodeKind() == NodeKind::UNIFIED_NODE);
39 globalStorage->IterateUsageGlobal([&normalGlobalNodeCount] ([[maybe_unused]] Node *node) {
40 normalGlobalNodeCount++;
41 });
42 globalStorage->SetNodeKind(NodeKind::NORMAL_NODE);
43 ASSERT(globalStorage->GetNodeKind() == NodeKind::NORMAL_NODE);
44 globalStorage->IterateUsageGlobal([&allGlobalNodeCount] ([[maybe_unused]] Node *node) {
45 allGlobalNodeCount++;
46 });
47 }
48 };
49
HWTEST_F_L0(EcmaGlobalStorageTest,XRefGlobalNodes)50 HWTEST_F_L0(EcmaGlobalStorageTest, XRefGlobalNodes)
51 {
52 EcmaVM *vm = thread->GetEcmaVM();
53 JSNApi::InitHybridVMEnv(vm);
54 JSHandle<TaggedArray> weakRefArray = vm->GetFactory()->NewTaggedArray(INT_VALUE_2, JSTaggedValue::Hole());
55 uintptr_t xRefArrayAddress;
56 vm->SetEnableForceGC(false);
57 {
58 [[maybe_unused]] EcmaHandleScope scope(thread);
59 JSHandle<JSTaggedValue> xRefArray = JSArray::ArrayCreate(thread, JSTaggedNumber(INT_VALUE_1));
60 JSHandle<JSTaggedValue> normalArray = JSArray::ArrayCreate(thread, JSTaggedNumber(INT_VALUE_2));
61 xRefArrayAddress = thread->NewXRefGlobalHandle(xRefArray.GetTaggedType());
62 weakRefArray->Set(thread, INT_VALUE_0, xRefArray.GetTaggedValue().CreateAndGetWeakRef());
63 weakRefArray->Set(thread, INT_VALUE_1, normalArray.GetTaggedValue().CreateAndGetWeakRef());
64 }
65 vm->CollectGarbage(TriggerGCType::FULL_GC);
66 EXPECT_TRUE(!weakRefArray->Get(thread, INT_VALUE_0).IsUndefined());
67 EXPECT_TRUE(weakRefArray->Get(thread, INT_VALUE_1).IsUndefined());
68
69 thread->DisposeXRefGlobalHandle(xRefArrayAddress);
70 vm->CollectGarbage(TriggerGCType::FULL_GC);
71 vm->SetEnableForceGC(true);
72 EXPECT_TRUE(weakRefArray->Get(thread, INT_VALUE_0).IsUndefined());
73 }
74
HWTEST_F_L0(EcmaGlobalStorageTest,SetNodeKind)75 HWTEST_F_L0(EcmaGlobalStorageTest, SetNodeKind)
76 {
77 EcmaVM *vm = thread->GetEcmaVM();
78 JSNApi::InitHybridVMEnv(vm);
79 JSHandle<TaggedArray> weakRefArray = vm->GetFactory()->NewTaggedArray(INT_VALUE_1, JSTaggedValue::Hole());
80 vm->SetEnableForceGC(false);
81 uintptr_t xrefAddr = 0;
82 {
83 [[maybe_unused]] EcmaHandleScope scope(thread);
84 JSHandle<JSTaggedValue> xRefArray = JSArray::ArrayCreate(thread, JSTaggedNumber(INT_VALUE_1));
85 xrefAddr = thread->NewXRefGlobalHandle(xRefArray.GetTaggedType());
86 weakRefArray->Set(thread, INT_VALUE_0, xRefArray.GetTaggedValue().CreateAndGetWeakRef());
87 }
88 thread->SetNodeKind(NodeKind::UNIFIED_NODE);
89 vm->CollectGarbage(TriggerGCType::FULL_GC);
90 thread->SetNodeKind(NodeKind::NORMAL_NODE);
91 thread->DisposeXRefGlobalHandle(xrefAddr);
92 vm->SetEnableForceGC(true);
93 EXPECT_TRUE(weakRefArray->Get(thread, INT_VALUE_0).IsUndefined());
94 }
95
HWTEST_F_L0(EcmaGlobalStorageTest,EcmaGlobalStorage)96 HWTEST_F_L0(EcmaGlobalStorageTest, EcmaGlobalStorage)
97 {
98 EcmaVM *vm = thread->GetEcmaVM();
99 auto chunk = vm->GetChunk();
100 EcmaGlobalStorage<Node> *globalStorage =
101 chunk->New<EcmaGlobalStorage<Node>>(nullptr, vm->GetNativeAreaAllocator());
102 uintptr_t xRefArrayAddress;
103 uintptr_t normalArrayAddress;
104 JSHandle<JSTaggedValue> xRefArray = JSArray::ArrayCreate(thread, JSTaggedNumber(INT_VALUE_1));
105 JSHandle<JSTaggedValue> normalArray = JSArray::ArrayCreate(thread, JSTaggedNumber(INT_VALUE_2));
106
107 uint64_t allGlobalNodeCountBefore = INT_VALUE_0;
108 uint64_t normalGlobalNodeCountBefore = INT_VALUE_0;
109 ASSERT(globalStorage->GetNodeKind() == NodeKind::NORMAL_NODE);
110 CalculateGlobalNodeCount(allGlobalNodeCountBefore, normalGlobalNodeCountBefore, globalStorage);
111 EXPECT_TRUE(normalGlobalNodeCountBefore == allGlobalNodeCountBefore);
112
113 uint64_t allGlobalNodeCountAfter = INT_VALUE_0;
114 uint64_t normalGlobalNodeCountAfter = INT_VALUE_0;
115 xRefArrayAddress = globalStorage->NewGlobalHandle<NodeKind::UNIFIED_NODE>(xRefArray.GetTaggedType());
116 CalculateGlobalNodeCount(allGlobalNodeCountAfter, normalGlobalNodeCountAfter, globalStorage);
117 EXPECT_TRUE(allGlobalNodeCountAfter == allGlobalNodeCountBefore + INT_VALUE_1);
118 EXPECT_TRUE(normalGlobalNodeCountAfter == normalGlobalNodeCountBefore);
119
120 allGlobalNodeCountAfter = INT_VALUE_0;
121 normalGlobalNodeCountAfter = INT_VALUE_0;
122 normalArrayAddress = globalStorage->NewGlobalHandle<NodeKind::NORMAL_NODE>(normalArray.GetTaggedType());
123 CalculateGlobalNodeCount(allGlobalNodeCountAfter, normalGlobalNodeCountAfter, globalStorage);
124 EXPECT_TRUE(allGlobalNodeCountAfter == allGlobalNodeCountBefore + INT_VALUE_2);
125 EXPECT_TRUE(normalGlobalNodeCountAfter == normalGlobalNodeCountBefore + INT_VALUE_1);
126
127 allGlobalNodeCountAfter = INT_VALUE_0;
128 normalGlobalNodeCountAfter = INT_VALUE_0;
129 globalStorage->DisposeGlobalHandle<NodeKind::UNIFIED_NODE>(xRefArrayAddress);
130 CalculateGlobalNodeCount(allGlobalNodeCountAfter, normalGlobalNodeCountAfter, globalStorage);
131 EXPECT_TRUE(allGlobalNodeCountAfter == allGlobalNodeCountBefore + INT_VALUE_1);
132 EXPECT_TRUE(normalGlobalNodeCountAfter == normalGlobalNodeCountBefore + INT_VALUE_1);
133
134 allGlobalNodeCountAfter = INT_VALUE_0;
135 normalGlobalNodeCountAfter = INT_VALUE_0;
136 globalStorage->DisposeGlobalHandle<NodeKind::NORMAL_NODE>(normalArrayAddress);
137 CalculateGlobalNodeCount(allGlobalNodeCountAfter, normalGlobalNodeCountAfter, globalStorage);
138 EXPECT_TRUE(allGlobalNodeCountAfter == allGlobalNodeCountBefore);
139 EXPECT_TRUE(normalGlobalNodeCountAfter == normalGlobalNodeCountBefore);
140
141 chunk->Delete(globalStorage);
142 }
143 };
144