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