Retain maps that have live prototypes.
authorulan <ulan@chromium.org>
Tue, 17 Mar 2015 10:52:00 +0000 (03:52 -0700)
committerCommit bot <commit-bot@chromium.org>
Tue, 17 Mar 2015 10:52:12 +0000 (10:52 +0000)
BUG=v8:3664
LOG=NO

Review URL: https://codereview.chromium.org/1009343002

Cr-Commit-Position: refs/heads/master@{#27233}

src/heap/mark-compact.cc
test/cctest/test-heap.cc

index cbdfadc..f0483c9 100644 (file)
@@ -2153,7 +2153,16 @@ void MarkCompactCollector::RetainMaps() {
         // be created. Do not retain this map.
         continue;
       }
-      new_age = age - 1;
+      Object* prototype = map->prototype();
+      if (prototype->IsHeapObject() &&
+          !Marking::MarkBitFrom(HeapObject::cast(prototype)).Get()) {
+        // The prototype is not marked, age the map.
+        new_age = age - 1;
+      } else {
+        // The prototype and the constructor are marked, this map keeps only
+        // transition tree alive, not JSObjects. Do not age the map.
+        new_age = age;
+      }
       MarkObject(map, map_mark);
     } else {
       new_age = FLAG_retain_maps_for_n_gc;
index d46d59a..65a1214 100644 (file)
@@ -5101,6 +5101,11 @@ void CheckMapRetainingFor(int n) {
   {
     HandleScope inner_scope(isolate);
     Handle<Map> map = Map::Create(isolate, 1);
+    v8::Local<v8::Value> result =
+        CompileRun("(function () { return {x : 10}; })();");
+    Handle<JSObject> proto =
+        v8::Utils::OpenHandle(*v8::Handle<v8::Object>::Cast(result));
+    map->set_prototype(*proto);
     heap->AddRetainedMap(map);
     weak_cell = inner_scope.CloseAndEscape(Map::WeakCellForMap(map));
   }