diff --git a/src/profiler/heap-snapshot-generator.cc b/src/profiler/heap-snapshot-generator.cc index 566ebe3820..322b164c5e 100644 --- a/src/profiler/heap-snapshot-generator.cc +++ b/src/profiler/heap-snapshot-generator.cc @@ -988,14 +988,14 @@ int V8HeapExplorer::EstimateObjectsCount(HeapIterator* iterator) { class IndexedReferencesExtractor : public ObjectVisitor { public: - IndexedReferencesExtractor(V8HeapExplorer* generator, - HeapObject* parent_obj, + IndexedReferencesExtractor(V8HeapExplorer* generator, HeapObject* parent_obj, int parent) : generator_(generator), parent_obj_(parent_obj), + parent_start_(HeapObject::RawField(parent_obj_, 0)), + parent_end_(HeapObject::RawField(parent_obj_, parent_obj_->Size())), parent_(parent), - next_index_(0) { - } + next_index_(0) {} void VisitCodeEntry(Address entry_address) override { Code* code = Code::cast(Code::GetObjectFromEntryAddress(entry_address)); generator_->SetInternalReference(parent_obj_, parent_, "code", code); @@ -1003,40 +1003,24 @@ class IndexedReferencesExtractor : public ObjectVisitor { } void VisitPointers(Object** start, Object** end) override { for (Object** p = start; p < end; p++) { + intptr_t index = + static_cast(p - HeapObject::RawField(parent_obj_, 0)); ++next_index_; - if (CheckVisitedAndUnmark(p)) continue; + // |p| could be outside of the object, e.g., while visiting RelocInfo of + // code objects. + if (p >= parent_start_ && p < parent_end_ && generator_->marks_[index]) { + generator_->marks_[index] = false; + continue; + } generator_->SetHiddenReference(parent_obj_, parent_, next_index_, *p); } } - static void MarkVisitedField(HeapObject* obj, int offset) { - if (offset < 0) return; - Address field = obj->address() + offset; - DCHECK(Memory::Object_at(field)->IsHeapObject()); - intptr_t p = reinterpret_cast(Memory::Object_at(field)); - DCHECK(!IsMarked(p)); - intptr_t p_tagged = p | kTag; - Memory::Object_at(field) = reinterpret_cast(p_tagged); - } private: - bool CheckVisitedAndUnmark(Object** field) { - intptr_t p = reinterpret_cast(*field); - if (IsMarked(p)) { - intptr_t p_untagged = (p & ~kTaggingMask) | kHeapObjectTag; - *field = reinterpret_cast(p_untagged); - DCHECK((*field)->IsHeapObject()); - return true; - } - return false; - } - - static const intptr_t kTaggingMask = 3; - static const intptr_t kTag = 3; - - static bool IsMarked(intptr_t p) { return (p & kTaggingMask) == kTag; } - V8HeapExplorer* generator_; HeapObject* parent_obj_; + Object** parent_start_; + Object** parent_end_; int parent_; int next_index_; }; @@ -1871,6 +1855,14 @@ bool V8HeapExplorer::IterateAndExtractSinglePass() { obj = iterator.next(), progress_->ProgressStep()) { if (interrupted) continue; + size_t max_pointer = obj->Size() / kPointerSize; + if (max_pointer > marks_.size()) { + // Clear the current bits. + std::vector().swap(marks_); + // Reallocate to right size. + marks_.resize(max_pointer, false); + } + HeapEntry* heap_entry = GetEntry(obj); int entry = heap_entry->index(); if ((this->*extractor)(entry, obj)) { @@ -1915,11 +1907,19 @@ void V8HeapExplorer::SetContextReference(HeapObject* parent_obj, parent_entry, names_->GetName(reference_name), child_entry); - IndexedReferencesExtractor::MarkVisitedField(parent_obj, field_offset); + MarkVisitedField(parent_obj, field_offset); } } +void V8HeapExplorer::MarkVisitedField(HeapObject* obj, int offset) { + if (offset < 0) return; + int index = offset / kPointerSize; + DCHECK(!marks_[index]); + marks_[index] = true; +} + + void V8HeapExplorer::SetNativeBindReference(HeapObject* parent_obj, int parent_entry, const char* reference_name, @@ -1964,7 +1964,7 @@ void V8HeapExplorer::SetInternalReference(HeapObject* parent_obj, reference_name, child_entry); } - IndexedReferencesExtractor::MarkVisitedField(parent_obj, field_offset); + MarkVisitedField(parent_obj, field_offset); } @@ -1982,7 +1982,7 @@ void V8HeapExplorer::SetInternalReference(HeapObject* parent_obj, names_->GetName(index), child_entry); } - IndexedReferencesExtractor::MarkVisitedField(parent_obj, field_offset); + MarkVisitedField(parent_obj, field_offset); } @@ -2015,7 +2015,7 @@ void V8HeapExplorer::SetWeakReference(HeapObject* parent_obj, reference_name, child_entry); } - IndexedReferencesExtractor::MarkVisitedField(parent_obj, field_offset); + MarkVisitedField(parent_obj, field_offset); } @@ -2033,7 +2033,7 @@ void V8HeapExplorer::SetWeakReference(HeapObject* parent_obj, names_->GetFormatted("%d", index), child_entry); } - IndexedReferencesExtractor::MarkVisitedField(parent_obj, field_offset); + MarkVisitedField(parent_obj, field_offset); } @@ -2074,7 +2074,7 @@ void V8HeapExplorer::SetPropertyReference(HeapObject* parent_obj, parent_entry, name, child_entry); - IndexedReferencesExtractor::MarkVisitedField(parent_obj, field_offset); + MarkVisitedField(parent_obj, field_offset); } } diff --git a/src/profiler/heap-snapshot-generator.h b/src/profiler/heap-snapshot-generator.h index 3d6693b0d9..865dd56ad1 100644 --- a/src/profiler/heap-snapshot-generator.h +++ b/src/profiler/heap-snapshot-generator.h @@ -351,6 +351,8 @@ class V8HeapExplorer : public HeapEntriesAllocator { typedef bool (V8HeapExplorer::*ExtractReferencesMethod)(int entry, HeapObject* object); + void MarkVisitedField(HeapObject* obj, int offset); + HeapEntry* AddEntry(HeapObject* object); HeapEntry* AddEntry(HeapObject* object, HeapEntry::Type type, @@ -465,6 +467,8 @@ class V8HeapExplorer : public HeapEntriesAllocator { HeapObjectsSet weak_containers_; v8::HeapProfiler::ObjectNameResolver* global_object_name_resolver_; + std::vector marks_; + friend class IndexedReferencesExtractor; friend class RootsReferencesExtractor;