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 #include <fcntl.h>
16 #include <unistd.h>
17 #include <chrono>
18 #include "ecmascript/dfx/hprof/heap_snapshot.h"
19 #include "ecmascript/dfx/hprof/heap_profiler.h"
20 #include "ecmascript/dfx/hprof/heap_root_visitor.h"
21 #include "ecmascript/global_env.h"
22 #include "ecmascript/jspandafile/js_pandafile_manager.h"
23 #include "ecmascript/js_api/js_api_arraylist.h"
24 #include "ecmascript/js_api/js_api_arraylist_iterator.h"
25 #include "ecmascript/js_api/js_api_deque.h"
26 #include "ecmascript/js_api/js_api_hashmap.h"
27 #include "ecmascript/js_api/js_api_hashset.h"
28 #include "ecmascript/js_api/js_api_lightweightmap.h"
29 #include "ecmascript/js_api/js_api_lightweightset.h"
30 #include "ecmascript/js_api/js_api_linked_list.h"
31 #include "ecmascript/js_api/js_api_list.h"
32 #include "ecmascript/js_api/js_api_plain_array.h"
33 #include "ecmascript/js_api/js_api_queue.h"
34 #include "ecmascript/js_api/js_api_stack.h"
35 #include "ecmascript/js_api/js_api_tree_map.h"
36 #include "ecmascript/js_api/js_api_tree_set.h"
37 #include "ecmascript/js_api/js_api_vector.h"
38 #include "ecmascript/js_date.h"
39 #include "ecmascript/js_iterator.h"
40 #include "ecmascript/js_map.h"
41 #include "ecmascript/js_primitive_ref.h"
42 #include "ecmascript/js_promise.h"
43 #include "ecmascript/js_regexp.h"
44 #include "ecmascript/js_set.h"
45 #include "ecmascript/js_string_iterator.h"
46 #include "ecmascript/js_typed_array.h"
47 #include "ecmascript/js_weak_container.h"
48 #include "ecmascript/linked_hash_table.h"
49 #include "ecmascript/napi/include/jsnapi.h"
50 #include "ecmascript/shared_objects/js_shared_array.h"
51 #include "ecmascript/shared_objects/js_shared_map.h"
52 #include "ecmascript/shared_objects/js_shared_set.h"
53 #include "ecmascript/tagged_hash_array.h"
54 #include "ecmascript/tagged_tree.h"
55 #include "ecmascript/tests/test_helper.h"
56
57 namespace panda::test {
58 using namespace panda::ecmascript;
59 using ErrorType = base::ErrorType;
60
61 class HeapDumpTest : public testing::Test {
62 public:
SetUp()63 void SetUp() override
64 {
65 TestHelper::CreateEcmaVMWithScope(ecmaVm_, thread_, scope_);
66 ecmaVm_->SetEnableForceGC(false);
67 }
68
TearDown()69 void TearDown() override
70 {
71 TestHelper::DestroyEcmaVMWithScope(ecmaVm_, scope_);
72 }
73
74 EcmaVM *ecmaVm_ {nullptr};
75 EcmaHandleScope *scope_ {nullptr};
76 JSThread *thread_ {nullptr};
77 };
78
79 class HeapDumpTestHelper {
80 public:
HeapDumpTestHelper(EcmaVM * vm)81 explicit HeapDumpTestHelper(EcmaVM *vm) : instance(vm) {}
82
~HeapDumpTestHelper()83 ~HeapDumpTestHelper()
84 {
85 HeapProfilerInterface::Destroy(instance);
86 }
87
GenerateSnapShot(const std::string & filePath)88 size_t GenerateSnapShot(const std::string &filePath)
89 {
90 // first generate this file of filePath if not exist,
91 // so the function `realpath` of FileStream can not failed on arm/arm64.
92 fstream outputString(filePath, std::ios::out);
93 outputString.close();
94 outputString.clear();
95 FileStream stream(filePath.c_str());
96 HeapProfilerInterface *heapProfile = HeapProfilerInterface::GetInstance(instance);
97 DumpSnapShotOption dumpOption;
98 dumpOption.dumpFormat = DumpFormat::JSON;
99 heapProfile->DumpHeapSnapshot(&stream, dumpOption);
100 return heapProfile->GetIdCount();
101 }
102
GenerateRawHeapSnashot(const std::string & filePath)103 bool GenerateRawHeapSnashot(const std::string &filePath)
104 {
105 HeapProfilerInterface *heapProfile = HeapProfilerInterface::GetInstance(instance);
106 DumpSnapShotOption dumpOption;
107 dumpOption.dumpFormat = DumpFormat::BINARY;
108 dumpOption.isDumpOOM = true;
109 fstream outputString(filePath, std::ios::out);
110 outputString.close();
111 outputString.clear();
112 int fd = open(filePath.c_str(), O_RDWR | O_CREAT);
113 FileDescriptorStream stream(fd);
114 auto ret = heapProfile->DumpHeapSnapshot(&stream, dumpOption);
115 stream.EndOfStream();
116 return ret;
117 }
118
DecodeRawHeapSnashot(std::string & inputPath,std::string & outputPath)119 bool DecodeRawHeapSnashot(std::string &inputPath, std::string &outputPath)
120 {
121 HeapProfilerInterface *heapProfile = HeapProfilerInterface::GetInstance(instance);
122 fstream outputString(outputPath, std::ios::out);
123 outputString.close();
124 outputString.clear();
125 auto ret = heapProfile->GenerateHeapSnapshot(inputPath, outputPath);
126 return ret;
127 }
MatchHeapDumpString(const std::string & filePath,std::string targetStr)128 bool MatchHeapDumpString(const std::string &filePath, std::string targetStr)
129 {
130 std::string line;
131 std::ifstream inputStream(filePath);
132 std::size_t lineNum = 0;
133 while (getline(inputStream, line)) {
134 lineNum = line.find(targetStr);
135 if (lineNum != line.npos) {
136 return true;
137 }
138 }
139 GTEST_LOG_(ERROR) << "file: " << filePath.c_str() << ", target:" << targetStr.c_str()
140 << ", line:" << std::to_string(lineNum) <<"not found";
141 return false; // Lost the Line
142 }
143
CreateNumberTypedArray(JSType jsType)144 JSHandle<JSTypedArray> CreateNumberTypedArray(JSType jsType)
145 {
146 JSHandle<GlobalEnv> env = instance->GetGlobalEnv();
147 ObjectFactory *factory = instance->GetFactory();
148 JSHandle<JSTaggedValue> handleTagValFunc = env->GetInt8ArrayFunction();
149 switch (jsType) {
150 case JSType::JS_INT8_ARRAY:
151 break;
152 case JSType::JS_UINT8_ARRAY:
153 handleTagValFunc = env->GetUint8ArrayFunction();
154 break;
155 case JSType::JS_UINT8_CLAMPED_ARRAY:
156 handleTagValFunc = env->GetUint8ClampedArrayFunction();
157 break;
158 case JSType::JS_INT16_ARRAY:
159 handleTagValFunc = env->GetInt16ArrayFunction();
160 break;
161 case JSType::JS_UINT16_ARRAY:
162 handleTagValFunc = env->GetUint16ArrayFunction();
163 break;
164 case JSType::JS_INT32_ARRAY:
165 handleTagValFunc = env->GetInt32ArrayFunction();
166 break;
167 case JSType::JS_UINT32_ARRAY:
168 handleTagValFunc = env->GetUint32ArrayFunction();
169 break;
170 case JSType::JS_FLOAT32_ARRAY:
171 handleTagValFunc = env->GetFloat32ArrayFunction();
172 break;
173 case JSType::JS_FLOAT64_ARRAY:
174 handleTagValFunc = env->GetFloat64ArrayFunction();
175 break;
176 case JSType::JS_BIGINT64_ARRAY:
177 handleTagValFunc = env->GetBigInt64ArrayFunction();
178 break;
179 case JSType::JS_BIGUINT64_ARRAY:
180 handleTagValFunc = env->GetBigUint64ArrayFunction();
181 break;
182 default:
183 ASSERT_PRINT(false, "wrong jsType used in CreateNumberTypedArray function");
184 break;
185 }
186 return JSHandle<JSTypedArray>::Cast(
187 factory->NewJSObjectByConstructor(JSHandle<JSFunction>::Cast(handleTagValFunc), handleTagValFunc));
188 }
189
NewObject(uint32_t size,JSType type,JSHandle<JSTaggedValue> proto)190 JSHandle<JSObject> NewObject(uint32_t size, JSType type, JSHandle<JSTaggedValue> proto)
191 {
192 ObjectFactory *factory = instance->GetFactory();
193 JSHandle<JSHClass> hclass = factory->NewEcmaHClass(size, type, proto);
194 return factory->NewJSObjectWithInit(hclass);
195 }
196
NewSObject(uint32_t size,JSType type,JSHandle<JSTaggedValue> proto)197 JSHandle<JSObject> NewSObject(uint32_t size, JSType type, JSHandle<JSTaggedValue> proto)
198 {
199 ObjectFactory *factory = instance->GetFactory();
200 auto emptySLayout = instance->GetJSThread()->GlobalConstants()->GetHandledEmptySLayoutInfo();
201 JSHandle<JSHClass> hclass = factory->NewSEcmaHClass(size, 0, type, proto, emptySLayout);
202 return factory->NewJSObjectWithInit(hclass);
203 }
204
205 // JS_SET
NewJSSet()206 JSHandle<JSSet> NewJSSet()
207 {
208 JSThread *thread = instance->GetJSThread();
209 JSHandle<JSTaggedValue> proto = instance->GetGlobalEnv()->GetFunctionPrototype();
210 JSHandle<JSObject> jsSetObject = NewObject(JSSet::SIZE, JSType::JS_SET, proto);
211 JSHandle<JSSet> jsSet = JSHandle<JSSet>::Cast(jsSetObject);
212 JSHandle<LinkedHashSet> linkedSet(LinkedHashSet::Create(thread));
213 jsSet->SetLinkedSet(thread, linkedSet);
214 return jsSet;
215 }
216
217 // JS_SHARED_SET
NewJSSharedSet()218 JSHandle<JSSharedSet> NewJSSharedSet()
219 {
220 JSThread *thread = instance->GetJSThread();
221 JSHandle<JSTaggedValue> proto = instance->GetGlobalEnv()->GetSFunctionPrototype();
222 JSHandle<JSObject> jsSSetObject = NewSObject(JSSharedSet::SIZE, JSType::JS_SHARED_SET, proto);
223 JSHandle<JSSharedSet> jsSSet = JSHandle<JSSharedSet>::Cast(jsSSetObject);
224 JSHandle<LinkedHashSet> linkedSet(
225 LinkedHashSet::Create(thread, LinkedHashSet::MIN_CAPACITY, MemSpaceKind::SHARED));
226 jsSSet->SetLinkedSet(thread, linkedSet);
227 jsSSet->SetModRecord(0);
228 return jsSSet;
229 }
230
231 // JS_MAP
NewJSMap()232 JSHandle<JSMap> NewJSMap()
233 {
234 JSThread *thread = instance->GetJSThread();
235 JSHandle<JSTaggedValue> proto = instance->GetGlobalEnv()->GetFunctionPrototype();
236 JSHandle<JSObject> jsMapObject = NewObject(JSMap::SIZE, JSType::JS_MAP, proto);
237 JSHandle<JSMap> jsMap = JSHandle<JSMap>::Cast(jsMapObject);
238 JSHandle<LinkedHashMap> linkedMap(LinkedHashMap::Create(thread));
239 jsMap->SetLinkedMap(thread, linkedMap);
240 return jsMap;
241 }
242
243 // JS_SHARED_MAP
NewJSSharedMap()244 JSHandle<JSSharedMap> NewJSSharedMap()
245 {
246 JSThread *thread = instance->GetJSThread();
247 JSHandle<JSTaggedValue> proto = instance->GetGlobalEnv()->GetSFunctionPrototype();
248 JSHandle<JSObject> jsSMapObject = NewSObject(JSSharedMap::SIZE, JSType::JS_SHARED_MAP, proto);
249 JSHandle<JSSharedMap> jsSMap = JSHandle<JSSharedMap>::Cast(jsSMapObject);
250 JSHandle<LinkedHashMap> linkedMap(
251 LinkedHashMap::Create(thread, LinkedHashMap::MIN_CAPACITY, MemSpaceKind::SHARED));
252 jsSMap->SetLinkedMap(thread, linkedMap);
253 jsSMap->SetModRecord(0);
254 return jsSMap;
255 }
256
257 //JS_WEAK_SET
NewJSWeakSet()258 JSHandle<JSWeakSet> NewJSWeakSet()
259 {
260 JSThread *thread = instance->GetJSThread();
261 JSHandle<JSTaggedValue> proto = instance->GetGlobalEnv()->GetFunctionPrototype();
262 JSHandle<JSObject> jsWeakSetObject = NewObject(JSWeakSet::SIZE, JSType::JS_WEAK_SET, proto);
263 JSHandle<JSWeakSet> jsWeakSet = JSHandle<JSWeakSet>::Cast(jsWeakSetObject);
264 JSHandle<LinkedHashSet> weakLinkedSet(LinkedHashSet::Create(thread));
265 jsWeakSet->SetLinkedSet(thread, weakLinkedSet);
266 return jsWeakSet;
267 }
268
269 //JS_WEAK_MAP
NewJSWeakMap()270 JSHandle<JSWeakMap> NewJSWeakMap()
271 {
272 JSThread *thread = instance->GetJSThread();
273 JSHandle<JSTaggedValue> proto = instance->GetGlobalEnv()->GetFunctionPrototype();
274 JSHandle<JSObject> jsWeakMapObject = NewObject(JSWeakMap::SIZE, JSType::JS_WEAK_MAP, proto);
275 JSHandle<JSWeakMap> jsWeakMap = JSHandle<JSWeakMap>::Cast(jsWeakMapObject);
276 JSHandle<LinkedHashMap> weakLinkedMap(LinkedHashMap::Create(thread));
277 jsWeakMap->SetLinkedMap(thread, weakLinkedMap);
278 return jsWeakMap;
279 }
280
281 // JS_PROXY
NewJSProxy()282 JSHandle<JSProxy> NewJSProxy()
283 {
284 JSThread *thread = instance->GetJSThread();
285 ObjectFactory *factory = instance->GetFactory();
286 JSFunction *newTarget = instance->GetGlobalEnv()->GetObjectFunction().GetObject<JSFunction>();
287 JSHandle<JSTaggedValue> newTargetHandle(thread, newTarget);
288 JSHandle<JSObject> jsObject =
289 factory->NewJSObjectByConstructor(JSHandle<JSFunction>(newTargetHandle), newTargetHandle);
290 JSHandle<JSTaggedValue> emptyObj(thread, jsObject.GetTaggedValue());
291 return factory->NewJSProxy(emptyObj, emptyObj);
292 }
293
294 // JS_FORIN_ITERATOR
NewJSForInIterator()295 JSHandle<JSForInIterator> NewJSForInIterator()
296 {
297 JSThread *thread = instance->GetJSThread();
298 ObjectFactory *factory = instance->GetFactory();
299 JSHandle<JSTaggedValue> arrayEmpty(thread, factory->NewJSArray().GetTaggedValue());
300 JSHandle<JSTaggedValue> keys(thread, factory->EmptyArray().GetTaggedValue());
301 JSHandle<JSTaggedValue> hclass(thread, JSTaggedValue::Undefined());
302 return factory->NewJSForinIterator(arrayEmpty, keys, hclass);
303 }
304
305 // JS_REG_EXP_ITERATOR
NewJSRegExpIterator()306 JSHandle<JSRegExpIterator> NewJSRegExpIterator()
307 {
308 ObjectFactory *factory = instance->GetFactory();
309 JSHandle<JSTaggedValue> proto = instance->GetGlobalEnv()->GetFunctionPrototype();
310 JSHandle<EcmaString> emptyString = factory->GetEmptyString();
311 JSHandle<JSTaggedValue> jsRegExp(NewObject(JSRegExp::SIZE, JSType::JS_REG_EXP, proto));
312 return factory->NewJSRegExpIterator(jsRegExp, emptyString, false, false);
313 }
314
315 // PROMISE_ITERATOR_RECORD
NewPromiseIteratorRecord()316 JSHandle<PromiseIteratorRecord> NewPromiseIteratorRecord()
317 {
318 JSThread *thread = instance->GetJSThread();
319 ObjectFactory *factory = instance->GetFactory();
320 JSFunction *newTarget = instance->GetGlobalEnv()->GetObjectFunction().GetObject<JSFunction>();
321 JSHandle<JSTaggedValue> newTargetHandle(thread, newTarget);
322 JSHandle<JSObject> jsObject =
323 factory->NewJSObjectByConstructor(JSHandle<JSFunction>(newTargetHandle), newTargetHandle);
324 JSHandle<JSTaggedValue> emptyObj(thread, jsObject.GetTaggedValue());
325 return factory->NewPromiseIteratorRecord(emptyObj, false);
326 }
327
328 // JS_API_ARRAY_LIST
NewJSAPIArrayList()329 JSHandle<JSAPIArrayList> NewJSAPIArrayList()
330 {
331 JSHandle<JSTaggedValue> proto = instance->GetGlobalEnv()->GetFunctionPrototype();
332 JSHandle<JSObject> jsAPIArrayListObject = NewObject(JSAPIArrayList::SIZE, JSType::JS_API_ARRAY_LIST, proto);
333 JSHandle<JSAPIArrayList> jsAPIArrayList = JSHandle<JSAPIArrayList>::Cast(jsAPIArrayListObject);
334 jsAPIArrayList->SetLength(instance->GetJSThread(), JSTaggedValue(0));
335 return jsAPIArrayList;
336 }
337
338 // JS_API_HASH_MAP
NewJSAPIHashMap()339 JSHandle<JSAPIHashMap> NewJSAPIHashMap()
340 {
341 JSThread *thread = instance->GetJSThread();
342 JSHandle<JSTaggedValue> proto = instance->GetGlobalEnv()->GetObjectFunctionPrototype();
343 JSHandle<JSObject> jsAPIHashMapObject = NewObject(JSAPIHashMap::SIZE, JSType::JS_API_HASH_MAP, proto);
344 JSHandle<JSAPIHashMap> jsAPIHashMap = JSHandle<JSAPIHashMap>::Cast(jsAPIHashMapObject);
345 jsAPIHashMap->SetTable(thread, TaggedHashArray::Create(thread));
346 jsAPIHashMap->SetSize(0);
347 return jsAPIHashMap;
348 }
349
350 // JS_API_HASH_SET
NewJSAPIHashSet()351 JSHandle<JSAPIHashSet> NewJSAPIHashSet()
352 {
353 JSThread *thread = instance->GetJSThread();
354 JSHandle<JSTaggedValue> proto = instance->GetGlobalEnv()->GetObjectFunctionPrototype();
355 JSHandle<JSObject> jsAPIHashSetObject = NewObject(JSAPIHashSet::SIZE, JSType::JS_API_HASH_SET, proto);
356 JSHandle<JSAPIHashSet> jsAPIHashSet = JSHandle<JSAPIHashSet>::Cast(jsAPIHashSetObject);
357 jsAPIHashSet->SetTable(thread, TaggedHashArray::Create(thread));
358 jsAPIHashSet->SetSize(0);
359 return jsAPIHashSet;
360 }
361
362 // JS_API_LIGHT_WEIGHT_MAP
NewJSAPILightWeightMap()363 JSHandle<JSAPILightWeightMap> NewJSAPILightWeightMap()
364 {
365 JSThread *thread = instance->GetJSThread();
366 ObjectFactory *factory = instance->GetFactory();
367 JSHandle<JSTaggedValue> proto = instance->GetGlobalEnv()->GetObjectFunctionPrototype();
368 JSHandle<JSObject> jsAPILightWeightMapObject =
369 NewObject(JSAPILightWeightMap::SIZE, JSType::JS_API_LIGHT_WEIGHT_MAP, proto);
370 JSHandle<JSAPILightWeightMap> jsAPILightWeightMap =
371 JSHandle<JSAPILightWeightMap>::Cast(jsAPILightWeightMapObject);
372 JSHandle<JSTaggedValue> hashArray =
373 JSHandle<JSTaggedValue>(factory->NewTaggedArray(JSAPILightWeightMap::DEFAULT_CAPACITY_LENGTH));
374 JSHandle<JSTaggedValue> keyArray =
375 JSHandle<JSTaggedValue>(factory->NewTaggedArray(JSAPILightWeightMap::DEFAULT_CAPACITY_LENGTH));
376 JSHandle<JSTaggedValue> valueArray =
377 JSHandle<JSTaggedValue>(factory->NewTaggedArray(JSAPILightWeightMap::DEFAULT_CAPACITY_LENGTH));
378 jsAPILightWeightMap->SetHashes(thread, hashArray);
379 jsAPILightWeightMap->SetKeys(thread, keyArray);
380 jsAPILightWeightMap->SetValues(thread, valueArray);
381 jsAPILightWeightMap->SetLength(0);
382 return jsAPILightWeightMap;
383 }
384
385 // JS_API_LIGHT_WEIGHT_SET
NewJSAPILightWeightSet()386 JSHandle<JSAPILightWeightSet> NewJSAPILightWeightSet()
387 {
388 JSThread *thread = instance->GetJSThread();
389 JSHandle<JSTaggedValue> proto = instance->GetGlobalEnv()->GetObjectFunctionPrototype();
390 JSHandle<JSObject> jsAPILightWeightSetObject =
391 NewObject(JSAPILightWeightSet::SIZE, JSType::JS_API_LIGHT_WEIGHT_SET, proto);
392 JSHandle<JSAPILightWeightSet> jsAPILightWeightSet =
393 JSHandle<JSAPILightWeightSet>::Cast(jsAPILightWeightSetObject);
394 JSHandle<TaggedArray> hashes =
395 JSAPILightWeightSet::CreateSlot(thread, JSAPILightWeightSet::DEFAULT_CAPACITY_LENGTH);
396 JSHandle<TaggedArray> values =
397 JSAPILightWeightSet::CreateSlot(thread, JSAPILightWeightSet::DEFAULT_CAPACITY_LENGTH);
398 jsAPILightWeightSet->SetHashes(thread, hashes);
399 jsAPILightWeightSet->SetValues(thread, values);
400 jsAPILightWeightSet->SetLength(0);
401 return jsAPILightWeightSet;
402 }
403
404 // JS_API_TREE_MAP
NewJSAPITreeMap()405 JSHandle<JSAPITreeMap> NewJSAPITreeMap()
406 {
407 JSThread *thread = instance->GetJSThread();
408 JSHandle<JSTaggedValue> proto = instance->GetGlobalEnv()->GetObjectFunctionPrototype();
409 JSHandle<JSObject> jsAPITreeMapObject = NewObject(JSAPITreeMap::SIZE, JSType::JS_API_TREE_MAP, proto);
410 JSHandle<JSAPITreeMap> jsAPITreeMap = JSHandle<JSAPITreeMap>::Cast(jsAPITreeMapObject);
411 JSHandle<TaggedTreeMap> treeMap(thread, TaggedTreeMap::Create(thread));
412 jsAPITreeMap->SetTreeMap(thread, treeMap);
413 return jsAPITreeMap;
414 }
415
416 // JS_API_TREE_SET
NewJSAPITreeSet()417 JSHandle<JSAPITreeSet> NewJSAPITreeSet()
418 {
419 JSThread *thread = instance->GetJSThread();
420 JSHandle<JSTaggedValue> proto = instance->GetGlobalEnv()->GetObjectFunctionPrototype();
421 JSHandle<JSObject> jsAPITreeSetObject = NewObject(JSAPITreeSet::SIZE, JSType::JS_API_TREE_SET, proto);
422 JSHandle<JSAPITreeSet> jsAPITreeSet = JSHandle<JSAPITreeSet>::Cast(jsAPITreeSetObject);
423 JSHandle<TaggedTreeSet> treeSet(thread, TaggedTreeSet::Create(thread));
424 jsAPITreeSet->SetTreeSet(thread, treeSet);
425 return jsAPITreeSet;
426 }
427
428 // JS_API_QUEUE
NewJSAPIQueue()429 JSHandle<JSAPIQueue> NewJSAPIQueue()
430 {
431 JSThread *thread = instance->GetJSThread();
432 ObjectFactory *factory = instance->GetFactory();
433 JSHandle<JSTaggedValue> proto = instance->GetGlobalEnv()->GetFunctionPrototype();
434 JSHandle<JSObject> jsAPIQueueObject = NewObject(JSAPIQueue::SIZE, JSType::JS_API_QUEUE, proto);
435 JSHandle<JSAPIQueue> jsAPIQueue = JSHandle<JSAPIQueue>::Cast(jsAPIQueueObject);
436 JSHandle<TaggedArray> newElements = factory->NewTaggedArray(JSAPIQueue::DEFAULT_CAPACITY_LENGTH);
437 jsAPIQueue->SetLength(thread, JSTaggedValue(0));
438 jsAPIQueue->SetFront(0);
439 jsAPIQueue->SetTail(0);
440 jsAPIQueue->SetElements(thread, newElements);
441 return jsAPIQueue;
442 }
443 // JS_API_DEQUE
NewJSAPIDeque()444 JSHandle<JSAPIDeque> NewJSAPIDeque()
445 {
446 ObjectFactory *factory = instance->GetFactory();
447 JSHandle<JSTaggedValue> proto = instance->GetGlobalEnv()->GetFunctionPrototype();
448 JSHandle<JSObject> jsAPIDequeObject = NewObject(JSAPIDeque::SIZE, JSType::JS_API_DEQUE, proto);
449 JSHandle<JSAPIDeque> jsAPIDeque = JSHandle<JSAPIDeque>::Cast(jsAPIDequeObject);
450 JSHandle<TaggedArray> newElements = factory->NewTaggedArray(JSAPIDeque::DEFAULT_CAPACITY_LENGTH);
451 jsAPIDeque->SetFirst(0);
452 jsAPIDeque->SetLast(0);
453 jsAPIDeque->SetElements(instance->GetJSThread(), newElements);
454 return jsAPIDeque;
455 }
456 // JS_API_STACK
NewJSAPIStack()457 JSHandle<JSAPIStack> NewJSAPIStack()
458 {
459 JSHandle<JSTaggedValue> proto = instance->GetGlobalEnv()->GetFunctionPrototype();
460 JSHandle<JSObject> jsAPIStackObject = NewObject(JSAPIStack::SIZE, JSType::JS_API_STACK, proto);
461 JSHandle<JSAPIStack> jsAPIStack = JSHandle<JSAPIStack>::Cast(jsAPIStackObject);
462 jsAPIStack->SetTop(0);
463 return jsAPIStack;
464 }
465
466 // JS_API_PLAIN_ARRAY
NewJSAPIPlainArray()467 JSHandle<JSAPIPlainArray> NewJSAPIPlainArray()
468 {
469 JSThread *thread = instance->GetJSThread();
470 JSHandle<JSTaggedValue> proto = instance->GetGlobalEnv()->GetObjectFunctionPrototype();
471 JSHandle<JSObject> jsAPIPlainArrayObject = NewObject(JSAPIPlainArray::SIZE, JSType::JS_API_PLAIN_ARRAY, proto);
472 JSHandle<JSAPIPlainArray> jsAPIPlainArray = JSHandle<JSAPIPlainArray>::Cast(jsAPIPlainArrayObject);
473 JSHandle<TaggedArray> keys =
474 JSAPIPlainArray::CreateSlot(thread, JSAPIPlainArray::DEFAULT_CAPACITY_LENGTH);
475 JSHandle<TaggedArray> values =
476 JSAPIPlainArray::CreateSlot(thread, JSAPIPlainArray::DEFAULT_CAPACITY_LENGTH);
477 jsAPIPlainArray->SetKeys(thread, keys);
478 jsAPIPlainArray->SetValues(thread, values);
479 jsAPIPlainArray->SetLength(0);
480 return jsAPIPlainArray;
481 }
482
483 // JS_API_LIST
NewJSAPIList()484 JSHandle<JSAPIList> NewJSAPIList()
485 {
486 JSThread *thread = instance->GetJSThread();
487 JSHandle<JSTaggedValue> proto = instance->GetGlobalEnv()->GetObjectFunctionPrototype();
488 JSHandle<JSObject> jsAPIListObject = NewObject(JSAPIList::SIZE, JSType::JS_API_LIST, proto);
489 JSHandle<JSAPIList> jsAPIList = JSHandle<JSAPIList>::Cast(jsAPIListObject);
490 JSHandle<JSTaggedValue> taggedSingleList(thread, TaggedSingleList::Create(thread));
491 jsAPIList->SetSingleList(thread, taggedSingleList);
492 return jsAPIList;
493 }
494
495 // JS_API_LINKED_LIST
NewJSAPILinkedList()496 JSHandle<JSAPILinkedList> NewJSAPILinkedList()
497 {
498 JSThread *thread = instance->GetJSThread();
499 JSHandle<JSTaggedValue> proto = instance->GetGlobalEnv()->GetObjectFunctionPrototype();
500 JSHandle<JSObject> jsAPILinkedListObject = NewObject(JSAPILinkedList::SIZE, JSType::JS_API_LINKED_LIST, proto);
501 JSHandle<JSAPILinkedList> jsAPILinkedList = JSHandle<JSAPILinkedList>::Cast(jsAPILinkedListObject);
502 JSHandle<JSTaggedValue> linkedlist(thread, TaggedDoubleList::Create(thread));
503 jsAPILinkedList->SetDoubleList(thread, linkedlist);
504 return jsAPILinkedList;
505 }
506
507 // JS_API_VECTOR
NewJSAPIVector()508 JSHandle<JSAPIVector> NewJSAPIVector()
509 {
510 JSHandle<JSTaggedValue> proto = instance->GetGlobalEnv()->GetFunctionPrototype();
511 JSHandle<JSObject> jsAPIVectorObject = NewObject(JSAPIVector::SIZE, JSType::JS_API_VECTOR, proto);
512 JSHandle<JSAPIVector> jsAPIVector = JSHandle<JSAPIVector>::Cast(jsAPIVectorObject);
513 jsAPIVector->SetLength(0);
514 return jsAPIVector;
515 }
516
517 private:
518 EcmaVM *instance {nullptr};
519 };
520
521 class MockHeapProfiler : public HeapProfilerInterface {
522 public:
523 NO_MOVE_SEMANTIC(MockHeapProfiler);
524 NO_COPY_SEMANTIC(MockHeapProfiler);
MockHeapProfiler(HeapProfilerInterface * profiler)525 explicit MockHeapProfiler(HeapProfilerInterface *profiler) : profiler_(profiler) {}
~MockHeapProfiler()526 ~MockHeapProfiler() override
527 {
528 allocEvtObj_.clear();
529 };
530
AllocationEvent(TaggedObject * address,size_t size)531 void AllocationEvent(TaggedObject *address, size_t size) override
532 {
533 allocEvtObj_.emplace(address, true);
534 profiler_->AllocationEvent(address, size);
535 }
536
MoveEvent(uintptr_t address,TaggedObject * forwardAddress,size_t size)537 void MoveEvent(uintptr_t address, TaggedObject *forwardAddress, size_t size) override
538 {
539 return profiler_->MoveEvent(address, forwardAddress, size);
540 }
541
DumpHeapSnapshot(Stream * stream,const DumpSnapShotOption & dumpOption,Progress * progress=nullptr)542 bool DumpHeapSnapshot(Stream *stream, const DumpSnapShotOption &dumpOption, Progress *progress = nullptr) override
543 {
544 return profiler_->DumpHeapSnapshot(stream, dumpOption, progress);
545 }
546
DumpHeapSnapshot(const DumpSnapShotOption & dumpOption)547 void DumpHeapSnapshot(const DumpSnapShotOption &dumpOption) override
548 {
549 profiler_->DumpHeapSnapshot(dumpOption);
550 }
551
GenerateHeapSnapshot(std::string & inputFilePath,std::string & outputPath)552 bool GenerateHeapSnapshot(std::string &inputFilePath, std::string &outputPath) override
553 {
554 return profiler_->GenerateHeapSnapshot(inputFilePath, outputPath);
555 }
556
StartHeapTracking(double timeInterval,bool isVmMode=true,Stream * stream=nullptr,bool traceAllocation=false,bool newThread=true)557 bool StartHeapTracking(double timeInterval, bool isVmMode = true, Stream *stream = nullptr,
558 bool traceAllocation = false, bool newThread = true) override
559 {
560 return profiler_->StartHeapTracking(timeInterval, isVmMode, stream, traceAllocation, newThread);
561 }
562
StopHeapTracking(Stream * stream,Progress * progress=nullptr,bool newThread=true)563 bool StopHeapTracking(Stream *stream, Progress *progress = nullptr, bool newThread = true) override
564 {
565 return profiler_->StopHeapTracking(stream, progress, newThread);
566 }
567
UpdateHeapTracking(Stream * stream)568 bool UpdateHeapTracking(Stream *stream) override
569 {
570 return profiler_->UpdateHeapTracking(stream);
571 }
572
StartHeapSampling(uint64_t samplingInterval,int stackDepth=128)573 bool StartHeapSampling(uint64_t samplingInterval, int stackDepth = 128) override
574 {
575 return profiler_->StartHeapSampling(samplingInterval, stackDepth);
576 }
577
StopHeapSampling()578 void StopHeapSampling() override
579 {
580 profiler_->StopHeapSampling();
581 }
582
GetAllocationProfile()583 const struct SamplingInfo *GetAllocationProfile() override
584 {
585 return profiler_->GetAllocationProfile();
586 }
587
GetIdCount()588 size_t GetIdCount() override
589 {
590 return profiler_->GetIdCount();
591 }
592
593 std::unordered_map<TaggedObject *, bool> allocEvtObj_;
594 HeapProfilerInterface *profiler_ {nullptr};
595 };
596
HWTEST_F_L0(HeapDumpTest,TestAllocationEvent)597 HWTEST_F_L0(HeapDumpTest, TestAllocationEvent)
598 {
599 const std::string abcFileName = HPROF_TEST_ABC_FILES_DIR"heapdump.abc";
600 const std::string jsFileName = HPROF_TEST_JS_FILES_DIR"heapdump.js";
601 MockHeapProfiler mockHeapProfiler(ecmaVm_->GetOrNewHeapProfile());
602 ecmaVm_->SetHeapProfile(&mockHeapProfiler);
603
604 std::unordered_map<TaggedObject *, bool> ObjBeforeExecute;
605 std::unordered_map<TaggedObject *, bool> *ObjMap = &ObjBeforeExecute;
606 auto heap = ecmaVm_->GetHeap();
607 ASSERT_NE(heap, nullptr);
608 auto countCb = [&ObjMap](TaggedObject *obj) {
609 ObjMap->emplace(obj, true);
610 };
611 heap->IterateOverObjects(countCb);
612 RootVisitor rootVisitor = [&countCb]([[maybe_unused]] Root type, ObjectSlot slot) {
613 JSTaggedValue value((slot).GetTaggedType());
614 if (!value.IsHeapObject()) {
615 return;
616 }
617 TaggedObject *root = value.GetTaggedObject();
618 countCb(root);
619 };
620 RootRangeVisitor rangeVisitor = [&rootVisitor]([[maybe_unused]] Root type,
621 ObjectSlot start, ObjectSlot end) {
622 for (ObjectSlot slot = start; slot < end; slot++) {
623 rootVisitor(type, slot);
624 }
625 };
626 RootBaseAndDerivedVisitor derivedVisitor = []
627 ([[maybe_unused]] Root type, [[maybe_unused]] ObjectSlot base, [[maybe_unused]] ObjectSlot derived,
628 [[maybe_unused]] uintptr_t baseOldObject) {};
629 ecmaVm_->Iterate(rootVisitor, rangeVisitor, VMRootVisitType::HEAP_SNAPSHOT);
630 thread_->Iterate(rootVisitor, rangeVisitor, derivedVisitor);
631
632 bool result = JSNApi::Execute(ecmaVm_, abcFileName, "heapdump");
633 EXPECT_TRUE(result);
634
635 std::unordered_map<TaggedObject *, bool> ObjAfterExecute;
636 ObjMap = &ObjAfterExecute;
637 heap->IterateOverObjects(countCb);
638 ecmaVm_->Iterate(rootVisitor, rangeVisitor, VMRootVisitType::HEAP_SNAPSHOT);
639 thread_->Iterate(rootVisitor, rangeVisitor, derivedVisitor);
640 ecmaVm_->SetHeapProfile(mockHeapProfiler.profiler_);
641
642 std::unordered_map<std::string, int> noTraceObjCheck =
643 {{"TaggedArray", 1}, {"AsyncFunction", 2}, {"LexicalEnv", 2}, {"Array", 3}, {"Function", 7}, {"Map", 1},
644 {"Object", 1}};
645 bool pass = true;
646 std::unordered_map<std::string, int> noTraceObj;
647 for (auto o = ObjAfterExecute.begin(); o != ObjAfterExecute.end(); o++) {
648 if (ObjBeforeExecute.find(o->first) != ObjBeforeExecute.end()) {
649 continue;
650 }
651 if (mockHeapProfiler.allocEvtObj_.find(o->first) != mockHeapProfiler.allocEvtObj_.end()) {
652 continue;
653 }
654 auto objType = o->first->GetClass()->GetObjectType();
655 std::string typeName = ConvertToStdString(JSHClass::DumpJSType(objType));
656 if (noTraceObjCheck.size() == 0) {
657 LOG_ECMA(ERROR) << "Object not traced, Addr=" << o->first << ", TypeName=" << typeName;
658 pass = false;
659 }
660 if (noTraceObj.find(typeName) == noTraceObj.end()) {
661 noTraceObj.emplace(typeName, 0);
662 }
663 noTraceObj[typeName] += 1;
664 }
665 for (auto o = noTraceObj.begin(); o != noTraceObj.end(); o++) {
666 if (noTraceObjCheck.find(o->first) == noTraceObjCheck.end()) {
667 LOG_ECMA(ERROR) << "Object not traced, TypeName=" << o->first << ", count=" << o->second;
668 pass = false;
669 }
670 }
671 ASSERT_TRUE(pass);
672 }
673
HWTEST_F_L0(HeapDumpTest,TestHeapDumpFunctionUrl)674 HWTEST_F_L0(HeapDumpTest, TestHeapDumpFunctionUrl)
675 {
676 const std::string abcFileName = HPROF_TEST_ABC_FILES_DIR"heapdump.abc";
677
678 bool result = JSNApi::Execute(ecmaVm_, abcFileName, "heapdump");
679 EXPECT_TRUE(result);
680
681 HeapDumpTestHelper tester(ecmaVm_);
682 tester.GenerateSnapShot("testFunctionUrl.heapsnapshot");
683
684 // match function url
685 std::string line;
686 std::ifstream inputStream("testFunctionUrl.heapsnapshot");
687 bool strMatched = false;
688 bool funcTempMatched = false;
689 while (getline(inputStream, line)) {
690 if (strMatched && funcTempMatched) {
691 break;
692 }
693 if (line == "\"heapdump greet(line:98)\",") {
694 strMatched = true;
695 continue;
696 }
697 if (line == "\"ArkInternalFunctionTemplate\",") {
698 funcTempMatched = true;
699 continue;
700 }
701 }
702 ASSERT_TRUE(strMatched);
703 ASSERT_TRUE(funcTempMatched);
704 }
705
HWTEST_F_L0(HeapDumpTest,DISABLED_TestAllocationMassiveMoveNode)706 HWTEST_F_L0(HeapDumpTest, DISABLED_TestAllocationMassiveMoveNode)
707 {
708 const std::string abcFileName = HPROF_TEST_ABC_FILES_DIR"allocation.abc";
709 HeapProfilerInterface *heapProfile = HeapProfilerInterface::GetInstance(ecmaVm_);
710
711 // start allocation
712 bool start = heapProfile->StartHeapTracking(50);
713 EXPECT_TRUE(start);
714
715 auto currentTime = std::chrono::system_clock::now();
716 auto currentTimeBeforeMs =
717 std::chrono::time_point_cast<std::chrono::milliseconds>(currentTime).time_since_epoch().count();
718
719 bool result = JSNApi::Execute(ecmaVm_, abcFileName, "allocation");
720
721 currentTime = std::chrono::system_clock::now();
722 auto currentTimeAfterMs =
723 std::chrono::time_point_cast<std::chrono::milliseconds>(currentTime).time_since_epoch().count();
724 EXPECT_TRUE(result);
725
726 std::string fileName = "test.allocationtime";
727 fstream outputString(fileName, std::ios::out);
728 outputString.close();
729 outputString.clear();
730
731 // stop allocation
732 FileStream stream(fileName.c_str());
733 bool stop = heapProfile->StopHeapTracking(&stream, nullptr);
734 EXPECT_TRUE(stop);
735 HeapProfilerInterface::Destroy(ecmaVm_);
736
737 auto timeSpent = currentTimeAfterMs - currentTimeBeforeMs;
738 long long int limitedTimeMs = 30000;
739 ASSERT_TRUE(timeSpent < limitedTimeMs);
740 }
741
HWTEST_F_L0(HeapDumpTest,TestHeapDumpGenerateNodeName1)742 HWTEST_F_L0(HeapDumpTest, TestHeapDumpGenerateNodeName1)
743 {
744 JSHandle<GlobalEnv> env = thread_->GetEcmaVM()->GetGlobalEnv();
745 ObjectFactory *factory = ecmaVm_->GetFactory();
746 HeapDumpTestHelper tester(ecmaVm_);
747
748 // TAGGED_ARRAY
749 factory->NewTaggedArray(10);
750 // LEXICAL_ENV
751 factory->NewLexicalEnv(10);
752 // CONSTANT_POOL
753 factory->NewConstantPool(10);
754 // PROFILE_TYPE_INFO
755 factory->NewProfileTypeInfo(10);
756 // TAGGED_DICTIONARY
757 factory->NewDictionaryArray(10);
758 // AOT_LITERAL_INFO
759 factory->NewAOTLiteralInfo(10);
760 // VTABLE
761 factory->NewVTable(10);
762 // COW_TAGGED_ARRAY
763 factory->NewCOWTaggedArray(10);
764 // HCLASS
765 JSHandle<JSTaggedValue> proto = env->GetFunctionPrototype();
766 factory->NewEcmaHClass(JSHClass::SIZE, JSType::HCLASS, proto);
767 // LINKED_NODE
768 JSHandle<LinkedNode> linkedNode(thread_, JSTaggedValue::Hole());
769 factory->NewLinkedNode(1, JSHandle<JSTaggedValue>(thread_, JSTaggedValue::Hole()),
770 JSHandle<JSTaggedValue>(thread_, JSTaggedValue::Hole()), linkedNode);
771 // JS_NATIVE_POINTER
772 auto newData = ecmaVm_->GetNativeAreaAllocator()->AllocateBuffer(8);
773 factory->NewJSNativePointer(newData);
774
775 tester.GenerateSnapShot("testGenerateNodeName_1.heapsnapshot");
776 ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_1.heapsnapshot", "\"ArkInternalArray["));
777 ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_1.heapsnapshot", "\"LexicalEnv["));
778 ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_1.heapsnapshot", "\"ArkInternalConstantPool["));
779 ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_1.heapsnapshot", "\"ArkInternalProfileTypeInfo["));
780 ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_1.heapsnapshot", "\"ArkInternalDict["));
781 ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_1.heapsnapshot", "\"ArkInternalAOTLiteralInfo["));
782 ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_1.heapsnapshot", "\"ArkInternalVTable["));
783 ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_1.heapsnapshot", "\"ArkInternalCOWArray["));
784 ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_1.heapsnapshot", "\"HiddenClass(NonMovable)"));
785 ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_1.heapsnapshot", "\"LinkedNode\""));
786 ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_1.heapsnapshot", "\"JSNativePointer\""));
787 // Test Not Found
788 ASSERT_TRUE(!tester.MatchHeapDumpString("testGenerateNodeName_1.heapsnapshot", "*#@failed case"));
789 }
790
HWTEST_F_L0(HeapDumpTest,TestHeapDumpGenerateNodeName2)791 HWTEST_F_L0(HeapDumpTest, TestHeapDumpGenerateNodeName2)
792 {
793 ObjectFactory *factory = ecmaVm_->GetFactory();
794 HeapDumpTestHelper tester(ecmaVm_);
795
796 // JS_ERROR
797 JSHandle<EcmaString> handleMessage(thread_, EcmaStringAccessor::CreateEmptyString(ecmaVm_));
798 factory->NewJSError(ErrorType::ERROR, handleMessage);
799 // JS_EVAL_ERROR
800 factory->NewJSError(ErrorType::EVAL_ERROR, handleMessage);
801 // JS_RANGE_ERROR
802 factory->NewJSError(ErrorType::RANGE_ERROR, handleMessage);
803 // JS_TYPE_ERROR
804 factory->NewJSError(ErrorType::TYPE_ERROR, handleMessage);
805 // JS_AGGREGATE_ERROR
806 factory->NewJSAggregateError();
807 // JS_REFERENCE_ERROR
808 factory->NewJSError(ErrorType::REFERENCE_ERROR, handleMessage);
809 // JS_URI_ERROR
810 factory->NewJSError(ErrorType::URI_ERROR, handleMessage);
811 // JS_SYNTAX_ERROR
812 factory->NewJSError(ErrorType::SYNTAX_ERROR, handleMessage);
813 // JS_OOM_ERROR
814 factory->NewJSError(ErrorType::OOM_ERROR, handleMessage);
815 // JS_TERMINATION_ERROR
816 factory->NewJSError(ErrorType::TERMINATION_ERROR, handleMessage);
817
818 tester.GenerateSnapShot("testGenerateNodeName_2.heapsnapshot");
819 ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_2.heapsnapshot", "\"Error\""));
820 ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_2.heapsnapshot", "\"Eval Error\""));
821 ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_2.heapsnapshot", "\"Range Error\""));
822 ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_2.heapsnapshot", "\"Type Error\""));
823 ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_2.heapsnapshot", "\"Aggregate Error\""));
824 ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_2.heapsnapshot", "\"Reference Error\""));
825 ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_2.heapsnapshot", "\"Uri Error\""));
826 ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_2.heapsnapshot", "\"Syntax Error\""));
827 ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_2.heapsnapshot", "\"OutOfMemory Error\""));
828 ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_2.heapsnapshot", "\"Termination Error\""));
829 }
830
HWTEST_F_L0(HeapDumpTest,TestHeapDumpGenerateNodeName3)831 HWTEST_F_L0(HeapDumpTest, TestHeapDumpGenerateNodeName3)
832 {
833 HeapDumpTestHelper tester(ecmaVm_);
834
835 // JS_INT8_ARRAY
836 tester.CreateNumberTypedArray(JSType::JS_INT8_ARRAY);
837 // JS_UINT8_ARRAY
838 tester.CreateNumberTypedArray(JSType::JS_UINT8_ARRAY);
839 // JS_UINT8_CLAMPED_ARRAY
840 tester.CreateNumberTypedArray(JSType::JS_UINT8_CLAMPED_ARRAY);
841 // JS_INT16_ARRAY
842 tester.CreateNumberTypedArray(JSType::JS_INT16_ARRAY);
843 // JS_UINT16_ARRAY
844 tester.CreateNumberTypedArray(JSType::JS_UINT16_ARRAY);
845 // JS_INT32_ARRAY
846 tester.CreateNumberTypedArray(JSType::JS_INT32_ARRAY);
847 // JS_UINT32_ARRAY
848 tester.CreateNumberTypedArray(JSType::JS_UINT32_ARRAY);
849 // JS_FLOAT32_ARRAY
850 tester.CreateNumberTypedArray(JSType::JS_FLOAT32_ARRAY);
851 // JS_FLOAT64_ARRAY
852 tester.CreateNumberTypedArray(JSType::JS_FLOAT64_ARRAY);
853 // JS_BIGINT64_ARRAY
854 tester.CreateNumberTypedArray(JSType::JS_BIGINT64_ARRAY);
855 // JS_BIGUINT64_ARRAY
856 tester.CreateNumberTypedArray(JSType::JS_BIGUINT64_ARRAY);
857
858 tester.GenerateSnapShot("testGenerateNodeName_3.heapsnapshot");
859 ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_3.heapsnapshot", "\"Int8 Array\""));
860 ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_3.heapsnapshot", "\"Uint8 Array\""));
861 ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_3.heapsnapshot", "\"Uint8 Clamped Array\""));
862 ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_3.heapsnapshot", "\"Int16 Array\""));
863 ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_3.heapsnapshot", "\"Uint16 Array\""));
864 ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_3.heapsnapshot", "\"Int32 Array\""));
865 ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_3.heapsnapshot", "\"Uint32 Array\""));
866 ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_3.heapsnapshot", "\"Float32 Array\""));
867 ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_3.heapsnapshot", "\"Float64 Array\""));
868 ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_3.heapsnapshot", "\"BigInt64 Array\""));
869 ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_3.heapsnapshot", "\"BigUint64 Array\""));
870 }
871
HWTEST_F_L0(HeapDumpTest,TestHeapDumpGenerateNodeName4)872 HWTEST_F_L0(HeapDumpTest, TestHeapDumpGenerateNodeName4)
873 {
874 ObjectFactory *factory = ecmaVm_->GetFactory();
875 HeapDumpTestHelper tester(ecmaVm_);
876
877 JSHandle<JSTaggedValue> proto = ecmaVm_->GetGlobalEnv()->GetFunctionPrototype();
878 // JS_SET
879 tester.NewJSSet();
880 // JS_SHARED_SET
881 tester.NewJSSharedSet();
882 // JS_MAP
883 tester.NewJSMap();
884 // JS_SHARED_MAP
885 tester.NewJSSharedMap();
886 // JS_WEAK_SET
887 tester.NewJSWeakSet();
888 // JS_WEAK_MAP
889 tester.NewJSWeakMap();
890 // JS_ARRAY
891 factory->NewJSArray();
892 // JS_TYPED_ARRAY
893 tester.NewObject(JSTypedArray::SIZE, JSType::JS_TYPED_ARRAY, proto);
894 tester.GenerateSnapShot("testGenerateNodeName_4.heapsnapshot");
895
896 ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_4.heapsnapshot", "\"Set\""));
897 ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_4.heapsnapshot", "\"SharedSet\""));
898 ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_4.heapsnapshot", "\"Map\""));
899 ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_4.heapsnapshot", "\"SharedMap\""));
900 ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_4.heapsnapshot", "\"WeakSet\""));
901 ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_4.heapsnapshot", "\"WeakMap\""));
902 ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_4.heapsnapshot", "\"JSArray\""));
903 ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_4.heapsnapshot", "\"Typed Array\""));
904 }
905
HWTEST_F_L0(HeapDumpTest,TestHeapDumpGenerateNodeName5)906 HWTEST_F_L0(HeapDumpTest, TestHeapDumpGenerateNodeName5)
907 {
908 ObjectFactory *factory = ecmaVm_->GetFactory();
909 HeapDumpTestHelper tester(ecmaVm_);
910
911 JSHandle<JSTaggedValue> proto = ecmaVm_->GetGlobalEnv()->GetFunctionPrototype();
912 // JS_REG_EXP
913 tester.NewObject(JSRegExp::SIZE, JSType::JS_REG_EXP, proto);
914 // JS_DATE
915 tester.NewObject(JSDate::SIZE, JSType::JS_DATE, proto);
916 // JS_ARGUMENTS
917 factory->NewJSArguments();
918 // JS_PROXY
919 tester.NewJSProxy();
920 // JS_PRIMITIVE_REF
921 tester.NewObject(JSPrimitiveRef::SIZE, JSType::JS_PRIMITIVE_REF, proto);
922 // JS_DATA_VIEW
923 factory->NewJSDataView(factory->NewJSArrayBuffer(10), 5, 5);
924
925 tester.GenerateSnapShot("testGenerateNodeName_5.heapsnapshot");
926 ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_5.heapsnapshot", "\"Regexp\""));
927 ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_5.heapsnapshot", "\"Date\""));
928 ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_5.heapsnapshot", "\"Arguments\""));
929 ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_5.heapsnapshot", "\"Proxy\""));
930 ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_5.heapsnapshot", "\"Primitive\""));
931 ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_5.heapsnapshot", "\"DataView\""));
932 }
933
HWTEST_F_L0(HeapDumpTest,TestHeapDumpGenerateNodeName6)934 HWTEST_F_L0(HeapDumpTest, TestHeapDumpGenerateNodeName6)
935 {
936 ObjectFactory *factory = ecmaVm_->GetFactory();
937 HeapDumpTestHelper tester(ecmaVm_);
938
939 // JS_FORIN_ITERATOR
940 tester.NewJSForInIterator();
941 // JS_MAP_ITERATOR
942 factory->NewJSMapIterator(tester.NewJSMap(), IterationKind::KEY);
943 // JS_SHARED_MAP_ITERATOR
944 factory->NewJSMapIterator(tester.NewJSSharedMap(), IterationKind::KEY);
945 // JS_SET_ITERATOR
946 factory->NewJSSetIterator(tester.NewJSSet(), IterationKind::KEY);
947 // JS_SHARED_SET_ITERATOR
948 factory->NewJSSetIterator(tester.NewJSSharedSet(), IterationKind::KEY);
949 // JS_REG_EXP_ITERATOR
950 tester.NewJSRegExpIterator();
951 // JS_ARRAY_ITERATOR
952 factory->NewJSArrayIterator(JSHandle<JSObject>::Cast(factory->NewJSArray()), IterationKind::KEY);
953 // JS_STRING_ITERATOR
954 JSStringIterator::CreateStringIterator(thread_, factory->GetEmptyString());
955
956 tester.GenerateSnapShot("testGenerateNodeName_6.heapsnapshot");
957 ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_6.heapsnapshot", "\"ForinInterator\""));
958 ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_6.heapsnapshot", "\"MapIterator\""));
959 ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_6.heapsnapshot", "\"SharedMapIterator\""));
960 ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_6.heapsnapshot", "\"SetIterator\""));
961 ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_6.heapsnapshot", "\"SharedSetIterator\""));
962 ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_6.heapsnapshot", "\"RegExpIterator\""));
963 ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_6.heapsnapshot", "\"ArrayIterator\""));
964 ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_6.heapsnapshot", "\"StringIterator\""));
965 }
966
HWTEST_F_L0(HeapDumpTest,TestHeapDumpGenerateNodeName7)967 HWTEST_F_L0(HeapDumpTest, TestHeapDumpGenerateNodeName7)
968 {
969 ObjectFactory *factory = ecmaVm_->GetFactory();
970 HeapDumpTestHelper tester(ecmaVm_);
971 // JS_ARRAY_BUFFER
972 factory->NewJSArrayBuffer(10);
973 // JS_SHARED_ARRAY_BUFFER
974 factory->NewJSSharedArrayBuffer(10);
975 // PROMISE_REACTIONS
976 factory->NewPromiseReaction();
977 // PROMISE_CAPABILITY
978 factory->NewPromiseCapability();
979 // PROMISE_ITERATOR_RECORD
980 tester.NewPromiseIteratorRecord();
981 // PROMISE_RECORD
982 factory->NewPromiseRecord();
983 // RESOLVING_FUNCTIONS_RECORD
984 factory->NewResolvingFunctionsRecord();
985 // JS_PROMISE
986 JSHandle<JSTaggedValue> proto = ecmaVm_->GetGlobalEnv()->GetFunctionPrototype();
987 tester.NewObject(JSPromise::SIZE, JSType::JS_PROMISE, proto);
988 // ASYNC_GENERATOR_REQUEST
989 factory->NewAsyncGeneratorRequest();
990
991 tester.GenerateSnapShot("testGenerateNodeName_7.heapsnapshot");
992 ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_7.heapsnapshot", "\"ArrayBuffer\""));
993 ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_7.heapsnapshot", "\"SharedArrayBuffer\""));
994 ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_7.heapsnapshot", "\"PromiseReaction\""));
995 ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_7.heapsnapshot", "\"PromiseCapability\""));
996 ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_7.heapsnapshot", "\"PromiseIteratorRecord\""));
997 ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_7.heapsnapshot", "\"PromiseRecord\""));
998 ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_7.heapsnapshot", "\"ResolvingFunctionsRecord\""));
999 ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_7.heapsnapshot", "\"Promise\""));
1000 ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_7.heapsnapshot", "\"AsyncGeneratorRequest\""));
1001 }
1002
HWTEST_F_L0(HeapDumpTest,TestHeapDumpGenerateNodeName8)1003 HWTEST_F_L0(HeapDumpTest, TestHeapDumpGenerateNodeName8)
1004 {
1005 auto factory = ecmaVm_->GetFactory();
1006 HeapDumpTestHelper tester(ecmaVm_);
1007 // JS_API_ARRAY_LIST
1008 auto jsAPIArrayList = tester.NewJSAPIArrayList();
1009 // JS_API_ARRAYLIST_ITERATOR
1010 factory->NewJSAPIArrayListIterator(jsAPIArrayList);
1011 // JS_API_HASH_MAP
1012 auto jsAPIHashMap = tester.NewJSAPIHashMap();
1013 // JS_API_HASHMAP_ITERATOR
1014 factory->NewJSAPIHashMapIterator(jsAPIHashMap, IterationKind::KEY);
1015 // JS_API_HASH_SET
1016 auto jsAPIHashSet = tester.NewJSAPIHashSet();
1017 // JS_API_HASHSET_ITERATOR
1018 factory->NewJSAPIHashSetIterator(jsAPIHashSet, IterationKind::KEY);
1019 // JS_API_LIGHT_WEIGHT_MAP
1020 auto jsAPILightWeightMap = tester.NewJSAPILightWeightMap();
1021 // JS_API_LIGHT_WEIGHT_MAP_ITERATOR
1022 factory->NewJSAPILightWeightMapIterator(jsAPILightWeightMap, IterationKind::KEY);
1023 // JS_API_LIGHT_WEIGHT_SET
1024 auto jsAPILightWeightSet = tester.NewJSAPILightWeightSet();
1025 // JS_API_LIGHT_WEIGHT_SET_ITERATOR
1026 factory->NewJSAPILightWeightSetIterator(jsAPILightWeightSet, IterationKind::KEY);
1027
1028 tester.GenerateSnapShot("testGenerateNodeName_8.heapsnapshot");
1029 ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_8.heapsnapshot", "\"ArrayList\""));
1030 ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_8.heapsnapshot", "\"ArrayListIterator\""));
1031 ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_8.heapsnapshot", "\"HashMap\""));
1032 ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_8.heapsnapshot", "\"HashSet\""));
1033 ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_8.heapsnapshot", "\"HashMapIterator\""));
1034 ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_8.heapsnapshot", "\"HashSetIterator\""));
1035 ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_8.heapsnapshot", "\"LightWeightMap\""));
1036 ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_8.heapsnapshot", "\"LightWeightMapIterator\""));
1037 ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_8.heapsnapshot", "\"LightWeightSet\""));
1038 ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_8.heapsnapshot", "\"LightWeightSetIterator\""));
1039 }
1040
HWTEST_F_L0(HeapDumpTest,TestHeapDumpGenerateNodeName9)1041 HWTEST_F_L0(HeapDumpTest, TestHeapDumpGenerateNodeName9)
1042 {
1043 auto factory = ecmaVm_->GetFactory();
1044 HeapDumpTestHelper tester(ecmaVm_);
1045 // JS_API_TREE_MAP
1046 auto jsAPITreeMap = tester.NewJSAPITreeMap();
1047 // JS_API_TREEMAP_ITERATOR
1048 factory->NewJSAPITreeMapIterator(jsAPITreeMap, IterationKind::KEY);
1049 // JS_API_TREE_SET
1050 auto jsAPITreeSet = tester.NewJSAPITreeSet();
1051 // JS_API_TREESET_ITERATOR
1052 factory->NewJSAPITreeSetIterator(jsAPITreeSet, IterationKind::KEY);
1053 // JS_API_VECTOR
1054 auto jsAPIVector = tester.NewJSAPIVector();
1055 // JS_API_VECTOR_ITERATOR
1056 factory->NewJSAPIVectorIterator(jsAPIVector);
1057 // JS_API_QUEUE
1058 auto jsAPIQueue = tester.NewJSAPIQueue();
1059 // JS_API_QUEUE_ITERATOR
1060 factory->NewJSAPIQueueIterator(jsAPIQueue);
1061 // JS_API_DEQUE
1062 auto jsAPIDeque = tester.NewJSAPIDeque();
1063 // JS_API_DEQUE_ITERATOR
1064 factory->NewJSAPIDequeIterator(jsAPIDeque);
1065 // JS_API_STACK
1066 auto jsAPIStack = tester.NewJSAPIStack();
1067 // JS_API_STACK_ITERATOR
1068 factory->NewJSAPIStackIterator(jsAPIStack);
1069 // JS_API_LIST
1070 tester.NewJSAPIList();
1071 // JS_API_LINKED_LIST
1072 tester.NewJSAPILinkedList();
1073 // JS_API_PLAIN_ARRAY
1074 auto jsAPIPlainArray = tester.NewJSAPIPlainArray();
1075 // JS_API_PLAIN_ARRAY_ITERATOR
1076 factory->NewJSAPIPlainArrayIterator(jsAPIPlainArray, IterationKind::KEY);
1077
1078 tester.GenerateSnapShot("testGenerateNodeName_9.heapsnapshot");
1079 ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_9.heapsnapshot", "\"TreeMap\""));
1080 ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_9.heapsnapshot", "\"TreeMapIterator\""));
1081 ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_9.heapsnapshot", "\"TreeSet\""));
1082 ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_9.heapsnapshot", "\"TreeSetIterator\""));
1083 ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_9.heapsnapshot", "\"Vector\""));
1084 ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_9.heapsnapshot", "\"VectorIterator\""));
1085 ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_9.heapsnapshot", "\"Queue\""));
1086 ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_9.heapsnapshot", "\"QueueIterator\""));
1087 ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_9.heapsnapshot", "\"Deque\""));
1088 ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_9.heapsnapshot", "\"DequeIterator\""));
1089 ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_9.heapsnapshot", "\"Stack\""));
1090 ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_9.heapsnapshot", "\"StackIterator\""));
1091 ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_9.heapsnapshot", "\"List\""));
1092 ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_9.heapsnapshot", "\"LinkedList\""));
1093 ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_9.heapsnapshot", "\"PlainArray\""));
1094 ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_9.heapsnapshot", "\"PlainArrayIterator\""));
1095 }
1096
1097 #ifdef PANDA_TARGET_ARM32
HWTEST_F_L0(HeapDumpTest,DISABLED_TestHeapDumpBinaryDump)1098 HWTEST_F_L0(HeapDumpTest, DISABLED_TestHeapDumpBinaryDump)
1099 #else
1100 HWTEST_F_L0(HeapDumpTest, TestHeapDumpBinaryDump)
1101 #endif
1102 {
1103 ObjectFactory *factory = ecmaVm_->GetFactory();
1104 HeapDumpTestHelper tester(ecmaVm_);
1105 // PROMISE_ITERATOR_RECORD
1106 tester.NewPromiseIteratorRecord();
1107 // PROMISE_RECORD
1108 factory->NewPromiseRecord();
1109 // JS_ARRAY_BUFFER
1110 factory->NewJSArrayBuffer(10);
1111 // JS_SHARED_ARRAY_BUFFER
1112 factory->NewJSSharedArrayBuffer(10);
1113 // PROMISE_REACTIONS
1114 factory->NewPromiseReaction();
1115 // PROMISE_CAPABILITY
1116 factory->NewPromiseCapability();
1117 // RESOLVING_FUNCTIONS_RECORD
1118 factory->NewResolvingFunctionsRecord();
1119 // JS_PROMISE
1120 JSHandle<JSTaggedValue> proto = ecmaVm_->GetGlobalEnv()->GetFunctionPrototype();
1121 tester.NewObject(JSPromise::SIZE, JSType::JS_PROMISE, proto);
1122 // ASYNC_GENERATOR_REQUEST
1123 factory->NewAsyncGeneratorRequest();
1124 // JS_WEAK_SET
1125 tester.NewJSWeakSet();
1126 // JS_WEAK_MAP
1127 tester.NewJSWeakMap();
1128 std::string rawHeapPath("test_binary_dump.raw");
1129 bool ret = tester.GenerateRawHeapSnashot(rawHeapPath);
1130 ASSERT_TRUE(ret);
1131 std::ifstream file(rawHeapPath, std::ios::binary);
1132 std::string content((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
1133 ASSERT_TRUE(content.size() > 0);
1134 auto u64Ptr = reinterpret_cast<const uint64_t *>(content.c_str());
1135 ASSERT_TRUE(u64Ptr[1] > 0);
1136 std::string snapshotPath("test_binary_dump.heapsnapshot");
1137 tester.DecodeRawHeapSnashot(rawHeapPath, snapshotPath);
1138 ASSERT_TRUE(tester.MatchHeapDumpString(snapshotPath, "\"SharedArrayBuffer\""));
1139 ASSERT_TRUE(tester.MatchHeapDumpString(snapshotPath, "\"WeakSet\""));
1140 ASSERT_TRUE(tester.MatchHeapDumpString(snapshotPath, "\"WeakMap\""));
1141 }
1142 }