14514f5e3Sopenharmony_ci/* 24514f5e3Sopenharmony_ci * Copyright (c) 2021-2022 Huawei Device Co., Ltd. 34514f5e3Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 44514f5e3Sopenharmony_ci * you may not use this file except in compliance with the License. 54514f5e3Sopenharmony_ci * You may obtain a copy of the License at 64514f5e3Sopenharmony_ci * 74514f5e3Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 84514f5e3Sopenharmony_ci * 94514f5e3Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 104514f5e3Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 114514f5e3Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 124514f5e3Sopenharmony_ci * See the License for the specific language governing permissions and 134514f5e3Sopenharmony_ci * limitations under the License. 144514f5e3Sopenharmony_ci */ 154514f5e3Sopenharmony_ci 164514f5e3Sopenharmony_ci#include "ecmascript/dfx/hprof/heap_snapshot.h" 174514f5e3Sopenharmony_ci 184514f5e3Sopenharmony_ci#include <functional> 194514f5e3Sopenharmony_ci 204514f5e3Sopenharmony_ci#include "ecmascript/ecma_string-inl.h" 214514f5e3Sopenharmony_ci#include "ecmascript/jspandafile/program_object.h" 224514f5e3Sopenharmony_ci 234514f5e3Sopenharmony_cinamespace panda::ecmascript { 244514f5e3Sopenharmony_ciCString *HeapSnapshot::GetString(const CString &as) 254514f5e3Sopenharmony_ci{ 264514f5e3Sopenharmony_ci return stringTable_->GetString(as); 274514f5e3Sopenharmony_ci} 284514f5e3Sopenharmony_ci 294514f5e3Sopenharmony_ciCString *HeapSnapshot::GetArrayString(TaggedArray *array, const CString &as) 304514f5e3Sopenharmony_ci{ 314514f5e3Sopenharmony_ci CString arrayName = as; 324514f5e3Sopenharmony_ci arrayName.append(ToCString(array->GetLength())); 334514f5e3Sopenharmony_ci arrayName.append("]"); 344514f5e3Sopenharmony_ci return GetString(arrayName); // String type was handled singly, see#GenerateStringNode 354514f5e3Sopenharmony_ci} 364514f5e3Sopenharmony_ci 374514f5e3Sopenharmony_ciNode *Node::NewNode(Chunk *chunk, NodeId id, size_t index, const CString *name, NodeType type, size_t size, 384514f5e3Sopenharmony_ci size_t nativeSize, JSTaggedType entry, bool isLive) 394514f5e3Sopenharmony_ci{ 404514f5e3Sopenharmony_ci auto node = chunk->New<Node>(id, index, name, type, size, nativeSize, 0, entry, isLive); 414514f5e3Sopenharmony_ci if (UNLIKELY(node == nullptr)) { 424514f5e3Sopenharmony_ci LOG_FULL(FATAL) << "internal allocator failed"; 434514f5e3Sopenharmony_ci UNREACHABLE(); 444514f5e3Sopenharmony_ci } 454514f5e3Sopenharmony_ci return node; 464514f5e3Sopenharmony_ci} 474514f5e3Sopenharmony_ci 484514f5e3Sopenharmony_ciEdge *Edge::NewEdge(Chunk *chunk, EdgeType type, Node *from, Node *to, CString *name) 494514f5e3Sopenharmony_ci{ 504514f5e3Sopenharmony_ci auto edge = chunk->New<Edge>(type, from, to, name); 514514f5e3Sopenharmony_ci if (UNLIKELY(edge == nullptr)) { 524514f5e3Sopenharmony_ci LOG_FULL(FATAL) << "internal allocator failed"; 534514f5e3Sopenharmony_ci UNREACHABLE(); 544514f5e3Sopenharmony_ci } 554514f5e3Sopenharmony_ci return edge; 564514f5e3Sopenharmony_ci} 574514f5e3Sopenharmony_ci 584514f5e3Sopenharmony_ciEdge *Edge::NewEdge(Chunk *chunk, EdgeType type, Node *from, Node *to, uint32_t index) 594514f5e3Sopenharmony_ci{ 604514f5e3Sopenharmony_ci auto edge = chunk->New<Edge>(type, from, to, index); 614514f5e3Sopenharmony_ci if (UNLIKELY(edge == nullptr)) { 624514f5e3Sopenharmony_ci LOG_FULL(FATAL) << "internal allocator failed"; 634514f5e3Sopenharmony_ci UNREACHABLE(); 644514f5e3Sopenharmony_ci } 654514f5e3Sopenharmony_ci return edge; 664514f5e3Sopenharmony_ci} 674514f5e3Sopenharmony_ci 684514f5e3Sopenharmony_ciHeapSnapshot::~HeapSnapshot() 694514f5e3Sopenharmony_ci{ 704514f5e3Sopenharmony_ci for (Node *node : nodes_) { 714514f5e3Sopenharmony_ci chunk_->Delete(node); 724514f5e3Sopenharmony_ci } 734514f5e3Sopenharmony_ci for (Edge *edge : edges_) { 744514f5e3Sopenharmony_ci chunk_->Delete(edge); 754514f5e3Sopenharmony_ci } 764514f5e3Sopenharmony_ci nodes_.clear(); 774514f5e3Sopenharmony_ci edges_.clear(); 784514f5e3Sopenharmony_ci traceInfoStack_.clear(); 794514f5e3Sopenharmony_ci stackInfo_.clear(); 804514f5e3Sopenharmony_ci scriptIdMap_.clear(); 814514f5e3Sopenharmony_ci methodToTraceNodeId_.clear(); 824514f5e3Sopenharmony_ci traceNodeIndex_.clear(); 834514f5e3Sopenharmony_ci entryIdMap_ = nullptr; 844514f5e3Sopenharmony_ci chunk_ = nullptr; 854514f5e3Sopenharmony_ci stringTable_ = nullptr; 864514f5e3Sopenharmony_ci} 874514f5e3Sopenharmony_ci 884514f5e3Sopenharmony_cibool HeapSnapshot::BuildUp(bool isSimplify) 894514f5e3Sopenharmony_ci{ 904514f5e3Sopenharmony_ci FillNodes(true, isSimplify); 914514f5e3Sopenharmony_ci FillEdges(isSimplify); 924514f5e3Sopenharmony_ci AddSyntheticRoot(); 934514f5e3Sopenharmony_ci return Verify(); 944514f5e3Sopenharmony_ci} 954514f5e3Sopenharmony_ci 964514f5e3Sopenharmony_cibool HeapSnapshot::Verify() 974514f5e3Sopenharmony_ci{ 984514f5e3Sopenharmony_ci GetString(CString("HeapVerify:").append(ToCString(totalNodesSize_))); 994514f5e3Sopenharmony_ci return (edgeCount_ > nodeCount_) && (totalNodesSize_ > 0); 1004514f5e3Sopenharmony_ci} 1014514f5e3Sopenharmony_ci 1024514f5e3Sopenharmony_civoid HeapSnapshot::PrepareSnapshot() 1034514f5e3Sopenharmony_ci{ 1044514f5e3Sopenharmony_ci FillNodes(); 1054514f5e3Sopenharmony_ci if (trackAllocations()) { 1064514f5e3Sopenharmony_ci PrepareTraceInfo(); 1074514f5e3Sopenharmony_ci } 1084514f5e3Sopenharmony_ci} 1094514f5e3Sopenharmony_ci 1104514f5e3Sopenharmony_civoid HeapSnapshot::UpdateNodes(bool isInFinish) 1114514f5e3Sopenharmony_ci{ 1124514f5e3Sopenharmony_ci for (Node *node : nodes_) { 1134514f5e3Sopenharmony_ci node->SetLive(false); 1144514f5e3Sopenharmony_ci } 1154514f5e3Sopenharmony_ci FillNodes(isInFinish); 1164514f5e3Sopenharmony_ci for (auto iter = nodes_.begin(); iter != nodes_.end();) { 1174514f5e3Sopenharmony_ci if (!(*iter)->IsLive()) { 1184514f5e3Sopenharmony_ci entryMap_.FindAndEraseNode((*iter)->GetAddress()); 1194514f5e3Sopenharmony_ci entryIdMap_->EraseId((*iter)->GetAddress()); 1204514f5e3Sopenharmony_ci DecreaseNodeSize((*iter)->GetSelfSize()); 1214514f5e3Sopenharmony_ci chunk_->Delete(*iter); 1224514f5e3Sopenharmony_ci iter = nodes_.erase(iter); 1234514f5e3Sopenharmony_ci nodeCount_--; 1244514f5e3Sopenharmony_ci } else { 1254514f5e3Sopenharmony_ci iter++; 1264514f5e3Sopenharmony_ci } 1274514f5e3Sopenharmony_ci } 1284514f5e3Sopenharmony_ci} 1294514f5e3Sopenharmony_ci 1304514f5e3Sopenharmony_cibool HeapSnapshot::FinishSnapshot() 1314514f5e3Sopenharmony_ci{ 1324514f5e3Sopenharmony_ci UpdateNodes(true); 1334514f5e3Sopenharmony_ci FillEdges(); 1344514f5e3Sopenharmony_ci AddSyntheticRoot(); 1354514f5e3Sopenharmony_ci return Verify(); 1364514f5e3Sopenharmony_ci} 1374514f5e3Sopenharmony_ci 1384514f5e3Sopenharmony_civoid HeapSnapshot::RecordSampleTime() 1394514f5e3Sopenharmony_ci{ 1404514f5e3Sopenharmony_ci timeStamps_.emplace_back(entryIdMap_->GetLastId()); 1414514f5e3Sopenharmony_ci} 1424514f5e3Sopenharmony_ci 1434514f5e3Sopenharmony_civoid HeapSnapshot::PushHeapStat(Stream* stream) 1444514f5e3Sopenharmony_ci{ 1454514f5e3Sopenharmony_ci CVector<HeapStat> statsBuffer; 1464514f5e3Sopenharmony_ci if (stream == nullptr) { 1474514f5e3Sopenharmony_ci LOG_DEBUGGER(ERROR) << "HeapSnapshot::PushHeapStat::stream is nullptr"; 1484514f5e3Sopenharmony_ci return; 1494514f5e3Sopenharmony_ci } 1504514f5e3Sopenharmony_ci int32_t preChunkSize = stream->GetSize(); 1514514f5e3Sopenharmony_ci int32_t sequenceId = 0; 1524514f5e3Sopenharmony_ci int64_t timeStampUs = 0; 1534514f5e3Sopenharmony_ci auto iter = nodes_.begin(); 1544514f5e3Sopenharmony_ci for (size_t timeIndex = 0; timeIndex < timeStamps_.size(); ++timeIndex) { 1554514f5e3Sopenharmony_ci TimeStamp& timeStamp = timeStamps_[timeIndex]; 1564514f5e3Sopenharmony_ci sequenceId = timeStamp.GetLastSequenceId(); 1574514f5e3Sopenharmony_ci timeStampUs = timeStamp.GetTimeStamp(); 1584514f5e3Sopenharmony_ci uint32_t nodesSize = 0; 1594514f5e3Sopenharmony_ci uint32_t nodesCount = 0; 1604514f5e3Sopenharmony_ci while (iter != nodes_.end() && (*iter)->GetId() <= static_cast<uint32_t>(sequenceId)) { 1614514f5e3Sopenharmony_ci nodesCount++; 1624514f5e3Sopenharmony_ci nodesSize += (*iter)->GetSelfSize(); 1634514f5e3Sopenharmony_ci iter++; 1644514f5e3Sopenharmony_ci } 1654514f5e3Sopenharmony_ci if ((timeStamp.GetCount() != nodesCount) || (timeStamp.GetSize() != nodesSize)) { 1664514f5e3Sopenharmony_ci timeStamp.SetCount(nodesCount); 1674514f5e3Sopenharmony_ci timeStamp.SetSize(nodesSize); 1684514f5e3Sopenharmony_ci statsBuffer.emplace_back(static_cast<int32_t>(timeIndex), nodesCount, nodesSize); 1694514f5e3Sopenharmony_ci if (static_cast<int32_t>(statsBuffer.size()) >= preChunkSize) { 1704514f5e3Sopenharmony_ci stream->UpdateHeapStats(&statsBuffer.front(), static_cast<int32_t>(statsBuffer.size())); 1714514f5e3Sopenharmony_ci statsBuffer.clear(); 1724514f5e3Sopenharmony_ci } 1734514f5e3Sopenharmony_ci } 1744514f5e3Sopenharmony_ci } 1754514f5e3Sopenharmony_ci if (!statsBuffer.empty()) { 1764514f5e3Sopenharmony_ci stream->UpdateHeapStats(&statsBuffer.front(), static_cast<int32_t>(statsBuffer.size())); 1774514f5e3Sopenharmony_ci statsBuffer.clear(); 1784514f5e3Sopenharmony_ci } 1794514f5e3Sopenharmony_ci stream->UpdateLastSeenObjectId(sequenceId, timeStampUs); 1804514f5e3Sopenharmony_ci} 1814514f5e3Sopenharmony_ci 1824514f5e3Sopenharmony_ciNode *HeapSnapshot::AddNode(TaggedObject *address, size_t size) 1834514f5e3Sopenharmony_ci{ 1844514f5e3Sopenharmony_ci return GenerateNode(JSTaggedValue(address), size); 1854514f5e3Sopenharmony_ci} 1864514f5e3Sopenharmony_ci 1874514f5e3Sopenharmony_civoid HeapSnapshot::MoveNode(uintptr_t address, TaggedObject *forwardAddress, size_t size) 1884514f5e3Sopenharmony_ci{ 1894514f5e3Sopenharmony_ci if (address == reinterpret_cast<uintptr_t>(forwardAddress)) { 1904514f5e3Sopenharmony_ci return; 1914514f5e3Sopenharmony_ci } 1924514f5e3Sopenharmony_ci 1934514f5e3Sopenharmony_ci Node *node = entryMap_.FindAndEraseNode(static_cast<JSTaggedType>(address)); 1944514f5e3Sopenharmony_ci if (node != nullptr) { 1954514f5e3Sopenharmony_ci ASSERT(node->GetId() <= UINT_MAX); 1964514f5e3Sopenharmony_ci 1974514f5e3Sopenharmony_ci Node *oldNode = entryMap_.FindAndEraseNode(Node::NewAddress(forwardAddress)); 1984514f5e3Sopenharmony_ci if (oldNode != nullptr) { 1994514f5e3Sopenharmony_ci oldNode->SetAddress(Node::NewAddress(TaggedObject::Cast(nullptr))); 2004514f5e3Sopenharmony_ci } 2014514f5e3Sopenharmony_ci 2024514f5e3Sopenharmony_ci // Size and name may change during its life for some types(such as string, array and etc). 2034514f5e3Sopenharmony_ci if (forwardAddress->GetClass() != nullptr) { 2044514f5e3Sopenharmony_ci node->SetName(GenerateNodeName(forwardAddress)); 2054514f5e3Sopenharmony_ci } 2064514f5e3Sopenharmony_ci if (JSTaggedValue(forwardAddress).IsString()) { 2074514f5e3Sopenharmony_ci node->SetSelfSize(EcmaStringAccessor(forwardAddress).GetFlatStringSize()); 2084514f5e3Sopenharmony_ci } else { 2094514f5e3Sopenharmony_ci node->SetSelfSize(size); 2104514f5e3Sopenharmony_ci } 2114514f5e3Sopenharmony_ci node->SetAddress(Node::NewAddress(forwardAddress)); 2124514f5e3Sopenharmony_ci entryMap_.InsertEntry(node); 2134514f5e3Sopenharmony_ci } else { 2144514f5e3Sopenharmony_ci LOG_DEBUGGER(WARN) << "Untracked object moves from " << address << " to " << forwardAddress; 2154514f5e3Sopenharmony_ci GenerateNode(JSTaggedValue(forwardAddress), size, false); 2164514f5e3Sopenharmony_ci } 2174514f5e3Sopenharmony_ci} 2184514f5e3Sopenharmony_ci 2194514f5e3Sopenharmony_ci// NOLINTNEXTLINE(readability-function-size) 2204514f5e3Sopenharmony_ciCString *HeapSnapshot::GenerateNodeName(TaggedObject *entry) 2214514f5e3Sopenharmony_ci{ 2224514f5e3Sopenharmony_ci auto *hCls = entry->GetClass(); 2234514f5e3Sopenharmony_ci JSType type = hCls->GetObjectType(); 2244514f5e3Sopenharmony_ci switch (type) { 2254514f5e3Sopenharmony_ci case JSType::TAGGED_ARRAY: 2264514f5e3Sopenharmony_ci return GetArrayString(TaggedArray::Cast(entry), "ArkInternalArray["); 2274514f5e3Sopenharmony_ci case JSType::LEXICAL_ENV: 2284514f5e3Sopenharmony_ci return GetArrayString(TaggedArray::Cast(entry), "LexicalEnv["); 2294514f5e3Sopenharmony_ci case JSType::SENDABLE_ENV: 2304514f5e3Sopenharmony_ci return GetArrayString(TaggedArray::Cast(entry), "SendableEnv["); 2314514f5e3Sopenharmony_ci case JSType::CONSTANT_POOL: 2324514f5e3Sopenharmony_ci return GetArrayString(TaggedArray::Cast(entry), "ArkInternalConstantPool["); 2334514f5e3Sopenharmony_ci case JSType::PROFILE_TYPE_INFO: 2344514f5e3Sopenharmony_ci return GetArrayString(TaggedArray::Cast(entry), "ArkInternalProfileTypeInfo["); 2354514f5e3Sopenharmony_ci case JSType::TAGGED_DICTIONARY: 2364514f5e3Sopenharmony_ci return GetArrayString(TaggedArray::Cast(entry), "ArkInternalDict["); 2374514f5e3Sopenharmony_ci case JSType::AOT_LITERAL_INFO: 2384514f5e3Sopenharmony_ci return GetArrayString(TaggedArray::Cast(entry), "ArkInternalAOTLiteralInfo["); 2394514f5e3Sopenharmony_ci case JSType::VTABLE: 2404514f5e3Sopenharmony_ci return GetArrayString(TaggedArray::Cast(entry), "ArkInternalVTable["); 2414514f5e3Sopenharmony_ci case JSType::COW_TAGGED_ARRAY: 2424514f5e3Sopenharmony_ci return GetArrayString(TaggedArray::Cast(entry), "ArkInternalCOWArray["); 2434514f5e3Sopenharmony_ci case JSType::HCLASS: 2444514f5e3Sopenharmony_ci return GetString("HiddenClass(NonMovable)"); 2454514f5e3Sopenharmony_ci case JSType::LINKED_NODE: 2464514f5e3Sopenharmony_ci return GetString("LinkedNode"); 2474514f5e3Sopenharmony_ci case JSType::TRACK_INFO: 2484514f5e3Sopenharmony_ci return GetString("TrackInfo"); 2494514f5e3Sopenharmony_ci case JSType::LINE_STRING: 2504514f5e3Sopenharmony_ci case JSType::CONSTANT_STRING: 2514514f5e3Sopenharmony_ci case JSType::TREE_STRING: 2524514f5e3Sopenharmony_ci case JSType::SLICED_STRING: 2534514f5e3Sopenharmony_ci return GetString("BaseString"); 2544514f5e3Sopenharmony_ci case JSType::JS_OBJECT: { 2554514f5e3Sopenharmony_ci CString objName = CString("JSObject"); // Ctor-name 2564514f5e3Sopenharmony_ci return GetString(objName); 2574514f5e3Sopenharmony_ci } 2584514f5e3Sopenharmony_ci case JSType::JS_SHARED_OBJECT: { 2594514f5e3Sopenharmony_ci return GetString("JSSharedObject"); 2604514f5e3Sopenharmony_ci } 2614514f5e3Sopenharmony_ci case JSType::JS_SHARED_FUNCTION: { 2624514f5e3Sopenharmony_ci return GetString("JSSharedFunction"); 2634514f5e3Sopenharmony_ci } 2644514f5e3Sopenharmony_ci case JSType::FREE_OBJECT_WITH_ONE_FIELD: 2654514f5e3Sopenharmony_ci case JSType::FREE_OBJECT_WITH_NONE_FIELD: 2664514f5e3Sopenharmony_ci case JSType::FREE_OBJECT_WITH_TWO_FIELD: 2674514f5e3Sopenharmony_ci return GetString("FreeObject"); 2684514f5e3Sopenharmony_ci case JSType::JS_NATIVE_POINTER: 2694514f5e3Sopenharmony_ci return GetString("JSNativePointer"); 2704514f5e3Sopenharmony_ci case JSType::JS_FUNCTION_BASE: 2714514f5e3Sopenharmony_ci return GetString("JSFunctionBase"); 2724514f5e3Sopenharmony_ci case JSType::JS_FUNCTION: 2734514f5e3Sopenharmony_ci return GetString(CString("JSFunction")); 2744514f5e3Sopenharmony_ci case JSType::FUNCTION_TEMPLATE: 2754514f5e3Sopenharmony_ci return GetString(CString("ArkInternalFunctionTemplate")); 2764514f5e3Sopenharmony_ci case JSType::JS_ERROR: 2774514f5e3Sopenharmony_ci return GetString("Error"); 2784514f5e3Sopenharmony_ci case JSType::JS_EVAL_ERROR: 2794514f5e3Sopenharmony_ci return GetString("Eval Error"); 2804514f5e3Sopenharmony_ci case JSType::JS_RANGE_ERROR: 2814514f5e3Sopenharmony_ci return GetString("Range Error"); 2824514f5e3Sopenharmony_ci case JSType::JS_TYPE_ERROR: 2834514f5e3Sopenharmony_ci return GetString("Type Error"); 2844514f5e3Sopenharmony_ci case JSType::JS_AGGREGATE_ERROR: 2854514f5e3Sopenharmony_ci return GetString("Aggregate Error"); 2864514f5e3Sopenharmony_ci case JSType::JS_REFERENCE_ERROR: 2874514f5e3Sopenharmony_ci return GetString("Reference Error"); 2884514f5e3Sopenharmony_ci case JSType::JS_URI_ERROR: 2894514f5e3Sopenharmony_ci return GetString("Uri Error"); 2904514f5e3Sopenharmony_ci case JSType::JS_SYNTAX_ERROR: 2914514f5e3Sopenharmony_ci return GetString("Syntax Error"); 2924514f5e3Sopenharmony_ci case JSType::JS_OOM_ERROR: 2934514f5e3Sopenharmony_ci return GetString("OutOfMemory Error"); 2944514f5e3Sopenharmony_ci case JSType::JS_TERMINATION_ERROR: 2954514f5e3Sopenharmony_ci return GetString("Termination Error"); 2964514f5e3Sopenharmony_ci case JSType::JS_REG_EXP: 2974514f5e3Sopenharmony_ci return GetString("Regexp"); 2984514f5e3Sopenharmony_ci case JSType::JS_SET: 2994514f5e3Sopenharmony_ci return GetString("Set"); 3004514f5e3Sopenharmony_ci case JSType::JS_SHARED_SET: 3014514f5e3Sopenharmony_ci return GetString("SharedSet"); 3024514f5e3Sopenharmony_ci case JSType::JS_MAP: 3034514f5e3Sopenharmony_ci return GetString("Map"); 3044514f5e3Sopenharmony_ci case JSType::JS_SHARED_MAP: 3054514f5e3Sopenharmony_ci return GetString("SharedMap"); 3064514f5e3Sopenharmony_ci case JSType::JS_WEAK_SET: 3074514f5e3Sopenharmony_ci return GetString("WeakSet"); 3084514f5e3Sopenharmony_ci case JSType::JS_WEAK_MAP: 3094514f5e3Sopenharmony_ci return GetString("WeakMap"); 3104514f5e3Sopenharmony_ci case JSType::JS_DATE: 3114514f5e3Sopenharmony_ci return GetString("Date"); 3124514f5e3Sopenharmony_ci case JSType::JS_BOUND_FUNCTION: 3134514f5e3Sopenharmony_ci return GetString("Bound Function"); 3144514f5e3Sopenharmony_ci case JSType::JS_ARRAY: 3154514f5e3Sopenharmony_ci return GetString("JSArray"); 3164514f5e3Sopenharmony_ci case JSType::JS_TYPED_ARRAY: 3174514f5e3Sopenharmony_ci return GetString("Typed Array"); 3184514f5e3Sopenharmony_ci case JSType::JS_INT8_ARRAY: 3194514f5e3Sopenharmony_ci return GetString("Int8 Array"); 3204514f5e3Sopenharmony_ci case JSType::JS_UINT8_ARRAY: 3214514f5e3Sopenharmony_ci return GetString("Uint8 Array"); 3224514f5e3Sopenharmony_ci case JSType::JS_UINT8_CLAMPED_ARRAY: 3234514f5e3Sopenharmony_ci return GetString("Uint8 Clamped Array"); 3244514f5e3Sopenharmony_ci case JSType::JS_INT16_ARRAY: 3254514f5e3Sopenharmony_ci return GetString("Int16 Array"); 3264514f5e3Sopenharmony_ci case JSType::JS_UINT16_ARRAY: 3274514f5e3Sopenharmony_ci return GetString("Uint16 Array"); 3284514f5e3Sopenharmony_ci case JSType::JS_INT32_ARRAY: 3294514f5e3Sopenharmony_ci return GetString("Int32 Array"); 3304514f5e3Sopenharmony_ci case JSType::JS_UINT32_ARRAY: 3314514f5e3Sopenharmony_ci return GetString("Uint32 Array"); 3324514f5e3Sopenharmony_ci case JSType::JS_FLOAT32_ARRAY: 3334514f5e3Sopenharmony_ci return GetString("Float32 Array"); 3344514f5e3Sopenharmony_ci case JSType::JS_FLOAT64_ARRAY: 3354514f5e3Sopenharmony_ci return GetString("Float64 Array"); 3364514f5e3Sopenharmony_ci case JSType::JS_BIGINT64_ARRAY: 3374514f5e3Sopenharmony_ci return GetString("BigInt64 Array"); 3384514f5e3Sopenharmony_ci case JSType::JS_BIGUINT64_ARRAY: 3394514f5e3Sopenharmony_ci return GetString("BigUint64 Array"); 3404514f5e3Sopenharmony_ci case JSType::JS_ARGUMENTS: 3414514f5e3Sopenharmony_ci return GetString("Arguments"); 3424514f5e3Sopenharmony_ci case JSType::BIGINT: 3434514f5e3Sopenharmony_ci return GetString("BigInt"); 3444514f5e3Sopenharmony_ci case JSType::JS_PROXY: 3454514f5e3Sopenharmony_ci return GetString("Proxy"); 3464514f5e3Sopenharmony_ci case JSType::JS_PRIMITIVE_REF: 3474514f5e3Sopenharmony_ci return GetString("Primitive"); 3484514f5e3Sopenharmony_ci case JSType::JS_DATA_VIEW: 3494514f5e3Sopenharmony_ci return GetString("DataView"); 3504514f5e3Sopenharmony_ci case JSType::JS_ITERATOR: 3514514f5e3Sopenharmony_ci return GetString("Iterator"); 3524514f5e3Sopenharmony_ci case JSType::JS_FORIN_ITERATOR: 3534514f5e3Sopenharmony_ci return GetString("ForinInterator"); 3544514f5e3Sopenharmony_ci case JSType::JS_MAP_ITERATOR: 3554514f5e3Sopenharmony_ci return GetString("MapIterator"); 3564514f5e3Sopenharmony_ci case JSType::JS_SHARED_MAP_ITERATOR: 3574514f5e3Sopenharmony_ci return GetString("SharedMapIterator"); 3584514f5e3Sopenharmony_ci case JSType::JS_SET_ITERATOR: 3594514f5e3Sopenharmony_ci return GetString("SetIterator"); 3604514f5e3Sopenharmony_ci case JSType::JS_SHARED_SET_ITERATOR: 3614514f5e3Sopenharmony_ci return GetString("SharedSetIterator"); 3624514f5e3Sopenharmony_ci case JSType::JS_REG_EXP_ITERATOR: 3634514f5e3Sopenharmony_ci return GetString("RegExpIterator"); 3644514f5e3Sopenharmony_ci case JSType::JS_ARRAY_ITERATOR: 3654514f5e3Sopenharmony_ci return GetString("ArrayIterator"); 3664514f5e3Sopenharmony_ci case JSType::JS_STRING_ITERATOR: 3674514f5e3Sopenharmony_ci return GetString("StringIterator"); 3684514f5e3Sopenharmony_ci case JSType::JS_ARRAY_BUFFER: 3694514f5e3Sopenharmony_ci return GetString("ArrayBuffer"); 3704514f5e3Sopenharmony_ci case JSType::JS_SENDABLE_ARRAY_BUFFER: 3714514f5e3Sopenharmony_ci return GetString("SendableArrayBuffer"); 3724514f5e3Sopenharmony_ci case JSType::JS_SHARED_ARRAY: 3734514f5e3Sopenharmony_ci return GetString("SharedArray"); 3744514f5e3Sopenharmony_ci case JSType::JS_SHARED_ARRAY_BUFFER: 3754514f5e3Sopenharmony_ci return GetString("SharedArrayBuffer"); 3764514f5e3Sopenharmony_ci case JSType::JS_PROXY_REVOC_FUNCTION: 3774514f5e3Sopenharmony_ci return GetString("ProxyRevocFunction"); 3784514f5e3Sopenharmony_ci case JSType::PROMISE_REACTIONS: 3794514f5e3Sopenharmony_ci return GetString("PromiseReaction"); 3804514f5e3Sopenharmony_ci case JSType::PROMISE_CAPABILITY: 3814514f5e3Sopenharmony_ci return GetString("PromiseCapability"); 3824514f5e3Sopenharmony_ci case JSType::ASYNC_GENERATOR_REQUEST: 3834514f5e3Sopenharmony_ci return GetString("AsyncGeneratorRequest"); 3844514f5e3Sopenharmony_ci case JSType::PROMISE_ITERATOR_RECORD: 3854514f5e3Sopenharmony_ci return GetString("PromiseIteratorRecord"); 3864514f5e3Sopenharmony_ci case JSType::PROMISE_RECORD: 3874514f5e3Sopenharmony_ci return GetString("PromiseRecord"); 3884514f5e3Sopenharmony_ci case JSType::RESOLVING_FUNCTIONS_RECORD: 3894514f5e3Sopenharmony_ci return GetString("ResolvingFunctionsRecord"); 3904514f5e3Sopenharmony_ci case JSType::JS_PROMISE: 3914514f5e3Sopenharmony_ci return GetString("Promise"); 3924514f5e3Sopenharmony_ci case JSType::JS_PROMISE_REACTIONS_FUNCTION: 3934514f5e3Sopenharmony_ci return GetString("PromiseReactionsFunction"); 3944514f5e3Sopenharmony_ci case JSType::JS_PROMISE_EXECUTOR_FUNCTION: 3954514f5e3Sopenharmony_ci return GetString("PromiseExecutorFunction"); 3964514f5e3Sopenharmony_ci case JSType::JS_ASYNC_MODULE_FULFILLED_FUNCTION: 3974514f5e3Sopenharmony_ci return GetString("AsyncModuleFulfilledFunction"); 3984514f5e3Sopenharmony_ci case JSType::JS_ASYNC_MODULE_REJECTED_FUNCTION: 3994514f5e3Sopenharmony_ci return GetString("AsyncModuleRejectedFunction"); 4004514f5e3Sopenharmony_ci case JSType::JS_ASYNC_FROM_SYNC_ITER_UNWARP_FUNCTION: 4014514f5e3Sopenharmony_ci return GetString("AsyncFromSyncIterUnwarpFunction"); 4024514f5e3Sopenharmony_ci case JSType::JS_PROMISE_ALL_RESOLVE_ELEMENT_FUNCTION: 4034514f5e3Sopenharmony_ci return GetString("PromiseAllResolveElementFunction"); 4044514f5e3Sopenharmony_ci case JSType::JS_PROMISE_ANY_REJECT_ELEMENT_FUNCTION: 4054514f5e3Sopenharmony_ci return GetString("PromiseAnyRejectElementFunction"); 4064514f5e3Sopenharmony_ci case JSType::JS_PROMISE_ALL_SETTLED_ELEMENT_FUNCTION: 4074514f5e3Sopenharmony_ci return GetString("PromiseAllSettledElementFunction"); 4084514f5e3Sopenharmony_ci case JSType::JS_PROMISE_FINALLY_FUNCTION: 4094514f5e3Sopenharmony_ci return GetString("PromiseFinallyFunction"); 4104514f5e3Sopenharmony_ci case JSType::JS_PROMISE_VALUE_THUNK_OR_THROWER_FUNCTION: 4114514f5e3Sopenharmony_ci return GetString("PromiseValueThunkOrThrowerFunction"); 4124514f5e3Sopenharmony_ci case JSType::JS_ASYNC_GENERATOR_RESUME_NEXT_RETURN_PROCESSOR_RST_FTN: 4134514f5e3Sopenharmony_ci return GetString("AsyncGeneratorResumeNextReturnProcessorRstFtn"); 4144514f5e3Sopenharmony_ci case JSType::JS_GENERATOR_FUNCTION: 4154514f5e3Sopenharmony_ci return GetString("JSGeneratorFunction"); 4164514f5e3Sopenharmony_ci case JSType::JS_ASYNC_GENERATOR_FUNCTION: 4174514f5e3Sopenharmony_ci return GetString("JSAsyncGeneratorFunction"); 4184514f5e3Sopenharmony_ci case JSType::SYMBOL: 4194514f5e3Sopenharmony_ci return GetString("Symbol"); 4204514f5e3Sopenharmony_ci case JSType::JS_ASYNC_FUNCTION: 4214514f5e3Sopenharmony_ci return GetString("AsyncFunction"); 4224514f5e3Sopenharmony_ci case JSType::JS_SHARED_ASYNC_FUNCTION: 4234514f5e3Sopenharmony_ci return GetString("SharedAsyncFunction"); 4244514f5e3Sopenharmony_ci case JSType::JS_INTL_BOUND_FUNCTION: 4254514f5e3Sopenharmony_ci return GetString("JSIntlBoundFunction"); 4264514f5e3Sopenharmony_ci case JSType::JS_ASYNC_AWAIT_STATUS_FUNCTION: 4274514f5e3Sopenharmony_ci return GetString("AsyncAwaitStatusFunction"); 4284514f5e3Sopenharmony_ci case JSType::JS_ASYNC_FUNC_OBJECT: 4294514f5e3Sopenharmony_ci return GetString("AsyncFunctionObject"); 4304514f5e3Sopenharmony_ci case JSType::JS_REALM: 4314514f5e3Sopenharmony_ci return GetString("Realm"); 4324514f5e3Sopenharmony_ci case JSType::JS_GLOBAL_OBJECT: 4334514f5e3Sopenharmony_ci return GetString("GlobalObject"); 4344514f5e3Sopenharmony_ci case JSType::JS_INTL: 4354514f5e3Sopenharmony_ci return GetString("JSIntl"); 4364514f5e3Sopenharmony_ci case JSType::JS_LOCALE: 4374514f5e3Sopenharmony_ci return GetString("JSLocale"); 4384514f5e3Sopenharmony_ci case JSType::JS_DATE_TIME_FORMAT: 4394514f5e3Sopenharmony_ci return GetString("JSDateTimeFormat"); 4404514f5e3Sopenharmony_ci case JSType::JS_RELATIVE_TIME_FORMAT: 4414514f5e3Sopenharmony_ci return GetString("JSRelativeTimeFormat"); 4424514f5e3Sopenharmony_ci case JSType::JS_NUMBER_FORMAT: 4434514f5e3Sopenharmony_ci return GetString("JSNumberFormat"); 4444514f5e3Sopenharmony_ci case JSType::JS_COLLATOR: 4454514f5e3Sopenharmony_ci return GetString("JSCollator"); 4464514f5e3Sopenharmony_ci case JSType::JS_PLURAL_RULES: 4474514f5e3Sopenharmony_ci return GetString("JSPluralRules"); 4484514f5e3Sopenharmony_ci case JSType::JS_DISPLAYNAMES: 4494514f5e3Sopenharmony_ci return GetString("JSDisplayNames"); 4504514f5e3Sopenharmony_ci case JSType::JS_SEGMENTER: 4514514f5e3Sopenharmony_ci return GetString("JSSegmenter"); 4524514f5e3Sopenharmony_ci case JSType::JS_SEGMENTS: 4534514f5e3Sopenharmony_ci return GetString("JSSegments"); 4544514f5e3Sopenharmony_ci case JSType::JS_SEGMENT_ITERATOR: 4554514f5e3Sopenharmony_ci return GetString("JSSegmentIterator"); 4564514f5e3Sopenharmony_ci case JSType::JS_LIST_FORMAT: 4574514f5e3Sopenharmony_ci return GetString("JSListFormat"); 4584514f5e3Sopenharmony_ci case JSType::JS_GENERATOR_OBJECT: 4594514f5e3Sopenharmony_ci return GetString("JSGeneratorObject"); 4604514f5e3Sopenharmony_ci case JSType::JS_ASYNC_GENERATOR_OBJECT: 4614514f5e3Sopenharmony_ci return GetString("JSAsyncGeneratorObject"); 4624514f5e3Sopenharmony_ci case JSType::JS_GENERATOR_CONTEXT: 4634514f5e3Sopenharmony_ci return GetString("JSGeneratorContext"); 4644514f5e3Sopenharmony_ci case JSType::ACCESSOR_DATA: 4654514f5e3Sopenharmony_ci return GetString("AccessorData"); 4664514f5e3Sopenharmony_ci case JSType::INTERNAL_ACCESSOR: 4674514f5e3Sopenharmony_ci return GetString("InternalAccessor"); 4684514f5e3Sopenharmony_ci case JSType::MICRO_JOB_QUEUE: 4694514f5e3Sopenharmony_ci return GetString("MicroJobQueue"); 4704514f5e3Sopenharmony_ci case JSType::PENDING_JOB: 4714514f5e3Sopenharmony_ci return GetString("PendingJob"); 4724514f5e3Sopenharmony_ci case JSType::COMPLETION_RECORD: 4734514f5e3Sopenharmony_ci return GetString("CompletionRecord"); 4744514f5e3Sopenharmony_ci case JSType::JS_API_ARRAY_LIST: 4754514f5e3Sopenharmony_ci return GetString("ArrayList"); 4764514f5e3Sopenharmony_ci case JSType::JS_API_ARRAYLIST_ITERATOR: 4774514f5e3Sopenharmony_ci return GetString("ArrayListIterator"); 4784514f5e3Sopenharmony_ci case JSType::JS_API_HASH_MAP: 4794514f5e3Sopenharmony_ci return GetString("HashMap"); 4804514f5e3Sopenharmony_ci case JSType::JS_API_HASH_SET: 4814514f5e3Sopenharmony_ci return GetString("HashSet"); 4824514f5e3Sopenharmony_ci case JSType::JS_API_HASHMAP_ITERATOR: 4834514f5e3Sopenharmony_ci return GetString("HashMapIterator"); 4844514f5e3Sopenharmony_ci case JSType::JS_API_HASHSET_ITERATOR: 4854514f5e3Sopenharmony_ci return GetString("HashSetIterator"); 4864514f5e3Sopenharmony_ci case JSType::JS_API_LIGHT_WEIGHT_MAP: 4874514f5e3Sopenharmony_ci return GetString("LightWeightMap"); 4884514f5e3Sopenharmony_ci case JSType::JS_API_LIGHT_WEIGHT_MAP_ITERATOR: 4894514f5e3Sopenharmony_ci return GetString("LightWeightMapIterator"); 4904514f5e3Sopenharmony_ci case JSType::JS_API_LIGHT_WEIGHT_SET: 4914514f5e3Sopenharmony_ci return GetString("LightWeightSet"); 4924514f5e3Sopenharmony_ci case JSType::JS_API_LIGHT_WEIGHT_SET_ITERATOR: 4934514f5e3Sopenharmony_ci return GetString("LightWeightSetIterator"); 4944514f5e3Sopenharmony_ci case JSType::JS_API_TREE_MAP: 4954514f5e3Sopenharmony_ci return GetString("TreeMap"); 4964514f5e3Sopenharmony_ci case JSType::JS_API_TREE_SET: 4974514f5e3Sopenharmony_ci return GetString("TreeSet"); 4984514f5e3Sopenharmony_ci case JSType::JS_API_TREEMAP_ITERATOR: 4994514f5e3Sopenharmony_ci return GetString("TreeMapIterator"); 5004514f5e3Sopenharmony_ci case JSType::JS_API_TREESET_ITERATOR: 5014514f5e3Sopenharmony_ci return GetString("TreeSetIterator"); 5024514f5e3Sopenharmony_ci case JSType::JS_API_VECTOR: 5034514f5e3Sopenharmony_ci return GetString("Vector"); 5044514f5e3Sopenharmony_ci case JSType::JS_API_VECTOR_ITERATOR: 5054514f5e3Sopenharmony_ci return GetString("VectorIterator"); 5064514f5e3Sopenharmony_ci case JSType::JS_API_BITVECTOR: 5074514f5e3Sopenharmony_ci return GetString("BitVector"); 5084514f5e3Sopenharmony_ci case JSType::JS_API_BITVECTOR_ITERATOR: 5094514f5e3Sopenharmony_ci return GetString("BitVectorIterator"); 5104514f5e3Sopenharmony_ci case JSType::JS_API_QUEUE: 5114514f5e3Sopenharmony_ci return GetString("Queue"); 5124514f5e3Sopenharmony_ci case JSType::JS_API_QUEUE_ITERATOR: 5134514f5e3Sopenharmony_ci return GetString("QueueIterator"); 5144514f5e3Sopenharmony_ci case JSType::JS_API_DEQUE: 5154514f5e3Sopenharmony_ci return GetString("Deque"); 5164514f5e3Sopenharmony_ci case JSType::JS_API_DEQUE_ITERATOR: 5174514f5e3Sopenharmony_ci return GetString("DequeIterator"); 5184514f5e3Sopenharmony_ci case JSType::JS_API_STACK: 5194514f5e3Sopenharmony_ci return GetString("Stack"); 5204514f5e3Sopenharmony_ci case JSType::JS_API_STACK_ITERATOR: 5214514f5e3Sopenharmony_ci return GetString("StackIterator"); 5224514f5e3Sopenharmony_ci case JSType::JS_API_LIST: 5234514f5e3Sopenharmony_ci return GetString("List"); 5244514f5e3Sopenharmony_ci case JSType::JS_API_LINKED_LIST: 5254514f5e3Sopenharmony_ci return GetString("LinkedList"); 5264514f5e3Sopenharmony_ci case JSType::SOURCE_TEXT_MODULE_RECORD: 5274514f5e3Sopenharmony_ci return GetString("SourceTextModule"); 5284514f5e3Sopenharmony_ci case JSType::IMPORTENTRY_RECORD: 5294514f5e3Sopenharmony_ci return GetString("ImportEntry"); 5304514f5e3Sopenharmony_ci case JSType::LOCAL_EXPORTENTRY_RECORD: 5314514f5e3Sopenharmony_ci return GetString("LocalExportEntry"); 5324514f5e3Sopenharmony_ci case JSType::INDIRECT_EXPORTENTRY_RECORD: 5334514f5e3Sopenharmony_ci return GetString("IndirectExportEntry"); 5344514f5e3Sopenharmony_ci case JSType::STAR_EXPORTENTRY_RECORD: 5354514f5e3Sopenharmony_ci return GetString("StarExportEntry"); 5364514f5e3Sopenharmony_ci case JSType::RESOLVEDBINDING_RECORD: 5374514f5e3Sopenharmony_ci return GetString("ResolvedBinding"); 5384514f5e3Sopenharmony_ci case JSType::RESOLVEDINDEXBINDING_RECORD: 5394514f5e3Sopenharmony_ci return GetString("ResolvedIndexBinding"); 5404514f5e3Sopenharmony_ci case JSType::RESOLVEDRECORDINDEXBINDING_RECORD: 5414514f5e3Sopenharmony_ci return GetString("ResolvedRecordIndexBinding"); 5424514f5e3Sopenharmony_ci case JSType::RESOLVEDRECORDBINDING_RECORD: 5434514f5e3Sopenharmony_ci return GetString("ResolvedRecordBinding"); 5444514f5e3Sopenharmony_ci case JSType::JS_MODULE_NAMESPACE: 5454514f5e3Sopenharmony_ci return GetString("ModuleNamespace"); 5464514f5e3Sopenharmony_ci case JSType::JS_API_PLAIN_ARRAY: 5474514f5e3Sopenharmony_ci return GetString("PlainArray"); 5484514f5e3Sopenharmony_ci case JSType::JS_API_PLAIN_ARRAY_ITERATOR: 5494514f5e3Sopenharmony_ci return GetString("PlainArrayIterator"); 5504514f5e3Sopenharmony_ci case JSType::JS_CJS_EXPORTS: 5514514f5e3Sopenharmony_ci return GetString("CJS Exports"); 5524514f5e3Sopenharmony_ci case JSType::JS_CJS_MODULE: 5534514f5e3Sopenharmony_ci return GetString("CJS Module"); 5544514f5e3Sopenharmony_ci case JSType::JS_CJS_REQUIRE: 5554514f5e3Sopenharmony_ci return GetString("CJS Require"); 5564514f5e3Sopenharmony_ci case JSType::METHOD: 5574514f5e3Sopenharmony_ci return GetString("Method"); 5584514f5e3Sopenharmony_ci default: 5594514f5e3Sopenharmony_ci break; 5604514f5e3Sopenharmony_ci } 5614514f5e3Sopenharmony_ci if (IsInVmMode()) { 5624514f5e3Sopenharmony_ci switch (type) { 5634514f5e3Sopenharmony_ci case JSType::PROPERTY_BOX: 5644514f5e3Sopenharmony_ci return GetString("PropertyBox"); 5654514f5e3Sopenharmony_ci case JSType::GLOBAL_ENV: 5664514f5e3Sopenharmony_ci return GetString("GlobalEnv"); 5674514f5e3Sopenharmony_ci case JSType::PROTOTYPE_HANDLER: 5684514f5e3Sopenharmony_ci return GetString("ProtoTypeHandler"); 5694514f5e3Sopenharmony_ci case JSType::TRANSITION_HANDLER: 5704514f5e3Sopenharmony_ci return GetString("TransitionHandler"); 5714514f5e3Sopenharmony_ci case JSType::TRANS_WITH_PROTO_HANDLER: 5724514f5e3Sopenharmony_ci return GetString("TransWithProtoHandler"); 5734514f5e3Sopenharmony_ci case JSType::STORE_TS_HANDLER: 5744514f5e3Sopenharmony_ci return GetString("StoreTSHandler"); 5754514f5e3Sopenharmony_ci case JSType::PROTO_CHANGE_MARKER: 5764514f5e3Sopenharmony_ci return GetString("ProtoChangeMarker"); 5774514f5e3Sopenharmony_ci case JSType::MARKER_CELL: 5784514f5e3Sopenharmony_ci return GetString("MarkerCell"); 5794514f5e3Sopenharmony_ci case JSType::PROTOTYPE_INFO: 5804514f5e3Sopenharmony_ci return GetString("ProtoChangeDetails"); 5814514f5e3Sopenharmony_ci case JSType::TEMPLATE_MAP: 5824514f5e3Sopenharmony_ci return GetString("TemplateMap"); 5834514f5e3Sopenharmony_ci case JSType::PROGRAM: 5844514f5e3Sopenharmony_ci return GetString("Program"); 5854514f5e3Sopenharmony_ci case JSType::MACHINE_CODE_OBJECT: 5864514f5e3Sopenharmony_ci return GetString("MachineCode"); 5874514f5e3Sopenharmony_ci case JSType::CLASS_INFO_EXTRACTOR: 5884514f5e3Sopenharmony_ci return GetString("ClassInfoExtractor"); 5894514f5e3Sopenharmony_ci default: 5904514f5e3Sopenharmony_ci break; 5914514f5e3Sopenharmony_ci } 5924514f5e3Sopenharmony_ci } else { 5934514f5e3Sopenharmony_ci return GetString("Hidden Object"); 5944514f5e3Sopenharmony_ci } 5954514f5e3Sopenharmony_ci return GetString(CString("UnKnownType").append(std::to_string(static_cast<int>(type)))); 5964514f5e3Sopenharmony_ci} 5974514f5e3Sopenharmony_ci 5984514f5e3Sopenharmony_ciNodeType HeapSnapshot::GenerateNodeType(TaggedObject *entry) 5994514f5e3Sopenharmony_ci{ 6004514f5e3Sopenharmony_ci NodeType nodeType = NodeType::DEFAULT; 6014514f5e3Sopenharmony_ci auto *hCls = entry->GetClass(); 6024514f5e3Sopenharmony_ci JSType type = hCls->GetObjectType(); 6034514f5e3Sopenharmony_ci 6044514f5e3Sopenharmony_ci if (hCls->IsTaggedArray()) { 6054514f5e3Sopenharmony_ci nodeType = NodeType::ARRAY; 6064514f5e3Sopenharmony_ci } else if (hCls->IsHClass()) { 6074514f5e3Sopenharmony_ci nodeType = NodeType::DEFAULT; 6084514f5e3Sopenharmony_ci } else if (type == JSType::PROPERTY_BOX) { 6094514f5e3Sopenharmony_ci nodeType = NodeType::HIDDEN; 6104514f5e3Sopenharmony_ci } else if (type == JSType::JS_ARRAY || type == JSType::JS_TYPED_ARRAY) { 6114514f5e3Sopenharmony_ci nodeType = NodeType::OBJECT; 6124514f5e3Sopenharmony_ci } else if (type == JSType::JS_OBJECT || type == JSType::JS_SHARED_OBJECT) { 6134514f5e3Sopenharmony_ci nodeType = NodeType::OBJECT; 6144514f5e3Sopenharmony_ci } else if (type >= JSType::JS_FUNCTION_FIRST && type <= JSType::JS_FUNCTION_LAST) { 6154514f5e3Sopenharmony_ci nodeType = NodeType::CLOSURE; 6164514f5e3Sopenharmony_ci } else if (type == JSType::JS_BOUND_FUNCTION) { 6174514f5e3Sopenharmony_ci nodeType = NodeType::DEFAULT; 6184514f5e3Sopenharmony_ci } else if (type == JSType::JS_FUNCTION_BASE) { 6194514f5e3Sopenharmony_ci nodeType = NodeType::DEFAULT; 6204514f5e3Sopenharmony_ci } else if (type == JSType::JS_REG_EXP) { 6214514f5e3Sopenharmony_ci nodeType = NodeType::REGEXP; 6224514f5e3Sopenharmony_ci } else if (type == JSType::SYMBOL) { 6234514f5e3Sopenharmony_ci nodeType = NodeType::SYMBOL; 6244514f5e3Sopenharmony_ci } else if (type == JSType::JS_PRIMITIVE_REF) { 6254514f5e3Sopenharmony_ci nodeType = NodeType::HEAPNUMBER; 6264514f5e3Sopenharmony_ci } else if (type == JSType::BIGINT) { 6274514f5e3Sopenharmony_ci nodeType = NodeType::BIGINT; 6284514f5e3Sopenharmony_ci } else { 6294514f5e3Sopenharmony_ci nodeType = NodeType::DEFAULT; 6304514f5e3Sopenharmony_ci } 6314514f5e3Sopenharmony_ci 6324514f5e3Sopenharmony_ci return nodeType; 6334514f5e3Sopenharmony_ci} 6344514f5e3Sopenharmony_ci 6354514f5e3Sopenharmony_civoid HeapSnapshot::FillNodes(bool isInFinish, bool isSimplify) 6364514f5e3Sopenharmony_ci{ 6374514f5e3Sopenharmony_ci // Iterate Heap Object 6384514f5e3Sopenharmony_ci auto heap = vm_->GetHeap(); 6394514f5e3Sopenharmony_ci if (heap != nullptr) { 6404514f5e3Sopenharmony_ci heap->IterateOverObjects([this, isInFinish, isSimplify](TaggedObject *obj) { 6414514f5e3Sopenharmony_ci GenerateNode(JSTaggedValue(obj), 0, isInFinish, isSimplify); 6424514f5e3Sopenharmony_ci }, isSimplify); 6434514f5e3Sopenharmony_ci } 6444514f5e3Sopenharmony_ci} 6454514f5e3Sopenharmony_ci 6464514f5e3Sopenharmony_ciNode *HeapSnapshot::HandleStringNode(JSTaggedValue &entry, size_t &size, bool &isInFinish, bool isBinMod) 6474514f5e3Sopenharmony_ci{ 6484514f5e3Sopenharmony_ci Node* node = nullptr; 6494514f5e3Sopenharmony_ci if (isPrivate_) { 6504514f5e3Sopenharmony_ci node = GeneratePrivateStringNode(size); 6514514f5e3Sopenharmony_ci } else { 6524514f5e3Sopenharmony_ci node = GenerateStringNode(entry, size, isInFinish, isBinMod); 6534514f5e3Sopenharmony_ci } 6544514f5e3Sopenharmony_ci if (node == nullptr) { 6554514f5e3Sopenharmony_ci LOG_ECMA(ERROR) << "string node nullptr"; 6564514f5e3Sopenharmony_ci } 6574514f5e3Sopenharmony_ci return node; 6584514f5e3Sopenharmony_ci} 6594514f5e3Sopenharmony_ci 6604514f5e3Sopenharmony_ciNode *HeapSnapshot::HandleFunctionNode(JSTaggedValue &entry, size_t &size, bool &isInFinish) 6614514f5e3Sopenharmony_ci{ 6624514f5e3Sopenharmony_ci Node* node = GenerateFunctionNode(entry, size, isInFinish); 6634514f5e3Sopenharmony_ci if (node == nullptr) { 6644514f5e3Sopenharmony_ci LOG_ECMA(ERROR) << "function node nullptr"; 6654514f5e3Sopenharmony_ci } 6664514f5e3Sopenharmony_ci return node; 6674514f5e3Sopenharmony_ci} 6684514f5e3Sopenharmony_ci 6694514f5e3Sopenharmony_ciNode *HeapSnapshot::HandleObjectNode(JSTaggedValue &entry, size_t &size, bool &isInFinish) 6704514f5e3Sopenharmony_ci{ 6714514f5e3Sopenharmony_ci Node* node = GenerateObjectNode(entry, size, isInFinish); 6724514f5e3Sopenharmony_ci if (node == nullptr) { 6734514f5e3Sopenharmony_ci LOG_ECMA(ERROR) << "object node nullptr"; 6744514f5e3Sopenharmony_ci } 6754514f5e3Sopenharmony_ci return node; 6764514f5e3Sopenharmony_ci} 6774514f5e3Sopenharmony_ci 6784514f5e3Sopenharmony_ciNode *HeapSnapshot::HandleBaseClassNode(size_t size, bool idExist, NodeId &sequenceId, 6794514f5e3Sopenharmony_ci TaggedObject* obj, JSTaggedType &addr) 6804514f5e3Sopenharmony_ci{ 6814514f5e3Sopenharmony_ci size_t selfSize = (size != 0) ? size : obj->GetClass()->SizeFromJSHClass(obj); 6824514f5e3Sopenharmony_ci size_t nativeSize = 0; 6834514f5e3Sopenharmony_ci if (obj->GetClass()->IsJSNativePointer()) { 6844514f5e3Sopenharmony_ci nativeSize = JSNativePointer::Cast(obj)->GetBindingSize(); 6854514f5e3Sopenharmony_ci } 6864514f5e3Sopenharmony_ci Node* node = Node::NewNode(chunk_, sequenceId, nodeCount_, GenerateNodeName(obj), GenerateNodeType(obj), 6874514f5e3Sopenharmony_ci selfSize, nativeSize, addr); 6884514f5e3Sopenharmony_ci entryMap_.InsertEntry(node); 6894514f5e3Sopenharmony_ci if (!idExist) { 6904514f5e3Sopenharmony_ci entryIdMap_->InsertId(addr, sequenceId); 6914514f5e3Sopenharmony_ci } 6924514f5e3Sopenharmony_ci InsertNodeUnique(node); 6934514f5e3Sopenharmony_ci ASSERT(entryMap_.FindEntry(node->GetAddress())->GetAddress() == node->GetAddress()); 6944514f5e3Sopenharmony_ci return node; 6954514f5e3Sopenharmony_ci} 6964514f5e3Sopenharmony_ci 6974514f5e3Sopenharmony_ciCString HeapSnapshot::GeneratePrimitiveNameString(JSTaggedValue &entry) 6984514f5e3Sopenharmony_ci{ 6994514f5e3Sopenharmony_ci CString primitiveName; 7004514f5e3Sopenharmony_ci if (entry.IsInt()) { 7014514f5e3Sopenharmony_ci primitiveName.append("Int:"); 7024514f5e3Sopenharmony_ci if (!isPrivate_) { 7034514f5e3Sopenharmony_ci primitiveName.append(ToCString(entry.GetInt())); 7044514f5e3Sopenharmony_ci } 7054514f5e3Sopenharmony_ci } else if (entry.IsDouble()) { 7064514f5e3Sopenharmony_ci primitiveName.append("Double:"); 7074514f5e3Sopenharmony_ci if (!isPrivate_) { 7084514f5e3Sopenharmony_ci primitiveName.append(FloatToCString(entry.GetDouble())); 7094514f5e3Sopenharmony_ci } 7104514f5e3Sopenharmony_ci } else if (entry.IsHole()) { 7114514f5e3Sopenharmony_ci primitiveName.append("Hole"); 7124514f5e3Sopenharmony_ci } else if (entry.IsNull()) { 7134514f5e3Sopenharmony_ci primitiveName.append("Null"); 7144514f5e3Sopenharmony_ci } else if (entry.IsTrue()) { 7154514f5e3Sopenharmony_ci primitiveName.append("Boolean:true"); 7164514f5e3Sopenharmony_ci } else if (entry.IsFalse()) { 7174514f5e3Sopenharmony_ci primitiveName.append("Boolean:false"); 7184514f5e3Sopenharmony_ci } else if (entry.IsException()) { 7194514f5e3Sopenharmony_ci primitiveName.append("Exception"); 7204514f5e3Sopenharmony_ci } else if (entry.IsUndefined()) { 7214514f5e3Sopenharmony_ci primitiveName.append("Undefined"); 7224514f5e3Sopenharmony_ci } else { 7234514f5e3Sopenharmony_ci primitiveName.append("Illegal_Primitive"); 7244514f5e3Sopenharmony_ci } 7254514f5e3Sopenharmony_ci return primitiveName; 7264514f5e3Sopenharmony_ci} 7274514f5e3Sopenharmony_ci 7284514f5e3Sopenharmony_ciNode *HeapSnapshot::GenerateNode(JSTaggedValue entry, size_t size, bool isInFinish, bool isSimplify, bool isBinMod) 7294514f5e3Sopenharmony_ci{ 7304514f5e3Sopenharmony_ci Node *node = nullptr; 7314514f5e3Sopenharmony_ci if (entry.IsHeapObject()) { 7324514f5e3Sopenharmony_ci if (entry.IsWeak()) { 7334514f5e3Sopenharmony_ci entry.RemoveWeakTag(); 7344514f5e3Sopenharmony_ci } 7354514f5e3Sopenharmony_ci if (entry.IsString()) { 7364514f5e3Sopenharmony_ci return HandleStringNode(entry, size, isInFinish, isBinMod); 7374514f5e3Sopenharmony_ci } 7384514f5e3Sopenharmony_ci if (entry.IsJSFunction()) { 7394514f5e3Sopenharmony_ci return HandleFunctionNode(entry, size, isInFinish); 7404514f5e3Sopenharmony_ci } 7414514f5e3Sopenharmony_ci if (entry.IsOnlyJSObject()) { 7424514f5e3Sopenharmony_ci return HandleObjectNode(entry, size, isInFinish); 7434514f5e3Sopenharmony_ci } 7444514f5e3Sopenharmony_ci TaggedObject *obj = entry.GetTaggedObject(); 7454514f5e3Sopenharmony_ci auto *baseClass = obj->GetClass(); 7464514f5e3Sopenharmony_ci if (baseClass != nullptr) { 7474514f5e3Sopenharmony_ci JSTaggedType addr = entry.GetRawData(); 7484514f5e3Sopenharmony_ci Node *existNode = entryMap_.FindEntry(addr); // Fast Index 7494514f5e3Sopenharmony_ci auto [idExist, sequenceId] = entryIdMap_->FindId(addr); 7504514f5e3Sopenharmony_ci if (existNode == nullptr) { 7514514f5e3Sopenharmony_ci return HandleBaseClassNode(size, idExist, sequenceId, obj, addr); 7524514f5e3Sopenharmony_ci } else { 7534514f5e3Sopenharmony_ci existNode->SetLive(true); 7544514f5e3Sopenharmony_ci return existNode; 7554514f5e3Sopenharmony_ci } 7564514f5e3Sopenharmony_ci } 7574514f5e3Sopenharmony_ci } else if (!isSimplify) { 7584514f5e3Sopenharmony_ci if ((entry.IsInt() || entry.IsDouble()) && !captureNumericValue_) { 7594514f5e3Sopenharmony_ci return nullptr; 7604514f5e3Sopenharmony_ci } 7614514f5e3Sopenharmony_ci CString primitiveName = GeneratePrimitiveNameString(entry); 7624514f5e3Sopenharmony_ci // A primitive value with tag will be regarded as a pointer 7634514f5e3Sopenharmony_ci JSTaggedType addr = entry.GetRawData(); 7644514f5e3Sopenharmony_ci Node *existNode = entryMap_.FindEntry(addr); 7654514f5e3Sopenharmony_ci if (existNode != nullptr) { 7664514f5e3Sopenharmony_ci existNode->SetLive(true); 7674514f5e3Sopenharmony_ci return existNode; 7684514f5e3Sopenharmony_ci } 7694514f5e3Sopenharmony_ci auto [idExist, sequenceId] = entryIdMap_->FindId(addr); 7704514f5e3Sopenharmony_ci node = Node::NewNode(chunk_, sequenceId, nodeCount_, GetString(primitiveName), NodeType::HEAPNUMBER, 0, 7714514f5e3Sopenharmony_ci 0, addr); 7724514f5e3Sopenharmony_ci entryMap_.InsertEntry(node); // Fast Index 7734514f5e3Sopenharmony_ci if (!idExist) { 7744514f5e3Sopenharmony_ci entryIdMap_->InsertId(addr, sequenceId); 7754514f5e3Sopenharmony_ci } 7764514f5e3Sopenharmony_ci InsertNodeUnique(node); 7774514f5e3Sopenharmony_ci } 7784514f5e3Sopenharmony_ci return node; 7794514f5e3Sopenharmony_ci} 7804514f5e3Sopenharmony_ci 7814514f5e3Sopenharmony_ciTraceNode::TraceNode(TraceTree* tree, uint32_t nodeIndex) 7824514f5e3Sopenharmony_ci : tree_(tree), 7834514f5e3Sopenharmony_ci nodeIndex_(nodeIndex), 7844514f5e3Sopenharmony_ci totalSize_(0), 7854514f5e3Sopenharmony_ci totalCount_(0), 7864514f5e3Sopenharmony_ci id_(tree->GetNextNodeId()) 7874514f5e3Sopenharmony_ci{ 7884514f5e3Sopenharmony_ci} 7894514f5e3Sopenharmony_ci 7904514f5e3Sopenharmony_ciTraceNode::~TraceNode() 7914514f5e3Sopenharmony_ci{ 7924514f5e3Sopenharmony_ci for (TraceNode* node : children_) { 7934514f5e3Sopenharmony_ci delete node; 7944514f5e3Sopenharmony_ci } 7954514f5e3Sopenharmony_ci children_.clear(); 7964514f5e3Sopenharmony_ci} 7974514f5e3Sopenharmony_ci 7984514f5e3Sopenharmony_ciTraceNode* TraceTree::AddNodeToTree(CVector<uint32_t> traceNodeIndex) 7994514f5e3Sopenharmony_ci{ 8004514f5e3Sopenharmony_ci uint32_t len = traceNodeIndex.size(); 8014514f5e3Sopenharmony_ci if (len == 0) { 8024514f5e3Sopenharmony_ci return nullptr; 8034514f5e3Sopenharmony_ci } 8044514f5e3Sopenharmony_ci 8054514f5e3Sopenharmony_ci TraceNode* node = GetRoot(); 8064514f5e3Sopenharmony_ci for (int i = static_cast<int>(len) - 1; i >= 0; i--) { 8074514f5e3Sopenharmony_ci node = node->FindOrAddChild(traceNodeIndex[i]); 8084514f5e3Sopenharmony_ci } 8094514f5e3Sopenharmony_ci return node; 8104514f5e3Sopenharmony_ci} 8114514f5e3Sopenharmony_ci 8124514f5e3Sopenharmony_ciTraceNode* TraceNode::FindOrAddChild(uint32_t nodeIndex) 8134514f5e3Sopenharmony_ci{ 8144514f5e3Sopenharmony_ci TraceNode* child = FindChild(nodeIndex); 8154514f5e3Sopenharmony_ci if (child == nullptr) { 8164514f5e3Sopenharmony_ci child = new TraceNode(tree_, nodeIndex); 8174514f5e3Sopenharmony_ci children_.push_back(child); 8184514f5e3Sopenharmony_ci } 8194514f5e3Sopenharmony_ci return child; 8204514f5e3Sopenharmony_ci} 8214514f5e3Sopenharmony_ci 8224514f5e3Sopenharmony_ciTraceNode* TraceNode::FindChild(uint32_t nodeIndex) 8234514f5e3Sopenharmony_ci{ 8244514f5e3Sopenharmony_ci for (TraceNode* node : children_) { 8254514f5e3Sopenharmony_ci if (node->GetNodeIndex() == nodeIndex) { 8264514f5e3Sopenharmony_ci return node; 8274514f5e3Sopenharmony_ci } 8284514f5e3Sopenharmony_ci } 8294514f5e3Sopenharmony_ci return nullptr; 8304514f5e3Sopenharmony_ci} 8314514f5e3Sopenharmony_ci 8324514f5e3Sopenharmony_civoid HeapSnapshot::AddTraceNodeId(MethodLiteral *methodLiteral) 8334514f5e3Sopenharmony_ci{ 8344514f5e3Sopenharmony_ci uint32_t traceNodeId = 0; 8354514f5e3Sopenharmony_ci auto result = methodToTraceNodeId_.find(methodLiteral); 8364514f5e3Sopenharmony_ci if (result == methodToTraceNodeId_.end()) { 8374514f5e3Sopenharmony_ci ASSERT(traceInfoStack_.size() > 0); 8384514f5e3Sopenharmony_ci traceNodeId = traceInfoStack_.size() - 1; 8394514f5e3Sopenharmony_ci methodToTraceNodeId_.emplace(methodLiteral, traceNodeId); 8404514f5e3Sopenharmony_ci } else { 8414514f5e3Sopenharmony_ci traceNodeId = result->second; 8424514f5e3Sopenharmony_ci } 8434514f5e3Sopenharmony_ci traceNodeIndex_.emplace_back(traceNodeId); 8444514f5e3Sopenharmony_ci} 8454514f5e3Sopenharmony_ci 8464514f5e3Sopenharmony_ciint HeapSnapshot::AddTraceNode(int sequenceId, int size) 8474514f5e3Sopenharmony_ci{ 8484514f5e3Sopenharmony_ci traceNodeIndex_.clear(); 8494514f5e3Sopenharmony_ci auto thread = vm_->GetJSThread(); 8504514f5e3Sopenharmony_ci JSTaggedType *current = const_cast<JSTaggedType *>(thread->GetCurrentFrame()); 8514514f5e3Sopenharmony_ci FrameIterator it(current, thread); 8524514f5e3Sopenharmony_ci for (; !it.Done(); it.Advance<GCVisitedFlag::VISITED>()) { 8534514f5e3Sopenharmony_ci if (!it.IsJSFrame()) { 8544514f5e3Sopenharmony_ci continue; 8554514f5e3Sopenharmony_ci } 8564514f5e3Sopenharmony_ci auto method = it.CheckAndGetMethod(); 8574514f5e3Sopenharmony_ci if (method == nullptr || method->IsNativeWithCallField()) { 8584514f5e3Sopenharmony_ci continue; 8594514f5e3Sopenharmony_ci } 8604514f5e3Sopenharmony_ci MethodLiteral *methodLiteral = method->GetMethodLiteral(); 8614514f5e3Sopenharmony_ci if (methodLiteral == nullptr) { 8624514f5e3Sopenharmony_ci continue; 8634514f5e3Sopenharmony_ci } 8644514f5e3Sopenharmony_ci if (stackInfo_.count(methodLiteral) == 0) { 8654514f5e3Sopenharmony_ci if (!AddMethodInfo(methodLiteral, method->GetJSPandaFile(), sequenceId)) { 8664514f5e3Sopenharmony_ci continue; 8674514f5e3Sopenharmony_ci } 8684514f5e3Sopenharmony_ci } 8694514f5e3Sopenharmony_ci AddTraceNodeId(methodLiteral); 8704514f5e3Sopenharmony_ci } 8714514f5e3Sopenharmony_ci 8724514f5e3Sopenharmony_ci TraceNode* topNode = traceTree_.AddNodeToTree(traceNodeIndex_); 8734514f5e3Sopenharmony_ci if (topNode == nullptr) { 8744514f5e3Sopenharmony_ci return -1; 8754514f5e3Sopenharmony_ci } 8764514f5e3Sopenharmony_ci ASSERT(topNode->GetTotalSize() <= static_cast<uint32_t>(INT_MAX)); 8774514f5e3Sopenharmony_ci int totalSize = static_cast<int>(topNode->GetTotalSize()); 8784514f5e3Sopenharmony_ci totalSize += size; 8794514f5e3Sopenharmony_ci topNode->SetTotalSize(totalSize); 8804514f5e3Sopenharmony_ci uint32_t totalCount = topNode->GetTotalCount(); 8814514f5e3Sopenharmony_ci topNode->SetTotalCount(++totalCount); 8824514f5e3Sopenharmony_ci return topNode->GetId(); 8834514f5e3Sopenharmony_ci} 8844514f5e3Sopenharmony_ci 8854514f5e3Sopenharmony_cibool HeapSnapshot::AddMethodInfo(MethodLiteral *methodLiteral, 8864514f5e3Sopenharmony_ci const JSPandaFile *jsPandaFile, 8874514f5e3Sopenharmony_ci int sequenceId) 8884514f5e3Sopenharmony_ci{ 8894514f5e3Sopenharmony_ci struct FunctionInfo codeEntry; 8904514f5e3Sopenharmony_ci codeEntry.functionId = sequenceId; 8914514f5e3Sopenharmony_ci panda_file::File::EntityId methodId = methodLiteral->GetMethodId(); 8924514f5e3Sopenharmony_ci const std::string &functionName = MethodLiteral::ParseFunctionName(jsPandaFile, methodId); 8934514f5e3Sopenharmony_ci if (functionName.empty()) { 8944514f5e3Sopenharmony_ci codeEntry.functionName = "anonymous"; 8954514f5e3Sopenharmony_ci } else { 8964514f5e3Sopenharmony_ci codeEntry.functionName = functionName; 8974514f5e3Sopenharmony_ci } 8984514f5e3Sopenharmony_ci GetString(codeEntry.functionName.c_str()); 8994514f5e3Sopenharmony_ci 9004514f5e3Sopenharmony_ci // source file 9014514f5e3Sopenharmony_ci DebugInfoExtractor *debugExtractor = 9024514f5e3Sopenharmony_ci JSPandaFileManager::GetInstance()->GetJSPtExtractor(jsPandaFile); 9034514f5e3Sopenharmony_ci const std::string &sourceFile = debugExtractor->GetSourceFile(methodId); 9044514f5e3Sopenharmony_ci if (sourceFile.empty()) { 9054514f5e3Sopenharmony_ci codeEntry.scriptName = ""; 9064514f5e3Sopenharmony_ci } else { 9074514f5e3Sopenharmony_ci codeEntry.scriptName = sourceFile; 9084514f5e3Sopenharmony_ci auto iter = scriptIdMap_.find(codeEntry.scriptName); 9094514f5e3Sopenharmony_ci if (iter == scriptIdMap_.end()) { 9104514f5e3Sopenharmony_ci scriptIdMap_.emplace(codeEntry.scriptName, scriptIdMap_.size() + 1); 9114514f5e3Sopenharmony_ci codeEntry.scriptId = static_cast<int>(scriptIdMap_.size()); 9124514f5e3Sopenharmony_ci } else { 9134514f5e3Sopenharmony_ci codeEntry.scriptId = iter->second; 9144514f5e3Sopenharmony_ci } 9154514f5e3Sopenharmony_ci } 9164514f5e3Sopenharmony_ci GetString(codeEntry.scriptName.c_str()); 9174514f5e3Sopenharmony_ci 9184514f5e3Sopenharmony_ci // line number 9194514f5e3Sopenharmony_ci codeEntry.lineNumber = debugExtractor->GetFristLine(methodId); 9204514f5e3Sopenharmony_ci // lineNumber is 0 means that lineTable error or empty function body, so jump this frame. 9214514f5e3Sopenharmony_ci if (UNLIKELY(codeEntry.lineNumber == 0)) { 9224514f5e3Sopenharmony_ci return false; 9234514f5e3Sopenharmony_ci } 9244514f5e3Sopenharmony_ci codeEntry.columnNumber = debugExtractor->GetFristColumn(methodId); 9254514f5e3Sopenharmony_ci 9264514f5e3Sopenharmony_ci traceInfoStack_.emplace_back(codeEntry); 9274514f5e3Sopenharmony_ci stackInfo_.emplace(methodLiteral, codeEntry); 9284514f5e3Sopenharmony_ci return true; 9294514f5e3Sopenharmony_ci} 9304514f5e3Sopenharmony_ci 9314514f5e3Sopenharmony_ciNode *HeapSnapshot::GenerateStringNode(JSTaggedValue entry, size_t size, bool isInFinish, bool isBinMod) 9324514f5e3Sopenharmony_ci{ 9334514f5e3Sopenharmony_ci static const CString EMPTY_STRING; 9344514f5e3Sopenharmony_ci JSTaggedType addr = entry.GetRawData(); 9354514f5e3Sopenharmony_ci Node *existNode = entryMap_.FindEntry(addr); // Fast Index 9364514f5e3Sopenharmony_ci if (existNode != nullptr) { 9374514f5e3Sopenharmony_ci if (isInFinish || isBinMod) { 9384514f5e3Sopenharmony_ci existNode->SetName(GetString(EntryVisitor::ConvertKey(entry))); 9394514f5e3Sopenharmony_ci } 9404514f5e3Sopenharmony_ci existNode->SetLive(true); 9414514f5e3Sopenharmony_ci return existNode; 9424514f5e3Sopenharmony_ci } 9434514f5e3Sopenharmony_ci // Allocation Event will generate string node for "". 9444514f5e3Sopenharmony_ci // When we need to serialize and isFinish is true, the nodeName will be given the actual string content. 9454514f5e3Sopenharmony_ci auto originStr = static_cast<EcmaString *>(entry.GetTaggedObject()); 9464514f5e3Sopenharmony_ci size_t selfsize = (size != 0) ? size : EcmaStringAccessor(originStr).GetFlatStringSize(); 9474514f5e3Sopenharmony_ci const CString *nodeName = &EMPTY_STRING; 9484514f5e3Sopenharmony_ci if (isInFinish || isBinMod) { 9494514f5e3Sopenharmony_ci nodeName = GetString(EntryVisitor::ConvertKey(entry)); 9504514f5e3Sopenharmony_ci } 9514514f5e3Sopenharmony_ci auto [idExist, sequenceId] = entryIdMap_->FindId(addr); 9524514f5e3Sopenharmony_ci Node *node = Node::NewNode(chunk_, sequenceId, nodeCount_, nodeName, NodeType::STRING, selfsize, 9534514f5e3Sopenharmony_ci 0, addr); 9544514f5e3Sopenharmony_ci if (!idExist) { 9554514f5e3Sopenharmony_ci entryIdMap_->InsertId(addr, sequenceId); 9564514f5e3Sopenharmony_ci } 9574514f5e3Sopenharmony_ci entryMap_.InsertEntry(node); 9584514f5e3Sopenharmony_ci InsertNodeUnique(node); 9594514f5e3Sopenharmony_ci return node; 9604514f5e3Sopenharmony_ci} 9614514f5e3Sopenharmony_ci 9624514f5e3Sopenharmony_ciNode *HeapSnapshot::GeneratePrivateStringNode(size_t size) 9634514f5e3Sopenharmony_ci{ 9644514f5e3Sopenharmony_ci if (privateStringNode_ != nullptr) { 9654514f5e3Sopenharmony_ci return privateStringNode_; 9664514f5e3Sopenharmony_ci } 9674514f5e3Sopenharmony_ci JSTaggedValue stringValue = vm_->GetJSThread()->GlobalConstants()->GetStringString(); 9684514f5e3Sopenharmony_ci auto originStr = static_cast<EcmaString *>(stringValue.GetTaggedObject()); 9694514f5e3Sopenharmony_ci size_t selfsize = (size != 0) ? size : EcmaStringAccessor(originStr).GetFlatStringSize(); 9704514f5e3Sopenharmony_ci CString strContent; 9714514f5e3Sopenharmony_ci strContent.append(EntryVisitor::ConvertKey(stringValue)); 9724514f5e3Sopenharmony_ci JSTaggedType addr = stringValue.GetRawData(); 9734514f5e3Sopenharmony_ci auto [idExist, sequenceId] = entryIdMap_->FindId(addr); 9744514f5e3Sopenharmony_ci Node *node = Node::NewNode(chunk_, sequenceId, nodeCount_, GetString(strContent), NodeType::STRING, selfsize, 9754514f5e3Sopenharmony_ci 0, addr); 9764514f5e3Sopenharmony_ci if (!idExist) { 9774514f5e3Sopenharmony_ci entryIdMap_->InsertId(addr, sequenceId); 9784514f5e3Sopenharmony_ci } 9794514f5e3Sopenharmony_ci entryMap_.InsertEntry(node); 9804514f5e3Sopenharmony_ci InsertNodeUnique(node); 9814514f5e3Sopenharmony_ci ASSERT(entryMap_.FindEntry(node->GetAddress())->GetAddress() == node->GetAddress()); 9824514f5e3Sopenharmony_ci privateStringNode_ = node; 9834514f5e3Sopenharmony_ci return node; 9844514f5e3Sopenharmony_ci} 9854514f5e3Sopenharmony_ci 9864514f5e3Sopenharmony_ciNode *HeapSnapshot::GenerateFunctionNode(JSTaggedValue entry, size_t size, bool isInFinish) 9874514f5e3Sopenharmony_ci{ 9884514f5e3Sopenharmony_ci TaggedObject *obj = entry.GetTaggedObject(); 9894514f5e3Sopenharmony_ci JSTaggedType addr = entry.GetRawData(); 9904514f5e3Sopenharmony_ci Node *existNode = entryMap_.FindEntry(addr); 9914514f5e3Sopenharmony_ci auto [idExist, sequenceId] = entryIdMap_->FindId(addr); 9924514f5e3Sopenharmony_ci if (existNode != nullptr) { 9934514f5e3Sopenharmony_ci if (isInFinish) { 9944514f5e3Sopenharmony_ci existNode->SetName(GetString(ParseFunctionName(obj))); 9954514f5e3Sopenharmony_ci } 9964514f5e3Sopenharmony_ci existNode->SetLive(true); 9974514f5e3Sopenharmony_ci return existNode; 9984514f5e3Sopenharmony_ci } 9994514f5e3Sopenharmony_ci size_t selfsize = (size != 0) ? size : obj->GetClass()->SizeFromJSHClass(obj); 10004514f5e3Sopenharmony_ci Node *node = Node::NewNode(chunk_, sequenceId, nodeCount_, GetString("JSFunction"), NodeType::CLOSURE, selfsize, 10014514f5e3Sopenharmony_ci 0, addr); 10024514f5e3Sopenharmony_ci if (isInFinish) { 10034514f5e3Sopenharmony_ci node->SetName(GetString(ParseFunctionName(obj))); 10044514f5e3Sopenharmony_ci } 10054514f5e3Sopenharmony_ci if (!idExist) { 10064514f5e3Sopenharmony_ci entryIdMap_->InsertId(addr, sequenceId); 10074514f5e3Sopenharmony_ci } 10084514f5e3Sopenharmony_ci entryMap_.InsertEntry(node); 10094514f5e3Sopenharmony_ci InsertNodeUnique(node); 10104514f5e3Sopenharmony_ci return node; 10114514f5e3Sopenharmony_ci} 10124514f5e3Sopenharmony_ci 10134514f5e3Sopenharmony_ciNode *HeapSnapshot::GenerateObjectNode(JSTaggedValue entry, size_t size, bool isInFinish) 10144514f5e3Sopenharmony_ci{ 10154514f5e3Sopenharmony_ci TaggedObject *obj = entry.GetTaggedObject(); 10164514f5e3Sopenharmony_ci JSTaggedType addr = entry.GetRawData(); 10174514f5e3Sopenharmony_ci Node *existNode = entryMap_.FindEntry(addr); 10184514f5e3Sopenharmony_ci auto [idExist, sequenceId] = entryIdMap_->FindId(addr); 10194514f5e3Sopenharmony_ci if (existNode != nullptr) { 10204514f5e3Sopenharmony_ci if (isInFinish) { 10214514f5e3Sopenharmony_ci existNode->SetName(GetString(ParseObjectName(obj))); 10224514f5e3Sopenharmony_ci } 10234514f5e3Sopenharmony_ci existNode->SetLive(true); 10244514f5e3Sopenharmony_ci return existNode; 10254514f5e3Sopenharmony_ci } 10264514f5e3Sopenharmony_ci size_t selfsize = (size != 0) ? size : obj->GetClass()->SizeFromJSHClass(obj); 10274514f5e3Sopenharmony_ci Node *node = Node::NewNode(chunk_, sequenceId, nodeCount_, GetString("Object"), NodeType::OBJECT, selfsize, 10284514f5e3Sopenharmony_ci 0, addr); 10294514f5e3Sopenharmony_ci if (isInFinish) { 10304514f5e3Sopenharmony_ci node->SetName(GetString(ParseObjectName(obj))); 10314514f5e3Sopenharmony_ci } 10324514f5e3Sopenharmony_ci if (!idExist) { 10334514f5e3Sopenharmony_ci entryIdMap_->InsertId(addr, sequenceId); 10344514f5e3Sopenharmony_ci } 10354514f5e3Sopenharmony_ci entryMap_.InsertEntry(node); 10364514f5e3Sopenharmony_ci InsertNodeUnique(node); 10374514f5e3Sopenharmony_ci return node; 10384514f5e3Sopenharmony_ci} 10394514f5e3Sopenharmony_ci 10404514f5e3Sopenharmony_civoid HeapSnapshot::FillEdges(bool isSimplify) 10414514f5e3Sopenharmony_ci{ 10424514f5e3Sopenharmony_ci auto iter = nodes_.begin(); 10434514f5e3Sopenharmony_ci size_t count = 0; 10444514f5e3Sopenharmony_ci while (count++ < nodes_.size()) { 10454514f5e3Sopenharmony_ci ASSERT(*iter != nullptr); 10464514f5e3Sopenharmony_ci auto entryFrom = *iter; 10474514f5e3Sopenharmony_ci JSTaggedValue value(entryFrom->GetAddress()); 10484514f5e3Sopenharmony_ci if (!value.IsHeapObject()) { 10494514f5e3Sopenharmony_ci iter++; 10504514f5e3Sopenharmony_ci continue; 10514514f5e3Sopenharmony_ci } 10524514f5e3Sopenharmony_ci std::vector<Reference> referenceResources; 10534514f5e3Sopenharmony_ci value.DumpForSnapshot(referenceResources, isVmMode_); 10544514f5e3Sopenharmony_ci for (auto const &it : referenceResources) { 10554514f5e3Sopenharmony_ci JSTaggedValue toValue = it.value_; 10564514f5e3Sopenharmony_ci if (toValue.IsNumber() && !captureNumericValue_) { 10574514f5e3Sopenharmony_ci continue; 10584514f5e3Sopenharmony_ci } 10594514f5e3Sopenharmony_ci Node *entryTo = nullptr; 10604514f5e3Sopenharmony_ci EdgeType type = toValue.IsWeak() ? EdgeType::WEAK : (EdgeType)it.type_; 10614514f5e3Sopenharmony_ci if (toValue.IsWeak()) { 10624514f5e3Sopenharmony_ci toValue.RemoveWeakTag(); 10634514f5e3Sopenharmony_ci } 10644514f5e3Sopenharmony_ci if (toValue.IsHeapObject()) { 10654514f5e3Sopenharmony_ci auto *to = toValue.GetTaggedObject(); 10664514f5e3Sopenharmony_ci entryTo = entryMap_.FindEntry(Node::NewAddress(to)); 10674514f5e3Sopenharmony_ci } 10684514f5e3Sopenharmony_ci if (entryTo == nullptr) { 10694514f5e3Sopenharmony_ci entryTo = GenerateNode(toValue, 0, true, isSimplify); 10704514f5e3Sopenharmony_ci } 10714514f5e3Sopenharmony_ci if (entryTo != nullptr) { 10724514f5e3Sopenharmony_ci Edge *edge = (it.type_ == Reference::ReferenceType::ELEMENT) ? 10734514f5e3Sopenharmony_ci Edge::NewEdge(chunk_, type, entryFrom, entryTo, it.index_) : 10744514f5e3Sopenharmony_ci Edge::NewEdge(chunk_, type, entryFrom, entryTo, GetString(it.name_)); 10754514f5e3Sopenharmony_ci RenameFunction(it.name_, entryFrom, entryTo); 10764514f5e3Sopenharmony_ci InsertEdgeUnique(edge); 10774514f5e3Sopenharmony_ci (*iter)->IncEdgeCount(); // Update Node's edgeCount_ here 10784514f5e3Sopenharmony_ci } 10794514f5e3Sopenharmony_ci } 10804514f5e3Sopenharmony_ci iter++; 10814514f5e3Sopenharmony_ci } 10824514f5e3Sopenharmony_ci} 10834514f5e3Sopenharmony_ci 10844514f5e3Sopenharmony_civoid HeapSnapshot::FillEdgesForBinMod(RawHeapObjInfo *objInfo) 10854514f5e3Sopenharmony_ci{ 10864514f5e3Sopenharmony_ci auto entryFrom = entryMap_.FindEntry(reinterpret_cast<JSTaggedType>(objInfo->newAddr)); 10874514f5e3Sopenharmony_ci JSTaggedValue value(entryFrom->GetAddress()); 10884514f5e3Sopenharmony_ci auto object = value.GetTaggedObject(); 10894514f5e3Sopenharmony_ci std::vector<Reference> referenceResources; 10904514f5e3Sopenharmony_ci auto jsHclass = object->GetClass(); 10914514f5e3Sopenharmony_ci if (jsHclass->IsJsGlobalEnv() || jsHclass->IsString()) { 10924514f5e3Sopenharmony_ci referenceResources.emplace_back("hclass", JSTaggedValue(jsHclass)); 10934514f5e3Sopenharmony_ci for (auto refAddr : objInfo->refSet) { 10944514f5e3Sopenharmony_ci JSTaggedValue val(refAddr); 10954514f5e3Sopenharmony_ci auto valTy = val.GetTaggedObject()->GetClass()->GetObjectType(); 10964514f5e3Sopenharmony_ci referenceResources.emplace_back(JSHClass::DumpJSType(valTy), val); 10974514f5e3Sopenharmony_ci } 10984514f5e3Sopenharmony_ci } else { 10994514f5e3Sopenharmony_ci value.DumpForSnapshot(referenceResources, false); 11004514f5e3Sopenharmony_ci } 11014514f5e3Sopenharmony_ci for (auto const &it : referenceResources) { 11024514f5e3Sopenharmony_ci JSTaggedValue toValue = it.value_; 11034514f5e3Sopenharmony_ci if (toValue.IsNumber() && !captureNumericValue_) { 11044514f5e3Sopenharmony_ci continue; 11054514f5e3Sopenharmony_ci } 11064514f5e3Sopenharmony_ci Node *entryTo = nullptr; 11074514f5e3Sopenharmony_ci EdgeType type = toValue.IsWeak() ? EdgeType::WEAK : (EdgeType)it.type_; 11084514f5e3Sopenharmony_ci if (toValue.IsWeak()) { 11094514f5e3Sopenharmony_ci toValue.RemoveWeakTag(); 11104514f5e3Sopenharmony_ci } 11114514f5e3Sopenharmony_ci if (toValue.IsHeapObject()) { 11124514f5e3Sopenharmony_ci auto *to = toValue.GetTaggedObject(); 11134514f5e3Sopenharmony_ci entryTo = entryMap_.FindEntry(Node::NewAddress(to)); 11144514f5e3Sopenharmony_ci } 11154514f5e3Sopenharmony_ci if (entryTo == nullptr) { 11164514f5e3Sopenharmony_ci CString name; 11174514f5e3Sopenharmony_ci name.append("MissObj").append(std::to_string(toValue.GetRawData())); 11184514f5e3Sopenharmony_ci Node *missObj = Node::NewNode(chunk_, 1, nodeCount_, GetString(name), NodeType::OBJECT, 0, 0, 0); 11194514f5e3Sopenharmony_ci entryMap_.InsertEntry(missObj); 11204514f5e3Sopenharmony_ci InsertNodeUnique(missObj); 11214514f5e3Sopenharmony_ci } 11224514f5e3Sopenharmony_ci if (entryTo != nullptr) { 11234514f5e3Sopenharmony_ci Edge *edge = (it.type_ == Reference::ReferenceType::ELEMENT) ? 11244514f5e3Sopenharmony_ci Edge::NewEdge(chunk_, type, entryFrom, entryTo, it.index_) : 11254514f5e3Sopenharmony_ci Edge::NewEdge(chunk_, type, entryFrom, entryTo, GetString(it.name_)); 11264514f5e3Sopenharmony_ci RenameFunction(it.name_, entryFrom, entryTo); 11274514f5e3Sopenharmony_ci InsertEdgeUnique(edge); 11284514f5e3Sopenharmony_ci entryFrom->IncEdgeCount(); // Update Node's edgeCount_ here 11294514f5e3Sopenharmony_ci } 11304514f5e3Sopenharmony_ci } 11314514f5e3Sopenharmony_ci} 11324514f5e3Sopenharmony_ci 11334514f5e3Sopenharmony_civoid HeapSnapshot::AddSyntheticRootForBinMod(RawHeapObjInfo *objInfo, int &edgeOffset, Node *syntheticRoot) 11344514f5e3Sopenharmony_ci{ 11354514f5e3Sopenharmony_ci if (!objInfo->isRoot) { 11364514f5e3Sopenharmony_ci return; 11374514f5e3Sopenharmony_ci } 11384514f5e3Sopenharmony_ci TaggedObject *root = reinterpret_cast<TaggedObject *>(objInfo->newAddr); 11394514f5e3Sopenharmony_ci Node *rootNode = entryMap_.FindEntry(Node::NewAddress(root)); 11404514f5e3Sopenharmony_ci if (rootNode != nullptr) { 11414514f5e3Sopenharmony_ci Edge *edge = Edge::NewEdge(chunk_, 11424514f5e3Sopenharmony_ci EdgeType::SHORTCUT, syntheticRoot, rootNode, GetString("-subroot-")); 11434514f5e3Sopenharmony_ci InsertEdgeAt(edgeOffset, edge); 11444514f5e3Sopenharmony_ci edgeOffset++; 11454514f5e3Sopenharmony_ci syntheticRoot->IncEdgeCount(); 11464514f5e3Sopenharmony_ci } 11474514f5e3Sopenharmony_ci} 11484514f5e3Sopenharmony_ci 11494514f5e3Sopenharmony_ciNode *HeapSnapshot::GenerateNodeForBinMod(TaggedObject *obj, RawHeapObjInfo *objInfo, 11504514f5e3Sopenharmony_ci CUnorderedMap<uint64_t, const char *> &strTableIdMap) 11514514f5e3Sopenharmony_ci{ 11524514f5e3Sopenharmony_ci auto currNode = GenerateNode(JSTaggedValue(obj), objInfo->tInfo->objSize, false, false, true); 11534514f5e3Sopenharmony_ci if (strTableIdMap.find(objInfo->tInfo->stringId) != strTableIdMap.end() 11544514f5e3Sopenharmony_ci && strTableIdMap[objInfo->tInfo->stringId] != nullptr) { 11554514f5e3Sopenharmony_ci if (currNode != nullptr) { 11564514f5e3Sopenharmony_ci currNode->SetName(GetString(strTableIdMap[objInfo->tInfo->stringId])); 11574514f5e3Sopenharmony_ci } 11584514f5e3Sopenharmony_ci } 11594514f5e3Sopenharmony_ci return currNode; 11604514f5e3Sopenharmony_ci} 11614514f5e3Sopenharmony_ci 11624514f5e3Sopenharmony_cibool HeapSnapshot::BuildSnapshotForBinMod(CVector<RawHeapObjInfo *> &objInfoVec) 11634514f5e3Sopenharmony_ci{ 11644514f5e3Sopenharmony_ci Node *syntheticRoot = Node::NewNode(chunk_, 1, nodeCount_, GetString("SyntheticRoot"), 11654514f5e3Sopenharmony_ci NodeType::SYNTHETIC, 0, 0, 0); 11664514f5e3Sopenharmony_ci InsertNodeAt(0, syntheticRoot); 11674514f5e3Sopenharmony_ci int edgeOffset = 0; 11684514f5e3Sopenharmony_ci for (auto objInfo : objInfoVec) { 11694514f5e3Sopenharmony_ci FillEdgesForBinMod(objInfo); 11704514f5e3Sopenharmony_ci AddSyntheticRootForBinMod(objInfo, edgeOffset, syntheticRoot); 11714514f5e3Sopenharmony_ci } 11724514f5e3Sopenharmony_ci int reindex = 0; 11734514f5e3Sopenharmony_ci for (Node *node : nodes_) { 11744514f5e3Sopenharmony_ci node->SetIndex(reindex); 11754514f5e3Sopenharmony_ci reindex++; 11764514f5e3Sopenharmony_ci } 11774514f5e3Sopenharmony_ci return Verify(); 11784514f5e3Sopenharmony_ci} 11794514f5e3Sopenharmony_ci 11804514f5e3Sopenharmony_civoid HeapSnapshot::RenameFunction(const CString &edgeName, Node *entryFrom, Node *entryTo) 11814514f5e3Sopenharmony_ci{ 11824514f5e3Sopenharmony_ci if (edgeName != "name") { 11834514f5e3Sopenharmony_ci return; 11844514f5e3Sopenharmony_ci } 11854514f5e3Sopenharmony_ci if (entryFrom->GetType() != NodeType::CLOSURE) { 11864514f5e3Sopenharmony_ci return; 11874514f5e3Sopenharmony_ci } 11884514f5e3Sopenharmony_ci if (*entryFrom->GetName() == "JSFunction" && *entryTo->GetName() != "" && 11894514f5e3Sopenharmony_ci *entryTo->GetName() != "InternalAccessor") { 11904514f5e3Sopenharmony_ci entryFrom->SetName(GetString(*entryTo->GetName())); 11914514f5e3Sopenharmony_ci } 11924514f5e3Sopenharmony_ci} 11934514f5e3Sopenharmony_ci 11944514f5e3Sopenharmony_ciCString HeapSnapshot::ParseFunctionName(TaggedObject *obj) 11954514f5e3Sopenharmony_ci{ 11964514f5e3Sopenharmony_ci CString result; 11974514f5e3Sopenharmony_ci JSFunctionBase *func = JSFunctionBase::Cast(obj); 11984514f5e3Sopenharmony_ci Method *method = Method::Cast(func->GetMethod().GetTaggedObject()); 11994514f5e3Sopenharmony_ci MethodLiteral *methodLiteral = method->GetMethodLiteral(); 12004514f5e3Sopenharmony_ci if (methodLiteral == nullptr) { 12014514f5e3Sopenharmony_ci return "JSFunction"; 12024514f5e3Sopenharmony_ci } 12034514f5e3Sopenharmony_ci const JSPandaFile *jsPandaFile = method->GetJSPandaFile(); 12044514f5e3Sopenharmony_ci panda_file::File::EntityId methodId = methodLiteral->GetMethodId(); 12054514f5e3Sopenharmony_ci const CString &nameStr = MethodLiteral::ParseFunctionNameToCString(jsPandaFile, methodId); 12064514f5e3Sopenharmony_ci const CString &moduleStr = method->GetRecordNameStr(); 12074514f5e3Sopenharmony_ci 12084514f5e3Sopenharmony_ci if (!moduleStr.empty()) { 12094514f5e3Sopenharmony_ci result.append(moduleStr).append(" "); 12104514f5e3Sopenharmony_ci } 12114514f5e3Sopenharmony_ci if (nameStr.empty()) { 12124514f5e3Sopenharmony_ci result.append("anonymous"); 12134514f5e3Sopenharmony_ci } else { 12144514f5e3Sopenharmony_ci result.append(nameStr); 12154514f5e3Sopenharmony_ci } 12164514f5e3Sopenharmony_ci DebugInfoExtractor *debugExtractor = 12174514f5e3Sopenharmony_ci JSPandaFileManager::GetInstance()->GetJSPtExtractor(jsPandaFile); 12184514f5e3Sopenharmony_ci if (debugExtractor == nullptr) { 12194514f5e3Sopenharmony_ci return result; 12204514f5e3Sopenharmony_ci } 12214514f5e3Sopenharmony_ci int32_t line = debugExtractor->GetFristLine(methodId); 12224514f5e3Sopenharmony_ci return result.append("(line:").append(std::to_string(line)).append(")"); 12234514f5e3Sopenharmony_ci} 12244514f5e3Sopenharmony_ci 12254514f5e3Sopenharmony_ciconst CString HeapSnapshot::ParseObjectName(TaggedObject *obj) 12264514f5e3Sopenharmony_ci{ 12274514f5e3Sopenharmony_ci ASSERT(JSTaggedValue(obj).IsJSObject()); 12284514f5e3Sopenharmony_ci JSThread *thread = vm_->GetJSThread(); 12294514f5e3Sopenharmony_ci bool isCallGetter = false; 12304514f5e3Sopenharmony_ci return JSObject::ExtractConstructorAndRecordName(thread, obj, true, &isCallGetter); 12314514f5e3Sopenharmony_ci} 12324514f5e3Sopenharmony_ci 12334514f5e3Sopenharmony_ciNode *HeapSnapshot::InsertNodeUnique(Node *node) 12344514f5e3Sopenharmony_ci{ 12354514f5e3Sopenharmony_ci AccumulateNodeSize(node->GetSelfSize()); 12364514f5e3Sopenharmony_ci nodes_.emplace_back(node); 12374514f5e3Sopenharmony_ci nodeCount_++; 12384514f5e3Sopenharmony_ci return node; 12394514f5e3Sopenharmony_ci} 12404514f5e3Sopenharmony_ci 12414514f5e3Sopenharmony_civoid HeapSnapshot::EraseNodeUnique(Node *node) 12424514f5e3Sopenharmony_ci{ 12434514f5e3Sopenharmony_ci auto iter = std::find(nodes_.begin(), nodes_.end(), node); 12444514f5e3Sopenharmony_ci if (iter != nodes_.end()) { 12454514f5e3Sopenharmony_ci DecreaseNodeSize(node->GetSelfSize()); 12464514f5e3Sopenharmony_ci chunk_->Delete(node); 12474514f5e3Sopenharmony_ci nodes_.erase(iter); 12484514f5e3Sopenharmony_ci nodeCount_--; 12494514f5e3Sopenharmony_ci } 12504514f5e3Sopenharmony_ci} 12514514f5e3Sopenharmony_ci 12524514f5e3Sopenharmony_ciEdge *HeapSnapshot::InsertEdgeUnique(Edge *edge) 12534514f5e3Sopenharmony_ci{ 12544514f5e3Sopenharmony_ci edges_.emplace_back(edge); 12554514f5e3Sopenharmony_ci edgeCount_++; 12564514f5e3Sopenharmony_ci return edge; 12574514f5e3Sopenharmony_ci} 12584514f5e3Sopenharmony_ci 12594514f5e3Sopenharmony_civoid HeapSnapshot::AddSyntheticRoot() 12604514f5e3Sopenharmony_ci{ 12614514f5e3Sopenharmony_ci Node *syntheticRoot = Node::NewNode(chunk_, 1, nodeCount_, GetString("SyntheticRoot"), 12624514f5e3Sopenharmony_ci NodeType::SYNTHETIC, 0, 0, 0); 12634514f5e3Sopenharmony_ci InsertNodeAt(0, syntheticRoot); 12644514f5e3Sopenharmony_ci CUnorderedSet<JSTaggedType> values {}; 12654514f5e3Sopenharmony_ci int edgeOffset = 0; 12664514f5e3Sopenharmony_ci// NOLINTNEXTLINE(cppcoreguidelines-macro-usage) 12674514f5e3Sopenharmony_ci#define ROOT_EDGE_BUILDER_CORE(type, slot) \ 12684514f5e3Sopenharmony_ci do { \ 12694514f5e3Sopenharmony_ci JSTaggedValue value((slot).GetTaggedType()); \ 12704514f5e3Sopenharmony_ci if (value.IsHeapObject()) { \ 12714514f5e3Sopenharmony_ci TaggedObject *root = value.GetTaggedObject(); \ 12724514f5e3Sopenharmony_ci Node *rootNode = entryMap_.FindEntry(Node::NewAddress(root)); \ 12734514f5e3Sopenharmony_ci if (rootNode != nullptr) { \ 12744514f5e3Sopenharmony_ci JSTaggedType valueTo = value.GetRawData(); \ 12754514f5e3Sopenharmony_ci auto it = values.find(valueTo); \ 12764514f5e3Sopenharmony_ci if (it == values.end()) { \ 12774514f5e3Sopenharmony_ci values.insert(valueTo); \ 12784514f5e3Sopenharmony_ci Edge *edge = Edge::NewEdge(chunk_, \ 12794514f5e3Sopenharmony_ci EdgeType::SHORTCUT, syntheticRoot, rootNode, GetString("-subroot-")); \ 12804514f5e3Sopenharmony_ci InsertEdgeAt(edgeOffset, edge); \ 12814514f5e3Sopenharmony_ci edgeOffset++; \ 12824514f5e3Sopenharmony_ci syntheticRoot->IncEdgeCount(); \ 12834514f5e3Sopenharmony_ci } \ 12844514f5e3Sopenharmony_ci } \ 12854514f5e3Sopenharmony_ci } \ 12864514f5e3Sopenharmony_ci } while (false) 12874514f5e3Sopenharmony_ci 12884514f5e3Sopenharmony_ci RootVisitor rootEdgeBuilder = [this, syntheticRoot, &edgeOffset, &values]( 12894514f5e3Sopenharmony_ci [[maybe_unused]] Root type, ObjectSlot slot) { 12904514f5e3Sopenharmony_ci ROOT_EDGE_BUILDER_CORE(type, slot); 12914514f5e3Sopenharmony_ci }; 12924514f5e3Sopenharmony_ci RootBaseAndDerivedVisitor rootBaseEdgeBuilder = [] 12934514f5e3Sopenharmony_ci ([[maybe_unused]] Root type, [[maybe_unused]] ObjectSlot base, [[maybe_unused]] ObjectSlot derived, 12944514f5e3Sopenharmony_ci [[maybe_unused]] uintptr_t baseOldObject) { 12954514f5e3Sopenharmony_ci }; 12964514f5e3Sopenharmony_ci 12974514f5e3Sopenharmony_ci RootRangeVisitor rootRangeEdgeBuilder = [this, syntheticRoot, &edgeOffset, &values]([[maybe_unused]] Root type, 12984514f5e3Sopenharmony_ci ObjectSlot start, ObjectSlot end) { 12994514f5e3Sopenharmony_ci for (ObjectSlot slot = start; slot < end; slot++) { 13004514f5e3Sopenharmony_ci ROOT_EDGE_BUILDER_CORE(type, slot); 13014514f5e3Sopenharmony_ci } 13024514f5e3Sopenharmony_ci }; 13034514f5e3Sopenharmony_ci#undef ROOT_EDGE_BUILDER_CORE 13044514f5e3Sopenharmony_ci rootVisitor_.VisitHeapRoots(vm_->GetJSThread(), rootEdgeBuilder, rootRangeEdgeBuilder, rootBaseEdgeBuilder); 13054514f5e3Sopenharmony_ci 13064514f5e3Sopenharmony_ci int reindex = 0; 13074514f5e3Sopenharmony_ci for (Node *node : nodes_) { 13084514f5e3Sopenharmony_ci node->SetIndex(reindex); 13094514f5e3Sopenharmony_ci reindex++; 13104514f5e3Sopenharmony_ci } 13114514f5e3Sopenharmony_ci} 13124514f5e3Sopenharmony_ci 13134514f5e3Sopenharmony_ciNode *HeapSnapshot::InsertNodeAt(size_t pos, Node *node) 13144514f5e3Sopenharmony_ci{ 13154514f5e3Sopenharmony_ci ASSERT(node != nullptr); 13164514f5e3Sopenharmony_ci auto iter = nodes_.begin(); 13174514f5e3Sopenharmony_ci std::advance(iter, static_cast<int>(pos)); 13184514f5e3Sopenharmony_ci nodes_.insert(iter, node); 13194514f5e3Sopenharmony_ci nodeCount_++; 13204514f5e3Sopenharmony_ci return node; 13214514f5e3Sopenharmony_ci} 13224514f5e3Sopenharmony_ci 13234514f5e3Sopenharmony_ciEdge *HeapSnapshot::InsertEdgeAt(size_t pos, Edge *edge) 13244514f5e3Sopenharmony_ci{ 13254514f5e3Sopenharmony_ci ASSERT(edge != nullptr); 13264514f5e3Sopenharmony_ci auto iter = edges_.begin(); 13274514f5e3Sopenharmony_ci std::advance(iter, static_cast<int>(pos)); 13284514f5e3Sopenharmony_ci edges_.insert(iter, edge); 13294514f5e3Sopenharmony_ci edgeCount_++; 13304514f5e3Sopenharmony_ci return edge; 13314514f5e3Sopenharmony_ci} 13324514f5e3Sopenharmony_ci 13334514f5e3Sopenharmony_ciCString EntryVisitor::ConvertKey(JSTaggedValue key) 13344514f5e3Sopenharmony_ci{ 13354514f5e3Sopenharmony_ci ASSERT(key.GetTaggedObject() != nullptr); 13364514f5e3Sopenharmony_ci EcmaString *keyString = EcmaString::Cast(key.GetTaggedObject()); 13374514f5e3Sopenharmony_ci 13384514f5e3Sopenharmony_ci if (key.IsSymbol()) { 13394514f5e3Sopenharmony_ci JSSymbol *symbol = JSSymbol::Cast(key.GetTaggedObject()); 13404514f5e3Sopenharmony_ci keyString = EcmaString::Cast(symbol->GetDescription().GetTaggedObject()); 13414514f5e3Sopenharmony_ci } 13424514f5e3Sopenharmony_ci // convert, expensive but safe 13434514f5e3Sopenharmony_ci return EcmaStringAccessor(keyString).ToCString(StringConvertedUsage::PRINT); 13444514f5e3Sopenharmony_ci} 13454514f5e3Sopenharmony_ci 13464514f5e3Sopenharmony_ciNode *HeapEntryMap::FindOrInsertNode(Node *node) 13474514f5e3Sopenharmony_ci{ 13484514f5e3Sopenharmony_ci ASSERT(node != nullptr); 13494514f5e3Sopenharmony_ci auto it = nodesMap_.find(node->GetAddress()); 13504514f5e3Sopenharmony_ci if (it != nodesMap_.end()) { 13514514f5e3Sopenharmony_ci return it->second; 13524514f5e3Sopenharmony_ci } 13534514f5e3Sopenharmony_ci InsertEntry(node); 13544514f5e3Sopenharmony_ci return node; 13554514f5e3Sopenharmony_ci} 13564514f5e3Sopenharmony_ci 13574514f5e3Sopenharmony_ciNode *HeapEntryMap::FindAndEraseNode(JSTaggedType addr) 13584514f5e3Sopenharmony_ci{ 13594514f5e3Sopenharmony_ci auto it = nodesMap_.find(addr); 13604514f5e3Sopenharmony_ci if (it != nodesMap_.end()) { 13614514f5e3Sopenharmony_ci Node *node = it->second; 13624514f5e3Sopenharmony_ci nodesMap_.erase(it); 13634514f5e3Sopenharmony_ci return node; 13644514f5e3Sopenharmony_ci } 13654514f5e3Sopenharmony_ci return nullptr; 13664514f5e3Sopenharmony_ci} 13674514f5e3Sopenharmony_ci 13684514f5e3Sopenharmony_ciNode *HeapEntryMap::FindEntry(JSTaggedType addr) 13694514f5e3Sopenharmony_ci{ 13704514f5e3Sopenharmony_ci auto it = nodesMap_.find(addr); 13714514f5e3Sopenharmony_ci return it != nodesMap_.end() ? it->second : nullptr; 13724514f5e3Sopenharmony_ci} 13734514f5e3Sopenharmony_ci 13744514f5e3Sopenharmony_civoid HeapEntryMap::InsertEntry(Node *node) 13754514f5e3Sopenharmony_ci{ 13764514f5e3Sopenharmony_ci nodesMap_.emplace(node->GetAddress(), node); 13774514f5e3Sopenharmony_ci} 13784514f5e3Sopenharmony_ci} // namespace panda::ecmascript 1379