Reviewers: danno,

Description:
Merged r11831 into trunk branch.

Revert part of 11727 as it sometimes tanked V8 benchmark (raytrace) performance for reasons that are not obvious. Now we make objects into fast-case objects when they are made prototypes for other objects, but we do not mark objects that are already fast case with a bit that helps keep them in fast case. Review URL:
https://chromiumcodereview.appspot.com/10556004

[email protected]
BUG=
TEST=


Please review this at https://chromiumcodereview.appspot.com/10564002/

SVN Base: https://v8.googlecode.com/svn/trunk

Affected files:
  M src/objects-inl.h
  M src/objects.h
  M src/objects.cc
  M src/version.cc
  M test/cctest/test-heap.cc
  M test/mjsunit/fast-prototype.js


Index: src/objects-inl.h
diff --git a/src/objects-inl.h b/src/objects-inl.h
index da1a35b08be6659e7fe3806ef7f64891b787d410..4f66af28aa7506870f9e54e9b97a7fd5f7ffe3a1 100644
--- a/src/objects-inl.h
+++ b/src/objects-inl.h
@@ -1616,8 +1616,7 @@ bool JSObject::TooManyFastProperties(int properties,
   int inobject = map()->inobject_properties();

   int limit;
-  if (store_mode == CERTAINLY_NOT_STORE_FROM_KEYED ||
-      map()->used_for_prototype()) {
+  if (store_mode == CERTAINLY_NOT_STORE_FROM_KEYED) {
     limit = Max(inobject, kMaxFastProperties);
   } else {
     limit = Max(inobject, kFastPropertiesSoftLimit);
@@ -2982,20 +2981,6 @@ bool Map::is_shared() {
 }


-void Map::set_used_for_prototype(bool value) {
-  if (value) {
-    set_bit_field3(bit_field3() | (1 << kUsedForPrototype));
-  } else {
-    set_bit_field3(bit_field3() & ~(1 << kUsedForPrototype));
-  }
-}
-
-
-bool Map::used_for_prototype() {
-  return ((1 << kUsedForPrototype) & bit_field3()) != 0;
-}
-
-
 JSFunction* Map::unchecked_constructor() {
return reinterpret_cast<JSFunction*>(READ_FIELD(this, kConstructorOffset));
 }
Index: src/objects.cc
diff --git a/src/objects.cc b/src/objects.cc
index 329a0c562b25407036bb24d51bb6e2398da2e6d5..b6cd328528d7f61a12f6e41de68a605b5f49bfeb 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -7515,34 +7515,11 @@ MaybeObject* JSObject::OptimizeAsPrototype() {
   // Make sure prototypes are fast objects and their maps have the bit set
   // so they remain fast.
   Map* proto_map = map();
-  if (!proto_map->used_for_prototype()) {
-    if (!HasFastProperties()) {
-      MaybeObject* new_proto = TransformToFastProperties(0);
-      if (new_proto->IsFailure()) return new_proto;
-      ASSERT(new_proto == this);
-      proto_map = map();
-      if (!proto_map->is_shared()) {
-        proto_map->set_used_for_prototype(true);
-      }
-    } else {
-      Heap* heap = GetHeap();
- // We use the hole value as a singleton key in the prototype transition
-      // map so that we don't multiply the number of maps unnecessarily.
-      Map* new_map =
-          proto_map->GetPrototypeTransition(heap->the_hole_value());
-      if (new_map == NULL) {
-        MaybeObject* maybe_new_map =
-            proto_map->CopyDropTransitions(DescriptorArray::MAY_BE_SHARED);
-        if (!maybe_new_map->To<Map>(&new_map)) return maybe_new_map;
-        new_map->set_used_for_prototype(true);
-        MaybeObject* ok =
-            proto_map->PutPrototypeTransition(heap->the_hole_value(),
-                                              new_map);
-        if (ok->IsFailure()) return ok;
-      }
-      ASSERT(!proto_map->is_shared() && !new_map->is_shared());
-      set_map(new_map);
-    }
+  if (!HasFastProperties()) {
+    MaybeObject* new_proto = TransformToFastProperties(0);
+    if (new_proto->IsFailure()) return new_proto;
+    ASSERT(new_proto == this);
+    proto_map = map();
   }
   return this;
 }
@@ -7552,8 +7529,8 @@ MaybeObject* JSFunction::SetInstancePrototype(Object* value) {
   ASSERT(value->IsJSReceiver());
   Heap* heap = GetHeap();

-  // First some logic for the map of the prototype to make sure the
-  // used_for_prototype flag is set.
+ // First some logic for the map of the prototype to make sure it is in fast
+  // mode.
   if (value->IsJSObject()) {
     MaybeObject* ok = JSObject::cast(value)->OptimizeAsPrototype();
     if (ok->IsFailure()) return ok;
Index: src/objects.h
diff --git a/src/objects.h b/src/objects.h
index 15ecdd1412c5e10a3a0fd564e3aa55c4f2a56633..9aa3fd1db36a63dbee32c8631b71a157f2c9e958 100644
--- a/src/objects.h
+++ b/src/objects.h
@@ -4749,14 +4749,6 @@ class Map: public HeapObject {
   inline void set_is_shared(bool value);
   inline bool is_shared();

- // Tells whether the map is used for an object that is a prototype for another - // object or is the prototype on a function. Such maps are made faster by - // tweaking the heuristics that distinguish between regular object-oriented - // objects and the objects that are being used as hash maps. This flag is
-  // for optimization, not correctness.
-  inline void set_used_for_prototype(bool value);
-  inline bool used_for_prototype();
-
   // Tells whether the instance needs security checks when accessing its
   // properties.
   inline void set_is_access_check_needed(bool access_check_needed);
@@ -4944,9 +4936,7 @@ class Map: public HeapObject {
// the original map. That way we can transition to the same map if the same
   // prototype is set, rather than creating a new map every time.  The
// transitions are in the form of a map where the keys are prototype objects
-  // and the values are the maps the are transitioned to.  The special key
-  // the_hole denotes the map we should transition to when the
-  // used_for_prototype flag is set.
+  // and the values are the maps the are transitioned to.
   static const int kMaxCachedPrototypeTransitions = 256;

   Map* GetPrototypeTransition(Object* prototype);
@@ -5042,7 +5032,6 @@ class Map: public HeapObject {
   // Bit positions for bit field 3
   static const int kIsShared = 0;
   static const int kFunctionWithPrototype = 1;
-  static const int kUsedForPrototype = 2;

   typedef FixedBodyDescriptor<kPointerFieldsBeginOffset,
                               kPointerFieldsEndOffset,
Index: src/version.cc
diff --git a/src/version.cc b/src/version.cc
index 39d5fef7278a6501900c3441c6846f0c372d2ecd..7a087fcbff2bd7be09846b12f03620ab566cc064 100644
--- a/src/version.cc
+++ b/src/version.cc
@@ -35,7 +35,7 @@
 #define MAJOR_VERSION     3
 #define MINOR_VERSION     11
 #define BUILD_NUMBER      10
-#define PATCH_LEVEL       4
+#define PATCH_LEVEL       5
 // Use 1 for candidates and 0 otherwise.
 // (Boolean macro values are not supported by all preprocessors.)
 #define IS_CANDIDATE_VERSION 0
Index: test/cctest/test-heap.cc
diff --git a/test/cctest/test-heap.cc b/test/cctest/test-heap.cc
index 498b67db2c65ebebf6fe14b01398d17531e6f12c..275bd3d0fd661f48de26b46d7af3d77987b2c272 100644
--- a/test/cctest/test-heap.cc
+++ b/test/cctest/test-heap.cc
@@ -1579,13 +1579,10 @@ TEST(PrototypeTransitionClearing) {
           *v8::Handle<v8::Object>::Cast(
               v8::Context::GetCurrent()->Global()->Get(v8_str("base"))));

-  // Verify that only dead prototype transitions are cleared.  There is an
-  // extra, 11th, prototype transition on the Object map, which is the
-  // transition to a map with the used_for_prototype flag set (the key is
-  // the_hole).
-  CHECK_EQ(11, baseObject->map()->NumberOfProtoTransitions());
+  // Verify that only dead prototype transitions are cleared.
+  CHECK_EQ(10, baseObject->map()->NumberOfProtoTransitions());
   HEAP->CollectAllGarbage(Heap::kNoGCFlags);
-  const int transitions = 11 - 3;
+  const int transitions = 10 - 3;
   CHECK_EQ(transitions, baseObject->map()->NumberOfProtoTransitions());

   // Verify that prototype transitions array was compacted.
Index: test/mjsunit/fast-prototype.js
diff --git a/test/mjsunit/fast-prototype.js b/test/mjsunit/fast-prototype.js
index f2fc20228bf0f6caabb841734ecd953ad20c88d2..7fd73a4e1221a4cf4b6bc95ed6e5099d90bacd06 100644
--- a/test/mjsunit/fast-prototype.js
+++ b/test/mjsunit/fast-prototype.js
@@ -71,8 +71,8 @@ function test(use_new, add_first, set__proto__, same_map_as) {
     // Still fast
     assertTrue(%HasFastProperties(proto));
     AddProps(proto);
-    // Setting the bit means it is still fast with all these properties.
-    assertTrue(%HasFastProperties(proto));
+    // After we add all those properties it went slow mode again :-(
+    assertFalse(%HasFastProperties(proto));
   }
   if (same_map_as && !add_first) {
     assertTrue(%HaveSameMap(same_map_as, proto));


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

Reply via email to