From: ulan@chromium.org Date: Thu, 27 Mar 2014 09:59:43 +0000 (+0000) Subject: Unify monomorphic and polymorphic cases in IC::PatchCache. X-Git-Tag: upstream/4.7.83~9978 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=179b4b0c9f5476b9c94f9a86fb9296a518cee1c8;p=platform%2Fupstream%2Fv8.git Unify monomorphic and polymorphic cases in IC::PatchCache. BUG= R=verwaest@chromium.org Review URL: https://codereview.chromium.org/171683007 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@20294 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- diff --git a/src/ic.cc b/src/ic.cc index da8afca..a327173 100644 --- a/src/ic.cc +++ b/src/ic.cc @@ -624,28 +624,33 @@ bool IC::UpdatePolymorphicIC(Handle 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 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 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 name) { } -bool IC::IsTransitionOfMonomorphicTarget(Handle 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 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 KeyedStoreIC::StoreElementStub(Handle receiver, } if ((receiver_map.is_identical_to(previous_receiver_map) && IsTransitionStoreMode(store_mode)) || - IsTransitionOfMonomorphicTarget( - MapToType(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. diff --git a/src/ic.h b/src/ic.h index 7d35471..e70cb82 100644 --- a/src/ic.h +++ b/src/ic.h @@ -217,7 +217,7 @@ class IC { virtual void UpdateMegamorphicCache(HeapType* type, Name* name, Code* code); void CopyICToMegamorphicCache(Handle name); - bool IsTransitionOfMonomorphicTarget(Handle type); + bool IsTransitionOfMonomorphicTarget(Map* source_map, Map* target_map); void PatchCache(Handle type, Handle name, Handle code);