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 1584 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1595 if (!obj->IsHeapObject()) return; | 1595 if (!obj->IsHeapObject()) return; |
1596 HeapObject* object = HeapObject::cast(obj); | 1596 HeapObject* object = HeapObject::cast(obj); |
1597 HashMap::Entry* cache_entry = | 1597 HashMap::Entry* cache_entry = |
1598 entries_.Lookup(object, HeapEntriesMap::Hash(object), true); | 1598 entries_.Lookup(object, HeapEntriesMap::Hash(object), true); |
1599 if (cache_entry->value == NULL) { | 1599 if (cache_entry->value == NULL) { |
1600 cache_entry->value = HeapEntriesMap::kHeapEntryPlaceholder; | 1600 cache_entry->value = HeapEntriesMap::kHeapEntryPlaceholder; |
1601 } | 1601 } |
1602 } | 1602 } |
1603 | 1603 |
1604 | 1604 |
1605 const char* HeapObjectsSet::GetTag(Object* obj) { | |
1606 HeapObject* object = HeapObject::cast(obj); | |
1607 HashMap::Entry* cache_entry = | |
1608 entries_.Lookup(object, HeapEntriesMap::Hash(object), false); | |
1609 if (cache_entry != NULL | |
1610 && cache_entry->value != HeapEntriesMap::kHeapEntryPlaceholder) { | |
1611 return reinterpret_cast<const char*>(cache_entry->value); | |
1612 } else { | |
1613 return NULL; | |
1614 } | |
1615 } | |
1616 | |
1617 | |
1618 void HeapObjectsSet::SetTag(Object* obj, const char* tag) { | |
1619 if (!obj->IsHeapObject()) return; | |
1620 HeapObject* object = HeapObject::cast(obj); | |
1621 HashMap::Entry* cache_entry = | |
1622 entries_.Lookup(object, HeapEntriesMap::Hash(object), true); | |
1623 cache_entry->value = const_cast<char*>(tag); | |
1624 } | |
1625 | |
1626 | |
1605 HeapObject *const V8HeapExplorer::kInternalRootObject = | 1627 HeapObject *const V8HeapExplorer::kInternalRootObject = |
1606 reinterpret_cast<HeapObject*>( | 1628 reinterpret_cast<HeapObject*>( |
1607 static_cast<intptr_t>(HeapObjectsMap::kInternalRootObjectId)); | 1629 static_cast<intptr_t>(HeapObjectsMap::kInternalRootObjectId)); |
1608 HeapObject *const V8HeapExplorer::kGcRootsObject = | 1630 HeapObject *const V8HeapExplorer::kGcRootsObject = |
1609 reinterpret_cast<HeapObject*>( | 1631 reinterpret_cast<HeapObject*>( |
1610 static_cast<intptr_t>(HeapObjectsMap::kGcRootsObjectId)); | 1632 static_cast<intptr_t>(HeapObjectsMap::kGcRootsObjectId)); |
1611 | 1633 |
1612 | 1634 |
1613 V8HeapExplorer::V8HeapExplorer( | 1635 V8HeapExplorer::V8HeapExplorer( |
1614 HeapSnapshot* snapshot, | 1636 HeapSnapshot* snapshot, |
(...skipping 17 matching lines...) Expand all Loading... | |
1632 | 1654 |
1633 | 1655 |
1634 HeapEntry* V8HeapExplorer::AddEntry(HeapObject* object, | 1656 HeapEntry* V8HeapExplorer::AddEntry(HeapObject* object, |
1635 int children_count, | 1657 int children_count, |
1636 int retainers_count) { | 1658 int retainers_count) { |
1637 if (object == kInternalRootObject) { | 1659 if (object == kInternalRootObject) { |
1638 ASSERT(retainers_count == 0); | 1660 ASSERT(retainers_count == 0); |
1639 return snapshot_->AddRootEntry(children_count); | 1661 return snapshot_->AddRootEntry(children_count); |
1640 } else if (object == kGcRootsObject) { | 1662 } else if (object == kGcRootsObject) { |
1641 return snapshot_->AddGcRootsEntry(children_count, retainers_count); | 1663 return snapshot_->AddGcRootsEntry(children_count, retainers_count); |
1664 } else if (object->IsJSGlobalObject()) { | |
1665 const char* tag = objects_tags_.GetTag(object); | |
1666 const char* name = collection_->names()->GetName( | |
1667 GetConstructorNameForHeapProfile( | |
1668 JSObject::cast(object))); | |
Vitaly Repeshko
2011/05/29 23:01:34
nit: Fits on the previous line?
mnaganov (inactive)
2011/05/30 14:20:42
Done.
| |
1669 if (tag != NULL) { | |
1670 name = collection_->names()->GetFormatted("%s / %s", name, tag); | |
1671 } | |
1672 return AddEntry(object, | |
1673 HeapEntry::kObject, | |
1674 name, | |
1675 children_count, | |
1676 retainers_count); | |
1642 } else if (object->IsJSFunction()) { | 1677 } else if (object->IsJSFunction()) { |
1643 JSFunction* func = JSFunction::cast(object); | 1678 JSFunction* func = JSFunction::cast(object); |
1644 SharedFunctionInfo* shared = func->shared(); | 1679 SharedFunctionInfo* shared = func->shared(); |
1645 return AddEntry(object, | 1680 return AddEntry(object, |
1646 HeapEntry::kClosure, | 1681 HeapEntry::kClosure, |
1647 collection_->names()->GetName(String::cast(shared->name())), | 1682 collection_->names()->GetName(String::cast(shared->name())), |
1648 children_count, | 1683 children_count, |
1649 retainers_count); | 1684 retainers_count); |
1650 } else if (object->IsJSRegExp()) { | 1685 } else if (object->IsJSRegExp()) { |
1651 JSRegExp* re = JSRegExp::cast(object); | 1686 JSRegExp* re = JSRegExp::cast(object); |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1773 generator_->SetHiddenReference(parent_obj_, parent_, next_index_++, *p); | 1808 generator_->SetHiddenReference(parent_obj_, parent_, next_index_++, *p); |
1774 } | 1809 } |
1775 } | 1810 } |
1776 static void MarkVisitedField(HeapObject* obj, int offset) { | 1811 static void MarkVisitedField(HeapObject* obj, int offset) { |
1777 if (offset < 0) return; | 1812 if (offset < 0) return; |
1778 Address field = obj->address() + offset; | 1813 Address field = obj->address() + offset; |
1779 ASSERT(!Memory::Object_at(field)->IsFailure()); | 1814 ASSERT(!Memory::Object_at(field)->IsFailure()); |
1780 ASSERT(Memory::Object_at(field)->IsHeapObject()); | 1815 ASSERT(Memory::Object_at(field)->IsHeapObject()); |
1781 *field |= kFailureTag; | 1816 *field |= kFailureTag; |
1782 } | 1817 } |
1818 | |
1783 private: | 1819 private: |
1784 bool CheckVisitedAndUnmark(Object** field) { | 1820 bool CheckVisitedAndUnmark(Object** field) { |
1785 if ((*field)->IsFailure()) { | 1821 if ((*field)->IsFailure()) { |
1786 intptr_t untagged = reinterpret_cast<intptr_t>(*field) & ~kFailureTagMask; | 1822 intptr_t untagged = reinterpret_cast<intptr_t>(*field) & ~kFailureTagMask; |
1787 *field = reinterpret_cast<Object*>(untagged | kHeapObjectTag); | 1823 *field = reinterpret_cast<Object*>(untagged | kHeapObjectTag); |
1788 ASSERT((*field)->IsHeapObject()); | 1824 ASSERT((*field)->IsHeapObject()); |
1789 return true; | 1825 return true; |
1790 } | 1826 } |
1791 return false; | 1827 return false; |
1792 } | 1828 } |
(...skipping 406 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2199 HeapEntry* child_entry = GetEntry(child_obj); | 2235 HeapEntry* child_entry = GetEntry(child_obj); |
2200 if (child_entry != NULL) { | 2236 if (child_entry != NULL) { |
2201 filler_->SetIndexedAutoIndexReference( | 2237 filler_->SetIndexedAutoIndexReference( |
2202 HeapGraphEdge::kElement, | 2238 HeapGraphEdge::kElement, |
2203 kGcRootsObject, snapshot_->gc_roots(), | 2239 kGcRootsObject, snapshot_->gc_roots(), |
2204 child_obj, child_entry); | 2240 child_obj, child_entry); |
2205 } | 2241 } |
2206 } | 2242 } |
2207 | 2243 |
2208 | 2244 |
2245 class GlobalObjectsCounter : public ObjectVisitor { | |
2246 public: | |
2247 GlobalObjectsCounter() : count_(0) {} | |
2248 void VisitPointers(Object** start, Object** end) { | |
Vitaly Repeshko
2011/05/29 23:01:34
nit: virtual
mnaganov (inactive)
2011/05/30 14:20:42
Done.
| |
2249 for (Object** p = start; p < end; p++) { | |
2250 if ((*p)->IsGlobalContext()) | |
2251 ++count_; | |
2252 } | |
2253 } | |
2254 int count() { return count_; } | |
2255 | |
2256 private: | |
2257 int count_; | |
2258 }; | |
2259 | |
2260 | |
2261 class GlobalObjectsEnumerator : public ObjectVisitor { | |
2262 public: | |
2263 explicit GlobalObjectsEnumerator(int length) | |
2264 : length_(length), | |
2265 count_(0), | |
2266 objects_(NewArray<Handle<JSGlobalObject> >(length)) {} | |
2267 ~GlobalObjectsEnumerator() { | |
2268 DeleteArray(objects_); | |
2269 } | |
2270 void VisitPointers(Object** start, Object** end) { | |
Vitaly Repeshko
2011/05/29 23:01:34
nit: virtual
mnaganov (inactive)
2011/05/30 14:20:42
Done.
| |
2271 for (Object** p = start; count_ < length_ && p < end; p++) { | |
2272 if ((*p)->IsGlobalContext()) { | |
2273 Context* context = Context::cast(*p); | |
2274 JSObject* proxy = context->global_proxy(); | |
2275 if (proxy->IsJSGlobalProxy()) { | |
Vitaly Repeshko
2011/05/29 23:01:34
Given that this loop has more conditions than its
mnaganov (inactive)
2011/05/30 14:20:42
Fixed by eliminating the counter class.
| |
2276 Object* global = proxy->map()->prototype(); | |
2277 if (global->IsJSGlobalObject()) | |
Vitaly Repeshko
2011/05/29 23:01:34
nit: {}
mnaganov (inactive)
2011/05/30 14:20:42
Done.
| |
2278 objects_[count_++] = | |
2279 Handle<JSGlobalObject>(JSGlobalObject::cast(global)); | |
2280 } | |
2281 } | |
2282 } | |
2283 } | |
2284 int count() { return count_; } | |
2285 Handle<JSGlobalObject>* objects() { return objects_; } | |
2286 | |
2287 private: | |
2288 const int length_; | |
2289 int count_; | |
2290 Handle<JSGlobalObject>* objects_; | |
Vitaly Repeshko
2011/05/29 23:01:34
Can we use a growable collection of handles (e.g.
mnaganov (inactive)
2011/05/30 14:20:42
Sure. Sorry, I forgot about their existence.
| |
2291 }; | |
2292 | |
2293 | |
2294 // Modifies heap. Must not be run during heap traversal. | |
2295 void V8HeapExplorer::TagGlobalObjects() { | |
Vitaly Repeshko
2011/05/29 23:01:34
Random idea. I don't know how flexible we want to
mnaganov (inactive)
2011/05/30 14:20:42
Let's discuss it later.
| |
2296 Isolate* isolate = Isolate::Current(); | |
2297 GlobalObjectsCounter counter; | |
2298 isolate->global_handles()->IterateAllRoots(&counter); | |
2299 GlobalObjectsEnumerator enumerator(counter.count()); | |
2300 isolate->global_handles()->IterateAllRoots(&enumerator); | |
2301 Handle<String> document_string = | |
2302 isolate->factory()->NewStringFromAscii(CStrVector("document")); | |
2303 Handle<String> url_string = | |
2304 isolate->factory()->NewStringFromAscii(CStrVector("URL")); | |
2305 const char** urls = NewArray<const char*>(counter.count()); | |
2306 for (int i = 0; i < counter.count(); ++i) { | |
2307 urls[i] = NULL; | |
2308 Handle<JSGlobalObject>& go = enumerator.objects()[i]; | |
Vitaly Repeshko
2011/05/29 23:01:34
Reference is not needed here. "go" is too short.
mnaganov (inactive)
2011/05/30 14:20:42
Removed ref. s/go/global_obj/
| |
2309 Object* obj_document = go->GetPropertyNoExceptionThrown(*document_string); | |
Vitaly Repeshko
2011/05/29 23:01:34
This is not safe, because it asserts on failure/ex
mnaganov (inactive)
2011/05/30 14:20:42
Done.
| |
2310 if (obj_document->IsJSObject()) { | |
2311 JSObject* document = JSObject::cast(obj_document); | |
2312 Object* obj_url = document->GetProperty(*url_string)->ToObjectUnchecked(); | |
Vitaly Repeshko
2011/05/29 23:01:34
Also asserts on failure/exception.
mnaganov (inactive)
2011/05/30 14:20:42
Done.
| |
2313 if (obj_url->IsString()) { | |
2314 urls[i] = collection_->names()->GetName(String::cast(obj_url)); | |
2315 } | |
2316 } | |
2317 } | |
2318 | |
2319 AssertNoAllocation no_allocation; | |
2320 for (int i = 0; i < counter.count(); ++i) { | |
2321 objects_tags_.SetTag(*enumerator.objects()[i], urls[i]); | |
2322 } | |
2323 | |
2324 DeleteArray(urls); | |
2325 } | |
2326 | |
2327 | |
2209 class GlobalHandlesExtractor : public ObjectVisitor { | 2328 class GlobalHandlesExtractor : public ObjectVisitor { |
2210 public: | 2329 public: |
2211 explicit GlobalHandlesExtractor(NativeObjectsExplorer* explorer) | 2330 explicit GlobalHandlesExtractor(NativeObjectsExplorer* explorer) |
2212 : explorer_(explorer) {} | 2331 : explorer_(explorer) {} |
2213 virtual ~GlobalHandlesExtractor() {} | 2332 virtual ~GlobalHandlesExtractor() {} |
2214 virtual void VisitPointers(Object** start, Object** end) { | 2333 virtual void VisitPointers(Object** start, Object** end) { |
2215 UNREACHABLE(); | 2334 UNREACHABLE(); |
2216 } | 2335 } |
2217 virtual void VisitEmbedderReference(Object** p, uint16_t class_id) { | 2336 virtual void VisitEmbedderReference(Object** p, uint16_t class_id) { |
2218 explorer_->VisitSubtreeWrapper(p, class_id); | 2337 explorer_->VisitSubtreeWrapper(p, class_id); |
(...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2441 HeapEntry*) { | 2560 HeapEntry*) { |
2442 entries_->CountReference(parent_ptr, child_ptr); | 2561 entries_->CountReference(parent_ptr, child_ptr); |
2443 } | 2562 } |
2444 void SetNamedAutoIndexReference(HeapGraphEdge::Type, | 2563 void SetNamedAutoIndexReference(HeapGraphEdge::Type, |
2445 HeapThing parent_ptr, | 2564 HeapThing parent_ptr, |
2446 HeapEntry*, | 2565 HeapEntry*, |
2447 HeapThing child_ptr, | 2566 HeapThing child_ptr, |
2448 HeapEntry*) { | 2567 HeapEntry*) { |
2449 entries_->CountReference(parent_ptr, child_ptr); | 2568 entries_->CountReference(parent_ptr, child_ptr); |
2450 } | 2569 } |
2570 | |
2451 private: | 2571 private: |
2452 HeapEntriesMap* entries_; | 2572 HeapEntriesMap* entries_; |
2453 }; | 2573 }; |
2454 | 2574 |
2455 | 2575 |
2456 class SnapshotFiller : public SnapshotFillerInterface { | 2576 class SnapshotFiller : public SnapshotFillerInterface { |
2457 public: | 2577 public: |
2458 explicit SnapshotFiller(HeapSnapshot* snapshot, HeapEntriesMap* entries) | 2578 explicit SnapshotFiller(HeapSnapshot* snapshot, HeapEntriesMap* entries) |
2459 : snapshot_(snapshot), | 2579 : snapshot_(snapshot), |
2460 collection_(snapshot->collection()), | 2580 collection_(snapshot->collection()), |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2512 HeapEntry* child_entry) { | 2632 HeapEntry* child_entry) { |
2513 int child_index, retainer_index; | 2633 int child_index, retainer_index; |
2514 entries_->CountReference( | 2634 entries_->CountReference( |
2515 parent_ptr, child_ptr, &child_index, &retainer_index); | 2635 parent_ptr, child_ptr, &child_index, &retainer_index); |
2516 parent_entry->SetNamedReference(type, | 2636 parent_entry->SetNamedReference(type, |
2517 child_index, | 2637 child_index, |
2518 collection_->names()->GetName(child_index + 1), | 2638 collection_->names()->GetName(child_index + 1), |
2519 child_entry, | 2639 child_entry, |
2520 retainer_index); | 2640 retainer_index); |
2521 } | 2641 } |
2642 | |
2522 private: | 2643 private: |
2523 HeapSnapshot* snapshot_; | 2644 HeapSnapshot* snapshot_; |
2524 HeapSnapshotsCollection* collection_; | 2645 HeapSnapshotsCollection* collection_; |
2525 HeapEntriesMap* entries_; | 2646 HeapEntriesMap* entries_; |
2526 }; | 2647 }; |
2527 | 2648 |
2528 | 2649 |
2529 bool HeapSnapshotGenerator::GenerateSnapshot() { | 2650 bool HeapSnapshotGenerator::GenerateSnapshot() { |
2651 v8_heap_explorer_.TagGlobalObjects(); | |
2652 | |
2530 AssertNoAllocation no_alloc; | 2653 AssertNoAllocation no_alloc; |
2531 | 2654 |
2532 SetProgressTotal(4); // 2 passes + dominators + sizes. | 2655 SetProgressTotal(4); // 2 passes + dominators + sizes. |
2533 | 2656 |
2534 // Pass 1. Iterate heap contents to count entries and references. | 2657 // Pass 1. Iterate heap contents to count entries and references. |
2535 if (!CountEntriesAndReferences()) return false; | 2658 if (!CountEntriesAndReferences()) return false; |
2536 | 2659 |
2537 // Allocate and fill entries in the snapshot, allocate references. | 2660 // Allocate and fill entries in the snapshot, allocate references. |
2538 snapshot_->AllocateEntries(entries_.entries_count(), | 2661 snapshot_->AllocateEntries(entries_.entries_count(), |
2539 entries_.total_children_count(), | 2662 entries_.total_children_count(), |
(...skipping 549 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3089 | 3212 |
3090 | 3213 |
3091 String* GetConstructorNameForHeapProfile(JSObject* object) { | 3214 String* GetConstructorNameForHeapProfile(JSObject* object) { |
3092 if (object->IsJSFunction()) return HEAP->closure_symbol(); | 3215 if (object->IsJSFunction()) return HEAP->closure_symbol(); |
3093 return object->constructor_name(); | 3216 return object->constructor_name(); |
3094 } | 3217 } |
3095 | 3218 |
3096 } } // namespace v8::internal | 3219 } } // namespace v8::internal |
3097 | 3220 |
3098 #endif // ENABLE_LOGGING_AND_PROFILING | 3221 #endif // ENABLE_LOGGING_AND_PROFILING |
OLD | NEW |