Chromium Code Reviews| Index: src/ic.cc |
| diff --git a/src/ic.cc b/src/ic.cc |
| index 7c156e59d84cfd20a52a8dbf2878b95cf0f3044a..8ba02740d3f8a1ccbf62ce25445392b104ec7a2a 100644 |
| --- a/src/ic.cc |
| +++ b/src/ic.cc |
| @@ -149,8 +149,6 @@ 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_); |
| } |
| @@ -283,7 +281,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 = first_map(); |
| + Map* old_map = target()->FindFirstMap(); |
| if (old_map == *map) return true; |
| if (old_map != NULL) { |
| if (old_map->is_deprecated()) return true; |
| @@ -308,8 +306,10 @@ bool IC::TryRemoveInvalidPrototypeDependentStub(Handle<Object> receiver, |
| void IC::TryRemoveInvalidHandlers(Handle<Map> map, Handle<String> name) { |
| - for (int i = 0; i < handlers()->length(); i++) { |
| - Handle<Code> handler = handlers()->at(i); |
| + CodeHandleList handlers; |
| + target()->FindHandlers(&handlers); |
| + 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,14 +605,18 @@ 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; |
| - int number_of_types = types()->length(); |
| + 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<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--; |
| @@ -628,19 +632,18 @@ bool IC::UpdatePolymorphicIC(Handle<HeapType> type, |
| if (number_of_valid_types >= 4) return false; |
| if (number_of_types == 0) return false; |
| - if (handlers()->length() < types()->length()) return false; |
| + if (!target()->FindHandlers(&handlers, 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); |
| } 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; |
| } |
| @@ -698,23 +701,29 @@ void IC::UpdateMonomorphicIC(Handle<HeapType> type, |
| void IC::CopyICToMegamorphicCache(Handle<String> name) { |
| - if (handlers()->length() < types()->length()) return; |
| - for (int i = 0; i < types()->length(); i++) { |
| - UpdateMegamorphicCache(*types()->at(i), *name, *handlers()->at(i)); |
| + 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)); |
| } |
| } |
| -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); |
| +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); |
| Map* transitioned_map = more_general_transition |
| - ? source_map->LookupElementsTransitionMap(target_elements_kind) |
| + ? current_map->LookupElementsTransitionMap(receiver_elements_kind) |
| : NULL; |
| - return transitioned_map == target_map; |
| + |
| + return transitioned_map == receiver_map; |
| } |
| @@ -731,11 +740,8 @@ 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)); |
| - 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)) { |
| + Code* old_handler = target()->FindFirstHandler(); |
| + if (old_handler == *code && IsTransitionOfMonomorphicTarget(type)) { |
| UpdateMonomorphicIC(type, code, name); |
| break; |
| } |
| @@ -1007,7 +1013,7 @@ Handle<Code> KeyedLoadIC::LoadElementStub(Handle<JSObject> receiver) { |
| if (target().is_identical_to(string_stub())) { |
| target_receiver_maps.Add(isolate()->factory()->string_map()); |
| } else { |
| - GetMapsFromTypes(&target_receiver_maps); |
| + target()->FindAllMaps(&target_receiver_maps); |
| if (target_receiver_maps.length() == 0) { |
| return isolate()->stub_cache()->ComputeKeyedLoadElement(receiver_map); |
| } |
| @@ -1411,25 +1417,37 @@ 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) { |
|
ulan
2014/02/25 10:18:30
Looks like the regression is caused by this chunk.
|
| + // 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_map = receiver_map; |
| + Handle<Map> transitioned_receiver_map = receiver_map; |
| if (IsTransitionStoreMode(store_mode)) { |
| - transitioned_map = ComputeTransitionedMap(receiver, store_mode); |
| + transitioned_receiver_map = |
| + ComputeTransitionedMap(receiver, store_mode); |
| } |
| - if (IsTransitionOfMonomorphicTarget(first_map(), *transitioned_map)) { |
| + if (IsTransitionOfMonomorphicTarget( |
| + MapToType<HeapType>(transitioned_receiver_map, isolate()))) { |
| // Element family is the same, use the "worst" case map. |
| store_mode = GetNonTransitioningStoreMode(store_mode); |
| return isolate()->stub_cache()->ComputeKeyedStoreElement( |
| - transitioned_map, strict_mode(), store_mode); |
| - } else if (first_map() == receiver->map() && |
| + transitioned_receiver_map, strict_mode(), store_mode); |
| + } else if (*previous_receiver_map == receiver->map() && |
| old_store_mode == STANDARD_STORE && |
| (IsGrowStoreMode(store_mode) || |
| store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS || |
| @@ -1444,9 +1462,6 @@ 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); |
| @@ -2703,8 +2718,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 && (first_map() != NULL) |
| - ? first_map() |
| + Handle<Map> monomorphic_map(already_monomorphic |
| + ? target()->FindFirstMap() |
| : HeapObject::cast(*object)->map()); |
| code = isolate()->stub_cache()->ComputeCompareNil(monomorphic_map, stub); |
| } else { |