11cb0ef41Sopenharmony_ci// Copyright 2013 the V8 project authors. All rights reserved. 21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be 31cb0ef41Sopenharmony_ci// found in the LICENSE file. 41cb0ef41Sopenharmony_ci 51cb0ef41Sopenharmony_ci#include "src/profiler/heap-snapshot-generator.h" 61cb0ef41Sopenharmony_ci 71cb0ef41Sopenharmony_ci#include <utility> 81cb0ef41Sopenharmony_ci 91cb0ef41Sopenharmony_ci#include "src/api/api-inl.h" 101cb0ef41Sopenharmony_ci#include "src/base/optional.h" 111cb0ef41Sopenharmony_ci#include "src/base/vector.h" 121cb0ef41Sopenharmony_ci#include "src/codegen/assembler-inl.h" 131cb0ef41Sopenharmony_ci#include "src/common/globals.h" 141cb0ef41Sopenharmony_ci#include "src/debug/debug.h" 151cb0ef41Sopenharmony_ci#include "src/handles/global-handles.h" 161cb0ef41Sopenharmony_ci#include "src/heap/combined-heap.h" 171cb0ef41Sopenharmony_ci#include "src/heap/safepoint.h" 181cb0ef41Sopenharmony_ci#include "src/numbers/conversions.h" 191cb0ef41Sopenharmony_ci#include "src/objects/allocation-site-inl.h" 201cb0ef41Sopenharmony_ci#include "src/objects/api-callbacks.h" 211cb0ef41Sopenharmony_ci#include "src/objects/cell-inl.h" 221cb0ef41Sopenharmony_ci#include "src/objects/feedback-cell-inl.h" 231cb0ef41Sopenharmony_ci#include "src/objects/hash-table-inl.h" 241cb0ef41Sopenharmony_ci#include "src/objects/js-array-buffer-inl.h" 251cb0ef41Sopenharmony_ci#include "src/objects/js-array-inl.h" 261cb0ef41Sopenharmony_ci#include "src/objects/js-collection-inl.h" 271cb0ef41Sopenharmony_ci#include "src/objects/js-generator-inl.h" 281cb0ef41Sopenharmony_ci#include "src/objects/js-promise-inl.h" 291cb0ef41Sopenharmony_ci#include "src/objects/js-regexp-inl.h" 301cb0ef41Sopenharmony_ci#include "src/objects/js-weak-refs-inl.h" 311cb0ef41Sopenharmony_ci#include "src/objects/literal-objects-inl.h" 321cb0ef41Sopenharmony_ci#include "src/objects/objects-inl.h" 331cb0ef41Sopenharmony_ci#include "src/objects/prototype.h" 341cb0ef41Sopenharmony_ci#include "src/objects/slots-inl.h" 351cb0ef41Sopenharmony_ci#include "src/objects/struct-inl.h" 361cb0ef41Sopenharmony_ci#include "src/objects/transitions-inl.h" 371cb0ef41Sopenharmony_ci#include "src/objects/visitors.h" 381cb0ef41Sopenharmony_ci#include "src/profiler/allocation-tracker.h" 391cb0ef41Sopenharmony_ci#include "src/profiler/heap-profiler.h" 401cb0ef41Sopenharmony_ci#include "src/profiler/heap-snapshot-generator-inl.h" 411cb0ef41Sopenharmony_ci#include "src/profiler/output-stream-writer.h" 421cb0ef41Sopenharmony_ci 431cb0ef41Sopenharmony_cinamespace v8 { 441cb0ef41Sopenharmony_cinamespace internal { 451cb0ef41Sopenharmony_ci 461cb0ef41Sopenharmony_ci#ifdef V8_ENABLE_HEAP_SNAPSHOT_VERIFY 471cb0ef41Sopenharmony_ciclass HeapEntryVerifier { 481cb0ef41Sopenharmony_ci public: 491cb0ef41Sopenharmony_ci HeapEntryVerifier(HeapSnapshotGenerator* generator, HeapObject obj) 501cb0ef41Sopenharmony_ci : generator_(generator), 511cb0ef41Sopenharmony_ci primary_object_(obj), 521cb0ef41Sopenharmony_ci reference_summary_( 531cb0ef41Sopenharmony_ci ReferenceSummary::SummarizeReferencesFrom(generator->heap(), obj)) { 541cb0ef41Sopenharmony_ci generator->set_verifier(this); 551cb0ef41Sopenharmony_ci } 561cb0ef41Sopenharmony_ci ~HeapEntryVerifier() { 571cb0ef41Sopenharmony_ci CheckAllReferencesWereChecked(); 581cb0ef41Sopenharmony_ci generator_->set_verifier(nullptr); 591cb0ef41Sopenharmony_ci } 601cb0ef41Sopenharmony_ci 611cb0ef41Sopenharmony_ci // Checks that `host` retains `target`, according to the marking visitor. This 621cb0ef41Sopenharmony_ci // allows us to verify, when adding edges to the snapshot, that they 631cb0ef41Sopenharmony_ci // correspond to real retaining relationships. 641cb0ef41Sopenharmony_ci void CheckStrongReference(HeapObject host, HeapObject target) { 651cb0ef41Sopenharmony_ci // All references should be from the current primary object. 661cb0ef41Sopenharmony_ci CHECK_EQ(host, primary_object_); 671cb0ef41Sopenharmony_ci 681cb0ef41Sopenharmony_ci checked_objects_.insert(target); 691cb0ef41Sopenharmony_ci 701cb0ef41Sopenharmony_ci // Check whether there is a direct strong reference from host to target. 711cb0ef41Sopenharmony_ci if (reference_summary_.strong_references().find(target) != 721cb0ef41Sopenharmony_ci reference_summary_.strong_references().end()) { 731cb0ef41Sopenharmony_ci return; 741cb0ef41Sopenharmony_ci } 751cb0ef41Sopenharmony_ci 761cb0ef41Sopenharmony_ci // There is no direct reference from host to target, but sometimes heap 771cb0ef41Sopenharmony_ci // snapshots include references that skip one, two, or three objects, such 781cb0ef41Sopenharmony_ci // as __proto__ on a JSObject referring to its Map's prototype, or a 791cb0ef41Sopenharmony_ci // property getter that bypasses the property array and accessor info. At 801cb0ef41Sopenharmony_ci // this point, we must check for those indirect references. 811cb0ef41Sopenharmony_ci for (size_t level = 0; level < 3; ++level) { 821cb0ef41Sopenharmony_ci const std::unordered_set<HeapObject, Object::Hasher>& indirect = 831cb0ef41Sopenharmony_ci GetIndirectStrongReferences(level); 841cb0ef41Sopenharmony_ci if (indirect.find(target) != indirect.end()) { 851cb0ef41Sopenharmony_ci return; 861cb0ef41Sopenharmony_ci } 871cb0ef41Sopenharmony_ci } 881cb0ef41Sopenharmony_ci 891cb0ef41Sopenharmony_ci FATAL("Could not find any matching reference"); 901cb0ef41Sopenharmony_ci } 911cb0ef41Sopenharmony_ci 921cb0ef41Sopenharmony_ci // Checks that `host` has a weak reference to `target`, according to the 931cb0ef41Sopenharmony_ci // marking visitor. 941cb0ef41Sopenharmony_ci void CheckWeakReference(HeapObject host, HeapObject target) { 951cb0ef41Sopenharmony_ci // All references should be from the current primary object. 961cb0ef41Sopenharmony_ci CHECK_EQ(host, primary_object_); 971cb0ef41Sopenharmony_ci 981cb0ef41Sopenharmony_ci checked_objects_.insert(target); 991cb0ef41Sopenharmony_ci CHECK_NE(reference_summary_.weak_references().find(target), 1001cb0ef41Sopenharmony_ci reference_summary_.weak_references().end()); 1011cb0ef41Sopenharmony_ci } 1021cb0ef41Sopenharmony_ci 1031cb0ef41Sopenharmony_ci // Marks the relationship between `host` and `target` as checked, even if the 1041cb0ef41Sopenharmony_ci // marking visitor found no such relationship. This is necessary for 1051cb0ef41Sopenharmony_ci // ephemerons, where a pair of objects is required to retain the target. 1061cb0ef41Sopenharmony_ci // Use this function with care, since it bypasses verification. 1071cb0ef41Sopenharmony_ci void MarkReferenceCheckedWithoutChecking(HeapObject host, HeapObject target) { 1081cb0ef41Sopenharmony_ci if (host == primary_object_) { 1091cb0ef41Sopenharmony_ci checked_objects_.insert(target); 1101cb0ef41Sopenharmony_ci } 1111cb0ef41Sopenharmony_ci } 1121cb0ef41Sopenharmony_ci 1131cb0ef41Sopenharmony_ci // Verifies that all of the references found by the marking visitor were 1141cb0ef41Sopenharmony_ci // checked via a call to CheckStrongReference or CheckWeakReference, or 1151cb0ef41Sopenharmony_ci // deliberately skipped via a call to MarkReferenceCheckedWithoutChecking. 1161cb0ef41Sopenharmony_ci // This ensures that there aren't retaining relationships found by the marking 1171cb0ef41Sopenharmony_ci // visitor which were omitted from the heap snapshot. 1181cb0ef41Sopenharmony_ci void CheckAllReferencesWereChecked() { 1191cb0ef41Sopenharmony_ci // Both loops below skip pointers to read-only objects, because the heap 1201cb0ef41Sopenharmony_ci // snapshot deliberately omits many of those (see IsEssentialObject). 1211cb0ef41Sopenharmony_ci // Read-only objects can't ever retain normal read-write objects, so these 1221cb0ef41Sopenharmony_ci // are fine to skip. 1231cb0ef41Sopenharmony_ci for (HeapObject obj : reference_summary_.strong_references()) { 1241cb0ef41Sopenharmony_ci if (!BasicMemoryChunk::FromHeapObject(obj)->InReadOnlySpace()) { 1251cb0ef41Sopenharmony_ci CHECK_NE(checked_objects_.find(obj), checked_objects_.end()); 1261cb0ef41Sopenharmony_ci } 1271cb0ef41Sopenharmony_ci } 1281cb0ef41Sopenharmony_ci for (HeapObject obj : reference_summary_.weak_references()) { 1291cb0ef41Sopenharmony_ci if (!BasicMemoryChunk::FromHeapObject(obj)->InReadOnlySpace()) { 1301cb0ef41Sopenharmony_ci CHECK_NE(checked_objects_.find(obj), checked_objects_.end()); 1311cb0ef41Sopenharmony_ci } 1321cb0ef41Sopenharmony_ci } 1331cb0ef41Sopenharmony_ci } 1341cb0ef41Sopenharmony_ci 1351cb0ef41Sopenharmony_ci private: 1361cb0ef41Sopenharmony_ci const std::unordered_set<HeapObject, Object::Hasher>& 1371cb0ef41Sopenharmony_ci GetIndirectStrongReferences(size_t level) { 1381cb0ef41Sopenharmony_ci CHECK_GE(indirect_strong_references_.size(), level); 1391cb0ef41Sopenharmony_ci 1401cb0ef41Sopenharmony_ci if (indirect_strong_references_.size() == level) { 1411cb0ef41Sopenharmony_ci // Expansion is needed. 1421cb0ef41Sopenharmony_ci indirect_strong_references_.resize(level + 1); 1431cb0ef41Sopenharmony_ci const std::unordered_set<HeapObject, Object::Hasher>& previous = 1441cb0ef41Sopenharmony_ci level == 0 ? reference_summary_.strong_references() 1451cb0ef41Sopenharmony_ci : indirect_strong_references_[level - 1]; 1461cb0ef41Sopenharmony_ci for (HeapObject obj : previous) { 1471cb0ef41Sopenharmony_ci if (BasicMemoryChunk::FromHeapObject(obj)->InReadOnlySpace()) { 1481cb0ef41Sopenharmony_ci // Marking visitors don't expect to visit objects in read-only space, 1491cb0ef41Sopenharmony_ci // and will fail DCHECKs if they are used on those objects. Read-only 1501cb0ef41Sopenharmony_ci // objects can never retain anything outside read-only space, so 1511cb0ef41Sopenharmony_ci // skipping those objects doesn't weaken verification. 1521cb0ef41Sopenharmony_ci continue; 1531cb0ef41Sopenharmony_ci } 1541cb0ef41Sopenharmony_ci 1551cb0ef41Sopenharmony_ci // Indirect references should only bypass internal structures, not 1561cb0ef41Sopenharmony_ci // user-visible objects or contexts. 1571cb0ef41Sopenharmony_ci if (obj.IsJSReceiver() || obj.IsString() || obj.IsContext()) { 1581cb0ef41Sopenharmony_ci continue; 1591cb0ef41Sopenharmony_ci } 1601cb0ef41Sopenharmony_ci 1611cb0ef41Sopenharmony_ci ReferenceSummary summary = 1621cb0ef41Sopenharmony_ci ReferenceSummary::SummarizeReferencesFrom(generator_->heap(), obj); 1631cb0ef41Sopenharmony_ci indirect_strong_references_[level].insert( 1641cb0ef41Sopenharmony_ci summary.strong_references().begin(), 1651cb0ef41Sopenharmony_ci summary.strong_references().end()); 1661cb0ef41Sopenharmony_ci } 1671cb0ef41Sopenharmony_ci } 1681cb0ef41Sopenharmony_ci 1691cb0ef41Sopenharmony_ci return indirect_strong_references_[level]; 1701cb0ef41Sopenharmony_ci } 1711cb0ef41Sopenharmony_ci 1721cb0ef41Sopenharmony_ci DISALLOW_GARBAGE_COLLECTION(no_gc) 1731cb0ef41Sopenharmony_ci HeapSnapshotGenerator* generator_; 1741cb0ef41Sopenharmony_ci HeapObject primary_object_; 1751cb0ef41Sopenharmony_ci 1761cb0ef41Sopenharmony_ci // All objects referred to by primary_object_, according to a marking visitor. 1771cb0ef41Sopenharmony_ci ReferenceSummary reference_summary_; 1781cb0ef41Sopenharmony_ci 1791cb0ef41Sopenharmony_ci // Objects that have been checked via a call to CheckStrongReference or 1801cb0ef41Sopenharmony_ci // CheckWeakReference, or deliberately skipped via a call to 1811cb0ef41Sopenharmony_ci // MarkReferenceCheckedWithoutChecking. 1821cb0ef41Sopenharmony_ci std::unordered_set<HeapObject, Object::Hasher> checked_objects_; 1831cb0ef41Sopenharmony_ci 1841cb0ef41Sopenharmony_ci // Objects transitively retained by the primary object. The objects in the set 1851cb0ef41Sopenharmony_ci // at index i are retained by the primary object via a chain of i+1 1861cb0ef41Sopenharmony_ci // intermediate objects. 1871cb0ef41Sopenharmony_ci std::vector<std::unordered_set<HeapObject, Object::Hasher>> 1881cb0ef41Sopenharmony_ci indirect_strong_references_; 1891cb0ef41Sopenharmony_ci}; 1901cb0ef41Sopenharmony_ci#endif 1911cb0ef41Sopenharmony_ci 1921cb0ef41Sopenharmony_ciHeapGraphEdge::HeapGraphEdge(Type type, const char* name, HeapEntry* from, 1931cb0ef41Sopenharmony_ci HeapEntry* to) 1941cb0ef41Sopenharmony_ci : bit_field_(TypeField::encode(type) | 1951cb0ef41Sopenharmony_ci FromIndexField::encode(from->index())), 1961cb0ef41Sopenharmony_ci to_entry_(to), 1971cb0ef41Sopenharmony_ci name_(name) { 1981cb0ef41Sopenharmony_ci DCHECK(type == kContextVariable 1991cb0ef41Sopenharmony_ci || type == kProperty 2001cb0ef41Sopenharmony_ci || type == kInternal 2011cb0ef41Sopenharmony_ci || type == kShortcut 2021cb0ef41Sopenharmony_ci || type == kWeak); 2031cb0ef41Sopenharmony_ci} 2041cb0ef41Sopenharmony_ci 2051cb0ef41Sopenharmony_ciHeapGraphEdge::HeapGraphEdge(Type type, int index, HeapEntry* from, 2061cb0ef41Sopenharmony_ci HeapEntry* to) 2071cb0ef41Sopenharmony_ci : bit_field_(TypeField::encode(type) | 2081cb0ef41Sopenharmony_ci FromIndexField::encode(from->index())), 2091cb0ef41Sopenharmony_ci to_entry_(to), 2101cb0ef41Sopenharmony_ci index_(index) { 2111cb0ef41Sopenharmony_ci DCHECK(type == kElement || type == kHidden); 2121cb0ef41Sopenharmony_ci} 2131cb0ef41Sopenharmony_ci 2141cb0ef41Sopenharmony_ciHeapEntry::HeapEntry(HeapSnapshot* snapshot, int index, Type type, 2151cb0ef41Sopenharmony_ci const char* name, SnapshotObjectId id, size_t self_size, 2161cb0ef41Sopenharmony_ci unsigned trace_node_id) 2171cb0ef41Sopenharmony_ci : type_(type), 2181cb0ef41Sopenharmony_ci index_(index), 2191cb0ef41Sopenharmony_ci children_count_(0), 2201cb0ef41Sopenharmony_ci self_size_(self_size), 2211cb0ef41Sopenharmony_ci snapshot_(snapshot), 2221cb0ef41Sopenharmony_ci name_(name), 2231cb0ef41Sopenharmony_ci id_(id), 2241cb0ef41Sopenharmony_ci trace_node_id_(trace_node_id) { 2251cb0ef41Sopenharmony_ci DCHECK_GE(index, 0); 2261cb0ef41Sopenharmony_ci} 2271cb0ef41Sopenharmony_ci 2281cb0ef41Sopenharmony_civoid HeapEntry::VerifyReference(HeapGraphEdge::Type type, HeapEntry* entry, 2291cb0ef41Sopenharmony_ci HeapSnapshotGenerator* generator, 2301cb0ef41Sopenharmony_ci ReferenceVerification verification) { 2311cb0ef41Sopenharmony_ci#ifdef V8_ENABLE_HEAP_SNAPSHOT_VERIFY 2321cb0ef41Sopenharmony_ci if (verification == kOffHeapPointer || generator->verifier() == nullptr) { 2331cb0ef41Sopenharmony_ci // Off-heap pointers are outside the scope of this verification; we just 2341cb0ef41Sopenharmony_ci // trust the embedder to provide accurate data. If the verifier is null, 2351cb0ef41Sopenharmony_ci // then verification is disabled. 2361cb0ef41Sopenharmony_ci return; 2371cb0ef41Sopenharmony_ci } 2381cb0ef41Sopenharmony_ci if (verification == kCustomWeakPointer) { 2391cb0ef41Sopenharmony_ci // The caller declared that this is a weak pointer ignored by the marking 2401cb0ef41Sopenharmony_ci // visitor. All we can verify at this point is that the edge type declares 2411cb0ef41Sopenharmony_ci // it to be weak. 2421cb0ef41Sopenharmony_ci CHECK_EQ(type, HeapGraphEdge::kWeak); 2431cb0ef41Sopenharmony_ci return; 2441cb0ef41Sopenharmony_ci } 2451cb0ef41Sopenharmony_ci Address from_address = 2461cb0ef41Sopenharmony_ci reinterpret_cast<Address>(generator->FindHeapThingForHeapEntry(this)); 2471cb0ef41Sopenharmony_ci Address to_address = 2481cb0ef41Sopenharmony_ci reinterpret_cast<Address>(generator->FindHeapThingForHeapEntry(entry)); 2491cb0ef41Sopenharmony_ci if (from_address == kNullAddress || to_address == kNullAddress) { 2501cb0ef41Sopenharmony_ci // One of these entries doesn't correspond to a real heap object. 2511cb0ef41Sopenharmony_ci // Verification is not possible. 2521cb0ef41Sopenharmony_ci return; 2531cb0ef41Sopenharmony_ci } 2541cb0ef41Sopenharmony_ci HeapObject from_obj = HeapObject::cast(Object(from_address)); 2551cb0ef41Sopenharmony_ci HeapObject to_obj = HeapObject::cast(Object(to_address)); 2561cb0ef41Sopenharmony_ci if (BasicMemoryChunk::FromHeapObject(to_obj)->InReadOnlySpace()) { 2571cb0ef41Sopenharmony_ci // We can't verify pointers into read-only space, because marking visitors 2581cb0ef41Sopenharmony_ci // might not mark those. For example, every Map has a pointer to the 2591cb0ef41Sopenharmony_ci // MetaMap, but marking visitors don't bother with following that link. 2601cb0ef41Sopenharmony_ci // Read-only objects are immortal and can never point to things outside of 2611cb0ef41Sopenharmony_ci // read-only space, so ignoring these objects is safe from the perspective 2621cb0ef41Sopenharmony_ci // of ensuring accurate retaining paths for normal read-write objects. 2631cb0ef41Sopenharmony_ci // Therefore, do nothing. 2641cb0ef41Sopenharmony_ci } else if (verification == kEphemeron) { 2651cb0ef41Sopenharmony_ci // Ephemerons can't be verified because they aren't marked directly by the 2661cb0ef41Sopenharmony_ci // marking visitor. 2671cb0ef41Sopenharmony_ci generator->verifier()->MarkReferenceCheckedWithoutChecking(from_obj, 2681cb0ef41Sopenharmony_ci to_obj); 2691cb0ef41Sopenharmony_ci } else if (type == HeapGraphEdge::kWeak) { 2701cb0ef41Sopenharmony_ci generator->verifier()->CheckWeakReference(from_obj, to_obj); 2711cb0ef41Sopenharmony_ci } else { 2721cb0ef41Sopenharmony_ci generator->verifier()->CheckStrongReference(from_obj, to_obj); 2731cb0ef41Sopenharmony_ci } 2741cb0ef41Sopenharmony_ci#endif 2751cb0ef41Sopenharmony_ci} 2761cb0ef41Sopenharmony_ci 2771cb0ef41Sopenharmony_civoid HeapEntry::SetNamedReference(HeapGraphEdge::Type type, const char* name, 2781cb0ef41Sopenharmony_ci HeapEntry* entry, 2791cb0ef41Sopenharmony_ci HeapSnapshotGenerator* generator, 2801cb0ef41Sopenharmony_ci ReferenceVerification verification) { 2811cb0ef41Sopenharmony_ci ++children_count_; 2821cb0ef41Sopenharmony_ci snapshot_->edges().emplace_back(type, name, this, entry); 2831cb0ef41Sopenharmony_ci VerifyReference(type, entry, generator, verification); 2841cb0ef41Sopenharmony_ci} 2851cb0ef41Sopenharmony_ci 2861cb0ef41Sopenharmony_civoid HeapEntry::SetIndexedReference(HeapGraphEdge::Type type, int index, 2871cb0ef41Sopenharmony_ci HeapEntry* entry, 2881cb0ef41Sopenharmony_ci HeapSnapshotGenerator* generator, 2891cb0ef41Sopenharmony_ci ReferenceVerification verification) { 2901cb0ef41Sopenharmony_ci ++children_count_; 2911cb0ef41Sopenharmony_ci snapshot_->edges().emplace_back(type, index, this, entry); 2921cb0ef41Sopenharmony_ci VerifyReference(type, entry, generator, verification); 2931cb0ef41Sopenharmony_ci} 2941cb0ef41Sopenharmony_ci 2951cb0ef41Sopenharmony_civoid HeapEntry::SetNamedAutoIndexReference(HeapGraphEdge::Type type, 2961cb0ef41Sopenharmony_ci const char* description, 2971cb0ef41Sopenharmony_ci HeapEntry* child, 2981cb0ef41Sopenharmony_ci StringsStorage* names, 2991cb0ef41Sopenharmony_ci HeapSnapshotGenerator* generator, 3001cb0ef41Sopenharmony_ci ReferenceVerification verification) { 3011cb0ef41Sopenharmony_ci int index = children_count_ + 1; 3021cb0ef41Sopenharmony_ci const char* name = description 3031cb0ef41Sopenharmony_ci ? names->GetFormatted("%d / %s", index, description) 3041cb0ef41Sopenharmony_ci : names->GetName(index); 3051cb0ef41Sopenharmony_ci SetNamedReference(type, name, child, generator, verification); 3061cb0ef41Sopenharmony_ci} 3071cb0ef41Sopenharmony_ci 3081cb0ef41Sopenharmony_civoid HeapEntry::Print(const char* prefix, const char* edge_name, int max_depth, 3091cb0ef41Sopenharmony_ci int indent) const { 3101cb0ef41Sopenharmony_ci STATIC_ASSERT(sizeof(unsigned) == sizeof(id())); 3111cb0ef41Sopenharmony_ci base::OS::Print("%6zu @%6u %*c %s%s: ", self_size(), id(), indent, ' ', 3121cb0ef41Sopenharmony_ci prefix, edge_name); 3131cb0ef41Sopenharmony_ci if (type() != kString) { 3141cb0ef41Sopenharmony_ci base::OS::Print("%s %.40s\n", TypeAsString(), name_); 3151cb0ef41Sopenharmony_ci } else { 3161cb0ef41Sopenharmony_ci base::OS::Print("\""); 3171cb0ef41Sopenharmony_ci const char* c = name_; 3181cb0ef41Sopenharmony_ci while (*c && (c - name_) <= 40) { 3191cb0ef41Sopenharmony_ci if (*c != '\n') 3201cb0ef41Sopenharmony_ci base::OS::Print("%c", *c); 3211cb0ef41Sopenharmony_ci else 3221cb0ef41Sopenharmony_ci base::OS::Print("\\n"); 3231cb0ef41Sopenharmony_ci ++c; 3241cb0ef41Sopenharmony_ci } 3251cb0ef41Sopenharmony_ci base::OS::Print("\"\n"); 3261cb0ef41Sopenharmony_ci } 3271cb0ef41Sopenharmony_ci if (--max_depth == 0) return; 3281cb0ef41Sopenharmony_ci for (auto i = children_begin(); i != children_end(); ++i) { 3291cb0ef41Sopenharmony_ci HeapGraphEdge& edge = **i; 3301cb0ef41Sopenharmony_ci const char* edge_prefix = ""; 3311cb0ef41Sopenharmony_ci base::EmbeddedVector<char, 64> index; 3321cb0ef41Sopenharmony_ci edge_name = index.begin(); 3331cb0ef41Sopenharmony_ci switch (edge.type()) { 3341cb0ef41Sopenharmony_ci case HeapGraphEdge::kContextVariable: 3351cb0ef41Sopenharmony_ci edge_prefix = "#"; 3361cb0ef41Sopenharmony_ci edge_name = edge.name(); 3371cb0ef41Sopenharmony_ci break; 3381cb0ef41Sopenharmony_ci case HeapGraphEdge::kElement: 3391cb0ef41Sopenharmony_ci SNPrintF(index, "%d", edge.index()); 3401cb0ef41Sopenharmony_ci break; 3411cb0ef41Sopenharmony_ci case HeapGraphEdge::kInternal: 3421cb0ef41Sopenharmony_ci edge_prefix = "$"; 3431cb0ef41Sopenharmony_ci edge_name = edge.name(); 3441cb0ef41Sopenharmony_ci break; 3451cb0ef41Sopenharmony_ci case HeapGraphEdge::kProperty: 3461cb0ef41Sopenharmony_ci edge_name = edge.name(); 3471cb0ef41Sopenharmony_ci break; 3481cb0ef41Sopenharmony_ci case HeapGraphEdge::kHidden: 3491cb0ef41Sopenharmony_ci edge_prefix = "$"; 3501cb0ef41Sopenharmony_ci SNPrintF(index, "%d", edge.index()); 3511cb0ef41Sopenharmony_ci break; 3521cb0ef41Sopenharmony_ci case HeapGraphEdge::kShortcut: 3531cb0ef41Sopenharmony_ci edge_prefix = "^"; 3541cb0ef41Sopenharmony_ci edge_name = edge.name(); 3551cb0ef41Sopenharmony_ci break; 3561cb0ef41Sopenharmony_ci case HeapGraphEdge::kWeak: 3571cb0ef41Sopenharmony_ci edge_prefix = "w"; 3581cb0ef41Sopenharmony_ci edge_name = edge.name(); 3591cb0ef41Sopenharmony_ci break; 3601cb0ef41Sopenharmony_ci default: 3611cb0ef41Sopenharmony_ci SNPrintF(index, "!!! unknown edge type: %d ", edge.type()); 3621cb0ef41Sopenharmony_ci } 3631cb0ef41Sopenharmony_ci edge.to()->Print(edge_prefix, edge_name, max_depth, indent + 2); 3641cb0ef41Sopenharmony_ci } 3651cb0ef41Sopenharmony_ci} 3661cb0ef41Sopenharmony_ci 3671cb0ef41Sopenharmony_ciconst char* HeapEntry::TypeAsString() const { 3681cb0ef41Sopenharmony_ci switch (type()) { 3691cb0ef41Sopenharmony_ci case kHidden: return "/hidden/"; 3701cb0ef41Sopenharmony_ci case kObject: return "/object/"; 3711cb0ef41Sopenharmony_ci case kClosure: return "/closure/"; 3721cb0ef41Sopenharmony_ci case kString: return "/string/"; 3731cb0ef41Sopenharmony_ci case kCode: return "/code/"; 3741cb0ef41Sopenharmony_ci case kArray: return "/array/"; 3751cb0ef41Sopenharmony_ci case kRegExp: return "/regexp/"; 3761cb0ef41Sopenharmony_ci case kHeapNumber: return "/number/"; 3771cb0ef41Sopenharmony_ci case kNative: return "/native/"; 3781cb0ef41Sopenharmony_ci case kSynthetic: return "/synthetic/"; 3791cb0ef41Sopenharmony_ci case kConsString: return "/concatenated string/"; 3801cb0ef41Sopenharmony_ci case kSlicedString: return "/sliced string/"; 3811cb0ef41Sopenharmony_ci case kSymbol: return "/symbol/"; 3821cb0ef41Sopenharmony_ci case kBigInt: 3831cb0ef41Sopenharmony_ci return "/bigint/"; 3841cb0ef41Sopenharmony_ci default: return "???"; 3851cb0ef41Sopenharmony_ci } 3861cb0ef41Sopenharmony_ci} 3871cb0ef41Sopenharmony_ci 3881cb0ef41Sopenharmony_ciHeapSnapshot::HeapSnapshot(HeapProfiler* profiler, bool global_objects_as_roots, 3891cb0ef41Sopenharmony_ci bool capture_numeric_value) 3901cb0ef41Sopenharmony_ci : profiler_(profiler), 3911cb0ef41Sopenharmony_ci treat_global_objects_as_roots_(global_objects_as_roots), 3921cb0ef41Sopenharmony_ci capture_numeric_value_(capture_numeric_value) { 3931cb0ef41Sopenharmony_ci // It is very important to keep objects that form a heap snapshot 3941cb0ef41Sopenharmony_ci // as small as possible. Check assumptions about data structure sizes. 3951cb0ef41Sopenharmony_ci STATIC_ASSERT(kSystemPointerSize != 4 || sizeof(HeapGraphEdge) == 12); 3961cb0ef41Sopenharmony_ci STATIC_ASSERT(kSystemPointerSize != 8 || sizeof(HeapGraphEdge) == 24); 3971cb0ef41Sopenharmony_ci STATIC_ASSERT(kSystemPointerSize != 4 || sizeof(HeapEntry) == 32); 3981cb0ef41Sopenharmony_ci#if V8_CC_MSVC 3991cb0ef41Sopenharmony_ci STATIC_ASSERT(kSystemPointerSize != 8 || sizeof(HeapEntry) == 48); 4001cb0ef41Sopenharmony_ci#else // !V8_CC_MSVC 4011cb0ef41Sopenharmony_ci STATIC_ASSERT(kSystemPointerSize != 8 || sizeof(HeapEntry) == 40); 4021cb0ef41Sopenharmony_ci#endif // !V8_CC_MSVC 4031cb0ef41Sopenharmony_ci memset(&gc_subroot_entries_, 0, sizeof(gc_subroot_entries_)); 4041cb0ef41Sopenharmony_ci} 4051cb0ef41Sopenharmony_ci 4061cb0ef41Sopenharmony_civoid HeapSnapshot::Delete() { 4071cb0ef41Sopenharmony_ci profiler_->RemoveSnapshot(this); 4081cb0ef41Sopenharmony_ci} 4091cb0ef41Sopenharmony_ci 4101cb0ef41Sopenharmony_civoid HeapSnapshot::RememberLastJSObjectId() { 4111cb0ef41Sopenharmony_ci max_snapshot_js_object_id_ = profiler_->heap_object_map()->last_assigned_id(); 4121cb0ef41Sopenharmony_ci} 4131cb0ef41Sopenharmony_ci 4141cb0ef41Sopenharmony_civoid HeapSnapshot::AddSyntheticRootEntries() { 4151cb0ef41Sopenharmony_ci AddRootEntry(); 4161cb0ef41Sopenharmony_ci AddGcRootsEntry(); 4171cb0ef41Sopenharmony_ci SnapshotObjectId id = HeapObjectsMap::kGcRootsFirstSubrootId; 4181cb0ef41Sopenharmony_ci for (int root = 0; root < static_cast<int>(Root::kNumberOfRoots); root++) { 4191cb0ef41Sopenharmony_ci AddGcSubrootEntry(static_cast<Root>(root), id); 4201cb0ef41Sopenharmony_ci id += HeapObjectsMap::kObjectIdStep; 4211cb0ef41Sopenharmony_ci } 4221cb0ef41Sopenharmony_ci DCHECK_EQ(HeapObjectsMap::kFirstAvailableObjectId, id); 4231cb0ef41Sopenharmony_ci} 4241cb0ef41Sopenharmony_ci 4251cb0ef41Sopenharmony_civoid HeapSnapshot::AddRootEntry() { 4261cb0ef41Sopenharmony_ci DCHECK_NULL(root_entry_); 4271cb0ef41Sopenharmony_ci DCHECK(entries_.empty()); // Root entry must be the first one. 4281cb0ef41Sopenharmony_ci root_entry_ = AddEntry(HeapEntry::kSynthetic, "", 4291cb0ef41Sopenharmony_ci HeapObjectsMap::kInternalRootObjectId, 0, 0); 4301cb0ef41Sopenharmony_ci DCHECK_EQ(1u, entries_.size()); 4311cb0ef41Sopenharmony_ci DCHECK_EQ(root_entry_, &entries_.front()); 4321cb0ef41Sopenharmony_ci} 4331cb0ef41Sopenharmony_ci 4341cb0ef41Sopenharmony_civoid HeapSnapshot::AddGcRootsEntry() { 4351cb0ef41Sopenharmony_ci DCHECK_NULL(gc_roots_entry_); 4361cb0ef41Sopenharmony_ci gc_roots_entry_ = AddEntry(HeapEntry::kSynthetic, "(GC roots)", 4371cb0ef41Sopenharmony_ci HeapObjectsMap::kGcRootsObjectId, 0, 0); 4381cb0ef41Sopenharmony_ci} 4391cb0ef41Sopenharmony_ci 4401cb0ef41Sopenharmony_civoid HeapSnapshot::AddGcSubrootEntry(Root root, SnapshotObjectId id) { 4411cb0ef41Sopenharmony_ci DCHECK_NULL(gc_subroot_entries_[static_cast<int>(root)]); 4421cb0ef41Sopenharmony_ci gc_subroot_entries_[static_cast<int>(root)] = 4431cb0ef41Sopenharmony_ci AddEntry(HeapEntry::kSynthetic, RootVisitor::RootName(root), id, 0, 0); 4441cb0ef41Sopenharmony_ci} 4451cb0ef41Sopenharmony_ci 4461cb0ef41Sopenharmony_civoid HeapSnapshot::AddLocation(HeapEntry* entry, int scriptId, int line, 4471cb0ef41Sopenharmony_ci int col) { 4481cb0ef41Sopenharmony_ci locations_.emplace_back(entry->index(), scriptId, line, col); 4491cb0ef41Sopenharmony_ci} 4501cb0ef41Sopenharmony_ci 4511cb0ef41Sopenharmony_ciHeapEntry* HeapSnapshot::AddEntry(HeapEntry::Type type, 4521cb0ef41Sopenharmony_ci const char* name, 4531cb0ef41Sopenharmony_ci SnapshotObjectId id, 4541cb0ef41Sopenharmony_ci size_t size, 4551cb0ef41Sopenharmony_ci unsigned trace_node_id) { 4561cb0ef41Sopenharmony_ci DCHECK(!is_complete()); 4571cb0ef41Sopenharmony_ci entries_.emplace_back(this, static_cast<int>(entries_.size()), type, name, id, 4581cb0ef41Sopenharmony_ci size, trace_node_id); 4591cb0ef41Sopenharmony_ci return &entries_.back(); 4601cb0ef41Sopenharmony_ci} 4611cb0ef41Sopenharmony_ci 4621cb0ef41Sopenharmony_civoid HeapSnapshot::FillChildren() { 4631cb0ef41Sopenharmony_ci DCHECK(children().empty()); 4641cb0ef41Sopenharmony_ci int children_index = 0; 4651cb0ef41Sopenharmony_ci for (HeapEntry& entry : entries()) { 4661cb0ef41Sopenharmony_ci children_index = entry.set_children_index(children_index); 4671cb0ef41Sopenharmony_ci } 4681cb0ef41Sopenharmony_ci DCHECK_EQ(edges().size(), static_cast<size_t>(children_index)); 4691cb0ef41Sopenharmony_ci children().resize(edges().size()); 4701cb0ef41Sopenharmony_ci for (HeapGraphEdge& edge : edges()) { 4711cb0ef41Sopenharmony_ci edge.from()->add_child(&edge); 4721cb0ef41Sopenharmony_ci } 4731cb0ef41Sopenharmony_ci} 4741cb0ef41Sopenharmony_ci 4751cb0ef41Sopenharmony_ciHeapEntry* HeapSnapshot::GetEntryById(SnapshotObjectId id) { 4761cb0ef41Sopenharmony_ci if (entries_by_id_cache_.empty()) { 4771cb0ef41Sopenharmony_ci CHECK(is_complete()); 4781cb0ef41Sopenharmony_ci entries_by_id_cache_.reserve(entries_.size()); 4791cb0ef41Sopenharmony_ci for (HeapEntry& entry : entries_) { 4801cb0ef41Sopenharmony_ci entries_by_id_cache_.emplace(entry.id(), &entry); 4811cb0ef41Sopenharmony_ci } 4821cb0ef41Sopenharmony_ci } 4831cb0ef41Sopenharmony_ci auto it = entries_by_id_cache_.find(id); 4841cb0ef41Sopenharmony_ci return it != entries_by_id_cache_.end() ? it->second : nullptr; 4851cb0ef41Sopenharmony_ci} 4861cb0ef41Sopenharmony_ci 4871cb0ef41Sopenharmony_civoid HeapSnapshot::Print(int max_depth) { 4881cb0ef41Sopenharmony_ci root()->Print("", "", max_depth, 0); 4891cb0ef41Sopenharmony_ci} 4901cb0ef41Sopenharmony_ci 4911cb0ef41Sopenharmony_ci// We split IDs on evens for embedder objects (see 4921cb0ef41Sopenharmony_ci// HeapObjectsMap::GenerateId) and odds for native objects. 4931cb0ef41Sopenharmony_ciconst SnapshotObjectId HeapObjectsMap::kInternalRootObjectId = 1; 4941cb0ef41Sopenharmony_ciconst SnapshotObjectId HeapObjectsMap::kGcRootsObjectId = 4951cb0ef41Sopenharmony_ci HeapObjectsMap::kInternalRootObjectId + HeapObjectsMap::kObjectIdStep; 4961cb0ef41Sopenharmony_ciconst SnapshotObjectId HeapObjectsMap::kGcRootsFirstSubrootId = 4971cb0ef41Sopenharmony_ci HeapObjectsMap::kGcRootsObjectId + HeapObjectsMap::kObjectIdStep; 4981cb0ef41Sopenharmony_ciconst SnapshotObjectId HeapObjectsMap::kFirstAvailableObjectId = 4991cb0ef41Sopenharmony_ci HeapObjectsMap::kGcRootsFirstSubrootId + 5001cb0ef41Sopenharmony_ci static_cast<int>(Root::kNumberOfRoots) * HeapObjectsMap::kObjectIdStep; 5011cb0ef41Sopenharmony_ci 5021cb0ef41Sopenharmony_ciHeapObjectsMap::HeapObjectsMap(Heap* heap) 5031cb0ef41Sopenharmony_ci : next_id_(kFirstAvailableObjectId), heap_(heap) { 5041cb0ef41Sopenharmony_ci // The dummy element at zero index is needed as entries_map_ cannot hold 5051cb0ef41Sopenharmony_ci // an entry with zero value. Otherwise it's impossible to tell if 5061cb0ef41Sopenharmony_ci // LookupOrInsert has added a new item or just returning exisiting one 5071cb0ef41Sopenharmony_ci // having the value of zero. 5081cb0ef41Sopenharmony_ci entries_.emplace_back(0, kNullAddress, 0, true); 5091cb0ef41Sopenharmony_ci} 5101cb0ef41Sopenharmony_ci 5111cb0ef41Sopenharmony_cibool HeapObjectsMap::MoveObject(Address from, Address to, int object_size) { 5121cb0ef41Sopenharmony_ci DCHECK_NE(kNullAddress, to); 5131cb0ef41Sopenharmony_ci DCHECK_NE(kNullAddress, from); 5141cb0ef41Sopenharmony_ci if (from == to) return false; 5151cb0ef41Sopenharmony_ci void* from_value = entries_map_.Remove(reinterpret_cast<void*>(from), 5161cb0ef41Sopenharmony_ci ComputeAddressHash(from)); 5171cb0ef41Sopenharmony_ci if (from_value == nullptr) { 5181cb0ef41Sopenharmony_ci // It may occur that some untracked object moves to an address X and there 5191cb0ef41Sopenharmony_ci // is a tracked object at that address. In this case we should remove the 5201cb0ef41Sopenharmony_ci // entry as we know that the object has died. 5211cb0ef41Sopenharmony_ci void* to_value = entries_map_.Remove(reinterpret_cast<void*>(to), 5221cb0ef41Sopenharmony_ci ComputeAddressHash(to)); 5231cb0ef41Sopenharmony_ci if (to_value != nullptr) { 5241cb0ef41Sopenharmony_ci int to_entry_info_index = 5251cb0ef41Sopenharmony_ci static_cast<int>(reinterpret_cast<intptr_t>(to_value)); 5261cb0ef41Sopenharmony_ci entries_.at(to_entry_info_index).addr = kNullAddress; 5271cb0ef41Sopenharmony_ci } 5281cb0ef41Sopenharmony_ci } else { 5291cb0ef41Sopenharmony_ci base::HashMap::Entry* to_entry = entries_map_.LookupOrInsert( 5301cb0ef41Sopenharmony_ci reinterpret_cast<void*>(to), ComputeAddressHash(to)); 5311cb0ef41Sopenharmony_ci if (to_entry->value != nullptr) { 5321cb0ef41Sopenharmony_ci // We found the existing entry with to address for an old object. 5331cb0ef41Sopenharmony_ci // Without this operation we will have two EntryInfo's with the same 5341cb0ef41Sopenharmony_ci // value in addr field. It is bad because later at RemoveDeadEntries 5351cb0ef41Sopenharmony_ci // one of this entry will be removed with the corresponding entries_map_ 5361cb0ef41Sopenharmony_ci // entry. 5371cb0ef41Sopenharmony_ci int to_entry_info_index = 5381cb0ef41Sopenharmony_ci static_cast<int>(reinterpret_cast<intptr_t>(to_entry->value)); 5391cb0ef41Sopenharmony_ci entries_.at(to_entry_info_index).addr = kNullAddress; 5401cb0ef41Sopenharmony_ci } 5411cb0ef41Sopenharmony_ci int from_entry_info_index = 5421cb0ef41Sopenharmony_ci static_cast<int>(reinterpret_cast<intptr_t>(from_value)); 5431cb0ef41Sopenharmony_ci entries_.at(from_entry_info_index).addr = to; 5441cb0ef41Sopenharmony_ci // Size of an object can change during its life, so to keep information 5451cb0ef41Sopenharmony_ci // about the object in entries_ consistent, we have to adjust size when the 5461cb0ef41Sopenharmony_ci // object is migrated. 5471cb0ef41Sopenharmony_ci if (FLAG_heap_profiler_trace_objects) { 5481cb0ef41Sopenharmony_ci PrintF("Move object from %p to %p old size %6d new size %6d\n", 5491cb0ef41Sopenharmony_ci reinterpret_cast<void*>(from), reinterpret_cast<void*>(to), 5501cb0ef41Sopenharmony_ci entries_.at(from_entry_info_index).size, object_size); 5511cb0ef41Sopenharmony_ci } 5521cb0ef41Sopenharmony_ci entries_.at(from_entry_info_index).size = object_size; 5531cb0ef41Sopenharmony_ci to_entry->value = from_value; 5541cb0ef41Sopenharmony_ci } 5551cb0ef41Sopenharmony_ci return from_value != nullptr; 5561cb0ef41Sopenharmony_ci} 5571cb0ef41Sopenharmony_ci 5581cb0ef41Sopenharmony_ci 5591cb0ef41Sopenharmony_civoid HeapObjectsMap::UpdateObjectSize(Address addr, int size) { 5601cb0ef41Sopenharmony_ci FindOrAddEntry(addr, size, false); 5611cb0ef41Sopenharmony_ci} 5621cb0ef41Sopenharmony_ci 5631cb0ef41Sopenharmony_ci 5641cb0ef41Sopenharmony_ciSnapshotObjectId HeapObjectsMap::FindEntry(Address addr) { 5651cb0ef41Sopenharmony_ci base::HashMap::Entry* entry = entries_map_.Lookup( 5661cb0ef41Sopenharmony_ci reinterpret_cast<void*>(addr), ComputeAddressHash(addr)); 5671cb0ef41Sopenharmony_ci if (entry == nullptr) return v8::HeapProfiler::kUnknownObjectId; 5681cb0ef41Sopenharmony_ci int entry_index = static_cast<int>(reinterpret_cast<intptr_t>(entry->value)); 5691cb0ef41Sopenharmony_ci EntryInfo& entry_info = entries_.at(entry_index); 5701cb0ef41Sopenharmony_ci DCHECK(static_cast<uint32_t>(entries_.size()) > entries_map_.occupancy()); 5711cb0ef41Sopenharmony_ci return entry_info.id; 5721cb0ef41Sopenharmony_ci} 5731cb0ef41Sopenharmony_ci 5741cb0ef41Sopenharmony_ci 5751cb0ef41Sopenharmony_ciSnapshotObjectId HeapObjectsMap::FindOrAddEntry(Address addr, 5761cb0ef41Sopenharmony_ci unsigned int size, 5771cb0ef41Sopenharmony_ci bool accessed) { 5781cb0ef41Sopenharmony_ci DCHECK(static_cast<uint32_t>(entries_.size()) > entries_map_.occupancy()); 5791cb0ef41Sopenharmony_ci base::HashMap::Entry* entry = entries_map_.LookupOrInsert( 5801cb0ef41Sopenharmony_ci reinterpret_cast<void*>(addr), ComputeAddressHash(addr)); 5811cb0ef41Sopenharmony_ci if (entry->value != nullptr) { 5821cb0ef41Sopenharmony_ci int entry_index = 5831cb0ef41Sopenharmony_ci static_cast<int>(reinterpret_cast<intptr_t>(entry->value)); 5841cb0ef41Sopenharmony_ci EntryInfo& entry_info = entries_.at(entry_index); 5851cb0ef41Sopenharmony_ci entry_info.accessed = accessed; 5861cb0ef41Sopenharmony_ci if (FLAG_heap_profiler_trace_objects) { 5871cb0ef41Sopenharmony_ci PrintF("Update object size : %p with old size %d and new size %d\n", 5881cb0ef41Sopenharmony_ci reinterpret_cast<void*>(addr), entry_info.size, size); 5891cb0ef41Sopenharmony_ci } 5901cb0ef41Sopenharmony_ci entry_info.size = size; 5911cb0ef41Sopenharmony_ci return entry_info.id; 5921cb0ef41Sopenharmony_ci } 5931cb0ef41Sopenharmony_ci entry->value = reinterpret_cast<void*>(entries_.size()); 5941cb0ef41Sopenharmony_ci SnapshotObjectId id = get_next_id(); 5951cb0ef41Sopenharmony_ci entries_.push_back(EntryInfo(id, addr, size, accessed)); 5961cb0ef41Sopenharmony_ci DCHECK(static_cast<uint32_t>(entries_.size()) > entries_map_.occupancy()); 5971cb0ef41Sopenharmony_ci return id; 5981cb0ef41Sopenharmony_ci} 5991cb0ef41Sopenharmony_ci 6001cb0ef41Sopenharmony_ciSnapshotObjectId HeapObjectsMap::FindMergedNativeEntry(NativeObject addr) { 6011cb0ef41Sopenharmony_ci auto it = merged_native_entries_map_.find(addr); 6021cb0ef41Sopenharmony_ci if (it == merged_native_entries_map_.end()) 6031cb0ef41Sopenharmony_ci return v8::HeapProfiler::kUnknownObjectId; 6041cb0ef41Sopenharmony_ci return entries_[it->second].id; 6051cb0ef41Sopenharmony_ci} 6061cb0ef41Sopenharmony_ci 6071cb0ef41Sopenharmony_civoid HeapObjectsMap::AddMergedNativeEntry(NativeObject addr, 6081cb0ef41Sopenharmony_ci Address canonical_addr) { 6091cb0ef41Sopenharmony_ci base::HashMap::Entry* entry = 6101cb0ef41Sopenharmony_ci entries_map_.Lookup(reinterpret_cast<void*>(canonical_addr), 6111cb0ef41Sopenharmony_ci ComputeAddressHash(canonical_addr)); 6121cb0ef41Sopenharmony_ci auto result = merged_native_entries_map_.insert( 6131cb0ef41Sopenharmony_ci {addr, reinterpret_cast<size_t>(entry->value)}); 6141cb0ef41Sopenharmony_ci if (!result.second) { 6151cb0ef41Sopenharmony_ci result.first->second = reinterpret_cast<size_t>(entry->value); 6161cb0ef41Sopenharmony_ci } 6171cb0ef41Sopenharmony_ci} 6181cb0ef41Sopenharmony_ci 6191cb0ef41Sopenharmony_civoid HeapObjectsMap::StopHeapObjectsTracking() { time_intervals_.clear(); } 6201cb0ef41Sopenharmony_ci 6211cb0ef41Sopenharmony_civoid HeapObjectsMap::UpdateHeapObjectsMap() { 6221cb0ef41Sopenharmony_ci if (FLAG_heap_profiler_trace_objects) { 6231cb0ef41Sopenharmony_ci PrintF("Begin HeapObjectsMap::UpdateHeapObjectsMap. map has %d entries.\n", 6241cb0ef41Sopenharmony_ci entries_map_.occupancy()); 6251cb0ef41Sopenharmony_ci } 6261cb0ef41Sopenharmony_ci heap_->PreciseCollectAllGarbage(Heap::kNoGCFlags, 6271cb0ef41Sopenharmony_ci GarbageCollectionReason::kHeapProfiler); 6281cb0ef41Sopenharmony_ci PtrComprCageBase cage_base(heap_->isolate()); 6291cb0ef41Sopenharmony_ci CombinedHeapObjectIterator iterator(heap_); 6301cb0ef41Sopenharmony_ci for (HeapObject obj = iterator.Next(); !obj.is_null(); 6311cb0ef41Sopenharmony_ci obj = iterator.Next()) { 6321cb0ef41Sopenharmony_ci int object_size = obj.Size(cage_base); 6331cb0ef41Sopenharmony_ci FindOrAddEntry(obj.address(), object_size); 6341cb0ef41Sopenharmony_ci if (FLAG_heap_profiler_trace_objects) { 6351cb0ef41Sopenharmony_ci PrintF("Update object : %p %6d. Next address is %p\n", 6361cb0ef41Sopenharmony_ci reinterpret_cast<void*>(obj.address()), object_size, 6371cb0ef41Sopenharmony_ci reinterpret_cast<void*>(obj.address() + object_size)); 6381cb0ef41Sopenharmony_ci } 6391cb0ef41Sopenharmony_ci } 6401cb0ef41Sopenharmony_ci RemoveDeadEntries(); 6411cb0ef41Sopenharmony_ci if (FLAG_heap_profiler_trace_objects) { 6421cb0ef41Sopenharmony_ci PrintF("End HeapObjectsMap::UpdateHeapObjectsMap. map has %d entries.\n", 6431cb0ef41Sopenharmony_ci entries_map_.occupancy()); 6441cb0ef41Sopenharmony_ci } 6451cb0ef41Sopenharmony_ci} 6461cb0ef41Sopenharmony_ci 6471cb0ef41Sopenharmony_ciSnapshotObjectId HeapObjectsMap::PushHeapObjectsStats(OutputStream* stream, 6481cb0ef41Sopenharmony_ci int64_t* timestamp_us) { 6491cb0ef41Sopenharmony_ci UpdateHeapObjectsMap(); 6501cb0ef41Sopenharmony_ci time_intervals_.emplace_back(next_id_); 6511cb0ef41Sopenharmony_ci int prefered_chunk_size = stream->GetChunkSize(); 6521cb0ef41Sopenharmony_ci std::vector<v8::HeapStatsUpdate> stats_buffer; 6531cb0ef41Sopenharmony_ci DCHECK(!entries_.empty()); 6541cb0ef41Sopenharmony_ci EntryInfo* entry_info = &entries_.front(); 6551cb0ef41Sopenharmony_ci EntryInfo* end_entry_info = &entries_.back() + 1; 6561cb0ef41Sopenharmony_ci for (size_t time_interval_index = 0; 6571cb0ef41Sopenharmony_ci time_interval_index < time_intervals_.size(); ++time_interval_index) { 6581cb0ef41Sopenharmony_ci TimeInterval& time_interval = time_intervals_[time_interval_index]; 6591cb0ef41Sopenharmony_ci SnapshotObjectId time_interval_id = time_interval.id; 6601cb0ef41Sopenharmony_ci uint32_t entries_size = 0; 6611cb0ef41Sopenharmony_ci EntryInfo* start_entry_info = entry_info; 6621cb0ef41Sopenharmony_ci while (entry_info < end_entry_info && entry_info->id < time_interval_id) { 6631cb0ef41Sopenharmony_ci entries_size += entry_info->size; 6641cb0ef41Sopenharmony_ci ++entry_info; 6651cb0ef41Sopenharmony_ci } 6661cb0ef41Sopenharmony_ci uint32_t entries_count = 6671cb0ef41Sopenharmony_ci static_cast<uint32_t>(entry_info - start_entry_info); 6681cb0ef41Sopenharmony_ci if (time_interval.count != entries_count || 6691cb0ef41Sopenharmony_ci time_interval.size != entries_size) { 6701cb0ef41Sopenharmony_ci stats_buffer.emplace_back(static_cast<uint32_t>(time_interval_index), 6711cb0ef41Sopenharmony_ci time_interval.count = entries_count, 6721cb0ef41Sopenharmony_ci time_interval.size = entries_size); 6731cb0ef41Sopenharmony_ci if (static_cast<int>(stats_buffer.size()) >= prefered_chunk_size) { 6741cb0ef41Sopenharmony_ci OutputStream::WriteResult result = stream->WriteHeapStatsChunk( 6751cb0ef41Sopenharmony_ci &stats_buffer.front(), static_cast<int>(stats_buffer.size())); 6761cb0ef41Sopenharmony_ci if (result == OutputStream::kAbort) return last_assigned_id(); 6771cb0ef41Sopenharmony_ci stats_buffer.clear(); 6781cb0ef41Sopenharmony_ci } 6791cb0ef41Sopenharmony_ci } 6801cb0ef41Sopenharmony_ci } 6811cb0ef41Sopenharmony_ci DCHECK(entry_info == end_entry_info); 6821cb0ef41Sopenharmony_ci if (!stats_buffer.empty()) { 6831cb0ef41Sopenharmony_ci OutputStream::WriteResult result = stream->WriteHeapStatsChunk( 6841cb0ef41Sopenharmony_ci &stats_buffer.front(), static_cast<int>(stats_buffer.size())); 6851cb0ef41Sopenharmony_ci if (result == OutputStream::kAbort) return last_assigned_id(); 6861cb0ef41Sopenharmony_ci } 6871cb0ef41Sopenharmony_ci stream->EndOfStream(); 6881cb0ef41Sopenharmony_ci if (timestamp_us) { 6891cb0ef41Sopenharmony_ci *timestamp_us = 6901cb0ef41Sopenharmony_ci (time_intervals_.back().timestamp - time_intervals_.front().timestamp) 6911cb0ef41Sopenharmony_ci .InMicroseconds(); 6921cb0ef41Sopenharmony_ci } 6931cb0ef41Sopenharmony_ci return last_assigned_id(); 6941cb0ef41Sopenharmony_ci} 6951cb0ef41Sopenharmony_ci 6961cb0ef41Sopenharmony_ci 6971cb0ef41Sopenharmony_civoid HeapObjectsMap::RemoveDeadEntries() { 6981cb0ef41Sopenharmony_ci DCHECK(entries_.size() > 0 && entries_.at(0).id == 0 && 6991cb0ef41Sopenharmony_ci entries_.at(0).addr == kNullAddress); 7001cb0ef41Sopenharmony_ci 7011cb0ef41Sopenharmony_ci // Build up temporary reverse map. 7021cb0ef41Sopenharmony_ci std::unordered_map<size_t, NativeObject> reverse_merged_native_entries_map; 7031cb0ef41Sopenharmony_ci for (const auto& it : merged_native_entries_map_) { 7041cb0ef41Sopenharmony_ci auto result = 7051cb0ef41Sopenharmony_ci reverse_merged_native_entries_map.emplace(it.second, it.first); 7061cb0ef41Sopenharmony_ci DCHECK(result.second); 7071cb0ef41Sopenharmony_ci USE(result); 7081cb0ef41Sopenharmony_ci } 7091cb0ef41Sopenharmony_ci 7101cb0ef41Sopenharmony_ci size_t first_free_entry = 1; 7111cb0ef41Sopenharmony_ci for (size_t i = 1; i < entries_.size(); ++i) { 7121cb0ef41Sopenharmony_ci EntryInfo& entry_info = entries_.at(i); 7131cb0ef41Sopenharmony_ci auto merged_reverse_it = reverse_merged_native_entries_map.find(i); 7141cb0ef41Sopenharmony_ci if (entry_info.accessed) { 7151cb0ef41Sopenharmony_ci if (first_free_entry != i) { 7161cb0ef41Sopenharmony_ci entries_.at(first_free_entry) = entry_info; 7171cb0ef41Sopenharmony_ci } 7181cb0ef41Sopenharmony_ci entries_.at(first_free_entry).accessed = false; 7191cb0ef41Sopenharmony_ci base::HashMap::Entry* entry = 7201cb0ef41Sopenharmony_ci entries_map_.Lookup(reinterpret_cast<void*>(entry_info.addr), 7211cb0ef41Sopenharmony_ci ComputeAddressHash(entry_info.addr)); 7221cb0ef41Sopenharmony_ci DCHECK(entry); 7231cb0ef41Sopenharmony_ci entry->value = reinterpret_cast<void*>(first_free_entry); 7241cb0ef41Sopenharmony_ci if (merged_reverse_it != reverse_merged_native_entries_map.end()) { 7251cb0ef41Sopenharmony_ci auto it = merged_native_entries_map_.find(merged_reverse_it->second); 7261cb0ef41Sopenharmony_ci DCHECK_NE(merged_native_entries_map_.end(), it); 7271cb0ef41Sopenharmony_ci it->second = first_free_entry; 7281cb0ef41Sopenharmony_ci } 7291cb0ef41Sopenharmony_ci ++first_free_entry; 7301cb0ef41Sopenharmony_ci } else { 7311cb0ef41Sopenharmony_ci if (entry_info.addr) { 7321cb0ef41Sopenharmony_ci entries_map_.Remove(reinterpret_cast<void*>(entry_info.addr), 7331cb0ef41Sopenharmony_ci ComputeAddressHash(entry_info.addr)); 7341cb0ef41Sopenharmony_ci if (merged_reverse_it != reverse_merged_native_entries_map.end()) { 7351cb0ef41Sopenharmony_ci merged_native_entries_map_.erase(merged_reverse_it->second); 7361cb0ef41Sopenharmony_ci } 7371cb0ef41Sopenharmony_ci } 7381cb0ef41Sopenharmony_ci } 7391cb0ef41Sopenharmony_ci } 7401cb0ef41Sopenharmony_ci entries_.erase(entries_.begin() + first_free_entry, entries_.end()); 7411cb0ef41Sopenharmony_ci 7421cb0ef41Sopenharmony_ci DCHECK(static_cast<uint32_t>(entries_.size()) - 1 == 7431cb0ef41Sopenharmony_ci entries_map_.occupancy()); 7441cb0ef41Sopenharmony_ci} 7451cb0ef41Sopenharmony_ci 7461cb0ef41Sopenharmony_ciV8HeapExplorer::V8HeapExplorer(HeapSnapshot* snapshot, 7471cb0ef41Sopenharmony_ci SnapshottingProgressReportingInterface* progress, 7481cb0ef41Sopenharmony_ci v8::HeapProfiler::ObjectNameResolver* resolver) 7491cb0ef41Sopenharmony_ci : heap_(snapshot->profiler()->heap_object_map()->heap()), 7501cb0ef41Sopenharmony_ci snapshot_(snapshot), 7511cb0ef41Sopenharmony_ci names_(snapshot_->profiler()->names()), 7521cb0ef41Sopenharmony_ci heap_object_map_(snapshot_->profiler()->heap_object_map()), 7531cb0ef41Sopenharmony_ci progress_(progress), 7541cb0ef41Sopenharmony_ci generator_(nullptr), 7551cb0ef41Sopenharmony_ci global_object_name_resolver_(resolver) {} 7561cb0ef41Sopenharmony_ci 7571cb0ef41Sopenharmony_ciHeapEntry* V8HeapExplorer::AllocateEntry(HeapThing ptr) { 7581cb0ef41Sopenharmony_ci return AddEntry(HeapObject::cast(Object(reinterpret_cast<Address>(ptr)))); 7591cb0ef41Sopenharmony_ci} 7601cb0ef41Sopenharmony_ci 7611cb0ef41Sopenharmony_ciHeapEntry* V8HeapExplorer::AllocateEntry(Smi smi) { 7621cb0ef41Sopenharmony_ci SnapshotObjectId id = heap_object_map_->get_next_id(); 7631cb0ef41Sopenharmony_ci HeapEntry* entry = 7641cb0ef41Sopenharmony_ci snapshot_->AddEntry(HeapEntry::kHeapNumber, "smi number", id, 0, 0); 7651cb0ef41Sopenharmony_ci // XXX: Smis do not appear in CombinedHeapObjectIterator, so we need to 7661cb0ef41Sopenharmony_ci // extract the references here 7671cb0ef41Sopenharmony_ci ExtractNumberReference(entry, smi); 7681cb0ef41Sopenharmony_ci return entry; 7691cb0ef41Sopenharmony_ci} 7701cb0ef41Sopenharmony_ci 7711cb0ef41Sopenharmony_civoid V8HeapExplorer::ExtractLocation(HeapEntry* entry, HeapObject object) { 7721cb0ef41Sopenharmony_ci if (object.IsJSFunction()) { 7731cb0ef41Sopenharmony_ci JSFunction func = JSFunction::cast(object); 7741cb0ef41Sopenharmony_ci ExtractLocationForJSFunction(entry, func); 7751cb0ef41Sopenharmony_ci 7761cb0ef41Sopenharmony_ci } else if (object.IsJSGeneratorObject()) { 7771cb0ef41Sopenharmony_ci JSGeneratorObject gen = JSGeneratorObject::cast(object); 7781cb0ef41Sopenharmony_ci ExtractLocationForJSFunction(entry, gen.function()); 7791cb0ef41Sopenharmony_ci 7801cb0ef41Sopenharmony_ci } else if (object.IsJSObject()) { 7811cb0ef41Sopenharmony_ci JSObject obj = JSObject::cast(object); 7821cb0ef41Sopenharmony_ci JSFunction maybe_constructor = GetConstructor(heap_->isolate(), obj); 7831cb0ef41Sopenharmony_ci 7841cb0ef41Sopenharmony_ci if (!maybe_constructor.is_null()) { 7851cb0ef41Sopenharmony_ci ExtractLocationForJSFunction(entry, maybe_constructor); 7861cb0ef41Sopenharmony_ci } 7871cb0ef41Sopenharmony_ci } 7881cb0ef41Sopenharmony_ci} 7891cb0ef41Sopenharmony_ci 7901cb0ef41Sopenharmony_civoid V8HeapExplorer::ExtractLocationForJSFunction(HeapEntry* entry, 7911cb0ef41Sopenharmony_ci JSFunction func) { 7921cb0ef41Sopenharmony_ci if (!func.shared().script().IsScript()) return; 7931cb0ef41Sopenharmony_ci Script script = Script::cast(func.shared().script()); 7941cb0ef41Sopenharmony_ci int scriptId = script.id(); 7951cb0ef41Sopenharmony_ci int start = func.shared().StartPosition(); 7961cb0ef41Sopenharmony_ci Script::PositionInfo info; 7971cb0ef41Sopenharmony_ci script.GetPositionInfo(start, &info, Script::WITH_OFFSET); 7981cb0ef41Sopenharmony_ci snapshot_->AddLocation(entry, scriptId, info.line, info.column); 7991cb0ef41Sopenharmony_ci} 8001cb0ef41Sopenharmony_ci 8011cb0ef41Sopenharmony_ciHeapEntry* V8HeapExplorer::AddEntry(HeapObject object) { 8021cb0ef41Sopenharmony_ci if (object.IsJSFunction()) { 8031cb0ef41Sopenharmony_ci JSFunction func = JSFunction::cast(object); 8041cb0ef41Sopenharmony_ci SharedFunctionInfo shared = func.shared(); 8051cb0ef41Sopenharmony_ci const char* name = names_->GetName(shared.Name()); 8061cb0ef41Sopenharmony_ci return AddEntry(object, HeapEntry::kClosure, name); 8071cb0ef41Sopenharmony_ci } else if (object.IsJSBoundFunction()) { 8081cb0ef41Sopenharmony_ci return AddEntry(object, HeapEntry::kClosure, "native_bind"); 8091cb0ef41Sopenharmony_ci } else if (object.IsJSRegExp()) { 8101cb0ef41Sopenharmony_ci JSRegExp re = JSRegExp::cast(object); 8111cb0ef41Sopenharmony_ci return AddEntry(object, HeapEntry::kRegExp, names_->GetName(re.source())); 8121cb0ef41Sopenharmony_ci } else if (object.IsJSObject()) { 8131cb0ef41Sopenharmony_ci // TODO(v8:12674) Fix and run full gcmole. 8141cb0ef41Sopenharmony_ci DisableGCMole no_gcmole; 8151cb0ef41Sopenharmony_ci const char* name = names_->GetName( 8161cb0ef41Sopenharmony_ci GetConstructorName(heap_->isolate(), JSObject::cast(object))); 8171cb0ef41Sopenharmony_ci if (object.IsJSGlobalObject()) { 8181cb0ef41Sopenharmony_ci auto it = global_object_tag_map_.find(JSGlobalObject::cast(object)); 8191cb0ef41Sopenharmony_ci if (it != global_object_tag_map_.end()) { 8201cb0ef41Sopenharmony_ci name = names_->GetFormatted("%s / %s", name, it->second); 8211cb0ef41Sopenharmony_ci } 8221cb0ef41Sopenharmony_ci } 8231cb0ef41Sopenharmony_ci return AddEntry(object, HeapEntry::kObject, name); 8241cb0ef41Sopenharmony_ci } else if (object.IsString()) { 8251cb0ef41Sopenharmony_ci String string = String::cast(object); 8261cb0ef41Sopenharmony_ci if (string.IsConsString()) { 8271cb0ef41Sopenharmony_ci return AddEntry(object, HeapEntry::kConsString, "(concatenated string)"); 8281cb0ef41Sopenharmony_ci } else if (string.IsSlicedString()) { 8291cb0ef41Sopenharmony_ci return AddEntry(object, HeapEntry::kSlicedString, "(sliced string)"); 8301cb0ef41Sopenharmony_ci } else { 8311cb0ef41Sopenharmony_ci return AddEntry(object, HeapEntry::kString, 8321cb0ef41Sopenharmony_ci names_->GetName(String::cast(object))); 8331cb0ef41Sopenharmony_ci } 8341cb0ef41Sopenharmony_ci } else if (object.IsSymbol()) { 8351cb0ef41Sopenharmony_ci if (Symbol::cast(object).is_private()) 8361cb0ef41Sopenharmony_ci return AddEntry(object, HeapEntry::kHidden, "private symbol"); 8371cb0ef41Sopenharmony_ci else 8381cb0ef41Sopenharmony_ci return AddEntry(object, HeapEntry::kSymbol, "symbol"); 8391cb0ef41Sopenharmony_ci } else if (object.IsBigInt()) { 8401cb0ef41Sopenharmony_ci return AddEntry(object, HeapEntry::kBigInt, "bigint"); 8411cb0ef41Sopenharmony_ci } else if (object.IsCode()) { 8421cb0ef41Sopenharmony_ci return AddEntry(object, HeapEntry::kCode, ""); 8431cb0ef41Sopenharmony_ci } else if (object.IsSharedFunctionInfo()) { 8441cb0ef41Sopenharmony_ci String name = SharedFunctionInfo::cast(object).Name(); 8451cb0ef41Sopenharmony_ci return AddEntry(object, HeapEntry::kCode, names_->GetName(name)); 8461cb0ef41Sopenharmony_ci } else if (object.IsScript()) { 8471cb0ef41Sopenharmony_ci Object name = Script::cast(object).name(); 8481cb0ef41Sopenharmony_ci return AddEntry(object, HeapEntry::kCode, 8491cb0ef41Sopenharmony_ci name.IsString() ? names_->GetName(String::cast(name)) : ""); 8501cb0ef41Sopenharmony_ci } else if (object.IsNativeContext()) { 8511cb0ef41Sopenharmony_ci return AddEntry(object, HeapEntry::kHidden, "system / NativeContext"); 8521cb0ef41Sopenharmony_ci } else if (object.IsContext()) { 8531cb0ef41Sopenharmony_ci return AddEntry(object, HeapEntry::kObject, "system / Context"); 8541cb0ef41Sopenharmony_ci } else if (object.IsHeapNumber()) { 8551cb0ef41Sopenharmony_ci return AddEntry(object, HeapEntry::kHeapNumber, "heap number"); 8561cb0ef41Sopenharmony_ci } 8571cb0ef41Sopenharmony_ci return AddEntry(object, GetSystemEntryType(object), 8581cb0ef41Sopenharmony_ci GetSystemEntryName(object)); 8591cb0ef41Sopenharmony_ci} 8601cb0ef41Sopenharmony_ci 8611cb0ef41Sopenharmony_ciHeapEntry* V8HeapExplorer::AddEntry(HeapObject object, HeapEntry::Type type, 8621cb0ef41Sopenharmony_ci const char* name) { 8631cb0ef41Sopenharmony_ci if (FLAG_heap_profiler_show_hidden_objects && type == HeapEntry::kHidden) { 8641cb0ef41Sopenharmony_ci type = HeapEntry::kNative; 8651cb0ef41Sopenharmony_ci } 8661cb0ef41Sopenharmony_ci PtrComprCageBase cage_base(isolate()); 8671cb0ef41Sopenharmony_ci return AddEntry(object.address(), type, name, object.Size(cage_base)); 8681cb0ef41Sopenharmony_ci} 8691cb0ef41Sopenharmony_ci 8701cb0ef41Sopenharmony_ciHeapEntry* V8HeapExplorer::AddEntry(Address address, 8711cb0ef41Sopenharmony_ci HeapEntry::Type type, 8721cb0ef41Sopenharmony_ci const char* name, 8731cb0ef41Sopenharmony_ci size_t size) { 8741cb0ef41Sopenharmony_ci SnapshotObjectId object_id = heap_object_map_->FindOrAddEntry( 8751cb0ef41Sopenharmony_ci address, static_cast<unsigned int>(size)); 8761cb0ef41Sopenharmony_ci unsigned trace_node_id = 0; 8771cb0ef41Sopenharmony_ci if (AllocationTracker* allocation_tracker = 8781cb0ef41Sopenharmony_ci snapshot_->profiler()->allocation_tracker()) { 8791cb0ef41Sopenharmony_ci trace_node_id = 8801cb0ef41Sopenharmony_ci allocation_tracker->address_to_trace()->GetTraceNodeId(address); 8811cb0ef41Sopenharmony_ci } 8821cb0ef41Sopenharmony_ci return snapshot_->AddEntry(type, name, object_id, size, trace_node_id); 8831cb0ef41Sopenharmony_ci} 8841cb0ef41Sopenharmony_ci 8851cb0ef41Sopenharmony_ciconst char* V8HeapExplorer::GetSystemEntryName(HeapObject object) { 8861cb0ef41Sopenharmony_ci if (object.IsMap()) { 8871cb0ef41Sopenharmony_ci switch (Map::cast(object).instance_type()) { 8881cb0ef41Sopenharmony_ci#define MAKE_STRING_MAP_CASE(instance_type, size, name, Name) \ 8891cb0ef41Sopenharmony_ci case instance_type: return "system / Map (" #Name ")"; 8901cb0ef41Sopenharmony_ci STRING_TYPE_LIST(MAKE_STRING_MAP_CASE) 8911cb0ef41Sopenharmony_ci#undef MAKE_STRING_MAP_CASE 8921cb0ef41Sopenharmony_ci default: return "system / Map"; 8931cb0ef41Sopenharmony_ci } 8941cb0ef41Sopenharmony_ci } 8951cb0ef41Sopenharmony_ci 8961cb0ef41Sopenharmony_ci InstanceType type = object.map().instance_type(); 8971cb0ef41Sopenharmony_ci 8981cb0ef41Sopenharmony_ci // Empty string names are special: TagObject can overwrite them, and devtools 8991cb0ef41Sopenharmony_ci // will report them as "(internal array)". 9001cb0ef41Sopenharmony_ci if (InstanceTypeChecker::IsFixedArray(type) || 9011cb0ef41Sopenharmony_ci InstanceTypeChecker::IsFixedDoubleArray(type) || 9021cb0ef41Sopenharmony_ci InstanceTypeChecker::IsByteArray(type)) { 9031cb0ef41Sopenharmony_ci return ""; 9041cb0ef41Sopenharmony_ci } 9051cb0ef41Sopenharmony_ci 9061cb0ef41Sopenharmony_ci switch (type) { 9071cb0ef41Sopenharmony_ci#define MAKE_TORQUE_CASE(Name, TYPE) \ 9081cb0ef41Sopenharmony_ci case TYPE: \ 9091cb0ef41Sopenharmony_ci return "system / " #Name; 9101cb0ef41Sopenharmony_ci // The following lists include every non-String instance type. 9111cb0ef41Sopenharmony_ci // This includes a few types that already have non-"system" names assigned 9121cb0ef41Sopenharmony_ci // by AddEntry, but this is a convenient way to avoid manual upkeep here. 9131cb0ef41Sopenharmony_ci TORQUE_INSTANCE_CHECKERS_SINGLE_FULLY_DEFINED(MAKE_TORQUE_CASE) 9141cb0ef41Sopenharmony_ci TORQUE_INSTANCE_CHECKERS_MULTIPLE_FULLY_DEFINED(MAKE_TORQUE_CASE) 9151cb0ef41Sopenharmony_ci TORQUE_INSTANCE_CHECKERS_SINGLE_ONLY_DECLARED(MAKE_TORQUE_CASE) 9161cb0ef41Sopenharmony_ci TORQUE_INSTANCE_CHECKERS_MULTIPLE_ONLY_DECLARED(MAKE_TORQUE_CASE) 9171cb0ef41Sopenharmony_ci#undef MAKE_TORQUE_CASE 9181cb0ef41Sopenharmony_ci 9191cb0ef41Sopenharmony_ci // Strings were already handled by AddEntry. 9201cb0ef41Sopenharmony_ci#define MAKE_STRING_CASE(instance_type, size, name, Name) \ 9211cb0ef41Sopenharmony_ci case instance_type: \ 9221cb0ef41Sopenharmony_ci UNREACHABLE(); 9231cb0ef41Sopenharmony_ci STRING_TYPE_LIST(MAKE_STRING_CASE) 9241cb0ef41Sopenharmony_ci#undef MAKE_STRING_CASE 9251cb0ef41Sopenharmony_ci } 9261cb0ef41Sopenharmony_ci} 9271cb0ef41Sopenharmony_ci 9281cb0ef41Sopenharmony_ciHeapEntry::Type V8HeapExplorer::GetSystemEntryType(HeapObject object) { 9291cb0ef41Sopenharmony_ci InstanceType type = object.map().instance_type(); 9301cb0ef41Sopenharmony_ci if (InstanceTypeChecker::IsAllocationSite(type) || 9311cb0ef41Sopenharmony_ci InstanceTypeChecker::IsArrayBoilerplateDescription(type) || 9321cb0ef41Sopenharmony_ci InstanceTypeChecker::IsBytecodeArray(type) || 9331cb0ef41Sopenharmony_ci InstanceTypeChecker::IsClosureFeedbackCellArray(type) || 9341cb0ef41Sopenharmony_ci InstanceTypeChecker::IsCodeDataContainer(type) || 9351cb0ef41Sopenharmony_ci InstanceTypeChecker::IsFeedbackCell(type) || 9361cb0ef41Sopenharmony_ci InstanceTypeChecker::IsFeedbackMetadata(type) || 9371cb0ef41Sopenharmony_ci InstanceTypeChecker::IsFeedbackVector(type) || 9381cb0ef41Sopenharmony_ci InstanceTypeChecker::IsInterpreterData(type) || 9391cb0ef41Sopenharmony_ci InstanceTypeChecker::IsLoadHandler(type) || 9401cb0ef41Sopenharmony_ci InstanceTypeChecker::IsObjectBoilerplateDescription(type) || 9411cb0ef41Sopenharmony_ci InstanceTypeChecker::IsPreparseData(type) || 9421cb0ef41Sopenharmony_ci InstanceTypeChecker::IsRegExpBoilerplateDescription(type) || 9431cb0ef41Sopenharmony_ci InstanceTypeChecker::IsScopeInfo(type) || 9441cb0ef41Sopenharmony_ci InstanceTypeChecker::IsStoreHandler(type) || 9451cb0ef41Sopenharmony_ci InstanceTypeChecker::IsTemplateObjectDescription(type) || 9461cb0ef41Sopenharmony_ci InstanceTypeChecker::IsTurbofanType(type) || 9471cb0ef41Sopenharmony_ci InstanceTypeChecker::IsUncompiledData(type)) { 9481cb0ef41Sopenharmony_ci return HeapEntry::kCode; 9491cb0ef41Sopenharmony_ci } 9501cb0ef41Sopenharmony_ci 9511cb0ef41Sopenharmony_ci // This check must come second, because some subtypes of FixedArray are 9521cb0ef41Sopenharmony_ci // determined above to represent code content. 9531cb0ef41Sopenharmony_ci if (InstanceTypeChecker::IsFixedArray(type) || 9541cb0ef41Sopenharmony_ci InstanceTypeChecker::IsFixedDoubleArray(type) || 9551cb0ef41Sopenharmony_ci InstanceTypeChecker::IsByteArray(type)) { 9561cb0ef41Sopenharmony_ci return HeapEntry::kArray; 9571cb0ef41Sopenharmony_ci } 9581cb0ef41Sopenharmony_ci 9591cb0ef41Sopenharmony_ci return HeapEntry::kHidden; 9601cb0ef41Sopenharmony_ci} 9611cb0ef41Sopenharmony_ci 9621cb0ef41Sopenharmony_ciuint32_t V8HeapExplorer::EstimateObjectsCount() { 9631cb0ef41Sopenharmony_ci CombinedHeapObjectIterator it(heap_, HeapObjectIterator::kFilterUnreachable); 9641cb0ef41Sopenharmony_ci uint32_t objects_count = 0; 9651cb0ef41Sopenharmony_ci // Avoid overflowing the objects count. In worst case, we will show the same 9661cb0ef41Sopenharmony_ci // progress for a longer period of time, but we do not expect to have that 9671cb0ef41Sopenharmony_ci // many objects. 9681cb0ef41Sopenharmony_ci while (!it.Next().is_null() && 9691cb0ef41Sopenharmony_ci objects_count != std::numeric_limits<uint32_t>::max()) 9701cb0ef41Sopenharmony_ci ++objects_count; 9711cb0ef41Sopenharmony_ci return objects_count; 9721cb0ef41Sopenharmony_ci} 9731cb0ef41Sopenharmony_ci 9741cb0ef41Sopenharmony_ciclass IndexedReferencesExtractor : public ObjectVisitorWithCageBases { 9751cb0ef41Sopenharmony_ci public: 9761cb0ef41Sopenharmony_ci IndexedReferencesExtractor(V8HeapExplorer* generator, HeapObject parent_obj, 9771cb0ef41Sopenharmony_ci HeapEntry* parent) 9781cb0ef41Sopenharmony_ci : ObjectVisitorWithCageBases(generator->isolate()), 9791cb0ef41Sopenharmony_ci generator_(generator), 9801cb0ef41Sopenharmony_ci parent_obj_(parent_obj), 9811cb0ef41Sopenharmony_ci parent_start_(parent_obj_.RawMaybeWeakField(0)), 9821cb0ef41Sopenharmony_ci parent_end_( 9831cb0ef41Sopenharmony_ci parent_obj_.RawMaybeWeakField(parent_obj_.Size(cage_base()))), 9841cb0ef41Sopenharmony_ci parent_(parent), 9851cb0ef41Sopenharmony_ci next_index_(0) {} 9861cb0ef41Sopenharmony_ci void VisitPointers(HeapObject host, ObjectSlot start, 9871cb0ef41Sopenharmony_ci ObjectSlot end) override { 9881cb0ef41Sopenharmony_ci VisitPointers(host, MaybeObjectSlot(start), MaybeObjectSlot(end)); 9891cb0ef41Sopenharmony_ci } 9901cb0ef41Sopenharmony_ci void VisitMapPointer(HeapObject object) override { 9911cb0ef41Sopenharmony_ci VisitSlotImpl(cage_base(), object.map_slot()); 9921cb0ef41Sopenharmony_ci } 9931cb0ef41Sopenharmony_ci void VisitPointers(HeapObject host, MaybeObjectSlot start, 9941cb0ef41Sopenharmony_ci MaybeObjectSlot end) override { 9951cb0ef41Sopenharmony_ci // [start,end) must be a sub-region of [parent_start_, parent_end), i.e. 9961cb0ef41Sopenharmony_ci // all the slots must point inside the object. 9971cb0ef41Sopenharmony_ci CHECK_LE(parent_start_, start); 9981cb0ef41Sopenharmony_ci CHECK_LE(end, parent_end_); 9991cb0ef41Sopenharmony_ci for (MaybeObjectSlot slot = start; slot < end; ++slot) { 10001cb0ef41Sopenharmony_ci VisitSlotImpl(cage_base(), slot); 10011cb0ef41Sopenharmony_ci } 10021cb0ef41Sopenharmony_ci } 10031cb0ef41Sopenharmony_ci 10041cb0ef41Sopenharmony_ci void VisitCodePointer(HeapObject host, CodeObjectSlot slot) override { 10051cb0ef41Sopenharmony_ci CHECK(V8_EXTERNAL_CODE_SPACE_BOOL); 10061cb0ef41Sopenharmony_ci VisitSlotImpl(code_cage_base(), slot); 10071cb0ef41Sopenharmony_ci } 10081cb0ef41Sopenharmony_ci 10091cb0ef41Sopenharmony_ci void VisitCodeTarget(Code host, RelocInfo* rinfo) override { 10101cb0ef41Sopenharmony_ci Code target = Code::GetCodeFromTargetAddress(rinfo->target_address()); 10111cb0ef41Sopenharmony_ci VisitHeapObjectImpl(target, -1); 10121cb0ef41Sopenharmony_ci } 10131cb0ef41Sopenharmony_ci 10141cb0ef41Sopenharmony_ci void VisitEmbeddedPointer(Code host, RelocInfo* rinfo) override { 10151cb0ef41Sopenharmony_ci HeapObject object = rinfo->target_object(cage_base()); 10161cb0ef41Sopenharmony_ci if (host.IsWeakObject(object)) { 10171cb0ef41Sopenharmony_ci generator_->SetWeakReference(parent_, next_index_++, object, {}); 10181cb0ef41Sopenharmony_ci } else { 10191cb0ef41Sopenharmony_ci VisitHeapObjectImpl(object, -1); 10201cb0ef41Sopenharmony_ci } 10211cb0ef41Sopenharmony_ci } 10221cb0ef41Sopenharmony_ci 10231cb0ef41Sopenharmony_ci private: 10241cb0ef41Sopenharmony_ci template <typename TSlot> 10251cb0ef41Sopenharmony_ci V8_INLINE void VisitSlotImpl(PtrComprCageBase cage_base, TSlot slot) { 10261cb0ef41Sopenharmony_ci int field_index = 10271cb0ef41Sopenharmony_ci static_cast<int>(MaybeObjectSlot(slot.address()) - parent_start_); 10281cb0ef41Sopenharmony_ci if (generator_->visited_fields_[field_index]) { 10291cb0ef41Sopenharmony_ci generator_->visited_fields_[field_index] = false; 10301cb0ef41Sopenharmony_ci } else { 10311cb0ef41Sopenharmony_ci HeapObject heap_object; 10321cb0ef41Sopenharmony_ci auto loaded_value = slot.load(cage_base); 10331cb0ef41Sopenharmony_ci if (loaded_value.GetHeapObjectIfStrong(&heap_object)) { 10341cb0ef41Sopenharmony_ci VisitHeapObjectImpl(heap_object, field_index); 10351cb0ef41Sopenharmony_ci } else if (loaded_value.GetHeapObjectIfWeak(&heap_object)) { 10361cb0ef41Sopenharmony_ci generator_->SetWeakReference(parent_, next_index_++, heap_object, {}); 10371cb0ef41Sopenharmony_ci } 10381cb0ef41Sopenharmony_ci } 10391cb0ef41Sopenharmony_ci } 10401cb0ef41Sopenharmony_ci 10411cb0ef41Sopenharmony_ci V8_INLINE void VisitHeapObjectImpl(HeapObject heap_object, int field_index) { 10421cb0ef41Sopenharmony_ci DCHECK_LE(-1, field_index); 10431cb0ef41Sopenharmony_ci // The last parameter {field_offset} is only used to check some well-known 10441cb0ef41Sopenharmony_ci // skipped references, so passing -1 * kTaggedSize for objects embedded 10451cb0ef41Sopenharmony_ci // into code is fine. 10461cb0ef41Sopenharmony_ci generator_->SetHiddenReference(parent_obj_, parent_, next_index_++, 10471cb0ef41Sopenharmony_ci heap_object, field_index * kTaggedSize); 10481cb0ef41Sopenharmony_ci } 10491cb0ef41Sopenharmony_ci 10501cb0ef41Sopenharmony_ci V8HeapExplorer* generator_; 10511cb0ef41Sopenharmony_ci HeapObject parent_obj_; 10521cb0ef41Sopenharmony_ci MaybeObjectSlot parent_start_; 10531cb0ef41Sopenharmony_ci MaybeObjectSlot parent_end_; 10541cb0ef41Sopenharmony_ci HeapEntry* parent_; 10551cb0ef41Sopenharmony_ci int next_index_; 10561cb0ef41Sopenharmony_ci}; 10571cb0ef41Sopenharmony_ci 10581cb0ef41Sopenharmony_civoid V8HeapExplorer::ExtractReferences(HeapEntry* entry, HeapObject obj) { 10591cb0ef41Sopenharmony_ci if (obj.IsJSGlobalProxy()) { 10601cb0ef41Sopenharmony_ci ExtractJSGlobalProxyReferences(entry, JSGlobalProxy::cast(obj)); 10611cb0ef41Sopenharmony_ci } else if (obj.IsJSArrayBuffer()) { 10621cb0ef41Sopenharmony_ci ExtractJSArrayBufferReferences(entry, JSArrayBuffer::cast(obj)); 10631cb0ef41Sopenharmony_ci } else if (obj.IsJSObject()) { 10641cb0ef41Sopenharmony_ci if (obj.IsJSWeakSet()) { 10651cb0ef41Sopenharmony_ci ExtractJSWeakCollectionReferences(entry, JSWeakSet::cast(obj)); 10661cb0ef41Sopenharmony_ci } else if (obj.IsJSWeakMap()) { 10671cb0ef41Sopenharmony_ci ExtractJSWeakCollectionReferences(entry, JSWeakMap::cast(obj)); 10681cb0ef41Sopenharmony_ci } else if (obj.IsJSSet()) { 10691cb0ef41Sopenharmony_ci ExtractJSCollectionReferences(entry, JSSet::cast(obj)); 10701cb0ef41Sopenharmony_ci } else if (obj.IsJSMap()) { 10711cb0ef41Sopenharmony_ci ExtractJSCollectionReferences(entry, JSMap::cast(obj)); 10721cb0ef41Sopenharmony_ci } else if (obj.IsJSPromise()) { 10731cb0ef41Sopenharmony_ci ExtractJSPromiseReferences(entry, JSPromise::cast(obj)); 10741cb0ef41Sopenharmony_ci } else if (obj.IsJSGeneratorObject()) { 10751cb0ef41Sopenharmony_ci ExtractJSGeneratorObjectReferences(entry, JSGeneratorObject::cast(obj)); 10761cb0ef41Sopenharmony_ci } else if (obj.IsJSWeakRef()) { 10771cb0ef41Sopenharmony_ci ExtractJSWeakRefReferences(entry, JSWeakRef::cast(obj)); 10781cb0ef41Sopenharmony_ci } 10791cb0ef41Sopenharmony_ci ExtractJSObjectReferences(entry, JSObject::cast(obj)); 10801cb0ef41Sopenharmony_ci } else if (obj.IsString()) { 10811cb0ef41Sopenharmony_ci ExtractStringReferences(entry, String::cast(obj)); 10821cb0ef41Sopenharmony_ci } else if (obj.IsSymbol()) { 10831cb0ef41Sopenharmony_ci ExtractSymbolReferences(entry, Symbol::cast(obj)); 10841cb0ef41Sopenharmony_ci } else if (obj.IsMap()) { 10851cb0ef41Sopenharmony_ci ExtractMapReferences(entry, Map::cast(obj)); 10861cb0ef41Sopenharmony_ci } else if (obj.IsSharedFunctionInfo()) { 10871cb0ef41Sopenharmony_ci ExtractSharedFunctionInfoReferences(entry, SharedFunctionInfo::cast(obj)); 10881cb0ef41Sopenharmony_ci } else if (obj.IsScript()) { 10891cb0ef41Sopenharmony_ci ExtractScriptReferences(entry, Script::cast(obj)); 10901cb0ef41Sopenharmony_ci } else if (obj.IsAccessorInfo()) { 10911cb0ef41Sopenharmony_ci ExtractAccessorInfoReferences(entry, AccessorInfo::cast(obj)); 10921cb0ef41Sopenharmony_ci } else if (obj.IsAccessorPair()) { 10931cb0ef41Sopenharmony_ci ExtractAccessorPairReferences(entry, AccessorPair::cast(obj)); 10941cb0ef41Sopenharmony_ci } else if (obj.IsCode()) { 10951cb0ef41Sopenharmony_ci ExtractCodeReferences(entry, Code::cast(obj)); 10961cb0ef41Sopenharmony_ci } else if (obj.IsCell()) { 10971cb0ef41Sopenharmony_ci ExtractCellReferences(entry, Cell::cast(obj)); 10981cb0ef41Sopenharmony_ci } else if (obj.IsFeedbackCell()) { 10991cb0ef41Sopenharmony_ci ExtractFeedbackCellReferences(entry, FeedbackCell::cast(obj)); 11001cb0ef41Sopenharmony_ci } else if (obj.IsPropertyCell()) { 11011cb0ef41Sopenharmony_ci ExtractPropertyCellReferences(entry, PropertyCell::cast(obj)); 11021cb0ef41Sopenharmony_ci } else if (obj.IsAllocationSite()) { 11031cb0ef41Sopenharmony_ci ExtractAllocationSiteReferences(entry, AllocationSite::cast(obj)); 11041cb0ef41Sopenharmony_ci } else if (obj.IsArrayBoilerplateDescription()) { 11051cb0ef41Sopenharmony_ci ExtractArrayBoilerplateDescriptionReferences( 11061cb0ef41Sopenharmony_ci entry, ArrayBoilerplateDescription::cast(obj)); 11071cb0ef41Sopenharmony_ci } else if (obj.IsRegExpBoilerplateDescription()) { 11081cb0ef41Sopenharmony_ci ExtractRegExpBoilerplateDescriptionReferences( 11091cb0ef41Sopenharmony_ci entry, RegExpBoilerplateDescription::cast(obj)); 11101cb0ef41Sopenharmony_ci } else if (obj.IsFeedbackVector()) { 11111cb0ef41Sopenharmony_ci ExtractFeedbackVectorReferences(entry, FeedbackVector::cast(obj)); 11121cb0ef41Sopenharmony_ci } else if (obj.IsDescriptorArray()) { 11131cb0ef41Sopenharmony_ci ExtractDescriptorArrayReferences(entry, DescriptorArray::cast(obj)); 11141cb0ef41Sopenharmony_ci } else if (obj.IsWeakFixedArray()) { 11151cb0ef41Sopenharmony_ci ExtractWeakArrayReferences(WeakFixedArray::kHeaderSize, entry, 11161cb0ef41Sopenharmony_ci WeakFixedArray::cast(obj)); 11171cb0ef41Sopenharmony_ci } else if (obj.IsWeakArrayList()) { 11181cb0ef41Sopenharmony_ci ExtractWeakArrayReferences(WeakArrayList::kHeaderSize, entry, 11191cb0ef41Sopenharmony_ci WeakArrayList::cast(obj)); 11201cb0ef41Sopenharmony_ci } else if (obj.IsContext()) { 11211cb0ef41Sopenharmony_ci ExtractContextReferences(entry, Context::cast(obj)); 11221cb0ef41Sopenharmony_ci } else if (obj.IsEphemeronHashTable()) { 11231cb0ef41Sopenharmony_ci ExtractEphemeronHashTableReferences(entry, EphemeronHashTable::cast(obj)); 11241cb0ef41Sopenharmony_ci } else if (obj.IsFixedArray()) { 11251cb0ef41Sopenharmony_ci ExtractFixedArrayReferences(entry, FixedArray::cast(obj)); 11261cb0ef41Sopenharmony_ci } else if (obj.IsWeakCell()) { 11271cb0ef41Sopenharmony_ci ExtractWeakCellReferences(entry, WeakCell::cast(obj)); 11281cb0ef41Sopenharmony_ci } else if (obj.IsHeapNumber()) { 11291cb0ef41Sopenharmony_ci if (snapshot_->capture_numeric_value()) { 11301cb0ef41Sopenharmony_ci ExtractNumberReference(entry, obj); 11311cb0ef41Sopenharmony_ci } 11321cb0ef41Sopenharmony_ci } else if (obj.IsBytecodeArray()) { 11331cb0ef41Sopenharmony_ci ExtractBytecodeArrayReferences(entry, BytecodeArray::cast(obj)); 11341cb0ef41Sopenharmony_ci } else if (obj.IsScopeInfo()) { 11351cb0ef41Sopenharmony_ci ExtractScopeInfoReferences(entry, ScopeInfo::cast(obj)); 11361cb0ef41Sopenharmony_ci } 11371cb0ef41Sopenharmony_ci} 11381cb0ef41Sopenharmony_ci 11391cb0ef41Sopenharmony_civoid V8HeapExplorer::ExtractJSGlobalProxyReferences(HeapEntry* entry, 11401cb0ef41Sopenharmony_ci JSGlobalProxy proxy) { 11411cb0ef41Sopenharmony_ci SetInternalReference(entry, "native_context", proxy.native_context(), 11421cb0ef41Sopenharmony_ci JSGlobalProxy::kNativeContextOffset); 11431cb0ef41Sopenharmony_ci} 11441cb0ef41Sopenharmony_ci 11451cb0ef41Sopenharmony_civoid V8HeapExplorer::ExtractJSObjectReferences(HeapEntry* entry, 11461cb0ef41Sopenharmony_ci JSObject js_obj) { 11471cb0ef41Sopenharmony_ci HeapObject obj = js_obj; 11481cb0ef41Sopenharmony_ci ExtractPropertyReferences(js_obj, entry); 11491cb0ef41Sopenharmony_ci ExtractElementReferences(js_obj, entry); 11501cb0ef41Sopenharmony_ci ExtractInternalReferences(js_obj, entry); 11511cb0ef41Sopenharmony_ci Isolate* isolate = Isolate::FromHeap(heap_); 11521cb0ef41Sopenharmony_ci PrototypeIterator iter(isolate, js_obj); 11531cb0ef41Sopenharmony_ci ReadOnlyRoots roots(isolate); 11541cb0ef41Sopenharmony_ci SetPropertyReference(entry, roots.proto_string(), iter.GetCurrent()); 11551cb0ef41Sopenharmony_ci if (obj.IsJSBoundFunction()) { 11561cb0ef41Sopenharmony_ci JSBoundFunction js_fun = JSBoundFunction::cast(obj); 11571cb0ef41Sopenharmony_ci TagObject(js_fun.bound_arguments(), "(bound arguments)"); 11581cb0ef41Sopenharmony_ci SetInternalReference(entry, "bindings", js_fun.bound_arguments(), 11591cb0ef41Sopenharmony_ci JSBoundFunction::kBoundArgumentsOffset); 11601cb0ef41Sopenharmony_ci SetInternalReference(entry, "bound_this", js_fun.bound_this(), 11611cb0ef41Sopenharmony_ci JSBoundFunction::kBoundThisOffset); 11621cb0ef41Sopenharmony_ci SetInternalReference(entry, "bound_function", 11631cb0ef41Sopenharmony_ci js_fun.bound_target_function(), 11641cb0ef41Sopenharmony_ci JSBoundFunction::kBoundTargetFunctionOffset); 11651cb0ef41Sopenharmony_ci FixedArray bindings = js_fun.bound_arguments(); 11661cb0ef41Sopenharmony_ci for (int i = 0; i < bindings.length(); i++) { 11671cb0ef41Sopenharmony_ci const char* reference_name = names_->GetFormatted("bound_argument_%d", i); 11681cb0ef41Sopenharmony_ci SetNativeBindReference(entry, reference_name, bindings.get(i)); 11691cb0ef41Sopenharmony_ci } 11701cb0ef41Sopenharmony_ci } else if (obj.IsJSFunction()) { 11711cb0ef41Sopenharmony_ci JSFunction js_fun = JSFunction::cast(js_obj); 11721cb0ef41Sopenharmony_ci if (js_fun.has_prototype_slot()) { 11731cb0ef41Sopenharmony_ci Object proto_or_map = js_fun.prototype_or_initial_map(kAcquireLoad); 11741cb0ef41Sopenharmony_ci if (!proto_or_map.IsTheHole(isolate)) { 11751cb0ef41Sopenharmony_ci if (!proto_or_map.IsMap()) { 11761cb0ef41Sopenharmony_ci SetPropertyReference(entry, roots.prototype_string(), proto_or_map, 11771cb0ef41Sopenharmony_ci nullptr, 11781cb0ef41Sopenharmony_ci JSFunction::kPrototypeOrInitialMapOffset); 11791cb0ef41Sopenharmony_ci } else { 11801cb0ef41Sopenharmony_ci SetPropertyReference(entry, roots.prototype_string(), 11811cb0ef41Sopenharmony_ci js_fun.prototype()); 11821cb0ef41Sopenharmony_ci SetInternalReference(entry, "initial_map", proto_or_map, 11831cb0ef41Sopenharmony_ci JSFunction::kPrototypeOrInitialMapOffset); 11841cb0ef41Sopenharmony_ci } 11851cb0ef41Sopenharmony_ci } 11861cb0ef41Sopenharmony_ci } 11871cb0ef41Sopenharmony_ci SharedFunctionInfo shared_info = js_fun.shared(); 11881cb0ef41Sopenharmony_ci TagObject(js_fun.raw_feedback_cell(), "(function feedback cell)"); 11891cb0ef41Sopenharmony_ci SetInternalReference(entry, "feedback_cell", js_fun.raw_feedback_cell(), 11901cb0ef41Sopenharmony_ci JSFunction::kFeedbackCellOffset); 11911cb0ef41Sopenharmony_ci TagObject(shared_info, "(shared function info)"); 11921cb0ef41Sopenharmony_ci SetInternalReference(entry, "shared", shared_info, 11931cb0ef41Sopenharmony_ci JSFunction::kSharedFunctionInfoOffset); 11941cb0ef41Sopenharmony_ci TagObject(js_fun.context(), "(context)"); 11951cb0ef41Sopenharmony_ci SetInternalReference(entry, "context", js_fun.context(), 11961cb0ef41Sopenharmony_ci JSFunction::kContextOffset); 11971cb0ef41Sopenharmony_ci SetInternalReference(entry, "code", js_fun.code(), JSFunction::kCodeOffset); 11981cb0ef41Sopenharmony_ci } else if (obj.IsJSGlobalObject()) { 11991cb0ef41Sopenharmony_ci JSGlobalObject global_obj = JSGlobalObject::cast(obj); 12001cb0ef41Sopenharmony_ci SetInternalReference(entry, "native_context", global_obj.native_context(), 12011cb0ef41Sopenharmony_ci JSGlobalObject::kNativeContextOffset); 12021cb0ef41Sopenharmony_ci SetInternalReference(entry, "global_proxy", global_obj.global_proxy(), 12031cb0ef41Sopenharmony_ci JSGlobalObject::kGlobalProxyOffset); 12041cb0ef41Sopenharmony_ci STATIC_ASSERT(JSGlobalObject::kHeaderSize - JSObject::kHeaderSize == 12051cb0ef41Sopenharmony_ci 2 * kTaggedSize); 12061cb0ef41Sopenharmony_ci } else if (obj.IsJSArrayBufferView()) { 12071cb0ef41Sopenharmony_ci JSArrayBufferView view = JSArrayBufferView::cast(obj); 12081cb0ef41Sopenharmony_ci SetInternalReference(entry, "buffer", view.buffer(), 12091cb0ef41Sopenharmony_ci JSArrayBufferView::kBufferOffset); 12101cb0ef41Sopenharmony_ci } 12111cb0ef41Sopenharmony_ci 12121cb0ef41Sopenharmony_ci TagObject(js_obj.raw_properties_or_hash(), "(object properties)"); 12131cb0ef41Sopenharmony_ci SetInternalReference(entry, "properties", js_obj.raw_properties_or_hash(), 12141cb0ef41Sopenharmony_ci JSObject::kPropertiesOrHashOffset); 12151cb0ef41Sopenharmony_ci 12161cb0ef41Sopenharmony_ci TagObject(js_obj.elements(), "(object elements)"); 12171cb0ef41Sopenharmony_ci SetInternalReference(entry, "elements", js_obj.elements(), 12181cb0ef41Sopenharmony_ci JSObject::kElementsOffset); 12191cb0ef41Sopenharmony_ci} 12201cb0ef41Sopenharmony_ci 12211cb0ef41Sopenharmony_civoid V8HeapExplorer::ExtractStringReferences(HeapEntry* entry, String string) { 12221cb0ef41Sopenharmony_ci if (string.IsConsString()) { 12231cb0ef41Sopenharmony_ci ConsString cs = ConsString::cast(string); 12241cb0ef41Sopenharmony_ci SetInternalReference(entry, "first", cs.first(), ConsString::kFirstOffset); 12251cb0ef41Sopenharmony_ci SetInternalReference(entry, "second", cs.second(), 12261cb0ef41Sopenharmony_ci ConsString::kSecondOffset); 12271cb0ef41Sopenharmony_ci } else if (string.IsSlicedString()) { 12281cb0ef41Sopenharmony_ci SlicedString ss = SlicedString::cast(string); 12291cb0ef41Sopenharmony_ci SetInternalReference(entry, "parent", ss.parent(), 12301cb0ef41Sopenharmony_ci SlicedString::kParentOffset); 12311cb0ef41Sopenharmony_ci } else if (string.IsThinString()) { 12321cb0ef41Sopenharmony_ci ThinString ts = ThinString::cast(string); 12331cb0ef41Sopenharmony_ci SetInternalReference(entry, "actual", ts.actual(), 12341cb0ef41Sopenharmony_ci ThinString::kActualOffset); 12351cb0ef41Sopenharmony_ci } 12361cb0ef41Sopenharmony_ci} 12371cb0ef41Sopenharmony_ci 12381cb0ef41Sopenharmony_civoid V8HeapExplorer::ExtractSymbolReferences(HeapEntry* entry, Symbol symbol) { 12391cb0ef41Sopenharmony_ci SetInternalReference(entry, "name", symbol.description(), 12401cb0ef41Sopenharmony_ci Symbol::kDescriptionOffset); 12411cb0ef41Sopenharmony_ci} 12421cb0ef41Sopenharmony_ci 12431cb0ef41Sopenharmony_civoid V8HeapExplorer::ExtractJSCollectionReferences(HeapEntry* entry, 12441cb0ef41Sopenharmony_ci JSCollection collection) { 12451cb0ef41Sopenharmony_ci SetInternalReference(entry, "table", collection.table(), 12461cb0ef41Sopenharmony_ci JSCollection::kTableOffset); 12471cb0ef41Sopenharmony_ci} 12481cb0ef41Sopenharmony_ci 12491cb0ef41Sopenharmony_civoid V8HeapExplorer::ExtractJSWeakCollectionReferences(HeapEntry* entry, 12501cb0ef41Sopenharmony_ci JSWeakCollection obj) { 12511cb0ef41Sopenharmony_ci SetInternalReference(entry, "table", obj.table(), 12521cb0ef41Sopenharmony_ci JSWeakCollection::kTableOffset); 12531cb0ef41Sopenharmony_ci} 12541cb0ef41Sopenharmony_ci 12551cb0ef41Sopenharmony_civoid V8HeapExplorer::ExtractEphemeronHashTableReferences( 12561cb0ef41Sopenharmony_ci HeapEntry* entry, EphemeronHashTable table) { 12571cb0ef41Sopenharmony_ci for (InternalIndex i : table.IterateEntries()) { 12581cb0ef41Sopenharmony_ci int key_index = EphemeronHashTable::EntryToIndex(i) + 12591cb0ef41Sopenharmony_ci EphemeronHashTable::kEntryKeyIndex; 12601cb0ef41Sopenharmony_ci int value_index = EphemeronHashTable::EntryToValueIndex(i); 12611cb0ef41Sopenharmony_ci Object key = table.get(key_index); 12621cb0ef41Sopenharmony_ci Object value = table.get(value_index); 12631cb0ef41Sopenharmony_ci SetWeakReference(entry, key_index, key, table.OffsetOfElementAt(key_index)); 12641cb0ef41Sopenharmony_ci SetWeakReference(entry, value_index, value, 12651cb0ef41Sopenharmony_ci table.OffsetOfElementAt(value_index)); 12661cb0ef41Sopenharmony_ci HeapEntry* key_entry = GetEntry(key); 12671cb0ef41Sopenharmony_ci HeapEntry* value_entry = GetEntry(value); 12681cb0ef41Sopenharmony_ci HeapEntry* table_entry = GetEntry(table); 12691cb0ef41Sopenharmony_ci if (key_entry && value_entry && !key.IsUndefined()) { 12701cb0ef41Sopenharmony_ci const char* edge_name = names_->GetFormatted( 12711cb0ef41Sopenharmony_ci "part of key (%s @%u) -> value (%s @%u) pair in WeakMap (table @%u)", 12721cb0ef41Sopenharmony_ci key_entry->name(), key_entry->id(), value_entry->name(), 12731cb0ef41Sopenharmony_ci value_entry->id(), table_entry->id()); 12741cb0ef41Sopenharmony_ci key_entry->SetNamedAutoIndexReference(HeapGraphEdge::kInternal, edge_name, 12751cb0ef41Sopenharmony_ci value_entry, names_, generator_, 12761cb0ef41Sopenharmony_ci HeapEntry::kEphemeron); 12771cb0ef41Sopenharmony_ci table_entry->SetNamedAutoIndexReference( 12781cb0ef41Sopenharmony_ci HeapGraphEdge::kInternal, edge_name, value_entry, names_, generator_, 12791cb0ef41Sopenharmony_ci HeapEntry::kEphemeron); 12801cb0ef41Sopenharmony_ci } 12811cb0ef41Sopenharmony_ci } 12821cb0ef41Sopenharmony_ci} 12831cb0ef41Sopenharmony_ci 12841cb0ef41Sopenharmony_ci// These static arrays are used to prevent excessive code-size in 12851cb0ef41Sopenharmony_ci// ExtractContextReferences below, which would happen if we called 12861cb0ef41Sopenharmony_ci// SetInternalReference for every native context field in a macro. 12871cb0ef41Sopenharmony_cistatic const struct { 12881cb0ef41Sopenharmony_ci int index; 12891cb0ef41Sopenharmony_ci const char* name; 12901cb0ef41Sopenharmony_ci} native_context_names[] = { 12911cb0ef41Sopenharmony_ci#define CONTEXT_FIELD_INDEX_NAME(index, _, name) {Context::index, #name}, 12921cb0ef41Sopenharmony_ci NATIVE_CONTEXT_FIELDS(CONTEXT_FIELD_INDEX_NAME) 12931cb0ef41Sopenharmony_ci#undef CONTEXT_FIELD_INDEX_NAME 12941cb0ef41Sopenharmony_ci}; 12951cb0ef41Sopenharmony_ci 12961cb0ef41Sopenharmony_civoid V8HeapExplorer::ExtractContextReferences(HeapEntry* entry, 12971cb0ef41Sopenharmony_ci Context context) { 12981cb0ef41Sopenharmony_ci DisallowGarbageCollection no_gc; 12991cb0ef41Sopenharmony_ci if (!context.IsNativeContext() && context.is_declaration_context()) { 13001cb0ef41Sopenharmony_ci ScopeInfo scope_info = context.scope_info(); 13011cb0ef41Sopenharmony_ci // Add context allocated locals. 13021cb0ef41Sopenharmony_ci for (auto it : ScopeInfo::IterateLocalNames(&scope_info, no_gc)) { 13031cb0ef41Sopenharmony_ci int idx = scope_info.ContextHeaderLength() + it->index(); 13041cb0ef41Sopenharmony_ci SetContextReference(entry, it->name(), context.get(idx), 13051cb0ef41Sopenharmony_ci Context::OffsetOfElementAt(idx)); 13061cb0ef41Sopenharmony_ci } 13071cb0ef41Sopenharmony_ci if (scope_info.HasContextAllocatedFunctionName()) { 13081cb0ef41Sopenharmony_ci String name = String::cast(scope_info.FunctionName()); 13091cb0ef41Sopenharmony_ci int idx = scope_info.FunctionContextSlotIndex(name); 13101cb0ef41Sopenharmony_ci if (idx >= 0) { 13111cb0ef41Sopenharmony_ci SetContextReference(entry, name, context.get(idx), 13121cb0ef41Sopenharmony_ci Context::OffsetOfElementAt(idx)); 13131cb0ef41Sopenharmony_ci } 13141cb0ef41Sopenharmony_ci } 13151cb0ef41Sopenharmony_ci } 13161cb0ef41Sopenharmony_ci 13171cb0ef41Sopenharmony_ci SetInternalReference( 13181cb0ef41Sopenharmony_ci entry, "scope_info", context.get(Context::SCOPE_INFO_INDEX), 13191cb0ef41Sopenharmony_ci FixedArray::OffsetOfElementAt(Context::SCOPE_INFO_INDEX)); 13201cb0ef41Sopenharmony_ci SetInternalReference(entry, "previous", context.get(Context::PREVIOUS_INDEX), 13211cb0ef41Sopenharmony_ci FixedArray::OffsetOfElementAt(Context::PREVIOUS_INDEX)); 13221cb0ef41Sopenharmony_ci if (context.has_extension()) { 13231cb0ef41Sopenharmony_ci SetInternalReference( 13241cb0ef41Sopenharmony_ci entry, "extension", context.get(Context::EXTENSION_INDEX), 13251cb0ef41Sopenharmony_ci FixedArray::OffsetOfElementAt(Context::EXTENSION_INDEX)); 13261cb0ef41Sopenharmony_ci } 13271cb0ef41Sopenharmony_ci 13281cb0ef41Sopenharmony_ci if (context.IsNativeContext()) { 13291cb0ef41Sopenharmony_ci TagObject(context.normalized_map_cache(), "(context norm. map cache)"); 13301cb0ef41Sopenharmony_ci TagObject(context.embedder_data(), "(context data)"); 13311cb0ef41Sopenharmony_ci for (size_t i = 0; i < arraysize(native_context_names); i++) { 13321cb0ef41Sopenharmony_ci int index = native_context_names[i].index; 13331cb0ef41Sopenharmony_ci const char* name = native_context_names[i].name; 13341cb0ef41Sopenharmony_ci SetInternalReference(entry, name, context.get(index), 13351cb0ef41Sopenharmony_ci FixedArray::OffsetOfElementAt(index)); 13361cb0ef41Sopenharmony_ci } 13371cb0ef41Sopenharmony_ci 13381cb0ef41Sopenharmony_ci SetWeakReference(entry, "optimized_code_list", 13391cb0ef41Sopenharmony_ci context.get(Context::OPTIMIZED_CODE_LIST), 13401cb0ef41Sopenharmony_ci Context::OffsetOfElementAt(Context::OPTIMIZED_CODE_LIST), 13411cb0ef41Sopenharmony_ci HeapEntry::kCustomWeakPointer); 13421cb0ef41Sopenharmony_ci SetWeakReference(entry, "deoptimized_code_list", 13431cb0ef41Sopenharmony_ci context.get(Context::DEOPTIMIZED_CODE_LIST), 13441cb0ef41Sopenharmony_ci Context::OffsetOfElementAt(Context::DEOPTIMIZED_CODE_LIST), 13451cb0ef41Sopenharmony_ci HeapEntry::kCustomWeakPointer); 13461cb0ef41Sopenharmony_ci STATIC_ASSERT(Context::OPTIMIZED_CODE_LIST == Context::FIRST_WEAK_SLOT); 13471cb0ef41Sopenharmony_ci STATIC_ASSERT(Context::NEXT_CONTEXT_LINK + 1 == 13481cb0ef41Sopenharmony_ci Context::NATIVE_CONTEXT_SLOTS); 13491cb0ef41Sopenharmony_ci STATIC_ASSERT(Context::FIRST_WEAK_SLOT + 3 == 13501cb0ef41Sopenharmony_ci Context::NATIVE_CONTEXT_SLOTS); 13511cb0ef41Sopenharmony_ci } 13521cb0ef41Sopenharmony_ci} 13531cb0ef41Sopenharmony_ci 13541cb0ef41Sopenharmony_civoid V8HeapExplorer::ExtractMapReferences(HeapEntry* entry, Map map) { 13551cb0ef41Sopenharmony_ci MaybeObject maybe_raw_transitions_or_prototype_info = map.raw_transitions(); 13561cb0ef41Sopenharmony_ci HeapObject raw_transitions_or_prototype_info; 13571cb0ef41Sopenharmony_ci if (maybe_raw_transitions_or_prototype_info->GetHeapObjectIfWeak( 13581cb0ef41Sopenharmony_ci &raw_transitions_or_prototype_info)) { 13591cb0ef41Sopenharmony_ci DCHECK(raw_transitions_or_prototype_info.IsMap()); 13601cb0ef41Sopenharmony_ci SetWeakReference(entry, "transition", raw_transitions_or_prototype_info, 13611cb0ef41Sopenharmony_ci Map::kTransitionsOrPrototypeInfoOffset); 13621cb0ef41Sopenharmony_ci } else if (maybe_raw_transitions_or_prototype_info->GetHeapObjectIfStrong( 13631cb0ef41Sopenharmony_ci &raw_transitions_or_prototype_info)) { 13641cb0ef41Sopenharmony_ci if (raw_transitions_or_prototype_info.IsTransitionArray()) { 13651cb0ef41Sopenharmony_ci TransitionArray transitions = 13661cb0ef41Sopenharmony_ci TransitionArray::cast(raw_transitions_or_prototype_info); 13671cb0ef41Sopenharmony_ci if (map.CanTransition() && transitions.HasPrototypeTransitions()) { 13681cb0ef41Sopenharmony_ci TagObject(transitions.GetPrototypeTransitions(), 13691cb0ef41Sopenharmony_ci "(prototype transitions)"); 13701cb0ef41Sopenharmony_ci } 13711cb0ef41Sopenharmony_ci TagObject(transitions, "(transition array)"); 13721cb0ef41Sopenharmony_ci SetInternalReference(entry, "transitions", transitions, 13731cb0ef41Sopenharmony_ci Map::kTransitionsOrPrototypeInfoOffset); 13741cb0ef41Sopenharmony_ci } else if (raw_transitions_or_prototype_info.IsFixedArray()) { 13751cb0ef41Sopenharmony_ci TagObject(raw_transitions_or_prototype_info, "(transition)"); 13761cb0ef41Sopenharmony_ci SetInternalReference(entry, "transition", 13771cb0ef41Sopenharmony_ci raw_transitions_or_prototype_info, 13781cb0ef41Sopenharmony_ci Map::kTransitionsOrPrototypeInfoOffset); 13791cb0ef41Sopenharmony_ci } else if (map.is_prototype_map()) { 13801cb0ef41Sopenharmony_ci TagObject(raw_transitions_or_prototype_info, "prototype_info"); 13811cb0ef41Sopenharmony_ci SetInternalReference(entry, "prototype_info", 13821cb0ef41Sopenharmony_ci raw_transitions_or_prototype_info, 13831cb0ef41Sopenharmony_ci Map::kTransitionsOrPrototypeInfoOffset); 13841cb0ef41Sopenharmony_ci } 13851cb0ef41Sopenharmony_ci } 13861cb0ef41Sopenharmony_ci DescriptorArray descriptors = map.instance_descriptors(); 13871cb0ef41Sopenharmony_ci TagObject(descriptors, "(map descriptors)"); 13881cb0ef41Sopenharmony_ci SetInternalReference(entry, "descriptors", descriptors, 13891cb0ef41Sopenharmony_ci Map::kInstanceDescriptorsOffset); 13901cb0ef41Sopenharmony_ci SetInternalReference(entry, "prototype", map.prototype(), 13911cb0ef41Sopenharmony_ci Map::kPrototypeOffset); 13921cb0ef41Sopenharmony_ci if (map.IsContextMap()) { 13931cb0ef41Sopenharmony_ci Object native_context = map.native_context(); 13941cb0ef41Sopenharmony_ci TagObject(native_context, "(native context)"); 13951cb0ef41Sopenharmony_ci SetInternalReference(entry, "native_context", native_context, 13961cb0ef41Sopenharmony_ci Map::kConstructorOrBackPointerOrNativeContextOffset); 13971cb0ef41Sopenharmony_ci } else { 13981cb0ef41Sopenharmony_ci Object constructor_or_back_pointer = map.constructor_or_back_pointer(); 13991cb0ef41Sopenharmony_ci if (constructor_or_back_pointer.IsMap()) { 14001cb0ef41Sopenharmony_ci TagObject(constructor_or_back_pointer, "(back pointer)"); 14011cb0ef41Sopenharmony_ci SetInternalReference(entry, "back_pointer", constructor_or_back_pointer, 14021cb0ef41Sopenharmony_ci Map::kConstructorOrBackPointerOrNativeContextOffset); 14031cb0ef41Sopenharmony_ci } else if (constructor_or_back_pointer.IsFunctionTemplateInfo()) { 14041cb0ef41Sopenharmony_ci TagObject(constructor_or_back_pointer, "(constructor function data)"); 14051cb0ef41Sopenharmony_ci SetInternalReference(entry, "constructor_function_data", 14061cb0ef41Sopenharmony_ci constructor_or_back_pointer, 14071cb0ef41Sopenharmony_ci Map::kConstructorOrBackPointerOrNativeContextOffset); 14081cb0ef41Sopenharmony_ci } else { 14091cb0ef41Sopenharmony_ci SetInternalReference(entry, "constructor", constructor_or_back_pointer, 14101cb0ef41Sopenharmony_ci Map::kConstructorOrBackPointerOrNativeContextOffset); 14111cb0ef41Sopenharmony_ci } 14121cb0ef41Sopenharmony_ci } 14131cb0ef41Sopenharmony_ci TagObject(map.dependent_code(), "(dependent code)"); 14141cb0ef41Sopenharmony_ci SetInternalReference(entry, "dependent_code", map.dependent_code(), 14151cb0ef41Sopenharmony_ci Map::kDependentCodeOffset); 14161cb0ef41Sopenharmony_ci} 14171cb0ef41Sopenharmony_ci 14181cb0ef41Sopenharmony_civoid V8HeapExplorer::ExtractSharedFunctionInfoReferences( 14191cb0ef41Sopenharmony_ci HeapEntry* entry, SharedFunctionInfo shared) { 14201cb0ef41Sopenharmony_ci std::unique_ptr<char[]> name = shared.DebugNameCStr(); 14211cb0ef41Sopenharmony_ci if (name[0] != '\0') { 14221cb0ef41Sopenharmony_ci TagObject(FromCodeT(shared.GetCode()), 14231cb0ef41Sopenharmony_ci names_->GetFormatted("(code for %s)", name.get())); 14241cb0ef41Sopenharmony_ci } else { 14251cb0ef41Sopenharmony_ci TagObject(FromCodeT(shared.GetCode()), 14261cb0ef41Sopenharmony_ci names_->GetFormatted("(%s code)", 14271cb0ef41Sopenharmony_ci CodeKindToString(shared.GetCode().kind()))); 14281cb0ef41Sopenharmony_ci } 14291cb0ef41Sopenharmony_ci 14301cb0ef41Sopenharmony_ci Object name_or_scope_info = shared.name_or_scope_info(kAcquireLoad); 14311cb0ef41Sopenharmony_ci if (name_or_scope_info.IsScopeInfo()) { 14321cb0ef41Sopenharmony_ci TagObject(name_or_scope_info, "(function scope info)"); 14331cb0ef41Sopenharmony_ci } 14341cb0ef41Sopenharmony_ci SetInternalReference(entry, "name_or_scope_info", name_or_scope_info, 14351cb0ef41Sopenharmony_ci SharedFunctionInfo::kNameOrScopeInfoOffset); 14361cb0ef41Sopenharmony_ci SetInternalReference(entry, "script_or_debug_info", 14371cb0ef41Sopenharmony_ci shared.script_or_debug_info(kAcquireLoad), 14381cb0ef41Sopenharmony_ci SharedFunctionInfo::kScriptOrDebugInfoOffset); 14391cb0ef41Sopenharmony_ci SetInternalReference(entry, "function_data", 14401cb0ef41Sopenharmony_ci shared.function_data(kAcquireLoad), 14411cb0ef41Sopenharmony_ci SharedFunctionInfo::kFunctionDataOffset); 14421cb0ef41Sopenharmony_ci SetInternalReference( 14431cb0ef41Sopenharmony_ci entry, "raw_outer_scope_info_or_feedback_metadata", 14441cb0ef41Sopenharmony_ci shared.raw_outer_scope_info_or_feedback_metadata(), 14451cb0ef41Sopenharmony_ci SharedFunctionInfo::kOuterScopeInfoOrFeedbackMetadataOffset); 14461cb0ef41Sopenharmony_ci} 14471cb0ef41Sopenharmony_ci 14481cb0ef41Sopenharmony_civoid V8HeapExplorer::ExtractScriptReferences(HeapEntry* entry, Script script) { 14491cb0ef41Sopenharmony_ci SetInternalReference(entry, "source", script.source(), Script::kSourceOffset); 14501cb0ef41Sopenharmony_ci SetInternalReference(entry, "name", script.name(), Script::kNameOffset); 14511cb0ef41Sopenharmony_ci SetInternalReference(entry, "context_data", script.context_data(), 14521cb0ef41Sopenharmony_ci Script::kContextDataOffset); 14531cb0ef41Sopenharmony_ci TagObject(script.line_ends(), "(script line ends)", HeapEntry::kCode); 14541cb0ef41Sopenharmony_ci SetInternalReference(entry, "line_ends", script.line_ends(), 14551cb0ef41Sopenharmony_ci Script::kLineEndsOffset); 14561cb0ef41Sopenharmony_ci TagObject(script.shared_function_infos(), "(shared function infos)", 14571cb0ef41Sopenharmony_ci HeapEntry::kCode); 14581cb0ef41Sopenharmony_ci TagObject(script.host_defined_options(), "(host-defined options)", 14591cb0ef41Sopenharmony_ci HeapEntry::kCode); 14601cb0ef41Sopenharmony_ci} 14611cb0ef41Sopenharmony_ci 14621cb0ef41Sopenharmony_civoid V8HeapExplorer::ExtractAccessorInfoReferences(HeapEntry* entry, 14631cb0ef41Sopenharmony_ci AccessorInfo accessor_info) { 14641cb0ef41Sopenharmony_ci SetInternalReference(entry, "name", accessor_info.name(), 14651cb0ef41Sopenharmony_ci AccessorInfo::kNameOffset); 14661cb0ef41Sopenharmony_ci SetInternalReference(entry, "expected_receiver_type", 14671cb0ef41Sopenharmony_ci accessor_info.expected_receiver_type(), 14681cb0ef41Sopenharmony_ci AccessorInfo::kExpectedReceiverTypeOffset); 14691cb0ef41Sopenharmony_ci SetInternalReference(entry, "getter", accessor_info.getter(), 14701cb0ef41Sopenharmony_ci AccessorInfo::kGetterOffset); 14711cb0ef41Sopenharmony_ci SetInternalReference(entry, "setter", accessor_info.setter(), 14721cb0ef41Sopenharmony_ci AccessorInfo::kSetterOffset); 14731cb0ef41Sopenharmony_ci SetInternalReference(entry, "data", accessor_info.data(), 14741cb0ef41Sopenharmony_ci AccessorInfo::kDataOffset); 14751cb0ef41Sopenharmony_ci} 14761cb0ef41Sopenharmony_ci 14771cb0ef41Sopenharmony_civoid V8HeapExplorer::ExtractAccessorPairReferences(HeapEntry* entry, 14781cb0ef41Sopenharmony_ci AccessorPair accessors) { 14791cb0ef41Sopenharmony_ci SetInternalReference(entry, "getter", accessors.getter(), 14801cb0ef41Sopenharmony_ci AccessorPair::kGetterOffset); 14811cb0ef41Sopenharmony_ci SetInternalReference(entry, "setter", accessors.setter(), 14821cb0ef41Sopenharmony_ci AccessorPair::kSetterOffset); 14831cb0ef41Sopenharmony_ci} 14841cb0ef41Sopenharmony_ci 14851cb0ef41Sopenharmony_civoid V8HeapExplorer::ExtractJSWeakRefReferences(HeapEntry* entry, 14861cb0ef41Sopenharmony_ci JSWeakRef js_weak_ref) { 14871cb0ef41Sopenharmony_ci SetWeakReference(entry, "target", js_weak_ref.target(), 14881cb0ef41Sopenharmony_ci JSWeakRef::kTargetOffset); 14891cb0ef41Sopenharmony_ci} 14901cb0ef41Sopenharmony_ci 14911cb0ef41Sopenharmony_civoid V8HeapExplorer::ExtractWeakCellReferences(HeapEntry* entry, 14921cb0ef41Sopenharmony_ci WeakCell weak_cell) { 14931cb0ef41Sopenharmony_ci SetWeakReference(entry, "target", weak_cell.target(), 14941cb0ef41Sopenharmony_ci WeakCell::kTargetOffset); 14951cb0ef41Sopenharmony_ci SetWeakReference(entry, "unregister_token", weak_cell.unregister_token(), 14961cb0ef41Sopenharmony_ci WeakCell::kUnregisterTokenOffset); 14971cb0ef41Sopenharmony_ci} 14981cb0ef41Sopenharmony_ci 14991cb0ef41Sopenharmony_civoid V8HeapExplorer::TagBuiltinCodeObject(CodeT code, const char* name) { 15001cb0ef41Sopenharmony_ci TagObject(FromCodeT(code), names_->GetFormatted("(%s builtin)", name)); 15011cb0ef41Sopenharmony_ci} 15021cb0ef41Sopenharmony_ci 15031cb0ef41Sopenharmony_civoid V8HeapExplorer::ExtractCodeReferences(HeapEntry* entry, Code code) { 15041cb0ef41Sopenharmony_ci TagObject(code.relocation_info(), "(code relocation info)", HeapEntry::kCode); 15051cb0ef41Sopenharmony_ci SetInternalReference(entry, "relocation_info", code.relocation_info(), 15061cb0ef41Sopenharmony_ci Code::kRelocationInfoOffset); 15071cb0ef41Sopenharmony_ci 15081cb0ef41Sopenharmony_ci if (code.kind() == CodeKind::BASELINE) { 15091cb0ef41Sopenharmony_ci TagObject(code.bytecode_or_interpreter_data(), "(interpreter data)"); 15101cb0ef41Sopenharmony_ci SetInternalReference(entry, "interpreter_data", 15111cb0ef41Sopenharmony_ci code.bytecode_or_interpreter_data(), 15121cb0ef41Sopenharmony_ci Code::kDeoptimizationDataOrInterpreterDataOffset); 15131cb0ef41Sopenharmony_ci TagObject(code.bytecode_offset_table(), "(bytecode offset table)", 15141cb0ef41Sopenharmony_ci HeapEntry::kCode); 15151cb0ef41Sopenharmony_ci SetInternalReference(entry, "bytecode_offset_table", 15161cb0ef41Sopenharmony_ci code.bytecode_offset_table(), 15171cb0ef41Sopenharmony_ci Code::kPositionTableOffset); 15181cb0ef41Sopenharmony_ci } else { 15191cb0ef41Sopenharmony_ci DeoptimizationData deoptimization_data = 15201cb0ef41Sopenharmony_ci DeoptimizationData::cast(code.deoptimization_data()); 15211cb0ef41Sopenharmony_ci TagObject(deoptimization_data, "(code deopt data)", HeapEntry::kCode); 15221cb0ef41Sopenharmony_ci SetInternalReference(entry, "deoptimization_data", deoptimization_data, 15231cb0ef41Sopenharmony_ci Code::kDeoptimizationDataOrInterpreterDataOffset); 15241cb0ef41Sopenharmony_ci if (deoptimization_data.length() > 0) { 15251cb0ef41Sopenharmony_ci TagObject(deoptimization_data.TranslationByteArray(), "(code deopt data)", 15261cb0ef41Sopenharmony_ci HeapEntry::kCode); 15271cb0ef41Sopenharmony_ci TagObject(deoptimization_data.LiteralArray(), "(code deopt data)", 15281cb0ef41Sopenharmony_ci HeapEntry::kCode); 15291cb0ef41Sopenharmony_ci TagObject(deoptimization_data.InliningPositions(), "(code deopt data)", 15301cb0ef41Sopenharmony_ci HeapEntry::kCode); 15311cb0ef41Sopenharmony_ci } 15321cb0ef41Sopenharmony_ci TagObject(code.source_position_table(), "(source position table)", 15331cb0ef41Sopenharmony_ci HeapEntry::kCode); 15341cb0ef41Sopenharmony_ci SetInternalReference(entry, "source_position_table", 15351cb0ef41Sopenharmony_ci code.source_position_table(), 15361cb0ef41Sopenharmony_ci Code::kPositionTableOffset); 15371cb0ef41Sopenharmony_ci } 15381cb0ef41Sopenharmony_ci} 15391cb0ef41Sopenharmony_ci 15401cb0ef41Sopenharmony_civoid V8HeapExplorer::ExtractCellReferences(HeapEntry* entry, Cell cell) { 15411cb0ef41Sopenharmony_ci SetInternalReference(entry, "value", cell.value(), Cell::kValueOffset); 15421cb0ef41Sopenharmony_ci} 15431cb0ef41Sopenharmony_ci 15441cb0ef41Sopenharmony_civoid V8HeapExplorer::ExtractFeedbackCellReferences(HeapEntry* entry, 15451cb0ef41Sopenharmony_ci FeedbackCell feedback_cell) { 15461cb0ef41Sopenharmony_ci TagObject(feedback_cell, "(feedback cell)"); 15471cb0ef41Sopenharmony_ci SetInternalReference(entry, "value", feedback_cell.value(), 15481cb0ef41Sopenharmony_ci FeedbackCell::kValueOffset); 15491cb0ef41Sopenharmony_ci} 15501cb0ef41Sopenharmony_ci 15511cb0ef41Sopenharmony_civoid V8HeapExplorer::ExtractPropertyCellReferences(HeapEntry* entry, 15521cb0ef41Sopenharmony_ci PropertyCell cell) { 15531cb0ef41Sopenharmony_ci SetInternalReference(entry, "value", cell.value(), 15541cb0ef41Sopenharmony_ci PropertyCell::kValueOffset); 15551cb0ef41Sopenharmony_ci TagObject(cell.dependent_code(), "(dependent code)"); 15561cb0ef41Sopenharmony_ci SetInternalReference(entry, "dependent_code", cell.dependent_code(), 15571cb0ef41Sopenharmony_ci PropertyCell::kDependentCodeOffset); 15581cb0ef41Sopenharmony_ci} 15591cb0ef41Sopenharmony_ci 15601cb0ef41Sopenharmony_civoid V8HeapExplorer::ExtractAllocationSiteReferences(HeapEntry* entry, 15611cb0ef41Sopenharmony_ci AllocationSite site) { 15621cb0ef41Sopenharmony_ci SetInternalReference(entry, "transition_info", 15631cb0ef41Sopenharmony_ci site.transition_info_or_boilerplate(), 15641cb0ef41Sopenharmony_ci AllocationSite::kTransitionInfoOrBoilerplateOffset); 15651cb0ef41Sopenharmony_ci SetInternalReference(entry, "nested_site", site.nested_site(), 15661cb0ef41Sopenharmony_ci AllocationSite::kNestedSiteOffset); 15671cb0ef41Sopenharmony_ci TagObject(site.dependent_code(), "(dependent code)", HeapEntry::kCode); 15681cb0ef41Sopenharmony_ci SetInternalReference(entry, "dependent_code", site.dependent_code(), 15691cb0ef41Sopenharmony_ci AllocationSite::kDependentCodeOffset); 15701cb0ef41Sopenharmony_ci} 15711cb0ef41Sopenharmony_ci 15721cb0ef41Sopenharmony_civoid V8HeapExplorer::ExtractArrayBoilerplateDescriptionReferences( 15731cb0ef41Sopenharmony_ci HeapEntry* entry, ArrayBoilerplateDescription value) { 15741cb0ef41Sopenharmony_ci FixedArrayBase constant_elements = value.constant_elements(); 15751cb0ef41Sopenharmony_ci SetInternalReference(entry, "constant_elements", constant_elements, 15761cb0ef41Sopenharmony_ci ArrayBoilerplateDescription::kConstantElementsOffset); 15771cb0ef41Sopenharmony_ci TagObject(constant_elements, "(constant elements)", HeapEntry::kCode); 15781cb0ef41Sopenharmony_ci} 15791cb0ef41Sopenharmony_ci 15801cb0ef41Sopenharmony_civoid V8HeapExplorer::ExtractRegExpBoilerplateDescriptionReferences( 15811cb0ef41Sopenharmony_ci HeapEntry* entry, RegExpBoilerplateDescription value) { 15821cb0ef41Sopenharmony_ci TagObject(value.data(), "(RegExp data)", HeapEntry::kCode); 15831cb0ef41Sopenharmony_ci} 15841cb0ef41Sopenharmony_ci 15851cb0ef41Sopenharmony_ciclass JSArrayBufferDataEntryAllocator : public HeapEntriesAllocator { 15861cb0ef41Sopenharmony_ci public: 15871cb0ef41Sopenharmony_ci JSArrayBufferDataEntryAllocator(size_t size, V8HeapExplorer* explorer) 15881cb0ef41Sopenharmony_ci : size_(size) 15891cb0ef41Sopenharmony_ci , explorer_(explorer) { 15901cb0ef41Sopenharmony_ci } 15911cb0ef41Sopenharmony_ci HeapEntry* AllocateEntry(HeapThing ptr) override { 15921cb0ef41Sopenharmony_ci return explorer_->AddEntry(reinterpret_cast<Address>(ptr), 15931cb0ef41Sopenharmony_ci HeapEntry::kNative, "system / JSArrayBufferData", 15941cb0ef41Sopenharmony_ci size_); 15951cb0ef41Sopenharmony_ci } 15961cb0ef41Sopenharmony_ci HeapEntry* AllocateEntry(Smi smi) override { 15971cb0ef41Sopenharmony_ci DCHECK(false); 15981cb0ef41Sopenharmony_ci return nullptr; 15991cb0ef41Sopenharmony_ci } 16001cb0ef41Sopenharmony_ci 16011cb0ef41Sopenharmony_ci private: 16021cb0ef41Sopenharmony_ci size_t size_; 16031cb0ef41Sopenharmony_ci V8HeapExplorer* explorer_; 16041cb0ef41Sopenharmony_ci}; 16051cb0ef41Sopenharmony_ci 16061cb0ef41Sopenharmony_civoid V8HeapExplorer::ExtractJSArrayBufferReferences(HeapEntry* entry, 16071cb0ef41Sopenharmony_ci JSArrayBuffer buffer) { 16081cb0ef41Sopenharmony_ci // Setup a reference to a native memory backing_store object. 16091cb0ef41Sopenharmony_ci if (!buffer.backing_store()) return; 16101cb0ef41Sopenharmony_ci size_t data_size = buffer.byte_length(); 16111cb0ef41Sopenharmony_ci JSArrayBufferDataEntryAllocator allocator(data_size, this); 16121cb0ef41Sopenharmony_ci HeapEntry* data_entry = 16131cb0ef41Sopenharmony_ci generator_->FindOrAddEntry(buffer.backing_store(), &allocator); 16141cb0ef41Sopenharmony_ci entry->SetNamedReference(HeapGraphEdge::kInternal, "backing_store", 16151cb0ef41Sopenharmony_ci data_entry, generator_, HeapEntry::kOffHeapPointer); 16161cb0ef41Sopenharmony_ci} 16171cb0ef41Sopenharmony_ci 16181cb0ef41Sopenharmony_civoid V8HeapExplorer::ExtractJSPromiseReferences(HeapEntry* entry, 16191cb0ef41Sopenharmony_ci JSPromise promise) { 16201cb0ef41Sopenharmony_ci SetInternalReference(entry, "reactions_or_result", 16211cb0ef41Sopenharmony_ci promise.reactions_or_result(), 16221cb0ef41Sopenharmony_ci JSPromise::kReactionsOrResultOffset); 16231cb0ef41Sopenharmony_ci} 16241cb0ef41Sopenharmony_ci 16251cb0ef41Sopenharmony_civoid V8HeapExplorer::ExtractJSGeneratorObjectReferences( 16261cb0ef41Sopenharmony_ci HeapEntry* entry, JSGeneratorObject generator) { 16271cb0ef41Sopenharmony_ci SetInternalReference(entry, "function", generator.function(), 16281cb0ef41Sopenharmony_ci JSGeneratorObject::kFunctionOffset); 16291cb0ef41Sopenharmony_ci SetInternalReference(entry, "context", generator.context(), 16301cb0ef41Sopenharmony_ci JSGeneratorObject::kContextOffset); 16311cb0ef41Sopenharmony_ci SetInternalReference(entry, "receiver", generator.receiver(), 16321cb0ef41Sopenharmony_ci JSGeneratorObject::kReceiverOffset); 16331cb0ef41Sopenharmony_ci SetInternalReference(entry, "parameters_and_registers", 16341cb0ef41Sopenharmony_ci generator.parameters_and_registers(), 16351cb0ef41Sopenharmony_ci JSGeneratorObject::kParametersAndRegistersOffset); 16361cb0ef41Sopenharmony_ci} 16371cb0ef41Sopenharmony_ci 16381cb0ef41Sopenharmony_civoid V8HeapExplorer::ExtractFixedArrayReferences(HeapEntry* entry, 16391cb0ef41Sopenharmony_ci FixedArray array) { 16401cb0ef41Sopenharmony_ci for (int i = 0, l = array.length(); i < l; ++i) { 16411cb0ef41Sopenharmony_ci DCHECK(!HasWeakHeapObjectTag(array.get(i))); 16421cb0ef41Sopenharmony_ci SetInternalReference(entry, i, array.get(i), array.OffsetOfElementAt(i)); 16431cb0ef41Sopenharmony_ci } 16441cb0ef41Sopenharmony_ci} 16451cb0ef41Sopenharmony_ci 16461cb0ef41Sopenharmony_civoid V8HeapExplorer::ExtractNumberReference(HeapEntry* entry, Object number) { 16471cb0ef41Sopenharmony_ci DCHECK(number.IsNumber()); 16481cb0ef41Sopenharmony_ci 16491cb0ef41Sopenharmony_ci // Must be large enough to fit any double, int, or size_t. 16501cb0ef41Sopenharmony_ci char arr[32]; 16511cb0ef41Sopenharmony_ci base::Vector<char> buffer(arr, arraysize(arr)); 16521cb0ef41Sopenharmony_ci 16531cb0ef41Sopenharmony_ci const char* string; 16541cb0ef41Sopenharmony_ci if (number.IsSmi()) { 16551cb0ef41Sopenharmony_ci int int_value = Smi::ToInt(number); 16561cb0ef41Sopenharmony_ci string = IntToCString(int_value, buffer); 16571cb0ef41Sopenharmony_ci } else { 16581cb0ef41Sopenharmony_ci double double_value = HeapNumber::cast(number).value(); 16591cb0ef41Sopenharmony_ci string = DoubleToCString(double_value, buffer); 16601cb0ef41Sopenharmony_ci } 16611cb0ef41Sopenharmony_ci 16621cb0ef41Sopenharmony_ci const char* name = names_->GetCopy(string); 16631cb0ef41Sopenharmony_ci 16641cb0ef41Sopenharmony_ci SnapshotObjectId id = heap_object_map_->get_next_id(); 16651cb0ef41Sopenharmony_ci HeapEntry* child_entry = 16661cb0ef41Sopenharmony_ci snapshot_->AddEntry(HeapEntry::kString, name, id, 0, 0); 16671cb0ef41Sopenharmony_ci entry->SetNamedReference(HeapGraphEdge::kInternal, "value", child_entry, 16681cb0ef41Sopenharmony_ci generator_); 16691cb0ef41Sopenharmony_ci} 16701cb0ef41Sopenharmony_ci 16711cb0ef41Sopenharmony_civoid V8HeapExplorer::ExtractBytecodeArrayReferences(HeapEntry* entry, 16721cb0ef41Sopenharmony_ci BytecodeArray bytecode) { 16731cb0ef41Sopenharmony_ci RecursivelyTagConstantPool(bytecode.constant_pool(), "(constant pool)", 16741cb0ef41Sopenharmony_ci HeapEntry::kCode, 3); 16751cb0ef41Sopenharmony_ci TagObject(bytecode.handler_table(), "(handler table)", HeapEntry::kCode); 16761cb0ef41Sopenharmony_ci TagObject(bytecode.source_position_table(kAcquireLoad), 16771cb0ef41Sopenharmony_ci "(source position table)", HeapEntry::kCode); 16781cb0ef41Sopenharmony_ci} 16791cb0ef41Sopenharmony_ci 16801cb0ef41Sopenharmony_civoid V8HeapExplorer::ExtractScopeInfoReferences(HeapEntry* entry, 16811cb0ef41Sopenharmony_ci ScopeInfo info) { 16821cb0ef41Sopenharmony_ci if (!info.HasInlinedLocalNames()) { 16831cb0ef41Sopenharmony_ci TagObject(info.context_local_names_hashtable(), "(context local names)", 16841cb0ef41Sopenharmony_ci HeapEntry::kCode); 16851cb0ef41Sopenharmony_ci } 16861cb0ef41Sopenharmony_ci} 16871cb0ef41Sopenharmony_ci 16881cb0ef41Sopenharmony_civoid V8HeapExplorer::ExtractFeedbackVectorReferences( 16891cb0ef41Sopenharmony_ci HeapEntry* entry, FeedbackVector feedback_vector) { 16901cb0ef41Sopenharmony_ci MaybeObject code = feedback_vector.maybe_optimized_code(); 16911cb0ef41Sopenharmony_ci HeapObject code_heap_object; 16921cb0ef41Sopenharmony_ci if (code->GetHeapObjectIfWeak(&code_heap_object)) { 16931cb0ef41Sopenharmony_ci SetWeakReference(entry, "optimized code", code_heap_object, 16941cb0ef41Sopenharmony_ci FeedbackVector::kMaybeOptimizedCodeOffset); 16951cb0ef41Sopenharmony_ci } 16961cb0ef41Sopenharmony_ci for (int i = 0; i < feedback_vector.length(); ++i) { 16971cb0ef41Sopenharmony_ci MaybeObject maybe_entry = *(feedback_vector.slots_start() + i); 16981cb0ef41Sopenharmony_ci HeapObject entry; 16991cb0ef41Sopenharmony_ci if (maybe_entry.GetHeapObjectIfStrong(&entry) && 17001cb0ef41Sopenharmony_ci (entry.map(isolate()).instance_type() == WEAK_FIXED_ARRAY_TYPE || 17011cb0ef41Sopenharmony_ci entry.IsFixedArrayExact())) { 17021cb0ef41Sopenharmony_ci TagObject(entry, "(feedback)", HeapEntry::kCode); 17031cb0ef41Sopenharmony_ci } 17041cb0ef41Sopenharmony_ci } 17051cb0ef41Sopenharmony_ci} 17061cb0ef41Sopenharmony_ci 17071cb0ef41Sopenharmony_civoid V8HeapExplorer::ExtractDescriptorArrayReferences(HeapEntry* entry, 17081cb0ef41Sopenharmony_ci DescriptorArray array) { 17091cb0ef41Sopenharmony_ci SetInternalReference(entry, "enum_cache", array.enum_cache(), 17101cb0ef41Sopenharmony_ci DescriptorArray::kEnumCacheOffset); 17111cb0ef41Sopenharmony_ci MaybeObjectSlot start = MaybeObjectSlot(array.GetDescriptorSlot(0)); 17121cb0ef41Sopenharmony_ci MaybeObjectSlot end = MaybeObjectSlot( 17131cb0ef41Sopenharmony_ci array.GetDescriptorSlot(array.number_of_all_descriptors())); 17141cb0ef41Sopenharmony_ci for (int i = 0; start + i < end; ++i) { 17151cb0ef41Sopenharmony_ci MaybeObjectSlot slot = start + i; 17161cb0ef41Sopenharmony_ci int offset = static_cast<int>(slot.address() - array.address()); 17171cb0ef41Sopenharmony_ci MaybeObject object = *slot; 17181cb0ef41Sopenharmony_ci HeapObject heap_object; 17191cb0ef41Sopenharmony_ci if (object->GetHeapObjectIfWeak(&heap_object)) { 17201cb0ef41Sopenharmony_ci SetWeakReference(entry, i, heap_object, offset); 17211cb0ef41Sopenharmony_ci } else if (object->GetHeapObjectIfStrong(&heap_object)) { 17221cb0ef41Sopenharmony_ci SetInternalReference(entry, i, heap_object, offset); 17231cb0ef41Sopenharmony_ci } 17241cb0ef41Sopenharmony_ci } 17251cb0ef41Sopenharmony_ci} 17261cb0ef41Sopenharmony_ci 17271cb0ef41Sopenharmony_citemplate <typename T> 17281cb0ef41Sopenharmony_civoid V8HeapExplorer::ExtractWeakArrayReferences(int header_size, 17291cb0ef41Sopenharmony_ci HeapEntry* entry, T array) { 17301cb0ef41Sopenharmony_ci for (int i = 0; i < array.length(); ++i) { 17311cb0ef41Sopenharmony_ci MaybeObject object = array.Get(i); 17321cb0ef41Sopenharmony_ci HeapObject heap_object; 17331cb0ef41Sopenharmony_ci if (object->GetHeapObjectIfWeak(&heap_object)) { 17341cb0ef41Sopenharmony_ci SetWeakReference(entry, i, heap_object, header_size + i * kTaggedSize); 17351cb0ef41Sopenharmony_ci } else if (object->GetHeapObjectIfStrong(&heap_object)) { 17361cb0ef41Sopenharmony_ci SetInternalReference(entry, i, heap_object, 17371cb0ef41Sopenharmony_ci header_size + i * kTaggedSize); 17381cb0ef41Sopenharmony_ci } 17391cb0ef41Sopenharmony_ci } 17401cb0ef41Sopenharmony_ci} 17411cb0ef41Sopenharmony_ci 17421cb0ef41Sopenharmony_civoid V8HeapExplorer::ExtractPropertyReferences(JSObject js_obj, 17431cb0ef41Sopenharmony_ci HeapEntry* entry) { 17441cb0ef41Sopenharmony_ci Isolate* isolate = js_obj.GetIsolate(); 17451cb0ef41Sopenharmony_ci if (js_obj.HasFastProperties()) { 17461cb0ef41Sopenharmony_ci DescriptorArray descs = js_obj.map().instance_descriptors(isolate); 17471cb0ef41Sopenharmony_ci for (InternalIndex i : js_obj.map().IterateOwnDescriptors()) { 17481cb0ef41Sopenharmony_ci PropertyDetails details = descs.GetDetails(i); 17491cb0ef41Sopenharmony_ci switch (details.location()) { 17501cb0ef41Sopenharmony_ci case PropertyLocation::kField: { 17511cb0ef41Sopenharmony_ci if (!snapshot_->capture_numeric_value()) { 17521cb0ef41Sopenharmony_ci Representation r = details.representation(); 17531cb0ef41Sopenharmony_ci if (r.IsSmi() || r.IsDouble()) break; 17541cb0ef41Sopenharmony_ci } 17551cb0ef41Sopenharmony_ci 17561cb0ef41Sopenharmony_ci Name k = descs.GetKey(i); 17571cb0ef41Sopenharmony_ci FieldIndex field_index = FieldIndex::ForDescriptor(js_obj.map(), i); 17581cb0ef41Sopenharmony_ci Object value = js_obj.RawFastPropertyAt(field_index); 17591cb0ef41Sopenharmony_ci int field_offset = 17601cb0ef41Sopenharmony_ci field_index.is_inobject() ? field_index.offset() : -1; 17611cb0ef41Sopenharmony_ci 17621cb0ef41Sopenharmony_ci SetDataOrAccessorPropertyReference(details.kind(), entry, k, value, 17631cb0ef41Sopenharmony_ci nullptr, field_offset); 17641cb0ef41Sopenharmony_ci break; 17651cb0ef41Sopenharmony_ci } 17661cb0ef41Sopenharmony_ci case PropertyLocation::kDescriptor: 17671cb0ef41Sopenharmony_ci SetDataOrAccessorPropertyReference( 17681cb0ef41Sopenharmony_ci details.kind(), entry, descs.GetKey(i), descs.GetStrongValue(i)); 17691cb0ef41Sopenharmony_ci break; 17701cb0ef41Sopenharmony_ci } 17711cb0ef41Sopenharmony_ci } 17721cb0ef41Sopenharmony_ci } else if (js_obj.IsJSGlobalObject()) { 17731cb0ef41Sopenharmony_ci // We assume that global objects can only have slow properties. 17741cb0ef41Sopenharmony_ci GlobalDictionary dictionary = 17751cb0ef41Sopenharmony_ci JSGlobalObject::cast(js_obj).global_dictionary(kAcquireLoad); 17761cb0ef41Sopenharmony_ci ReadOnlyRoots roots(isolate); 17771cb0ef41Sopenharmony_ci for (InternalIndex i : dictionary.IterateEntries()) { 17781cb0ef41Sopenharmony_ci if (!dictionary.IsKey(roots, dictionary.KeyAt(i))) continue; 17791cb0ef41Sopenharmony_ci PropertyCell cell = dictionary.CellAt(i); 17801cb0ef41Sopenharmony_ci Name name = cell.name(); 17811cb0ef41Sopenharmony_ci Object value = cell.value(); 17821cb0ef41Sopenharmony_ci PropertyDetails details = cell.property_details(); 17831cb0ef41Sopenharmony_ci SetDataOrAccessorPropertyReference(details.kind(), entry, name, value); 17841cb0ef41Sopenharmony_ci } 17851cb0ef41Sopenharmony_ci } else if (V8_ENABLE_SWISS_NAME_DICTIONARY_BOOL) { 17861cb0ef41Sopenharmony_ci // SwissNameDictionary::IterateEntries creates a Handle, which should not 17871cb0ef41Sopenharmony_ci // leak out of here. 17881cb0ef41Sopenharmony_ci HandleScope scope(isolate); 17891cb0ef41Sopenharmony_ci 17901cb0ef41Sopenharmony_ci SwissNameDictionary dictionary = js_obj.property_dictionary_swiss(); 17911cb0ef41Sopenharmony_ci ReadOnlyRoots roots(isolate); 17921cb0ef41Sopenharmony_ci for (InternalIndex i : dictionary.IterateEntries()) { 17931cb0ef41Sopenharmony_ci Object k = dictionary.KeyAt(i); 17941cb0ef41Sopenharmony_ci if (!dictionary.IsKey(roots, k)) continue; 17951cb0ef41Sopenharmony_ci Object value = dictionary.ValueAt(i); 17961cb0ef41Sopenharmony_ci PropertyDetails details = dictionary.DetailsAt(i); 17971cb0ef41Sopenharmony_ci SetDataOrAccessorPropertyReference(details.kind(), entry, Name::cast(k), 17981cb0ef41Sopenharmony_ci value); 17991cb0ef41Sopenharmony_ci } 18001cb0ef41Sopenharmony_ci } else { 18011cb0ef41Sopenharmony_ci NameDictionary dictionary = js_obj.property_dictionary(); 18021cb0ef41Sopenharmony_ci ReadOnlyRoots roots(isolate); 18031cb0ef41Sopenharmony_ci for (InternalIndex i : dictionary.IterateEntries()) { 18041cb0ef41Sopenharmony_ci Object k = dictionary.KeyAt(i); 18051cb0ef41Sopenharmony_ci if (!dictionary.IsKey(roots, k)) continue; 18061cb0ef41Sopenharmony_ci Object value = dictionary.ValueAt(i); 18071cb0ef41Sopenharmony_ci PropertyDetails details = dictionary.DetailsAt(i); 18081cb0ef41Sopenharmony_ci SetDataOrAccessorPropertyReference(details.kind(), entry, Name::cast(k), 18091cb0ef41Sopenharmony_ci value); 18101cb0ef41Sopenharmony_ci } 18111cb0ef41Sopenharmony_ci } 18121cb0ef41Sopenharmony_ci} 18131cb0ef41Sopenharmony_ci 18141cb0ef41Sopenharmony_civoid V8HeapExplorer::ExtractAccessorPairProperty(HeapEntry* entry, Name key, 18151cb0ef41Sopenharmony_ci Object callback_obj, 18161cb0ef41Sopenharmony_ci int field_offset) { 18171cb0ef41Sopenharmony_ci if (!callback_obj.IsAccessorPair()) return; 18181cb0ef41Sopenharmony_ci AccessorPair accessors = AccessorPair::cast(callback_obj); 18191cb0ef41Sopenharmony_ci SetPropertyReference(entry, key, accessors, nullptr, field_offset); 18201cb0ef41Sopenharmony_ci Object getter = accessors.getter(); 18211cb0ef41Sopenharmony_ci if (!getter.IsOddball()) { 18221cb0ef41Sopenharmony_ci SetPropertyReference(entry, key, getter, "get %s"); 18231cb0ef41Sopenharmony_ci } 18241cb0ef41Sopenharmony_ci Object setter = accessors.setter(); 18251cb0ef41Sopenharmony_ci if (!setter.IsOddball()) { 18261cb0ef41Sopenharmony_ci SetPropertyReference(entry, key, setter, "set %s"); 18271cb0ef41Sopenharmony_ci } 18281cb0ef41Sopenharmony_ci} 18291cb0ef41Sopenharmony_ci 18301cb0ef41Sopenharmony_civoid V8HeapExplorer::ExtractElementReferences(JSObject js_obj, 18311cb0ef41Sopenharmony_ci HeapEntry* entry) { 18321cb0ef41Sopenharmony_ci ReadOnlyRoots roots = js_obj.GetReadOnlyRoots(); 18331cb0ef41Sopenharmony_ci if (js_obj.HasObjectElements()) { 18341cb0ef41Sopenharmony_ci FixedArray elements = FixedArray::cast(js_obj.elements()); 18351cb0ef41Sopenharmony_ci int length = js_obj.IsJSArray() ? Smi::ToInt(JSArray::cast(js_obj).length()) 18361cb0ef41Sopenharmony_ci : elements.length(); 18371cb0ef41Sopenharmony_ci for (int i = 0; i < length; ++i) { 18381cb0ef41Sopenharmony_ci if (!elements.get(i).IsTheHole(roots)) { 18391cb0ef41Sopenharmony_ci SetElementReference(entry, i, elements.get(i)); 18401cb0ef41Sopenharmony_ci } 18411cb0ef41Sopenharmony_ci } 18421cb0ef41Sopenharmony_ci } else if (js_obj.HasDictionaryElements()) { 18431cb0ef41Sopenharmony_ci NumberDictionary dictionary = js_obj.element_dictionary(); 18441cb0ef41Sopenharmony_ci for (InternalIndex i : dictionary.IterateEntries()) { 18451cb0ef41Sopenharmony_ci Object k = dictionary.KeyAt(i); 18461cb0ef41Sopenharmony_ci if (!dictionary.IsKey(roots, k)) continue; 18471cb0ef41Sopenharmony_ci DCHECK(k.IsNumber()); 18481cb0ef41Sopenharmony_ci uint32_t index = static_cast<uint32_t>(k.Number()); 18491cb0ef41Sopenharmony_ci SetElementReference(entry, index, dictionary.ValueAt(i)); 18501cb0ef41Sopenharmony_ci } 18511cb0ef41Sopenharmony_ci } 18521cb0ef41Sopenharmony_ci} 18531cb0ef41Sopenharmony_ci 18541cb0ef41Sopenharmony_civoid V8HeapExplorer::ExtractInternalReferences(JSObject js_obj, 18551cb0ef41Sopenharmony_ci HeapEntry* entry) { 18561cb0ef41Sopenharmony_ci int length = js_obj.GetEmbedderFieldCount(); 18571cb0ef41Sopenharmony_ci for (int i = 0; i < length; ++i) { 18581cb0ef41Sopenharmony_ci Object o = js_obj.GetEmbedderField(i); 18591cb0ef41Sopenharmony_ci SetInternalReference(entry, i, o, js_obj.GetEmbedderFieldOffset(i)); 18601cb0ef41Sopenharmony_ci } 18611cb0ef41Sopenharmony_ci} 18621cb0ef41Sopenharmony_ci 18631cb0ef41Sopenharmony_ciJSFunction V8HeapExplorer::GetConstructor(Isolate* isolate, 18641cb0ef41Sopenharmony_ci JSReceiver receiver) { 18651cb0ef41Sopenharmony_ci DisallowGarbageCollection no_gc; 18661cb0ef41Sopenharmony_ci HandleScope scope(isolate); 18671cb0ef41Sopenharmony_ci MaybeHandle<JSFunction> maybe_constructor = 18681cb0ef41Sopenharmony_ci JSReceiver::GetConstructor(isolate, handle(receiver, isolate)); 18691cb0ef41Sopenharmony_ci 18701cb0ef41Sopenharmony_ci if (maybe_constructor.is_null()) return JSFunction(); 18711cb0ef41Sopenharmony_ci 18721cb0ef41Sopenharmony_ci return *maybe_constructor.ToHandleChecked(); 18731cb0ef41Sopenharmony_ci} 18741cb0ef41Sopenharmony_ci 18751cb0ef41Sopenharmony_ciString V8HeapExplorer::GetConstructorName(Isolate* isolate, JSObject object) { 18761cb0ef41Sopenharmony_ci if (object.IsJSFunction()) return ReadOnlyRoots(isolate).closure_string(); 18771cb0ef41Sopenharmony_ci DisallowGarbageCollection no_gc; 18781cb0ef41Sopenharmony_ci HandleScope scope(isolate); 18791cb0ef41Sopenharmony_ci return *JSReceiver::GetConstructorName(isolate, handle(object, isolate)); 18801cb0ef41Sopenharmony_ci} 18811cb0ef41Sopenharmony_ci 18821cb0ef41Sopenharmony_ciHeapEntry* V8HeapExplorer::GetEntry(Object obj) { 18831cb0ef41Sopenharmony_ci if (obj.IsHeapObject()) { 18841cb0ef41Sopenharmony_ci return generator_->FindOrAddEntry(reinterpret_cast<void*>(obj.ptr()), this); 18851cb0ef41Sopenharmony_ci } 18861cb0ef41Sopenharmony_ci 18871cb0ef41Sopenharmony_ci DCHECK(obj.IsSmi()); 18881cb0ef41Sopenharmony_ci if (!snapshot_->capture_numeric_value()) { 18891cb0ef41Sopenharmony_ci return nullptr; 18901cb0ef41Sopenharmony_ci } 18911cb0ef41Sopenharmony_ci return generator_->FindOrAddEntry(Smi::cast(obj), this); 18921cb0ef41Sopenharmony_ci} 18931cb0ef41Sopenharmony_ci 18941cb0ef41Sopenharmony_ciclass RootsReferencesExtractor : public RootVisitor { 18951cb0ef41Sopenharmony_ci public: 18961cb0ef41Sopenharmony_ci explicit RootsReferencesExtractor(V8HeapExplorer* explorer) 18971cb0ef41Sopenharmony_ci : explorer_(explorer), visiting_weak_roots_(false) {} 18981cb0ef41Sopenharmony_ci 18991cb0ef41Sopenharmony_ci void SetVisitingWeakRoots() { visiting_weak_roots_ = true; } 19001cb0ef41Sopenharmony_ci 19011cb0ef41Sopenharmony_ci void VisitRootPointer(Root root, const char* description, 19021cb0ef41Sopenharmony_ci FullObjectSlot object) override { 19031cb0ef41Sopenharmony_ci if (root == Root::kBuiltins) { 19041cb0ef41Sopenharmony_ci explorer_->TagBuiltinCodeObject(CodeT::cast(*object), description); 19051cb0ef41Sopenharmony_ci } 19061cb0ef41Sopenharmony_ci explorer_->SetGcSubrootReference(root, description, visiting_weak_roots_, 19071cb0ef41Sopenharmony_ci *object); 19081cb0ef41Sopenharmony_ci } 19091cb0ef41Sopenharmony_ci 19101cb0ef41Sopenharmony_ci void VisitRootPointers(Root root, const char* description, 19111cb0ef41Sopenharmony_ci FullObjectSlot start, FullObjectSlot end) override { 19121cb0ef41Sopenharmony_ci for (FullObjectSlot p = start; p < end; ++p) { 19131cb0ef41Sopenharmony_ci DCHECK(!MapWord::IsPacked(p.Relaxed_Load().ptr())); 19141cb0ef41Sopenharmony_ci VisitRootPointer(root, description, p); 19151cb0ef41Sopenharmony_ci } 19161cb0ef41Sopenharmony_ci } 19171cb0ef41Sopenharmony_ci 19181cb0ef41Sopenharmony_ci void VisitRootPointers(Root root, const char* description, 19191cb0ef41Sopenharmony_ci OffHeapObjectSlot start, 19201cb0ef41Sopenharmony_ci OffHeapObjectSlot end) override { 19211cb0ef41Sopenharmony_ci DCHECK_EQ(root, Root::kStringTable); 19221cb0ef41Sopenharmony_ci PtrComprCageBase cage_base(explorer_->heap_->isolate()); 19231cb0ef41Sopenharmony_ci for (OffHeapObjectSlot p = start; p < end; ++p) { 19241cb0ef41Sopenharmony_ci explorer_->SetGcSubrootReference(root, description, visiting_weak_roots_, 19251cb0ef41Sopenharmony_ci p.load(cage_base)); 19261cb0ef41Sopenharmony_ci } 19271cb0ef41Sopenharmony_ci } 19281cb0ef41Sopenharmony_ci 19291cb0ef41Sopenharmony_ci void VisitRunningCode(FullObjectSlot p) override { 19301cb0ef41Sopenharmony_ci // Must match behavior in 19311cb0ef41Sopenharmony_ci // MarkCompactCollector::RootMarkingVisitor::VisitRunningCode, which treats 19321cb0ef41Sopenharmony_ci // deoptimization literals in running code as stack roots. 19331cb0ef41Sopenharmony_ci Code code = Code::cast(*p); 19341cb0ef41Sopenharmony_ci if (code.kind() != CodeKind::BASELINE) { 19351cb0ef41Sopenharmony_ci DeoptimizationData deopt_data = 19361cb0ef41Sopenharmony_ci DeoptimizationData::cast(code.deoptimization_data()); 19371cb0ef41Sopenharmony_ci if (deopt_data.length() > 0) { 19381cb0ef41Sopenharmony_ci DeoptimizationLiteralArray literals = deopt_data.LiteralArray(); 19391cb0ef41Sopenharmony_ci int literals_length = literals.length(); 19401cb0ef41Sopenharmony_ci for (int i = 0; i < literals_length; ++i) { 19411cb0ef41Sopenharmony_ci MaybeObject maybe_literal = literals.Get(i); 19421cb0ef41Sopenharmony_ci HeapObject heap_literal; 19431cb0ef41Sopenharmony_ci if (maybe_literal.GetHeapObject(&heap_literal)) { 19441cb0ef41Sopenharmony_ci VisitRootPointer(Root::kStackRoots, nullptr, 19451cb0ef41Sopenharmony_ci FullObjectSlot(&heap_literal)); 19461cb0ef41Sopenharmony_ci } 19471cb0ef41Sopenharmony_ci } 19481cb0ef41Sopenharmony_ci } 19491cb0ef41Sopenharmony_ci } 19501cb0ef41Sopenharmony_ci 19511cb0ef41Sopenharmony_ci // Finally visit the Code itself. 19521cb0ef41Sopenharmony_ci VisitRootPointer(Root::kStackRoots, nullptr, p); 19531cb0ef41Sopenharmony_ci } 19541cb0ef41Sopenharmony_ci 19551cb0ef41Sopenharmony_ci private: 19561cb0ef41Sopenharmony_ci V8HeapExplorer* explorer_; 19571cb0ef41Sopenharmony_ci bool visiting_weak_roots_; 19581cb0ef41Sopenharmony_ci}; 19591cb0ef41Sopenharmony_ci 19601cb0ef41Sopenharmony_cibool V8HeapExplorer::IterateAndExtractReferences( 19611cb0ef41Sopenharmony_ci HeapSnapshotGenerator* generator) { 19621cb0ef41Sopenharmony_ci generator_ = generator; 19631cb0ef41Sopenharmony_ci 19641cb0ef41Sopenharmony_ci // Create references to the synthetic roots. 19651cb0ef41Sopenharmony_ci SetRootGcRootsReference(); 19661cb0ef41Sopenharmony_ci for (int root = 0; root < static_cast<int>(Root::kNumberOfRoots); root++) { 19671cb0ef41Sopenharmony_ci SetGcRootsReference(static_cast<Root>(root)); 19681cb0ef41Sopenharmony_ci } 19691cb0ef41Sopenharmony_ci 19701cb0ef41Sopenharmony_ci // Make sure builtin code objects get their builtin tags 19711cb0ef41Sopenharmony_ci // first. Otherwise a particular JSFunction object could set 19721cb0ef41Sopenharmony_ci // its custom name to a generic builtin. 19731cb0ef41Sopenharmony_ci RootsReferencesExtractor extractor(this); 19741cb0ef41Sopenharmony_ci ReadOnlyRoots(heap_).Iterate(&extractor); 19751cb0ef41Sopenharmony_ci heap_->IterateRoots(&extractor, base::EnumSet<SkipRoot>{SkipRoot::kWeak}); 19761cb0ef41Sopenharmony_ci // TODO(v8:11800): The heap snapshot generator incorrectly considers the weak 19771cb0ef41Sopenharmony_ci // string tables as strong retainers. Move IterateWeakRoots after 19781cb0ef41Sopenharmony_ci // SetVisitingWeakRoots. 19791cb0ef41Sopenharmony_ci heap_->IterateWeakRoots(&extractor, {}); 19801cb0ef41Sopenharmony_ci extractor.SetVisitingWeakRoots(); 19811cb0ef41Sopenharmony_ci heap_->IterateWeakGlobalHandles(&extractor); 19821cb0ef41Sopenharmony_ci 19831cb0ef41Sopenharmony_ci bool interrupted = false; 19841cb0ef41Sopenharmony_ci 19851cb0ef41Sopenharmony_ci CombinedHeapObjectIterator iterator(heap_, 19861cb0ef41Sopenharmony_ci HeapObjectIterator::kFilterUnreachable); 19871cb0ef41Sopenharmony_ci PtrComprCageBase cage_base(heap_->isolate()); 19881cb0ef41Sopenharmony_ci // Heap iteration with filtering must be finished in any case. 19891cb0ef41Sopenharmony_ci for (HeapObject obj = iterator.Next(); !obj.is_null(); 19901cb0ef41Sopenharmony_ci obj = iterator.Next(), progress_->ProgressStep()) { 19911cb0ef41Sopenharmony_ci if (interrupted) continue; 19921cb0ef41Sopenharmony_ci 19931cb0ef41Sopenharmony_ci size_t max_pointer = obj.Size(cage_base) / kTaggedSize; 19941cb0ef41Sopenharmony_ci if (max_pointer > visited_fields_.size()) { 19951cb0ef41Sopenharmony_ci // Clear the current bits. 19961cb0ef41Sopenharmony_ci std::vector<bool>().swap(visited_fields_); 19971cb0ef41Sopenharmony_ci // Reallocate to right size. 19981cb0ef41Sopenharmony_ci visited_fields_.resize(max_pointer, false); 19991cb0ef41Sopenharmony_ci } 20001cb0ef41Sopenharmony_ci 20011cb0ef41Sopenharmony_ci#ifdef V8_ENABLE_HEAP_SNAPSHOT_VERIFY 20021cb0ef41Sopenharmony_ci std::unique_ptr<HeapEntryVerifier> verifier; 20031cb0ef41Sopenharmony_ci // MarkingVisitorBase doesn't expect that we will ever visit read-only 20041cb0ef41Sopenharmony_ci // objects, and fails DCHECKs if we attempt to. Read-only objects can 20051cb0ef41Sopenharmony_ci // never retain read-write objects, so there is no risk in skipping 20061cb0ef41Sopenharmony_ci // verification for them. 20071cb0ef41Sopenharmony_ci if (FLAG_heap_snapshot_verify && 20081cb0ef41Sopenharmony_ci !BasicMemoryChunk::FromHeapObject(obj)->InReadOnlySpace()) { 20091cb0ef41Sopenharmony_ci verifier = std::make_unique<HeapEntryVerifier>(generator, obj); 20101cb0ef41Sopenharmony_ci } 20111cb0ef41Sopenharmony_ci#endif 20121cb0ef41Sopenharmony_ci 20131cb0ef41Sopenharmony_ci HeapEntry* entry = GetEntry(obj); 20141cb0ef41Sopenharmony_ci ExtractReferences(entry, obj); 20151cb0ef41Sopenharmony_ci SetInternalReference(entry, "map", obj.map(cage_base), 20161cb0ef41Sopenharmony_ci HeapObject::kMapOffset); 20171cb0ef41Sopenharmony_ci // Extract unvisited fields as hidden references and restore tags 20181cb0ef41Sopenharmony_ci // of visited fields. 20191cb0ef41Sopenharmony_ci IndexedReferencesExtractor refs_extractor(this, obj, entry); 20201cb0ef41Sopenharmony_ci obj.Iterate(cage_base, &refs_extractor); 20211cb0ef41Sopenharmony_ci 20221cb0ef41Sopenharmony_ci // Ensure visited_fields_ doesn't leak to the next object. 20231cb0ef41Sopenharmony_ci for (size_t i = 0; i < max_pointer; ++i) { 20241cb0ef41Sopenharmony_ci DCHECK(!visited_fields_[i]); 20251cb0ef41Sopenharmony_ci } 20261cb0ef41Sopenharmony_ci 20271cb0ef41Sopenharmony_ci // Extract location for specific object types 20281cb0ef41Sopenharmony_ci ExtractLocation(entry, obj); 20291cb0ef41Sopenharmony_ci 20301cb0ef41Sopenharmony_ci if (!progress_->ProgressReport(false)) interrupted = true; 20311cb0ef41Sopenharmony_ci } 20321cb0ef41Sopenharmony_ci 20331cb0ef41Sopenharmony_ci generator_ = nullptr; 20341cb0ef41Sopenharmony_ci return interrupted ? false : progress_->ProgressReport(true); 20351cb0ef41Sopenharmony_ci} 20361cb0ef41Sopenharmony_ci 20371cb0ef41Sopenharmony_cibool V8HeapExplorer::IsEssentialObject(Object object) { 20381cb0ef41Sopenharmony_ci Isolate* isolate = heap_->isolate(); 20391cb0ef41Sopenharmony_ci ReadOnlyRoots roots(isolate); 20401cb0ef41Sopenharmony_ci return object.IsHeapObject() && !object.IsOddball(isolate) && 20411cb0ef41Sopenharmony_ci object != roots.empty_byte_array() && 20421cb0ef41Sopenharmony_ci object != roots.empty_fixed_array() && 20431cb0ef41Sopenharmony_ci object != roots.empty_weak_fixed_array() && 20441cb0ef41Sopenharmony_ci object != roots.empty_descriptor_array() && 20451cb0ef41Sopenharmony_ci object != roots.fixed_array_map() && object != roots.cell_map() && 20461cb0ef41Sopenharmony_ci object != roots.global_property_cell_map() && 20471cb0ef41Sopenharmony_ci object != roots.shared_function_info_map() && 20481cb0ef41Sopenharmony_ci object != roots.free_space_map() && 20491cb0ef41Sopenharmony_ci object != roots.one_pointer_filler_map() && 20501cb0ef41Sopenharmony_ci object != roots.two_pointer_filler_map(); 20511cb0ef41Sopenharmony_ci} 20521cb0ef41Sopenharmony_ci 20531cb0ef41Sopenharmony_cibool V8HeapExplorer::IsEssentialHiddenReference(Object parent, 20541cb0ef41Sopenharmony_ci int field_offset) { 20551cb0ef41Sopenharmony_ci if (parent.IsAllocationSite() && 20561cb0ef41Sopenharmony_ci field_offset == AllocationSite::kWeakNextOffset) 20571cb0ef41Sopenharmony_ci return false; 20581cb0ef41Sopenharmony_ci if (parent.IsCodeDataContainer() && 20591cb0ef41Sopenharmony_ci field_offset == CodeDataContainer::kNextCodeLinkOffset) 20601cb0ef41Sopenharmony_ci return false; 20611cb0ef41Sopenharmony_ci if (parent.IsContext() && 20621cb0ef41Sopenharmony_ci field_offset == Context::OffsetOfElementAt(Context::NEXT_CONTEXT_LINK)) 20631cb0ef41Sopenharmony_ci return false; 20641cb0ef41Sopenharmony_ci if (parent.IsJSFinalizationRegistry() && 20651cb0ef41Sopenharmony_ci field_offset == JSFinalizationRegistry::kNextDirtyOffset) 20661cb0ef41Sopenharmony_ci return false; 20671cb0ef41Sopenharmony_ci return true; 20681cb0ef41Sopenharmony_ci} 20691cb0ef41Sopenharmony_ci 20701cb0ef41Sopenharmony_civoid V8HeapExplorer::SetContextReference(HeapEntry* parent_entry, 20711cb0ef41Sopenharmony_ci String reference_name, 20721cb0ef41Sopenharmony_ci Object child_obj, int field_offset) { 20731cb0ef41Sopenharmony_ci HeapEntry* child_entry = GetEntry(child_obj); 20741cb0ef41Sopenharmony_ci if (child_entry == nullptr) return; 20751cb0ef41Sopenharmony_ci parent_entry->SetNamedReference(HeapGraphEdge::kContextVariable, 20761cb0ef41Sopenharmony_ci names_->GetName(reference_name), child_entry, 20771cb0ef41Sopenharmony_ci generator_); 20781cb0ef41Sopenharmony_ci MarkVisitedField(field_offset); 20791cb0ef41Sopenharmony_ci} 20801cb0ef41Sopenharmony_ci 20811cb0ef41Sopenharmony_civoid V8HeapExplorer::MarkVisitedField(int offset) { 20821cb0ef41Sopenharmony_ci if (offset < 0) return; 20831cb0ef41Sopenharmony_ci int index = offset / kTaggedSize; 20841cb0ef41Sopenharmony_ci DCHECK(!visited_fields_[index]); 20851cb0ef41Sopenharmony_ci visited_fields_[index] = true; 20861cb0ef41Sopenharmony_ci} 20871cb0ef41Sopenharmony_ci 20881cb0ef41Sopenharmony_civoid V8HeapExplorer::SetNativeBindReference(HeapEntry* parent_entry, 20891cb0ef41Sopenharmony_ci const char* reference_name, 20901cb0ef41Sopenharmony_ci Object child_obj) { 20911cb0ef41Sopenharmony_ci HeapEntry* child_entry = GetEntry(child_obj); 20921cb0ef41Sopenharmony_ci if (child_entry == nullptr) return; 20931cb0ef41Sopenharmony_ci parent_entry->SetNamedReference(HeapGraphEdge::kShortcut, reference_name, 20941cb0ef41Sopenharmony_ci child_entry, generator_); 20951cb0ef41Sopenharmony_ci} 20961cb0ef41Sopenharmony_ci 20971cb0ef41Sopenharmony_civoid V8HeapExplorer::SetElementReference(HeapEntry* parent_entry, int index, 20981cb0ef41Sopenharmony_ci Object child_obj) { 20991cb0ef41Sopenharmony_ci HeapEntry* child_entry = GetEntry(child_obj); 21001cb0ef41Sopenharmony_ci if (child_entry == nullptr) return; 21011cb0ef41Sopenharmony_ci parent_entry->SetIndexedReference(HeapGraphEdge::kElement, index, child_entry, 21021cb0ef41Sopenharmony_ci generator_); 21031cb0ef41Sopenharmony_ci} 21041cb0ef41Sopenharmony_ci 21051cb0ef41Sopenharmony_civoid V8HeapExplorer::SetInternalReference(HeapEntry* parent_entry, 21061cb0ef41Sopenharmony_ci const char* reference_name, 21071cb0ef41Sopenharmony_ci Object child_obj, int field_offset) { 21081cb0ef41Sopenharmony_ci if (!IsEssentialObject(child_obj)) { 21091cb0ef41Sopenharmony_ci return; 21101cb0ef41Sopenharmony_ci } 21111cb0ef41Sopenharmony_ci HeapEntry* child_entry = GetEntry(child_obj); 21121cb0ef41Sopenharmony_ci DCHECK_NOT_NULL(child_entry); 21131cb0ef41Sopenharmony_ci parent_entry->SetNamedReference(HeapGraphEdge::kInternal, reference_name, 21141cb0ef41Sopenharmony_ci child_entry, generator_); 21151cb0ef41Sopenharmony_ci MarkVisitedField(field_offset); 21161cb0ef41Sopenharmony_ci} 21171cb0ef41Sopenharmony_ci 21181cb0ef41Sopenharmony_civoid V8HeapExplorer::SetInternalReference(HeapEntry* parent_entry, int index, 21191cb0ef41Sopenharmony_ci Object child_obj, int field_offset) { 21201cb0ef41Sopenharmony_ci if (!IsEssentialObject(child_obj)) { 21211cb0ef41Sopenharmony_ci return; 21221cb0ef41Sopenharmony_ci } 21231cb0ef41Sopenharmony_ci HeapEntry* child_entry = GetEntry(child_obj); 21241cb0ef41Sopenharmony_ci DCHECK_NOT_NULL(child_entry); 21251cb0ef41Sopenharmony_ci parent_entry->SetNamedReference(HeapGraphEdge::kInternal, 21261cb0ef41Sopenharmony_ci names_->GetName(index), child_entry, 21271cb0ef41Sopenharmony_ci generator_); 21281cb0ef41Sopenharmony_ci MarkVisitedField(field_offset); 21291cb0ef41Sopenharmony_ci} 21301cb0ef41Sopenharmony_ci 21311cb0ef41Sopenharmony_civoid V8HeapExplorer::SetHiddenReference(HeapObject parent_obj, 21321cb0ef41Sopenharmony_ci HeapEntry* parent_entry, int index, 21331cb0ef41Sopenharmony_ci Object child_obj, int field_offset) { 21341cb0ef41Sopenharmony_ci DCHECK_EQ(parent_entry, GetEntry(parent_obj)); 21351cb0ef41Sopenharmony_ci DCHECK(!MapWord::IsPacked(child_obj.ptr())); 21361cb0ef41Sopenharmony_ci if (!IsEssentialObject(child_obj)) { 21371cb0ef41Sopenharmony_ci return; 21381cb0ef41Sopenharmony_ci } 21391cb0ef41Sopenharmony_ci HeapEntry* child_entry = GetEntry(child_obj); 21401cb0ef41Sopenharmony_ci DCHECK_NOT_NULL(child_entry); 21411cb0ef41Sopenharmony_ci if (IsEssentialHiddenReference(parent_obj, field_offset)) { 21421cb0ef41Sopenharmony_ci parent_entry->SetIndexedReference(HeapGraphEdge::kHidden, index, 21431cb0ef41Sopenharmony_ci child_entry, generator_); 21441cb0ef41Sopenharmony_ci } 21451cb0ef41Sopenharmony_ci} 21461cb0ef41Sopenharmony_ci 21471cb0ef41Sopenharmony_civoid V8HeapExplorer::SetWeakReference( 21481cb0ef41Sopenharmony_ci HeapEntry* parent_entry, const char* reference_name, Object child_obj, 21491cb0ef41Sopenharmony_ci int field_offset, HeapEntry::ReferenceVerification verification) { 21501cb0ef41Sopenharmony_ci if (!IsEssentialObject(child_obj)) { 21511cb0ef41Sopenharmony_ci return; 21521cb0ef41Sopenharmony_ci } 21531cb0ef41Sopenharmony_ci HeapEntry* child_entry = GetEntry(child_obj); 21541cb0ef41Sopenharmony_ci DCHECK_NOT_NULL(child_entry); 21551cb0ef41Sopenharmony_ci parent_entry->SetNamedReference(HeapGraphEdge::kWeak, reference_name, 21561cb0ef41Sopenharmony_ci child_entry, generator_, verification); 21571cb0ef41Sopenharmony_ci MarkVisitedField(field_offset); 21581cb0ef41Sopenharmony_ci} 21591cb0ef41Sopenharmony_ci 21601cb0ef41Sopenharmony_civoid V8HeapExplorer::SetWeakReference(HeapEntry* parent_entry, int index, 21611cb0ef41Sopenharmony_ci Object child_obj, 21621cb0ef41Sopenharmony_ci base::Optional<int> field_offset) { 21631cb0ef41Sopenharmony_ci if (!IsEssentialObject(child_obj)) { 21641cb0ef41Sopenharmony_ci return; 21651cb0ef41Sopenharmony_ci } 21661cb0ef41Sopenharmony_ci HeapEntry* child_entry = GetEntry(child_obj); 21671cb0ef41Sopenharmony_ci DCHECK_NOT_NULL(child_entry); 21681cb0ef41Sopenharmony_ci parent_entry->SetNamedReference(HeapGraphEdge::kWeak, 21691cb0ef41Sopenharmony_ci names_->GetFormatted("%d", index), 21701cb0ef41Sopenharmony_ci child_entry, generator_); 21711cb0ef41Sopenharmony_ci if (field_offset.has_value()) { 21721cb0ef41Sopenharmony_ci MarkVisitedField(*field_offset); 21731cb0ef41Sopenharmony_ci } 21741cb0ef41Sopenharmony_ci} 21751cb0ef41Sopenharmony_ci 21761cb0ef41Sopenharmony_civoid V8HeapExplorer::SetDataOrAccessorPropertyReference( 21771cb0ef41Sopenharmony_ci PropertyKind kind, HeapEntry* parent_entry, Name reference_name, 21781cb0ef41Sopenharmony_ci Object child_obj, const char* name_format_string, int field_offset) { 21791cb0ef41Sopenharmony_ci if (kind == PropertyKind::kAccessor) { 21801cb0ef41Sopenharmony_ci ExtractAccessorPairProperty(parent_entry, reference_name, child_obj, 21811cb0ef41Sopenharmony_ci field_offset); 21821cb0ef41Sopenharmony_ci } else { 21831cb0ef41Sopenharmony_ci SetPropertyReference(parent_entry, reference_name, child_obj, 21841cb0ef41Sopenharmony_ci name_format_string, field_offset); 21851cb0ef41Sopenharmony_ci } 21861cb0ef41Sopenharmony_ci} 21871cb0ef41Sopenharmony_ci 21881cb0ef41Sopenharmony_civoid V8HeapExplorer::SetPropertyReference(HeapEntry* parent_entry, 21891cb0ef41Sopenharmony_ci Name reference_name, Object child_obj, 21901cb0ef41Sopenharmony_ci const char* name_format_string, 21911cb0ef41Sopenharmony_ci int field_offset) { 21921cb0ef41Sopenharmony_ci HeapEntry* child_entry = GetEntry(child_obj); 21931cb0ef41Sopenharmony_ci if (child_entry == nullptr) return; 21941cb0ef41Sopenharmony_ci HeapGraphEdge::Type type = 21951cb0ef41Sopenharmony_ci reference_name.IsSymbol() || String::cast(reference_name).length() > 0 21961cb0ef41Sopenharmony_ci ? HeapGraphEdge::kProperty 21971cb0ef41Sopenharmony_ci : HeapGraphEdge::kInternal; 21981cb0ef41Sopenharmony_ci const char* name = 21991cb0ef41Sopenharmony_ci name_format_string != nullptr && reference_name.IsString() 22001cb0ef41Sopenharmony_ci ? names_->GetFormatted( 22011cb0ef41Sopenharmony_ci name_format_string, 22021cb0ef41Sopenharmony_ci String::cast(reference_name) 22031cb0ef41Sopenharmony_ci .ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL) 22041cb0ef41Sopenharmony_ci .get()) 22051cb0ef41Sopenharmony_ci : names_->GetName(reference_name); 22061cb0ef41Sopenharmony_ci 22071cb0ef41Sopenharmony_ci parent_entry->SetNamedReference(type, name, child_entry, generator_); 22081cb0ef41Sopenharmony_ci MarkVisitedField(field_offset); 22091cb0ef41Sopenharmony_ci} 22101cb0ef41Sopenharmony_ci 22111cb0ef41Sopenharmony_civoid V8HeapExplorer::SetRootGcRootsReference() { 22121cb0ef41Sopenharmony_ci snapshot_->root()->SetIndexedAutoIndexReference( 22131cb0ef41Sopenharmony_ci HeapGraphEdge::kElement, snapshot_->gc_roots(), generator_); 22141cb0ef41Sopenharmony_ci} 22151cb0ef41Sopenharmony_ci 22161cb0ef41Sopenharmony_civoid V8HeapExplorer::SetUserGlobalReference(Object child_obj) { 22171cb0ef41Sopenharmony_ci HeapEntry* child_entry = GetEntry(child_obj); 22181cb0ef41Sopenharmony_ci DCHECK_NOT_NULL(child_entry); 22191cb0ef41Sopenharmony_ci snapshot_->root()->SetNamedAutoIndexReference( 22201cb0ef41Sopenharmony_ci HeapGraphEdge::kShortcut, nullptr, child_entry, names_, generator_); 22211cb0ef41Sopenharmony_ci} 22221cb0ef41Sopenharmony_ci 22231cb0ef41Sopenharmony_civoid V8HeapExplorer::SetGcRootsReference(Root root) { 22241cb0ef41Sopenharmony_ci snapshot_->gc_roots()->SetIndexedAutoIndexReference( 22251cb0ef41Sopenharmony_ci HeapGraphEdge::kElement, snapshot_->gc_subroot(root), generator_); 22261cb0ef41Sopenharmony_ci} 22271cb0ef41Sopenharmony_ci 22281cb0ef41Sopenharmony_civoid V8HeapExplorer::SetGcSubrootReference(Root root, const char* description, 22291cb0ef41Sopenharmony_ci bool is_weak, Object child_obj) { 22301cb0ef41Sopenharmony_ci if (child_obj.IsSmi()) { 22311cb0ef41Sopenharmony_ci // TODO(arenevier): if we handle smis here, the snapshot gets 2 to 3 times 22321cb0ef41Sopenharmony_ci // slower on large heaps. According to perf, The bulk of the extra works 22331cb0ef41Sopenharmony_ci // happens in TemplateHashMapImpl::Probe method, when tyring to get 22341cb0ef41Sopenharmony_ci // names->GetFormatted("%d / %s", index, description) 22351cb0ef41Sopenharmony_ci return; 22361cb0ef41Sopenharmony_ci } 22371cb0ef41Sopenharmony_ci HeapEntry* child_entry = GetEntry(child_obj); 22381cb0ef41Sopenharmony_ci if (child_entry == nullptr) return; 22391cb0ef41Sopenharmony_ci const char* name = GetStrongGcSubrootName(child_obj); 22401cb0ef41Sopenharmony_ci HeapGraphEdge::Type edge_type = 22411cb0ef41Sopenharmony_ci is_weak ? HeapGraphEdge::kWeak : HeapGraphEdge::kInternal; 22421cb0ef41Sopenharmony_ci if (name != nullptr) { 22431cb0ef41Sopenharmony_ci snapshot_->gc_subroot(root)->SetNamedReference(edge_type, name, child_entry, 22441cb0ef41Sopenharmony_ci generator_); 22451cb0ef41Sopenharmony_ci } else { 22461cb0ef41Sopenharmony_ci snapshot_->gc_subroot(root)->SetNamedAutoIndexReference( 22471cb0ef41Sopenharmony_ci edge_type, description, child_entry, names_, generator_); 22481cb0ef41Sopenharmony_ci } 22491cb0ef41Sopenharmony_ci 22501cb0ef41Sopenharmony_ci // For full heap snapshots we do not emit user roots but rather rely on 22511cb0ef41Sopenharmony_ci // regular GC roots to retain objects. 22521cb0ef41Sopenharmony_ci if (!snapshot_->treat_global_objects_as_roots()) return; 22531cb0ef41Sopenharmony_ci 22541cb0ef41Sopenharmony_ci // Add a shortcut to JS global object reference at snapshot root. 22551cb0ef41Sopenharmony_ci // That allows the user to easily find global objects. They are 22561cb0ef41Sopenharmony_ci // also used as starting points in distance calculations. 22571cb0ef41Sopenharmony_ci if (is_weak || !child_obj.IsNativeContext()) return; 22581cb0ef41Sopenharmony_ci 22591cb0ef41Sopenharmony_ci JSGlobalObject global = Context::cast(child_obj).global_object(); 22601cb0ef41Sopenharmony_ci if (!global.IsJSGlobalObject()) return; 22611cb0ef41Sopenharmony_ci 22621cb0ef41Sopenharmony_ci if (!user_roots_.insert(global).second) return; 22631cb0ef41Sopenharmony_ci 22641cb0ef41Sopenharmony_ci SetUserGlobalReference(global); 22651cb0ef41Sopenharmony_ci} 22661cb0ef41Sopenharmony_ci 22671cb0ef41Sopenharmony_ciconst char* V8HeapExplorer::GetStrongGcSubrootName(Object object) { 22681cb0ef41Sopenharmony_ci if (strong_gc_subroot_names_.empty()) { 22691cb0ef41Sopenharmony_ci Isolate* isolate = Isolate::FromHeap(heap_); 22701cb0ef41Sopenharmony_ci for (RootIndex root_index = RootIndex::kFirstStrongOrReadOnlyRoot; 22711cb0ef41Sopenharmony_ci root_index <= RootIndex::kLastStrongOrReadOnlyRoot; ++root_index) { 22721cb0ef41Sopenharmony_ci const char* name = RootsTable::name(root_index); 22731cb0ef41Sopenharmony_ci strong_gc_subroot_names_.emplace(isolate->root(root_index), name); 22741cb0ef41Sopenharmony_ci } 22751cb0ef41Sopenharmony_ci CHECK(!strong_gc_subroot_names_.empty()); 22761cb0ef41Sopenharmony_ci } 22771cb0ef41Sopenharmony_ci auto it = strong_gc_subroot_names_.find(object); 22781cb0ef41Sopenharmony_ci return it != strong_gc_subroot_names_.end() ? it->second : nullptr; 22791cb0ef41Sopenharmony_ci} 22801cb0ef41Sopenharmony_ci 22811cb0ef41Sopenharmony_civoid V8HeapExplorer::TagObject(Object obj, const char* tag, 22821cb0ef41Sopenharmony_ci base::Optional<HeapEntry::Type> type) { 22831cb0ef41Sopenharmony_ci if (IsEssentialObject(obj)) { 22841cb0ef41Sopenharmony_ci HeapEntry* entry = GetEntry(obj); 22851cb0ef41Sopenharmony_ci if (entry->name()[0] == '\0') { 22861cb0ef41Sopenharmony_ci entry->set_name(tag); 22871cb0ef41Sopenharmony_ci } 22881cb0ef41Sopenharmony_ci if (type.has_value()) { 22891cb0ef41Sopenharmony_ci entry->set_type(*type); 22901cb0ef41Sopenharmony_ci } 22911cb0ef41Sopenharmony_ci } 22921cb0ef41Sopenharmony_ci} 22931cb0ef41Sopenharmony_ci 22941cb0ef41Sopenharmony_civoid V8HeapExplorer::RecursivelyTagConstantPool(Object obj, const char* tag, 22951cb0ef41Sopenharmony_ci HeapEntry::Type type, 22961cb0ef41Sopenharmony_ci int recursion_limit) { 22971cb0ef41Sopenharmony_ci --recursion_limit; 22981cb0ef41Sopenharmony_ci if (obj.IsFixedArrayExact(isolate())) { 22991cb0ef41Sopenharmony_ci FixedArray arr = FixedArray::cast(obj); 23001cb0ef41Sopenharmony_ci TagObject(arr, tag, type); 23011cb0ef41Sopenharmony_ci if (recursion_limit <= 0) return; 23021cb0ef41Sopenharmony_ci for (int i = 0; i < arr.length(); ++i) { 23031cb0ef41Sopenharmony_ci RecursivelyTagConstantPool(arr.get(i), tag, type, recursion_limit); 23041cb0ef41Sopenharmony_ci } 23051cb0ef41Sopenharmony_ci } else if (obj.IsNameDictionary(isolate()) || 23061cb0ef41Sopenharmony_ci obj.IsNumberDictionary(isolate())) { 23071cb0ef41Sopenharmony_ci TagObject(obj, tag, type); 23081cb0ef41Sopenharmony_ci } 23091cb0ef41Sopenharmony_ci} 23101cb0ef41Sopenharmony_ci 23111cb0ef41Sopenharmony_ciclass GlobalObjectsEnumerator : public RootVisitor { 23121cb0ef41Sopenharmony_ci public: 23131cb0ef41Sopenharmony_ci explicit GlobalObjectsEnumerator(Isolate* isolate) : isolate_(isolate) {} 23141cb0ef41Sopenharmony_ci 23151cb0ef41Sopenharmony_ci void VisitRootPointers(Root root, const char* description, 23161cb0ef41Sopenharmony_ci FullObjectSlot start, FullObjectSlot end) override { 23171cb0ef41Sopenharmony_ci VisitRootPointersImpl(root, description, start, end); 23181cb0ef41Sopenharmony_ci } 23191cb0ef41Sopenharmony_ci 23201cb0ef41Sopenharmony_ci void VisitRootPointers(Root root, const char* description, 23211cb0ef41Sopenharmony_ci OffHeapObjectSlot start, 23221cb0ef41Sopenharmony_ci OffHeapObjectSlot end) override { 23231cb0ef41Sopenharmony_ci VisitRootPointersImpl(root, description, start, end); 23241cb0ef41Sopenharmony_ci } 23251cb0ef41Sopenharmony_ci 23261cb0ef41Sopenharmony_ci int count() const { return static_cast<int>(objects_.size()); } 23271cb0ef41Sopenharmony_ci Handle<JSGlobalObject>& at(int i) { return objects_[i]; } 23281cb0ef41Sopenharmony_ci 23291cb0ef41Sopenharmony_ci private: 23301cb0ef41Sopenharmony_ci template <typename TSlot> 23311cb0ef41Sopenharmony_ci void VisitRootPointersImpl(Root root, const char* description, TSlot start, 23321cb0ef41Sopenharmony_ci TSlot end) { 23331cb0ef41Sopenharmony_ci for (TSlot p = start; p < end; ++p) { 23341cb0ef41Sopenharmony_ci DCHECK(!MapWord::IsPacked(p.Relaxed_Load(isolate_).ptr())); 23351cb0ef41Sopenharmony_ci Object o = p.load(isolate_); 23361cb0ef41Sopenharmony_ci if (!o.IsNativeContext(isolate_)) continue; 23371cb0ef41Sopenharmony_ci JSObject proxy = Context::cast(o).global_proxy(); 23381cb0ef41Sopenharmony_ci if (!proxy.IsJSGlobalProxy(isolate_)) continue; 23391cb0ef41Sopenharmony_ci Object global = proxy.map(isolate_).prototype(isolate_); 23401cb0ef41Sopenharmony_ci if (!global.IsJSGlobalObject(isolate_)) continue; 23411cb0ef41Sopenharmony_ci objects_.push_back(handle(JSGlobalObject::cast(global), isolate_)); 23421cb0ef41Sopenharmony_ci } 23431cb0ef41Sopenharmony_ci } 23441cb0ef41Sopenharmony_ci 23451cb0ef41Sopenharmony_ci Isolate* isolate_; 23461cb0ef41Sopenharmony_ci std::vector<Handle<JSGlobalObject>> objects_; 23471cb0ef41Sopenharmony_ci}; 23481cb0ef41Sopenharmony_ci 23491cb0ef41Sopenharmony_ci 23501cb0ef41Sopenharmony_ci// Modifies heap. Must not be run during heap traversal. 23511cb0ef41Sopenharmony_civoid V8HeapExplorer::CollectGlobalObjectsTags() { 23521cb0ef41Sopenharmony_ci if (!global_object_name_resolver_) return; 23531cb0ef41Sopenharmony_ci 23541cb0ef41Sopenharmony_ci Isolate* isolate = Isolate::FromHeap(heap_); 23551cb0ef41Sopenharmony_ci GlobalObjectsEnumerator enumerator(isolate); 23561cb0ef41Sopenharmony_ci isolate->global_handles()->IterateAllRoots(&enumerator); 23571cb0ef41Sopenharmony_ci for (int i = 0, l = enumerator.count(); i < l; ++i) { 23581cb0ef41Sopenharmony_ci Handle<JSGlobalObject> obj = enumerator.at(i); 23591cb0ef41Sopenharmony_ci const char* tag = global_object_name_resolver_->GetName( 23601cb0ef41Sopenharmony_ci Utils::ToLocal(Handle<JSObject>::cast(obj))); 23611cb0ef41Sopenharmony_ci if (tag) { 23621cb0ef41Sopenharmony_ci global_object_tag_pairs_.emplace_back(obj, tag); 23631cb0ef41Sopenharmony_ci } 23641cb0ef41Sopenharmony_ci } 23651cb0ef41Sopenharmony_ci} 23661cb0ef41Sopenharmony_ci 23671cb0ef41Sopenharmony_civoid V8HeapExplorer::MakeGlobalObjectTagMap( 23681cb0ef41Sopenharmony_ci const SafepointScope& safepoint_scope) { 23691cb0ef41Sopenharmony_ci for (const auto& pair : global_object_tag_pairs_) { 23701cb0ef41Sopenharmony_ci global_object_tag_map_.emplace(*pair.first, pair.second); 23711cb0ef41Sopenharmony_ci } 23721cb0ef41Sopenharmony_ci} 23731cb0ef41Sopenharmony_ci 23741cb0ef41Sopenharmony_ciclass EmbedderGraphImpl : public EmbedderGraph { 23751cb0ef41Sopenharmony_ci public: 23761cb0ef41Sopenharmony_ci struct Edge { 23771cb0ef41Sopenharmony_ci Node* from; 23781cb0ef41Sopenharmony_ci Node* to; 23791cb0ef41Sopenharmony_ci const char* name; 23801cb0ef41Sopenharmony_ci }; 23811cb0ef41Sopenharmony_ci 23821cb0ef41Sopenharmony_ci class V8NodeImpl : public Node { 23831cb0ef41Sopenharmony_ci public: 23841cb0ef41Sopenharmony_ci explicit V8NodeImpl(Object object) : object_(object) {} 23851cb0ef41Sopenharmony_ci Object GetObject() { return object_; } 23861cb0ef41Sopenharmony_ci 23871cb0ef41Sopenharmony_ci // Node overrides. 23881cb0ef41Sopenharmony_ci bool IsEmbedderNode() override { return false; } 23891cb0ef41Sopenharmony_ci const char* Name() override { 23901cb0ef41Sopenharmony_ci // The name should be retrieved via GetObject(). 23911cb0ef41Sopenharmony_ci UNREACHABLE(); 23921cb0ef41Sopenharmony_ci } 23931cb0ef41Sopenharmony_ci size_t SizeInBytes() override { 23941cb0ef41Sopenharmony_ci // The size should be retrieved via GetObject(). 23951cb0ef41Sopenharmony_ci UNREACHABLE(); 23961cb0ef41Sopenharmony_ci } 23971cb0ef41Sopenharmony_ci 23981cb0ef41Sopenharmony_ci private: 23991cb0ef41Sopenharmony_ci Object object_; 24001cb0ef41Sopenharmony_ci }; 24011cb0ef41Sopenharmony_ci 24021cb0ef41Sopenharmony_ci Node* V8Node(const v8::Local<v8::Value>& value) final { 24031cb0ef41Sopenharmony_ci Handle<Object> object = v8::Utils::OpenHandle(*value); 24041cb0ef41Sopenharmony_ci DCHECK(!object.is_null()); 24051cb0ef41Sopenharmony_ci return AddNode(std::unique_ptr<Node>(new V8NodeImpl(*object))); 24061cb0ef41Sopenharmony_ci } 24071cb0ef41Sopenharmony_ci 24081cb0ef41Sopenharmony_ci Node* AddNode(std::unique_ptr<Node> node) final { 24091cb0ef41Sopenharmony_ci Node* result = node.get(); 24101cb0ef41Sopenharmony_ci nodes_.push_back(std::move(node)); 24111cb0ef41Sopenharmony_ci return result; 24121cb0ef41Sopenharmony_ci } 24131cb0ef41Sopenharmony_ci 24141cb0ef41Sopenharmony_ci void AddEdge(Node* from, Node* to, const char* name) final { 24151cb0ef41Sopenharmony_ci edges_.push_back({from, to, name}); 24161cb0ef41Sopenharmony_ci } 24171cb0ef41Sopenharmony_ci 24181cb0ef41Sopenharmony_ci const std::vector<std::unique_ptr<Node>>& nodes() { return nodes_; } 24191cb0ef41Sopenharmony_ci const std::vector<Edge>& edges() { return edges_; } 24201cb0ef41Sopenharmony_ci 24211cb0ef41Sopenharmony_ci private: 24221cb0ef41Sopenharmony_ci std::vector<std::unique_ptr<Node>> nodes_; 24231cb0ef41Sopenharmony_ci std::vector<Edge> edges_; 24241cb0ef41Sopenharmony_ci}; 24251cb0ef41Sopenharmony_ci 24261cb0ef41Sopenharmony_ciclass EmbedderGraphEntriesAllocator : public HeapEntriesAllocator { 24271cb0ef41Sopenharmony_ci public: 24281cb0ef41Sopenharmony_ci explicit EmbedderGraphEntriesAllocator(HeapSnapshot* snapshot) 24291cb0ef41Sopenharmony_ci : snapshot_(snapshot), 24301cb0ef41Sopenharmony_ci names_(snapshot_->profiler()->names()), 24311cb0ef41Sopenharmony_ci heap_object_map_(snapshot_->profiler()->heap_object_map()) {} 24321cb0ef41Sopenharmony_ci HeapEntry* AllocateEntry(HeapThing ptr) override; 24331cb0ef41Sopenharmony_ci HeapEntry* AllocateEntry(Smi smi) override; 24341cb0ef41Sopenharmony_ci 24351cb0ef41Sopenharmony_ci private: 24361cb0ef41Sopenharmony_ci HeapSnapshot* snapshot_; 24371cb0ef41Sopenharmony_ci StringsStorage* names_; 24381cb0ef41Sopenharmony_ci HeapObjectsMap* heap_object_map_; 24391cb0ef41Sopenharmony_ci}; 24401cb0ef41Sopenharmony_ci 24411cb0ef41Sopenharmony_cinamespace { 24421cb0ef41Sopenharmony_ci 24431cb0ef41Sopenharmony_ciconst char* EmbedderGraphNodeName(StringsStorage* names, 24441cb0ef41Sopenharmony_ci EmbedderGraphImpl::Node* node) { 24451cb0ef41Sopenharmony_ci const char* prefix = node->NamePrefix(); 24461cb0ef41Sopenharmony_ci return prefix ? names->GetFormatted("%s %s", prefix, node->Name()) 24471cb0ef41Sopenharmony_ci : names->GetCopy(node->Name()); 24481cb0ef41Sopenharmony_ci} 24491cb0ef41Sopenharmony_ci 24501cb0ef41Sopenharmony_ciHeapEntry::Type EmbedderGraphNodeType(EmbedderGraphImpl::Node* node) { 24511cb0ef41Sopenharmony_ci return node->IsRootNode() ? HeapEntry::kSynthetic : HeapEntry::kNative; 24521cb0ef41Sopenharmony_ci} 24531cb0ef41Sopenharmony_ci 24541cb0ef41Sopenharmony_ci// Merges the names of an embedder node and its wrapper node. 24551cb0ef41Sopenharmony_ci// If the wrapper node name contains a tag suffix (part after '/') then the 24561cb0ef41Sopenharmony_ci// result is the embedder node name concatenated with the tag suffix. 24571cb0ef41Sopenharmony_ci// Otherwise, the result is the embedder node name. 24581cb0ef41Sopenharmony_ciconst char* MergeNames(StringsStorage* names, const char* embedder_name, 24591cb0ef41Sopenharmony_ci const char* wrapper_name) { 24601cb0ef41Sopenharmony_ci const char* suffix = strchr(wrapper_name, '/'); 24611cb0ef41Sopenharmony_ci return suffix ? names->GetFormatted("%s %s", embedder_name, suffix) 24621cb0ef41Sopenharmony_ci : embedder_name; 24631cb0ef41Sopenharmony_ci} 24641cb0ef41Sopenharmony_ci 24651cb0ef41Sopenharmony_ci} // anonymous namespace 24661cb0ef41Sopenharmony_ci 24671cb0ef41Sopenharmony_ciHeapEntry* EmbedderGraphEntriesAllocator::AllocateEntry(HeapThing ptr) { 24681cb0ef41Sopenharmony_ci EmbedderGraphImpl::Node* node = 24691cb0ef41Sopenharmony_ci reinterpret_cast<EmbedderGraphImpl::Node*>(ptr); 24701cb0ef41Sopenharmony_ci DCHECK(node->IsEmbedderNode()); 24711cb0ef41Sopenharmony_ci size_t size = node->SizeInBytes(); 24721cb0ef41Sopenharmony_ci Address lookup_address = reinterpret_cast<Address>(node->GetNativeObject()); 24731cb0ef41Sopenharmony_ci SnapshotObjectId id = 24741cb0ef41Sopenharmony_ci (lookup_address) ? heap_object_map_->FindOrAddEntry(lookup_address, 0) 24751cb0ef41Sopenharmony_ci : static_cast<SnapshotObjectId>( 24761cb0ef41Sopenharmony_ci reinterpret_cast<uintptr_t>(node) << 1); 24771cb0ef41Sopenharmony_ci auto* heap_entry = snapshot_->AddEntry(EmbedderGraphNodeType(node), 24781cb0ef41Sopenharmony_ci EmbedderGraphNodeName(names_, node), 24791cb0ef41Sopenharmony_ci id, static_cast<int>(size), 0); 24801cb0ef41Sopenharmony_ci heap_entry->set_detachedness(node->GetDetachedness()); 24811cb0ef41Sopenharmony_ci return heap_entry; 24821cb0ef41Sopenharmony_ci} 24831cb0ef41Sopenharmony_ci 24841cb0ef41Sopenharmony_ciHeapEntry* EmbedderGraphEntriesAllocator::AllocateEntry(Smi smi) { 24851cb0ef41Sopenharmony_ci DCHECK(false); 24861cb0ef41Sopenharmony_ci return nullptr; 24871cb0ef41Sopenharmony_ci} 24881cb0ef41Sopenharmony_ci 24891cb0ef41Sopenharmony_ciNativeObjectsExplorer::NativeObjectsExplorer( 24901cb0ef41Sopenharmony_ci HeapSnapshot* snapshot, SnapshottingProgressReportingInterface* progress) 24911cb0ef41Sopenharmony_ci : isolate_( 24921cb0ef41Sopenharmony_ci Isolate::FromHeap(snapshot->profiler()->heap_object_map()->heap())), 24931cb0ef41Sopenharmony_ci snapshot_(snapshot), 24941cb0ef41Sopenharmony_ci names_(snapshot_->profiler()->names()), 24951cb0ef41Sopenharmony_ci heap_object_map_(snapshot_->profiler()->heap_object_map()), 24961cb0ef41Sopenharmony_ci embedder_graph_entries_allocator_( 24971cb0ef41Sopenharmony_ci new EmbedderGraphEntriesAllocator(snapshot)) {} 24981cb0ef41Sopenharmony_ci 24991cb0ef41Sopenharmony_civoid NativeObjectsExplorer::MergeNodeIntoEntry( 25001cb0ef41Sopenharmony_ci HeapEntry* entry, EmbedderGraph::Node* original_node, 25011cb0ef41Sopenharmony_ci EmbedderGraph::Node* wrapper_node) { 25021cb0ef41Sopenharmony_ci // The wrapper node may be an embedder node (for testing purposes) or a V8 25031cb0ef41Sopenharmony_ci // node (production code). 25041cb0ef41Sopenharmony_ci if (!wrapper_node->IsEmbedderNode()) { 25051cb0ef41Sopenharmony_ci // For V8 nodes only we can add a lookup. 25061cb0ef41Sopenharmony_ci EmbedderGraphImpl::V8NodeImpl* v8_node = 25071cb0ef41Sopenharmony_ci static_cast<EmbedderGraphImpl::V8NodeImpl*>(wrapper_node); 25081cb0ef41Sopenharmony_ci Object object = v8_node->GetObject(); 25091cb0ef41Sopenharmony_ci DCHECK(!object.IsSmi()); 25101cb0ef41Sopenharmony_ci if (original_node->GetNativeObject()) { 25111cb0ef41Sopenharmony_ci HeapObject heap_object = HeapObject::cast(object); 25121cb0ef41Sopenharmony_ci heap_object_map_->AddMergedNativeEntry(original_node->GetNativeObject(), 25131cb0ef41Sopenharmony_ci heap_object.address()); 25141cb0ef41Sopenharmony_ci DCHECK_EQ(entry->id(), heap_object_map_->FindMergedNativeEntry( 25151cb0ef41Sopenharmony_ci original_node->GetNativeObject())); 25161cb0ef41Sopenharmony_ci } 25171cb0ef41Sopenharmony_ci } 25181cb0ef41Sopenharmony_ci entry->set_detachedness(original_node->GetDetachedness()); 25191cb0ef41Sopenharmony_ci entry->set_name(MergeNames( 25201cb0ef41Sopenharmony_ci names_, EmbedderGraphNodeName(names_, original_node), entry->name())); 25211cb0ef41Sopenharmony_ci entry->set_type(EmbedderGraphNodeType(original_node)); 25221cb0ef41Sopenharmony_ci DCHECK_GE(entry->self_size() + original_node->SizeInBytes(), 25231cb0ef41Sopenharmony_ci entry->self_size()); 25241cb0ef41Sopenharmony_ci entry->add_self_size(original_node->SizeInBytes()); 25251cb0ef41Sopenharmony_ci} 25261cb0ef41Sopenharmony_ci 25271cb0ef41Sopenharmony_ciHeapEntry* NativeObjectsExplorer::EntryForEmbedderGraphNode( 25281cb0ef41Sopenharmony_ci EmbedderGraphImpl::Node* node) { 25291cb0ef41Sopenharmony_ci // Return the entry for the wrapper node if present. 25301cb0ef41Sopenharmony_ci if (node->WrapperNode()) { 25311cb0ef41Sopenharmony_ci node = node->WrapperNode(); 25321cb0ef41Sopenharmony_ci } 25331cb0ef41Sopenharmony_ci // Node is EmbedderNode. 25341cb0ef41Sopenharmony_ci if (node->IsEmbedderNode()) { 25351cb0ef41Sopenharmony_ci return generator_->FindOrAddEntry(node, 25361cb0ef41Sopenharmony_ci embedder_graph_entries_allocator_.get()); 25371cb0ef41Sopenharmony_ci } 25381cb0ef41Sopenharmony_ci // Node is V8NodeImpl. 25391cb0ef41Sopenharmony_ci Object object = 25401cb0ef41Sopenharmony_ci static_cast<EmbedderGraphImpl::V8NodeImpl*>(node)->GetObject(); 25411cb0ef41Sopenharmony_ci if (object.IsSmi()) return nullptr; 25421cb0ef41Sopenharmony_ci auto* entry = generator_->FindEntry( 25431cb0ef41Sopenharmony_ci reinterpret_cast<void*>(Object::cast(object).ptr())); 25441cb0ef41Sopenharmony_ci return entry; 25451cb0ef41Sopenharmony_ci} 25461cb0ef41Sopenharmony_ci 25471cb0ef41Sopenharmony_cibool NativeObjectsExplorer::IterateAndExtractReferences( 25481cb0ef41Sopenharmony_ci HeapSnapshotGenerator* generator) { 25491cb0ef41Sopenharmony_ci generator_ = generator; 25501cb0ef41Sopenharmony_ci 25511cb0ef41Sopenharmony_ci if (FLAG_heap_profiler_use_embedder_graph && 25521cb0ef41Sopenharmony_ci snapshot_->profiler()->HasBuildEmbedderGraphCallback()) { 25531cb0ef41Sopenharmony_ci v8::HandleScope scope(reinterpret_cast<v8::Isolate*>(isolate_)); 25541cb0ef41Sopenharmony_ci DisallowGarbageCollection no_gc; 25551cb0ef41Sopenharmony_ci EmbedderGraphImpl graph; 25561cb0ef41Sopenharmony_ci snapshot_->profiler()->BuildEmbedderGraph(isolate_, &graph); 25571cb0ef41Sopenharmony_ci for (const auto& node : graph.nodes()) { 25581cb0ef41Sopenharmony_ci // Only add embedder nodes as V8 nodes have been added already by the 25591cb0ef41Sopenharmony_ci // V8HeapExplorer. 25601cb0ef41Sopenharmony_ci if (!node->IsEmbedderNode()) continue; 25611cb0ef41Sopenharmony_ci 25621cb0ef41Sopenharmony_ci if (auto* entry = EntryForEmbedderGraphNode(node.get())) { 25631cb0ef41Sopenharmony_ci if (node->IsRootNode()) { 25641cb0ef41Sopenharmony_ci snapshot_->root()->SetIndexedAutoIndexReference( 25651cb0ef41Sopenharmony_ci HeapGraphEdge::kElement, entry, generator_, 25661cb0ef41Sopenharmony_ci HeapEntry::kOffHeapPointer); 25671cb0ef41Sopenharmony_ci } 25681cb0ef41Sopenharmony_ci if (node->WrapperNode()) { 25691cb0ef41Sopenharmony_ci MergeNodeIntoEntry(entry, node.get(), node->WrapperNode()); 25701cb0ef41Sopenharmony_ci } 25711cb0ef41Sopenharmony_ci } 25721cb0ef41Sopenharmony_ci } 25731cb0ef41Sopenharmony_ci // Fill edges of the graph. 25741cb0ef41Sopenharmony_ci for (const auto& edge : graph.edges()) { 25751cb0ef41Sopenharmony_ci // |from| and |to| can be nullptr if the corresponding node is a V8 node 25761cb0ef41Sopenharmony_ci // pointing to a Smi. 25771cb0ef41Sopenharmony_ci HeapEntry* from = EntryForEmbedderGraphNode(edge.from); 25781cb0ef41Sopenharmony_ci if (!from) continue; 25791cb0ef41Sopenharmony_ci HeapEntry* to = EntryForEmbedderGraphNode(edge.to); 25801cb0ef41Sopenharmony_ci if (!to) continue; 25811cb0ef41Sopenharmony_ci if (edge.name == nullptr) { 25821cb0ef41Sopenharmony_ci from->SetIndexedAutoIndexReference(HeapGraphEdge::kElement, to, 25831cb0ef41Sopenharmony_ci generator_, 25841cb0ef41Sopenharmony_ci HeapEntry::kOffHeapPointer); 25851cb0ef41Sopenharmony_ci } else { 25861cb0ef41Sopenharmony_ci from->SetNamedReference(HeapGraphEdge::kInternal, 25871cb0ef41Sopenharmony_ci names_->GetCopy(edge.name), to, generator_, 25881cb0ef41Sopenharmony_ci HeapEntry::kOffHeapPointer); 25891cb0ef41Sopenharmony_ci } 25901cb0ef41Sopenharmony_ci } 25911cb0ef41Sopenharmony_ci } 25921cb0ef41Sopenharmony_ci generator_ = nullptr; 25931cb0ef41Sopenharmony_ci return true; 25941cb0ef41Sopenharmony_ci} 25951cb0ef41Sopenharmony_ci 25961cb0ef41Sopenharmony_ciHeapSnapshotGenerator::HeapSnapshotGenerator( 25971cb0ef41Sopenharmony_ci HeapSnapshot* snapshot, v8::ActivityControl* control, 25981cb0ef41Sopenharmony_ci v8::HeapProfiler::ObjectNameResolver* resolver, Heap* heap) 25991cb0ef41Sopenharmony_ci : snapshot_(snapshot), 26001cb0ef41Sopenharmony_ci control_(control), 26011cb0ef41Sopenharmony_ci v8_heap_explorer_(snapshot_, this, resolver), 26021cb0ef41Sopenharmony_ci dom_explorer_(snapshot_, this), 26031cb0ef41Sopenharmony_ci heap_(heap) {} 26041cb0ef41Sopenharmony_ci 26051cb0ef41Sopenharmony_cinamespace { 26061cb0ef41Sopenharmony_ciclass V8_NODISCARD NullContextForSnapshotScope { 26071cb0ef41Sopenharmony_ci public: 26081cb0ef41Sopenharmony_ci explicit NullContextForSnapshotScope(Isolate* isolate) 26091cb0ef41Sopenharmony_ci : isolate_(isolate), prev_(isolate->context()) { 26101cb0ef41Sopenharmony_ci isolate_->set_context(Context()); 26111cb0ef41Sopenharmony_ci } 26121cb0ef41Sopenharmony_ci ~NullContextForSnapshotScope() { isolate_->set_context(prev_); } 26131cb0ef41Sopenharmony_ci 26141cb0ef41Sopenharmony_ci private: 26151cb0ef41Sopenharmony_ci Isolate* isolate_; 26161cb0ef41Sopenharmony_ci Context prev_; 26171cb0ef41Sopenharmony_ci}; 26181cb0ef41Sopenharmony_ci} // namespace 26191cb0ef41Sopenharmony_ci 26201cb0ef41Sopenharmony_cibool HeapSnapshotGenerator::GenerateSnapshot() { 26211cb0ef41Sopenharmony_ci Isolate* isolate = Isolate::FromHeap(heap_); 26221cb0ef41Sopenharmony_ci base::Optional<HandleScope> handle_scope(base::in_place, isolate); 26231cb0ef41Sopenharmony_ci v8_heap_explorer_.CollectGlobalObjectsTags(); 26241cb0ef41Sopenharmony_ci 26251cb0ef41Sopenharmony_ci heap_->CollectAllAvailableGarbage(GarbageCollectionReason::kHeapProfiler); 26261cb0ef41Sopenharmony_ci 26271cb0ef41Sopenharmony_ci NullContextForSnapshotScope null_context_scope(isolate); 26281cb0ef41Sopenharmony_ci SafepointScope scope(heap_); 26291cb0ef41Sopenharmony_ci v8_heap_explorer_.MakeGlobalObjectTagMap(scope); 26301cb0ef41Sopenharmony_ci handle_scope.reset(); 26311cb0ef41Sopenharmony_ci 26321cb0ef41Sopenharmony_ci#ifdef VERIFY_HEAP 26331cb0ef41Sopenharmony_ci Heap* debug_heap = heap_; 26341cb0ef41Sopenharmony_ci if (FLAG_verify_heap) { 26351cb0ef41Sopenharmony_ci debug_heap->Verify(); 26361cb0ef41Sopenharmony_ci } 26371cb0ef41Sopenharmony_ci#endif 26381cb0ef41Sopenharmony_ci 26391cb0ef41Sopenharmony_ci InitProgressCounter(); 26401cb0ef41Sopenharmony_ci 26411cb0ef41Sopenharmony_ci#ifdef VERIFY_HEAP 26421cb0ef41Sopenharmony_ci if (FLAG_verify_heap) { 26431cb0ef41Sopenharmony_ci debug_heap->Verify(); 26441cb0ef41Sopenharmony_ci } 26451cb0ef41Sopenharmony_ci#endif 26461cb0ef41Sopenharmony_ci 26471cb0ef41Sopenharmony_ci snapshot_->AddSyntheticRootEntries(); 26481cb0ef41Sopenharmony_ci 26491cb0ef41Sopenharmony_ci if (!FillReferences()) return false; 26501cb0ef41Sopenharmony_ci 26511cb0ef41Sopenharmony_ci snapshot_->FillChildren(); 26521cb0ef41Sopenharmony_ci snapshot_->RememberLastJSObjectId(); 26531cb0ef41Sopenharmony_ci 26541cb0ef41Sopenharmony_ci progress_counter_ = progress_total_; 26551cb0ef41Sopenharmony_ci if (!ProgressReport(true)) return false; 26561cb0ef41Sopenharmony_ci return true; 26571cb0ef41Sopenharmony_ci} 26581cb0ef41Sopenharmony_ci 26591cb0ef41Sopenharmony_civoid HeapSnapshotGenerator::ProgressStep() { 26601cb0ef41Sopenharmony_ci // Only increment the progress_counter_ until 26611cb0ef41Sopenharmony_ci // equal to progress_total -1 == progress_counter. 26621cb0ef41Sopenharmony_ci // This ensures that intermediate ProgressReport calls will never signal 26631cb0ef41Sopenharmony_ci // that the work is finished (i.e. progress_counter_ == progress_total_). 26641cb0ef41Sopenharmony_ci // Only the forced ProgressReport() at the end of GenerateSnapshot() should, 26651cb0ef41Sopenharmony_ci // after setting progress_counter_ = progress_total_, signal that the 26661cb0ef41Sopenharmony_ci // work is finished because signalling finished twice 26671cb0ef41Sopenharmony_ci // breaks the DevTools frontend. 26681cb0ef41Sopenharmony_ci if (control_ != nullptr && progress_total_ > progress_counter_ + 1) { 26691cb0ef41Sopenharmony_ci ++progress_counter_; 26701cb0ef41Sopenharmony_ci } 26711cb0ef41Sopenharmony_ci} 26721cb0ef41Sopenharmony_ci 26731cb0ef41Sopenharmony_cibool HeapSnapshotGenerator::ProgressReport(bool force) { 26741cb0ef41Sopenharmony_ci const int kProgressReportGranularity = 10000; 26751cb0ef41Sopenharmony_ci if (control_ != nullptr && 26761cb0ef41Sopenharmony_ci (force || progress_counter_ % kProgressReportGranularity == 0)) { 26771cb0ef41Sopenharmony_ci return control_->ReportProgressValue(progress_counter_, progress_total_) == 26781cb0ef41Sopenharmony_ci v8::ActivityControl::kContinue; 26791cb0ef41Sopenharmony_ci } 26801cb0ef41Sopenharmony_ci return true; 26811cb0ef41Sopenharmony_ci} 26821cb0ef41Sopenharmony_ci 26831cb0ef41Sopenharmony_civoid HeapSnapshotGenerator::InitProgressCounter() { 26841cb0ef41Sopenharmony_ci if (control_ == nullptr) return; 26851cb0ef41Sopenharmony_ci progress_total_ = v8_heap_explorer_.EstimateObjectsCount(); 26861cb0ef41Sopenharmony_ci progress_counter_ = 0; 26871cb0ef41Sopenharmony_ci} 26881cb0ef41Sopenharmony_ci 26891cb0ef41Sopenharmony_cibool HeapSnapshotGenerator::FillReferences() { 26901cb0ef41Sopenharmony_ci return v8_heap_explorer_.IterateAndExtractReferences(this) && 26911cb0ef41Sopenharmony_ci dom_explorer_.IterateAndExtractReferences(this); 26921cb0ef41Sopenharmony_ci} 26931cb0ef41Sopenharmony_ci 26941cb0ef41Sopenharmony_ci// type, name|index, to_node. 26951cb0ef41Sopenharmony_ciconst int HeapSnapshotJSONSerializer::kEdgeFieldsCount = 3; 26961cb0ef41Sopenharmony_ci// type, name, id, self_size, edge_count, trace_node_id, detachedness. 26971cb0ef41Sopenharmony_ciconst int HeapSnapshotJSONSerializer::kNodeFieldsCount = 7; 26981cb0ef41Sopenharmony_ci 26991cb0ef41Sopenharmony_civoid HeapSnapshotJSONSerializer::Serialize(v8::OutputStream* stream) { 27001cb0ef41Sopenharmony_ci if (AllocationTracker* allocation_tracker = 27011cb0ef41Sopenharmony_ci snapshot_->profiler()->allocation_tracker()) { 27021cb0ef41Sopenharmony_ci allocation_tracker->PrepareForSerialization(); 27031cb0ef41Sopenharmony_ci } 27041cb0ef41Sopenharmony_ci DCHECK_NULL(writer_); 27051cb0ef41Sopenharmony_ci writer_ = new OutputStreamWriter(stream); 27061cb0ef41Sopenharmony_ci SerializeImpl(); 27071cb0ef41Sopenharmony_ci delete writer_; 27081cb0ef41Sopenharmony_ci writer_ = nullptr; 27091cb0ef41Sopenharmony_ci} 27101cb0ef41Sopenharmony_ci 27111cb0ef41Sopenharmony_ci 27121cb0ef41Sopenharmony_civoid HeapSnapshotJSONSerializer::SerializeImpl() { 27131cb0ef41Sopenharmony_ci DCHECK_EQ(0, snapshot_->root()->index()); 27141cb0ef41Sopenharmony_ci writer_->AddCharacter('{'); 27151cb0ef41Sopenharmony_ci writer_->AddString("\"snapshot\":{"); 27161cb0ef41Sopenharmony_ci SerializeSnapshot(); 27171cb0ef41Sopenharmony_ci if (writer_->aborted()) return; 27181cb0ef41Sopenharmony_ci writer_->AddString("},\n"); 27191cb0ef41Sopenharmony_ci writer_->AddString("\"nodes\":["); 27201cb0ef41Sopenharmony_ci SerializeNodes(); 27211cb0ef41Sopenharmony_ci if (writer_->aborted()) return; 27221cb0ef41Sopenharmony_ci writer_->AddString("],\n"); 27231cb0ef41Sopenharmony_ci writer_->AddString("\"edges\":["); 27241cb0ef41Sopenharmony_ci SerializeEdges(); 27251cb0ef41Sopenharmony_ci if (writer_->aborted()) return; 27261cb0ef41Sopenharmony_ci writer_->AddString("],\n"); 27271cb0ef41Sopenharmony_ci 27281cb0ef41Sopenharmony_ci writer_->AddString("\"trace_function_infos\":["); 27291cb0ef41Sopenharmony_ci SerializeTraceNodeInfos(); 27301cb0ef41Sopenharmony_ci if (writer_->aborted()) return; 27311cb0ef41Sopenharmony_ci writer_->AddString("],\n"); 27321cb0ef41Sopenharmony_ci writer_->AddString("\"trace_tree\":["); 27331cb0ef41Sopenharmony_ci SerializeTraceTree(); 27341cb0ef41Sopenharmony_ci if (writer_->aborted()) return; 27351cb0ef41Sopenharmony_ci writer_->AddString("],\n"); 27361cb0ef41Sopenharmony_ci 27371cb0ef41Sopenharmony_ci writer_->AddString("\"samples\":["); 27381cb0ef41Sopenharmony_ci SerializeSamples(); 27391cb0ef41Sopenharmony_ci if (writer_->aborted()) return; 27401cb0ef41Sopenharmony_ci writer_->AddString("],\n"); 27411cb0ef41Sopenharmony_ci 27421cb0ef41Sopenharmony_ci writer_->AddString("\"locations\":["); 27431cb0ef41Sopenharmony_ci SerializeLocations(); 27441cb0ef41Sopenharmony_ci if (writer_->aborted()) return; 27451cb0ef41Sopenharmony_ci writer_->AddString("],\n"); 27461cb0ef41Sopenharmony_ci 27471cb0ef41Sopenharmony_ci writer_->AddString("\"strings\":["); 27481cb0ef41Sopenharmony_ci SerializeStrings(); 27491cb0ef41Sopenharmony_ci if (writer_->aborted()) return; 27501cb0ef41Sopenharmony_ci writer_->AddCharacter(']'); 27511cb0ef41Sopenharmony_ci writer_->AddCharacter('}'); 27521cb0ef41Sopenharmony_ci writer_->Finalize(); 27531cb0ef41Sopenharmony_ci} 27541cb0ef41Sopenharmony_ci 27551cb0ef41Sopenharmony_ci 27561cb0ef41Sopenharmony_ciint HeapSnapshotJSONSerializer::GetStringId(const char* s) { 27571cb0ef41Sopenharmony_ci base::HashMap::Entry* cache_entry = 27581cb0ef41Sopenharmony_ci strings_.LookupOrInsert(const_cast<char*>(s), StringHash(s)); 27591cb0ef41Sopenharmony_ci if (cache_entry->value == nullptr) { 27601cb0ef41Sopenharmony_ci cache_entry->value = reinterpret_cast<void*>(next_string_id_++); 27611cb0ef41Sopenharmony_ci } 27621cb0ef41Sopenharmony_ci return static_cast<int>(reinterpret_cast<intptr_t>(cache_entry->value)); 27631cb0ef41Sopenharmony_ci} 27641cb0ef41Sopenharmony_ci 27651cb0ef41Sopenharmony_ci 27661cb0ef41Sopenharmony_cinamespace { 27671cb0ef41Sopenharmony_ci 27681cb0ef41Sopenharmony_citemplate<size_t size> struct ToUnsigned; 27691cb0ef41Sopenharmony_ci 27701cb0ef41Sopenharmony_citemplate <> 27711cb0ef41Sopenharmony_cistruct ToUnsigned<1> { 27721cb0ef41Sopenharmony_ci using Type = uint8_t; 27731cb0ef41Sopenharmony_ci}; 27741cb0ef41Sopenharmony_ci 27751cb0ef41Sopenharmony_citemplate<> struct ToUnsigned<4> { 27761cb0ef41Sopenharmony_ci using Type = uint32_t; 27771cb0ef41Sopenharmony_ci}; 27781cb0ef41Sopenharmony_ci 27791cb0ef41Sopenharmony_citemplate<> struct ToUnsigned<8> { 27801cb0ef41Sopenharmony_ci using Type = uint64_t; 27811cb0ef41Sopenharmony_ci}; 27821cb0ef41Sopenharmony_ci 27831cb0ef41Sopenharmony_ci} // namespace 27841cb0ef41Sopenharmony_ci 27851cb0ef41Sopenharmony_citemplate <typename T> 27861cb0ef41Sopenharmony_cistatic int utoa_impl(T value, const base::Vector<char>& buffer, 27871cb0ef41Sopenharmony_ci int buffer_pos) { 27881cb0ef41Sopenharmony_ci STATIC_ASSERT(static_cast<T>(-1) > 0); // Check that T is unsigned 27891cb0ef41Sopenharmony_ci int number_of_digits = 0; 27901cb0ef41Sopenharmony_ci T t = value; 27911cb0ef41Sopenharmony_ci do { 27921cb0ef41Sopenharmony_ci ++number_of_digits; 27931cb0ef41Sopenharmony_ci } while (t /= 10); 27941cb0ef41Sopenharmony_ci 27951cb0ef41Sopenharmony_ci buffer_pos += number_of_digits; 27961cb0ef41Sopenharmony_ci int result = buffer_pos; 27971cb0ef41Sopenharmony_ci do { 27981cb0ef41Sopenharmony_ci int last_digit = static_cast<int>(value % 10); 27991cb0ef41Sopenharmony_ci buffer[--buffer_pos] = '0' + last_digit; 28001cb0ef41Sopenharmony_ci value /= 10; 28011cb0ef41Sopenharmony_ci } while (value); 28021cb0ef41Sopenharmony_ci return result; 28031cb0ef41Sopenharmony_ci} 28041cb0ef41Sopenharmony_ci 28051cb0ef41Sopenharmony_citemplate <typename T> 28061cb0ef41Sopenharmony_cistatic int utoa(T value, const base::Vector<char>& buffer, int buffer_pos) { 28071cb0ef41Sopenharmony_ci typename ToUnsigned<sizeof(value)>::Type unsigned_value = value; 28081cb0ef41Sopenharmony_ci STATIC_ASSERT(sizeof(value) == sizeof(unsigned_value)); 28091cb0ef41Sopenharmony_ci return utoa_impl(unsigned_value, buffer, buffer_pos); 28101cb0ef41Sopenharmony_ci} 28111cb0ef41Sopenharmony_ci 28121cb0ef41Sopenharmony_civoid HeapSnapshotJSONSerializer::SerializeEdge(HeapGraphEdge* edge, 28131cb0ef41Sopenharmony_ci bool first_edge) { 28141cb0ef41Sopenharmony_ci // The buffer needs space for 3 unsigned ints, 3 commas, \n and \0 28151cb0ef41Sopenharmony_ci static const int kBufferSize = 28161cb0ef41Sopenharmony_ci MaxDecimalDigitsIn<sizeof(unsigned)>::kUnsigned * 3 + 3 + 2; 28171cb0ef41Sopenharmony_ci base::EmbeddedVector<char, kBufferSize> buffer; 28181cb0ef41Sopenharmony_ci int edge_name_or_index = edge->type() == HeapGraphEdge::kElement 28191cb0ef41Sopenharmony_ci || edge->type() == HeapGraphEdge::kHidden 28201cb0ef41Sopenharmony_ci ? edge->index() : GetStringId(edge->name()); 28211cb0ef41Sopenharmony_ci int buffer_pos = 0; 28221cb0ef41Sopenharmony_ci if (!first_edge) { 28231cb0ef41Sopenharmony_ci buffer[buffer_pos++] = ','; 28241cb0ef41Sopenharmony_ci } 28251cb0ef41Sopenharmony_ci buffer_pos = utoa(edge->type(), buffer, buffer_pos); 28261cb0ef41Sopenharmony_ci buffer[buffer_pos++] = ','; 28271cb0ef41Sopenharmony_ci buffer_pos = utoa(edge_name_or_index, buffer, buffer_pos); 28281cb0ef41Sopenharmony_ci buffer[buffer_pos++] = ','; 28291cb0ef41Sopenharmony_ci buffer_pos = utoa(to_node_index(edge->to()), buffer, buffer_pos); 28301cb0ef41Sopenharmony_ci buffer[buffer_pos++] = '\n'; 28311cb0ef41Sopenharmony_ci buffer[buffer_pos++] = '\0'; 28321cb0ef41Sopenharmony_ci writer_->AddString(buffer.begin()); 28331cb0ef41Sopenharmony_ci} 28341cb0ef41Sopenharmony_ci 28351cb0ef41Sopenharmony_civoid HeapSnapshotJSONSerializer::SerializeEdges() { 28361cb0ef41Sopenharmony_ci std::vector<HeapGraphEdge*>& edges = snapshot_->children(); 28371cb0ef41Sopenharmony_ci for (size_t i = 0; i < edges.size(); ++i) { 28381cb0ef41Sopenharmony_ci DCHECK(i == 0 || 28391cb0ef41Sopenharmony_ci edges[i - 1]->from()->index() <= edges[i]->from()->index()); 28401cb0ef41Sopenharmony_ci SerializeEdge(edges[i], i == 0); 28411cb0ef41Sopenharmony_ci if (writer_->aborted()) return; 28421cb0ef41Sopenharmony_ci } 28431cb0ef41Sopenharmony_ci} 28441cb0ef41Sopenharmony_ci 28451cb0ef41Sopenharmony_civoid HeapSnapshotJSONSerializer::SerializeNode(const HeapEntry* entry) { 28461cb0ef41Sopenharmony_ci // The buffer needs space for 5 unsigned ints, 1 size_t, 1 uint8_t, 7 commas, 28471cb0ef41Sopenharmony_ci // \n and \0 28481cb0ef41Sopenharmony_ci static const int kBufferSize = 28491cb0ef41Sopenharmony_ci 5 * MaxDecimalDigitsIn<sizeof(unsigned)>::kUnsigned + 28501cb0ef41Sopenharmony_ci MaxDecimalDigitsIn<sizeof(size_t)>::kUnsigned + 28511cb0ef41Sopenharmony_ci MaxDecimalDigitsIn<sizeof(uint8_t)>::kUnsigned + 7 + 1 + 1; 28521cb0ef41Sopenharmony_ci base::EmbeddedVector<char, kBufferSize> buffer; 28531cb0ef41Sopenharmony_ci int buffer_pos = 0; 28541cb0ef41Sopenharmony_ci if (to_node_index(entry) != 0) { 28551cb0ef41Sopenharmony_ci buffer[buffer_pos++] = ','; 28561cb0ef41Sopenharmony_ci } 28571cb0ef41Sopenharmony_ci buffer_pos = utoa(entry->type(), buffer, buffer_pos); 28581cb0ef41Sopenharmony_ci buffer[buffer_pos++] = ','; 28591cb0ef41Sopenharmony_ci buffer_pos = utoa(GetStringId(entry->name()), buffer, buffer_pos); 28601cb0ef41Sopenharmony_ci buffer[buffer_pos++] = ','; 28611cb0ef41Sopenharmony_ci buffer_pos = utoa(entry->id(), buffer, buffer_pos); 28621cb0ef41Sopenharmony_ci buffer[buffer_pos++] = ','; 28631cb0ef41Sopenharmony_ci buffer_pos = utoa(entry->self_size(), buffer, buffer_pos); 28641cb0ef41Sopenharmony_ci buffer[buffer_pos++] = ','; 28651cb0ef41Sopenharmony_ci buffer_pos = utoa(entry->children_count(), buffer, buffer_pos); 28661cb0ef41Sopenharmony_ci buffer[buffer_pos++] = ','; 28671cb0ef41Sopenharmony_ci buffer_pos = utoa(entry->trace_node_id(), buffer, buffer_pos); 28681cb0ef41Sopenharmony_ci buffer[buffer_pos++] = ','; 28691cb0ef41Sopenharmony_ci buffer_pos = utoa(entry->detachedness(), buffer, buffer_pos); 28701cb0ef41Sopenharmony_ci buffer[buffer_pos++] = '\n'; 28711cb0ef41Sopenharmony_ci buffer[buffer_pos++] = '\0'; 28721cb0ef41Sopenharmony_ci writer_->AddString(buffer.begin()); 28731cb0ef41Sopenharmony_ci} 28741cb0ef41Sopenharmony_ci 28751cb0ef41Sopenharmony_civoid HeapSnapshotJSONSerializer::SerializeNodes() { 28761cb0ef41Sopenharmony_ci const std::deque<HeapEntry>& entries = snapshot_->entries(); 28771cb0ef41Sopenharmony_ci for (const HeapEntry& entry : entries) { 28781cb0ef41Sopenharmony_ci SerializeNode(&entry); 28791cb0ef41Sopenharmony_ci if (writer_->aborted()) return; 28801cb0ef41Sopenharmony_ci } 28811cb0ef41Sopenharmony_ci} 28821cb0ef41Sopenharmony_ci 28831cb0ef41Sopenharmony_civoid HeapSnapshotJSONSerializer::SerializeSnapshot() { 28841cb0ef41Sopenharmony_ci writer_->AddString("\"meta\":"); 28851cb0ef41Sopenharmony_ci // The object describing node serialization layout. 28861cb0ef41Sopenharmony_ci // We use a set of macros to improve readability. 28871cb0ef41Sopenharmony_ci 28881cb0ef41Sopenharmony_ci// clang-format off 28891cb0ef41Sopenharmony_ci#define JSON_A(s) "[" s "]" 28901cb0ef41Sopenharmony_ci#define JSON_O(s) "{" s "}" 28911cb0ef41Sopenharmony_ci#define JSON_S(s) "\"" s "\"" 28921cb0ef41Sopenharmony_ci writer_->AddString(JSON_O( 28931cb0ef41Sopenharmony_ci JSON_S("node_fields") ":" JSON_A( 28941cb0ef41Sopenharmony_ci JSON_S("type") "," 28951cb0ef41Sopenharmony_ci JSON_S("name") "," 28961cb0ef41Sopenharmony_ci JSON_S("id") "," 28971cb0ef41Sopenharmony_ci JSON_S("self_size") "," 28981cb0ef41Sopenharmony_ci JSON_S("edge_count") "," 28991cb0ef41Sopenharmony_ci JSON_S("trace_node_id") "," 29001cb0ef41Sopenharmony_ci JSON_S("detachedness")) "," 29011cb0ef41Sopenharmony_ci JSON_S("node_types") ":" JSON_A( 29021cb0ef41Sopenharmony_ci JSON_A( 29031cb0ef41Sopenharmony_ci JSON_S("hidden") "," 29041cb0ef41Sopenharmony_ci JSON_S("array") "," 29051cb0ef41Sopenharmony_ci JSON_S("string") "," 29061cb0ef41Sopenharmony_ci JSON_S("object") "," 29071cb0ef41Sopenharmony_ci JSON_S("code") "," 29081cb0ef41Sopenharmony_ci JSON_S("closure") "," 29091cb0ef41Sopenharmony_ci JSON_S("regexp") "," 29101cb0ef41Sopenharmony_ci JSON_S("number") "," 29111cb0ef41Sopenharmony_ci JSON_S("native") "," 29121cb0ef41Sopenharmony_ci JSON_S("synthetic") "," 29131cb0ef41Sopenharmony_ci JSON_S("concatenated string") "," 29141cb0ef41Sopenharmony_ci JSON_S("sliced string") "," 29151cb0ef41Sopenharmony_ci JSON_S("symbol") "," 29161cb0ef41Sopenharmony_ci JSON_S("bigint")) "," 29171cb0ef41Sopenharmony_ci JSON_S("string") "," 29181cb0ef41Sopenharmony_ci JSON_S("number") "," 29191cb0ef41Sopenharmony_ci JSON_S("number") "," 29201cb0ef41Sopenharmony_ci JSON_S("number") "," 29211cb0ef41Sopenharmony_ci JSON_S("number") "," 29221cb0ef41Sopenharmony_ci JSON_S("number")) "," 29231cb0ef41Sopenharmony_ci JSON_S("edge_fields") ":" JSON_A( 29241cb0ef41Sopenharmony_ci JSON_S("type") "," 29251cb0ef41Sopenharmony_ci JSON_S("name_or_index") "," 29261cb0ef41Sopenharmony_ci JSON_S("to_node")) "," 29271cb0ef41Sopenharmony_ci JSON_S("edge_types") ":" JSON_A( 29281cb0ef41Sopenharmony_ci JSON_A( 29291cb0ef41Sopenharmony_ci JSON_S("context") "," 29301cb0ef41Sopenharmony_ci JSON_S("element") "," 29311cb0ef41Sopenharmony_ci JSON_S("property") "," 29321cb0ef41Sopenharmony_ci JSON_S("internal") "," 29331cb0ef41Sopenharmony_ci JSON_S("hidden") "," 29341cb0ef41Sopenharmony_ci JSON_S("shortcut") "," 29351cb0ef41Sopenharmony_ci JSON_S("weak")) "," 29361cb0ef41Sopenharmony_ci JSON_S("string_or_number") "," 29371cb0ef41Sopenharmony_ci JSON_S("node")) "," 29381cb0ef41Sopenharmony_ci JSON_S("trace_function_info_fields") ":" JSON_A( 29391cb0ef41Sopenharmony_ci JSON_S("function_id") "," 29401cb0ef41Sopenharmony_ci JSON_S("name") "," 29411cb0ef41Sopenharmony_ci JSON_S("script_name") "," 29421cb0ef41Sopenharmony_ci JSON_S("script_id") "," 29431cb0ef41Sopenharmony_ci JSON_S("line") "," 29441cb0ef41Sopenharmony_ci JSON_S("column")) "," 29451cb0ef41Sopenharmony_ci JSON_S("trace_node_fields") ":" JSON_A( 29461cb0ef41Sopenharmony_ci JSON_S("id") "," 29471cb0ef41Sopenharmony_ci JSON_S("function_info_index") "," 29481cb0ef41Sopenharmony_ci JSON_S("count") "," 29491cb0ef41Sopenharmony_ci JSON_S("size") "," 29501cb0ef41Sopenharmony_ci JSON_S("children")) "," 29511cb0ef41Sopenharmony_ci JSON_S("sample_fields") ":" JSON_A( 29521cb0ef41Sopenharmony_ci JSON_S("timestamp_us") "," 29531cb0ef41Sopenharmony_ci JSON_S("last_assigned_id")) "," 29541cb0ef41Sopenharmony_ci JSON_S("location_fields") ":" JSON_A( 29551cb0ef41Sopenharmony_ci JSON_S("object_index") "," 29561cb0ef41Sopenharmony_ci JSON_S("script_id") "," 29571cb0ef41Sopenharmony_ci JSON_S("line") "," 29581cb0ef41Sopenharmony_ci JSON_S("column")))); 29591cb0ef41Sopenharmony_ci// clang-format on 29601cb0ef41Sopenharmony_ci#undef JSON_S 29611cb0ef41Sopenharmony_ci#undef JSON_O 29621cb0ef41Sopenharmony_ci#undef JSON_A 29631cb0ef41Sopenharmony_ci writer_->AddString(",\"node_count\":"); 29641cb0ef41Sopenharmony_ci writer_->AddNumber(static_cast<unsigned>(snapshot_->entries().size())); 29651cb0ef41Sopenharmony_ci writer_->AddString(",\"edge_count\":"); 29661cb0ef41Sopenharmony_ci writer_->AddNumber(static_cast<double>(snapshot_->edges().size())); 29671cb0ef41Sopenharmony_ci writer_->AddString(",\"trace_function_count\":"); 29681cb0ef41Sopenharmony_ci uint32_t count = 0; 29691cb0ef41Sopenharmony_ci AllocationTracker* tracker = snapshot_->profiler()->allocation_tracker(); 29701cb0ef41Sopenharmony_ci if (tracker) { 29711cb0ef41Sopenharmony_ci count = static_cast<uint32_t>(tracker->function_info_list().size()); 29721cb0ef41Sopenharmony_ci } 29731cb0ef41Sopenharmony_ci writer_->AddNumber(count); 29741cb0ef41Sopenharmony_ci} 29751cb0ef41Sopenharmony_ci 29761cb0ef41Sopenharmony_ci 29771cb0ef41Sopenharmony_cistatic void WriteUChar(OutputStreamWriter* w, unibrow::uchar u) { 29781cb0ef41Sopenharmony_ci static const char hex_chars[] = "0123456789ABCDEF"; 29791cb0ef41Sopenharmony_ci w->AddString("\\u"); 29801cb0ef41Sopenharmony_ci w->AddCharacter(hex_chars[(u >> 12) & 0xF]); 29811cb0ef41Sopenharmony_ci w->AddCharacter(hex_chars[(u >> 8) & 0xF]); 29821cb0ef41Sopenharmony_ci w->AddCharacter(hex_chars[(u >> 4) & 0xF]); 29831cb0ef41Sopenharmony_ci w->AddCharacter(hex_chars[u & 0xF]); 29841cb0ef41Sopenharmony_ci} 29851cb0ef41Sopenharmony_ci 29861cb0ef41Sopenharmony_ci 29871cb0ef41Sopenharmony_civoid HeapSnapshotJSONSerializer::SerializeTraceTree() { 29881cb0ef41Sopenharmony_ci AllocationTracker* tracker = snapshot_->profiler()->allocation_tracker(); 29891cb0ef41Sopenharmony_ci if (!tracker) return; 29901cb0ef41Sopenharmony_ci AllocationTraceTree* traces = tracker->trace_tree(); 29911cb0ef41Sopenharmony_ci SerializeTraceNode(traces->root()); 29921cb0ef41Sopenharmony_ci} 29931cb0ef41Sopenharmony_ci 29941cb0ef41Sopenharmony_ci 29951cb0ef41Sopenharmony_civoid HeapSnapshotJSONSerializer::SerializeTraceNode(AllocationTraceNode* node) { 29961cb0ef41Sopenharmony_ci // The buffer needs space for 4 unsigned ints, 4 commas, [ and \0 29971cb0ef41Sopenharmony_ci const int kBufferSize = 29981cb0ef41Sopenharmony_ci 4 * MaxDecimalDigitsIn<sizeof(unsigned)>::kUnsigned + 4 + 1 + 1; 29991cb0ef41Sopenharmony_ci base::EmbeddedVector<char, kBufferSize> buffer; 30001cb0ef41Sopenharmony_ci int buffer_pos = 0; 30011cb0ef41Sopenharmony_ci buffer_pos = utoa(node->id(), buffer, buffer_pos); 30021cb0ef41Sopenharmony_ci buffer[buffer_pos++] = ','; 30031cb0ef41Sopenharmony_ci buffer_pos = utoa(node->function_info_index(), buffer, buffer_pos); 30041cb0ef41Sopenharmony_ci buffer[buffer_pos++] = ','; 30051cb0ef41Sopenharmony_ci buffer_pos = utoa(node->allocation_count(), buffer, buffer_pos); 30061cb0ef41Sopenharmony_ci buffer[buffer_pos++] = ','; 30071cb0ef41Sopenharmony_ci buffer_pos = utoa(node->allocation_size(), buffer, buffer_pos); 30081cb0ef41Sopenharmony_ci buffer[buffer_pos++] = ','; 30091cb0ef41Sopenharmony_ci buffer[buffer_pos++] = '['; 30101cb0ef41Sopenharmony_ci buffer[buffer_pos++] = '\0'; 30111cb0ef41Sopenharmony_ci writer_->AddString(buffer.begin()); 30121cb0ef41Sopenharmony_ci 30131cb0ef41Sopenharmony_ci int i = 0; 30141cb0ef41Sopenharmony_ci for (AllocationTraceNode* child : node->children()) { 30151cb0ef41Sopenharmony_ci if (i++ > 0) { 30161cb0ef41Sopenharmony_ci writer_->AddCharacter(','); 30171cb0ef41Sopenharmony_ci } 30181cb0ef41Sopenharmony_ci SerializeTraceNode(child); 30191cb0ef41Sopenharmony_ci } 30201cb0ef41Sopenharmony_ci writer_->AddCharacter(']'); 30211cb0ef41Sopenharmony_ci} 30221cb0ef41Sopenharmony_ci 30231cb0ef41Sopenharmony_ci 30241cb0ef41Sopenharmony_ci// 0-based position is converted to 1-based during the serialization. 30251cb0ef41Sopenharmony_cistatic int SerializePosition(int position, const base::Vector<char>& buffer, 30261cb0ef41Sopenharmony_ci int buffer_pos) { 30271cb0ef41Sopenharmony_ci if (position == -1) { 30281cb0ef41Sopenharmony_ci buffer[buffer_pos++] = '0'; 30291cb0ef41Sopenharmony_ci } else { 30301cb0ef41Sopenharmony_ci DCHECK_GE(position, 0); 30311cb0ef41Sopenharmony_ci buffer_pos = utoa(static_cast<unsigned>(position + 1), buffer, buffer_pos); 30321cb0ef41Sopenharmony_ci } 30331cb0ef41Sopenharmony_ci return buffer_pos; 30341cb0ef41Sopenharmony_ci} 30351cb0ef41Sopenharmony_ci 30361cb0ef41Sopenharmony_civoid HeapSnapshotJSONSerializer::SerializeTraceNodeInfos() { 30371cb0ef41Sopenharmony_ci AllocationTracker* tracker = snapshot_->profiler()->allocation_tracker(); 30381cb0ef41Sopenharmony_ci if (!tracker) return; 30391cb0ef41Sopenharmony_ci // The buffer needs space for 6 unsigned ints, 6 commas, \n and \0 30401cb0ef41Sopenharmony_ci const int kBufferSize = 30411cb0ef41Sopenharmony_ci 6 * MaxDecimalDigitsIn<sizeof(unsigned)>::kUnsigned + 6 + 1 + 1; 30421cb0ef41Sopenharmony_ci base::EmbeddedVector<char, kBufferSize> buffer; 30431cb0ef41Sopenharmony_ci int i = 0; 30441cb0ef41Sopenharmony_ci for (AllocationTracker::FunctionInfo* info : tracker->function_info_list()) { 30451cb0ef41Sopenharmony_ci int buffer_pos = 0; 30461cb0ef41Sopenharmony_ci if (i++ > 0) { 30471cb0ef41Sopenharmony_ci buffer[buffer_pos++] = ','; 30481cb0ef41Sopenharmony_ci } 30491cb0ef41Sopenharmony_ci buffer_pos = utoa(info->function_id, buffer, buffer_pos); 30501cb0ef41Sopenharmony_ci buffer[buffer_pos++] = ','; 30511cb0ef41Sopenharmony_ci buffer_pos = utoa(GetStringId(info->name), buffer, buffer_pos); 30521cb0ef41Sopenharmony_ci buffer[buffer_pos++] = ','; 30531cb0ef41Sopenharmony_ci buffer_pos = utoa(GetStringId(info->script_name), buffer, buffer_pos); 30541cb0ef41Sopenharmony_ci buffer[buffer_pos++] = ','; 30551cb0ef41Sopenharmony_ci // The cast is safe because script id is a non-negative Smi. 30561cb0ef41Sopenharmony_ci buffer_pos = utoa(static_cast<unsigned>(info->script_id), buffer, 30571cb0ef41Sopenharmony_ci buffer_pos); 30581cb0ef41Sopenharmony_ci buffer[buffer_pos++] = ','; 30591cb0ef41Sopenharmony_ci buffer_pos = SerializePosition(info->line, buffer, buffer_pos); 30601cb0ef41Sopenharmony_ci buffer[buffer_pos++] = ','; 30611cb0ef41Sopenharmony_ci buffer_pos = SerializePosition(info->column, buffer, buffer_pos); 30621cb0ef41Sopenharmony_ci buffer[buffer_pos++] = '\n'; 30631cb0ef41Sopenharmony_ci buffer[buffer_pos++] = '\0'; 30641cb0ef41Sopenharmony_ci writer_->AddString(buffer.begin()); 30651cb0ef41Sopenharmony_ci } 30661cb0ef41Sopenharmony_ci} 30671cb0ef41Sopenharmony_ci 30681cb0ef41Sopenharmony_ci 30691cb0ef41Sopenharmony_civoid HeapSnapshotJSONSerializer::SerializeSamples() { 30701cb0ef41Sopenharmony_ci const std::vector<HeapObjectsMap::TimeInterval>& samples = 30711cb0ef41Sopenharmony_ci snapshot_->profiler()->heap_object_map()->samples(); 30721cb0ef41Sopenharmony_ci if (samples.empty()) return; 30731cb0ef41Sopenharmony_ci base::TimeTicks start_time = samples[0].timestamp; 30741cb0ef41Sopenharmony_ci // The buffer needs space for 2 unsigned ints, 2 commas, \n and \0 30751cb0ef41Sopenharmony_ci const int kBufferSize = MaxDecimalDigitsIn<sizeof( 30761cb0ef41Sopenharmony_ci base::TimeDelta().InMicroseconds())>::kUnsigned + 30771cb0ef41Sopenharmony_ci MaxDecimalDigitsIn<sizeof(samples[0].id)>::kUnsigned + 30781cb0ef41Sopenharmony_ci 2 + 1 + 1; 30791cb0ef41Sopenharmony_ci base::EmbeddedVector<char, kBufferSize> buffer; 30801cb0ef41Sopenharmony_ci int i = 0; 30811cb0ef41Sopenharmony_ci for (const HeapObjectsMap::TimeInterval& sample : samples) { 30821cb0ef41Sopenharmony_ci int buffer_pos = 0; 30831cb0ef41Sopenharmony_ci if (i++ > 0) { 30841cb0ef41Sopenharmony_ci buffer[buffer_pos++] = ','; 30851cb0ef41Sopenharmony_ci } 30861cb0ef41Sopenharmony_ci base::TimeDelta time_delta = sample.timestamp - start_time; 30871cb0ef41Sopenharmony_ci buffer_pos = utoa(time_delta.InMicroseconds(), buffer, buffer_pos); 30881cb0ef41Sopenharmony_ci buffer[buffer_pos++] = ','; 30891cb0ef41Sopenharmony_ci buffer_pos = utoa(sample.last_assigned_id(), buffer, buffer_pos); 30901cb0ef41Sopenharmony_ci buffer[buffer_pos++] = '\n'; 30911cb0ef41Sopenharmony_ci buffer[buffer_pos++] = '\0'; 30921cb0ef41Sopenharmony_ci writer_->AddString(buffer.begin()); 30931cb0ef41Sopenharmony_ci } 30941cb0ef41Sopenharmony_ci} 30951cb0ef41Sopenharmony_ci 30961cb0ef41Sopenharmony_ci 30971cb0ef41Sopenharmony_civoid HeapSnapshotJSONSerializer::SerializeString(const unsigned char* s) { 30981cb0ef41Sopenharmony_ci writer_->AddCharacter('\n'); 30991cb0ef41Sopenharmony_ci writer_->AddCharacter('\"'); 31001cb0ef41Sopenharmony_ci for ( ; *s != '\0'; ++s) { 31011cb0ef41Sopenharmony_ci switch (*s) { 31021cb0ef41Sopenharmony_ci case '\b': 31031cb0ef41Sopenharmony_ci writer_->AddString("\\b"); 31041cb0ef41Sopenharmony_ci continue; 31051cb0ef41Sopenharmony_ci case '\f': 31061cb0ef41Sopenharmony_ci writer_->AddString("\\f"); 31071cb0ef41Sopenharmony_ci continue; 31081cb0ef41Sopenharmony_ci case '\n': 31091cb0ef41Sopenharmony_ci writer_->AddString("\\n"); 31101cb0ef41Sopenharmony_ci continue; 31111cb0ef41Sopenharmony_ci case '\r': 31121cb0ef41Sopenharmony_ci writer_->AddString("\\r"); 31131cb0ef41Sopenharmony_ci continue; 31141cb0ef41Sopenharmony_ci case '\t': 31151cb0ef41Sopenharmony_ci writer_->AddString("\\t"); 31161cb0ef41Sopenharmony_ci continue; 31171cb0ef41Sopenharmony_ci case '\"': 31181cb0ef41Sopenharmony_ci case '\\': 31191cb0ef41Sopenharmony_ci writer_->AddCharacter('\\'); 31201cb0ef41Sopenharmony_ci writer_->AddCharacter(*s); 31211cb0ef41Sopenharmony_ci continue; 31221cb0ef41Sopenharmony_ci default: 31231cb0ef41Sopenharmony_ci if (*s > 31 && *s < 128) { 31241cb0ef41Sopenharmony_ci writer_->AddCharacter(*s); 31251cb0ef41Sopenharmony_ci } else if (*s <= 31) { 31261cb0ef41Sopenharmony_ci // Special character with no dedicated literal. 31271cb0ef41Sopenharmony_ci WriteUChar(writer_, *s); 31281cb0ef41Sopenharmony_ci } else { 31291cb0ef41Sopenharmony_ci // Convert UTF-8 into \u UTF-16 literal. 31301cb0ef41Sopenharmony_ci size_t length = 1, cursor = 0; 31311cb0ef41Sopenharmony_ci for ( ; length <= 4 && *(s + length) != '\0'; ++length) { } 31321cb0ef41Sopenharmony_ci unibrow::uchar c = unibrow::Utf8::CalculateValue(s, length, &cursor); 31331cb0ef41Sopenharmony_ci if (c != unibrow::Utf8::kBadChar) { 31341cb0ef41Sopenharmony_ci WriteUChar(writer_, c); 31351cb0ef41Sopenharmony_ci DCHECK_NE(cursor, 0); 31361cb0ef41Sopenharmony_ci s += cursor - 1; 31371cb0ef41Sopenharmony_ci } else { 31381cb0ef41Sopenharmony_ci writer_->AddCharacter('?'); 31391cb0ef41Sopenharmony_ci } 31401cb0ef41Sopenharmony_ci } 31411cb0ef41Sopenharmony_ci } 31421cb0ef41Sopenharmony_ci } 31431cb0ef41Sopenharmony_ci writer_->AddCharacter('\"'); 31441cb0ef41Sopenharmony_ci} 31451cb0ef41Sopenharmony_ci 31461cb0ef41Sopenharmony_ci 31471cb0ef41Sopenharmony_civoid HeapSnapshotJSONSerializer::SerializeStrings() { 31481cb0ef41Sopenharmony_ci base::ScopedVector<const unsigned char*> sorted_strings(strings_.occupancy() + 31491cb0ef41Sopenharmony_ci 1); 31501cb0ef41Sopenharmony_ci for (base::HashMap::Entry* entry = strings_.Start(); entry != nullptr; 31511cb0ef41Sopenharmony_ci entry = strings_.Next(entry)) { 31521cb0ef41Sopenharmony_ci int index = static_cast<int>(reinterpret_cast<uintptr_t>(entry->value)); 31531cb0ef41Sopenharmony_ci sorted_strings[index] = reinterpret_cast<const unsigned char*>(entry->key); 31541cb0ef41Sopenharmony_ci } 31551cb0ef41Sopenharmony_ci writer_->AddString("\"<dummy>\""); 31561cb0ef41Sopenharmony_ci for (int i = 1; i < sorted_strings.length(); ++i) { 31571cb0ef41Sopenharmony_ci writer_->AddCharacter(','); 31581cb0ef41Sopenharmony_ci SerializeString(sorted_strings[i]); 31591cb0ef41Sopenharmony_ci if (writer_->aborted()) return; 31601cb0ef41Sopenharmony_ci } 31611cb0ef41Sopenharmony_ci} 31621cb0ef41Sopenharmony_ci 31631cb0ef41Sopenharmony_civoid HeapSnapshotJSONSerializer::SerializeLocation( 31641cb0ef41Sopenharmony_ci const SourceLocation& location) { 31651cb0ef41Sopenharmony_ci // The buffer needs space for 4 unsigned ints, 3 commas, \n and \0 31661cb0ef41Sopenharmony_ci static const int kBufferSize = 31671cb0ef41Sopenharmony_ci MaxDecimalDigitsIn<sizeof(unsigned)>::kUnsigned * 4 + 3 + 2; 31681cb0ef41Sopenharmony_ci base::EmbeddedVector<char, kBufferSize> buffer; 31691cb0ef41Sopenharmony_ci int buffer_pos = 0; 31701cb0ef41Sopenharmony_ci buffer_pos = utoa(to_node_index(location.entry_index), buffer, buffer_pos); 31711cb0ef41Sopenharmony_ci buffer[buffer_pos++] = ','; 31721cb0ef41Sopenharmony_ci buffer_pos = utoa(location.scriptId, buffer, buffer_pos); 31731cb0ef41Sopenharmony_ci buffer[buffer_pos++] = ','; 31741cb0ef41Sopenharmony_ci buffer_pos = utoa(location.line, buffer, buffer_pos); 31751cb0ef41Sopenharmony_ci buffer[buffer_pos++] = ','; 31761cb0ef41Sopenharmony_ci buffer_pos = utoa(location.col, buffer, buffer_pos); 31771cb0ef41Sopenharmony_ci buffer[buffer_pos++] = '\n'; 31781cb0ef41Sopenharmony_ci buffer[buffer_pos++] = '\0'; 31791cb0ef41Sopenharmony_ci writer_->AddString(buffer.begin()); 31801cb0ef41Sopenharmony_ci} 31811cb0ef41Sopenharmony_ci 31821cb0ef41Sopenharmony_civoid HeapSnapshotJSONSerializer::SerializeLocations() { 31831cb0ef41Sopenharmony_ci const std::vector<SourceLocation>& locations = snapshot_->locations(); 31841cb0ef41Sopenharmony_ci for (size_t i = 0; i < locations.size(); i++) { 31851cb0ef41Sopenharmony_ci if (i > 0) writer_->AddCharacter(','); 31861cb0ef41Sopenharmony_ci SerializeLocation(locations[i]); 31871cb0ef41Sopenharmony_ci if (writer_->aborted()) return; 31881cb0ef41Sopenharmony_ci } 31891cb0ef41Sopenharmony_ci} 31901cb0ef41Sopenharmony_ci 31911cb0ef41Sopenharmony_ci} // namespace internal 31921cb0ef41Sopenharmony_ci} // namespace v8 3193