• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 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/dfx/hprof/heap_profiler.h"
17 #include "ecmascript/dfx/hprof/heap_snapshot.h"
18 #include "ecmascript/tests/test_helper.h"
19 
20 using namespace panda::ecmascript;
21 namespace panda::ecmascript {
22 class HeapSnapShotFriendTest {
23 public:
HeapSnapShotFriendTest(const EcmaVM * vm,StringHashMap * stringTable,DumpSnapShotOption dumpOption,bool traceAllocation,EntryIdMap * entryIdMap)24     explicit HeapSnapShotFriendTest(const EcmaVM *vm, StringHashMap *stringTable, DumpSnapShotOption dumpOption,
25                                     bool traceAllocation, EntryIdMap* entryIdMap)
26         : heapSnapshot(vm, stringTable, dumpOption, traceAllocation, entryIdMap) {}
27 
GeneratePrivateStringNodeTest(size_t size)28     Node *GeneratePrivateStringNodeTest(size_t size)
29     {
30         return heapSnapshot.GeneratePrivateStringNode(size);
31     }
32 
MoveNodeTest(uintptr_t address,TaggedObject * forwardAddress,size_t size)33     void MoveNodeTest(uintptr_t address, TaggedObject *forwardAddress, size_t size)
34     {
35         return heapSnapshot.MoveNode(address, forwardAddress, size);
36     }
37 
InsertEntryTest(Node * node)38     void InsertEntryTest(Node *node)
39     {
40         heapSnapshot.entryMap_.InsertEntry(node);
41     }
42 
GenerateNodeNameTest(TaggedObject * taggedObject)43     CString *GenerateNodeNameTest(TaggedObject *taggedObject)
44     {
45         return heapSnapshot.GenerateNodeName(taggedObject);
46     }
47 
GenerateNodeTypeTest(TaggedObject * taggedObject)48     NodeType GenerateNodeTypeTest(TaggedObject *taggedObject)
49     {
50         return heapSnapshot.GenerateNodeType(taggedObject);
51     }
52 
GetEntryMapTest()53     HeapEntryMap &GetEntryMapTest()
54     {
55         return heapSnapshot.entryMap_;
56     }
57 
GetChunkTest()58     Chunk &GetChunkTest()
59     {
60         return heapSnapshot.chunk_;
61     }
62 private:
63     HeapSnapshot heapSnapshot;
64 };
65 
66 class HeapProfilerFriendTest {
67 public:
HeapProfilerFriendTest(const EcmaVM * vm)68     explicit HeapProfilerFriendTest(const EcmaVM *vm) : heapProfiler(vm) {}
69 
MakeHeapSnapshotTest(HeapProfiler::SampleType type,DumpSnapShotOption dumpOption)70     HeapSnapshot *MakeHeapSnapshotTest(HeapProfiler::SampleType type, DumpSnapShotOption dumpOption)
71     {
72         return heapProfiler.MakeHeapSnapshot(type, dumpOption);
73     }
74 
GetEntryIdMapTest()75     EntryIdMap *GetEntryIdMapTest()
76     {
77         return heapProfiler.GetEntryIdMap();
78     }
79 
GetEcmaStringTableTest()80     StringHashMap *GetEcmaStringTableTest()
81     {
82         return heapProfiler.GetEcmaStringTable();
83     }
84 private:
85     HeapProfiler heapProfiler;
86 };
87 }
88 
89 namespace panda::test {
90 class HeapSnapShotTest : public testing::Test {
91 public:
SetUp()92     void SetUp() override
93     {
94         TestHelper::CreateEcmaVMWithScope(ecmaVm_, thread_, scope_);
95         ecmaVm_->SetEnableForceGC(false);
96     }
97 
TearDown()98     void TearDown() override
99     {
100         TestHelper::DestroyEcmaVMWithScope(ecmaVm_, scope_);
101     }
102 
103     EcmaVM *ecmaVm_ {nullptr};
104     EcmaHandleScope *scope_ {nullptr};
105     JSThread *thread_ {nullptr};
106 };
107 
108 const std::set<CString> variableMap({
109     "string1", "string2", "string3", "string4",
110     "string5", "string6", "string7", "string8",
111     "string1string2", "string3string4", "string5string6", "string7string8",
112     "string1string2string3string4", "string5string6string7string8",
113     "string1string2string3string4string5string6string7string8"
114 });
115 
HWTEST_F_L0(HeapSnapShotTest,TestGenerateStringNode)116 HWTEST_F_L0(HeapSnapShotTest, TestGenerateStringNode)
117 {
118     const std::string abcFileName = HPROF_TEST_ABC_FILES_DIR "heap_snapshot.abc";
119 
120     std::string entryPoint = "heap_snapshot";
121     bool result = JSNApi::Execute(ecmaVm_, abcFileName, entryPoint);
122     ASSERT_TRUE(result);
123 
124     // start MakeHeapSnapshot
125     DumpSnapShotOption dumpOption;
126     HeapProfilerFriendTest tester(ecmaVm_);
127     HeapSnapshot *snapshot = tester.MakeHeapSnapshotTest(HeapProfiler::SampleType::ONE_SHOT, dumpOption);
128     size_t totalSize = 0;
129     // global string also generate node
130     for (auto node : *snapshot->GetNodes()) {
131         if (variableMap.find(*node->GetName()) != variableMap.end()) {
132             totalSize += node->GetSelfSize();
133         }
134     }
135     // lineString: 24
136     // treeString: 32
137     // totalSize: 8 * 24 + 7 * 32
138     ASSERT_EQ(totalSize, 416);
139 }
140 
HWTEST_F_L0(HeapSnapShotTest,TestGeneratePrivateStringNode)141 HWTEST_F_L0(HeapSnapShotTest, TestGeneratePrivateStringNode)
142 {
143     HeapProfilerFriendTest tester(ecmaVm_);
144     DumpSnapShotOption dumpOption;
145     dumpOption.isPrivate = true;
146     HeapSnapShotFriendTest heapSnapShotTest(ecmaVm_, tester.GetEcmaStringTableTest(),
147                                             dumpOption, false, tester.GetEntryIdMapTest());
148     Node *node = heapSnapShotTest.GeneratePrivateStringNodeTest(0);
149     // lineString: 24
150     ASSERT_EQ(node->GetSelfSize(), 24);
151 }
152 
HWTEST_F_L0(HeapSnapShotTest,TestMoveNode)153 HWTEST_F_L0(HeapSnapShotTest, TestMoveNode)
154 {
155     HeapProfilerFriendTest tester(ecmaVm_);
156     DumpSnapShotOption dumpOption;
157     HeapSnapShotFriendTest heapSnapShotTest(ecmaVm_, tester.GetEcmaStringTableTest(),
158                                             dumpOption, false, tester.GetEntryIdMapTest());
159     ObjectFactory *factory = ecmaVm_->GetFactory();
160     // create tree string
161     JSHandle<EcmaString> strLeft = factory->NewFromUtf8("leftString");
162     JSHandle<EcmaString> strRight = factory->NewFromUtf8("rightString");
163     EcmaString *treeString = EcmaStringAccessor::Concat(ecmaVm_, strLeft, strRight);
164     uintptr_t address = 0;
165     Node *node = Node::NewNode(heapSnapShotTest.GetChunkTest(), 0, 0,
166         heapSnapShotTest.GenerateNodeNameTest(reinterpret_cast<TaggedObject *>(treeString)),
167         heapSnapShotTest.GenerateNodeTypeTest(reinterpret_cast<TaggedObject *>(treeString)),
168         0, 0, address);
169     heapSnapShotTest.InsertEntryTest(node);
170     heapSnapShotTest.MoveNodeTest(address, reinterpret_cast<TaggedObject *>(treeString), 0);
171     HeapEntryMap &heapEntryMap = heapSnapShotTest.GetEntryMapTest();
172     Node *movedNode = heapEntryMap.FindEntry(reinterpret_cast<JSTaggedType>(treeString));
173     // treeString: 32
174     ASSERT_EQ(movedNode->GetSelfSize(), 32);
175 }
176 }