Revision: 11259
Author:   [email protected]
Date:     Tue Apr 10 23:58:42 2012
Log:      I'd like to add addr field into EntryInfo struct.
This will give us the ability to keep entries_ list sorted by id.
And based on that fact we will be able to use it for:
1) GetNodeById method and drop sorted version of entries list in HeapSnapshot;
2) building heap stats;
3) doing the fill stage instead of second iteration over heap.

BUG=none
TEST=none
R=yurys

Review URL: https://chromiumcodereview.appspot.com/10031032
http://code.google.com/p/v8/source/detail?r=11259

Modified:
 /branches/bleeding_edge/src/hashmap.h
 /branches/bleeding_edge/src/profile-generator.cc
 /branches/bleeding_edge/src/profile-generator.h

=======================================
--- /branches/bleeding_edge/src/hashmap.h       Thu Mar 15 08:01:59 2012
+++ /branches/bleeding_edge/src/hashmap.h       Tue Apr 10 23:58:42 2012
@@ -63,7 +63,9 @@
   Entry* Lookup(void* key, uint32_t hash, bool insert);

   // Removes the entry with matching key.
-  void Remove(void* key, uint32_t hash);
+  // It returns the value of the deleted entry
+  // or null if there is no value for such key.
+  void* Remove(void* key, uint32_t hash);

   // Empties the hash map (occupancy() == 0).
   void Clear();
@@ -146,14 +148,15 @@


 template<class P>
