• 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 #include <fcntl.h>
16 #include <unistd.h>
17 #include <chrono>
18 #include "ecmascript/base/number_helper.h"
19 #include "ecmascript/dfx/hprof/heap_snapshot.h"
20 #include "ecmascript/dfx/hprof/heap_profiler.h"
21 #include "ecmascript/dfx/hprof/heap_root_visitor.h"
22 #include "ecmascript/dfx/hprof/rawheap_translate/rawheap_translate.h"
23 #include "ecmascript/dfx/hprof/heap_marker.h"
24 #include "ecmascript/global_env.h"
25 #include "ecmascript/jspandafile/js_pandafile_manager.h"
26 #include "ecmascript/js_api/js_api_arraylist.h"
27 #include "ecmascript/js_api/js_api_arraylist_iterator.h"
28 #include "ecmascript/js_api/js_api_deque.h"
29 #include "ecmascript/js_api/js_api_hashmap.h"
30 #include "ecmascript/js_api/js_api_hashset.h"
31 #include "ecmascript/js_api/js_api_lightweightmap.h"
32 #include "ecmascript/js_api/js_api_lightweightset.h"
33 #include "ecmascript/js_api/js_api_linked_list.h"
34 #include "ecmascript/js_api/js_api_list.h"
35 #include "ecmascript/js_api/js_api_plain_array.h"
36 #include "ecmascript/js_api/js_api_queue.h"
37 #include "ecmascript/js_api/js_api_stack.h"
38 #include "ecmascript/js_api/js_api_tree_map.h"
39 #include "ecmascript/js_api/js_api_tree_set.h"
40 #include "ecmascript/js_api/js_api_vector.h"
41 #include "ecmascript/js_date.h"
42 #include "ecmascript/js_iterator.h"
43 #include "ecmascript/js_map.h"
44 #include "ecmascript/js_primitive_ref.h"
45 #include "ecmascript/js_promise.h"
46 #include "ecmascript/js_regexp.h"
47 #include "ecmascript/js_set.h"
48 #include "ecmascript/js_string_iterator.h"
49 #include "ecmascript/js_typed_array.h"
50 #include "ecmascript/js_weak_container.h"
51 #include "ecmascript/linked_hash_table.h"
52 #include "ecmascript/napi/include/jsnapi.h"
53 #include "ecmascript/shared_objects/js_shared_array.h"
54 #include "ecmascript/shared_objects/js_shared_map.h"
55 #include "ecmascript/shared_objects/js_shared_set.h"
56 #include "ecmascript/tagged_hash_array.h"
57 #include "ecmascript/tagged_tree.h"
58 #include "ecmascript/tests/test_helper.h"
59 
60 namespace panda::test {
61 using namespace panda::ecmascript;
62 using ErrorType = base::ErrorType;
63 
64 class HeapDumpTest : public testing::Test {
65 public:
SetUp()66     void SetUp() override
67     {
68         TestHelper::CreateEcmaVMWithScope(ecmaVm_, thread_, scope_);
69         ecmaVm_->SetEnableForceGC(false);
70     }
71 
TearDown()72     void TearDown() override
73     {
74         TestHelper::DestroyEcmaVMWithScope(ecmaVm_, scope_);
75     }
76 
77     EcmaVM *ecmaVm_ {nullptr};
78     EcmaHandleScope *scope_ {nullptr};
79     JSThread *thread_ {nullptr};
80 };
81 
82 class HeapDumpTestHelper {
83 public:
HeapDumpTestHelper(EcmaVM * vm)84     explicit HeapDumpTestHelper(EcmaVM *vm) : instance(vm) {}
85 
~HeapDumpTestHelper()86     ~HeapDumpTestHelper()
87     {
88         HeapProfilerInterface::Destroy(instance);
89     }
90 
GenerateSnapShot(const std::string & filePath)91     size_t GenerateSnapShot(const std::string &filePath)
92     {
93         // first generate this file of filePath if not exist,
94         // so the function `realpath` of FileStream can not failed on arm/arm64.
95         fstream outputString(filePath, std::ios::out);
96         outputString.close();
97         outputString.clear();
98         FileStream stream(filePath.c_str());
99         HeapProfilerInterface *heapProfile = HeapProfilerInterface::GetInstance(instance);
100         DumpSnapShotOption dumpOption;
101         dumpOption.dumpFormat = DumpFormat::JSON;
102         heapProfile->DumpHeapSnapshot(&stream, dumpOption);
103         return heapProfile->GetIdCount();
104     }
105 
GenerateRawHeapSnashot(const std::string & filePath,DumpSnapShotOption & dumpOption,Progress * progress=nullptr,std::function<void (uint8_t)> callback=[](uint8_t){})106     bool GenerateRawHeapSnashot(const std::string &filePath, DumpSnapShotOption &dumpOption,
107                                 Progress *progress = nullptr, std::function<void(uint8_t)> callback = [] (uint8_t) {})
108     {
109         HeapProfilerInterface *heapProfile = HeapProfilerInterface::GetInstance(instance);
110         dumpOption.dumpFormat = DumpFormat::BINARY;
111         dumpOption.isDumpOOM = true;
112         dumpOption.isFullGC = false;
113         fstream outputString(filePath, std::ios::out);
114         outputString.close();
115         outputString.clear();
116         int fd = open(filePath.c_str(), O_RDWR | O_CREAT);
117         FileDescriptorStream stream(fd);
118         auto ret = heapProfile->DumpHeapSnapshot(&stream, dumpOption, progress, callback);
119         stream.EndOfStream();
120         return ret;
121     }
122 
DecodeRawHeapObjectTableV1(std::string & filePath,CSet<JSTaggedType> & result)123     bool DecodeRawHeapObjectTableV1(std::string &filePath, CSet<JSTaggedType> &result)
124     {
125         uint64_t fileSize = rawheap_translate::FileReader::GetFileSize(filePath);
126         rawheap_translate::FileReader file;
127         rawheap_translate::RawHeapTranslateV1 translate(nullptr);
128 
129         if (!file.Initialize(filePath) || !translate.Parse(file, fileSize)) {
130             return false;
131         }
132 
133         for (auto &it : translate.nodesMap_) {
134             result.insert(it.first);
135         }
136         GTEST_LOG_(INFO) << "DecodeRawHeapObjectTable count " << translate.nodesMap_.size();
137         return true;
138     }
139 
CheckHashInNodeId(JSThread * thread,const std::vector<Reference> & refs,const std::string & filePath)140     bool CheckHashInNodeId(JSThread *thread, const std::vector<Reference> &refs, const std::string &filePath)
141     {
142         uint64_t fileSize = rawheap_translate::FileReader::GetFileSize(filePath);
143         rawheap_translate::FileReader file;
144         rawheap_translate::RawHeapTranslateV1 translate(nullptr);
145         if (!file.Initialize(filePath) || !translate.Parse(file, fileSize)) {
146             return false;
147         }
148 
149         int checkCnt = 0;
150         for (auto const &ref : refs) {
151             if (!ref.value_.IsJSObject()) {
152                 continue;
153             }
154 
155             auto it = translate.nodesMap_.find(ref.value_.GetRawData());
156             if (it == translate.nodesMap_.end()) {
157                 std::cout << "CheckHashInNodeId, missed object in rawheap." << std::endl;
158                 return false;
159             }
160 
161             ++checkCnt;
162             // 32: 32-bits means a half of uint64_t
163             if (JSObject::Cast(ref.value_)->GetHash(thread) != static_cast<int32_t>(it->second->nodeId >> 32)) {
164                 std::cout << "CheckHashInNodeId, hash value verification failed!" << std::endl;
165                 return false;
166             }
167         }
168 
169         if (checkCnt == 0) {
170             std::cout << "CheckHashInNodeId, no JSObject." << std::endl;
171             return false;
172         }
173         return true;
174     }
175 
DecodeRawHeapObjectTableV2(std::string & filePath,CSet<uint32_t> & result)176     bool DecodeRawHeapObjectTableV2(std::string &filePath, CSet<uint32_t> &result)
177     {
178         uint64_t fileSize = rawheap_translate::FileReader::GetFileSize(filePath);
179         rawheap_translate::FileReader file;
180         rawheap_translate::RawHeapTranslateV2 translate(nullptr);
181 
182         if (!file.Initialize(filePath) || !translate.Parse(file, fileSize)) {
183             return false;
184         }
185 
186         for (auto &it : translate.nodesMap_) {
187             result.insert(it.first);
188         }
189         GTEST_LOG_(INFO) << "DecodeRawHeapObjectTable count " << translate.nodesMap_.size();
190         return true;
191     }
192 
AddMetaDataJsonToRawheap(const std::string & rawFilePath)193     bool AddMetaDataJsonToRawheap(const std::string &rawFilePath)
194     {
195         uint32_t rawheapSize = rawheap_translate::FileReader::GetFileSize(rawFilePath);
196         uint32_t metadataSize = rawheap_translate::FileReader::GetFileSize(HPROF_TEST_METADATA_JSON_DIR"metadata.json");
197         if (rawheapSize == 0 || metadataSize == 0) {
198             std::cout << "rawheapSize=" << rawheapSize << ", metadataSize=" << metadataSize << std::endl;
199             return false;
200         }
201 
202         std::ofstream rawheapFile(rawFilePath, std::ios::app | std::ios::binary);
203         std::ifstream metadataFile(HPROF_TEST_METADATA_JSON_DIR"metadata.json", std::ios::binary);
204         if (!rawheapFile.is_open() || !metadataFile.is_open()) {
205             return false;
206         }
207 
208         uint32_t bufSize = metadataSize + sizeof(uint64_t);
209         char *buf = new char[bufSize];
210         if (!metadataFile.read(buf, metadataSize)) {
211             delete[] buf;
212             return false;
213         }
214 
215         *reinterpret_cast<uint32_t *>(buf + bufSize - sizeof(uint64_t)) = rawheapSize;
216         *reinterpret_cast<uint32_t *>(buf + bufSize - sizeof(uint32_t)) = metadataSize;
217         rawheapFile.write(buf, bufSize);
218 
219         rawheapFile.close();
220         metadataFile.close();
221         delete[] buf;
222         return true;
223     }
224 
DecodeRawheap(const std::string & rawFilePath,const std::string & outputPath)225     bool DecodeRawheap(const std::string &rawFilePath, const std::string &outputPath)
226     {
227         return rawheap_translate::RawHeap::TranslateRawheap(rawFilePath, outputPath);
228     }
229 
MatchHeapObjectReferencesV1(const std::vector<Reference> & refs,const CSet<JSTaggedType> & dumpObjects)230     bool MatchHeapObjectReferencesV1(const std::vector<Reference> &refs, const CSet<JSTaggedType> &dumpObjects)
231     {
232         for (auto &ref : refs) {
233             if (ref.value_.IsHeapObject() && dumpObjects.find(ref.value_.GetRawData()) == dumpObjects.end()) {
234                 return false;
235             }
236         }
237         return true;
238     }
239 
MatchHeapObjectReferencesV2(const std::vector<Reference> & refs,const CSet<uint32_t> & dumpObjects)240     bool MatchHeapObjectReferencesV2(const std::vector<Reference> &refs, const CSet<uint32_t> &dumpObjects)
241     {
242         for (auto &ref : refs) {
243             if (ref.value_.IsHeapObject() &&
244                 dumpObjects.find(static_cast<uint32_t>(ref.value_.GetRawData())) == dumpObjects.end()) {
245                 return false;
246             }
247         }
248         return true;
249     }
250 
MatchHeapDumpString(const std::string & filePath,std::string targetStr)251     bool MatchHeapDumpString(const std::string &filePath, std::string targetStr)
252     {
253         std::string line;
254         std::ifstream inputStream(filePath);
255         std::size_t lineNum = 0;
256         while (getline(inputStream, line)) {
257             lineNum = line.find(targetStr);
258             if (lineNum != line.npos) {
259                 return true;
260             }
261         }
262         GTEST_LOG_(ERROR) << "file: " << filePath.c_str() << ", target:" << targetStr.c_str()
263                           << ", line:" << std::to_string(lineNum) <<"not found";
264         return false;  // Lost the Line
265     }
266 
CreateNumberTypedArray(JSType jsType)267     JSHandle<JSTypedArray> CreateNumberTypedArray(JSType jsType)
268     {
269         JSHandle<GlobalEnv> env = instance->GetGlobalEnv();
270         ObjectFactory *factory = instance->GetFactory();
271         JSHandle<JSTaggedValue> handleTagValFunc = env->GetInt8ArrayFunction();
272         switch (jsType) {
273             case JSType::JS_INT8_ARRAY:
274                 break;
275             case JSType::JS_UINT8_ARRAY:
276                 handleTagValFunc = env->GetUint8ArrayFunction();
277                 break;
278             case JSType::JS_UINT8_CLAMPED_ARRAY:
279                 handleTagValFunc = env->GetUint8ClampedArrayFunction();
280                 break;
281             case JSType::JS_INT16_ARRAY:
282                 handleTagValFunc = env->GetInt16ArrayFunction();
283                 break;
284             case JSType::JS_UINT16_ARRAY:
285                 handleTagValFunc = env->GetUint16ArrayFunction();
286                 break;
287             case JSType::JS_INT32_ARRAY:
288                 handleTagValFunc = env->GetInt32ArrayFunction();
289                 break;
290             case JSType::JS_UINT32_ARRAY:
291                 handleTagValFunc = env->GetUint32ArrayFunction();
292                 break;
293             case JSType::JS_FLOAT32_ARRAY:
294                 handleTagValFunc = env->GetFloat32ArrayFunction();
295                 break;
296             case JSType::JS_FLOAT64_ARRAY:
297                 handleTagValFunc = env->GetFloat64ArrayFunction();
298                 break;
299             case JSType::JS_BIGINT64_ARRAY:
300                 handleTagValFunc = env->GetBigInt64ArrayFunction();
301                 break;
302             case JSType::JS_BIGUINT64_ARRAY:
303                 handleTagValFunc = env->GetBigUint64ArrayFunction();
304                 break;
305             default:
306                 ASSERT_PRINT(false, "wrong jsType used in CreateNumberTypedArray function");
307                 break;
308         }
309         return JSHandle<JSTypedArray>::Cast(
310             factory->NewJSObjectByConstructor(JSHandle<JSFunction>::Cast(handleTagValFunc), handleTagValFunc));
311     }
312 
CreateNumberSharedTypedArray(JSType jsType)313     JSHandle<JSSharedTypedArray> CreateNumberSharedTypedArray(JSType jsType)
314     {
315         JSHandle<GlobalEnv> env = instance->GetGlobalEnv();
316         ObjectFactory *factory = instance->GetFactory();
317         JSHandle<JSTaggedValue> handleTagValFunc = env->GetSharedInt8ArrayFunction();
318         switch (jsType) {
319             case JSType::JS_SHARED_INT8_ARRAY:
320                 break;
321             case JSType::JS_SHARED_UINT8_ARRAY:
322                 handleTagValFunc = env->GetSharedUint8ArrayFunction();
323                 break;
324             case JSType::JS_SHARED_UINT8_CLAMPED_ARRAY:
325                 handleTagValFunc = env->GetSharedUint8ClampedArrayFunction();
326                 break;
327             case JSType::JS_SHARED_INT16_ARRAY:
328                 handleTagValFunc = env->GetSharedInt16ArrayFunction();
329                 break;
330             case JSType::JS_SHARED_UINT16_ARRAY:
331                 handleTagValFunc = env->GetSharedUint16ArrayFunction();
332                 break;
333             case JSType::JS_SHARED_INT32_ARRAY:
334                 handleTagValFunc = env->GetSharedInt32ArrayFunction();
335                 break;
336             case JSType::JS_SHARED_UINT32_ARRAY:
337                 handleTagValFunc = env->GetSharedUint32ArrayFunction();
338                 break;
339             case JSType::JS_SHARED_FLOAT32_ARRAY:
340                 handleTagValFunc = env->GetSharedFloat32ArrayFunction();
341                 break;
342             case JSType::JS_SHARED_FLOAT64_ARRAY:
343                 handleTagValFunc = env->GetSharedFloat64ArrayFunction();
344                 break;
345             case JSType::JS_SHARED_BIGINT64_ARRAY:
346                 handleTagValFunc = env->GetSharedBigInt64ArrayFunction();
347                 break;
348             case JSType::JS_SHARED_BIGUINT64_ARRAY:
349                 handleTagValFunc = env->GetSharedBigUint64ArrayFunction();
350                 break;
351             default:
352                 ASSERT_PRINT(false, "wrong jsType used in CreateNumberTypedArray function");
353                 break;
354         }
355         return JSHandle<JSSharedTypedArray>::Cast(
356             factory->NewJSObjectByConstructor(JSHandle<JSFunction>::Cast(handleTagValFunc), handleTagValFunc));
357     }
358 
NewSharedTypedArray()359     JSHandle<TaggedArray> NewSharedTypedArray()
360     {
361         ObjectFactory *factory = instance->GetFactory();
362         JSThread *thread = instance->GetJSThread();
363         JSHandle<TaggedArray> array(factory->NewTaggedArray(11)); // 11: elements
364         // 0: JS_SHARED_INT8_ARRAY
365         array->Set(thread, 0, CreateNumberSharedTypedArray(JSType::JS_SHARED_INT8_ARRAY));
366         // 1: JS_SHARED_UINT8_ARRAY
367         array->Set(thread, 1, CreateNumberSharedTypedArray(JSType::JS_SHARED_UINT8_ARRAY));
368         // 2: JS_SHARED_UINT8_CLAMPED_ARRAY
369         array->Set(thread, 2, CreateNumberSharedTypedArray(JSType::JS_SHARED_UINT8_CLAMPED_ARRAY));
370         // 3: JS_SHARED_INT16_ARRAY
371         array->Set(thread, 3, CreateNumberSharedTypedArray(JSType::JS_SHARED_INT16_ARRAY));
372         // 4: JS_SHARED_UINT16_ARRAY
373         array->Set(thread, 4, CreateNumberSharedTypedArray(JSType::JS_SHARED_UINT16_ARRAY));
374         // 5: JS_SHARED_INT32_ARRAY
375         array->Set(thread, 5, CreateNumberSharedTypedArray(JSType::JS_SHARED_INT32_ARRAY));
376         // 6: JS_SHARED_UINT32_ARRAY
377         array->Set(thread, 6, CreateNumberSharedTypedArray(JSType::JS_SHARED_UINT32_ARRAY));
378         // 7: JS_SHARED_FLOAT32_ARRAY
379         array->Set(thread, 7, CreateNumberSharedTypedArray(JSType::JS_SHARED_FLOAT32_ARRAY));
380         // 8: JS_SHARED_FLOAT64_ARRAY
381         array->Set(thread, 8, CreateNumberSharedTypedArray(JSType::JS_SHARED_FLOAT64_ARRAY));
382         // 9: JS_SHARED_BIGINT64_ARRAY
383         array->Set(thread, 9, CreateNumberSharedTypedArray(JSType::JS_SHARED_BIGINT64_ARRAY));
384         // 10: JS_SHARED_BIGUINT64_ARRAY
385         array->Set(thread, 10, CreateNumberSharedTypedArray(JSType::JS_SHARED_BIGUINT64_ARRAY));
386         return array;
387     }
388 
NewObject(uint32_t size,JSType type,JSHandle<JSTaggedValue> proto)389     JSHandle<JSObject> NewObject(uint32_t size, JSType type, JSHandle<JSTaggedValue> proto)
390     {
391         ObjectFactory *factory = instance->GetFactory();
392         JSHandle<JSHClass> hclass = factory->NewEcmaHClass(size, type, proto);
393         return factory->NewJSObjectWithInit(hclass);
394     }
395 
NewSObject(uint32_t size,JSType type,JSHandle<JSTaggedValue> proto)396     JSHandle<JSObject> NewSObject(uint32_t size, JSType type, JSHandle<JSTaggedValue> proto)
397     {
398         ObjectFactory *factory = instance->GetFactory();
399         auto emptySLayout = instance->GetJSThread()->GlobalConstants()->GetHandledEmptySLayoutInfo();
400         JSHandle<JSHClass> hclass = factory->NewSEcmaHClass(size, 0, type, proto, emptySLayout);
401         return factory->NewJSObjectWithInit(hclass);
402     }
403 
404     // JS_SET
NewJSSet()405     JSHandle<JSSet> NewJSSet()
406     {
407         JSThread *thread = instance->GetJSThread();
408         JSHandle<JSTaggedValue> proto = instance->GetGlobalEnv()->GetFunctionPrototype();
409         JSHandle<JSObject> jsSetObject = NewObject(JSSet::SIZE, JSType::JS_SET, proto);
410         JSHandle<JSSet> jsSet = JSHandle<JSSet>::Cast(jsSetObject);
411         JSHandle<LinkedHashSet> linkedSet(LinkedHashSet::Create(thread));
412         jsSet->SetLinkedSet(thread, linkedSet);
413         return jsSet;
414     }
415 
416     // JS_SHARED_SET
NewJSSharedSet()417     JSHandle<JSSharedSet> NewJSSharedSet()
418     {
419         JSThread *thread = instance->GetJSThread();
420         JSHandle<JSTaggedValue> proto = instance->GetGlobalEnv()->GetSFunctionPrototype();
421         JSHandle<JSObject> jsSSetObject = NewSObject(JSSharedSet::SIZE, JSType::JS_SHARED_SET, proto);
422         JSHandle<JSSharedSet> jsSSet = JSHandle<JSSharedSet>::Cast(jsSSetObject);
423         JSHandle<LinkedHashSet> linkedSet(
424             LinkedHashSet::Create(thread, LinkedHashSet::MIN_CAPACITY, MemSpaceKind::SHARED));
425         jsSSet->SetLinkedSet(thread, linkedSet);
426         jsSSet->SetModRecord(0);
427         return jsSSet;
428     }
429 
430     // JS_MAP
NewJSMap()431     JSHandle<JSMap> NewJSMap()
432     {
433         JSThread *thread = instance->GetJSThread();
434         JSHandle<JSTaggedValue> proto = instance->GetGlobalEnv()->GetFunctionPrototype();
435         JSHandle<JSObject> jsMapObject = NewObject(JSMap::SIZE, JSType::JS_MAP, proto);
436         JSHandle<JSMap> jsMap = JSHandle<JSMap>::Cast(jsMapObject);
437         JSHandle<LinkedHashMap> linkedMap(LinkedHashMap::Create(thread));
438         jsMap->SetLinkedMap(thread, linkedMap);
439         return jsMap;
440     }
441 
442     // JS_SHARED_MAP
NewJSSharedMap()443     JSHandle<JSSharedMap> NewJSSharedMap()
444     {
445         JSThread *thread = instance->GetJSThread();
446         JSHandle<JSTaggedValue> proto = instance->GetGlobalEnv()->GetSFunctionPrototype();
447         JSHandle<JSObject> jsSMapObject = NewSObject(JSSharedMap::SIZE, JSType::JS_SHARED_MAP, proto);
448         JSHandle<JSSharedMap> jsSMap = JSHandle<JSSharedMap>::Cast(jsSMapObject);
449         JSHandle<LinkedHashMap> linkedMap(
450             LinkedHashMap::Create(thread, LinkedHashMap::MIN_CAPACITY, MemSpaceKind::SHARED));
451         jsSMap->SetLinkedMap(thread, linkedMap);
452         jsSMap->SetModRecord(0);
453         return jsSMap;
454     }
455 
456     //JS_WEAK_SET
NewJSWeakSet()457     JSHandle<JSWeakSet> NewJSWeakSet()
458     {
459         JSThread *thread = instance->GetJSThread();
460         JSHandle<JSTaggedValue> proto = instance->GetGlobalEnv()->GetFunctionPrototype();
461         JSHandle<JSObject> jsWeakSetObject = NewObject(JSWeakSet::SIZE, JSType::JS_WEAK_SET, proto);
462         JSHandle<JSWeakSet> jsWeakSet = JSHandle<JSWeakSet>::Cast(jsWeakSetObject);
463         JSHandle<LinkedHashSet> weakLinkedSet(LinkedHashSet::Create(thread));
464         jsWeakSet->SetLinkedSet(thread, weakLinkedSet);
465         return jsWeakSet;
466     }
467 
468     //JS_WEAK_MAP
NewJSWeakMap()469     JSHandle<JSWeakMap> NewJSWeakMap()
470     {
471         JSThread *thread = instance->GetJSThread();
472         JSHandle<JSTaggedValue> proto = instance->GetGlobalEnv()->GetFunctionPrototype();
473         JSHandle<JSObject> jsWeakMapObject = NewObject(JSWeakMap::SIZE, JSType::JS_WEAK_MAP, proto);
474         JSHandle<JSWeakMap> jsWeakMap = JSHandle<JSWeakMap>::Cast(jsWeakMapObject);
475         JSHandle<LinkedHashMap> weakLinkedMap(LinkedHashMap::Create(thread));
476         jsWeakMap->SetLinkedMap(thread, weakLinkedMap);
477         return jsWeakMap;
478     }
479 
480     // JS_PROXY
NewJSProxy()481     JSHandle<JSProxy> NewJSProxy()
482     {
483         JSThread *thread = instance->GetJSThread();
484         ObjectFactory *factory = instance->GetFactory();
485         JSFunction *newTarget = instance->GetGlobalEnv()->GetObjectFunction().GetObject<JSFunction>();
486         JSHandle<JSTaggedValue> newTargetHandle(thread, newTarget);
487         JSHandle<JSObject> jsObject =
488             factory->NewJSObjectByConstructor(JSHandle<JSFunction>(newTargetHandle), newTargetHandle);
489         JSHandle<JSTaggedValue> emptyObj(thread, jsObject.GetTaggedValue());
490         return factory->NewJSProxy(emptyObj, emptyObj);
491     }
492 
493     // JS_FORIN_ITERATOR
NewJSForInIterator()494     JSHandle<JSForInIterator> NewJSForInIterator()
495     {
496         JSThread *thread = instance->GetJSThread();
497         ObjectFactory *factory = instance->GetFactory();
498         JSHandle<JSTaggedValue> arrayEmpty(thread, factory->NewJSArray().GetTaggedValue());
499         JSHandle<JSTaggedValue> keys(thread, factory->EmptyArray().GetTaggedValue());
500         JSHandle<JSTaggedValue> hclass(thread, JSTaggedValue::Undefined());
501         return factory->NewJSForinIterator(arrayEmpty, keys, hclass, static_cast<uint32_t>(EnumCacheKind::NONE));
502     }
503 
504     // JS_REG_EXP_ITERATOR
NewJSRegExpIterator()505     JSHandle<JSRegExpIterator> NewJSRegExpIterator()
506     {
507         ObjectFactory *factory = instance->GetFactory();
508         JSHandle<JSTaggedValue> proto = instance->GetGlobalEnv()->GetFunctionPrototype();
509         JSHandle<EcmaString> emptyString = factory->GetEmptyString();
510         JSHandle<JSTaggedValue> jsRegExp(NewObject(JSRegExp::SIZE, JSType::JS_REG_EXP, proto));
511         return factory->NewJSRegExpIterator(jsRegExp, emptyString, false, false);
512     }
513 
514     // PROMISE_ITERATOR_RECORD
NewPromiseIteratorRecord()515     JSHandle<PromiseIteratorRecord> NewPromiseIteratorRecord()
516     {
517         JSThread *thread = instance->GetJSThread();
518         ObjectFactory *factory = instance->GetFactory();
519         JSFunction *newTarget = instance->GetGlobalEnv()->GetObjectFunction().GetObject<JSFunction>();
520         JSHandle<JSTaggedValue> newTargetHandle(thread, newTarget);
521         JSHandle<JSObject> jsObject =
522             factory->NewJSObjectByConstructor(JSHandle<JSFunction>(newTargetHandle), newTargetHandle);
523         JSHandle<JSTaggedValue> emptyObj(thread, jsObject.GetTaggedValue());
524         return factory->NewPromiseIteratorRecord(emptyObj, false);
525     }
526 
527     // JS_API_ARRAY_LIST
NewJSAPIArrayList()528     JSHandle<JSAPIArrayList> NewJSAPIArrayList()
529     {
530         JSHandle<JSTaggedValue> proto = instance->GetGlobalEnv()->GetFunctionPrototype();
531         JSHandle<JSObject> jsAPIArrayListObject = NewObject(JSAPIArrayList::SIZE, JSType::JS_API_ARRAY_LIST, proto);
532         JSHandle<JSAPIArrayList> jsAPIArrayList = JSHandle<JSAPIArrayList>::Cast(jsAPIArrayListObject);
533         JSThread *thread = instance->GetJSThread();
534         jsAPIArrayList->SetLength(thread, JSTaggedValue(0));
535         return jsAPIArrayList;
536     }
537 
538     // JS_API_HASH_MAP
NewJSAPIHashMap()539     JSHandle<JSAPIHashMap> NewJSAPIHashMap()
540     {
541         JSThread *thread = instance->GetJSThread();
542         JSHandle<JSTaggedValue> proto = instance->GetGlobalEnv()->GetObjectFunctionPrototype();
543         JSHandle<JSObject> jsAPIHashMapObject = NewObject(JSAPIHashMap::SIZE, JSType::JS_API_HASH_MAP, proto);
544         JSHandle<JSAPIHashMap> jsAPIHashMap = JSHandle<JSAPIHashMap>::Cast(jsAPIHashMapObject);
545         jsAPIHashMap->SetTable(thread, TaggedHashArray::Create(thread));
546         jsAPIHashMap->SetSize(0);
547         return jsAPIHashMap;
548     }
549 
550     // JS_API_HASH_SET
NewJSAPIHashSet()551     JSHandle<JSAPIHashSet> NewJSAPIHashSet()
552     {
553         JSThread *thread = instance->GetJSThread();
554         JSHandle<JSTaggedValue> proto = instance->GetGlobalEnv()->GetObjectFunctionPrototype();
555         JSHandle<JSObject> jsAPIHashSetObject = NewObject(JSAPIHashSet::SIZE, JSType::JS_API_HASH_SET, proto);
556         JSHandle<JSAPIHashSet> jsAPIHashSet = JSHandle<JSAPIHashSet>::Cast(jsAPIHashSetObject);
557         jsAPIHashSet->SetTable(thread, TaggedHashArray::Create(thread));
558         jsAPIHashSet->SetSize(0);
559         return jsAPIHashSet;
560     }
561 
562     // JS_API_LIGHT_WEIGHT_MAP
NewJSAPILightWeightMap()563     JSHandle<JSAPILightWeightMap> NewJSAPILightWeightMap()
564     {
565         JSThread *thread = instance->GetJSThread();
566         ObjectFactory *factory = instance->GetFactory();
567         JSHandle<JSTaggedValue> proto = instance->GetGlobalEnv()->GetObjectFunctionPrototype();
568         JSHandle<JSObject> jsAPILightWeightMapObject =
569             NewObject(JSAPILightWeightMap::SIZE, JSType::JS_API_LIGHT_WEIGHT_MAP, proto);
570         JSHandle<JSAPILightWeightMap> jsAPILightWeightMap =
571             JSHandle<JSAPILightWeightMap>::Cast(jsAPILightWeightMapObject);
572         JSHandle<JSTaggedValue> hashArray =
573             JSHandle<JSTaggedValue>(factory->NewTaggedArray(JSAPILightWeightMap::DEFAULT_CAPACITY_LENGTH));
574         JSHandle<JSTaggedValue> keyArray =
575             JSHandle<JSTaggedValue>(factory->NewTaggedArray(JSAPILightWeightMap::DEFAULT_CAPACITY_LENGTH));
576         JSHandle<JSTaggedValue> valueArray =
577             JSHandle<JSTaggedValue>(factory->NewTaggedArray(JSAPILightWeightMap::DEFAULT_CAPACITY_LENGTH));
578         jsAPILightWeightMap->SetHashes(thread, hashArray);
579         jsAPILightWeightMap->SetKeys(thread, keyArray);
580         jsAPILightWeightMap->SetValues(thread, valueArray);
581         jsAPILightWeightMap->SetLength(0);
582         return jsAPILightWeightMap;
583     }
584 
585     // JS_API_LIGHT_WEIGHT_SET
NewJSAPILightWeightSet()586     JSHandle<JSAPILightWeightSet> NewJSAPILightWeightSet()
587     {
588         JSThread *thread = instance->GetJSThread();
589         JSHandle<JSTaggedValue> proto = instance->GetGlobalEnv()->GetObjectFunctionPrototype();
590         JSHandle<JSObject> jsAPILightWeightSetObject =
591             NewObject(JSAPILightWeightSet::SIZE, JSType::JS_API_LIGHT_WEIGHT_SET, proto);
592         JSHandle<JSAPILightWeightSet> jsAPILightWeightSet =
593             JSHandle<JSAPILightWeightSet>::Cast(jsAPILightWeightSetObject);
594         JSHandle<TaggedArray> hashes =
595             JSAPILightWeightSet::CreateSlot(thread, JSAPILightWeightSet::DEFAULT_CAPACITY_LENGTH);
596         JSHandle<TaggedArray> values =
597             JSAPILightWeightSet::CreateSlot(thread, JSAPILightWeightSet::DEFAULT_CAPACITY_LENGTH);
598         jsAPILightWeightSet->SetHashes(thread, hashes);
599         jsAPILightWeightSet->SetValues(thread, values);
600         jsAPILightWeightSet->SetLength(0);
601         return jsAPILightWeightSet;
602     }
603 
604     // JS_API_TREE_MAP
NewJSAPITreeMap()605     JSHandle<JSAPITreeMap> NewJSAPITreeMap()
606     {
607         JSThread *thread = instance->GetJSThread();
608         JSHandle<JSTaggedValue> proto = instance->GetGlobalEnv()->GetObjectFunctionPrototype();
609         JSHandle<JSObject> jsAPITreeMapObject = NewObject(JSAPITreeMap::SIZE, JSType::JS_API_TREE_MAP, proto);
610         JSHandle<JSAPITreeMap> jsAPITreeMap = JSHandle<JSAPITreeMap>::Cast(jsAPITreeMapObject);
611         JSHandle<TaggedTreeMap> treeMap(thread, TaggedTreeMap::Create(thread));
612         jsAPITreeMap->SetTreeMap(thread, treeMap);
613         return jsAPITreeMap;
614     }
615 
616     // JS_API_TREE_SET
NewJSAPITreeSet()617     JSHandle<JSAPITreeSet> NewJSAPITreeSet()
618     {
619         JSThread *thread = instance->GetJSThread();
620         JSHandle<JSTaggedValue> proto = instance->GetGlobalEnv()->GetObjectFunctionPrototype();
621         JSHandle<JSObject> jsAPITreeSetObject = NewObject(JSAPITreeSet::SIZE, JSType::JS_API_TREE_SET, proto);
622         JSHandle<JSAPITreeSet> jsAPITreeSet = JSHandle<JSAPITreeSet>::Cast(jsAPITreeSetObject);
623         JSHandle<TaggedTreeSet> treeSet(thread, TaggedTreeSet::Create(thread));
624         jsAPITreeSet->SetTreeSet(thread, treeSet);
625         return jsAPITreeSet;
626     }
627 
628     // JS_API_QUEUE
NewJSAPIQueue()629     JSHandle<JSAPIQueue> NewJSAPIQueue()
630     {
631         JSThread *thread = instance->GetJSThread();
632         ObjectFactory *factory = instance->GetFactory();
633         JSHandle<JSTaggedValue> proto = instance->GetGlobalEnv()->GetFunctionPrototype();
634         JSHandle<JSObject> jsAPIQueueObject = NewObject(JSAPIQueue::SIZE, JSType::JS_API_QUEUE, proto);
635         JSHandle<JSAPIQueue> jsAPIQueue = JSHandle<JSAPIQueue>::Cast(jsAPIQueueObject);
636         JSHandle<TaggedArray> newElements = factory->NewTaggedArray(JSAPIQueue::DEFAULT_CAPACITY_LENGTH);
637         jsAPIQueue->SetLength(thread, JSTaggedValue(0));
638         jsAPIQueue->SetFront(0);
639         jsAPIQueue->SetTail(0);
640         jsAPIQueue->SetElements(thread, newElements);
641         return jsAPIQueue;
642     }
643     // JS_API_DEQUE
NewJSAPIDeque()644     JSHandle<JSAPIDeque> NewJSAPIDeque()
645     {
646         ObjectFactory *factory = instance->GetFactory();
647         JSHandle<JSTaggedValue> proto = instance->GetGlobalEnv()->GetFunctionPrototype();
648         JSHandle<JSObject> jsAPIDequeObject = NewObject(JSAPIDeque::SIZE, JSType::JS_API_DEQUE, proto);
649         JSHandle<JSAPIDeque> jsAPIDeque = JSHandle<JSAPIDeque>::Cast(jsAPIDequeObject);
650         JSHandle<TaggedArray> newElements = factory->NewTaggedArray(JSAPIDeque::DEFAULT_CAPACITY_LENGTH);
651         jsAPIDeque->SetFirst(0);
652         jsAPIDeque->SetLast(0);
653         jsAPIDeque->SetElements(instance->GetJSThread(), newElements);
654         return jsAPIDeque;
655     }
656     // JS_API_STACK
NewJSAPIStack()657     JSHandle<JSAPIStack> NewJSAPIStack()
658     {
659         JSHandle<JSTaggedValue> proto = instance->GetGlobalEnv()->GetFunctionPrototype();
660         JSHandle<JSObject> jsAPIStackObject = NewObject(JSAPIStack::SIZE, JSType::JS_API_STACK, proto);
661         JSHandle<JSAPIStack> jsAPIStack = JSHandle<JSAPIStack>::Cast(jsAPIStackObject);
662         jsAPIStack->SetTop(0);
663         return jsAPIStack;
664     }
665 
666     // JS_API_PLAIN_ARRAY
NewJSAPIPlainArray()667     JSHandle<JSAPIPlainArray> NewJSAPIPlainArray()
668     {
669         JSThread *thread = instance->GetJSThread();
670         JSHandle<JSTaggedValue> proto = instance->GetGlobalEnv()->GetObjectFunctionPrototype();
671         JSHandle<JSObject> jsAPIPlainArrayObject = NewObject(JSAPIPlainArray::SIZE, JSType::JS_API_PLAIN_ARRAY, proto);
672         JSHandle<JSAPIPlainArray> jsAPIPlainArray = JSHandle<JSAPIPlainArray>::Cast(jsAPIPlainArrayObject);
673         JSHandle<TaggedArray> keys =
674                 JSAPIPlainArray::CreateSlot(thread, JSAPIPlainArray::DEFAULT_CAPACITY_LENGTH);
675         JSHandle<TaggedArray> values =
676                 JSAPIPlainArray::CreateSlot(thread, JSAPIPlainArray::DEFAULT_CAPACITY_LENGTH);
677         jsAPIPlainArray->SetKeys(thread, keys);
678         jsAPIPlainArray->SetValues(thread, values);
679         jsAPIPlainArray->SetLength(0);
680         return jsAPIPlainArray;
681     }
682 
683     // JS_API_LIST
NewJSAPIList()684     JSHandle<JSAPIList> NewJSAPIList()
685     {
686         JSThread *thread = instance->GetJSThread();
687         JSHandle<JSTaggedValue> proto = instance->GetGlobalEnv()->GetObjectFunctionPrototype();
688         JSHandle<JSObject> jsAPIListObject = NewObject(JSAPIList::SIZE, JSType::JS_API_LIST, proto);
689         JSHandle<JSAPIList> jsAPIList = JSHandle<JSAPIList>::Cast(jsAPIListObject);
690         JSHandle<JSTaggedValue> taggedSingleList(thread, TaggedSingleList::Create(thread));
691         jsAPIList->SetSingleList(thread, taggedSingleList);
692         return jsAPIList;
693     }
694 
695     // JS_API_LINKED_LIST
NewJSAPILinkedList()696     JSHandle<JSAPILinkedList> NewJSAPILinkedList()
697     {
698         JSThread *thread = instance->GetJSThread();
699         JSHandle<JSTaggedValue> proto = instance->GetGlobalEnv()->GetObjectFunctionPrototype();
700         JSHandle<JSObject> jsAPILinkedListObject = NewObject(JSAPILinkedList::SIZE, JSType::JS_API_LINKED_LIST, proto);
701         JSHandle<JSAPILinkedList> jsAPILinkedList = JSHandle<JSAPILinkedList>::Cast(jsAPILinkedListObject);
702         JSHandle<JSTaggedValue> linkedlist(thread, TaggedDoubleList::Create(thread));
703         jsAPILinkedList->SetDoubleList(thread, linkedlist);
704         return jsAPILinkedList;
705     }
706 
707     // JS_API_VECTOR
NewJSAPIVector()708     JSHandle<JSAPIVector> NewJSAPIVector()
709     {
710         JSHandle<JSTaggedValue> proto = instance->GetGlobalEnv()->GetFunctionPrototype();
711         JSHandle<JSObject> jsAPIVectorObject = NewObject(JSAPIVector::SIZE, JSType::JS_API_VECTOR, proto);
712         JSHandle<JSAPIVector> jsAPIVector = JSHandle<JSAPIVector>::Cast(jsAPIVectorObject);
713         jsAPIVector->SetLength(0);
714         return jsAPIVector;
715     }
716 
717     // JS_WEAK_REF
NewJSWeakRef()718     JSHandle<JSWeakRef> NewJSWeakRef()
719     {
720         JSHandle<JSTaggedValue> proto = instance->GetGlobalEnv()->GetFunctionPrototype();
721         JSHandle<JSObject> jsWeakRefObject = NewObject(JSWeakRef::SIZE, JSType::JS_WEAK_REF, proto);
722         JSHandle<JSWeakRef> jsWeakRef = JSHandle<JSWeakRef>::Cast(jsWeakRefObject);
723         return jsWeakRef;
724     }
725 
726     // JS_FINALIZATION_REGISTRY
NewJSFinalizationRegistry()727     JSHandle<JSFinalizationRegistry> NewJSFinalizationRegistry()
728     {
729         JSHandle<JSTaggedValue> proto = instance->GetGlobalEnv()->GetFunctionPrototype();
730         JSHandle<JSObject> jsFinalizationRegistryObject =
731             NewObject(JSFinalizationRegistry::SIZE, JSType::JS_FINALIZATION_REGISTRY, proto);
732         JSHandle<JSFinalizationRegistry> jsFinalizationRegistry =
733             JSHandle<JSFinalizationRegistry>::Cast(jsFinalizationRegistryObject);
734         return jsFinalizationRegistry;
735     }
736 
737     // JS_ASYNC_FROM_SYNC_ITERATOR
NewJSAsyncFromSyncIterator()738     JSHandle<JSAsyncFromSyncIterator> NewJSAsyncFromSyncIterator()
739     {
740         JSHandle<JSTaggedValue> proto = instance->GetGlobalEnv()->GetFunctionPrototype();
741         JSHandle<JSObject> jsAsyncFromSyncIteratorObject =
742             NewObject(JSAsyncFromSyncIterator::SIZE, JSType::JS_ASYNC_FROM_SYNC_ITERATOR, proto);
743         JSHandle<JSAsyncFromSyncIterator> jsAsyncFromSyncIterator =
744             JSHandle<JSAsyncFromSyncIterator>::Cast(jsAsyncFromSyncIteratorObject);
745         return jsAsyncFromSyncIterator;
746     }
747 
748     // JS_API_LINKED_LIST_ITERATOR
NewJSAPILinkedListIterator()749     JSHandle<JSAPILinkedListIterator> NewJSAPILinkedListIterator()
750     {
751         ObjectFactory *factory = instance->GetFactory();
752         JSHandle<JSAPILinkedList> jsAPILinkedList = NewJSAPILinkedList();
753         JSHandle<JSAPILinkedListIterator> jsAPILinkedListIter =
754             factory->NewJSAPILinkedListIterator(jsAPILinkedList);
755         return jsAPILinkedListIter;
756     }
757 
758     // JS_API_LIST_ITERATOR
NewJSAPIListIterator()759     JSHandle<JSAPIListIterator> NewJSAPIListIterator()
760     {
761         ObjectFactory *factory = instance->GetFactory();
762         JSHandle<JSAPIList> jsAPIList = NewJSAPIList();
763         JSHandle<JSAPIListIterator> jsAPIListIter = factory->NewJSAPIListIterator(jsAPIList);
764         return jsAPIListIter;
765     }
766 
767     // JS_SHARED_ARRAY_ITERATOR
NewJSSharedArrayIterator()768     JSHandle<JSSharedArrayIterator> NewJSSharedArrayIterator()
769     {
770         ObjectFactory *factory = instance->GetFactory();
771         JSHandle<JSSharedArrayIterator> sharedArrayIter = factory->NewJSSharedArrayIterator(
772             JSHandle<JSObject>::Cast(factory->NewJSSArray()), IterationKind::KEY);
773         return sharedArrayIter;
774     }
775 
776     // BYTE_ARRAY
NewByteArray()777     JSHandle<ByteArray> NewByteArray()
778     {
779         uint8_t value = 255; // 255 : test case
780         int byteArrayLength = 10; // 10: arrayLength
781         ObjectFactory *factory = instance->GetFactory();
782         JSHandle<ByteArray> byteArray = factory->NewByteArray(byteArrayLength, sizeof(value));
783         return byteArray;
784     }
785 
786     // RB_TREENODE
NewRBTreeNode()787     JSHandle<RBTreeNode> NewRBTreeNode()
788     {
789         ObjectFactory *factory = instance->GetFactory();
790         JSThread *thread = instance->GetJSThread();
791         std::string k("testKey");
792         std::string v("testValue");
793         JSHandle<JSTaggedValue> key(thread, factory->NewFromStdString(k).GetTaggedValue());
794         JSHandle<JSTaggedValue> value(thread, factory->NewFromStdString(v).GetTaggedValue());
795         int hash = TaggedNode::Hash(thread, factory->NewFromStdString(k).GetTaggedValue());
796         JSHandle<RBTreeNode> newNode = factory->NewTreeNode(hash, key, value);
797         return newNode;
798     }
799 
800     // CLASS_LITERAL
NewClassLiteral()801     JSHandle<ClassLiteral> NewClassLiteral()
802     {
803         JSHandle<JSTaggedValue> proto = instance->GetGlobalEnv()->GetFunctionPrototype();
804         JSHandle<JSObject> classLiteralObject = NewObject(ClassLiteral::SIZE, JSType::CLASS_LITERAL, proto);
805         JSHandle<ClassLiteral> classLiteral = JSHandle<ClassLiteral>::Cast(classLiteralObject);
806         ObjectFactory *factory = instance->GetFactory();
807         JSHandle<TaggedArray> emptyArray = factory->EmptyArray();
808 
809         classLiteral->SetArray(instance->GetJSThread(), emptyArray);
810         classLiteral->SetIsAOTUsed(false);
811         return classLiteral;
812     }
813 
814     // ASYNC_ITERATOR_RECORD
NewAsyncIteratorRecord()815     JSHandle<AsyncIteratorRecord> NewAsyncIteratorRecord()
816     {
817         ObjectFactory *factory = instance->GetFactory();
818         JSHandle<JSTaggedValue> proto = instance->GetGlobalEnv()->GetFunctionPrototype();
819         JSHandle<JSObject> jsObject = NewObject(JSObject::SIZE, JSType::JS_OBJECT, proto);
820         JSHandle<JSTaggedValue> emptyObj(jsObject);
821         JSHandle<JSTaggedValue> emptyMethod(jsObject);
822         JSHandle<AsyncIteratorRecord> asyncIteratorRecord =
823             factory->NewAsyncIteratorRecord(emptyObj, emptyMethod, false);
824         return asyncIteratorRecord;
825     }
826 
827     // PROFILE_TYPE_INFO_CELL
NewProfileTypeInfoCell()828     JSHandle<ProfileTypeInfoCell> NewProfileTypeInfoCell()
829     {
830         JSThread *thread = instance->GetJSThread();
831         JSHandle<JSTaggedValue> handleUndefined(thread, JSTaggedValue::Undefined());
832         JSHandle<ProfileTypeInfoCell> newProfileTypeInfoCell =
833             instance->GetFactory()->NewProfileTypeInfoCell(handleUndefined);
834         return newProfileTypeInfoCell;
835     }
836 private:
837     EcmaVM *instance {nullptr};
838 };
839 
840 class MockHeapProfiler : public HeapProfilerInterface {
841 public:
842     NO_MOVE_SEMANTIC(MockHeapProfiler);
843     NO_COPY_SEMANTIC(MockHeapProfiler);
MockHeapProfiler(HeapProfilerInterface * profiler)844     explicit MockHeapProfiler(HeapProfilerInterface *profiler) : profiler_(profiler) {}
~MockHeapProfiler()845     ~MockHeapProfiler() override
846     {
847         allocEvtObj_.clear();
848     };
849 
AllocationEvent(TaggedObject * address,size_t size)850     void AllocationEvent(TaggedObject *address, size_t size) override
851     {
852         allocEvtObj_.emplace(address, true);
853         profiler_->AllocationEvent(address, size);
854     }
855 
MoveEvent(uintptr_t address,TaggedObject * forwardAddress,size_t size)856     void MoveEvent(uintptr_t address, TaggedObject *forwardAddress, size_t size) override
857     {
858         return profiler_->MoveEvent(address, forwardAddress, size);
859     }
860 
DumpHeapSnapshot(Stream * stream,const DumpSnapShotOption & dumpOption,Progress * progress=nullptr,std::function<void (uint8_t)> callback=[](uint8_t){})861     bool DumpHeapSnapshot(Stream *stream, const DumpSnapShotOption &dumpOption, Progress *progress = nullptr,
862                           std::function<void(uint8_t)> callback = [] (uint8_t) {}) override
863     {
864         return profiler_->DumpHeapSnapshot(stream, dumpOption, progress, callback);
865     }
866 
DumpHeapSnapshotForOOM(const DumpSnapShotOption & dumpOption,bool fromSharedGC=false)867     void DumpHeapSnapshotForOOM(const DumpSnapShotOption &dumpOption, bool fromSharedGC = false) override
868     {
869         profiler_->DumpHeapSnapshotForOOM(dumpOption, fromSharedGC);
870     }
871 
StartHeapTracking(double timeInterval,bool isVmMode=true,Stream * stream=nullptr,bool traceAllocation=false,bool newThread=true)872     bool StartHeapTracking(double timeInterval, bool isVmMode = true, Stream *stream = nullptr,
873                            bool traceAllocation = false, bool newThread = true) override
874     {
875         return profiler_->StartHeapTracking(timeInterval, isVmMode, stream, traceAllocation, newThread);
876     }
877 
StopHeapTracking(Stream * stream,Progress * progress=nullptr,bool newThread=true)878     bool StopHeapTracking(Stream *stream, Progress *progress = nullptr, bool newThread = true) override
879     {
880         return profiler_->StopHeapTracking(stream, progress, newThread);
881     }
882 
UpdateHeapTracking(Stream * stream)883     bool UpdateHeapTracking(Stream *stream) override
884     {
885         return profiler_->UpdateHeapTracking(stream);
886     }
887 
StartHeapSampling(uint64_t samplingInterval,int stackDepth=128)888     bool StartHeapSampling(uint64_t samplingInterval, int stackDepth = 128) override
889     {
890         return profiler_->StartHeapSampling(samplingInterval, stackDepth);
891     }
892 
StopHeapSampling()893     void StopHeapSampling() override
894     {
895         profiler_->StopHeapSampling();
896     }
897 
GetAllocationProfile()898     const struct SamplingInfo *GetAllocationProfile() override
899     {
900         return profiler_->GetAllocationProfile();
901     }
902 
GetIdCount()903     size_t GetIdCount() override
904     {
905         return profiler_->GetIdCount();
906     }
907 
908     std::unordered_map<TaggedObject *, bool> allocEvtObj_;
909     HeapProfilerInterface *profiler_ {nullptr};
910 };
911 
912 template <class Callback>
913 class TestAllocationEventRootVisitor final : public RootVisitor {
914 public:
TestAllocationEventRootVisitor(Callback & cb)915     explicit TestAllocationEventRootVisitor(Callback &cb) : cb_(cb) {}
916     ~TestAllocationEventRootVisitor() = default;
VisitRoot(Root type,ObjectSlot slot)917     void VisitRoot([[maybe_unused]] Root type, ObjectSlot slot) override
918     {
919         JSTaggedValue value((slot).GetTaggedType());
920         if (!value.IsHeapObject()) {
921             return;
922         }
923         TaggedObject *root = value.GetTaggedObject();
924         cb_(root);
925     }
VisitRangeRoot(Root type,ObjectSlot start,ObjectSlot end)926     void VisitRangeRoot([[maybe_unused]] Root type, ObjectSlot start, ObjectSlot end) override
927     {
928         for (ObjectSlot slot = start; slot < end; slot++) {
929             VisitRoot(type, slot);
930         }
931     }
VisitBaseAndDerivedRoot(Root type,ObjectSlot base,ObjectSlot derived,uintptr_t baseOldObject)932     void VisitBaseAndDerivedRoot([[maybe_unused]] Root type, [[maybe_unused]] ObjectSlot base,
933         [[maybe_unused]] ObjectSlot derived, [[maybe_unused]] uintptr_t baseOldObject) override {}
934 private:
935     Callback &cb_;
936 };
937 
HWTEST_F_L0(HeapDumpTest,TestAllocationEvent)938 HWTEST_F_L0(HeapDumpTest, TestAllocationEvent)
939 {
940     const std::string abcFileName = HPROF_TEST_ABC_FILES_DIR"heapdump.abc";
941     const std::string jsFileName = HPROF_TEST_JS_FILES_DIR"heapdump.js";
942     MockHeapProfiler mockHeapProfiler(ecmaVm_->GetOrNewHeapProfile());
943     ecmaVm_->SetHeapProfile(&mockHeapProfiler);
944 
945     std::unordered_map<TaggedObject *, bool> ObjBeforeExecute;
946     std::unordered_map<TaggedObject *, bool> *ObjMap = &ObjBeforeExecute;
947     auto heap = ecmaVm_->GetHeap();
948     ASSERT_NE(heap, nullptr);
949     auto countCb = [&ObjMap](TaggedObject *obj) {
950         ObjMap->emplace(obj, true);
951     };
952     heap->IterateOverObjects(countCb);
953 
954     TestAllocationEventRootVisitor testAllocationEventRootVisitor(countCb);
955     ecmaVm_->Iterate(testAllocationEventRootVisitor);
956     thread_->Iterate(testAllocationEventRootVisitor);
957 
958     bool result = JSNApi::Execute(ecmaVm_, abcFileName, "heapdump");
959     EXPECT_TRUE(result);
960 
961     std::unordered_map<TaggedObject *, bool> ObjAfterExecute;
962     ObjMap = &ObjAfterExecute;
963     heap->IterateOverObjects(countCb);
964     ecmaVm_->Iterate(testAllocationEventRootVisitor);
965     thread_->Iterate(testAllocationEventRootVisitor);
966     ecmaVm_->SetHeapProfile(mockHeapProfiler.profiler_);
967 
968     std::unordered_map<std::string, int> noTraceObjCheck =
969        {{"TaggedArray", 1}, {"AsyncFunction", 2}, {"LexicalEnv", 2}, {"Array", 3}, {"Function", 7}, {"Map", 1},
970        {"Object", 1}, {"Uint8 Clamped Array", 1}, {"Uint32 Array", 1}, {"Float32 Array", 1}, {"Int32 Array", 1},
971        {"Int16 Array", 1}, {"BigUint64 Array", 1}, {"Uint8 Array", 1}, {"Float64 Array", 1}, {"ByteArray", 11},
972        {"Int8 Array", 1}, {"BigInt64 Array", 1}, {"Uint16 Array", 1}, {"ArrayIterator", 1}};
973     bool pass = true;
974     std::unordered_map<std::string, int> noTraceObj;
975     for (auto o = ObjAfterExecute.begin(); o != ObjAfterExecute.end(); o++) {
976         if (ObjBeforeExecute.find(o->first) != ObjBeforeExecute.end()) {
977             continue;
978         }
979         if (mockHeapProfiler.allocEvtObj_.find(o->first) != mockHeapProfiler.allocEvtObj_.end()) {
980             continue;
981         }
982         auto objType = o->first->GetClass()->GetObjectType();
983         std::string typeName = ConvertToStdString(JSHClass::DumpJSType(objType));
984         if (noTraceObjCheck.size() == 0) {
985             LOG_ECMA(ERROR) << "Object not traced, Addr=" << o->first << ", TypeName=" << typeName;
986             pass = false;
987         }
988         if (noTraceObj.find(typeName) == noTraceObj.end()) {
989             noTraceObj.emplace(typeName, 0);
990         }
991         noTraceObj[typeName] += 1;
992     }
993     for (auto o = noTraceObj.begin(); o != noTraceObj.end(); o++) {
994         if (noTraceObjCheck.find(o->first) == noTraceObjCheck.end()) {
995             LOG_ECMA(ERROR) << "Object not traced, TypeName=" << o->first << ", count=" << o->second;
996             pass = false;
997         }
998     }
999     ASSERT_TRUE(pass);
1000 }
1001 
HWTEST_F_L0(HeapDumpTest,TestHeapDumpFunctionUrl)1002 HWTEST_F_L0(HeapDumpTest, TestHeapDumpFunctionUrl)
1003 {
1004     const std::string abcFileName = HPROF_TEST_ABC_FILES_DIR"heapdump.abc";
1005 
1006     bool result = JSNApi::Execute(ecmaVm_, abcFileName, "heapdump");
1007     EXPECT_TRUE(result);
1008 
1009     HeapDumpTestHelper tester(ecmaVm_);
1010     tester.GenerateSnapShot("testFunctionUrl.heapsnapshot");
1011 
1012     // match function url
1013     std::string line;
1014     std::ifstream inputStream("testFunctionUrl.heapsnapshot");
1015     bool strMatched = false;
1016     bool funcTempMatched = false;
1017     while (getline(inputStream, line)) {
1018         if (strMatched && funcTempMatched) {
1019             break;
1020         }
1021         if (line.find("heapdump.js#greet(line:98)") != std::string::npos) {
1022             strMatched = true;
1023             continue;
1024         }
1025         if (line == "\"ArkInternalFunctionTemplate\",") {
1026             funcTempMatched = true;
1027             continue;
1028         }
1029     }
1030     ASSERT_TRUE(strMatched);
1031     ASSERT_TRUE(funcTempMatched);
1032 }
1033 
HWTEST_F_L0(HeapDumpTest,TestHeapDumpFunctionAndObject)1034 HWTEST_F_L0(HeapDumpTest, TestHeapDumpFunctionAndObject)
1035 {
1036     const std::string abcFileName = HPROF_TEST_ABC_FILES_DIR"heapdump1.abc";
1037 
1038     bool result = JSNApi::Execute(ecmaVm_, abcFileName, "heapdump1");
1039     EXPECT_TRUE(result);
1040     ecmaVm_->SetBundleName("com.example.testFunctionAndObject");
1041     HeapDumpTestHelper tester(ecmaVm_);
1042     tester.GenerateSnapShot("testFunctionAndObject.heapsnapshot");
1043 
1044     // match function url
1045     std::string line;
1046     std::ifstream inputStream("testFunctionAndObject.heapsnapshot");
1047     bool strMatched = false;
1048     bool strMatched1 = false;
1049     bool strMatched2 = false;
1050     bool strMatched3 = false;
1051     bool strMatched4 = false;
1052     bool strMatched5 = false;
1053     bool strMatched6 = false;
1054     bool strMatched7 = false;
1055     while (getline(inputStream, line)) {
1056         if (strMatched && strMatched1 && strMatched2 && strMatched3 &&
1057             strMatched4 && strMatched5 && strMatched6 && strMatched7) {
1058             break;
1059         }
1060         if (line.find("heapdump1.js#anonymous(line:19)") != std::string::npos) {
1061             strMatched = true;
1062             continue;
1063         }
1064         if (line.find("heapdump1.js#test(line:25)") != std::string::npos) {
1065             strMatched1 = true;
1066             continue;
1067         }
1068         if (line.find("heapdump1.js#ObjectFun(line:30)") != std::string::npos) {
1069             strMatched2 = true;
1070             continue;
1071         }
1072         if (line.find("heapdump1.js#Person(line:35)") != std::string::npos) {
1073             strMatched3 = true;
1074             continue;
1075         }
1076         if (line.find("heapdump1.js#greet(line:40)") != std::string::npos) {
1077             strMatched4 = true;
1078             continue;
1079         }
1080         if (line.find("heapdump1.js#testObject(line:51)") != std::string::npos) {
1081             strMatched5 = true;
1082             continue;
1083         }
1084         if (line.find("heapdump1.js#Student(line:62)") != std::string::npos) {
1085             strMatched6 = true;
1086             continue;
1087         }
1088         if (line.find("heapdump1.js#getMessage(line:67)") != std::string::npos) {
1089             strMatched7 = true;
1090             continue;
1091         }
1092     }
1093     ASSERT_TRUE(strMatched);
1094     ASSERT_TRUE(strMatched1);
1095     ASSERT_TRUE(strMatched2);
1096     ASSERT_TRUE(strMatched3);
1097     ASSERT_TRUE(strMatched4);
1098     ASSERT_TRUE(strMatched5);
1099     ASSERT_TRUE(strMatched6);
1100     ASSERT_TRUE(strMatched7);
1101 }
1102 
HWTEST_F_L0(HeapDumpTest,TestHeapDumpGenerateNodeName1)1103 HWTEST_F_L0(HeapDumpTest, TestHeapDumpGenerateNodeName1)
1104 {
1105     JSHandle<GlobalEnv> env = thread_->GetEcmaVM()->GetGlobalEnv();
1106     ObjectFactory *factory = ecmaVm_->GetFactory();
1107     HeapDumpTestHelper tester(ecmaVm_);
1108 
1109     // TAGGED_ARRAY
1110     factory->NewTaggedArray(10);
1111     // LEXICAL_ENV
1112     factory->NewLexicalEnv(10);
1113     // CONSTANT_POOL
1114     factory->NewConstantPool(10);
1115     // PROFILE_TYPE_INFO
1116     factory->NewProfileTypeInfo(10);
1117     // TAGGED_DICTIONARY
1118     factory->NewDictionaryArray(10);
1119     // AOT_LITERAL_INFO
1120     factory->NewAOTLiteralInfo(10);
1121     // VTABLE
1122     factory->NewVTable(10);
1123     // COW_TAGGED_ARRAY
1124     factory->NewCOWTaggedArray(10);
1125     // HCLASS
1126     JSHandle<JSTaggedValue> proto = env->GetFunctionPrototype();
1127     factory->NewEcmaHClass(JSHClass::SIZE, JSType::HCLASS, proto);
1128     // LINKED_NODE
1129     JSHandle<LinkedNode> linkedNode(thread_, JSTaggedValue::Hole());
1130     factory->NewLinkedNode(1, JSHandle<JSTaggedValue>(thread_, JSTaggedValue::Hole()),
1131         JSHandle<JSTaggedValue>(thread_, JSTaggedValue::Hole()), linkedNode);
1132     // JS_NATIVE_POINTER
1133     auto newData = ecmaVm_->GetNativeAreaAllocator()->AllocateBuffer(8);
1134     factory->NewJSNativePointer(newData);
1135 
1136     tester.GenerateSnapShot("testGenerateNodeName_1.heapsnapshot");
1137     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_1.heapsnapshot", "\"ArkInternalArray["));
1138     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_1.heapsnapshot", "\"LexicalEnv["));
1139     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_1.heapsnapshot", "\"ArkInternalConstantPool["));
1140     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_1.heapsnapshot", "\"ArkInternalProfileTypeInfo["));
1141     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_1.heapsnapshot", "\"ArkInternalDict["));
1142     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_1.heapsnapshot", "\"ArkInternalAOTLiteralInfo["));
1143     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_1.heapsnapshot", "\"ArkInternalVTable["));
1144     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_1.heapsnapshot", "\"ArkInternalCOWArray["));
1145     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_1.heapsnapshot", "\"HiddenClass(NonMovable)"));
1146     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_1.heapsnapshot", "\"LinkedNode\""));
1147     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_1.heapsnapshot", "\"JSNativePointer\""));
1148     // Test Not Found
1149     ASSERT_TRUE(!tester.MatchHeapDumpString("testGenerateNodeName_1.heapsnapshot", "*#@failed case"));
1150 }
1151 
HWTEST_F_L0(HeapDumpTest,TestHeapDumpGenerateNodeName2)1152 HWTEST_F_L0(HeapDumpTest, TestHeapDumpGenerateNodeName2)
1153 {
1154     ObjectFactory *factory = ecmaVm_->GetFactory();
1155     HeapDumpTestHelper tester(ecmaVm_);
1156 
1157     // JS_ERROR
1158     JSHandle<EcmaString> handleMessage(thread_, EcmaStringAccessor::CreateEmptyString(ecmaVm_));
1159     factory->NewJSError(ErrorType::ERROR, handleMessage);
1160     // JS_EVAL_ERROR
1161     factory->NewJSError(ErrorType::EVAL_ERROR, handleMessage);
1162     // JS_RANGE_ERROR
1163     factory->NewJSError(ErrorType::RANGE_ERROR, handleMessage);
1164     // JS_TYPE_ERROR
1165     factory->NewJSError(ErrorType::TYPE_ERROR, handleMessage);
1166     // JS_AGGREGATE_ERROR
1167     factory->NewJSAggregateError();
1168     // JS_REFERENCE_ERROR
1169     factory->NewJSError(ErrorType::REFERENCE_ERROR, handleMessage);
1170     // JS_URI_ERROR
1171     factory->NewJSError(ErrorType::URI_ERROR, handleMessage);
1172     // JS_SYNTAX_ERROR
1173     factory->NewJSError(ErrorType::SYNTAX_ERROR, handleMessage);
1174     // JS_OOM_ERROR
1175     factory->NewJSError(ErrorType::OOM_ERROR, handleMessage);
1176     // JS_TERMINATION_ERROR
1177     factory->NewJSError(ErrorType::TERMINATION_ERROR, handleMessage);
1178 
1179     tester.GenerateSnapShot("testGenerateNodeName_2.heapsnapshot");
1180     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_2.heapsnapshot", "\"Error\""));
1181     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_2.heapsnapshot", "\"Eval Error\""));
1182     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_2.heapsnapshot", "\"Range Error\""));
1183     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_2.heapsnapshot", "\"Type Error\""));
1184     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_2.heapsnapshot", "\"Aggregate Error\""));
1185     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_2.heapsnapshot", "\"Reference Error\""));
1186     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_2.heapsnapshot", "\"Uri Error\""));
1187     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_2.heapsnapshot", "\"Syntax Error\""));
1188     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_2.heapsnapshot", "\"OutOfMemory Error\""));
1189     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_2.heapsnapshot", "\"Termination Error\""));
1190 }
1191 
HWTEST_F_L0(HeapDumpTest,TestHeapDumpGenerateNodeName3)1192 HWTEST_F_L0(HeapDumpTest, TestHeapDumpGenerateNodeName3)
1193 {
1194     HeapDumpTestHelper tester(ecmaVm_);
1195 
1196     // JS_INT8_ARRAY
1197     tester.CreateNumberTypedArray(JSType::JS_INT8_ARRAY);
1198     // JS_UINT8_ARRAY
1199     tester.CreateNumberTypedArray(JSType::JS_UINT8_ARRAY);
1200     // JS_UINT8_CLAMPED_ARRAY
1201     tester.CreateNumberTypedArray(JSType::JS_UINT8_CLAMPED_ARRAY);
1202     // JS_INT16_ARRAY
1203     tester.CreateNumberTypedArray(JSType::JS_INT16_ARRAY);
1204     // JS_UINT16_ARRAY
1205     tester.CreateNumberTypedArray(JSType::JS_UINT16_ARRAY);
1206     // JS_INT32_ARRAY
1207     tester.CreateNumberTypedArray(JSType::JS_INT32_ARRAY);
1208     // JS_UINT32_ARRAY
1209     tester.CreateNumberTypedArray(JSType::JS_UINT32_ARRAY);
1210     // JS_FLOAT32_ARRAY
1211     tester.CreateNumberTypedArray(JSType::JS_FLOAT32_ARRAY);
1212     // JS_FLOAT64_ARRAY
1213     tester.CreateNumberTypedArray(JSType::JS_FLOAT64_ARRAY);
1214     // JS_BIGINT64_ARRAY
1215     tester.CreateNumberTypedArray(JSType::JS_BIGINT64_ARRAY);
1216     // JS_BIGUINT64_ARRAY
1217     tester.CreateNumberTypedArray(JSType::JS_BIGUINT64_ARRAY);
1218 
1219     tester.GenerateSnapShot("testGenerateNodeName_3.heapsnapshot");
1220     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_3.heapsnapshot", "\"Int8 Array\""));
1221     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_3.heapsnapshot", "\"Uint8 Array\""));
1222     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_3.heapsnapshot", "\"Uint8 Clamped Array\""));
1223     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_3.heapsnapshot", "\"Int16 Array\""));
1224     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_3.heapsnapshot", "\"Uint16 Array\""));
1225     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_3.heapsnapshot", "\"Int32 Array\""));
1226     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_3.heapsnapshot", "\"Uint32 Array\""));
1227     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_3.heapsnapshot", "\"Float32 Array\""));
1228     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_3.heapsnapshot", "\"Float64 Array\""));
1229     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_3.heapsnapshot", "\"BigInt64 Array\""));
1230     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_3.heapsnapshot", "\"BigUint64 Array\""));
1231 }
1232 
HWTEST_F_L0(HeapDumpTest,TestHeapDumpGenerateNodeName4)1233 HWTEST_F_L0(HeapDumpTest, TestHeapDumpGenerateNodeName4)
1234 {
1235     ObjectFactory *factory = ecmaVm_->GetFactory();
1236     HeapDumpTestHelper tester(ecmaVm_);
1237 
1238     JSHandle<JSTaggedValue> proto = ecmaVm_->GetGlobalEnv()->GetFunctionPrototype();
1239     // JS_SET
1240     tester.NewJSSet();
1241     // JS_SHARED_SET
1242     tester.NewJSSharedSet();
1243     // JS_MAP
1244     tester.NewJSMap();
1245     // JS_SHARED_MAP
1246     tester.NewJSSharedMap();
1247     // JS_WEAK_SET
1248     tester.NewJSWeakSet();
1249     // JS_WEAK_MAP
1250     tester.NewJSWeakMap();
1251     // JS_ARRAY
1252     factory->NewJSArray();
1253     // JS_TYPED_ARRAY
1254     tester.NewObject(JSTypedArray::SIZE, JSType::JS_TYPED_ARRAY, proto);
1255     tester.GenerateSnapShot("testGenerateNodeName_4.heapsnapshot");
1256 
1257     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_4.heapsnapshot", "\"Set\""));
1258     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_4.heapsnapshot", "\"SharedSet\""));
1259     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_4.heapsnapshot", "\"Map\""));
1260     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_4.heapsnapshot", "\"SharedMap\""));
1261     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_4.heapsnapshot", "\"WeakSet\""));
1262     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_4.heapsnapshot", "\"WeakMap\""));
1263     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_4.heapsnapshot", "\"JSArray\""));
1264     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_4.heapsnapshot", "\"Typed Array\""));
1265 }
1266 
HWTEST_F_L0(HeapDumpTest,TestHeapDumpGenerateNodeName5)1267 HWTEST_F_L0(HeapDumpTest, TestHeapDumpGenerateNodeName5)
1268 {
1269     ObjectFactory *factory = ecmaVm_->GetFactory();
1270     HeapDumpTestHelper tester(ecmaVm_);
1271 
1272     JSHandle<JSTaggedValue> proto = ecmaVm_->GetGlobalEnv()->GetFunctionPrototype();
1273     // JS_REG_EXP
1274     tester.NewObject(JSRegExp::SIZE, JSType::JS_REG_EXP, proto);
1275     // JS_DATE
1276     tester.NewObject(JSDate::SIZE, JSType::JS_DATE, proto);
1277     // JS_ARGUMENTS
1278     factory->NewJSArguments();
1279     // JS_PROXY
1280     tester.NewJSProxy();
1281     // JS_PRIMITIVE_REF
1282     tester.NewObject(JSPrimitiveRef::SIZE, JSType::JS_PRIMITIVE_REF, proto);
1283     // JS_DATA_VIEW
1284     factory->NewJSDataView(factory->NewJSArrayBuffer(10), 5, 5);
1285 
1286     tester.GenerateSnapShot("testGenerateNodeName_5.heapsnapshot");
1287     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_5.heapsnapshot", "\"Regexp\""));
1288     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_5.heapsnapshot", "\"Date\""));
1289     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_5.heapsnapshot", "\"Arguments\""));
1290     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_5.heapsnapshot", "\"Proxy\""));
1291     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_5.heapsnapshot", "\"Primitive\""));
1292     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_5.heapsnapshot", "\"DataView\""));
1293 }
1294 
HWTEST_F_L0(HeapDumpTest,TestHeapDumpGenerateNodeName6)1295 HWTEST_F_L0(HeapDumpTest, TestHeapDumpGenerateNodeName6)
1296 {
1297     ObjectFactory *factory = ecmaVm_->GetFactory();
1298     HeapDumpTestHelper tester(ecmaVm_);
1299 
1300     // JS_FORIN_ITERATOR
1301     tester.NewJSForInIterator();
1302     // JS_MAP_ITERATOR
1303     factory->NewJSMapIterator(tester.NewJSMap(), IterationKind::KEY);
1304     // JS_SHARED_MAP_ITERATOR
1305     factory->NewJSMapIterator(tester.NewJSSharedMap(), IterationKind::KEY);
1306     // JS_SET_ITERATOR
1307     factory->NewJSSetIterator(tester.NewJSSet(), IterationKind::KEY);
1308     // JS_SHARED_SET_ITERATOR
1309     factory->NewJSSetIterator(tester.NewJSSharedSet(), IterationKind::KEY);
1310     // JS_REG_EXP_ITERATOR
1311     tester.NewJSRegExpIterator();
1312     // JS_ARRAY_ITERATOR
1313     factory->NewJSArrayIterator(JSHandle<JSObject>::Cast(factory->NewJSArray()), IterationKind::KEY);
1314     // JS_STRING_ITERATOR
1315     JSStringIterator::CreateStringIterator(thread_, factory->GetEmptyString());
1316 
1317     tester.GenerateSnapShot("testGenerateNodeName_6.heapsnapshot");
1318     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_6.heapsnapshot", "\"ForinInterator\""));
1319     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_6.heapsnapshot", "\"MapIterator\""));
1320     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_6.heapsnapshot", "\"SharedMapIterator\""));
1321     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_6.heapsnapshot", "\"SetIterator\""));
1322     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_6.heapsnapshot", "\"SharedSetIterator\""));
1323     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_6.heapsnapshot", "\"RegExpIterator\""));
1324     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_6.heapsnapshot", "\"ArrayIterator\""));
1325     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_6.heapsnapshot", "\"StringIterator\""));
1326 }
1327 
HWTEST_F_L0(HeapDumpTest,TestHeapDumpGenerateNodeName7)1328 HWTEST_F_L0(HeapDumpTest, TestHeapDumpGenerateNodeName7)
1329 {
1330     ObjectFactory *factory = ecmaVm_->GetFactory();
1331     HeapDumpTestHelper tester(ecmaVm_);
1332     // JS_ARRAY_BUFFER
1333     factory->NewJSArrayBuffer(10);
1334     // JS_SHARED_ARRAY_BUFFER
1335     factory->NewJSSharedArrayBuffer(10);
1336     // PROMISE_REACTIONS
1337     factory->NewPromiseReaction();
1338     // PROMISE_CAPABILITY
1339     factory->NewPromiseCapability();
1340     // PROMISE_ITERATOR_RECORD
1341     tester.NewPromiseIteratorRecord();
1342     // PROMISE_RECORD
1343     factory->NewPromiseRecord();
1344     // RESOLVING_FUNCTIONS_RECORD
1345     factory->NewResolvingFunctionsRecord();
1346     // JS_PROMISE
1347     JSHandle<JSTaggedValue> proto = ecmaVm_->GetGlobalEnv()->GetFunctionPrototype();
1348     tester.NewObject(JSPromise::SIZE, JSType::JS_PROMISE, proto);
1349     // ASYNC_GENERATOR_REQUEST
1350     factory->NewAsyncGeneratorRequest();
1351 
1352     tester.GenerateSnapShot("testGenerateNodeName_7.heapsnapshot");
1353     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_7.heapsnapshot", "\"ArrayBuffer\""));
1354     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_7.heapsnapshot", "\"SharedArrayBuffer\""));
1355     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_7.heapsnapshot", "\"PromiseReaction\""));
1356     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_7.heapsnapshot", "\"PromiseCapability\""));
1357     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_7.heapsnapshot", "\"PromiseIteratorRecord\""));
1358     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_7.heapsnapshot", "\"PromiseRecord\""));
1359     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_7.heapsnapshot", "\"ResolvingFunctionsRecord\""));
1360     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_7.heapsnapshot", "\"Promise\""));
1361     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_7.heapsnapshot", "\"AsyncGeneratorRequest\""));
1362 }
1363 
HWTEST_F_L0(HeapDumpTest,TestHeapDumpGenerateNodeName8)1364 HWTEST_F_L0(HeapDumpTest, TestHeapDumpGenerateNodeName8)
1365 {
1366     auto factory = ecmaVm_->GetFactory();
1367     HeapDumpTestHelper tester(ecmaVm_);
1368     // JS_API_ARRAY_LIST
1369     auto jsAPIArrayList = tester.NewJSAPIArrayList();
1370     // JS_API_ARRAYLIST_ITERATOR
1371     factory->NewJSAPIArrayListIterator(jsAPIArrayList);
1372     // JS_API_HASH_MAP
1373     auto jsAPIHashMap = tester.NewJSAPIHashMap();
1374     // JS_API_HASHMAP_ITERATOR
1375     factory->NewJSAPIHashMapIterator(jsAPIHashMap, IterationKind::KEY);
1376     // JS_API_HASH_SET
1377     auto jsAPIHashSet = tester.NewJSAPIHashSet();
1378     // JS_API_HASHSET_ITERATOR
1379     factory->NewJSAPIHashSetIterator(jsAPIHashSet, IterationKind::KEY);
1380     // JS_API_LIGHT_WEIGHT_MAP
1381     auto jsAPILightWeightMap = tester.NewJSAPILightWeightMap();
1382     // JS_API_LIGHT_WEIGHT_MAP_ITERATOR
1383     factory->NewJSAPILightWeightMapIterator(jsAPILightWeightMap, IterationKind::KEY);
1384     // JS_API_LIGHT_WEIGHT_SET
1385     auto jsAPILightWeightSet = tester.NewJSAPILightWeightSet();
1386     // JS_API_LIGHT_WEIGHT_SET_ITERATOR
1387     factory->NewJSAPILightWeightSetIterator(jsAPILightWeightSet, IterationKind::KEY);
1388 
1389     tester.GenerateSnapShot("testGenerateNodeName_8.heapsnapshot");
1390     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_8.heapsnapshot", "\"ArrayList\""));
1391     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_8.heapsnapshot", "\"ArrayListIterator\""));
1392     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_8.heapsnapshot", "\"HashMap\""));
1393     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_8.heapsnapshot", "\"HashSet\""));
1394     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_8.heapsnapshot", "\"HashMapIterator\""));
1395     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_8.heapsnapshot", "\"HashSetIterator\""));
1396     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_8.heapsnapshot", "\"LightWeightMap\""));
1397     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_8.heapsnapshot", "\"LightWeightMapIterator\""));
1398     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_8.heapsnapshot", "\"LightWeightSet\""));
1399     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_8.heapsnapshot", "\"LightWeightSetIterator\""));
1400 }
1401 
HWTEST_F_L0(HeapDumpTest,TestHeapDumpGenerateNodeName9)1402 HWTEST_F_L0(HeapDumpTest, TestHeapDumpGenerateNodeName9)
1403 {
1404     auto factory = ecmaVm_->GetFactory();
1405     HeapDumpTestHelper tester(ecmaVm_);
1406     // JS_API_TREE_MAP
1407     auto jsAPITreeMap = tester.NewJSAPITreeMap();
1408     // JS_API_TREEMAP_ITERATOR
1409     factory->NewJSAPITreeMapIterator(jsAPITreeMap, IterationKind::KEY);
1410     // JS_API_TREE_SET
1411     auto jsAPITreeSet = tester.NewJSAPITreeSet();
1412     // JS_API_TREESET_ITERATOR
1413     factory->NewJSAPITreeSetIterator(jsAPITreeSet, IterationKind::KEY);
1414     // JS_API_VECTOR
1415     auto jsAPIVector = tester.NewJSAPIVector();
1416     // JS_API_VECTOR_ITERATOR
1417     factory->NewJSAPIVectorIterator(jsAPIVector);
1418     // JS_API_QUEUE
1419     auto jsAPIQueue = tester.NewJSAPIQueue();
1420     // JS_API_QUEUE_ITERATOR
1421     factory->NewJSAPIQueueIterator(jsAPIQueue);
1422     // JS_API_DEQUE
1423     auto jsAPIDeque = tester.NewJSAPIDeque();
1424     // JS_API_DEQUE_ITERATOR
1425     factory->NewJSAPIDequeIterator(jsAPIDeque);
1426     // JS_API_STACK
1427     auto jsAPIStack = tester.NewJSAPIStack();
1428     // JS_API_STACK_ITERATOR
1429     factory->NewJSAPIStackIterator(jsAPIStack);
1430     // JS_API_LIST
1431     tester.NewJSAPIList();
1432     // JS_API_LINKED_LIST
1433     tester.NewJSAPILinkedList();
1434     // JS_API_PLAIN_ARRAY
1435     auto jsAPIPlainArray = tester.NewJSAPIPlainArray();
1436     // JS_API_PLAIN_ARRAY_ITERATOR
1437     factory->NewJSAPIPlainArrayIterator(jsAPIPlainArray, IterationKind::KEY);
1438 
1439     tester.GenerateSnapShot("testGenerateNodeName_9.heapsnapshot");
1440     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_9.heapsnapshot", "\"TreeMap\""));
1441     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_9.heapsnapshot", "\"TreeMapIterator\""));
1442     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_9.heapsnapshot", "\"TreeSet\""));
1443     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_9.heapsnapshot", "\"TreeSetIterator\""));
1444     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_9.heapsnapshot", "\"Vector\""));
1445     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_9.heapsnapshot", "\"VectorIterator\""));
1446     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_9.heapsnapshot", "\"Queue\""));
1447     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_9.heapsnapshot", "\"QueueIterator\""));
1448     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_9.heapsnapshot", "\"Deque\""));
1449     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_9.heapsnapshot", "\"DequeIterator\""));
1450     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_9.heapsnapshot", "\"Stack\""));
1451     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_9.heapsnapshot", "\"StackIterator\""));
1452     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_9.heapsnapshot", "\"List\""));
1453     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_9.heapsnapshot", "\"LinkedList\""));
1454     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_9.heapsnapshot", "\"PlainArray\""));
1455     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_9.heapsnapshot", "\"PlainArrayIterator\""));
1456 }
1457 
HWTEST_F_L0(HeapDumpTest,TestHeapDumpGenerateNodeName10)1458 HWTEST_F_L0(HeapDumpTest, TestHeapDumpGenerateNodeName10)
1459 {
1460     auto factory = ecmaVm_->GetFactory();
1461     HeapDumpTestHelper tester(ecmaVm_);
1462     // JS_WEAK_REF
1463     tester.NewJSWeakRef();
1464     // JS_FINALIZATION_REGISTRY
1465     tester.NewJSFinalizationRegistry();
1466     // JS_ASYNC_FROM_SYNC_ITERATOR
1467     tester.NewJSAsyncFromSyncIterator();
1468     // JS_API_LINKED_LIST_ITERATOR
1469     tester.NewJSAPILinkedListIterator();
1470     // JS_API_LIST_ITERATOR
1471     tester.NewJSAPIListIterator();
1472     // JS_SHARED_ARRAY_ITERATOR
1473     tester.NewJSSharedArrayIterator();
1474     // JS_SHARED_INT8_ARRAY
1475     // JS_SHARED_UINT8_ARRAY
1476     // JS_SHARED_UINT8_CLAMPED_ARRAY
1477     // JS_SHARED_INT16_ARRAY
1478     // JS_SHARED_UINT16_ARRAY
1479     // JS_SHARED_INT32_ARRAY
1480     // JS_SHARED_UINT32_ARRAY
1481     // JS_SHARED_FLOAT32_ARRAY
1482     // JS_SHARED_FLOAT64_ARRAY
1483     // JS_SHARED_BIGINT64_ARRAY
1484     // JS_SHARED_BIGUINT64_ARRAY
1485     tester.NewSharedTypedArray();
1486     // BYTE_ARRAY
1487     tester.NewByteArray();
1488     // RB_TREENODE
1489     tester.NewRBTreeNode();
1490     // ENUM_CACHE
1491     factory->NewEnumCache();
1492     // CLASS_LITERAL
1493     factory->NewClassLiteral();
1494     // ASYNC_ITERATOR_RECORD
1495     tester.NewAsyncIteratorRecord();
1496     // PROFILE_TYPE_INFO_CELL
1497     tester.NewProfileTypeInfoCell();
1498     // CELL_RECORD
1499     factory->NewCellRecord();
1500     // NATIVE_MODULE_FAILURE_INFO
1501     factory->NewNativeModuleFailureInfo();
1502     // MUTANT_TAGGED_ARRAY
1503     factory->NewMutantTaggedArray(10); // 10: arrayLength
1504     // COW_MUTANT_TAGGED_ARRAY
1505     factory->NewCOWMutantTaggedArray(10); // 10: arrayLength
1506     // EXTRA_PROFILE_TYPE_INFO
1507     factory->NewExtraProfileTypeInfo();
1508 
1509     tester.GenerateSnapShot("testGenerateNodeName_10.heapsnapshot");
1510     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_10.heapsnapshot", "\"WeakRef\""));
1511     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_10.heapsnapshot", "\"JSFinalizationRegistry\""));
1512     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_10.heapsnapshot", "\"AsyncFromSyncIterator\""));
1513     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_10.heapsnapshot", "\"LinkedListIterator\""));
1514     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_10.heapsnapshot", "\"ListIterator\""));
1515     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_10.heapsnapshot", "\"SharedArrayIterator\""));
1516     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_10.heapsnapshot", "\"ByteArray\""));
1517     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_10.heapsnapshot", "\"RBTreeNode\""));
1518     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_10.heapsnapshot", "\"EnumCache\""));
1519     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_10.heapsnapshot", "\"ClassLiteral\""));
1520     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_10.heapsnapshot", "\"AsyncIteratorRecord\""));
1521     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_10.heapsnapshot", "\"ProfileTypeInfoCell\""));
1522     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_10.heapsnapshot", "\"CellRecord\""));
1523     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_10.heapsnapshot", "\"NativeModuleFailureInfo\""));
1524     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_10.heapsnapshot", "\"MutantTaggedArray\""));
1525     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_10.heapsnapshot", "\"COWMutantTaggedArray\""));
1526     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_10.heapsnapshot", "\"ExtraProfileTypeInfo\""));
1527     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_10.heapsnapshot", "\"Shared Int8 Array\""));
1528     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_10.heapsnapshot", "\"Shared Uint8 Array\""));
1529     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_10.heapsnapshot", "\"Shared Uint8 Clamped Array\""));
1530     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_10.heapsnapshot", "\"Shared Int16 Array\""));
1531     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_10.heapsnapshot", "\"Shared Uint16 Array\""));
1532     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_10.heapsnapshot", "\"Shared Int32 Array\""));
1533     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_10.heapsnapshot", "\"Shared Uint32 Array\""));
1534     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_10.heapsnapshot", "\"Shared Float32 Array\""));
1535     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_10.heapsnapshot", "\"Shared Float64 Array\""));
1536     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_10.heapsnapshot", "\"Shared BigInt64 Array\""));
1537     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_10.heapsnapshot", "\"Shared BigUint64 Array\""));
1538 }
1539 
1540 #ifndef PANDA_TARGET_ARM32
1541 #define CREATE_OBJECT_AND_ADD_REFS(generator, typeName, refs)           \
1542     {                                                                   \
1543         auto obj = generator->New##typeName();                          \
1544         refs.emplace_back(#typeName, obj.GetTaggedValue());             \
1545         obj.GetTaggedValue().DumpForSnapshot(thread, refs);             \
1546     }
1547 
1548 #define CREATE_ARRAY_AND_ADD_REFS(generator, typeName, length, refs)    \
1549     {                                                                   \
1550         auto obj = generator->New##typeName(length);                    \
1551         refs.emplace_back(#typeName, obj.GetTaggedValue());             \
1552         obj.GetTaggedValue().DumpForSnapshot(thread, refs);             \
1553     }
1554 
CreateObjectsForBinaryDump(JSThread * thread,ObjectFactory * factory,HeapDumpTestHelper * tester,std::vector<Reference> & refs)1555 void CreateObjectsForBinaryDump(JSThread *thread, ObjectFactory *factory, HeapDumpTestHelper *tester,
1556                                 std::vector<Reference> &refs)
1557 {
1558     CREATE_OBJECT_AND_ADD_REFS(factory, PromiseRecord, refs)
1559     CREATE_OBJECT_AND_ADD_REFS(factory, PromiseReaction, refs)
1560     CREATE_OBJECT_AND_ADD_REFS(factory, PromiseCapability, refs)
1561     CREATE_OBJECT_AND_ADD_REFS(factory, ResolvingFunctionsRecord, refs)
1562     CREATE_OBJECT_AND_ADD_REFS(factory, AsyncGeneratorRequest, refs)
1563     CREATE_OBJECT_AND_ADD_REFS(tester, PromiseIteratorRecord, refs)
1564     CREATE_OBJECT_AND_ADD_REFS(tester, JSWeakSet, refs)
1565     CREATE_OBJECT_AND_ADD_REFS(tester, JSWeakMap, refs)
1566     CREATE_ARRAY_AND_ADD_REFS(factory, JSArrayBuffer, 10, refs)
1567     CREATE_ARRAY_AND_ADD_REFS(factory, JSSharedArrayBuffer, 10, refs)
1568 }
1569 
HWTEST_F_L0(HeapDumpTest,TestHeapDumpBinaryDumpV0)1570 HWTEST_F_L0(HeapDumpTest, TestHeapDumpBinaryDumpV0)
1571 {
1572     ObjectFactory *factory = ecmaVm_->GetFactory();
1573     HeapDumpTestHelper tester(ecmaVm_);
1574     std::vector<Reference> vec;
1575     CreateObjectsForBinaryDump(thread_, factory, &tester, vec);
1576 
1577     std::string rawHeapPath("test_binary_dump_v0.rawheap");
1578     DumpSnapShotOption dumpOption;
1579     ASSERT_TRUE(tester.GenerateRawHeapSnashot(rawHeapPath, dumpOption));
1580 
1581     FILE* file = std::fopen(rawHeapPath.c_str(), "rb+");
1582     ASSERT_TRUE(file != nullptr);
1583 
1584     char version[sizeof(uint64_t)];
1585     *reinterpret_cast<uint64_t *>(version) = 0;
1586     std::fseek(file, 0, SEEK_SET);
1587     std::fwrite(version, sizeof(char), sizeof(version), file);
1588     std::fclose(file);
1589 
1590     std::string heapsnapshotPath("test_binary_dump_v0.heapsnapshot");
1591     ASSERT_TRUE(tester.AddMetaDataJsonToRawheap(rawHeapPath));
1592     ASSERT_TRUE(tester.DecodeRawheap(rawHeapPath, heapsnapshotPath));
1593 }
1594 
HWTEST_F_L0(HeapDumpTest,TestHeapDumpBinaryDumpV1)1595 HWTEST_F_L0(HeapDumpTest, TestHeapDumpBinaryDumpV1)
1596 {
1597     ObjectFactory *factory = ecmaVm_->GetFactory();
1598     HeapDumpTestHelper tester(ecmaVm_);
1599     std::vector<Reference> vec;
1600     CreateObjectsForBinaryDump(thread_, factory, &tester, vec);
1601 
1602     std::string rawHeapPath("test_binary_dump_v1.rawheap");
1603     DumpSnapShotOption dumpOption;
1604     ASSERT_TRUE(tester.GenerateRawHeapSnashot(rawHeapPath, dumpOption));
1605 
1606     CSet<JSTaggedType> dumpObjects;
1607     ASSERT_TRUE(tester.DecodeRawHeapObjectTableV1(rawHeapPath, dumpObjects));
1608 
1609     ASSERT_TRUE(tester.MatchHeapObjectReferencesV1(vec, dumpObjects));
1610 
1611     std::string heapsnapshotPath("test_binary_dump_v1.heapsnapshot");
1612     ASSERT_TRUE(tester.AddMetaDataJsonToRawheap(rawHeapPath));
1613     ASSERT_TRUE(tester.DecodeRawheap(rawHeapPath, heapsnapshotPath));
1614 }
1615 
HWTEST_F_L0(HeapDumpTest,TestHeapDumpBinaryDumpV2)1616 HWTEST_F_L0(HeapDumpTest, TestHeapDumpBinaryDumpV2)
1617 {
1618     ObjectFactory *factory = ecmaVm_->GetFactory();
1619     HeapDumpTestHelper tester(ecmaVm_);
1620     std::vector<Reference> vec;
1621     CreateObjectsForBinaryDump(thread_, factory, &tester, vec);
1622 
1623     std::string rawHeapPath("test_binary_dump_v2.rawheap");
1624     Runtime::GetInstance()->SetRawHeapDumpCropLevel(RawHeapDumpCropLevel::LEVEL_V2);
1625     DumpSnapShotOption dumpOption;
1626     ASSERT_TRUE(tester.GenerateRawHeapSnashot(rawHeapPath, dumpOption));
1627 
1628     CSet<uint32_t> dumpObjects;
1629     ASSERT_TRUE(tester.DecodeRawHeapObjectTableV2(rawHeapPath, dumpObjects));
1630 
1631     ASSERT_TRUE(tester.MatchHeapObjectReferencesV2(vec, dumpObjects));
1632     Runtime::GetInstance()->SetRawHeapDumpCropLevel(RawHeapDumpCropLevel::DEFAULT);
1633 
1634     std::string heapsnapshotPath("test_binary_dump_v2.heapsnapshot");
1635     ASSERT_TRUE(tester.AddMetaDataJsonToRawheap(rawHeapPath));
1636     ASSERT_TRUE(tester.DecodeRawheap(rawHeapPath, heapsnapshotPath));
1637 }
1638 
HWTEST_F_L0(HeapDumpTest,TestHeapDumpBinaryDumpByForkWithCallback)1639 HWTEST_F_L0(HeapDumpTest, TestHeapDumpBinaryDumpByForkWithCallback)
1640 {
1641     ObjectFactory *factory = ecmaVm_->GetFactory();
1642     HeapDumpTestHelper tester(ecmaVm_);
1643     std::vector<Reference> vec;
1644     CreateObjectsForBinaryDump(thread_, factory, &tester, vec);
1645 
1646     bool status = true;
1647     std::string rawHeapPath("test_binary_dump_by_fork_with_callback.raw");
1648     auto cb = [&status](uint8_t retCode) {
1649         if (retCode != static_cast<uint8_t>(DumpHeapSnapshotStatus::SUCCESS)) {
1650             status = false;
1651         }
1652     };
1653     DumpSnapShotOption dumpOption;
1654     dumpOption.isSync = false;
1655     ASSERT_TRUE(tester.GenerateRawHeapSnashot(rawHeapPath, dumpOption, nullptr, cb));
1656     ASSERT_TRUE(status);
1657 }
1658 
HWTEST_F_L0(HeapDumpTest,TestGenerateMixedNodeId)1659 HWTEST_F_L0(HeapDumpTest, TestGenerateMixedNodeId)
1660 {
1661     ObjectFactory *factory = ecmaVm_->GetFactory();
1662     HeapDumpTestHelper tester(ecmaVm_);
1663     std::vector<Reference> vec;
1664     CreateObjectsForBinaryDump(thread_, factory, &tester, vec);
1665 
1666     for (auto ref : vec) {
1667         if (ref.value_.IsJSObject()) {
1668             int32_t hash = base::RandomGenerator::GenerateIdentityHash();
1669             JSHandle<ECMAObject> ecmaObj(thread_, ref.value_);
1670             ECMAObject::SetHash(thread_, hash, ecmaObj);
1671         }
1672     }
1673 
1674     std::string rawHeapPath("test_binary_dump_for_mixed_node_id.rawheap");
1675     DumpSnapShotOption dumpOption;
1676     dumpOption.isSync = false;
1677     dumpOption.isJSLeakWatcher = true;
1678     ASSERT_TRUE(tester.GenerateRawHeapSnashot(rawHeapPath, dumpOption));
1679     ASSERT_TRUE(tester.CheckHashInNodeId(thread_, vec, rawHeapPath));
1680 }
1681 #endif
1682 
HWTEST_F_L0(HeapDumpTest,TestSharedFullGCInHeapDump)1683 HWTEST_F_L0(HeapDumpTest, TestSharedFullGCInHeapDump)
1684 {
1685     ObjectFactory *factory = ecmaVm_->GetFactory();
1686     HeapDumpTestHelper tester(ecmaVm_);
1687 
1688     JSHandle<JSTaggedValue> proto = ecmaVm_->GetGlobalEnv()->GetFunctionPrototype();
1689     // JS_SET
1690     tester.NewJSSet();
1691     // JS_SHARED_SET
1692     tester.NewJSSharedSet();
1693     // JS_MAP
1694     tester.NewJSMap();
1695     // JS_SHARED_MAP
1696     tester.NewJSSharedMap();
1697     // JS_WEAK_SET
1698     tester.NewJSWeakSet();
1699     // JS_WEAK_MAP
1700     tester.NewJSWeakMap();
1701     // JS_ARRAY
1702     factory->NewJSArray();
1703     // JS_TYPED_ARRAY
1704     tester.NewObject(JSTypedArray::SIZE, JSType::JS_TYPED_ARRAY, proto);
1705     tester.GenerateSnapShot("testGenerateNodeName_4.heapsnapshot");
1706 
1707     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_4.heapsnapshot", "\"Set\""));
1708     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_4.heapsnapshot", "\"SharedSet\""));
1709     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_4.heapsnapshot", "\"Map\""));
1710     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_4.heapsnapshot", "\"SharedMap\""));
1711     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_4.heapsnapshot", "\"WeakSet\""));
1712     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_4.heapsnapshot", "\"WeakMap\""));
1713     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_4.heapsnapshot", "\"JSArray\""));
1714     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_4.heapsnapshot", "\"Typed Array\""));
1715 
1716     auto sHeap = SharedHeap::GetInstance();
1717     sHeap->CollectGarbage<TriggerGCType::SHARED_FULL_GC, GCReason::OTHER>(thread_);
1718 
1719     tester.GenerateSnapShot("testGenerateNodeName_4.heapsnapshot");
1720 
1721     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_4.heapsnapshot", "\"Set\""));
1722     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_4.heapsnapshot", "\"SharedSet\""));
1723     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_4.heapsnapshot", "\"Map\""));
1724     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_4.heapsnapshot", "\"SharedMap\""));
1725     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_4.heapsnapshot", "\"WeakSet\""));
1726     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_4.heapsnapshot", "\"WeakMap\""));
1727     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_4.heapsnapshot", "\"JSArray\""));
1728     ASSERT_TRUE(tester.MatchHeapDumpString("testGenerateNodeName_4.heapsnapshot", "\"Typed Array\""));
1729 }
1730 
HWTEST_F_L0(HeapDumpTest,TestMarkObjects)1731 HWTEST_F_L0(HeapDumpTest, TestMarkObjects)
1732 {
1733     HeapDumpTestHelper tester(ecmaVm_);
1734     JSHandle<JSMap> jsMap = tester.NewJSMap();
1735     JSHandle<JSSet> jsSet = tester.NewJSSet();
1736     JSHandle<JSAPIArrayList> jsAPIArrayList = tester.NewJSAPIArrayList();
1737     [[maybe_unused]] JSHandle<JSAPIDeque> jsAPIDeque = tester.NewJSAPIDeque();
1738     [[maybe_unused]] JSHandle<JSSharedMap> jsSharedMap = tester.NewJSSharedMap();
1739     [[maybe_unused]] JSHandle<JSWeakMap> jsWeakMap = tester.NewJSWeakMap();
1740 
1741     HeapMarker marker {};
1742     marker.Mark(jsMap.GetTaggedType());
1743     marker.Mark(jsSet.GetTaggedType());
1744     marker.Mark(jsAPIArrayList.GetTaggedType());
1745 
1746     ASSERT_TRUE(marker.IsMarked(jsMap.GetTaggedType()));
1747     ASSERT_FALSE(marker.IsMarked(jsSharedMap.GetTaggedType()));
1748 }
1749 
HWTEST_F_L0(HeapDumpTest,TestIterateMarkedObjects)1750 HWTEST_F_L0(HeapDumpTest, TestIterateMarkedObjects)
1751 {
1752     HeapDumpTestHelper tester(ecmaVm_);
1753     JSHandle<JSMap> jsMap = tester.NewJSMap();
1754     JSHandle<JSSet> jsSet = tester.NewJSSet();
1755     JSHandle<JSAPIArrayList> jsAPIArrayList = tester.NewJSAPIArrayList();
1756     [[maybe_unused]] JSHandle<JSAPIDeque> jsAPIDeque = tester.NewJSAPIDeque();
1757     [[maybe_unused]] JSHandle<JSSharedMap> jsSharedMap = tester.NewJSSharedMap();
1758     [[maybe_unused]] JSHandle<JSWeakMap> jsWeakMap = tester.NewJSWeakMap();
1759 
1760     HeapMarker marker {};
1761     marker.Mark(jsMap.GetTaggedType());
1762     marker.Mark(jsSet.GetTaggedType());
1763     marker.Mark(jsAPIArrayList.GetTaggedType());
1764 
1765     std::unordered_set<uintptr_t> markedObjects;
1766     markedObjects.emplace(jsMap.GetTaggedType());
1767     markedObjects.emplace(jsSet.GetTaggedType());
1768     markedObjects.emplace(jsAPIArrayList.GetTaggedType());
1769     std::function<void(JSTaggedType addr)> callback = [markedObjects](JSTaggedType addr) {
1770         ASSERT_TRUE(markedObjects.find(addr) != markedObjects.end());
1771     };
1772     marker.IterateMarked(callback);
1773 }
1774 
HWTEST_F_L0(HeapDumpTest,TestRemoveUnmarkedObjects)1775 HWTEST_F_L0(HeapDumpTest, TestRemoveUnmarkedObjects)
1776 {
1777     HeapDumpTestHelper tester(ecmaVm_);
1778     JSHandle<JSMap> jsMap = tester.NewJSMap();
1779     JSHandle<JSSet> jsSet = tester.NewJSSet();
1780     JSHandle<JSAPIArrayList> jsAPIArrayList = tester.NewJSAPIArrayList();
1781     JSHandle<JSAPIDeque> jsAPIDeque = tester.NewJSAPIDeque();
1782     JSHandle<JSSharedMap> jsSharedMap = tester.NewJSSharedMap();
1783     JSHandle<JSWeakMap> jsWeakMap = tester.NewJSWeakMap();
1784 
1785     EntryIdMap entryIdMap {};
1786     entryIdMap.InsertId(jsMap.GetTaggedType(), entryIdMap.GetNextId());
1787     entryIdMap.InsertId(jsSet.GetTaggedType(), entryIdMap.GetNextId());
1788     entryIdMap.InsertId(jsAPIArrayList.GetTaggedType(), entryIdMap.GetNextId());
1789     entryIdMap.InsertId(jsAPIDeque.GetTaggedType(), entryIdMap.GetNextId());
1790     entryIdMap.InsertId(jsSharedMap.GetTaggedType(), entryIdMap.GetNextId());
1791     entryIdMap.InsertId(jsWeakMap.GetTaggedType(), entryIdMap.GetNextId());
1792     ASSERT_EQ(entryIdMap.GetIdMap()->size(), 6);
1793 
1794     HeapMarker marker {};
1795     marker.Mark(jsMap.GetTaggedType());
1796     marker.Mark(jsSet.GetTaggedType());
1797     marker.Mark(jsAPIArrayList.GetTaggedType());
1798     marker.Mark(jsAPIDeque.GetTaggedType());
1799 
1800     entryIdMap.RemoveUnmarkedObjects(marker);
1801     ASSERT_EQ(entryIdMap.GetIdMap()->size(), 4);
1802 }
1803 }
1804