| 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/v8.h" |     5 #include "src/v8.h" | 
|     6  |     6  | 
|     7 #include "src/heap-snapshot-generator-inl.h" |     7 #include "src/heap-snapshot-generator-inl.h" | 
|     8  |     8  | 
|     9 #include "src/allocation-tracker.h" |     9 #include "src/allocation-tracker.h" | 
|    10 #include "src/code-stubs.h" |    10 #include "src/code-stubs.h" | 
| (...skipping 373 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|   384     // It may occur that some untracked object moves to an address X and there |   384     // It may occur that some untracked object moves to an address X and there | 
|   385     // is a tracked object at that address. In this case we should remove the |   385     // is a tracked object at that address. In this case we should remove the | 
|   386     // entry as we know that the object has died. |   386     // entry as we know that the object has died. | 
|   387     void* to_value = entries_map_.Remove(to, ComputePointerHash(to)); |   387     void* to_value = entries_map_.Remove(to, ComputePointerHash(to)); | 
|   388     if (to_value != NULL) { |   388     if (to_value != NULL) { | 
|   389       int to_entry_info_index = |   389       int to_entry_info_index = | 
|   390           static_cast<int>(reinterpret_cast<intptr_t>(to_value)); |   390           static_cast<int>(reinterpret_cast<intptr_t>(to_value)); | 
|   391       entries_.at(to_entry_info_index).addr = NULL; |   391       entries_.at(to_entry_info_index).addr = NULL; | 
|   392     } |   392     } | 
|   393   } else { |   393   } else { | 
|   394     HashMap::Entry* to_entry = entries_map_.Lookup(to, ComputePointerHash(to), |   394     HashMap::Entry* to_entry = | 
|   395                                                    true); |   395         entries_map_.LookupOrInsert(to, ComputePointerHash(to)); | 
|   396     if (to_entry->value != NULL) { |   396     if (to_entry->value != NULL) { | 
|   397       // We found the existing entry with to address for an old object. |   397       // We found the existing entry with to address for an old object. | 
|   398       // Without this operation we will have two EntryInfo's with the same |   398       // Without this operation we will have two EntryInfo's with the same | 
|   399       // value in addr field. It is bad because later at RemoveDeadEntries |   399       // value in addr field. It is bad because later at RemoveDeadEntries | 
|   400       // one of this entry will be removed with the corresponding entries_map_ |   400       // one of this entry will be removed with the corresponding entries_map_ | 
|   401       // entry. |   401       // entry. | 
|   402       int to_entry_info_index = |   402       int to_entry_info_index = | 
|   403           static_cast<int>(reinterpret_cast<intptr_t>(to_entry->value)); |   403           static_cast<int>(reinterpret_cast<intptr_t>(to_entry->value)); | 
|   404       entries_.at(to_entry_info_index).addr = NULL; |   404       entries_.at(to_entry_info_index).addr = NULL; | 
|   405     } |   405     } | 
| (...skipping 16 matching lines...) Expand all  Loading... | 
|   422   return from_value != NULL; |   422   return from_value != NULL; | 
|   423 } |   423 } | 
|   424  |   424  | 
|   425  |   425  | 
|   426 void HeapObjectsMap::UpdateObjectSize(Address addr, int size) { |   426 void HeapObjectsMap::UpdateObjectSize(Address addr, int size) { | 
|   427   FindOrAddEntry(addr, size, false); |   427   FindOrAddEntry(addr, size, false); | 
|   428 } |   428 } | 
|   429  |   429  | 
|   430  |   430  | 
|   431 SnapshotObjectId HeapObjectsMap::FindEntry(Address addr) { |   431 SnapshotObjectId HeapObjectsMap::FindEntry(Address addr) { | 
|   432   HashMap::Entry* entry = entries_map_.Lookup(addr, ComputePointerHash(addr), |   432   HashMap::Entry* entry = entries_map_.Lookup(addr, ComputePointerHash(addr)); | 
|   433                                               false); |  | 
|   434   if (entry == NULL) return 0; |   433   if (entry == NULL) return 0; | 
|   435   int entry_index = static_cast<int>(reinterpret_cast<intptr_t>(entry->value)); |   434   int entry_index = static_cast<int>(reinterpret_cast<intptr_t>(entry->value)); | 
|   436   EntryInfo& entry_info = entries_.at(entry_index); |   435   EntryInfo& entry_info = entries_.at(entry_index); | 
|   437   DCHECK(static_cast<uint32_t>(entries_.length()) > entries_map_.occupancy()); |   436   DCHECK(static_cast<uint32_t>(entries_.length()) > entries_map_.occupancy()); | 
|   438   return entry_info.id; |   437   return entry_info.id; | 
|   439 } |   438 } | 
|   440  |   439  | 
|   441  |   440  | 
|   442 SnapshotObjectId HeapObjectsMap::FindOrAddEntry(Address addr, |   441 SnapshotObjectId HeapObjectsMap::FindOrAddEntry(Address addr, | 
|   443                                                 unsigned int size, |   442                                                 unsigned int size, | 
|   444                                                 bool accessed) { |   443                                                 bool accessed) { | 
|   445   DCHECK(static_cast<uint32_t>(entries_.length()) > entries_map_.occupancy()); |   444   DCHECK(static_cast<uint32_t>(entries_.length()) > entries_map_.occupancy()); | 
|   446   HashMap::Entry* entry = entries_map_.Lookup(addr, ComputePointerHash(addr), |   445   HashMap::Entry* entry = | 
|   447                                               true); |   446       entries_map_.LookupOrInsert(addr, ComputePointerHash(addr)); | 
|   448   if (entry->value != NULL) { |   447   if (entry->value != NULL) { | 
|   449     int entry_index = |   448     int entry_index = | 
|   450         static_cast<int>(reinterpret_cast<intptr_t>(entry->value)); |   449         static_cast<int>(reinterpret_cast<intptr_t>(entry->value)); | 
|   451     EntryInfo& entry_info = entries_.at(entry_index); |   450     EntryInfo& entry_info = entries_.at(entry_index); | 
|   452     entry_info.accessed = accessed; |   451     entry_info.accessed = accessed; | 
|   453     if (FLAG_heap_profiler_trace_objects) { |   452     if (FLAG_heap_profiler_trace_objects) { | 
|   454       PrintF("Update object size : %p with old size %d and new size %d\n", |   453       PrintF("Update object size : %p with old size %d and new size %d\n", | 
|   455              addr, |   454              addr, | 
|   456              entry_info.size, |   455              entry_info.size, | 
|   457              size); |   456              size); | 
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|   547  |   546  | 
|   548  |   547  | 
|   549 int HeapObjectsMap::FindUntrackedObjects() { |   548 int HeapObjectsMap::FindUntrackedObjects() { | 
|   550   List<HeapObjectInfo> heap_objects(1000); |   549   List<HeapObjectInfo> heap_objects(1000); | 
|   551  |   550  | 
|   552   HeapIterator iterator(heap_); |   551   HeapIterator iterator(heap_); | 
|   553   int untracked = 0; |   552   int untracked = 0; | 
|   554   for (HeapObject* obj = iterator.next(); |   553   for (HeapObject* obj = iterator.next(); | 
|   555        obj != NULL; |   554        obj != NULL; | 
|   556        obj = iterator.next()) { |   555        obj = iterator.next()) { | 
|   557     HashMap::Entry* entry = entries_map_.Lookup( |   556     HashMap::Entry* entry = | 
|   558       obj->address(), ComputePointerHash(obj->address()), false); |   557         entries_map_.Lookup(obj->address(), ComputePointerHash(obj->address())); | 
|   559     if (entry == NULL) { |   558     if (entry == NULL) { | 
|   560       ++untracked; |   559       ++untracked; | 
|   561       if (FLAG_heap_profiler_trace_objects) { |   560       if (FLAG_heap_profiler_trace_objects) { | 
|   562         heap_objects.Add(HeapObjectInfo(obj, 0)); |   561         heap_objects.Add(HeapObjectInfo(obj, 0)); | 
|   563       } |   562       } | 
|   564     } else { |   563     } else { | 
|   565       int entry_index = static_cast<int>( |   564       int entry_index = static_cast<int>( | 
|   566           reinterpret_cast<intptr_t>(entry->value)); |   565           reinterpret_cast<intptr_t>(entry->value)); | 
|   567       EntryInfo& entry_info = entries_.at(entry_index); |   566       EntryInfo& entry_info = entries_.at(entry_index); | 
|   568       if (FLAG_heap_profiler_trace_objects) { |   567       if (FLAG_heap_profiler_trace_objects) { | 
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|   668          entries_.at(0).addr == NULL); |   667          entries_.at(0).addr == NULL); | 
|   669   int first_free_entry = 1; |   668   int first_free_entry = 1; | 
|   670   for (int i = 1; i < entries_.length(); ++i) { |   669   for (int i = 1; i < entries_.length(); ++i) { | 
|   671     EntryInfo& entry_info = entries_.at(i); |   670     EntryInfo& entry_info = entries_.at(i); | 
|   672     if (entry_info.accessed) { |   671     if (entry_info.accessed) { | 
|   673       if (first_free_entry != i) { |   672       if (first_free_entry != i) { | 
|   674         entries_.at(first_free_entry) = entry_info; |   673         entries_.at(first_free_entry) = entry_info; | 
|   675       } |   674       } | 
|   676       entries_.at(first_free_entry).accessed = false; |   675       entries_.at(first_free_entry).accessed = false; | 
|   677       HashMap::Entry* entry = entries_map_.Lookup( |   676       HashMap::Entry* entry = entries_map_.Lookup( | 
|   678           entry_info.addr, ComputePointerHash(entry_info.addr), false); |   677           entry_info.addr, ComputePointerHash(entry_info.addr)); | 
|   679       DCHECK(entry); |   678       DCHECK(entry); | 
|   680       entry->value = reinterpret_cast<void*>(first_free_entry); |   679       entry->value = reinterpret_cast<void*>(first_free_entry); | 
|   681       ++first_free_entry; |   680       ++first_free_entry; | 
|   682     } else { |   681     } else { | 
|   683       if (entry_info.addr) { |   682       if (entry_info.addr) { | 
|   684         entries_map_.Remove(entry_info.addr, |   683         entries_map_.Remove(entry_info.addr, | 
|   685                             ComputePointerHash(entry_info.addr)); |   684                             ComputePointerHash(entry_info.addr)); | 
|   686       } |   685       } | 
|   687     } |   686     } | 
|   688   } |   687   } | 
| (...skipping 25 matching lines...) Expand all  Loading... | 
|   714       GetMemoryUsedByList(time_intervals_); |   713       GetMemoryUsedByList(time_intervals_); | 
|   715 } |   714 } | 
|   716  |   715  | 
|   717  |   716  | 
|   718 HeapEntriesMap::HeapEntriesMap() |   717 HeapEntriesMap::HeapEntriesMap() | 
|   719     : entries_(HashMap::PointersMatch) { |   718     : entries_(HashMap::PointersMatch) { | 
|   720 } |   719 } | 
|   721  |   720  | 
|   722  |   721  | 
|   723 int HeapEntriesMap::Map(HeapThing thing) { |   722 int HeapEntriesMap::Map(HeapThing thing) { | 
|   724   HashMap::Entry* cache_entry = entries_.Lookup(thing, Hash(thing), false); |   723   HashMap::Entry* cache_entry = entries_.Lookup(thing, Hash(thing)); | 
|   725   if (cache_entry == NULL) return HeapEntry::kNoEntry; |   724   if (cache_entry == NULL) return HeapEntry::kNoEntry; | 
|   726   return static_cast<int>(reinterpret_cast<intptr_t>(cache_entry->value)); |   725   return static_cast<int>(reinterpret_cast<intptr_t>(cache_entry->value)); | 
|   727 } |   726 } | 
|   728  |   727  | 
|   729  |   728  | 
|   730 void HeapEntriesMap::Pair(HeapThing thing, int entry) { |   729 void HeapEntriesMap::Pair(HeapThing thing, int entry) { | 
|   731   HashMap::Entry* cache_entry = entries_.Lookup(thing, Hash(thing), true); |   730   HashMap::Entry* cache_entry = entries_.LookupOrInsert(thing, Hash(thing)); | 
|   732   DCHECK(cache_entry->value == NULL); |   731   DCHECK(cache_entry->value == NULL); | 
|   733   cache_entry->value = reinterpret_cast<void*>(static_cast<intptr_t>(entry)); |   732   cache_entry->value = reinterpret_cast<void*>(static_cast<intptr_t>(entry)); | 
|   734 } |   733 } | 
|   735  |   734  | 
|   736  |   735  | 
|   737 HeapObjectsSet::HeapObjectsSet() |   736 HeapObjectsSet::HeapObjectsSet() | 
|   738     : entries_(HashMap::PointersMatch) { |   737     : entries_(HashMap::PointersMatch) { | 
|   739 } |   738 } | 
|   740  |   739  | 
|   741  |   740  | 
|   742 void HeapObjectsSet::Clear() { |   741 void HeapObjectsSet::Clear() { | 
|   743   entries_.Clear(); |   742   entries_.Clear(); | 
|   744 } |   743 } | 
|   745  |   744  | 
|   746  |   745  | 
|   747 bool HeapObjectsSet::Contains(Object* obj) { |   746 bool HeapObjectsSet::Contains(Object* obj) { | 
|   748   if (!obj->IsHeapObject()) return false; |   747   if (!obj->IsHeapObject()) return false; | 
|   749   HeapObject* object = HeapObject::cast(obj); |   748   HeapObject* object = HeapObject::cast(obj); | 
|   750   return entries_.Lookup(object, HeapEntriesMap::Hash(object), false) != NULL; |   749   return entries_.Lookup(object, HeapEntriesMap::Hash(object)) != NULL; | 
|   751 } |   750 } | 
|   752  |   751  | 
|   753  |   752  | 
|   754 void HeapObjectsSet::Insert(Object* obj) { |   753 void HeapObjectsSet::Insert(Object* obj) { | 
|   755   if (!obj->IsHeapObject()) return; |   754   if (!obj->IsHeapObject()) return; | 
|   756   HeapObject* object = HeapObject::cast(obj); |   755   HeapObject* object = HeapObject::cast(obj); | 
|   757   entries_.Lookup(object, HeapEntriesMap::Hash(object), true); |   756   entries_.LookupOrInsert(object, HeapEntriesMap::Hash(object)); | 
|   758 } |   757 } | 
|   759  |   758  | 
|   760  |   759  | 
|   761 const char* HeapObjectsSet::GetTag(Object* obj) { |   760 const char* HeapObjectsSet::GetTag(Object* obj) { | 
|   762   HeapObject* object = HeapObject::cast(obj); |   761   HeapObject* object = HeapObject::cast(obj); | 
|   763   HashMap::Entry* cache_entry = |   762   HashMap::Entry* cache_entry = | 
|   764       entries_.Lookup(object, HeapEntriesMap::Hash(object), false); |   763       entries_.Lookup(object, HeapEntriesMap::Hash(object)); | 
|   765   return cache_entry != NULL |   764   return cache_entry != NULL | 
|   766       ? reinterpret_cast<const char*>(cache_entry->value) |   765       ? reinterpret_cast<const char*>(cache_entry->value) | 
|   767       : NULL; |   766       : NULL; | 
|   768 } |   767 } | 
|   769  |   768  | 
|   770  |   769  | 
|   771 void HeapObjectsSet::SetTag(Object* obj, const char* tag) { |   770 void HeapObjectsSet::SetTag(Object* obj, const char* tag) { | 
|   772   if (!obj->IsHeapObject()) return; |   771   if (!obj->IsHeapObject()) return; | 
|   773   HeapObject* object = HeapObject::cast(obj); |   772   HeapObject* object = HeapObject::cast(obj); | 
|   774   HashMap::Entry* cache_entry = |   773   HashMap::Entry* cache_entry = | 
|   775       entries_.Lookup(object, HeapEntriesMap::Hash(object), true); |   774       entries_.LookupOrInsert(object, HeapEntriesMap::Hash(object)); | 
|   776   cache_entry->value = const_cast<char*>(tag); |   775   cache_entry->value = const_cast<char*>(tag); | 
|   777 } |   776 } | 
|   778  |   777  | 
|   779  |   778  | 
|   780 V8HeapExplorer::V8HeapExplorer( |   779 V8HeapExplorer::V8HeapExplorer( | 
|   781     HeapSnapshot* snapshot, |   780     HeapSnapshot* snapshot, | 
|   782     SnapshottingProgressReportingInterface* progress, |   781     SnapshottingProgressReportingInterface* progress, | 
|   783     v8::HeapProfiler::ObjectNameResolver* resolver) |   782     v8::HeapProfiler::ObjectNameResolver* resolver) | 
|   784     : heap_(snapshot->profiler()->heap_object_map()->heap()), |   783     : heap_(snapshot->profiler()->heap_object_map()->heap()), | 
|   785       snapshot_(snapshot), |   784       snapshot_(snapshot), | 
| (...skipping 1597 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  2383           parent_entry, |  2382           parent_entry, | 
|  2384           "native", |  2383           "native", | 
|  2385           child_entry); |  2384           child_entry); | 
|  2386     } |  2385     } | 
|  2387   } |  2386   } | 
|  2388   isolate->global_handles()->RemoveImplicitRefGroups(); |  2387   isolate->global_handles()->RemoveImplicitRefGroups(); | 
|  2389 } |  2388 } | 
|  2390  |  2389  | 
|  2391 List<HeapObject*>* NativeObjectsExplorer::GetListMaybeDisposeInfo( |  2390 List<HeapObject*>* NativeObjectsExplorer::GetListMaybeDisposeInfo( | 
|  2392     v8::RetainedObjectInfo* info) { |  2391     v8::RetainedObjectInfo* info) { | 
|  2393   HashMap::Entry* entry = |  2392   HashMap::Entry* entry = objects_by_info_.LookupOrInsert(info, InfoHash(info)); | 
|  2394       objects_by_info_.Lookup(info, InfoHash(info), true); |  | 
|  2395   if (entry->value != NULL) { |  2393   if (entry->value != NULL) { | 
|  2396     info->Dispose(); |  2394     info->Dispose(); | 
|  2397   } else { |  2395   } else { | 
|  2398     entry->value = new List<HeapObject*>(4); |  2396     entry->value = new List<HeapObject*>(4); | 
|  2399   } |  2397   } | 
|  2400   return reinterpret_cast<List<HeapObject*>* >(entry->value); |  2398   return reinterpret_cast<List<HeapObject*>* >(entry->value); | 
|  2401 } |  2399 } | 
|  2402  |  2400  | 
|  2403  |  2401  | 
|  2404 bool NativeObjectsExplorer::IterateAndExtractReferences( |  2402 bool NativeObjectsExplorer::IterateAndExtractReferences( | 
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  2453 }; |  2451 }; | 
|  2454  |  2452  | 
|  2455  |  2453  | 
|  2456 NativeGroupRetainedObjectInfo* NativeObjectsExplorer::FindOrAddGroupInfo( |  2454 NativeGroupRetainedObjectInfo* NativeObjectsExplorer::FindOrAddGroupInfo( | 
|  2457     const char* label) { |  2455     const char* label) { | 
|  2458   const char* label_copy = names_->GetCopy(label); |  2456   const char* label_copy = names_->GetCopy(label); | 
|  2459   uint32_t hash = StringHasher::HashSequentialString( |  2457   uint32_t hash = StringHasher::HashSequentialString( | 
|  2460       label_copy, |  2458       label_copy, | 
|  2461       static_cast<int>(strlen(label_copy)), |  2459       static_cast<int>(strlen(label_copy)), | 
|  2462       isolate_->heap()->HashSeed()); |  2460       isolate_->heap()->HashSeed()); | 
|  2463   HashMap::Entry* entry = native_groups_.Lookup(const_cast<char*>(label_copy), |  2461   HashMap::Entry* entry = | 
|  2464                                                 hash, true); |  2462       native_groups_.LookupOrInsert(const_cast<char*>(label_copy), hash); | 
|  2465   if (entry->value == NULL) { |  2463   if (entry->value == NULL) { | 
|  2466     entry->value = new NativeGroupRetainedObjectInfo(label); |  2464     entry->value = new NativeGroupRetainedObjectInfo(label); | 
|  2467   } |  2465   } | 
|  2468   return static_cast<NativeGroupRetainedObjectInfo*>(entry->value); |  2466   return static_cast<NativeGroupRetainedObjectInfo*>(entry->value); | 
|  2469 } |  2467 } | 
|  2470  |  2468  | 
|  2471  |  2469  | 
|  2472 void NativeObjectsExplorer::SetNativeRootReference( |  2470 void NativeObjectsExplorer::SetNativeRootReference( | 
|  2473     v8::RetainedObjectInfo* info) { |  2471     v8::RetainedObjectInfo* info) { | 
|  2474   HeapEntry* child_entry = |  2472   HeapEntry* child_entry = | 
| (...skipping 290 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  2765   writer_->AddString("\"strings\":["); |  2763   writer_->AddString("\"strings\":["); | 
|  2766   SerializeStrings(); |  2764   SerializeStrings(); | 
|  2767   if (writer_->aborted()) return; |  2765   if (writer_->aborted()) return; | 
|  2768   writer_->AddCharacter(']'); |  2766   writer_->AddCharacter(']'); | 
|  2769   writer_->AddCharacter('}'); |  2767   writer_->AddCharacter('}'); | 
|  2770   writer_->Finalize(); |  2768   writer_->Finalize(); | 
|  2771 } |  2769 } | 
|  2772  |  2770  | 
|  2773  |  2771  | 
|  2774 int HeapSnapshotJSONSerializer::GetStringId(const char* s) { |  2772 int HeapSnapshotJSONSerializer::GetStringId(const char* s) { | 
|  2775   HashMap::Entry* cache_entry = strings_.Lookup( |  2773   HashMap::Entry* cache_entry = | 
|  2776       const_cast<char*>(s), StringHash(s), true); |  2774       strings_.LookupOrInsert(const_cast<char*>(s), StringHash(s)); | 
|  2777   if (cache_entry->value == NULL) { |  2775   if (cache_entry->value == NULL) { | 
|  2778     cache_entry->value = reinterpret_cast<void*>(next_string_id_++); |  2776     cache_entry->value = reinterpret_cast<void*>(next_string_id_++); | 
|  2779   } |  2777   } | 
|  2780   return static_cast<int>(reinterpret_cast<intptr_t>(cache_entry->value)); |  2778   return static_cast<int>(reinterpret_cast<intptr_t>(cache_entry->value)); | 
|  2781 } |  2779 } | 
|  2782  |  2780  | 
|  2783  |  2781  | 
|  2784 namespace { |  2782 namespace { | 
|  2785  |  2783  | 
|  2786 template<size_t size> struct ToUnsigned; |  2784 template<size_t size> struct ToUnsigned; | 
| (...skipping 379 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  3166   writer_->AddString("\"<dummy>\""); |  3164   writer_->AddString("\"<dummy>\""); | 
|  3167   for (int i = 1; i < sorted_strings.length(); ++i) { |  3165   for (int i = 1; i < sorted_strings.length(); ++i) { | 
|  3168     writer_->AddCharacter(','); |  3166     writer_->AddCharacter(','); | 
|  3169     SerializeString(sorted_strings[i]); |  3167     SerializeString(sorted_strings[i]); | 
|  3170     if (writer_->aborted()) return; |  3168     if (writer_->aborted()) return; | 
|  3171   } |  3169   } | 
|  3172 } |  3170 } | 
|  3173  |  3171  | 
|  3174  |  3172  | 
|  3175 } }  // namespace v8::internal |  3173 } }  // namespace v8::internal | 
| OLD | NEW |