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