| Index: src/heap-snapshot-generator.cc
|
| diff --git a/src/heap-snapshot-generator.cc b/src/heap-snapshot-generator.cc
|
| index 895c0da1e04f1ea8114bb1de00e566d35b88565a..d65b8140039e43eb1e7c9d76747c54e6c3d0c1da 100644
|
| --- a/src/heap-snapshot-generator.cc
|
| +++ b/src/heap-snapshot-generator.cc
|
| @@ -189,15 +189,11 @@ template <size_t ptr_size> struct SnapshotSizeConstants;
|
| template <> struct SnapshotSizeConstants<4> {
|
| static const int kExpectedHeapGraphEdgeSize = 12;
|
| static const int kExpectedHeapEntrySize = 24;
|
| - static const int kExpectedHeapSnapshotsCollectionSize = 100;
|
| - static const int kExpectedHeapSnapshotSize = 132;
|
| };
|
|
|
| template <> struct SnapshotSizeConstants<8> {
|
| static const int kExpectedHeapGraphEdgeSize = 24;
|
| static const int kExpectedHeapEntrySize = 32;
|
| - static const int kExpectedHeapSnapshotsCollectionSize = 152;
|
| - static const int kExpectedHeapSnapshotSize = 160;
|
| };
|
|
|
| } // namespace
|
| @@ -238,7 +234,7 @@ void HeapSnapshot::RememberLastJSObjectId() {
|
| HeapEntry* HeapSnapshot::AddRootEntry() {
|
| ASSERT(root_index_ == HeapEntry::kNoEntry);
|
| ASSERT(entries_.is_empty()); // Root entry must be the first one.
|
| - HeapEntry* entry = AddEntry(HeapEntry::kObject,
|
| + HeapEntry* entry = AddEntry(HeapEntry::kSynthetic,
|
| "",
|
| HeapObjectsMap::kInternalRootObjectId,
|
| 0);
|
| @@ -250,7 +246,7 @@ HeapEntry* HeapSnapshot::AddRootEntry() {
|
|
|
| HeapEntry* HeapSnapshot::AddGcRootsEntry() {
|
| ASSERT(gc_roots_index_ == HeapEntry::kNoEntry);
|
| - HeapEntry* entry = AddEntry(HeapEntry::kObject,
|
| + HeapEntry* entry = AddEntry(HeapEntry::kSynthetic,
|
| "(GC roots)",
|
| HeapObjectsMap::kGcRootsObjectId,
|
| 0);
|
| @@ -263,7 +259,7 @@ HeapEntry* HeapSnapshot::AddGcSubrootEntry(int tag) {
|
| ASSERT(gc_subroot_indexes_[tag] == HeapEntry::kNoEntry);
|
| ASSERT(0 <= tag && tag < VisitorSynchronization::kNumberOfSyncTags);
|
| HeapEntry* entry = AddEntry(
|
| - HeapEntry::kObject,
|
| + HeapEntry::kSynthetic,
|
| VisitorSynchronization::kTagNames[tag],
|
| HeapObjectsMap::GetNthGcSubrootId(tag),
|
| 0);
|
| @@ -353,8 +349,6 @@ static size_t GetMemoryUsedByList(const List<T, P>& list) {
|
|
|
|
|
| size_t HeapSnapshot::RawSnapshotSize() const {
|
| - STATIC_CHECK(SnapshotSizeConstants<kPointerSize>::kExpectedHeapSnapshotSize ==
|
| - sizeof(HeapSnapshot)); // NOLINT
|
| return
|
| sizeof(*this) +
|
| GetMemoryUsedByList(entries_) +
|
| @@ -465,6 +459,7 @@ void HeapObjectsMap::StopHeapObjectsTracking() {
|
| time_intervals_.Clear();
|
| }
|
|
|
| +
|
| void HeapObjectsMap::UpdateHeapObjectsMap() {
|
| HEAP->CollectAllGarbage(Heap::kMakeHeapIterableMask,
|
| "HeapSnapshotsCollection::UpdateHeapObjectsMap");
|
| @@ -578,8 +573,6 @@ size_t HeapObjectsMap::GetUsedMemorySize() const {
|
|
|
| HeapSnapshotsCollection::HeapSnapshotsCollection(Heap* heap)
|
| : is_tracking_objects_(false),
|
| - snapshots_uids_(HeapSnapshotsMatch),
|
| - token_enumerator_(new TokenEnumerator()),
|
| ids_(heap) {
|
| }
|
|
|
| @@ -590,7 +583,6 @@ static void DeleteHeapSnapshot(HeapSnapshot** snapshot_ptr) {
|
|
|
|
|
| HeapSnapshotsCollection::~HeapSnapshotsCollection() {
|
| - delete token_enumerator_;
|
| snapshots_.Iterate(DeleteHeapSnapshot);
|
| }
|
|
|
| @@ -607,29 +599,12 @@ void HeapSnapshotsCollection::SnapshotGenerationFinished(
|
| ids_.SnapshotGenerationFinished();
|
| if (snapshot != NULL) {
|
| snapshots_.Add(snapshot);
|
| - HashMap::Entry* entry =
|
| - snapshots_uids_.Lookup(reinterpret_cast<void*>(snapshot->uid()),
|
| - static_cast<uint32_t>(snapshot->uid()),
|
| - true);
|
| - ASSERT(entry->value == NULL);
|
| - entry->value = snapshot;
|
| }
|
| }
|
|
|
|
|
| -HeapSnapshot* HeapSnapshotsCollection::GetSnapshot(unsigned uid) {
|
| - HashMap::Entry* entry = snapshots_uids_.Lookup(reinterpret_cast<void*>(uid),
|
| - static_cast<uint32_t>(uid),
|
| - false);
|
| - return entry != NULL ? reinterpret_cast<HeapSnapshot*>(entry->value) : NULL;
|
| -}
|
| -
|
| -
|
| void HeapSnapshotsCollection::RemoveSnapshot(HeapSnapshot* snapshot) {
|
| snapshots_.RemoveElement(snapshot);
|
| - unsigned uid = snapshot->uid();
|
| - snapshots_uids_.Remove(reinterpret_cast<void*>(uid),
|
| - static_cast<uint32_t>(uid));
|
| }
|
|
|
|
|
| @@ -656,13 +631,9 @@ Handle<HeapObject> HeapSnapshotsCollection::FindHeapObjectById(
|
|
|
|
|
| size_t HeapSnapshotsCollection::GetUsedMemorySize() const {
|
| - STATIC_CHECK(SnapshotSizeConstants<kPointerSize>::
|
| - kExpectedHeapSnapshotsCollectionSize ==
|
| - sizeof(HeapSnapshotsCollection)); // NOLINT
|
| size_t size = sizeof(*this);
|
| size += names_.GetUsedMemorySize();
|
| size += ids_.GetUsedMemorySize();
|
| - size += sizeof(HashMap::Entry) * snapshots_uids_.capacity();
|
| size += GetMemoryUsedByList(snapshots_);
|
| for (int i = 0; i < snapshots_.length(); ++i) {
|
| size += snapshots_[i]->RawSnapshotSize();
|
| @@ -961,7 +932,7 @@ void V8HeapExplorer::ExtractReferences(HeapObject* obj) {
|
|
|
| bool extract_indexed_refs = true;
|
| if (obj->IsJSGlobalProxy()) {
|
| - ExtractJSGlobalProxyReferences(JSGlobalProxy::cast(obj));
|
| + ExtractJSGlobalProxyReferences(entry, JSGlobalProxy::cast(obj));
|
| } else if (obj->IsJSObject()) {
|
| ExtractJSObjectReferences(entry, JSObject::cast(obj));
|
| } else if (obj->IsString()) {
|
| @@ -996,19 +967,11 @@ void V8HeapExplorer::ExtractReferences(HeapObject* obj) {
|
| }
|
|
|
|
|
| -void V8HeapExplorer::ExtractJSGlobalProxyReferences(JSGlobalProxy* proxy) {
|
| - // We need to reference JS global objects from snapshot's root.
|
| - // We use JSGlobalProxy because this is what embedder (e.g. browser)
|
| - // uses for the global object.
|
| - Object* object = proxy->map()->prototype();
|
| - bool is_debug_object = false;
|
| -#ifdef ENABLE_DEBUGGER_SUPPORT
|
| - is_debug_object = object->IsGlobalObject() &&
|
| - Isolate::Current()->debug()->IsDebugGlobal(GlobalObject::cast(object));
|
| -#endif
|
| - if (!is_debug_object) {
|
| - SetUserGlobalReference(object);
|
| - }
|
| +void V8HeapExplorer::ExtractJSGlobalProxyReferences(
|
| + int entry, JSGlobalProxy* proxy) {
|
| + SetInternalReference(proxy, entry,
|
| + "native_context", proxy->native_context(),
|
| + JSGlobalProxy::kNativeContextOffset);
|
| }
|
|
|
|
|
| @@ -1778,6 +1741,22 @@ void V8HeapExplorer::SetGcSubrootReference(
|
| snapshot_->gc_subroot(tag)->index(),
|
| child_entry);
|
| }
|
| +
|
| + // Add a shortcut to JS global object reference at snapshot root.
|
| + if (child_obj->IsNativeContext()) {
|
| + Context* context = Context::cast(child_obj);
|
| + GlobalObject* global = context->global_object();
|
| + if (global->IsJSGlobalObject()) {
|
| + bool is_debug_object = false;
|
| +#ifdef ENABLE_DEBUGGER_SUPPORT
|
| + is_debug_object = heap_->isolate()->debug()->IsDebugGlobal(global);
|
| +#endif
|
| + if (!is_debug_object && !user_roots_.Contains(global)) {
|
| + user_roots_.Insert(global);
|
| + SetUserGlobalReference(global);
|
| + }
|
| + }
|
| + }
|
| }
|
| }
|
|
|
| @@ -1983,6 +1962,7 @@ void NativeObjectsExplorer::FillRetainedObjects() {
|
| embedder_queried_ = true;
|
| }
|
|
|
| +
|
| void NativeObjectsExplorer::FillImplicitReferences() {
|
| Isolate* isolate = Isolate::Current();
|
| List<ImplicitRefGroup*>* groups =
|
| @@ -2608,6 +2588,7 @@ static void WriteUChar(OutputStreamWriter* w, unibrow::uchar u) {
|
| w->AddCharacter(hex_chars[u & 0xf]);
|
| }
|
|
|
| +
|
| void HeapSnapshotJSONSerializer::SerializeString(const unsigned char* s) {
|
| writer_->AddCharacter('\n');
|
| writer_->AddCharacter('\"');
|
|
|