Index: src/ic.cc |
diff --git a/src/ic.cc b/src/ic.cc |
index 0ca70d3711a47971f5c3a0d240bd47dae2c16eae..bd06cb6f9617d5bcf435673cbf507ae91eeedc97 100644 |
--- 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); |
ulan
2014/02/18 14:50:26
This function modifies handlers and types. Do you
Toon Verwaest
2014/02/18 15:06:36
This is done at the end of IC computation. It shou
|
} 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 { |