OLD | NEW |
---|---|
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 1617 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1628 reinterpret_cast<HeapObject*>( | 1628 reinterpret_cast<HeapObject*>( |
1629 static_cast<intptr_t>(HeapObjectsMap::kInternalRootObjectId)); | 1629 static_cast<intptr_t>(HeapObjectsMap::kInternalRootObjectId)); |
1630 HeapObject *const V8HeapExplorer::kGcRootsObject = | 1630 HeapObject *const V8HeapExplorer::kGcRootsObject = |
1631 reinterpret_cast<HeapObject*>( | 1631 reinterpret_cast<HeapObject*>( |
1632 static_cast<intptr_t>(HeapObjectsMap::kGcRootsObjectId)); | 1632 static_cast<intptr_t>(HeapObjectsMap::kGcRootsObjectId)); |
1633 | 1633 |
1634 | 1634 |
1635 V8HeapExplorer::V8HeapExplorer( | 1635 V8HeapExplorer::V8HeapExplorer( |
1636 HeapSnapshot* snapshot, | 1636 HeapSnapshot* snapshot, |
1637 SnapshottingProgressReportingInterface* progress) | 1637 SnapshottingProgressReportingInterface* progress) |
1638 : snapshot_(snapshot), | 1638 : heap_(Isolate::Current()->heap()), |
1639 snapshot_(snapshot), | |
1639 collection_(snapshot_->collection()), | 1640 collection_(snapshot_->collection()), |
1640 progress_(progress), | 1641 progress_(progress), |
1641 filler_(NULL) { | 1642 filler_(NULL) { |
1642 } | 1643 } |
1643 | 1644 |
1644 | 1645 |
1645 V8HeapExplorer::~V8HeapExplorer() { | 1646 V8HeapExplorer::~V8HeapExplorer() { |
1646 } | 1647 } |
1647 | 1648 |
1648 | 1649 |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1718 } else if (object->IsScript()) { | 1719 } else if (object->IsScript()) { |
1719 Script* script = Script::cast(object); | 1720 Script* script = Script::cast(object); |
1720 return AddEntry(object, | 1721 return AddEntry(object, |
1721 HeapEntry::kCode, | 1722 HeapEntry::kCode, |
1722 script->name()->IsString() ? | 1723 script->name()->IsString() ? |
1723 collection_->names()->GetName( | 1724 collection_->names()->GetName( |
1724 String::cast(script->name())) | 1725 String::cast(script->name())) |
1725 : "", | 1726 : "", |
1726 children_count, | 1727 children_count, |
1727 retainers_count); | 1728 retainers_count); |
1728 } else if (object->IsFixedArray() || object->IsByteArray()) { | 1729 } else if (object->IsFixedArray() || |
1730 object->IsFixedDoubleArray() || | |
1731 object->IsByteArray() || | |
1732 object->IsExternalArray()) { | |
1733 const char* tag = objects_tags_.GetTag(object); | |
1729 return AddEntry(object, | 1734 return AddEntry(object, |
1730 HeapEntry::kArray, | 1735 HeapEntry::kArray, |
1731 "", | 1736 tag != NULL ? tag : "", |
1732 children_count, | 1737 children_count, |
1733 retainers_count); | 1738 retainers_count); |
1734 } else if (object->IsHeapNumber()) { | 1739 } else if (object->IsHeapNumber()) { |
1735 return AddEntry(object, | 1740 return AddEntry(object, |
1736 HeapEntry::kHeapNumber, | 1741 HeapEntry::kHeapNumber, |
1737 "number", | 1742 "number", |
1738 children_count, | 1743 children_count, |
1739 retainers_count); | 1744 retainers_count); |
1740 } | 1745 } |
1741 return AddEntry(object, | 1746 return AddEntry(object, |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1829 HeapObject* parent_obj_; | 1834 HeapObject* parent_obj_; |
1830 HeapEntry* parent_; | 1835 HeapEntry* parent_; |
1831 int next_index_; | 1836 int next_index_; |
1832 }; | 1837 }; |
1833 | 1838 |
1834 | 1839 |
1835 void V8HeapExplorer::ExtractReferences(HeapObject* obj) { | 1840 void V8HeapExplorer::ExtractReferences(HeapObject* obj) { |
1836 HeapEntry* entry = GetEntry(obj); | 1841 HeapEntry* entry = GetEntry(obj); |
1837 if (entry == NULL) return; // No interest in this object. | 1842 if (entry == NULL) return; // No interest in this object. |
1838 | 1843 |
1844 bool extract_indexed_refs = true; | |
1839 if (obj->IsJSGlobalProxy()) { | 1845 if (obj->IsJSGlobalProxy()) { |
1840 // We need to reference JS global objects from snapshot's root. | 1846 // We need to reference JS global objects from snapshot's root. |
1841 // We use JSGlobalProxy because this is what embedder (e.g. browser) | 1847 // We use JSGlobalProxy because this is what embedder (e.g. browser) |
1842 // uses for the global object. | 1848 // uses for the global object. |
1843 JSGlobalProxy* proxy = JSGlobalProxy::cast(obj); | 1849 JSGlobalProxy* proxy = JSGlobalProxy::cast(obj); |
1844 SetRootShortcutReference(proxy->map()->prototype()); | 1850 SetRootShortcutReference(proxy->map()->prototype()); |
1845 SetInternalReference(obj, entry, "map", obj->map(), HeapObject::kMapOffset); | |
1846 IndexedReferencesExtractor refs_extractor(this, obj, entry); | |
1847 obj->Iterate(&refs_extractor); | |
1848 } else if (obj->IsJSObject()) { | 1851 } else if (obj->IsJSObject()) { |
1849 JSObject* js_obj = JSObject::cast(obj); | 1852 JSObject* js_obj = JSObject::cast(obj); |
1850 ExtractClosureReferences(js_obj, entry); | 1853 ExtractClosureReferences(js_obj, entry); |
1851 ExtractPropertyReferences(js_obj, entry); | 1854 ExtractPropertyReferences(js_obj, entry); |
1852 ExtractElementReferences(js_obj, entry); | 1855 ExtractElementReferences(js_obj, entry); |
1853 ExtractInternalReferences(js_obj, entry); | 1856 ExtractInternalReferences(js_obj, entry); |
1854 SetPropertyReference( | 1857 SetPropertyReference( |
1855 obj, entry, HEAP->Proto_symbol(), js_obj->GetPrototype()); | 1858 obj, entry, heap_->Proto_symbol(), js_obj->GetPrototype()); |
1856 if (obj->IsJSFunction()) { | 1859 if (obj->IsJSFunction()) { |
1857 JSFunction* js_fun = JSFunction::cast(js_obj); | 1860 JSFunction* js_fun = JSFunction::cast(js_obj); |
1858 Object* proto_or_map = js_fun->prototype_or_initial_map(); | 1861 Object* proto_or_map = js_fun->prototype_or_initial_map(); |
1859 if (!proto_or_map->IsTheHole()) { | 1862 if (!proto_or_map->IsTheHole()) { |
1860 if (!proto_or_map->IsMap()) { | 1863 if (!proto_or_map->IsMap()) { |
1861 SetPropertyReference( | 1864 SetPropertyReference( |
1862 obj, entry, | 1865 obj, entry, |
1863 HEAP->prototype_symbol(), proto_or_map, | 1866 heap_->prototype_symbol(), proto_or_map, |
1864 JSFunction::kPrototypeOrInitialMapOffset); | 1867 JSFunction::kPrototypeOrInitialMapOffset); |
1865 } else { | 1868 } else { |
1866 SetPropertyReference( | 1869 SetPropertyReference( |
1867 obj, entry, | 1870 obj, entry, |
1868 HEAP->prototype_symbol(), js_fun->prototype()); | 1871 heap_->prototype_symbol(), js_fun->prototype()); |
1869 } | 1872 } |
1870 } | 1873 } |
1871 SetInternalReference(js_fun, entry, | 1874 SetInternalReference(js_fun, entry, |
1872 "shared", js_fun->shared(), | 1875 "shared", js_fun->shared(), |
1873 JSFunction::kSharedFunctionInfoOffset); | 1876 JSFunction::kSharedFunctionInfoOffset); |
1877 TagObject(js_fun->unchecked_context(), "(context)"); | |
1874 SetInternalReference(js_fun, entry, | 1878 SetInternalReference(js_fun, entry, |
1875 "context", js_fun->unchecked_context(), | 1879 "context", js_fun->unchecked_context(), |
1876 JSFunction::kContextOffset); | 1880 JSFunction::kContextOffset); |
1881 TagObject(js_fun->literals(), "(function literals)"); | |
1877 SetInternalReference(js_fun, entry, | 1882 SetInternalReference(js_fun, entry, |
1878 "literals", js_fun->literals(), | 1883 "literals", js_fun->literals(), |
1879 JSFunction::kLiteralsOffset); | 1884 JSFunction::kLiteralsOffset); |
1880 } | 1885 } |
1886 TagObject(js_obj->properties(), "(object properties)"); | |
1881 SetInternalReference(obj, entry, | 1887 SetInternalReference(obj, entry, |
1882 "properties", js_obj->properties(), | 1888 "properties", js_obj->properties(), |
1883 JSObject::kPropertiesOffset); | 1889 JSObject::kPropertiesOffset); |
1890 TagObject(js_obj->elements(), "(object elements)"); | |
1884 SetInternalReference(obj, entry, | 1891 SetInternalReference(obj, entry, |
1885 "elements", js_obj->elements(), | 1892 "elements", js_obj->elements(), |
1886 JSObject::kElementsOffset); | 1893 JSObject::kElementsOffset); |
1887 SetInternalReference(obj, entry, "map", obj->map(), HeapObject::kMapOffset); | |
1888 IndexedReferencesExtractor refs_extractor(this, obj, entry); | |
1889 obj->Iterate(&refs_extractor); | |
1890 } else if (obj->IsString()) { | 1894 } else if (obj->IsString()) { |
1891 if (obj->IsConsString()) { | 1895 if (obj->IsConsString()) { |
1892 ConsString* cs = ConsString::cast(obj); | 1896 ConsString* cs = ConsString::cast(obj); |
1893 SetInternalReference(obj, entry, 1, cs->first()); | 1897 SetInternalReference(obj, entry, 1, cs->first()); |
1894 SetInternalReference(obj, entry, 2, cs->second()); | 1898 SetInternalReference(obj, entry, 2, cs->second()); |
1895 } | 1899 } |
1900 extract_indexed_refs = false; | |
1901 } else if (obj->IsGlobalContext()) { | |
1902 Context* context = Context::cast(obj); | |
1903 TagObject(context->jsfunction_result_caches(), "(context func caches)"); | |
Vitaly Repeshko
2011/06/30 13:45:27
nit: Maybe we should avoid abbreviations? The name
mnaganov (inactive)
2011/06/30 14:15:22
Done.
| |
1904 TagObject(context->normalized_map_cache(), "(context norm. map cache)"); | |
1905 TagObject(context->runtime_context(), "(runtime context)"); | |
1906 TagObject(context->map_cache(), "(context map cache)"); | |
1907 TagObject(context->data(), "(context data)"); | |
1896 } else if (obj->IsMap()) { | 1908 } else if (obj->IsMap()) { |
1897 Map* map = Map::cast(obj); | 1909 Map* map = Map::cast(obj); |
1898 SetInternalReference(obj, entry, | 1910 SetInternalReference(obj, entry, |
1899 "prototype", map->prototype(), Map::kPrototypeOffset); | 1911 "prototype", map->prototype(), Map::kPrototypeOffset); |
1900 SetInternalReference(obj, entry, | 1912 SetInternalReference(obj, entry, |
1901 "constructor", map->constructor(), | 1913 "constructor", map->constructor(), |
1902 Map::kConstructorOffset); | 1914 Map::kConstructorOffset); |
1903 if (!map->instance_descriptors()->IsEmpty()) { | 1915 if (!map->instance_descriptors()->IsEmpty()) { |
1916 objects_tags_.SetTag(map->instance_descriptors(), "(map descriptors)"); | |
Vitaly Repeshko
2011/06/30 13:45:27
Use TagObject here?
mnaganov (inactive)
2011/06/30 14:15:22
Done.
| |
1904 SetInternalReference(obj, entry, | 1917 SetInternalReference(obj, entry, |
1905 "descriptors", map->instance_descriptors(), | 1918 "descriptors", map->instance_descriptors(), |
1906 Map::kInstanceDescriptorsOrBitField3Offset); | 1919 Map::kInstanceDescriptorsOrBitField3Offset); |
1907 } | 1920 } |
1908 SetInternalReference(obj, entry, | 1921 SetInternalReference(obj, entry, |
1909 "code_cache", map->code_cache(), | 1922 "code_cache", map->code_cache(), |
1910 Map::kCodeCacheOffset); | 1923 Map::kCodeCacheOffset); |
1911 SetInternalReference(obj, entry, "map", obj->map(), HeapObject::kMapOffset); | |
1912 IndexedReferencesExtractor refs_extractor(this, obj, entry); | |
1913 obj->Iterate(&refs_extractor); | |
1914 } else if (obj->IsSharedFunctionInfo()) { | 1924 } else if (obj->IsSharedFunctionInfo()) { |
1915 SharedFunctionInfo* shared = SharedFunctionInfo::cast(obj); | 1925 SharedFunctionInfo* shared = SharedFunctionInfo::cast(obj); |
1916 SetInternalReference(obj, entry, | 1926 SetInternalReference(obj, entry, |
1917 "name", shared->name(), | 1927 "name", shared->name(), |
1918 SharedFunctionInfo::kNameOffset); | 1928 SharedFunctionInfo::kNameOffset); |
1919 SetInternalReference(obj, entry, | 1929 SetInternalReference(obj, entry, |
1920 "code", shared->unchecked_code(), | 1930 "code", shared->unchecked_code(), |
1921 SharedFunctionInfo::kCodeOffset); | 1931 SharedFunctionInfo::kCodeOffset); |
1932 TagObject(shared->scope_info(), "(function scope info)"); | |
1933 SetInternalReference(obj, entry, | |
1934 "scope_info", shared->scope_info(), | |
1935 SharedFunctionInfo::kScopeInfoOffset); | |
1922 SetInternalReference(obj, entry, | 1936 SetInternalReference(obj, entry, |
1923 "instance_class_name", shared->instance_class_name(), | 1937 "instance_class_name", shared->instance_class_name(), |
1924 SharedFunctionInfo::kInstanceClassNameOffset); | 1938 SharedFunctionInfo::kInstanceClassNameOffset); |
1925 SetInternalReference(obj, entry, | 1939 SetInternalReference(obj, entry, |
1926 "script", shared->script(), | 1940 "script", shared->script(), |
1927 SharedFunctionInfo::kScriptOffset); | 1941 SharedFunctionInfo::kScriptOffset); |
1942 } else if (obj->IsScript()) { | |
1943 Script* script = Script::cast(obj); | |
1944 SetInternalReference(obj, entry, | |
1945 "source", script->source(), | |
1946 Script::kSourceOffset); | |
1947 SetInternalReference(obj, entry, | |
1948 "name", script->name(), | |
1949 Script::kNameOffset); | |
1950 SetInternalReference(obj, entry, | |
1951 "data", script->data(), | |
1952 Script::kDataOffset); | |
1953 SetInternalReference(obj, entry, | |
1954 "context_data", script->context_data(), | |
1955 Script::kContextOffset); | |
1956 TagObject(script->line_ends(), "(script line ends)"); | |
1957 SetInternalReference(obj, entry, | |
1958 "line_ends", script->line_ends(), | |
1959 Script::kLineEndsOffset); | |
1960 } else if (obj->IsDescriptorArray()) { | |
1961 DescriptorArray* desc_array = DescriptorArray::cast(obj); | |
1962 if (desc_array->length() > DescriptorArray::kContentArrayIndex) { | |
1963 Object* content_array = | |
1964 desc_array->get(DescriptorArray::kContentArrayIndex); | |
1965 TagObject(content_array, "(map descriptor content)"); | |
1966 SetInternalReference(obj, entry, | |
1967 "content", content_array, | |
1968 FixedArray::OffsetOfElementAt( | |
1969 DescriptorArray::kContentArrayIndex)); | |
1970 } | |
1971 } else if (obj->IsCodeCache()) { | |
1972 CodeCache* code_cache = CodeCache::cast(obj); | |
1973 TagObject(code_cache->default_cache(), "(default code cache)"); | |
1974 SetInternalReference(obj, entry, | |
1975 "default_cache", code_cache->default_cache(), | |
1976 CodeCache::kDefaultCacheOffset); | |
1977 TagObject(code_cache->normal_type_cache(), "(code type cache)"); | |
1978 SetInternalReference(obj, entry, | |
1979 "type_cache", code_cache->normal_type_cache(), | |
1980 CodeCache::kNormalTypeCacheOffset); | |
1981 } else if (obj->IsCode()) { | |
1982 Code* code = Code::cast(obj); | |
1983 TagObject(code->unchecked_relocation_info(), "(code relocation info)"); | |
1984 TagObject(code->unchecked_deoptimization_data(), "(code deopt data)"); | |
1985 } | |
1986 if (extract_indexed_refs) { | |
1928 SetInternalReference(obj, entry, "map", obj->map(), HeapObject::kMapOffset); | 1987 SetInternalReference(obj, entry, "map", obj->map(), HeapObject::kMapOffset); |
1929 IndexedReferencesExtractor refs_extractor(this, obj, entry); | 1988 IndexedReferencesExtractor refs_extractor(this, obj, entry); |
1930 obj->Iterate(&refs_extractor); | 1989 obj->Iterate(&refs_extractor); |
1931 } else { | |
1932 SetInternalReference(obj, entry, "map", obj->map(), HeapObject::kMapOffset); | |
1933 IndexedReferencesExtractor refs_extractor(this, obj, entry); | |
1934 obj->Iterate(&refs_extractor); | |
1935 } | 1990 } |
1936 } | 1991 } |
1937 | 1992 |
1938 | 1993 |
1939 void V8HeapExplorer::ExtractClosureReferences(JSObject* js_obj, | 1994 void V8HeapExplorer::ExtractClosureReferences(JSObject* js_obj, |
1940 HeapEntry* entry) { | 1995 HeapEntry* entry) { |
1941 if (js_obj->IsJSFunction()) { | 1996 if (js_obj->IsJSFunction()) { |
1942 HandleScope hs; | 1997 HandleScope hs; |
1943 JSFunction* func = JSFunction::cast(js_obj); | 1998 JSFunction* func = JSFunction::cast(js_obj); |
1944 Context* context = func->context(); | 1999 Context* context = func->context(); |
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2079 ExtractReferences(obj); | 2134 ExtractReferences(obj); |
2080 if (!progress_->ProgressReport(false)) interrupted = true; | 2135 if (!progress_->ProgressReport(false)) interrupted = true; |
2081 } | 2136 } |
2082 } | 2137 } |
2083 if (interrupted) { | 2138 if (interrupted) { |
2084 filler_ = NULL; | 2139 filler_ = NULL; |
2085 return false; | 2140 return false; |
2086 } | 2141 } |
2087 SetRootGcRootsReference(); | 2142 SetRootGcRootsReference(); |
2088 RootsReferencesExtractor extractor(this); | 2143 RootsReferencesExtractor extractor(this); |
2089 HEAP->IterateRoots(&extractor, VISIT_ALL); | 2144 heap_->IterateRoots(&extractor, VISIT_ALL); |
2090 filler_ = NULL; | 2145 filler_ = NULL; |
2091 return progress_->ProgressReport(false); | 2146 return progress_->ProgressReport(false); |
2092 } | 2147 } |
2093 | 2148 |
2094 | 2149 |
2095 void V8HeapExplorer::SetClosureReference(HeapObject* parent_obj, | 2150 void V8HeapExplorer::SetClosureReference(HeapObject* parent_obj, |
2096 HeapEntry* parent_entry, | 2151 HeapEntry* parent_entry, |
2097 String* reference_name, | 2152 String* reference_name, |
2098 Object* child_obj) { | 2153 Object* child_obj) { |
2099 HeapEntry* child_entry = GetEntry(child_obj); | 2154 HeapEntry* child_entry = GetEntry(child_obj); |
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2234 HeapEntry* child_entry = GetEntry(child_obj); | 2289 HeapEntry* child_entry = GetEntry(child_obj); |
2235 if (child_entry != NULL) { | 2290 if (child_entry != NULL) { |
2236 filler_->SetIndexedAutoIndexReference( | 2291 filler_->SetIndexedAutoIndexReference( |
2237 HeapGraphEdge::kElement, | 2292 HeapGraphEdge::kElement, |
2238 kGcRootsObject, snapshot_->gc_roots(), | 2293 kGcRootsObject, snapshot_->gc_roots(), |
2239 child_obj, child_entry); | 2294 child_obj, child_entry); |
2240 } | 2295 } |
2241 } | 2296 } |
2242 | 2297 |
2243 | 2298 |
2299 void V8HeapExplorer::TagObject(Object* obj, const char* tag) { | |
2300 if (obj->IsHeapObject() && | |
2301 !obj->IsOddball() && | |
2302 obj != heap_->raw_unchecked_empty_byte_array() && | |
2303 obj != heap_->raw_unchecked_empty_fixed_array() && | |
2304 obj != heap_->raw_unchecked_empty_fixed_double_array() && | |
2305 obj != heap_->raw_unchecked_empty_descriptor_array()) { | |
2306 objects_tags_.SetTag(obj, tag); | |
2307 } | |
2308 } | |
2309 | |
2310 | |
2244 class GlobalObjectsEnumerator : public ObjectVisitor { | 2311 class GlobalObjectsEnumerator : public ObjectVisitor { |
2245 public: | 2312 public: |
2246 virtual void VisitPointers(Object** start, Object** end) { | 2313 virtual void VisitPointers(Object** start, Object** end) { |
2247 for (Object** p = start; p < end; p++) { | 2314 for (Object** p = start; p < end; p++) { |
2248 if ((*p)->IsGlobalContext()) { | 2315 if ((*p)->IsGlobalContext()) { |
2249 Context* context = Context::cast(*p); | 2316 Context* context = Context::cast(*p); |
2250 JSObject* proxy = context->global_proxy(); | 2317 JSObject* proxy = context->global_proxy(); |
2251 if (proxy->IsJSGlobalProxy()) { | 2318 if (proxy->IsJSGlobalProxy()) { |
2252 Object* global = proxy->map()->prototype(); | 2319 Object* global = proxy->map()->prototype(); |
2253 if (global->IsJSGlobalObject()) { | 2320 if (global->IsJSGlobalObject()) { |
(...skipping 932 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3186 | 3253 |
3187 | 3254 |
3188 String* GetConstructorNameForHeapProfile(JSObject* object) { | 3255 String* GetConstructorNameForHeapProfile(JSObject* object) { |
3189 if (object->IsJSFunction()) return HEAP->closure_symbol(); | 3256 if (object->IsJSFunction()) return HEAP->closure_symbol(); |
3190 return object->constructor_name(); | 3257 return object->constructor_name(); |
3191 } | 3258 } |
3192 | 3259 |
3193 } } // namespace v8::internal | 3260 } } // namespace v8::internal |
3194 | 3261 |
3195 #endif // ENABLE_LOGGING_AND_PROFILING | 3262 #endif // ENABLE_LOGGING_AND_PROFILING |
OLD | NEW |