diff --git a/ecmascript/dfx/hprof/rawheap_translate/rawheap_translate.cpp b/ecmascript/dfx/hprof/rawheap_translate/rawheap_translate.cpp index 901b8d11d73c58fbff077fbfe50d4db09b584de2..6ce0ed7b31b227a592bfe091e7b15498df96d9c1 100755 --- a/ecmascript/dfx/hprof/rawheap_translate/rawheap_translate.cpp +++ b/ecmascript/dfx/hprof/rawheap_translate/rawheap_translate.cpp @@ -180,6 +180,33 @@ void RawHeap::SetVersion(const std::string &version) version_ = version; } +void RawHeap::CreateHashEdge(Node *node) +{ + static const StringId hashStrId = InsertAndGetStringId("ArkInternalHash"); + uint32_t hash = static_cast(node->nodeId >> 32); // 32: the high-32bits means hash value + node->nodeId &= 0xFFFFFFFFULL; + if (hash == 0) { + return; + } + + Node *hashNode = new Node(nodeIndex_++); + hashNode->nodeId = 0; + hashNode->type = 7; // 7: means HEAPNUMBER + hashNode->strId = InsertAndGetStringId("Int: " + std::to_string(hash)); + InsertEdge(hashNode, hashStrId, EdgeType::DEFAULT); + primitiveNodes_.push_back(hashNode); + node->edgeCount++; + +#ifdef OHOS_UNIT_TEST + hashSet_.insert(hash); +#endif +} + +void RawHeap::AddPrimitiveNodes() +{ + nodes_.insert(nodes_.end(), primitiveNodes_.begin(), primitiveNodes_.end()); +} + bool RawHeap::ReadSectionInfo(FileReader &file, uint32_t offset, std::vector §ion) { if (!file.CheckAndGetHeaderAt(offset - sizeof(uint64_t), sizeof(uint32_t))) { @@ -236,10 +263,13 @@ bool RawHeapTranslateV1::Translate() JSType type = metaParser_->GetJSTypeFromHClass(hclass); FillNodes(node, type); CreateHClassEdge(node, hclass); + CreateHashEdge(node); if (!metaParser_->IsString(type)) { BuildEdges(node, type); } } + + AddPrimitiveNodes(); LOG_INFO_ << "success!"; return true; } @@ -567,11 +597,14 @@ bool RawHeapTranslateV2::Translate() CreateEdge(node, hclass, InsertAndGetStringId("hclass"), EdgeType::DEFAULT); } + CreateHashEdge(node); if (metaParser_->IsString(node->jsType)) { continue; } BuildEdges(node); } + + AddPrimitiveNodes(); LOG_INFO_ << "success!"; return true; } diff --git a/ecmascript/dfx/hprof/rawheap_translate/rawheap_translate.h b/ecmascript/dfx/hprof/rawheap_translate/rawheap_translate.h index c69803429c74e044c2991335754a241fc2acc2a2..1149703e7688b04b06f3ebf26c615f50f8396752 100644 --- a/ecmascript/dfx/hprof/rawheap_translate/rawheap_translate.h +++ b/ecmascript/dfx/hprof/rawheap_translate/rawheap_translate.h @@ -54,15 +54,24 @@ protected: void InsertEdge(Node *toNode, uint32_t indexOrStrId, EdgeType type); StringId InsertAndGetStringId(const std::string &str); void SetVersion(const std::string &version); + void CreateHashEdge(Node *node); + void AddPrimitiveNodes(); static bool ReadSectionInfo(FileReader &file, uint32_t offset, std::vector §ion); private: StringHashMap *strTable_ {nullptr}; + std::vector primitiveNodes_ {}; std::vector nodes_ {}; std::vector edges_ {}; std::string version_; uint32_t nodeIndex_ {0}; + +#ifdef OHOS_UNIT_TEST + std::unordered_set hashSet_ {}; +#endif + + friend class panda::test::HeapDumpTestHelper; }; class RawHeapTranslateV1 : public RawHeap { diff --git a/ecmascript/dfx/hprof/tests/BUILD.gn b/ecmascript/dfx/hprof/tests/BUILD.gn index 64f2ed573645057556f55b1591d48e7f4953a71e..5c7e90ddb9147d39823638f0c3bc5a90daea81a3 100644 --- a/ecmascript/dfx/hprof/tests/BUILD.gn +++ b/ecmascript/dfx/hprof/tests/BUILD.gn @@ -102,6 +102,7 @@ host_unittest_action("HeapDumpTest") { "HPROF_TEST_JS_FILES_DIR=\"${test_js_dir}\"", "HPROF_TEST_ABC_FILES_DIR=\"${test_abc_dir}\"", "HPROF_TEST_METADATA_JSON_DIR=\"${test_metadata_dir}\"", + "OHOS_UNIT_TEST", ] external_deps = [ diff --git a/ecmascript/dfx/hprof/tests/heap_dump_test.cpp b/ecmascript/dfx/hprof/tests/heap_dump_test.cpp index bb5ae380a26428c380073354698898b209514ec8..6b5c680fca3510175e119286aec1d6dd5c1c7faa 100644 --- a/ecmascript/dfx/hprof/tests/heap_dump_test.cpp +++ b/ecmascript/dfx/hprof/tests/heap_dump_test.cpp @@ -137,12 +137,19 @@ public: return true; } - bool CheckHashInNodeId(JSThread *thread, const std::vector &refs, const std::string &filePath) + bool CheckHashInRawheap(JSThread *thread, const std::vector &refs, const std::string &filePath) { uint64_t fileSize = rawheap_translate::FileReader::GetFileSize(filePath); rawheap_translate::FileReader file; - rawheap_translate::RawHeapTranslateV1 translate(nullptr); - if (!file.Initialize(filePath) || !translate.Parse(file, fileSize)) { + rawheap_translate::MetaParser metaParser; + + if (!file.Initialize(filePath) || !rawheap_translate::RawHeap::ParseMetaData(file, &metaParser) || + !file.CheckAndGetHeaderAt(fileSize - sizeof(uint64_t), 0)) { + return false; + } + + rawheap_translate::RawHeapTranslateV1 translate(&metaParser); + if (!translate.Parse(file, file.GetHeaderLeft()) || !translate.Translate()) { return false; } @@ -152,22 +159,21 @@ public: continue; } - auto it = translate.nodesMap_.find(ref.value_.GetRawData()); - if (it == translate.nodesMap_.end()) { - std::cout << "CheckHashInNodeId, missed object in rawheap." << std::endl; - return false; + uint32_t hash = static_cast(JSObject::Cast(ref.value_)->GetHash(thread)); + if (hash == 0) { + continue; } - ++checkCnt; - // 32: 32-bits means a half of uint64_t - if (JSObject::Cast(ref.value_)->GetHash(thread) != static_cast(it->second->nodeId >> 32)) { - std::cout << "CheckHashInNodeId, hash value verification failed!" << std::endl; + if (translate.hashSet_.find(hash) == translate.hashSet_.end()) { + std::cout << "CheckHashInRawheap, missed object hash in rawheap." << std::endl; return false; } + + ++checkCnt; } if (checkCnt == 0) { - std::cout << "CheckHashInNodeId, no JSObject." << std::endl; + std::cout << "CheckHashInRawheap, no JSObject." << std::endl; return false; } return true; @@ -1678,7 +1684,7 @@ HWTEST_F_L0(HeapDumpTest, TestHeapDumpBinaryDumpByForkWithCallback) ASSERT_TRUE(status); } -HWTEST_F_L0(HeapDumpTest, TestGenerateMixedNodeId) +HWTEST_F_L0(HeapDumpTest, TestGenerateHashInRawheap) { ObjectFactory *factory = ecmaVm_->GetFactory(); HeapDumpTestHelper tester(ecmaVm_); @@ -1698,7 +1704,8 @@ HWTEST_F_L0(HeapDumpTest, TestGenerateMixedNodeId) dumpOption.isSync = false; dumpOption.isJSLeakWatcher = true; ASSERT_TRUE(tester.GenerateRawHeapSnashot(rawHeapPath, dumpOption)); - ASSERT_TRUE(tester.CheckHashInNodeId(thread_, vec, rawHeapPath)); + ASSERT_TRUE(tester.AddMetaDataJsonToRawheap(rawHeapPath)); + ASSERT_TRUE(tester.CheckHashInRawheap(thread_, vec, rawHeapPath)); } HWTEST_F_L0(HeapDumpTest, TestDecodeRawheapAddrTableItemSizeMin)