From dafb11f8b3056312e96425ce7def3b42386f5d27 Mon Sep 17 00:00:00 2001 From: "ulan@chromium.org" Date: Tue, 18 Feb 2014 15:12:58 +0000 Subject: [PATCH] Load target types and handlers before IC computation. BUG= R=verwaest@chromium.org Review URL: https://codereview.chromium.org/170563002 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@19455 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/ic.cc | 95 +++++++++++++++++++++++++++------------------------------------ src/ic.h | 18 +++++++++++- 2 files changed, 57 insertions(+), 56 deletions(-) diff --git a/src/ic.cc b/src/ic.cc index 0ca70d3..bd06cb6 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 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 receiver, void IC::TryRemoveInvalidHandlers(Handle map, Handle name) { - CodeHandleList handlers; - target()->FindHandlers(&handlers); - for (int i = 0; i < handlers.length(); i++) { - Handle handler = handlers.at(i); + for (int i = 0; i < handlers()->length(); i++) { + Handle 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 type, Handle name, Handle 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 current_type = types.at(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--; @@ -632,18 +628,19 @@ bool IC::UpdatePolymorphicIC(Handle 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); } else { - types.Add(type); - handlers.Add(code); + types()->Add(type); + handlers()->Add(code); } Handle 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 type, void IC::CopyICToMegamorphicCache(Handle 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 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 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 KeyedLoadIC::LoadElementStub(Handle 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 KeyedStoreIC::StoreElementStub(Handle 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 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 transitioned_receiver_map = receiver_map; + Handle transitioned_map = receiver_map; if (IsTransitionStoreMode(store_mode)) { - transitioned_receiver_map = - ComputeTransitionedMap(receiver, store_mode); + transitioned_map = ComputeTransitionedMap(receiver, store_mode); } - if (IsTransitionOfMonomorphicTarget( - MapToType(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 KeyedStoreIC::StoreElementStub(Handle 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) { // Find or create the specialized stub to support the new set of types. Handle code; if (stub.IsMonomorphic()) { - Handle monomorphic_map(already_monomorphic - ? target()->FindFirstMap() + Handle monomorphic_map(already_monomorphic && (first_map() != NULL) + ? first_map() : HeapObject::cast(*object)->map()); code = isolate()->stub_cache()->ComputeCompareNil(monomorphic_map, stub); } else { diff --git a/src/ic.h b/src/ic.h index 213a481..fce585f 100644 --- a/src/ic.h +++ b/src/ic.h @@ -150,6 +150,19 @@ class IC { // Get the call-site target; used for determining the state. Handle target() const { return target_; } + TypeHandleList* types() { return &types_; } + CodeHandleList* handlers() { return &handlers_; } + Map* first_map() { + return types_.length() == 0 ? NULL : *TypeToMap(*types_.at(0), isolate_); + } + Code* first_handler() { + return handlers_.length() == 0 ? NULL : *handlers_.at(0); + } + void GetMapsFromTypes(MapHandleList* maps) { + for (int i = 0; i < types_.length(); ++i) { + maps->Add(TypeToMap(*types_.at(i), isolate_)); + } + } Address fp() const { return fp_; } Address pc() const { return *pc_address_; } Isolate* isolate() const { return isolate_; } @@ -209,7 +222,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); @@ -260,6 +273,9 @@ class IC { ExtraICState extra_ic_state_; + TypeHandleList types_; + CodeHandleList handlers_; + DISALLOW_IMPLICIT_CONSTRUCTORS(IC); }; -- 2.7.4