Lazily initialize the target map list in IC.
authorulan@chromium.org <ulan@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 2 Apr 2014 07:59:54 +0000 (07:59 +0000)
committerulan@chromium.org <ulan@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 2 Apr 2014 07:59:54 +0000 (07:59 +0000)
This makes sure that we keep the target map list alive in the handle scope during IC computation.

BUG=
R=verwaest@chromium.org

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

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

src/ic.cc
src/ic.h
src/objects.cc
src/objects.h

index 8b19a60..36c7e5a 100644 (file)
--- a/src/ic.cc
+++ b/src/ic.cc
@@ -121,7 +121,8 @@ void IC::TraceIC(const char* type,
 
 IC::IC(FrameDepth depth, Isolate* isolate)
     : isolate_(isolate),
-      target_set_(false) {
+      target_set_(false),
+      target_maps_set_(false) {
   // To improve the performance of the (much used) IC code, we unfold a few
   // levels of the stack frame iteration code. This yields a ~35% speedup when
   // running DeltaBlue and a ~25% speedup of gbemu with the '--nouse-ic' flag.
@@ -293,7 +294,7 @@ bool IC::TryRemoveInvalidPrototypeDependentStub(Handle<Object> receiver,
   // If the IC is shared between multiple receivers (slow dictionary mode), then
   // the map cannot be deprecated and the stub invalidated.
   if (cache_holder == OWN_MAP) {
-    Map* old_map = target()->FindFirstMap();
+    Map* old_map = FirstTargetMap();
     if (old_map == *map) return true;
     if (old_map != NULL) {
       if (old_map->is_deprecated()) return true;
@@ -632,7 +633,7 @@ bool IC::UpdatePolymorphicIC(Handle<HeapType> type,
   TypeHandleList types;
   CodeHandleList handlers;
 
-  target()->FindAllTypes(&types);
+  TargetTypes(&types);
   int number_of_types = types.length();
   int deprecated_types = 0;
   int handler_to_overwrite = -1;
@@ -735,7 +736,7 @@ void IC::UpdateMonomorphicIC(Handle<HeapType> type,
 void IC::CopyICToMegamorphicCache(Handle<String> name) {
   TypeHandleList types;
   CodeHandleList handlers;
-  target()->FindAllTypes(&types);
+  TargetTypes(&types);
   if (!target()->FindHandlers(&handlers, types.length())) return;
   for (int i = 0; i < types.length(); i++) {
     UpdateMegamorphicCache(*types.at(i), *name, *handlers.at(i));
@@ -1036,19 +1037,13 @@ Handle<Code> KeyedLoadIC::LoadElementStub(Handle<JSObject> receiver) {
 
   Handle<Map> receiver_map(receiver->map(), isolate());
   MapHandleList target_receiver_maps;
-  if (state() == UNINITIALIZED || state() == PREMONOMORPHIC) {
-    // Optimistically assume that ICs that haven't reached the MONOMORPHIC state
-    // yet will do so and stay there.
-    return isolate()->stub_cache()->ComputeKeyedLoadElement(receiver_map);
-  }
-
   if (target().is_identical_to(string_stub())) {
     target_receiver_maps.Add(isolate()->factory()->string_map());
   } else {
-    target()->FindAllMaps(&target_receiver_maps);
-    if (target_receiver_maps.length() == 0) {
-      return isolate()->stub_cache()->ComputeKeyedLoadElement(receiver_map);
-    }
+    TargetMaps(&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
@@ -1435,24 +1430,15 @@ Handle<Code> KeyedStoreIC::StoreElementStub(Handle<JSObject> receiver,
   }
 
   Handle<Map> receiver_map(receiver->map(), isolate());
-  if (state() == UNINITIALIZED || state() == PREMONOMORPHIC) {
-    // Optimistically assume that ICs that haven't reached the MONOMORPHIC state
-    // yet will do so and stay there.
+  MapHandleList target_receiver_maps;
+  TargetMaps(&target_receiver_maps);
+  if (target_receiver_maps.length() == 0) {
     Handle<Map> monomorphic_map = ComputeTransitionedMap(receiver, store_mode);
     store_mode = GetNonTransitioningStoreMode(store_mode);
     return isolate()->stub_cache()->ComputeKeyedStoreElement(
         monomorphic_map, strict_mode(), store_mode);
   }
 
-  MapHandleList target_receiver_maps;
-  target()->FindAllMaps(&target_receiver_maps);
-  if (target_receiver_maps.length() == 0) {
-    // In the case that there is a non-map-specific IC is installed (e.g. keyed
-    // stores into properties in dictionary mode), then there will be not
-    // receiver maps in the target.
-    return generic_stub();
-  }
-
   // There are several special cases where an IC that is MONOMORPHIC can still
   // transition to a different GetNonTransitioningStoreMode IC that handles a
   // superset of the original IC. Handle those here if the receiver map hasn't
@@ -2754,8 +2740,8 @@ MaybeObject* CompareNilIC::CompareNil(Handle<Object> object) {
   // Find or create the specialized stub to support the new set of types.
   Handle<Code> code;
   if (stub.IsMonomorphic()) {
-    Handle<Map> monomorphic_map(already_monomorphic
-                                ? target()->FindFirstMap()
+    Handle<Map> monomorphic_map(already_monomorphic && FirstTargetMap() != NULL
+                                ? FirstTargetMap()
                                 : HeapObject::cast(*object)->map());
     code = isolate()->stub_cache()->ComputeCompareNil(monomorphic_map, stub);
   } else {
index 146b26b..41882e6 100644 (file)
--- a/src/ic.h
+++ b/src/ic.h
@@ -253,6 +253,25 @@ class IC {
     extra_ic_state_ = state;
   }
 
+  void TargetMaps(MapHandleList* list) {
+    FindTargetMaps();
+    for (int i = 0; i < target_maps_.length(); i++) {
+      list->Add(target_maps_.at(i));
+    }
+  }
+
+  void TargetTypes(TypeHandleList* list) {
+    FindTargetMaps();
+    for (int i = 0; i < target_maps_.length(); i++) {
+      list->Add(IC::MapToType<HeapType>(target_maps_.at(i), isolate_));
+    }
+  }
+
+  Map* FirstTargetMap() {
+    FindTargetMaps();
+    return target_maps_.length() > 0 ? *target_maps_.at(0) : NULL;
+  }
+
  protected:
   void UpdateTarget() {
     target_ = handle(raw_target(), isolate_);
@@ -265,6 +284,17 @@ class IC {
   inline ConstantPoolArray* constant_pool() const;
   inline ConstantPoolArray* raw_constant_pool() const;
 
+  void FindTargetMaps() {
+    if (target_maps_set_) return;
+    target_maps_set_ = true;
+    if (state_ == MONOMORPHIC) {
+      Map* map = target_->FindFirstMap();
+      if (map != NULL) target_maps_.Add(handle(map));
+    } else if (state_ != UNINITIALIZED && state_ != PREMONOMORPHIC) {
+      target_->FindAllMaps(&target_maps_);
+    }
+  }
+
   // Frame pointer for the frame that uses (calls) the IC.
   Address fp_;
 
@@ -286,6 +316,8 @@ class IC {
   bool target_set_;
 
   ExtraICState extra_ic_state_;
+  MapHandleList target_maps_;
+  bool target_maps_set_;
 
   DISALLOW_IMPLICIT_CONSTRUCTORS(IC);
 };
index 7057e9a..a5d0dbf 100644 (file)
@@ -10540,21 +10540,6 @@ void Code::FindAllMaps(MapHandleList* maps) {
 }
 
 
-void Code::FindAllTypes(TypeHandleList* types) {
-  ASSERT(is_inline_cache_stub());
-  DisallowHeapAllocation no_allocation;
-  int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
-  for (RelocIterator it(this, mask); !it.done(); it.next()) {
-    RelocInfo* info = it.rinfo();
-    Object* object = info->target_object();
-    if (object->IsMap()) {
-      Handle<Map> map(Map::cast(object));
-      types->Add(IC::MapToType<HeapType>(map, map->GetIsolate()));
-    }
-  }
-}
-
-
 Code* Code::FindFirstHandler() {
   ASSERT(is_inline_cache_stub());
   DisallowHeapAllocation no_allocation;
index ce4dd50..e8e20e9 100644 (file)
@@ -5407,7 +5407,6 @@ class Code: public HeapObject {
   // Find the first map in an IC stub.
   Map* FindFirstMap();
   void FindAllMaps(MapHandleList* maps);
-  void FindAllTypes(TypeHandleList* types);
 
   // Find the first handler in an IC stub.
   Code* FindFirstHandler();