Index: src/ic.cc |
diff --git a/src/ic.cc b/src/ic.cc |
index da8afca789af9a974913c7192dfcd75f47e99b0d..a32717362965973cc961e9f4ba7ebfaa2b073f66 100644 |
--- a/src/ic.cc |
+++ b/src/ic.cc |
@@ -624,28 +624,33 @@ bool IC::UpdatePolymorphicIC(Handle<HeapType> type, |
TypeHandleList types; |
CodeHandleList handlers; |
- int number_of_valid_types; |
- int handler_to_overwrite = -1; |
- |
target()->FindAllTypes(&types); |
int number_of_types = types.length(); |
- number_of_valid_types = number_of_types; |
+ int deprecated_types = 0; |
+ int handler_to_overwrite = -1; |
for (int i = 0; i < number_of_types; 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--; |
- // If the receiver type is already in the polymorphic IC, this indicates |
- // there was a prototoype chain failure. In that case, just overwrite the |
- // handler. |
+ // Filter out deprecated maps to ensure their instances get migrated. |
+ ++deprecated_types; |
} else if (type->IsCurrently(current_type)) { |
- ASSERT(handler_to_overwrite == -1); |
- number_of_valid_types--; |
+ // If the receiver type is already in the polymorphic IC, this indicates |
+ // there was a prototoype chain failure. In that case, just overwrite the |
+ // handler. |
+ handler_to_overwrite = i; |
+ } else if (handler_to_overwrite == -1 && |
+ current_type->IsClass() && |
+ type->IsClass() && |
+ IsTransitionOfMonomorphicTarget(*current_type->AsClass(), |
+ *type->AsClass())) { |
handler_to_overwrite = i; |
} |
} |
+ int number_of_valid_types = |
+ number_of_types - deprecated_types - (handler_to_overwrite != -1); |
+ |
if (number_of_valid_types >= 4) return false; |
if (number_of_types == 0) return false; |
if (!target()->FindHandlers(&handlers, types.length())) return false; |
@@ -653,6 +658,9 @@ bool IC::UpdatePolymorphicIC(Handle<HeapType> type, |
number_of_valid_types++; |
if (handler_to_overwrite >= 0) { |
handlers.Set(handler_to_overwrite, code); |
+ if (!type->IsCurrently(types.at(handler_to_overwrite))) { |
+ types.Set(handler_to_overwrite, type); |
+ } |
} else { |
types.Add(type); |
handlers.Add(code); |
@@ -727,19 +735,18 @@ void IC::CopyICToMegamorphicCache(Handle<String> name) { |
} |
-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 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( |
- current_map->elements_kind(), receiver_elements_kind); |
+ 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; |
} |
@@ -752,17 +759,7 @@ void IC::PatchCache(Handle<HeapType> type, |
case MONOMORPHIC_PROTOTYPE_FAILURE: |
UpdateMonomorphicIC(type, code, name); |
break; |
- case MONOMORPHIC: { |
- // 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)) { |
- UpdateMonomorphicIC(type, code, name); |
- break; |
- } |
- // Fall through. |
- } |
+ case MONOMORPHIC: // Fall through. |
case POLYMORPHIC: |
if (!target()->is_keyed_stub()) { |
if (UpdatePolymorphicIC(type, name, code)) break; |
@@ -1457,8 +1454,8 @@ Handle<Code> KeyedStoreIC::StoreElementStub(Handle<JSObject> receiver, |
} |
if ((receiver_map.is_identical_to(previous_receiver_map) && |
IsTransitionStoreMode(store_mode)) || |
- IsTransitionOfMonomorphicTarget( |
- MapToType<HeapType>(transitioned_receiver_map, isolate()))) { |
+ IsTransitionOfMonomorphicTarget(*previous_receiver_map, |
+ *transitioned_receiver_map)) { |
// If the "old" and "new" maps are in the same elements map family, or |
// if they at least come from the same origin for a transitioning store, |
// stay MONOMORPHIC and use the map for the most generic ElementsKind. |