Index: src/ic.cc |
diff --git a/src/ic.cc b/src/ic.cc |
index 2f225323404f23b9471b6e7df1fdbff936e18559..9b304057ade037d471539297de6c3c4762d9bc73 100644 |
--- a/src/ic.cc |
+++ b/src/ic.cc |
@@ -783,7 +783,7 @@ void CallICBase::UpdateCaches(LookupResult* lookup, |
: Handle<JSObject>(JSObject::cast(object->GetPrototype(isolate())), |
isolate()); |
- PatchCache(cache_object, name, code); |
+ PatchCache(handle(Type::CurrentOf(cache_object), isolate()), name, code); |
TRACE_IC("CallIC", name); |
} |
@@ -967,79 +967,94 @@ static bool AddOneReceiverMapIfMissing(MapHandleList* receiver_maps, |
} |
-bool IC::UpdatePolymorphicIC(Handle<Object> receiver, |
+bool IC::UpdatePolymorphicIC(Handle<Type> type, |
Handle<String> name, |
Handle<Code> code) { |
if (!code->is_handler()) return false; |
- MapHandleList receiver_maps; |
+ TypeHandleList types; |
CodeHandleList handlers; |
- int number_of_valid_maps; |
+ int number_of_valid_types; |
int handler_to_overwrite = -1; |
- Handle<Map> new_receiver_map(receiver->GetMarkerMap(isolate())); |
- |
- target()->FindAllMaps(&receiver_maps); |
- int number_of_maps = receiver_maps.length(); |
- number_of_valid_maps = number_of_maps; |
- |
- for (int i = 0; i < number_of_maps; i++) { |
- Handle<Map> map = receiver_maps.at(i); |
- // Filter out deprecated maps to ensure its instances get migrated. |
- if (map->is_deprecated()) { |
- number_of_valid_maps--; |
- // If the receiver map is already in the polymorphic IC, this indicates |
+ |
+ target()->FindAllTypes(&types); |
+ int number_of_types = types.length(); |
+ number_of_valid_types = number_of_types; |
+ |
+ for (int i = 0; i < number_of_types; i++) { |
+ Handle<Type> 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. |
- } else if (map.is_identical_to(new_receiver_map)) { |
- number_of_valid_maps--; |
+ } else if (type->Is(current_type)) { |
+ ASSERT(handler_to_overwrite == -1); |
+ number_of_valid_types--; |
handler_to_overwrite = i; |
} |
} |
- if (number_of_valid_maps >= 4) return false; |
- if (number_of_maps == 0) return false; |
+ if (number_of_valid_types >= 4) return false; |
+ if (number_of_types == 0) return false; |
+ if (!target()->FindHandlers(&handlers, types.length())) return false; |
- if (!target()->FindHandlers(&handlers, receiver_maps.length())) { |
- return false; |
- } |
- |
- number_of_valid_maps++; |
+ number_of_valid_types++; |
if (handler_to_overwrite >= 0) { |
handlers.Set(handler_to_overwrite, code); |
} else { |
- receiver_maps.Add(new_receiver_map); |
+ types.Add(type); |
handlers.Add(code); |
} |
Handle<Code> ic = isolate()->stub_cache()->ComputePolymorphicIC( |
- &receiver_maps, &handlers, number_of_valid_maps, name, strict_mode()); |
+ &types, &handlers, number_of_valid_types, name, strict_mode()); |
set_target(*ic); |
return true; |
} |
-void IC::UpdateMonomorphicIC(Handle<Object> receiver, |
+Handle<Map> IC::TypeToMap(Type* type, Isolate* isolate) { |
+ if (type->Is(Type::Number())) return isolate->factory()->heap_number_map(); |
+ if (type->Is(Type::Boolean())) return isolate->factory()->oddball_map(); |
+ ASSERT(type->IsClass()); |
+ return type->AsClass(); |
+} |
+ |
+ |
+Type* IC::MapToType(Handle<Map> map) { |
+ if (map->instance_type() == HEAP_NUMBER_TYPE) return Type::Number(); |
+ // The only oddballs that can be recorded in ICs are booleans. |
+ if (map->instance_type() == ODDBALL_TYPE) return Type::Boolean(); |
+ return Type::Class(map); |
+} |
+ |
+ |
+void IC::UpdateMonomorphicIC(Handle<Type> type, |
Handle<Code> handler, |
Handle<String> name) { |
if (!handler->is_handler()) return set_target(*handler); |
Handle<Code> ic = isolate()->stub_cache()->ComputeMonomorphicIC( |
- name, receiver, handler, strict_mode()); |
+ name, type, handler, strict_mode()); |
set_target(*ic); |
} |
void IC::CopyICToMegamorphicCache(Handle<String> name) { |
- MapHandleList receiver_maps; |
+ TypeHandleList types; |
CodeHandleList handlers; |
- target()->FindAllMaps(&receiver_maps); |
- if (!target()->FindHandlers(&handlers, receiver_maps.length())) return; |
- for (int i = 0; i < receiver_maps.length(); i++) { |
- UpdateMegamorphicCache(*receiver_maps.at(i), *name, *handlers.at(i)); |
+ 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)); |
} |
} |
-bool IC::IsTransitionedMapOfMonomorphicTarget(Map* receiver_map) { |
+bool IC::IsTransitionOfMonomorphicTarget(Type* 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 = |
@@ -1053,14 +1068,14 @@ bool IC::IsTransitionedMapOfMonomorphicTarget(Map* receiver_map) { |
} |
-void IC::PatchCache(Handle<Object> object, |
+void IC::PatchCache(Handle<Type> type, |
Handle<String> name, |
Handle<Code> code) { |
switch (state()) { |
case UNINITIALIZED: |
case PREMONOMORPHIC: |
case MONOMORPHIC_PROTOTYPE_FAILURE: |
- UpdateMonomorphicIC(object, code, name); |
+ UpdateMonomorphicIC(type, code, name); |
break; |
case MONOMORPHIC: { |
// For now, call stubs are allowed to rewrite to the same stub. This |
@@ -1069,23 +1084,21 @@ void IC::PatchCache(Handle<Object> object, |
target()->is_keyed_call_stub() || |
!target().is_identical_to(code)); |
Code* old_handler = target()->FindFirstHandler(); |
- if (old_handler == *code && |
- IsTransitionedMapOfMonomorphicTarget( |
- object->GetMarkerMap(isolate()))) { |
- UpdateMonomorphicIC(object, code, name); |
+ if (old_handler == *code && IsTransitionOfMonomorphicTarget(*type)) { |
+ UpdateMonomorphicIC(type, code, name); |
break; |
} |
// Fall through. |
} |
case POLYMORPHIC: |
if (!target()->is_keyed_stub()) { |
- if (UpdatePolymorphicIC(object, name, code)) break; |
+ if (UpdatePolymorphicIC(type, name, code)) break; |
CopyICToMegamorphicCache(name); |
} |
set_target(*megamorphic_stub()); |
// Fall through. |
case MEGAMORPHIC: |
- UpdateMegamorphicCache(object->GetMarkerMap(isolate()), *name, *code); |
+ UpdateMegamorphicCache(*type, *name, *code); |
break; |
case DEBUG_STUB: |
break; |
@@ -1135,14 +1148,15 @@ void LoadIC::UpdateCaches(LookupResult* lookup, |
code = ComputeHandler(lookup, object, name); |
} |
- PatchCache(object, name, code); |
+ PatchCache(handle(Type::CurrentOf(object), isolate()), name, code); |
TRACE_IC("LoadIC", name); |
} |
-void IC::UpdateMegamorphicCache(Map* map, Name* name, Code* code) { |
+void IC::UpdateMegamorphicCache(Type* type, Name* name, Code* code) { |
// Cache code holding map should be consistent with |
// GenerateMonomorphicCacheProbe. |
+ Map* map = *TypeToMap(type, isolate()); |
isolate()->stub_cache()->Set(name, map, code); |
} |
@@ -1598,7 +1612,7 @@ void StoreIC::UpdateCaches(LookupResult* lookup, |
Handle<Code> code = ComputeHandler(lookup, receiver, name, value); |
- PatchCache(receiver, name, code); |
+ PatchCache(handle(Type::CurrentOf(receiver), isolate()), name, code); |
TRACE_IC("StoreIC", name); |
} |
@@ -1744,7 +1758,7 @@ Handle<Code> KeyedStoreIC::StoreElementStub(Handle<JSObject> receiver, |
transitioned_receiver_map = |
ComputeTransitionedMap(receiver, store_mode); |
} |
- if (IsTransitionedMapOfMonomorphicTarget(*transitioned_receiver_map)) { |
+ if (IsTransitionOfMonomorphicTarget(MapToType(transitioned_receiver_map))) { |
// Element family is the same, use the "worst" case map. |
store_mode = GetNonTransitioningStoreMode(store_mode); |
return isolate()->stub_cache()->ComputeKeyedStoreElement( |