Optimize call sites that only ever see a single elements transition
authordanno@chromium.org <danno@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Mon, 13 Feb 2012 11:37:39 +0000 (11:37 +0000)
committerdanno@chromium.org <danno@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Mon, 13 Feb 2012 11:37:39 +0000 (11:37 +0000)
R=jkummerow@chromium.org
TEST=imaging-gaussian-blur performance improves

Review URL: https://chromiumcodereview.appspot.com/9389001

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@10683 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/ic.cc

index 248f4fc891d16430d602c613c81deb21badbaf86..ef3fc2c86b6d8e76dbfcd2d3f027fad5ee70ca9a 100644 (file)
--- a/src/ic.cc
+++ b/src/ic.cc
@@ -1503,8 +1503,32 @@ Handle<Code> KeyedIC::ComputeStub(Handle<JSObject> receiver,
   KeyedAccessGrowMode grow_mode = IsGrowStubKind(stub_kind)
       ? ALLOW_JSARRAY_GROWTH
       : DO_NOT_ALLOW_JSARRAY_GROWTH;
-  if ((ic_state == UNINITIALIZED || ic_state == PREMONOMORPHIC) &&
-      !IsTransitionStubKind(stub_kind)) {
+
+  bool monomorphic = false;
+  MapHandleList target_receiver_maps;
+  if (ic_state != UNINITIALIZED && ic_state != PREMONOMORPHIC) {
+    GetReceiverMapsForStub(Handle<Code>(target()), &target_receiver_maps);
+  }
+  if (!IsTransitionStubKind(stub_kind)) {
+    if (ic_state == UNINITIALIZED || ic_state == PREMONOMORPHIC) {
+      monomorphic = true;
+    } else {
+      if (ic_state == MONOMORPHIC) {
+        // The first time a receiver is seen that is a transitioned version of
+        // the previous monomorphic receiver type, assume the new ElementsKind
+        // is the monomorphic type. This benefits global arrays that only
+        // transition once, and all call sites accessing them are faster if they
+        // remain monomorphic. If this optimistic assumption is not true, the IC
+        // will miss again and it will become polymorphic and support both the
+        // untransitioned and transitioned maps.
+        monomorphic = IsMoreGeneralElementsKindTransition(
+            target_receiver_maps.at(0)->elements_kind(),
+            receiver->GetElementsKind());
+      }
+    }
+  }
+
+  if (monomorphic) {
     return ComputeMonomorphicStub(
         receiver, stub_kind, strict_mode, generic_stub);
   }
@@ -1520,13 +1544,7 @@ Handle<Code> KeyedIC::ComputeStub(Handle<JSObject> receiver,
 
   // Determine the list of receiver maps that this call site has seen,
   // adding the map that was just encountered.
-  MapHandleList target_receiver_maps;
   Handle<Map> receiver_map(receiver->map());
-  if (ic_state == UNINITIALIZED || ic_state == PREMONOMORPHIC) {
-    target_receiver_maps.Add(receiver_map);
-  } else {
-    GetReceiverMapsForStub(Handle<Code>(target()), &target_receiver_maps);
-  }
   bool map_added =
       AddOneReceiverMapIfMissing(&target_receiver_maps, receiver_map);
   if (IsTransitionStubKind(stub_kind)) {