Commit 179b4b0c authored by ulan@chromium.org's avatar ulan@chromium.org

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
parent caad1de7
......@@ -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.
......
......@@ -217,7 +217,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);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment