Merge changes 8634 and 8636 to trunk.

Fix bug in prototype transitions cache clearing introduced by r8165.

Invalid loop nesting causes full cleanup of the prototype transitions cache on
every GC.
Review URL: http://codereview.chromium.org/7342045

git-svn-id: http://v8.googlecode.com/svn/trunk@8640 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/src/mark-compact.cc b/src/mark-compact.cc
index 8e2fe2f..0bf8286 100644
--- a/src/mark-compact.cc
+++ b/src/mark-compact.cc
@@ -1661,31 +1661,34 @@
 
     // Clear dead prototype transitions.
     int number_of_transitions = map->NumberOfProtoTransitions();
-    FixedArray* prototype_transitions = map->unchecked_prototype_transitions();
-    int new_number_of_transitions = 0;
-    const int header = Map::kProtoTransitionHeaderSize;
-    const int proto_offset =
-        header + Map::kProtoTransitionPrototypeOffset;
-    const int map_offset = header + Map::kProtoTransitionMapOffset;
-    const int step = Map::kProtoTransitionElementsPerEntry;
-    for (int i = 0; i < number_of_transitions; i++) {
-      Object* prototype = prototype_transitions->get(proto_offset + i * step);
-      Object* cached_map = prototype_transitions->get(map_offset + i * step);
-      if (HeapObject::cast(prototype)->IsMarked() &&
-          HeapObject::cast(cached_map)->IsMarked()) {
-        if (new_number_of_transitions != i) {
-          prototype_transitions->set_unchecked(
-              heap_,
-              proto_offset + new_number_of_transitions * step,
-              prototype,
-              UPDATE_WRITE_BARRIER);
-          prototype_transitions->set_unchecked(
-              heap_,
-              map_offset + new_number_of_transitions * step,
-              cached_map,
-              SKIP_WRITE_BARRIER);
+    if (number_of_transitions > 0) {
+      FixedArray* prototype_transitions =
+          map->unchecked_prototype_transitions();
+      int new_number_of_transitions = 0;
+      const int header = Map::kProtoTransitionHeaderSize;
+      const int proto_offset =
+          header + Map::kProtoTransitionPrototypeOffset;
+      const int map_offset = header + Map::kProtoTransitionMapOffset;
+      const int step = Map::kProtoTransitionElementsPerEntry;
+      for (int i = 0; i < number_of_transitions; i++) {
+        Object* prototype = prototype_transitions->get(proto_offset + i * step);
+        Object* cached_map = prototype_transitions->get(map_offset + i * step);
+        if (HeapObject::cast(prototype)->IsMarked() &&
+            HeapObject::cast(cached_map)->IsMarked()) {
+          if (new_number_of_transitions != i) {
+            prototype_transitions->set_unchecked(
+                heap_,
+                proto_offset + new_number_of_transitions * step,
+                prototype,
+                UPDATE_WRITE_BARRIER);
+            prototype_transitions->set_unchecked(
+                heap_,
+                map_offset + new_number_of_transitions * step,
+                cached_map,
+                SKIP_WRITE_BARRIER);
+          }
+          new_number_of_transitions++;
         }
-        new_number_of_transitions++;
       }
 
       // Fill slots that became free with undefined value.
diff --git a/src/version.cc b/src/version.cc
index 6b4bfbd..ee5411d 100644
--- a/src/version.cc
+++ b/src/version.cc
@@ -35,7 +35,7 @@
 #define MAJOR_VERSION     3
 #define MINOR_VERSION     4
 #define BUILD_NUMBER      12
-#define PATCH_LEVEL       0
+#define PATCH_LEVEL       1
 // Use 1 for candidates and 0 otherwise.
 // (Boolean macro values are not supported by all preprocessors.)
 #define IS_CANDIDATE_VERSION 0