Load target types and handlers before IC computation.
authorulan@chromium.org <ulan@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 18 Feb 2014 15:12:58 +0000 (15:12 +0000)
committerulan@chromium.org <ulan@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 18 Feb 2014 15:12:58 +0000 (15:12 +0000)
BUG=
R=verwaest@chromium.org

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

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

src/ic.cc
src/ic.h

index 0ca70d3..bd06cb6 100644 (file)
--- a/src/ic.cc
+++ b/src/ic.cc
@@ -149,6 +149,8 @@ IC::IC(FrameDepth depth, Isolate* isolate)
   target_ = handle(raw_target(), isolate);
   state_ = target_->ic_state();
   extra_ic_state_ = target_->extra_ic_state();
+  target()->FindAllTypes(&types_);
+  target()->FindHandlers(&handlers_);
 }
 
 
@@ -281,7 +283,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 = first_map();
     if (old_map == *map) return true;
     if (old_map != NULL) {
       if (old_map->is_deprecated()) return true;
@@ -306,10 +308,8 @@ bool IC::TryRemoveInvalidPrototypeDependentStub(Handle<Object> receiver,
 
 
 void IC::TryRemoveInvalidHandlers(Handle<Map> map, Handle<String> name) {
-  CodeHandleList handlers;
-  target()->FindHandlers(&handlers);
-  for (int i = 0; i < handlers.length(); i++) {
-    Handle<Code> handler = handlers.at(i);
+  for (int i = 0; i < handlers()->length(); i++) {
+    Handle<Code> handler = handlers()->at(i);
     int index = map->IndexInCodeCache(*name, *handler);
     if (index >= 0) {
       map->RemoveFromCodeCache(*name, *handler, index);
@@ -605,18 +605,14 @@ bool IC::UpdatePolymorphicIC(Handle<HeapType> type,
                              Handle<String> name,
                              Handle<Code> code) {
   if (!code->is_handler()) return false;
-  TypeHandleList types;
-  CodeHandleList handlers;
-
   int number_of_valid_types;
   int handler_to_overwrite = -1;
 
-  target()->FindAllTypes(&types);
-  int number_of_types = types.length();
+  int number_of_types = types()->length();
   number_of_valid_types = number_of_types;
 
   for (int i = 0; i < number_of_types; i++) {
-    Handle<HeapType> current_type = types.at(i);
+    Handle<HeapType> current_type = types()->at(i);
     // Filter out deprecated maps to ensure their instances get migrated.
     if (current_type->IsClass() && current_type->AsClass()->is_deprecated()) {
       number_of_valid_types--;
@@ -632,18 +628,19 @@ bool IC::UpdatePolymorphicIC(Handle<HeapType> type,
 
   if (number_of_valid_types >= 4) return false;
   if (number_of_types == 0) return false;
-  if (!target()->FindHandlers(&handlers, types.length())) return false;
+  if (handlers()->length() < types()->length()) return false;
 
   number_of_valid_types++;
   if (handler_to_overwrite >= 0) {
-    handlers.Set(handler_to_overwrite, code);
+    handlers()->Set(handler_to_overwrite, code);
   } else {
-    types.Add(type);
-    handlers.Add(code);
+    types()->Add(type);
+    handlers()->Add(code);
   }
 
   Handle<Code> ic = isolate()->stub_cache()->ComputePolymorphicIC(
-      kind(), &types, &handlers, number_of_valid_types, name, extra_ic_state());
+      kind(), types(), handlers(), number_of_valid_types,
+      name, extra_ic_state());
   set_target(*ic);
   return true;
 }
@@ -701,29 +698,23 @@ void IC::UpdateMonomorphicIC(Handle<HeapType> type,
 
 
 void IC::CopyICToMegamorphicCache(Handle<String> name) {
-  TypeHandleList types;
-  CodeHandleList handlers;
-  target()->FindAllTypes(&types);
-  if (!target()->FindHandlers(&handlers, types.length())) return;
-  for (int i = 0; i < types.length(); i++) {
-    UpdateMegamorphicCache(*types.at(i), *name, *handlers.at(i));
+  if (handlers()->length() < types()->length()) return;
+  for (int i = 0; i < types()->length(); i++) {
+    UpdateMegamorphicCache(*types()->at(i), *name, *handlers()->at(i));
   }
 }
 
 
-bool IC::IsTransitionOfMonomorphicTarget(Handle<HeapType> type) {
-  if (!type->IsClass()) return false;
-  Map* receiver_map = *type->AsClass();
-  Map* current_map = target()->FindFirstMap();
-  ElementsKind receiver_elements_kind = receiver_map->elements_kind();
-  bool more_general_transition =
-      IsMoreGeneralElementsKindTransition(
-        current_map->elements_kind(), receiver_elements_kind);
+bool IC::IsTransitionOfMonomorphicTarget(Map* source_map, Map* target_map) {
+  if (source_map == NULL) return true;
+  if (target_map == NULL) return false;
+  ElementsKind target_elements_kind = target_map->elements_kind();
+  bool more_general_transition = IsMoreGeneralElementsKindTransition(
+      source_map->elements_kind(), target_elements_kind);
   Map* transitioned_map = more_general_transition
-      ? current_map->LookupElementsTransitionMap(receiver_elements_kind)
+      ? source_map->LookupElementsTransitionMap(target_elements_kind)
       : NULL;
-
-  return transitioned_map == receiver_map;
+  return transitioned_map == target_map;
 }
 
 
@@ -740,8 +731,11 @@ void IC::PatchCache(Handle<HeapType> type,
       // For now, call stubs are allowed to rewrite to the same stub. This
       // happens e.g., when the field does not contain a function.
       ASSERT(!target().is_identical_to(code));
-      Code* old_handler = target()->FindFirstHandler();
-      if (old_handler == *code && IsTransitionOfMonomorphicTarget(type)) {
+      Map* old_map = first_map();
+      Code* old_handler = first_handler();
+      Map* map = type->IsClass() ? *type->AsClass() : NULL;
+      if (old_handler == *code &&
+          IsTransitionOfMonomorphicTarget(old_map, map)) {
         UpdateMonomorphicIC(type, code, name);
         break;
       }
@@ -1010,7 +1004,7 @@ Handle<Code> KeyedLoadIC::LoadElementStub(Handle<JSObject> receiver) {
   if (target().is_identical_to(string_stub())) {
     target_receiver_maps.Add(isolate()->factory()->string_map());
   } else {
-    target()->FindAllMaps(&target_receiver_maps);
+    GetMapsFromTypes(&target_receiver_maps);
     if (target_receiver_maps.length() == 0) {
       return isolate()->stub_cache()->ComputeKeyedLoadElement(receiver_map);
     }
@@ -1414,37 +1408,25 @@ Handle<Code> KeyedStoreIC::StoreElementStub(Handle<JSObject> receiver,
         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
   // changed or it has transitioned to a more general kind.
   KeyedAccessStoreMode old_store_mode =
       KeyedStoreIC::GetKeyedAccessStoreMode(target()->extra_ic_state());
-  Handle<Map> previous_receiver_map = target_receiver_maps.at(0);
   if (state() == MONOMORPHIC) {
       // If the "old" and "new" maps are in the same elements map family, stay
       // MONOMORPHIC and use the map for the most generic ElementsKind.
-    Handle<Map> transitioned_receiver_map = receiver_map;
+    Handle<Map> transitioned_map = receiver_map;
     if (IsTransitionStoreMode(store_mode)) {
-      transitioned_receiver_map =
-          ComputeTransitionedMap(receiver, store_mode);
+      transitioned_map = ComputeTransitionedMap(receiver, store_mode);
     }
-    if (IsTransitionOfMonomorphicTarget(
-            MapToType<HeapType>(transitioned_receiver_map, isolate()))) {
+    if (IsTransitionOfMonomorphicTarget(first_map(), *transitioned_map)) {
       // Element family is the same, use the "worst" case map.
       store_mode = GetNonTransitioningStoreMode(store_mode);
       return isolate()->stub_cache()->ComputeKeyedStoreElement(
-          transitioned_receiver_map, strict_mode(), store_mode);
-    } else if (*previous_receiver_map == receiver->map() &&
+          transitioned_map, strict_mode(), store_mode);
+    } else if (first_map() == receiver->map() &&
                old_store_mode == STANDARD_STORE &&
                (IsGrowStoreMode(store_mode) ||
                 store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS ||
@@ -1459,6 +1441,9 @@ Handle<Code> KeyedStoreIC::StoreElementStub(Handle<JSObject> receiver,
 
   ASSERT(state() != GENERIC);
 
+  MapHandleList target_receiver_maps;
+  GetMapsFromTypes(&target_receiver_maps);
+
   bool map_added =
       AddOneReceiverMapIfMissing(&target_receiver_maps, receiver_map);
 
@@ -2715,8 +2700,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 && (first_map() != NULL)
+                                ? first_map()
                                 : HeapObject::cast(*object)->map());
     code = isolate()->stub_cache()->ComputeCompareNil(monomorphic_map, stub);
   } else {
index 213a481..fce585f 100644 (file)
--- a/src/ic.h
+++ b/src/ic.h
@@ -150,6 +150,19 @@ class IC {
   // Get the call-site target; used for determining the state.
   Handle<Code> target() const { return target_; }
 
+  TypeHandleList* types() { return &types_; }
+  CodeHandleList* handlers() { return &handlers_; }
+  Map* first_map() {
+    return types_.length() == 0 ? NULL : *TypeToMap(*types_.at(0), isolate_);
+  }
+  Code* first_handler() {
+    return handlers_.length() == 0 ? NULL : *handlers_.at(0);
+  }
+  void GetMapsFromTypes(MapHandleList* maps) {
+    for (int i = 0; i < types_.length(); ++i) {
+      maps->Add(TypeToMap(*types_.at(i), isolate_));
+    }
+  }
   Address fp() const { return fp_; }
   Address pc() const { return *pc_address_; }
   Isolate* isolate() const { return isolate_; }
@@ -209,7 +222,7 @@ class IC {
   virtual void UpdateMegamorphicCache(HeapType* type, Name* name, Code* code);
 
   void CopyICToMegamorphicCache(Handle<String> name);
-  bool IsTransitionOfMonomorphicTarget(Handle<HeapType> type);
+  bool IsTransitionOfMonomorphicTarget(Map* source_map, Map* target_map);
   void PatchCache(Handle<HeapType> type,
                   Handle<String> name,
                   Handle<Code> code);
@@ -260,6 +273,9 @@ class IC {
 
   ExtraICState extra_ic_state_;
 
+  TypeHandleList types_;
+  CodeHandleList handlers_;
+
   DISALLOW_IMPLICIT_CONSTRUCTORS(IC);
 };