Do not try to collect the map if the monomorphic IC stub has no map.
authorverwaest@chromium.org <verwaest@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Mon, 28 Jan 2013 13:19:53 +0000 (13:19 +0000)
committerverwaest@chromium.org <verwaest@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Mon, 28 Jan 2013 13:19:53 +0000 (13:19 +0000)
This is necessary for monomorphic stubs that rely on instance types,
such as ArrayLength, StringLength and FunctionPrototype.

BUG=chromium:172345

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

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

src/ic.cc
test/mjsunit/regress/regress-crbug-172345.js [new file with mode: 0644]

index 7fa7eaf..9d5bf17 100644 (file)
--- a/src/ic.cc
+++ b/src/ic.cc
@@ -1139,32 +1139,35 @@ static bool AddOneReceiverMapIfMissing(MapHandleList* receiver_maps,
 static void GetReceiverMapsForStub(Handle<Code> stub,
                                    MapHandleList* result) {
   ASSERT(stub->is_inline_cache_stub());
-  if (stub->is_keyed_load_stub() || stub->is_keyed_store_stub()) {
-    switch (stub->ic_state()) {
-      case MONOMORPHIC:
-        result->Add(Handle<Map>(stub->FindFirstMap()));
-        break;
-      case POLYMORPHIC: {
-        AssertNoAllocation no_allocation;
-        int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
-        for (RelocIterator it(*stub, mask); !it.done(); it.next()) {
-          RelocInfo* info = it.rinfo();
-          Handle<Object> object(info->target_object());
-          ASSERT(object->IsMap());
-          AddOneReceiverMapIfMissing(result, Handle<Map>::cast(object));
-        }
-        break;
+  ASSERT(stub->is_keyed_load_stub() || stub->is_keyed_store_stub());
+  switch (stub->ic_state()) {
+    case MONOMORPHIC: {
+      Map* map = stub->FindFirstMap();
+      if (map != NULL) {
+        result->Add(Handle<Map>(map));
+      }
+      break;
+    }
+    case POLYMORPHIC: {
+      AssertNoAllocation no_allocation;
+      int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
+      for (RelocIterator it(*stub, mask); !it.done(); it.next()) {
+        RelocInfo* info = it.rinfo();
+        Handle<Object> object(info->target_object());
+        ASSERT(object->IsMap());
+        AddOneReceiverMapIfMissing(result, Handle<Map>::cast(object));
       }
-      case MEGAMORPHIC:
-      case GENERIC:
-        break;
-      case UNINITIALIZED:
-      case PREMONOMORPHIC:
-      case MONOMORPHIC_PROTOTYPE_FAILURE:
-      case DEBUG_STUB:
-        UNREACHABLE();
-        break;
+      break;
     }
+    case MEGAMORPHIC:
+    case GENERIC:
+      break;
+    case UNINITIALIZED:
+    case PREMONOMORPHIC:
+    case MONOMORPHIC_PROTOTYPE_FAILURE:
+    case DEBUG_STUB:
+      UNREACHABLE();
+      break;
   }
 }
 
@@ -1192,6 +1195,9 @@ Handle<Code> KeyedLoadIC::LoadElementStub(Handle<JSObject> receiver) {
     target_receiver_maps.Add(isolate()->factory()->string_map());
   } else {
     GetReceiverMapsForStub(Handle<Code>(target()), &target_receiver_maps);
+    if (target_receiver_maps.length() == 0) {
+      return isolate()->stub_cache()->ComputeKeyedLoadElement(receiver_map);
+    }
   }
 
   // The first time a receiver is seen that is a transitioned version of the
@@ -1564,6 +1570,13 @@ Handle<Code> KeyedStoreIC::StoreElementStub(Handle<JSObject> receiver,
   }
 
   GetReceiverMapsForStub(Handle<Code>(target()), &target_receiver_maps);
+  if (target_receiver_maps.length() == 0) {
+    // Optimistically assume that ICs that haven't reached the MONOMORPHIC state
+    // yet will do so and stay there.
+    stub_kind = GetNoTransitionStubKind(stub_kind);
+    return isolate()->stub_cache()->ComputeKeyedStoreElement(
+        receiver_map, stub_kind, strict_mode, grow_mode);
+  }
   // 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
diff --git a/test/mjsunit/regress/regress-crbug-172345.js b/test/mjsunit/regress/regress-crbug-172345.js
new file mode 100644 (file)
index 0000000..711501c
--- /dev/null
@@ -0,0 +1,34 @@
+// Copyright 2013 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+function f(a,i) {
+  return a[i];
+}
+
+f([1,2,3], "length");
+f([1,2,3], "length");
+f([1,2,3], 2);