OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/profiler/heap-snapshot-generator.h" | 5 #include "src/profiler/heap-snapshot-generator.h" |
6 | 6 |
7 #include "src/code-stubs.h" | 7 #include "src/code-stubs.h" |
8 #include "src/conversions.h" | 8 #include "src/conversions.h" |
9 #include "src/debug/debug.h" | 9 #include "src/debug/debug.h" |
10 #include "src/objects-body-descriptors.h" | 10 #include "src/objects-body-descriptors.h" |
(...skipping 970 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
981 obj != NULL; | 981 obj != NULL; |
982 obj = iterator->next()) { | 982 obj = iterator->next()) { |
983 objects_count++; | 983 objects_count++; |
984 } | 984 } |
985 return objects_count; | 985 return objects_count; |
986 } | 986 } |
987 | 987 |
988 | 988 |
989 class IndexedReferencesExtractor : public ObjectVisitor { | 989 class IndexedReferencesExtractor : public ObjectVisitor { |
990 public: | 990 public: |
991 IndexedReferencesExtractor(V8HeapExplorer* generator, | 991 IndexedReferencesExtractor(V8HeapExplorer* generator, HeapObject* parent_obj, |
992 HeapObject* parent_obj, | |
993 int parent) | 992 int parent) |
994 : generator_(generator), | 993 : generator_(generator), |
995 parent_obj_(parent_obj), | 994 parent_obj_(parent_obj), |
| 995 parent_start_(HeapObject::RawField(parent_obj_, 0)), |
| 996 parent_end_(HeapObject::RawField(parent_obj_, parent_obj_->Size())), |
996 parent_(parent), | 997 parent_(parent), |
997 next_index_(0) { | 998 next_index_(0) {} |
998 } | |
999 void VisitCodeEntry(Address entry_address) override { | 999 void VisitCodeEntry(Address entry_address) override { |
1000 Code* code = Code::cast(Code::GetObjectFromEntryAddress(entry_address)); | 1000 Code* code = Code::cast(Code::GetObjectFromEntryAddress(entry_address)); |
1001 generator_->SetInternalReference(parent_obj_, parent_, "code", code); | 1001 generator_->SetInternalReference(parent_obj_, parent_, "code", code); |
1002 generator_->TagCodeObject(code); | 1002 generator_->TagCodeObject(code); |
1003 } | 1003 } |
1004 void VisitPointers(Object** start, Object** end) override { | 1004 void VisitPointers(Object** start, Object** end) override { |
1005 for (Object** p = start; p < end; p++) { | 1005 for (Object** p = start; p < end; p++) { |
| 1006 intptr_t index = |
| 1007 static_cast<intptr_t>(p - HeapObject::RawField(parent_obj_, 0)); |
1006 ++next_index_; | 1008 ++next_index_; |
1007 if (CheckVisitedAndUnmark(p)) continue; | 1009 // |p| could be outside of the object, e.g., while visiting RelocInfo of |
| 1010 // code objects. |
| 1011 if (p >= parent_start_ && p < parent_end_ && generator_->marks_[index]) { |
| 1012 generator_->marks_[index] = false; |
| 1013 continue; |
| 1014 } |
1008 generator_->SetHiddenReference(parent_obj_, parent_, next_index_, *p); | 1015 generator_->SetHiddenReference(parent_obj_, parent_, next_index_, *p); |
1009 } | 1016 } |
1010 } | 1017 } |
1011 static void MarkVisitedField(HeapObject* obj, int offset) { | |
1012 if (offset < 0) return; | |
1013 Address field = obj->address() + offset; | |
1014 DCHECK(Memory::Object_at(field)->IsHeapObject()); | |
1015 intptr_t p = reinterpret_cast<intptr_t>(Memory::Object_at(field)); | |
1016 DCHECK(!IsMarked(p)); | |
1017 intptr_t p_tagged = p | kTag; | |
1018 Memory::Object_at(field) = reinterpret_cast<Object*>(p_tagged); | |
1019 } | |
1020 | 1018 |
1021 private: | 1019 private: |
1022 bool CheckVisitedAndUnmark(Object** field) { | |
1023 intptr_t p = reinterpret_cast<intptr_t>(*field); | |
1024 if (IsMarked(p)) { | |
1025 intptr_t p_untagged = (p & ~kTaggingMask) | kHeapObjectTag; | |
1026 *field = reinterpret_cast<Object*>(p_untagged); | |
1027 DCHECK((*field)->IsHeapObject()); | |
1028 return true; | |
1029 } | |
1030 return false; | |
1031 } | |
1032 | |
1033 static const intptr_t kTaggingMask = 3; | |
1034 static const intptr_t kTag = 3; | |
1035 | |
1036 static bool IsMarked(intptr_t p) { return (p & kTaggingMask) == kTag; } | |
1037 | |
1038 V8HeapExplorer* generator_; | 1020 V8HeapExplorer* generator_; |
1039 HeapObject* parent_obj_; | 1021 HeapObject* parent_obj_; |
| 1022 Object** parent_start_; |
| 1023 Object** parent_end_; |
1040 int parent_; | 1024 int parent_; |
1041 int next_index_; | 1025 int next_index_; |
1042 }; | 1026 }; |
1043 | 1027 |
1044 | 1028 |
1045 bool V8HeapExplorer::ExtractReferencesPass1(int entry, HeapObject* obj) { | 1029 bool V8HeapExplorer::ExtractReferencesPass1(int entry, HeapObject* obj) { |
1046 if (obj->IsFixedArray()) return false; // FixedArrays are processed on pass 2 | 1030 if (obj->IsFixedArray()) return false; // FixedArrays are processed on pass 2 |
1047 | 1031 |
1048 if (obj->IsJSGlobalProxy()) { | 1032 if (obj->IsJSGlobalProxy()) { |
1049 ExtractJSGlobalProxyReferences(entry, JSGlobalProxy::cast(obj)); | 1033 ExtractJSGlobalProxyReferences(entry, JSGlobalProxy::cast(obj)); |
(...skipping 814 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1864 bool V8HeapExplorer::IterateAndExtractSinglePass() { | 1848 bool V8HeapExplorer::IterateAndExtractSinglePass() { |
1865 // Now iterate the whole heap. | 1849 // Now iterate the whole heap. |
1866 bool interrupted = false; | 1850 bool interrupted = false; |
1867 HeapIterator iterator(heap_, HeapIterator::kFilterUnreachable); | 1851 HeapIterator iterator(heap_, HeapIterator::kFilterUnreachable); |
1868 // Heap iteration with filtering must be finished in any case. | 1852 // Heap iteration with filtering must be finished in any case. |
1869 for (HeapObject* obj = iterator.next(); | 1853 for (HeapObject* obj = iterator.next(); |
1870 obj != NULL; | 1854 obj != NULL; |
1871 obj = iterator.next(), progress_->ProgressStep()) { | 1855 obj = iterator.next(), progress_->ProgressStep()) { |
1872 if (interrupted) continue; | 1856 if (interrupted) continue; |
1873 | 1857 |
| 1858 size_t max_pointer = obj->Size() / kPointerSize; |
| 1859 if (max_pointer > marks_.size()) { |
| 1860 // Clear the current bits. |
| 1861 std::vector<bool>().swap(marks_); |
| 1862 // Reallocate to right size. |
| 1863 marks_.resize(max_pointer, false); |
| 1864 } |
| 1865 |
1874 HeapEntry* heap_entry = GetEntry(obj); | 1866 HeapEntry* heap_entry = GetEntry(obj); |
1875 int entry = heap_entry->index(); | 1867 int entry = heap_entry->index(); |
1876 if ((this->*extractor)(entry, obj)) { | 1868 if ((this->*extractor)(entry, obj)) { |
1877 SetInternalReference(obj, entry, | 1869 SetInternalReference(obj, entry, |
1878 "map", obj->map(), HeapObject::kMapOffset); | 1870 "map", obj->map(), HeapObject::kMapOffset); |
1879 // Extract unvisited fields as hidden references and restore tags | 1871 // Extract unvisited fields as hidden references and restore tags |
1880 // of visited fields. | 1872 // of visited fields. |
1881 IndexedReferencesExtractor refs_extractor(this, obj, entry); | 1873 IndexedReferencesExtractor refs_extractor(this, obj, entry); |
1882 obj->Iterate(&refs_extractor); | 1874 obj->Iterate(&refs_extractor); |
1883 } | 1875 } |
(...skipping 24 matching lines...) Expand all Loading... |
1908 String* reference_name, | 1900 String* reference_name, |
1909 Object* child_obj, | 1901 Object* child_obj, |
1910 int field_offset) { | 1902 int field_offset) { |
1911 DCHECK(parent_entry == GetEntry(parent_obj)->index()); | 1903 DCHECK(parent_entry == GetEntry(parent_obj)->index()); |
1912 HeapEntry* child_entry = GetEntry(child_obj); | 1904 HeapEntry* child_entry = GetEntry(child_obj); |
1913 if (child_entry != NULL) { | 1905 if (child_entry != NULL) { |
1914 filler_->SetNamedReference(HeapGraphEdge::kContextVariable, | 1906 filler_->SetNamedReference(HeapGraphEdge::kContextVariable, |
1915 parent_entry, | 1907 parent_entry, |
1916 names_->GetName(reference_name), | 1908 names_->GetName(reference_name), |
1917 child_entry); | 1909 child_entry); |
1918 IndexedReferencesExtractor::MarkVisitedField(parent_obj, field_offset); | 1910 MarkVisitedField(parent_obj, field_offset); |
1919 } | 1911 } |
1920 } | 1912 } |
1921 | 1913 |
1922 | 1914 |
| 1915 void V8HeapExplorer::MarkVisitedField(HeapObject* obj, int offset) { |
| 1916 if (offset < 0) return; |
| 1917 int index = offset / kPointerSize; |
| 1918 DCHECK(!marks_[index]); |
| 1919 marks_[index] = true; |
| 1920 } |
| 1921 |
| 1922 |
1923 void V8HeapExplorer::SetNativeBindReference(HeapObject* parent_obj, | 1923 void V8HeapExplorer::SetNativeBindReference(HeapObject* parent_obj, |
1924 int parent_entry, | 1924 int parent_entry, |
1925 const char* reference_name, | 1925 const char* reference_name, |
1926 Object* child_obj) { | 1926 Object* child_obj) { |
1927 DCHECK(parent_entry == GetEntry(parent_obj)->index()); | 1927 DCHECK(parent_entry == GetEntry(parent_obj)->index()); |
1928 HeapEntry* child_entry = GetEntry(child_obj); | 1928 HeapEntry* child_entry = GetEntry(child_obj); |
1929 if (child_entry != NULL) { | 1929 if (child_entry != NULL) { |
1930 filler_->SetNamedReference(HeapGraphEdge::kShortcut, | 1930 filler_->SetNamedReference(HeapGraphEdge::kShortcut, |
1931 parent_entry, | 1931 parent_entry, |
1932 reference_name, | 1932 reference_name, |
(...skipping 24 matching lines...) Expand all Loading... |
1957 int field_offset) { | 1957 int field_offset) { |
1958 DCHECK(parent_entry == GetEntry(parent_obj)->index()); | 1958 DCHECK(parent_entry == GetEntry(parent_obj)->index()); |
1959 HeapEntry* child_entry = GetEntry(child_obj); | 1959 HeapEntry* child_entry = GetEntry(child_obj); |
1960 if (child_entry == NULL) return; | 1960 if (child_entry == NULL) return; |
1961 if (IsEssentialObject(child_obj)) { | 1961 if (IsEssentialObject(child_obj)) { |
1962 filler_->SetNamedReference(HeapGraphEdge::kInternal, | 1962 filler_->SetNamedReference(HeapGraphEdge::kInternal, |
1963 parent_entry, | 1963 parent_entry, |
1964 reference_name, | 1964 reference_name, |
1965 child_entry); | 1965 child_entry); |
1966 } | 1966 } |
1967 IndexedReferencesExtractor::MarkVisitedField(parent_obj, field_offset); | 1967 MarkVisitedField(parent_obj, field_offset); |
1968 } | 1968 } |
1969 | 1969 |
1970 | 1970 |
1971 void V8HeapExplorer::SetInternalReference(HeapObject* parent_obj, | 1971 void V8HeapExplorer::SetInternalReference(HeapObject* parent_obj, |
1972 int parent_entry, | 1972 int parent_entry, |
1973 int index, | 1973 int index, |
1974 Object* child_obj, | 1974 Object* child_obj, |
1975 int field_offset) { | 1975 int field_offset) { |
1976 DCHECK(parent_entry == GetEntry(parent_obj)->index()); | 1976 DCHECK(parent_entry == GetEntry(parent_obj)->index()); |
1977 HeapEntry* child_entry = GetEntry(child_obj); | 1977 HeapEntry* child_entry = GetEntry(child_obj); |
1978 if (child_entry == NULL) return; | 1978 if (child_entry == NULL) return; |
1979 if (IsEssentialObject(child_obj)) { | 1979 if (IsEssentialObject(child_obj)) { |
1980 filler_->SetNamedReference(HeapGraphEdge::kInternal, | 1980 filler_->SetNamedReference(HeapGraphEdge::kInternal, |
1981 parent_entry, | 1981 parent_entry, |
1982 names_->GetName(index), | 1982 names_->GetName(index), |
1983 child_entry); | 1983 child_entry); |
1984 } | 1984 } |
1985 IndexedReferencesExtractor::MarkVisitedField(parent_obj, field_offset); | 1985 MarkVisitedField(parent_obj, field_offset); |
1986 } | 1986 } |
1987 | 1987 |
1988 | 1988 |
1989 void V8HeapExplorer::SetHiddenReference(HeapObject* parent_obj, | 1989 void V8HeapExplorer::SetHiddenReference(HeapObject* parent_obj, |
1990 int parent_entry, | 1990 int parent_entry, |
1991 int index, | 1991 int index, |
1992 Object* child_obj) { | 1992 Object* child_obj) { |
1993 DCHECK(parent_entry == GetEntry(parent_obj)->index()); | 1993 DCHECK(parent_entry == GetEntry(parent_obj)->index()); |
1994 HeapEntry* child_entry = GetEntry(child_obj); | 1994 HeapEntry* child_entry = GetEntry(child_obj); |
1995 if (child_entry != NULL && IsEssentialObject(child_obj)) { | 1995 if (child_entry != NULL && IsEssentialObject(child_obj)) { |
(...skipping 12 matching lines...) Expand all Loading... |
2008 int field_offset) { | 2008 int field_offset) { |
2009 DCHECK(parent_entry == GetEntry(parent_obj)->index()); | 2009 DCHECK(parent_entry == GetEntry(parent_obj)->index()); |
2010 HeapEntry* child_entry = GetEntry(child_obj); | 2010 HeapEntry* child_entry = GetEntry(child_obj); |
2011 if (child_entry == NULL) return; | 2011 if (child_entry == NULL) return; |
2012 if (IsEssentialObject(child_obj)) { | 2012 if (IsEssentialObject(child_obj)) { |
2013 filler_->SetNamedReference(HeapGraphEdge::kWeak, | 2013 filler_->SetNamedReference(HeapGraphEdge::kWeak, |
2014 parent_entry, | 2014 parent_entry, |
2015 reference_name, | 2015 reference_name, |
2016 child_entry); | 2016 child_entry); |
2017 } | 2017 } |
2018 IndexedReferencesExtractor::MarkVisitedField(parent_obj, field_offset); | 2018 MarkVisitedField(parent_obj, field_offset); |
2019 } | 2019 } |
2020 | 2020 |
2021 | 2021 |
2022 void V8HeapExplorer::SetWeakReference(HeapObject* parent_obj, | 2022 void V8HeapExplorer::SetWeakReference(HeapObject* parent_obj, |
2023 int parent_entry, | 2023 int parent_entry, |
2024 int index, | 2024 int index, |
2025 Object* child_obj, | 2025 Object* child_obj, |
2026 int field_offset) { | 2026 int field_offset) { |
2027 DCHECK(parent_entry == GetEntry(parent_obj)->index()); | 2027 DCHECK(parent_entry == GetEntry(parent_obj)->index()); |
2028 HeapEntry* child_entry = GetEntry(child_obj); | 2028 HeapEntry* child_entry = GetEntry(child_obj); |
2029 if (child_entry == NULL) return; | 2029 if (child_entry == NULL) return; |
2030 if (IsEssentialObject(child_obj)) { | 2030 if (IsEssentialObject(child_obj)) { |
2031 filler_->SetNamedReference(HeapGraphEdge::kWeak, | 2031 filler_->SetNamedReference(HeapGraphEdge::kWeak, |
2032 parent_entry, | 2032 parent_entry, |
2033 names_->GetFormatted("%d", index), | 2033 names_->GetFormatted("%d", index), |
2034 child_entry); | 2034 child_entry); |
2035 } | 2035 } |
2036 IndexedReferencesExtractor::MarkVisitedField(parent_obj, field_offset); | 2036 MarkVisitedField(parent_obj, field_offset); |
2037 } | 2037 } |
2038 | 2038 |
2039 | 2039 |
2040 void V8HeapExplorer::SetDataOrAccessorPropertyReference( | 2040 void V8HeapExplorer::SetDataOrAccessorPropertyReference( |
2041 PropertyKind kind, JSObject* parent_obj, int parent_entry, | 2041 PropertyKind kind, JSObject* parent_obj, int parent_entry, |
2042 Name* reference_name, Object* child_obj, const char* name_format_string, | 2042 Name* reference_name, Object* child_obj, const char* name_format_string, |
2043 int field_offset) { | 2043 int field_offset) { |
2044 if (kind == kAccessor) { | 2044 if (kind == kAccessor) { |
2045 ExtractAccessorPairProperty(parent_obj, parent_entry, reference_name, | 2045 ExtractAccessorPairProperty(parent_obj, parent_entry, reference_name, |
2046 child_obj, field_offset); | 2046 child_obj, field_offset); |
(...skipping 20 matching lines...) Expand all Loading... |
2067 ? names_->GetFormatted( | 2067 ? names_->GetFormatted( |
2068 name_format_string, | 2068 name_format_string, |
2069 String::cast(reference_name)->ToCString( | 2069 String::cast(reference_name)->ToCString( |
2070 DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL).get()) : | 2070 DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL).get()) : |
2071 names_->GetName(reference_name); | 2071 names_->GetName(reference_name); |
2072 | 2072 |
2073 filler_->SetNamedReference(type, | 2073 filler_->SetNamedReference(type, |
2074 parent_entry, | 2074 parent_entry, |
2075 name, | 2075 name, |
2076 child_entry); | 2076 child_entry); |
2077 IndexedReferencesExtractor::MarkVisitedField(parent_obj, field_offset); | 2077 MarkVisitedField(parent_obj, field_offset); |
2078 } | 2078 } |
2079 } | 2079 } |
2080 | 2080 |
2081 | 2081 |
2082 void V8HeapExplorer::SetRootGcRootsReference() { | 2082 void V8HeapExplorer::SetRootGcRootsReference() { |
2083 filler_->SetIndexedAutoIndexReference( | 2083 filler_->SetIndexedAutoIndexReference( |
2084 HeapGraphEdge::kElement, | 2084 HeapGraphEdge::kElement, |
2085 snapshot_->root()->index(), | 2085 snapshot_->root()->index(), |
2086 snapshot_->gc_roots()); | 2086 snapshot_->gc_roots()); |
2087 } | 2087 } |
(...skipping 1083 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3171 for (int i = 1; i < sorted_strings.length(); ++i) { | 3171 for (int i = 1; i < sorted_strings.length(); ++i) { |
3172 writer_->AddCharacter(','); | 3172 writer_->AddCharacter(','); |
3173 SerializeString(sorted_strings[i]); | 3173 SerializeString(sorted_strings[i]); |
3174 if (writer_->aborted()) return; | 3174 if (writer_->aborted()) return; |
3175 } | 3175 } |
3176 } | 3176 } |
3177 | 3177 |
3178 | 3178 |
3179 } // namespace internal | 3179 } // namespace internal |
3180 } // namespace v8 | 3180 } // namespace v8 |
OLD | NEW |