Index: src/profile-generator.h |
diff --git a/src/profile-generator.h b/src/profile-generator.h |
index 4e423c8d920640fa7b663cda5225c6ea510b7d1f..205458098da5c89ee52e668bd4b7e22cf8f4830b 100644 |
--- a/src/profile-generator.h |
+++ b/src/profile-generator.h |
@@ -74,7 +74,7 @@ class StringsStorage { |
reinterpret_cast<char*>(key2)) == 0; |
} |
- // String::Hash -> const char* |
+ // Mapping of strings by String::Hash to const char* strings. |
HashMap names_; |
DISALLOW_COPY_AND_ASSIGN(StringsStorage); |
@@ -156,7 +156,7 @@ class ProfileNode { |
CodeEntry* entry_; |
unsigned total_ticks_; |
unsigned self_ticks_; |
- // CodeEntry* -> ProfileNode* |
+ // Mapping from CodeEntry* to ProfileNode* |
HashMap children_; |
List<ProfileNode*> children_list_; |
@@ -312,11 +312,12 @@ class CpuProfilesCollection { |
} |
StringsStorage function_and_resource_names_; |
- // args_count -> char* |
+ // Mapping from args_count (int) to char* strings. |
List<char*> args_count_names_; |
List<CodeEntry*> code_entries_; |
List<List<CpuProfile*>* > profiles_by_token_; |
- // uid -> index |
+ // Mapping from profiles' uids to indexes in the second nested list |
+ // of profiles_by_token_. |
HashMap profiles_uids_; |
// Accessed by VM thread and profile generator thread. |
@@ -482,6 +483,7 @@ class HeapEntry { |
visited_(false), |
type_(INTERNAL), |
name_(""), |
+ id_(0), |
next_auto_index_(0), |
self_size_(0), |
security_token_id_(TokenEnumerator::kNoSecurityToken), |
@@ -494,12 +496,14 @@ class HeapEntry { |
HeapEntry(HeapSnapshot* snapshot, |
Type type, |
const char* name, |
+ int id, |
int self_size, |
int security_token_id) |
: snapshot_(snapshot), |
visited_(false), |
type_(type), |
name_(name), |
+ id_(id), |
next_auto_index_(1), |
self_size_(self_size), |
security_token_id_(security_token_id), |
@@ -514,6 +518,7 @@ class HeapEntry { |
bool visited() const { return visited_; } |
Type type() const { return type_; } |
const char* name() const { return name_; } |
+ uint64_t id() const { return id_; } |
int self_size() const { return self_size_; } |
int security_token_id() const { return security_token_id_; } |
bool painted_reachable() { return painted_ == kPaintReachable; } |
@@ -524,9 +529,13 @@ class HeapEntry { |
const List<HeapGraphEdge*>* retainers() const { return &retainers_; } |
const List<HeapGraphPath*>* GetRetainingPaths(); |
+ template<class Visitor> |
+ void ApplyAndPaintAllReachable(Visitor* visitor); |
+ |
void ClearPaint() { painted_ = kUnpainted; } |
void CutEdges(); |
void MarkAsVisited() { visited_ = true; } |
+ void PaintAllReachable(); |
void PaintReachable() { |
ASSERT(painted_ == kUnpainted); |
painted_ = kPaintReachable; |
@@ -537,6 +546,7 @@ class HeapEntry { |
void SetInternalReference(const char* name, HeapEntry* entry); |
void SetPropertyReference(const char* name, HeapEntry* entry); |
void SetAutoIndexReference(HeapEntry* entry); |
+ void SetUnidirAutoIndexReference(HeapEntry* entry); |
int TotalSize(); |
int NonSharedTotalSize(); |
@@ -557,6 +567,7 @@ class HeapEntry { |
bool visited_; |
Type type_; |
const char* name_; |
+ uint64_t id_; |
int next_auto_index_; |
int self_size_; |
int security_token_id_; |
@@ -607,6 +618,8 @@ class HeapEntriesMap { |
HeapEntry* Map(HeapObject* object); |
void Pair(HeapObject* object, HeapEntry* entry); |
+ uint32_t capacity() { return entries_.capacity(); } |
+ |
private: |
INLINE(uint32_t Hash(HeapObject* object)) { |
return static_cast<uint32_t>(reinterpret_cast<intptr_t>(object)); |
@@ -627,6 +640,7 @@ class HeapEntriesMap { |
class HeapSnapshotsCollection; |
+class HeapSnapshotsDiff; |
// HeapSnapshot represents a single heap snapshot. It is stored in |
// HeapSnapshotsCollection, which is also a factory for |
@@ -638,6 +652,7 @@ class HeapSnapshot { |
HeapSnapshot(HeapSnapshotsCollection* collection, |
const char* title, |
unsigned uid); |
+ ~HeapSnapshot(); |
void ClearPaint(); |
void CutObjectsFromForeignSecurityContexts(); |
HeapEntry* GetEntry(Object* object); |
@@ -655,6 +670,8 @@ class HeapSnapshot { |
HeapEntry* root() { return &root_; } |
template<class Visitor> |
void IterateEntries(Visitor* visitor) { entries_.Apply(visitor); } |
+ List<HeapEntry*>* GetSortedEntriesList(); |
+ HeapSnapshotsDiff* CompareWith(HeapSnapshot* snapshot); |
void Print(int max_depth); |
@@ -679,19 +696,108 @@ class HeapSnapshot { |
const char* title_; |
unsigned uid_; |
HeapEntry root_; |
- // HeapObject* -> HeapEntry* |
+ // Mapping from HeapObject* pointers to HeapEntry* pointers. |
HeapEntriesMap entries_; |
+ // Entries sorted by id. |
+ List<HeapEntry*>* sorted_entries_; |
DISALLOW_COPY_AND_ASSIGN(HeapSnapshot); |
}; |
+class HeapObjectsMap { |
+ public: |
+ HeapObjectsMap(); |
+ ~HeapObjectsMap(); |
+ |
+ void SnapshotGenerationFinished(); |
+ uint64_t FindObject(Address addr); |
+ void MoveObject(Address from, Address to); |
+ |
+ private: |
+ struct EntryInfo { |
+ explicit EntryInfo(uint64_t id) : id(id), accessed(true) { } |
+ EntryInfo(uint64_t id, bool accessed) : id(id), accessed(accessed) { } |
+ uint64_t id; |
+ bool accessed; |
+ }; |
+ |
+ void AddEntry(Address addr, uint64_t id); |
+ uint64_t FindEntry(Address addr); |
+ void RemoveDeadEntries(); |
+ |
+ static bool AddressesMatch(void* key1, void* key2) { |
+ return key1 == key2; |
+ } |
+ |
+ static uint32_t AddressHash(Address addr) { |
+ return static_cast<int32_t>(reinterpret_cast<intptr_t>(addr)); |
+ } |
+ |
+ bool initial_fill_mode_; |
+ uint64_t next_id_; |
+ HashMap entries_map_; |
+ List<EntryInfo>* entries_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(HeapObjectsMap); |
+}; |
+ |
+ |
+class HeapSnapshotsDiff { |
+ public: |
+ HeapSnapshotsDiff(HeapSnapshot* snapshot1, HeapSnapshot* snapshot2) |
+ : snapshot1_(snapshot1), |
+ snapshot2_(snapshot2), |
+ additions_root_(new HeapEntry(snapshot2)), |
+ deletions_root_(new HeapEntry(snapshot1)) { } |
+ |
+ ~HeapSnapshotsDiff() { |
+ delete deletions_root_; |
+ delete additions_root_; |
+ } |
+ |
+ void AddAddedEntry(HeapEntry* entry) { |
+ additions_root_->SetUnidirAutoIndexReference(entry); |
+ } |
+ |
+ void AddDeletedEntry(HeapEntry* entry) { |
+ deletions_root_->SetUnidirAutoIndexReference(entry); |
+ } |
+ |
+ const HeapEntry* additions_root() const { return additions_root_; } |
+ const HeapEntry* deletions_root() const { return deletions_root_; } |
+ |
+ private: |
+ HeapSnapshot* snapshot1_; |
+ HeapSnapshot* snapshot2_; |
+ HeapEntry* additions_root_; |
+ HeapEntry* deletions_root_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(HeapSnapshotsDiff); |
+}; |
+ |
+ |
+class HeapSnapshotsComparator { |
+ public: |
+ HeapSnapshotsComparator() { } |
+ ~HeapSnapshotsComparator(); |
+ HeapSnapshotsDiff* Compare(HeapSnapshot* snapshot1, HeapSnapshot* snapshot2); |
+ private: |
+ List<HeapSnapshotsDiff*> diffs_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(HeapSnapshotsComparator); |
+}; |
+ |
+ |
class HeapSnapshotsCollection { |
public: |
HeapSnapshotsCollection(); |
~HeapSnapshotsCollection(); |
+ bool is_tracking_objects() { return is_tracking_objects_; } |
+ |
HeapSnapshot* NewSnapshot(const char* name, unsigned uid); |
+ void SnapshotGenerationFinished() { ids_.SnapshotGenerationFinished(); } |
List<HeapSnapshot*>* snapshots() { return &snapshots_; } |
HeapSnapshot* GetSnapshot(unsigned uid); |
@@ -699,16 +805,26 @@ class HeapSnapshotsCollection { |
TokenEnumerator* token_enumerator() { return token_enumerator_; } |
+ uint64_t GetObjectId(Address addr) { return ids_.FindObject(addr); } |
+ void ObjectMoveEvent(Address from, Address to) { ids_.MoveObject(from, to); } |
+ |
+ HeapSnapshotsDiff* CompareSnapshots(HeapSnapshot* snapshot1, |
+ HeapSnapshot* snapshot2); |
+ |
private: |
INLINE(static bool HeapSnapshotsMatch(void* key1, void* key2)) { |
return key1 == key2; |
} |
+ bool is_tracking_objects_; // Whether tracking object moves is needed. |
List<HeapSnapshot*> snapshots_; |
- // uid -> HeapSnapshot* |
+ // Mapping from snapshots' uids to HeapSnapshot* pointers. |
HashMap snapshots_uids_; |
StringsStorage names_; |
TokenEnumerator* token_enumerator_; |
+ // Mapping from HeapObject addresses to objects' uids. |
+ HeapObjectsMap ids_; |
+ HeapSnapshotsComparator comparator_; |
DISALLOW_COPY_AND_ASSIGN(HeapSnapshotsCollection); |
}; |