14514f5e3Sopenharmony_ci/* 24514f5e3Sopenharmony_ci * Copyright (c) 2021-2023 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#ifndef ECMASCRIPT_DFX_HPROF_HEAP_SNAPSHOT_H 174514f5e3Sopenharmony_ci#define ECMASCRIPT_DFX_HPROF_HEAP_SNAPSHOT_H 184514f5e3Sopenharmony_ci 194514f5e3Sopenharmony_ci#include <atomic> 204514f5e3Sopenharmony_ci#include <cstdint> 214514f5e3Sopenharmony_ci#include <fstream> 224514f5e3Sopenharmony_ci#include <sys/time.h> 234514f5e3Sopenharmony_ci 244514f5e3Sopenharmony_ci#include "ecmascript/dfx/hprof/heap_profiler.h" 254514f5e3Sopenharmony_ci#include "ecmascript/dfx/hprof/heap_root_visitor.h" 264514f5e3Sopenharmony_ci#include "ecmascript/dfx/hprof/string_hashmap.h" 274514f5e3Sopenharmony_ci#include "ecmascript/js_hclass.h" 284514f5e3Sopenharmony_ci#include "ecmascript/js_object.h" 294514f5e3Sopenharmony_ci#include "ecmascript/js_tagged_value.h" 304514f5e3Sopenharmony_ci#include "ecmascript/jspandafile/method_literal.h" 314514f5e3Sopenharmony_ci#include "ecmascript/mem/c_containers.h" 324514f5e3Sopenharmony_ci#include "ecmascript/dfx/hprof/file_stream.h" 334514f5e3Sopenharmony_ci#include "ecmascript/interpreter/frame_handler.h" 344514f5e3Sopenharmony_ci#include "ecmascript/mem/object_xray.h" 354514f5e3Sopenharmony_ci#include "ecmascript/object_fast_operator.h" 364514f5e3Sopenharmony_ci 374514f5e3Sopenharmony_cinamespace panda::ecmascript { 384514f5e3Sopenharmony_ciclass EntryIdMap; 394514f5e3Sopenharmony_ci// Define the Object Graphic 404514f5e3Sopenharmony_ciusing Address = uintptr_t; 414514f5e3Sopenharmony_ci 424514f5e3Sopenharmony_cienum class NodeType { 434514f5e3Sopenharmony_ci HIDDEN, 444514f5e3Sopenharmony_ci ARRAY, 454514f5e3Sopenharmony_ci STRING, 464514f5e3Sopenharmony_ci OBJECT, 474514f5e3Sopenharmony_ci CODE, 484514f5e3Sopenharmony_ci CLOSURE, 494514f5e3Sopenharmony_ci REGEXP, 504514f5e3Sopenharmony_ci HEAPNUMBER, 514514f5e3Sopenharmony_ci NATIVE, 524514f5e3Sopenharmony_ci SYNTHETIC, 534514f5e3Sopenharmony_ci CONSSTRING, 544514f5e3Sopenharmony_ci SLICEDSTRING, 554514f5e3Sopenharmony_ci SYMBOL, 564514f5e3Sopenharmony_ci BIGINT, 574514f5e3Sopenharmony_ci DEFAULT = NATIVE, 584514f5e3Sopenharmony_ci}; 594514f5e3Sopenharmony_ci 604514f5e3Sopenharmony_cienum class EdgeType { CONTEXT, ELEMENT, PROPERTY, INTERNAL, HIDDEN, SHORTCUT, WEAK, DEFAULT = PROPERTY }; 614514f5e3Sopenharmony_ci 624514f5e3Sopenharmony_ciclass Node { 634514f5e3Sopenharmony_cipublic: 644514f5e3Sopenharmony_ci Node(NodeId id, uint32_t index, const CString *name, NodeType type, size_t size, size_t nativeSize, 654514f5e3Sopenharmony_ci uint32_t traceId, JSTaggedType address, bool isLive = true) 664514f5e3Sopenharmony_ci : id_(id), 674514f5e3Sopenharmony_ci index_(index), 684514f5e3Sopenharmony_ci name_(name), 694514f5e3Sopenharmony_ci type_(type), 704514f5e3Sopenharmony_ci size_(size), 714514f5e3Sopenharmony_ci nativeSize_(nativeSize), 724514f5e3Sopenharmony_ci traceId_(traceId), 734514f5e3Sopenharmony_ci address_(address), 744514f5e3Sopenharmony_ci isLive_(isLive) 754514f5e3Sopenharmony_ci { 764514f5e3Sopenharmony_ci } 774514f5e3Sopenharmony_ci NodeId GetId() const 784514f5e3Sopenharmony_ci { 794514f5e3Sopenharmony_ci return id_; 804514f5e3Sopenharmony_ci } 814514f5e3Sopenharmony_ci void SetIndex(uint32_t index) 824514f5e3Sopenharmony_ci { 834514f5e3Sopenharmony_ci index_ = index; 844514f5e3Sopenharmony_ci } 854514f5e3Sopenharmony_ci uint32_t GetIndex() const 864514f5e3Sopenharmony_ci { 874514f5e3Sopenharmony_ci return index_; 884514f5e3Sopenharmony_ci } 894514f5e3Sopenharmony_ci 904514f5e3Sopenharmony_ci const CString *GetName() const 914514f5e3Sopenharmony_ci { 924514f5e3Sopenharmony_ci return name_; 934514f5e3Sopenharmony_ci } 944514f5e3Sopenharmony_ci 954514f5e3Sopenharmony_ci void SetName(CString *name) 964514f5e3Sopenharmony_ci { 974514f5e3Sopenharmony_ci name_ = name; 984514f5e3Sopenharmony_ci } 994514f5e3Sopenharmony_ci 1004514f5e3Sopenharmony_ci NodeType GetType() const 1014514f5e3Sopenharmony_ci { 1024514f5e3Sopenharmony_ci return type_; 1034514f5e3Sopenharmony_ci } 1044514f5e3Sopenharmony_ci size_t GetSelfSize() const 1054514f5e3Sopenharmony_ci { 1064514f5e3Sopenharmony_ci return size_; 1074514f5e3Sopenharmony_ci } 1084514f5e3Sopenharmony_ci void SetSelfSize(size_t size) 1094514f5e3Sopenharmony_ci { 1104514f5e3Sopenharmony_ci size_ = size; 1114514f5e3Sopenharmony_ci } 1124514f5e3Sopenharmony_ci size_t GetNativeSize() const 1134514f5e3Sopenharmony_ci { 1144514f5e3Sopenharmony_ci return nativeSize_; 1154514f5e3Sopenharmony_ci } 1164514f5e3Sopenharmony_ci void SetNativeSize(size_t size) 1174514f5e3Sopenharmony_ci { 1184514f5e3Sopenharmony_ci nativeSize_ = size; 1194514f5e3Sopenharmony_ci } 1204514f5e3Sopenharmony_ci size_t GetEdgeCount() const 1214514f5e3Sopenharmony_ci { 1224514f5e3Sopenharmony_ci return edgeCount_; 1234514f5e3Sopenharmony_ci } 1244514f5e3Sopenharmony_ci void IncEdgeCount() 1254514f5e3Sopenharmony_ci { 1264514f5e3Sopenharmony_ci edgeCount_++; 1274514f5e3Sopenharmony_ci } 1284514f5e3Sopenharmony_ci uint32_t GetStackTraceId() const 1294514f5e3Sopenharmony_ci { 1304514f5e3Sopenharmony_ci return traceId_; 1314514f5e3Sopenharmony_ci } 1324514f5e3Sopenharmony_ci JSTaggedType GetAddress() const 1334514f5e3Sopenharmony_ci { 1344514f5e3Sopenharmony_ci return address_; 1354514f5e3Sopenharmony_ci } 1364514f5e3Sopenharmony_ci void SetAddress(JSTaggedType address) 1374514f5e3Sopenharmony_ci { 1384514f5e3Sopenharmony_ci address_ = address; 1394514f5e3Sopenharmony_ci } 1404514f5e3Sopenharmony_ci bool IsLive() const 1414514f5e3Sopenharmony_ci { 1424514f5e3Sopenharmony_ci return isLive_; 1434514f5e3Sopenharmony_ci } 1444514f5e3Sopenharmony_ci void SetLive(bool isLive) 1454514f5e3Sopenharmony_ci { 1464514f5e3Sopenharmony_ci isLive_ = isLive; 1474514f5e3Sopenharmony_ci } 1484514f5e3Sopenharmony_ci void SetTraceId(uint32_t traceId) 1494514f5e3Sopenharmony_ci { 1504514f5e3Sopenharmony_ci traceId_ = traceId; 1514514f5e3Sopenharmony_ci } 1524514f5e3Sopenharmony_ci static Node *NewNode(Chunk *chunk, NodeId id, size_t index, const CString *name, NodeType type, size_t size, 1534514f5e3Sopenharmony_ci size_t nativeSize, JSTaggedType entry, bool isLive = true); 1544514f5e3Sopenharmony_ci template<typename T> 1554514f5e3Sopenharmony_ci static JSTaggedType NewAddress(T *addr) 1564514f5e3Sopenharmony_ci { 1574514f5e3Sopenharmony_ci return reinterpret_cast<JSTaggedType>(addr); 1584514f5e3Sopenharmony_ci } 1594514f5e3Sopenharmony_ci static constexpr int NODE_FIELD_COUNT = 8; 1604514f5e3Sopenharmony_ci ~Node() = default; 1614514f5e3Sopenharmony_ci 1624514f5e3Sopenharmony_ciprivate: 1634514f5e3Sopenharmony_ci NodeId id_ {0}; // Range from 1 1644514f5e3Sopenharmony_ci uint32_t index_ {0}; 1654514f5e3Sopenharmony_ci const CString *name_ {nullptr}; 1664514f5e3Sopenharmony_ci NodeType type_ {NodeType::DEFAULT}; 1674514f5e3Sopenharmony_ci size_t size_ {0}; 1684514f5e3Sopenharmony_ci size_t nativeSize_ {0}; 1694514f5e3Sopenharmony_ci size_t edgeCount_ {0}; 1704514f5e3Sopenharmony_ci uint32_t traceId_ {0}; 1714514f5e3Sopenharmony_ci JSTaggedType address_ {0}; 1724514f5e3Sopenharmony_ci bool isLive_ {true}; 1734514f5e3Sopenharmony_ci}; 1744514f5e3Sopenharmony_ci 1754514f5e3Sopenharmony_ciclass Edge { 1764514f5e3Sopenharmony_cipublic: 1774514f5e3Sopenharmony_ci Edge(EdgeType type, Node *from, Node *to, CString *name) 1784514f5e3Sopenharmony_ci : edgeType_(type), from_(from), to_(to), name_(name) {} 1794514f5e3Sopenharmony_ci Edge(EdgeType type, Node *from, Node *to, uint32_t index) 1804514f5e3Sopenharmony_ci : edgeType_(type), from_(from), to_(to), index_(index) {} 1814514f5e3Sopenharmony_ci EdgeType GetType() const 1824514f5e3Sopenharmony_ci { 1834514f5e3Sopenharmony_ci return edgeType_; 1844514f5e3Sopenharmony_ci } 1854514f5e3Sopenharmony_ci const Node *GetFrom() const 1864514f5e3Sopenharmony_ci { 1874514f5e3Sopenharmony_ci return from_; 1884514f5e3Sopenharmony_ci } 1894514f5e3Sopenharmony_ci const Node *GetTo() const 1904514f5e3Sopenharmony_ci { 1914514f5e3Sopenharmony_ci return to_; 1924514f5e3Sopenharmony_ci } 1934514f5e3Sopenharmony_ci const CString *GetName() const 1944514f5e3Sopenharmony_ci { 1954514f5e3Sopenharmony_ci ASSERT(GetType() != EdgeType::ELEMENT); 1964514f5e3Sopenharmony_ci return name_; 1974514f5e3Sopenharmony_ci } 1984514f5e3Sopenharmony_ci uint32_t GetIndex() const 1994514f5e3Sopenharmony_ci { 2004514f5e3Sopenharmony_ci ASSERT(GetType() == EdgeType::ELEMENT); 2014514f5e3Sopenharmony_ci return index_; 2024514f5e3Sopenharmony_ci } 2034514f5e3Sopenharmony_ci void SetName(CString *name) 2044514f5e3Sopenharmony_ci { 2054514f5e3Sopenharmony_ci ASSERT(GetType() != EdgeType::ELEMENT); 2064514f5e3Sopenharmony_ci name_ = name; 2074514f5e3Sopenharmony_ci } 2084514f5e3Sopenharmony_ci void UpdateFrom(Node *node) 2094514f5e3Sopenharmony_ci { 2104514f5e3Sopenharmony_ci from_ = node; 2114514f5e3Sopenharmony_ci } 2124514f5e3Sopenharmony_ci void UpdateTo(Node *node) 2134514f5e3Sopenharmony_ci { 2144514f5e3Sopenharmony_ci to_ = node; 2154514f5e3Sopenharmony_ci } 2164514f5e3Sopenharmony_ci static Edge *NewEdge(Chunk *chunk, EdgeType type, Node *from, Node *to, CString *name); 2174514f5e3Sopenharmony_ci static Edge *NewEdge(Chunk *chunk, EdgeType type, Node *from, Node *to, uint32_t index); 2184514f5e3Sopenharmony_ci static constexpr int EDGE_FIELD_COUNT = 3; 2194514f5e3Sopenharmony_ci ~Edge() = default; 2204514f5e3Sopenharmony_ci 2214514f5e3Sopenharmony_ciprivate: 2224514f5e3Sopenharmony_ci EdgeType edgeType_ {EdgeType::DEFAULT}; 2234514f5e3Sopenharmony_ci Node *from_ {nullptr}; 2244514f5e3Sopenharmony_ci Node *to_ {nullptr}; 2254514f5e3Sopenharmony_ci union { 2264514f5e3Sopenharmony_ci CString *name_; 2274514f5e3Sopenharmony_ci uint32_t index_; 2284514f5e3Sopenharmony_ci }; 2294514f5e3Sopenharmony_ci}; 2304514f5e3Sopenharmony_ci 2314514f5e3Sopenharmony_ciclass TimeStamp { 2324514f5e3Sopenharmony_cipublic: 2334514f5e3Sopenharmony_ci explicit TimeStamp(int sequenceId) : lastSequenceId_(sequenceId), timeStampUs_(TimeStamp::Now()) {} 2344514f5e3Sopenharmony_ci ~TimeStamp() = default; 2354514f5e3Sopenharmony_ci 2364514f5e3Sopenharmony_ci DEFAULT_MOVE_SEMANTIC(TimeStamp); 2374514f5e3Sopenharmony_ci DEFAULT_COPY_SEMANTIC(TimeStamp); 2384514f5e3Sopenharmony_ci 2394514f5e3Sopenharmony_ci int GetLastSequenceId() const 2404514f5e3Sopenharmony_ci { 2414514f5e3Sopenharmony_ci return lastSequenceId_; 2424514f5e3Sopenharmony_ci } 2434514f5e3Sopenharmony_ci 2444514f5e3Sopenharmony_ci int64_t GetTimeStamp() const 2454514f5e3Sopenharmony_ci { 2464514f5e3Sopenharmony_ci return timeStampUs_; 2474514f5e3Sopenharmony_ci } 2484514f5e3Sopenharmony_ci 2494514f5e3Sopenharmony_ci uint32_t GetSize() const 2504514f5e3Sopenharmony_ci { 2514514f5e3Sopenharmony_ci return size_; 2524514f5e3Sopenharmony_ci } 2534514f5e3Sopenharmony_ci 2544514f5e3Sopenharmony_ci void SetSize(uint32_t size) 2554514f5e3Sopenharmony_ci { 2564514f5e3Sopenharmony_ci size_ = size; 2574514f5e3Sopenharmony_ci } 2584514f5e3Sopenharmony_ci 2594514f5e3Sopenharmony_ci uint32_t GetCount() const 2604514f5e3Sopenharmony_ci { 2614514f5e3Sopenharmony_ci return count_; 2624514f5e3Sopenharmony_ci } 2634514f5e3Sopenharmony_ci 2644514f5e3Sopenharmony_ci void SetCount(uint32_t count) 2654514f5e3Sopenharmony_ci { 2664514f5e3Sopenharmony_ci count_ = count; 2674514f5e3Sopenharmony_ci } 2684514f5e3Sopenharmony_ci 2694514f5e3Sopenharmony_ciprivate: 2704514f5e3Sopenharmony_ci static int64_t Now() 2714514f5e3Sopenharmony_ci { 2724514f5e3Sopenharmony_ci struct timeval tv = {0, 0}; 2734514f5e3Sopenharmony_ci gettimeofday(&tv, nullptr); 2744514f5e3Sopenharmony_ci const int THOUSAND = 1000; 2754514f5e3Sopenharmony_ci return tv.tv_usec + tv.tv_sec * THOUSAND * THOUSAND; 2764514f5e3Sopenharmony_ci } 2774514f5e3Sopenharmony_ci 2784514f5e3Sopenharmony_ci int lastSequenceId_ {0}; 2794514f5e3Sopenharmony_ci int64_t timeStampUs_ {0}; 2804514f5e3Sopenharmony_ci uint32_t size_ {0}; 2814514f5e3Sopenharmony_ci uint32_t count_ {0}; 2824514f5e3Sopenharmony_ci}; 2834514f5e3Sopenharmony_ci 2844514f5e3Sopenharmony_ciclass HeapEntryMap { 2854514f5e3Sopenharmony_cipublic: 2864514f5e3Sopenharmony_ci HeapEntryMap() = default; 2874514f5e3Sopenharmony_ci ~HeapEntryMap() = default; 2884514f5e3Sopenharmony_ci NO_MOVE_SEMANTIC(HeapEntryMap); 2894514f5e3Sopenharmony_ci NO_COPY_SEMANTIC(HeapEntryMap); 2904514f5e3Sopenharmony_ci Node *FindOrInsertNode(Node *node); 2914514f5e3Sopenharmony_ci Node *FindAndEraseNode(JSTaggedType addr); 2924514f5e3Sopenharmony_ci Node *FindEntry(JSTaggedType addr); 2934514f5e3Sopenharmony_ci void InsertEntry(Node *node); 2944514f5e3Sopenharmony_ci 2954514f5e3Sopenharmony_ciprivate: 2964514f5e3Sopenharmony_ci CUnorderedMap<JSTaggedType, Node *> nodesMap_ {}; 2974514f5e3Sopenharmony_ci}; 2984514f5e3Sopenharmony_ci 2994514f5e3Sopenharmony_cistruct FunctionInfo { 3004514f5e3Sopenharmony_ci int functionId = 0; 3014514f5e3Sopenharmony_ci std::string functionName = ""; 3024514f5e3Sopenharmony_ci std::string scriptName = ""; 3034514f5e3Sopenharmony_ci int scriptId = 0; 3044514f5e3Sopenharmony_ci int columnNumber = 0; 3054514f5e3Sopenharmony_ci int lineNumber = 0; 3064514f5e3Sopenharmony_ci}; 3074514f5e3Sopenharmony_ci 3084514f5e3Sopenharmony_ciclass TraceTree; 3094514f5e3Sopenharmony_ciclass TraceNode { 3104514f5e3Sopenharmony_cipublic: 3114514f5e3Sopenharmony_ci TraceNode(TraceTree* tree, uint32_t nodeIndex); 3124514f5e3Sopenharmony_ci ~TraceNode(); 3134514f5e3Sopenharmony_ci 3144514f5e3Sopenharmony_ci TraceNode(const TraceNode&) = delete; 3154514f5e3Sopenharmony_ci TraceNode& operator=(const TraceNode&) = delete; 3164514f5e3Sopenharmony_ci TraceNode* FindChild(uint32_t nodeIndex); 3174514f5e3Sopenharmony_ci TraceNode* FindOrAddChild(uint32_t nodeIndex); 3184514f5e3Sopenharmony_ci uint32_t GetNodeIndex() const 3194514f5e3Sopenharmony_ci { 3204514f5e3Sopenharmony_ci return nodeIndex_; 3214514f5e3Sopenharmony_ci } 3224514f5e3Sopenharmony_ci uint32_t GetTotalSize() const 3234514f5e3Sopenharmony_ci { 3244514f5e3Sopenharmony_ci return totalSize_; 3254514f5e3Sopenharmony_ci } 3264514f5e3Sopenharmony_ci uint32_t GetTotalCount() const 3274514f5e3Sopenharmony_ci { 3284514f5e3Sopenharmony_ci return totalCount_; 3294514f5e3Sopenharmony_ci } 3304514f5e3Sopenharmony_ci uint32_t GetId() const 3314514f5e3Sopenharmony_ci { 3324514f5e3Sopenharmony_ci return id_; 3334514f5e3Sopenharmony_ci } 3344514f5e3Sopenharmony_ci const std::vector<TraceNode*>& GetChildren() const 3354514f5e3Sopenharmony_ci { 3364514f5e3Sopenharmony_ci return children_; 3374514f5e3Sopenharmony_ci } 3384514f5e3Sopenharmony_ci TraceNode &SetTotalSize(uint32_t totalSize) 3394514f5e3Sopenharmony_ci { 3404514f5e3Sopenharmony_ci totalSize_ = totalSize; 3414514f5e3Sopenharmony_ci return *this; 3424514f5e3Sopenharmony_ci } 3434514f5e3Sopenharmony_ci TraceNode &SetTotalCount(uint32_t totalCount) 3444514f5e3Sopenharmony_ci { 3454514f5e3Sopenharmony_ci totalCount_ = totalCount; 3464514f5e3Sopenharmony_ci return *this; 3474514f5e3Sopenharmony_ci } 3484514f5e3Sopenharmony_ci 3494514f5e3Sopenharmony_ciprivate: 3504514f5e3Sopenharmony_ci TraceTree* tree_ {nullptr}; 3514514f5e3Sopenharmony_ci uint32_t nodeIndex_ {0}; 3524514f5e3Sopenharmony_ci uint32_t totalSize_ {0}; 3534514f5e3Sopenharmony_ci uint32_t totalCount_ {0}; 3544514f5e3Sopenharmony_ci uint32_t id_ {0}; 3554514f5e3Sopenharmony_ci std::vector<TraceNode*> children_ {}; 3564514f5e3Sopenharmony_ci}; 3574514f5e3Sopenharmony_ci 3584514f5e3Sopenharmony_ciclass TraceTree { 3594514f5e3Sopenharmony_cipublic: 3604514f5e3Sopenharmony_ci TraceTree() : nextNodeId_(1), root_(this, 0) 3614514f5e3Sopenharmony_ci { 3624514f5e3Sopenharmony_ci } 3634514f5e3Sopenharmony_ci ~TraceTree() = default; 3644514f5e3Sopenharmony_ci TraceTree(const TraceTree&) = delete; 3654514f5e3Sopenharmony_ci TraceTree& operator=(const TraceTree&) = delete; 3664514f5e3Sopenharmony_ci TraceNode* AddNodeToTree(CVector<uint32_t> traceNodeIndex); 3674514f5e3Sopenharmony_ci TraceNode* GetRoot() 3684514f5e3Sopenharmony_ci { 3694514f5e3Sopenharmony_ci return &root_; 3704514f5e3Sopenharmony_ci } 3714514f5e3Sopenharmony_ci uint32_t GetNextNodeId() 3724514f5e3Sopenharmony_ci { 3734514f5e3Sopenharmony_ci return nextNodeId_++; 3744514f5e3Sopenharmony_ci } 3754514f5e3Sopenharmony_ci 3764514f5e3Sopenharmony_ciprivate: 3774514f5e3Sopenharmony_ci uint32_t nextNodeId_ {0}; 3784514f5e3Sopenharmony_ci TraceNode root_; 3794514f5e3Sopenharmony_ci}; 3804514f5e3Sopenharmony_ci 3814514f5e3Sopenharmony_cistruct Reference { 3824514f5e3Sopenharmony_ci enum class ReferenceType { CONTEXT, ELEMENT, PROPERTY, INTERNAL, HIDDEN, SHORTCUT, WEAK, DEFAULT = PROPERTY }; 3834514f5e3Sopenharmony_ci 3844514f5e3Sopenharmony_ci Reference(const CString &name, JSTaggedValue value) : name_(name), value_(value) {} 3854514f5e3Sopenharmony_ci Reference(const CString &name, JSTaggedValue value, ReferenceType type) : name_(name), value_(value), type_(type) {} 3864514f5e3Sopenharmony_ci Reference(uint32_t index, JSTaggedValue value, ReferenceType type) : index_(index), value_(value), type_(type) {} 3874514f5e3Sopenharmony_ci 3884514f5e3Sopenharmony_ci CString name_; 3894514f5e3Sopenharmony_ci uint32_t index_ {-1U}; 3904514f5e3Sopenharmony_ci JSTaggedValue value_; 3914514f5e3Sopenharmony_ci ReferenceType type_ {ReferenceType::DEFAULT}; 3924514f5e3Sopenharmony_ci}; 3934514f5e3Sopenharmony_ci 3944514f5e3Sopenharmony_ciclass EntryVisitor { 3954514f5e3Sopenharmony_cipublic: 3964514f5e3Sopenharmony_ci NO_MOVE_SEMANTIC(EntryVisitor); 3974514f5e3Sopenharmony_ci NO_COPY_SEMANTIC(EntryVisitor); 3984514f5e3Sopenharmony_ci EntryVisitor() = default; 3994514f5e3Sopenharmony_ci ~EntryVisitor() = default; 4004514f5e3Sopenharmony_ci static CString ConvertKey(JSTaggedValue key); 4014514f5e3Sopenharmony_ci}; 4024514f5e3Sopenharmony_ci 4034514f5e3Sopenharmony_ciclass HeapSnapshot { 4044514f5e3Sopenharmony_cipublic: 4054514f5e3Sopenharmony_ci static constexpr int SEQ_STEP = 2; 4064514f5e3Sopenharmony_ci NO_MOVE_SEMANTIC(HeapSnapshot); 4074514f5e3Sopenharmony_ci NO_COPY_SEMANTIC(HeapSnapshot); 4084514f5e3Sopenharmony_ci HeapSnapshot(const EcmaVM *vm, StringHashMap *stringTable, const DumpSnapShotOption &dumpOption, 4094514f5e3Sopenharmony_ci const bool trackAllocations, EntryIdMap *entryIdMap, Chunk *chunk) 4104514f5e3Sopenharmony_ci : vm_(vm), stringTable_(stringTable), isVmMode_(dumpOption.isVmMode), isPrivate_(dumpOption.isPrivate), 4114514f5e3Sopenharmony_ci captureNumericValue_(dumpOption.captureNumericValue), trackAllocations_(trackAllocations), 4124514f5e3Sopenharmony_ci entryIdMap_(entryIdMap), chunk_(chunk) {} 4134514f5e3Sopenharmony_ci ~HeapSnapshot(); 4144514f5e3Sopenharmony_ci bool BuildUp(bool isSimplify = false); 4154514f5e3Sopenharmony_ci bool Verify(); 4164514f5e3Sopenharmony_ci 4174514f5e3Sopenharmony_ci void PrepareSnapshot(); 4184514f5e3Sopenharmony_ci void UpdateNodes(bool isInFinish = false); 4194514f5e3Sopenharmony_ci Node *AddNode(TaggedObject *address, size_t size); 4204514f5e3Sopenharmony_ci void MoveNode(uintptr_t address, TaggedObject *forwardAddress, size_t size); 4214514f5e3Sopenharmony_ci void RecordSampleTime(); 4224514f5e3Sopenharmony_ci bool FinishSnapshot(); 4234514f5e3Sopenharmony_ci void PushHeapStat(Stream* stream); 4244514f5e3Sopenharmony_ci int AddTraceNode(int sequenceId, int size); 4254514f5e3Sopenharmony_ci bool AddMethodInfo(MethodLiteral *methodLiteral, 4264514f5e3Sopenharmony_ci const JSPandaFile *jsPandaFile, int sequenceId); 4274514f5e3Sopenharmony_ci void AddTraceNodeId(MethodLiteral *methodLiteral); 4284514f5e3Sopenharmony_ci 4294514f5e3Sopenharmony_ci const CVector<TimeStamp> &GetTimeStamps() const 4304514f5e3Sopenharmony_ci { 4314514f5e3Sopenharmony_ci return timeStamps_; 4324514f5e3Sopenharmony_ci } 4334514f5e3Sopenharmony_ci 4344514f5e3Sopenharmony_ci size_t GetNodeCount() const 4354514f5e3Sopenharmony_ci { 4364514f5e3Sopenharmony_ci return nodeCount_; 4374514f5e3Sopenharmony_ci } 4384514f5e3Sopenharmony_ci size_t GetEdgeCount() const 4394514f5e3Sopenharmony_ci { 4404514f5e3Sopenharmony_ci return edgeCount_; 4414514f5e3Sopenharmony_ci } 4424514f5e3Sopenharmony_ci size_t GetTotalNodeSize() const 4434514f5e3Sopenharmony_ci { 4444514f5e3Sopenharmony_ci return totalNodesSize_; 4454514f5e3Sopenharmony_ci } 4464514f5e3Sopenharmony_ci void AccumulateNodeSize(size_t size) 4474514f5e3Sopenharmony_ci { 4484514f5e3Sopenharmony_ci totalNodesSize_ += static_cast<int>(size); 4494514f5e3Sopenharmony_ci } 4504514f5e3Sopenharmony_ci void DecreaseNodeSize(size_t size) 4514514f5e3Sopenharmony_ci { 4524514f5e3Sopenharmony_ci totalNodesSize_ -= static_cast<int>(size); 4534514f5e3Sopenharmony_ci } 4544514f5e3Sopenharmony_ci CString *GenerateNodeName(TaggedObject *entry); 4554514f5e3Sopenharmony_ci NodeType GenerateNodeType(TaggedObject *entry); 4564514f5e3Sopenharmony_ci const CList<Node *> *GetNodes() const 4574514f5e3Sopenharmony_ci { 4584514f5e3Sopenharmony_ci return &nodes_; 4594514f5e3Sopenharmony_ci } 4604514f5e3Sopenharmony_ci const CList<Edge *> *GetEdges() const 4614514f5e3Sopenharmony_ci { 4624514f5e3Sopenharmony_ci return &edges_; 4634514f5e3Sopenharmony_ci } 4644514f5e3Sopenharmony_ci 4654514f5e3Sopenharmony_ci CString *GetString(const CString &as); 4664514f5e3Sopenharmony_ci CString *GetArrayString(TaggedArray *array, const CString &as); 4674514f5e3Sopenharmony_ci 4684514f5e3Sopenharmony_ci bool IsInVmMode() const 4694514f5e3Sopenharmony_ci { 4704514f5e3Sopenharmony_ci return isVmMode_; 4714514f5e3Sopenharmony_ci } 4724514f5e3Sopenharmony_ci 4734514f5e3Sopenharmony_ci bool IsPrivate() const 4744514f5e3Sopenharmony_ci { 4754514f5e3Sopenharmony_ci return isPrivate_; 4764514f5e3Sopenharmony_ci } 4774514f5e3Sopenharmony_ci 4784514f5e3Sopenharmony_ci bool trackAllocations() const 4794514f5e3Sopenharmony_ci { 4804514f5e3Sopenharmony_ci return trackAllocations_; 4814514f5e3Sopenharmony_ci } 4824514f5e3Sopenharmony_ci 4834514f5e3Sopenharmony_ci const CVector<FunctionInfo> &GetTrackAllocationsStack() const 4844514f5e3Sopenharmony_ci { 4854514f5e3Sopenharmony_ci return traceInfoStack_; 4864514f5e3Sopenharmony_ci } 4874514f5e3Sopenharmony_ci 4884514f5e3Sopenharmony_ci TraceTree* GetTraceTree() 4894514f5e3Sopenharmony_ci { 4904514f5e3Sopenharmony_ci return &traceTree_; 4914514f5e3Sopenharmony_ci } 4924514f5e3Sopenharmony_ci 4934514f5e3Sopenharmony_ci void PrepareTraceInfo() 4944514f5e3Sopenharmony_ci { 4954514f5e3Sopenharmony_ci struct FunctionInfo info; 4964514f5e3Sopenharmony_ci info.functionName = "(root)"; 4974514f5e3Sopenharmony_ci GetString(info.functionName.c_str()); 4984514f5e3Sopenharmony_ci traceInfoStack_.push_back(info); 4994514f5e3Sopenharmony_ci } 5004514f5e3Sopenharmony_ci const StringHashMap *GetEcmaStringTable() const 5014514f5e3Sopenharmony_ci { 5024514f5e3Sopenharmony_ci return stringTable_; 5034514f5e3Sopenharmony_ci } 5044514f5e3Sopenharmony_ci 5054514f5e3Sopenharmony_ci bool BuildSnapshotForBinMod(CVector<RawHeapObjInfo *> &objInfoVec); 5064514f5e3Sopenharmony_ci Node *GenerateNodeForBinMod(TaggedObject *obj, RawHeapObjInfo *objInfo, 5074514f5e3Sopenharmony_ci CUnorderedMap<uint64_t, const char *> &strTableIdMap); 5084514f5e3Sopenharmony_ci 5094514f5e3Sopenharmony_ci StringId GenerateStringId(TaggedObject *obj) 5104514f5e3Sopenharmony_ci { 5114514f5e3Sopenharmony_ci JSTaggedValue entry(obj); 5124514f5e3Sopenharmony_ci if (entry.IsOnlyJSObject()) { 5134514f5e3Sopenharmony_ci return stringTable_->InsertStrAndGetStringId(ParseObjectName(obj)); 5144514f5e3Sopenharmony_ci } 5154514f5e3Sopenharmony_ci if (entry.IsJSFunction()) { 5164514f5e3Sopenharmony_ci return stringTable_->InsertStrAndGetStringId(ParseFunctionName(obj)); 5174514f5e3Sopenharmony_ci } 5184514f5e3Sopenharmony_ci return 1; // 1 : invalid id 5194514f5e3Sopenharmony_ci } 5204514f5e3Sopenharmony_ci 5214514f5e3Sopenharmony_ciprivate: 5224514f5e3Sopenharmony_ci void FillNodes(bool isInFinish = false, bool isSimplify = false); 5234514f5e3Sopenharmony_ci Node *GenerateNode(JSTaggedValue entry, size_t size = 0, 5244514f5e3Sopenharmony_ci bool isInFinish = false, bool isSimplify = false, bool isBinMod = false); 5254514f5e3Sopenharmony_ci Node *HandleStringNode(JSTaggedValue &entry, size_t &size, bool &isInFinish, bool isBinMod); 5264514f5e3Sopenharmony_ci Node *HandleFunctionNode(JSTaggedValue &entry, size_t &size, bool &isInFinish); 5274514f5e3Sopenharmony_ci Node *HandleObjectNode(JSTaggedValue &entry, size_t &size, bool &isInFinish); 5284514f5e3Sopenharmony_ci Node *HandleBaseClassNode(size_t size, bool idExist, NodeId &sequenceId, 5294514f5e3Sopenharmony_ci TaggedObject* obj, JSTaggedType &addr); 5304514f5e3Sopenharmony_ci CString GeneratePrimitiveNameString(JSTaggedValue &entry); 5314514f5e3Sopenharmony_ci Node *GeneratePrivateStringNode(size_t size); 5324514f5e3Sopenharmony_ci Node *GenerateStringNode(JSTaggedValue entry, size_t size, bool isInFinish = false, bool isBinMod = false); 5334514f5e3Sopenharmony_ci Node *GenerateFunctionNode(JSTaggedValue entry, size_t size, bool isInFinish = false); 5344514f5e3Sopenharmony_ci Node *GenerateObjectNode(JSTaggedValue entry, size_t size, bool isInFinish = false); 5354514f5e3Sopenharmony_ci void FillEdges(bool isSimplify = false); 5364514f5e3Sopenharmony_ci void RenameFunction(const CString &edgeName, Node *entryFrom, Node *entryTo); 5374514f5e3Sopenharmony_ci CString ParseFunctionName(TaggedObject *obj); 5384514f5e3Sopenharmony_ci const CString ParseObjectName(TaggedObject *obj); 5394514f5e3Sopenharmony_ci 5404514f5e3Sopenharmony_ci Node *InsertNodeUnique(Node *node); 5414514f5e3Sopenharmony_ci void EraseNodeUnique(Node *node); 5424514f5e3Sopenharmony_ci Edge *InsertEdgeUnique(Edge *edge); 5434514f5e3Sopenharmony_ci void AddSyntheticRoot(); 5444514f5e3Sopenharmony_ci void FillEdgesForBinMod(RawHeapObjInfo *objInfo); 5454514f5e3Sopenharmony_ci void AddSyntheticRootForBinMod(RawHeapObjInfo *objInfoVec, int &edgeOffset, Node *syntheticRoot); 5464514f5e3Sopenharmony_ci Node *InsertNodeAt(size_t pos, Node *node); 5474514f5e3Sopenharmony_ci Edge *InsertEdgeAt(size_t pos, Edge *edge); 5484514f5e3Sopenharmony_ci 5494514f5e3Sopenharmony_ci CList<Node *> nodes_ {}; 5504514f5e3Sopenharmony_ci CList<Edge *> edges_ {}; 5514514f5e3Sopenharmony_ci CVector<TimeStamp> timeStamps_ {}; 5524514f5e3Sopenharmony_ci int nodeCount_ {0}; 5534514f5e3Sopenharmony_ci int edgeCount_ {0}; 5544514f5e3Sopenharmony_ci int totalNodesSize_ {0}; 5554514f5e3Sopenharmony_ci HeapEntryMap entryMap_; 5564514f5e3Sopenharmony_ci panda::ecmascript::HeapRootVisitor rootVisitor_; 5574514f5e3Sopenharmony_ci const EcmaVM *vm_; 5584514f5e3Sopenharmony_ci StringHashMap *stringTable_ {nullptr}; 5594514f5e3Sopenharmony_ci bool isVmMode_ {true}; 5604514f5e3Sopenharmony_ci bool isPrivate_ {false}; 5614514f5e3Sopenharmony_ci bool captureNumericValue_ {false}; 5624514f5e3Sopenharmony_ci Node* privateStringNode_ {nullptr}; 5634514f5e3Sopenharmony_ci bool trackAllocations_ {false}; 5644514f5e3Sopenharmony_ci CVector<FunctionInfo> traceInfoStack_ {}; 5654514f5e3Sopenharmony_ci CMap<MethodLiteral *, struct FunctionInfo> stackInfo_; 5664514f5e3Sopenharmony_ci CMap<std::string, int> scriptIdMap_; 5674514f5e3Sopenharmony_ci TraceTree traceTree_; 5684514f5e3Sopenharmony_ci CMap<MethodLiteral *, uint32_t> methodToTraceNodeId_; 5694514f5e3Sopenharmony_ci CVector<uint32_t> traceNodeIndex_; 5704514f5e3Sopenharmony_ci EntryIdMap* entryIdMap_; 5714514f5e3Sopenharmony_ci Chunk *chunk_ {nullptr}; 5724514f5e3Sopenharmony_ci}; 5734514f5e3Sopenharmony_ci 5744514f5e3Sopenharmony_ci} // namespace panda::ecmascript 5754514f5e3Sopenharmony_ci#endif // ECMASCRIPT_DFX_HPROF_HEAP_SNAPSHOT_H 576