-void TemplateHashMapImpl<P>::Remove(void* key, uint32_t hash) {
+void* TemplateHashMapImpl<P>::Remove(void* key, uint32_t hash) {
   // Lookup the entry for the key to remove.
   Entry* p = Probe(key, hash);
   if (p->key == NULL) {
     // Key not found nothing to remove.
-    return;
+    return NULL;
   }

+  void* value = p->value;
   // To remove an entry we need to ensure that it does not create an empty
// entry that will cause the search for another entry to stop too soon. If all // the entries between the entry to remove and the next empty slot have their
@@ -202,6 +205,7 @@
   // Clear the entry which is allowed to en emptied.
   p->key = NULL;
   occupancy_--;
+  return value;
 }


=======================================
--- /branches/bleeding_edge/src/profile-generator.cc Tue Apr 10 04:24:09 2012 +++ /branches/bleeding_edge/src/profile-generator.cc Tue Apr 10 23:58:42 2012
@@ -1315,7 +1315,16 @@
     : initial_fill_mode_(true),
       next_id_(kFirstAvailableObjectId),
       entries_map_(AddressesMatch),
-      entries_(new List<EntryInfo>()) { }
+      entries_(new List<EntryInfo>()) {
+  // This dummy element solves a problem with entries_map_.
+  // When we do lookup in HashMap we see no difference between two cases:
+  // it has an entry with NULL as the value or it has created
+  // a new entry on the fly with NULL as the default value.
+ // With such dummy element we have a guaranty that all entries_map_ entries
+  // will have the value field grater than 0.
+  // This fact is using in MoveObject method.
+  entries_->Add(EntryInfo(0, NULL));
+}


 HeapObjectsMap::~HeapObjectsMap() {
@@ -1337,31 +1346,47 @@
   SnapshotObjectId id = next_id_;
   next_id_ += kObjectIdStep;
   AddEntry(addr, id);
+  // Here and in other places the length of entries_ list has to be
+  // the same or greater than the length of entries_map_. But entries_ list
+  // has a dummy element at index 0.
+ ASSERT(static_cast<uint32_t>(entries_->length()) > entries_map_.occupancy());
   return id;
 }


 void HeapObjectsMap::MoveObject(Address from, Address to) {
+  ASSERT(to != NULL);
+  ASSERT(from != NULL);
   if (from == to) return;
- HashMap::Entry* entry = entries_map_.Lookup(from, AddressHash(from), false);
-  if (entry != NULL) {
-    void* value = entry->value;
-    entries_map_.Remove(from, AddressHash(from));
-    if (to != NULL) {
-      entry = entries_map_.Lookup(to, AddressHash(to), true);
- // We can have an entry at the new location, it is OK, as GC can overwrite
-      // dead objects with alive objects being moved.
-      entry->value = value;
-    }
-  }
+  void* from_value = entries_map_.Remove(from, AddressHash(from));
+  if (from_value == NULL) return;
+  int from_entry_info_index =
+      static_cast<int>(reinterpret_cast<intptr_t>(from_value));
+  entries_->at(from_entry_info_index).addr = to;
+ HashMap::Entry* to_entry = entries_map_.Lookup(to, AddressHash(to), true);
+  if (to_entry->value != NULL) {
+    int to_entry_info_index =
+        static_cast<int>(reinterpret_cast<intptr_t>(to_entry->value));
+    // Without this operation we will have two EntryInfo's with the same
+    // value in addr field. It is bad because later at RemoveDeadEntries
+ // one of this entry will be removed with the corresponding entries_map_
+    // entry.
+    entries_->at(to_entry_info_index).addr = NULL;
+  }
+  to_entry->value = reinterpret_cast<void*>(from_entry_info_index);
 }


 void HeapObjectsMap::AddEntry(Address addr, SnapshotObjectId id) {
HashMap::Entry* entry = entries_map_.Lookup(addr, AddressHash(addr), true);
   ASSERT(entry->value == NULL);
+  ASSERT(entries_->length() > 0 &&
+         entries_->at(0).id == 0 &&
+         entries_->at(0).addr == NULL);
+  ASSERT(entries_->at(entries_->length() - 1).id < id);
   entry->value = reinterpret_cast<void*>(entries_->length());
-  entries_->Add(EntryInfo(id));
+  entries_->Add(EntryInfo(id, addr));
+ ASSERT(static_cast<uint32_t>(entries_->length()) > entries_map_.occupancy());
 }


@@ -1372,6 +1397,8 @@
         static_cast<int>(reinterpret_cast<intptr_t>(entry->value));
     EntryInfo& entry_info = entries_->at(entry_index);
     entry_info.accessed = true;
+    ASSERT(static_cast<uint32_t>(entries_->length()) >
+           entries_map_.occupancy());
     return entry_info.id;
   } else {
     return 0;
@@ -1380,28 +1407,31 @@


 void HeapObjectsMap::RemoveDeadEntries() {
-  List<EntryInfo>* new_entries = new List<EntryInfo>();
-  List<void*> dead_entries;
-  for (HashMap::Entry* entry = entries_map_.Start();
-       entry != NULL;
-       entry = entries_map_.Next(entry)) {
-    int entry_index =
-        static_cast<int>(reinterpret_cast<intptr_t>(entry->value));
-    EntryInfo& entry_info = entries_->at(entry_index);
+  ASSERT(entries_->length() > 0 &&
+         entries_->at(0).id == 0 &&
+         entries_->at(0).addr == NULL);
+  int first_free_entry = 1;
+  for (int i = 1; i < entries_->length(); ++i) {
+    EntryInfo& entry_info = entries_->at(i);
     if (entry_info.accessed) {
-      entry->value = reinterpret_cast<void*>(new_entries->length());
-      new_entries->Add(EntryInfo(entry_info.id, false));
+      if (first_free_entry != i) {
+        entries_->at(first_free_entry) = entry_info;
+      }
+      entries_->at(first_free_entry).accessed = false;
+      HashMap::Entry* entry = entries_map_.Lookup(
+          entry_info.addr, AddressHash(entry_info.addr), false);
+      ASSERT(entry);
+      entry->value = reinterpret_cast<void*>(first_free_entry);
+      ++first_free_entry;
     } else {
-      dead_entries.Add(entry->key);
+      if (entry_info.addr) {
+        entries_map_.Remove(entry_info.addr, AddressHash(entry_info.addr));
+      }
     }
   }
-  for (int i = 0; i < dead_entries.length(); ++i) {
-    void* raw_entry = dead_entries[i];
-    entries_map_.Remove(
-        raw_entry, AddressHash(reinterpret_cast<Address>(raw_entry)));
-  }
-  delete entries_;
-  entries_ = new_entries;
+  entries_->Rewind(first_free_entry);
+  ASSERT(static_cast<uint32_t>(entries_->length()) - 1 ==
+         entries_map_.occupancy());
 }


=======================================
--- /branches/bleeding_edge/src/profile-generator.h     Sun Apr  8 12:18:06 2012
+++ /branches/bleeding_edge/src/profile-generator.h     Tue Apr 10 23:58:42 2012
@@ -722,11 +722,12 @@

  private:
   struct EntryInfo {
-    explicit EntryInfo(SnapshotObjectId id) : id(id), accessed(true) { }
-    EntryInfo(SnapshotObjectId id, bool accessed)
-      : id(id),
-        accessed(accessed) { }
+    EntryInfo(SnapshotObjectId id, Address addr)
+      : id(id), addr(addr), accessed(true) { }
+    EntryInfo(SnapshotObjectId id, Address addr, bool accessed)
+      : id(id), addr(addr), accessed(accessed) { }
     SnapshotObjectId id;
+    Address addr;
     bool accessed;
   };

--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev

Reply via email to