diff --git a/src/heap/objects-visiting-inl.h b/src/heap/objects-visiting-inl.h index c415713ee3..b714335132 100644 --- a/src/heap/objects-visiting-inl.h +++ b/src/heap/objects-visiting-inl.h @@ -265,8 +265,8 @@ void StaticMarkingVisitor::VisitCodeTarget(Heap* heap, // when they might be keeping a Context alive, or when the heap is about // to be serialized. if (FLAG_cleanup_code_caches_at_gc && target->is_inline_cache_stub() && - !target->is_call_stub() && (heap->isolate()->serializer_enabled() || - target->ic_age() != heap->global_ic_age())) { + (heap->isolate()->serializer_enabled() || + target->ic_age() != heap->global_ic_age())) { ICUtility::Clear(heap->isolate(), rinfo->pc(), rinfo->host()->constant_pool()); target = Code::GetCodeFromTargetAddress(rinfo->target_address()); diff --git a/src/ic/ic-inl.h b/src/ic/ic-inl.h index 998bd8cf12..f77c40a396 100644 --- a/src/ic/ic-inl.h +++ b/src/ic/ic-inl.h @@ -87,42 +87,12 @@ void IC::SetTargetAtAddress(Address address, Code* target, void IC::set_target(Code* code) { SetTargetAtAddress(address(), code, constant_pool()); - target_set_ = true; } - -void LoadIC::set_target(Code* code) { - // The contextual mode must be preserved across IC patching. - DCHECK(LoadICState::GetTypeofMode(code->extra_ic_state()) == - LoadICState::GetTypeofMode(target()->extra_ic_state())); - - IC::set_target(code); -} - - -void StoreIC::set_target(Code* code) { - // Language mode must be preserved across IC patching. - DCHECK(StoreICState::GetLanguageMode(code->extra_ic_state()) == - StoreICState::GetLanguageMode(target()->extra_ic_state())); - IC::set_target(code); -} - - -void KeyedStoreIC::set_target(Code* code) { - // Language mode must be preserved across IC patching. - DCHECK(StoreICState::GetLanguageMode(code->extra_ic_state()) == - language_mode()); - IC::set_target(code); -} - - -Code* IC::raw_target() const { +Code* IC::target() const { return GetTargetAtAddress(address(), constant_pool()); } -void IC::UpdateTarget() { target_ = handle(raw_target(), isolate_); } - - Handle IC::GetHandlerCacheHolder(Handle receiver_map, bool receiver_is_holder, Isolate* isolate, CacheHolderFlag* flag) { diff --git a/src/ic/ic.cc b/src/ic/ic.cc index 045c4593e1..f8ffc5e2a1 100644 --- a/src/ic/ic.cc +++ b/src/ic/ic.cc @@ -95,8 +95,8 @@ const char* GetTransitionMarkModifier(KeyedAccessStoreMode mode) { void IC::TraceIC(const char* type, Handle name) { if (FLAG_trace_ic) { if (AddressIsDeoptimizedCode()) return; - State new_state = - UseVector() ? nexus()->StateFromFeedback() : raw_target()->ic_state(); + DCHECK(UseVector()); + State new_state = nexus()->StateFromFeedback(); TraceIC(type, name, state(), new_state); } } @@ -105,8 +105,7 @@ void IC::TraceIC(const char* type, Handle name) { void IC::TraceIC(const char* type, Handle name, State old_state, State new_state) { if (FLAG_trace_ic) { - Code* new_target = raw_target(); - PrintF("[%s%s in ", new_target->is_keyed_stub() ? "Keyed" : "", type); + PrintF("[%s%s in ", is_keyed() ? "Keyed" : "", type); // TODO(jkummerow): Add support for "apply". The logic is roughly: // marker = [fp_ + kMarkerOffset]; @@ -123,7 +122,7 @@ void IC::TraceIC(const char* type, Handle name, State old_state, } const char* modifier = ""; - if (new_target->kind() == Code::KEYED_STORE_IC) { + if (kind() == Code::KEYED_STORE_IC) { KeyedAccessStoreMode mode = casted_nexus()->GetKeyedAccessStoreMode(); modifier = GetTransitionMarkModifier(mode); @@ -146,7 +145,6 @@ void IC::TraceIC(const char* type, Handle name, State old_state, IC::IC(FrameDepth depth, Isolate* isolate, FeedbackNexus* nexus) : isolate_(isolate), - target_set_(false), vector_set_(false), target_maps_set_(false), nexus_(nexus) { @@ -185,11 +183,11 @@ IC::IC(FrameDepth depth, Isolate* isolate, FeedbackNexus* nexus) constant_pool_address_ = constant_pool; } pc_address_ = StackFrame::ResolveReturnAddressLocation(pc_address); - target_ = handle(raw_target(), isolate); - kind_ = target_->kind(); - state_ = UseVector() ? nexus->StateFromFeedback() : target_->ic_state(); + Code* target = this->target(); + kind_ = target->kind(); + state_ = UseVector() ? nexus->StateFromFeedback() : target->ic_state(); old_state_ = state_; - extra_ic_state_ = target_->extra_ic_state(); + extra_ic_state_ = target->extra_ic_state(); } @@ -260,11 +258,8 @@ static void LookupForRead(LookupIterator* it) { bool IC::ShouldRecomputeHandler(Handle receiver, Handle name) { if (!RecomputeHandlerForName(name)) return false; - if (UseVector()) { - maybe_handler_ = nexus()->FindHandlerForMap(receiver_map()); - } else { - maybe_handler_ = target()->FindHandlerForMap(*receiver_map()); - } + DCHECK(UseVector()); + maybe_handler_ = nexus()->FindHandlerForMap(receiver_map()); // The current map wasn't handled yet. There's no reason to stay monomorphic, // *unless* we're moving from a deprecated map to its replacement, or @@ -293,11 +288,11 @@ bool IC::ShouldRecomputeHandler(Handle receiver, Handle name) { } bool IC::RecomputeHandlerForName(Handle name) { - if (target()->is_keyed_stub()) { + if (is_keyed()) { // Determine whether the failure is due to a name failure. if (!name->IsName()) return false; - Name* stub_name = - UseVector() ? nexus()->FindFirstName() : target()->FindFirstName(); + DCHECK(UseVector()); + Name* stub_name = nexus()->FindFirstName(); if (*name != stub_name) return false; } @@ -369,37 +364,6 @@ static void ComputeTypeInfoCountDelta(IC::State old_state, IC::State new_state, } } - -void IC::OnTypeFeedbackChanged(Isolate* isolate, Address address, - State old_state, State new_state, - bool target_remains_ic_stub) { - Code* host = - isolate->inner_pointer_to_code_cache()->GetCacheEntry(address)->code; - if (host->kind() != Code::FUNCTION) return; - - if (FLAG_type_info_threshold > 0 && target_remains_ic_stub && - // Not all Code objects have TypeFeedbackInfo. - host->type_feedback_info()->IsTypeFeedbackInfo()) { - int polymorphic_delta = 0; // "Polymorphic" here includes monomorphic. - int generic_delta = 0; // "Generic" here includes megamorphic. - ComputeTypeInfoCountDelta(old_state, new_state, &polymorphic_delta, - &generic_delta); - TypeFeedbackInfo* info = TypeFeedbackInfo::cast(host->type_feedback_info()); - info->change_ic_with_type_info_count(polymorphic_delta); - info->change_ic_generic_count(generic_delta); - } - if (host->type_feedback_info()->IsTypeFeedbackInfo()) { - TypeFeedbackInfo* info = TypeFeedbackInfo::cast(host->type_feedback_info()); - info->change_own_type_change_checksum(); - } - host->set_profiler_ticks(0); - isolate->runtime_profiler()->NotifyICChanged(); - // TODO(2029): When an optimized function is patched, it would - // be nice to propagate the corresponding type information to its - // unoptimized version for the benefit of later inlining. -} - - // static void IC::OnTypeFeedbackChanged(Isolate* isolate, Code* host) { if (host->kind() != Code::FUNCTION) return; @@ -413,48 +377,51 @@ void IC::OnTypeFeedbackChanged(Isolate* isolate, Code* host) { // unoptimized version for the benefit of later inlining. } - void IC::PostPatching(Address address, Code* target, Code* old_target) { // Type vector based ICs update these statistics at a different time because // they don't always patch on state change. if (ICUseVector(target->kind())) return; - Isolate* isolate = target->GetHeap()->isolate(); - State old_state = UNINITIALIZED; - State new_state = UNINITIALIZED; - bool target_remains_ic_stub = false; - if (old_target->is_inline_cache_stub() && target->is_inline_cache_stub()) { - old_state = old_target->ic_state(); - new_state = target->ic_state(); - target_remains_ic_stub = true; + DCHECK(old_target->is_inline_cache_stub()); + DCHECK(target->is_inline_cache_stub()); + State old_state = old_target->ic_state(); + State new_state = target->ic_state(); + + Isolate* isolate = target->GetIsolate(); + Code* host = + isolate->inner_pointer_to_code_cache()->GetCacheEntry(address)->code; + if (host->kind() != Code::FUNCTION) return; + + // Not all Code objects have TypeFeedbackInfo. + if (host->type_feedback_info()->IsTypeFeedbackInfo()) { + if (FLAG_type_info_threshold > 0) { + int polymorphic_delta = 0; // "Polymorphic" here includes monomorphic. + int generic_delta = 0; // "Generic" here includes megamorphic. + ComputeTypeInfoCountDelta(old_state, new_state, &polymorphic_delta, + &generic_delta); + TypeFeedbackInfo* info = + TypeFeedbackInfo::cast(host->type_feedback_info()); + info->change_ic_with_type_info_count(polymorphic_delta); + info->change_ic_generic_count(generic_delta); + } + TypeFeedbackInfo* info = TypeFeedbackInfo::cast(host->type_feedback_info()); + info->change_own_type_change_checksum(); } - - OnTypeFeedbackChanged(isolate, address, old_state, new_state, - target_remains_ic_stub); + host->set_profiler_ticks(0); + isolate->runtime_profiler()->NotifyICChanged(); + // TODO(2029): When an optimized function is patched, it would + // be nice to propagate the corresponding type information to its + // unoptimized version for the benefit of later inlining. } - void IC::Clear(Isolate* isolate, Address address, Address constant_pool) { Code* target = GetTargetAtAddress(address, constant_pool); // Don't clear debug break inline cache as it will remove the break point. if (target->is_debug_stub()) return; - switch (target->kind()) { - case Code::COMPARE_IC: - return CompareIC::Clear(isolate, address, target, constant_pool); - case Code::BINARY_OP_IC: - case Code::CALL_IC: // CallICs are vector-based and cleared differently. - case Code::KEYED_LOAD_IC: - case Code::KEYED_STORE_IC: - case Code::LOAD_IC: - case Code::STORE_IC: - case Code::TO_BOOLEAN_IC: - // Clearing these is tricky and does not - // make any performance difference. - return; - default: - UNREACHABLE(); + if (target->kind() == Code::COMPARE_IC) { + CompareIC::Clear(isolate, address, target, constant_pool); } } @@ -704,7 +671,7 @@ static bool AddOneReceiverMapIfMissing(MapHandleList* receiver_maps, bool IC::UpdatePolymorphicIC(Handle name, Handle code) { if (!code->is_handler()) return false; - if (target()->is_keyed_stub() && state() != RECOMPUTE_HANDLER) return false; + if (is_keyed() && state() != RECOMPUTE_HANDLER) return false; Handle map = receiver_map(); MapHandleList maps; CodeHandleList handlers; @@ -737,14 +704,11 @@ bool IC::UpdatePolymorphicIC(Handle name, Handle code) { if (number_of_maps == 0 && state() != MONOMORPHIC && state() != POLYMORPHIC) { return false; } - if (UseVector()) { - if (!nexus()->FindHandlers(&handlers, maps.length())) return false; - } else { - if (!target()->FindHandlers(&handlers, maps.length())) return false; - } + DCHECK(UseVector()); + if (!nexus()->FindHandlers(&handlers, maps.length())) return false; number_of_valid_maps++; - if (number_of_valid_maps > 1 && target()->is_keyed_stub()) return false; + if (number_of_valid_maps > 1 && is_keyed()) return false; Handle ic; if (number_of_valid_maps == 1) { ConfigureVectorState(name, receiver_map(), code); @@ -762,7 +726,6 @@ bool IC::UpdatePolymorphicIC(Handle name, Handle code) { ConfigureVectorState(name, &maps, &handlers); } - if (!UseVector()) set_target(*ic); return true; } @@ -777,7 +740,7 @@ void IC::CopyICToMegamorphicCache(Handle name) { MapHandleList maps; CodeHandleList handlers; TargetMaps(&maps); - if (!target()->FindHandlers(&handlers, maps.length())) return; + if (!nexus()->FindHandlers(&handlers, maps.length())) return; for (int i = 0; i < maps.length(); i++) { UpdateMegamorphicCache(*maps.at(i), *name, *handlers.at(i)); } @@ -808,26 +771,20 @@ void IC::PatchCache(Handle name, Handle code) { case RECOMPUTE_HANDLER: case MONOMORPHIC: case POLYMORPHIC: - if (!target()->is_keyed_stub() || state() == RECOMPUTE_HANDLER) { + if (!is_keyed() || state() == RECOMPUTE_HANDLER) { if (UpdatePolymorphicIC(name, code)) break; // For keyed stubs, we can't know whether old handlers were for the // same key. CopyICToMegamorphicCache(name); } - if (UseVector()) { - ConfigureVectorState(MEGAMORPHIC); - } else { - set_target(*megamorphic_stub()); - } + DCHECK(UseVector()); + ConfigureVectorState(MEGAMORPHIC); // Fall through. case MEGAMORPHIC: UpdateMegamorphicCache(*receiver_map(), *name, *code); // Indicate that we've handled this case. - if (UseVector()) { - vector_set_ = true; - } else { - target_set_ = true; - } + DCHECK(UseVector()); + vector_set_ = true; break; case DEBUG_STUB: break; @@ -912,12 +869,6 @@ Handle KeyedStoreIC::ChooseMegamorphicStub(Isolate* isolate, } -Handle LoadIC::megamorphic_stub() { - DCHECK_EQ(Code::KEYED_LOAD_IC, kind()); - return KeyedLoadIC::ChooseMegamorphicStub(isolate(), extra_ic_state()); -} - - Handle LoadIC::SimpleFieldLoad(FieldIndex index) { LoadFieldStub stub(isolate(), index); return stub.GetCode(); @@ -1239,7 +1190,6 @@ static Handle TryConvertKey(Handle key, Isolate* isolate) { Handle KeyedLoadIC::LoadElementStub(Handle receiver) { - Handle null_handle; Handle receiver_map(receiver->map(), isolate()); DCHECK(receiver_map->instance_type() != JS_VALUE_TYPE); // Checked by caller. MapHandleList target_receiver_maps; @@ -1250,14 +1200,14 @@ Handle KeyedLoadIC::LoadElementStub(Handle receiver) { PropertyICCompiler::ComputeKeyedLoadMonomorphicHandler( receiver_map, extra_ic_state()); ConfigureVectorState(Handle::null(), receiver_map, handler); - return null_handle; + return Handle(); } for (int i = 0; i < target_receiver_maps.length(); i++) { if (!target_receiver_maps.at(i).is_null() && target_receiver_maps.at(i)->instance_type() == JS_VALUE_TYPE) { TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "JSValue"); - return megamorphic_stub(); + return Handle(); } } @@ -1276,7 +1226,7 @@ Handle KeyedLoadIC::LoadElementStub(Handle receiver) { PropertyICCompiler::ComputeKeyedLoadMonomorphicHandler( receiver_map, extra_ic_state()); ConfigureVectorState(Handle::null(), receiver_map, handler); - return null_handle; + return Handle(); } DCHECK(state() != GENERIC); @@ -1287,21 +1237,21 @@ Handle KeyedLoadIC::LoadElementStub(Handle receiver) { // If the miss wasn't due to an unseen map, a polymorphic stub // won't help, use the generic stub. TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "same map added twice"); - return megamorphic_stub(); + return Handle(); } // If the maximum number of receiver maps has been exceeded, use the generic // version of the IC. if (target_receiver_maps.length() > kMaxKeyedPolymorphism) { TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "max polymorph exceeded"); - return megamorphic_stub(); + return Handle(); } CodeHandleList handlers(target_receiver_maps.length()); ElementHandlerCompiler compiler(isolate()); compiler.CompileElementHandlers(&target_receiver_maps, &handlers); ConfigureVectorState(Handle::null(), &target_receiver_maps, &handlers); - return null_handle; + return Handle(); } @@ -1316,7 +1266,7 @@ MaybeHandle KeyedLoadIC::Load(Handle object, } Handle load_handle; - Handle stub = megamorphic_stub(); + Handle stub; // Check for non-string values that can be converted into an // internalized string directly or is representable as a smi. @@ -1335,9 +1285,8 @@ MaybeHandle KeyedLoadIC::Load(Handle object, } DCHECK(UseVector()); - if (!is_vector_set() || stub.is_null()) { - Code* generic = *megamorphic_stub(); - if (!stub.is_null() && *stub == generic) { + if (!is_vector_set()) { + if (stub.is_null()) { ConfigureVectorState(MEGAMORPHIC); TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "set generic"); } @@ -1431,11 +1380,8 @@ MaybeHandle StoreIC::Store(Handle object, Handle name, if (kind() == Code::KEYED_STORE_IC && name->AsArrayIndex(&index)) { // Rewrite to the generic keyed store stub. if (FLAG_use_ic) { - if (UseVector()) { - ConfigureVectorState(MEGAMORPHIC); - } else if (!AddressIsDeoptimizedCode()) { - set_target(*megamorphic_stub()); - } + DCHECK(UseVector()); + ConfigureVectorState(MEGAMORPHIC); TRACE_IC("StoreIC", name); TRACE_GENERIC_IC(isolate(), "StoreIC", "name as array index"); } @@ -1534,15 +1480,6 @@ Handle CallIC::initialize_stub_in_optimized_code( } -static Handle StoreICInitializeStubHelper( - Isolate* isolate, ExtraICState extra_state, - InlineCacheState initialization_state) { - Handle ic = PropertyICCompiler::ComputeStore( - isolate, initialization_state, extra_state); - return ic; -} - - Handle StoreIC::initialize_stub(Isolate* isolate, LanguageMode language_mode, State initialization_state) { @@ -1564,26 +1501,10 @@ Handle StoreIC::initialize_stub_in_optimized_code( return stub.GetCode(); } - return StoreICInitializeStubHelper( - isolate, ComputeExtraICState(language_mode), initialization_state); + return PropertyICCompiler::ComputeStore(isolate, initialization_state, + ComputeExtraICState(language_mode)); } - -Handle StoreIC::megamorphic_stub() { - if (kind() == Code::STORE_IC) { - return PropertyICCompiler::ComputeStore(isolate(), MEGAMORPHIC, - extra_ic_state()); - } else { - DCHECK(kind() == Code::KEYED_STORE_IC); - if (is_strict(language_mode())) { - return isolate()->builtins()->KeyedStoreIC_Megamorphic_Strict(); - } else { - return isolate()->builtins()->KeyedStoreIC_Megamorphic(); - } - } -} - - Handle StoreIC::slow_stub() const { if (kind() == Code::STORE_IC) { return isolate()->builtins()->StoreIC_Slow(); @@ -1845,13 +1766,13 @@ Handle KeyedStoreIC::StoreElementStub(Handle receiver_map, // If the miss wasn't due to an unseen map, a polymorphic stub // won't help, use the megamorphic stub which can handle everything. TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "same map added twice"); - return megamorphic_stub(); + return Handle(); } // If the maximum number of receiver maps has been exceeded, use the // megamorphic version of the IC. if (target_receiver_maps.length() > kMaxKeyedPolymorphism) { - return megamorphic_stub(); + return Handle(); } // Make sure all polymorphic handlers have the same store mode, otherwise the @@ -1862,7 +1783,7 @@ Handle KeyedStoreIC::StoreElementStub(Handle receiver_map, store_mode = old_store_mode; } else if (store_mode != old_store_mode) { TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "store mode mismatch"); - return megamorphic_stub(); + return Handle(); } } @@ -1880,7 +1801,7 @@ Handle KeyedStoreIC::StoreElementStub(Handle receiver_map, external_arrays != target_receiver_maps.length()) { TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "unsupported combination of external and normal arrays"); - return megamorphic_stub(); + return Handle(); } } @@ -2003,7 +1924,6 @@ MaybeHandle KeyedStoreIC::Store(Handle object, key = TryConvertKey(key, isolate()); Handle store_handle; - Handle stub = megamorphic_stub(); uint32_t index; if ((key->IsInternalizedString() && @@ -2064,6 +1984,7 @@ MaybeHandle KeyedStoreIC::Store(Handle object, value, language_mode()), Object); + Handle stub; if (use_ic) { if (!old_receiver_map.is_null()) { if (sloppy_arguments_elements) { @@ -2087,12 +2008,11 @@ MaybeHandle KeyedStoreIC::Store(Handle object, } } - if (!is_vector_set() || stub.is_null()) { - Code* megamorphic = *megamorphic_stub(); - if (!stub.is_null() && (*stub == megamorphic || *stub == *slow_stub())) { + if (!is_vector_set()) { + if (stub.is_null() || *stub == *slow_stub()) { ConfigureVectorState(MEGAMORPHIC); TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", - *stub == megamorphic ? "set generic" : "slow stub"); + stub.is_null() ? "set generic" : "slow stub"); } } TRACE_IC("StoreIC", key); @@ -2438,7 +2358,7 @@ RUNTIME_FUNCTION(Runtime_ElementsTransitionAndStoreIC_Miss) { MaybeHandle BinaryOpIC::Transition( Handle allocation_site, Handle left, Handle right) { - BinaryOpICState state(isolate(), target()->extra_ic_state()); + BinaryOpICState state(isolate(), extra_ic_state()); // Compute the actual result using the builtin for the binary operation. Handle result; @@ -2502,12 +2422,8 @@ MaybeHandle BinaryOpIC::Transition( return result; } - // Execution::Call can execute arbitrary JavaScript, hence potentially - // update the state of this very IC, so we must update the stored state. - UpdateTarget(); - // Compute the new state. - BinaryOpICState old_state(isolate(), target()->extra_ic_state()); + BinaryOpICState old_state(isolate(), extra_ic_state()); state.Update(left, right, result); // Check if we have a string operation here. @@ -2665,7 +2581,7 @@ RUNTIME_FUNCTION(Runtime_Unreachable) { Handle ToBooleanIC::ToBoolean(Handle object) { - ToBooleanICStub stub(isolate(), target()->extra_ic_state()); + ToBooleanICStub stub(isolate(), extra_ic_state()); bool to_boolean_value = stub.UpdateStatus(object); Handle code = stub.GetCode(); set_target(*code); diff --git a/src/ic/ic.h b/src/ic/ic.h index b4bd2ddb7d..ffdb9ab632 100644 --- a/src/ic/ic.h +++ b/src/ic/ic.h @@ -47,14 +47,12 @@ class IC { #ifdef DEBUG bool IsLoadStub() const { - return target()->is_load_stub() || target()->is_keyed_load_stub(); + return kind_ == Code::LOAD_IC || kind_ == Code::KEYED_LOAD_IC; } - bool IsStoreStub() const { - return target()->is_store_stub() || target()->is_keyed_store_stub(); + return kind_ == Code::STORE_IC || kind_ == Code::KEYED_STORE_IC; } - - bool IsCallStub() const { return target()->is_call_stub(); } + bool IsCallStub() const { return kind_ == Code::CALL_IC; } #endif static inline Handle GetHandlerCacheHolder(Handle receiver_map, @@ -82,9 +80,6 @@ class IC { } protected: - // Get the call-site target; used for determining the state. - Handle target() const { return target_; } - Address fp() const { return fp_; } Address pc() const { return *pc_address_; } Isolate* isolate() const { return isolate_; } @@ -101,13 +96,12 @@ class IC { // Set the call-site target. inline void set_target(Code* code); - bool is_target_set() { return target_set_; } bool is_vector_set() { return vector_set_; } bool UseVector() const { bool use = ICUseVector(kind()); // If we are supposed to use the nexus, verify the nexus is non-null. - DCHECK(!use || nexus_ != NULL); + DCHECK(!use || nexus_ != nullptr); return use; } @@ -139,9 +133,6 @@ class IC { Address constant_pool); static inline void SetTargetAtAddress(Address address, Code* target, Address constant_pool); - static void OnTypeFeedbackChanged(Isolate* isolate, Address address, - State old_state, State new_state, - bool target_remains_ic_stub); // As a vector-based IC, type feedback must be updated differently. static void OnTypeFeedbackChanged(Isolate* isolate, Code* host); static void PostPatching(Address address, Code* target, Code* old_target); @@ -164,21 +155,18 @@ class IC { bool IsTransitionOfMonomorphicTarget(Map* source_map, Map* target_map); void PatchCache(Handle name, Handle code); Code::Kind kind() const { return kind_; } + bool is_keyed() const { + return kind_ == Code::KEYED_LOAD_IC || kind_ == Code::KEYED_STORE_IC; + } Code::Kind handler_kind() const { if (kind_ == Code::KEYED_LOAD_IC) return Code::LOAD_IC; DCHECK(kind_ == Code::LOAD_IC || kind_ == Code::STORE_IC || kind_ == Code::KEYED_STORE_IC); return kind_; } - virtual Handle megamorphic_stub() { - UNREACHABLE(); - return Handle::null(); - } - bool ShouldRecomputeHandler(Handle receiver, Handle name); ExtraICState extra_ic_state() const { return extra_ic_state_; } - void set_extra_ic_state(ExtraICState state) { extra_ic_state_ = state; } Handle receiver_map() { return receiver_map_; } void update_receiver_map(Handle receiver) { @@ -201,8 +189,6 @@ class IC { return target_maps_.length() > 0 ? *target_maps_.at(0) : NULL; } - inline void UpdateTarget(); - Handle vector() const { return nexus()->vector_handle(); } FeedbackVectorSlot slot() const { return nexus()->slot(); } State saved_state() const { @@ -216,25 +202,17 @@ class IC { FeedbackNexus* nexus() const { return nexus_; } inline Code* get_host(); + inline Code* target() const; private: - inline Code* raw_target() const; inline Address constant_pool() const; inline Address raw_constant_pool() const; void FindTargetMaps() { if (target_maps_set_) return; target_maps_set_ = true; - if (UseVector()) { - nexus()->ExtractMaps(&target_maps_); - } else { - if (state_ == MONOMORPHIC) { - Map* map = target_->FindFirstMap(); - if (map != NULL) target_maps_.Add(handle(map)); - } else if (state_ != UNINITIALIZED && state_ != PREMONOMORPHIC) { - target_->FindAllMaps(&target_maps_); - } - } + DCHECK(UseVector()); + nexus()->ExtractMaps(&target_maps_); } // Frame pointer for the frame that uses (calls) the IC. @@ -252,9 +230,6 @@ class IC { Isolate* isolate_; - // The original code target that missed. - Handle target_; - bool target_set_; bool vector_set_; State old_state_; // For saving if we marked as prototype failure. State state_; @@ -330,8 +305,6 @@ class LoadIC : public IC { static void Clear(Isolate* isolate, Code* host, LoadICNexus* nexus); protected: - inline void set_target(Code* code); - Handle slow_stub() const { if (kind() == Code::LOAD_IC) { return isolate()->builtins()->LoadIC_Slow(); @@ -341,8 +314,6 @@ class LoadIC : public IC { } } - Handle megamorphic_stub() override; - // Update the inline cache and the global stub cache based on the // lookup result. void UpdateCaches(LookupIterator* lookup); @@ -377,7 +348,6 @@ class KeyedLoadIC : public LoadIC { KeyedLoadICNexus* nexus = NULL) : LoadIC(depth, isolate, nexus) { DCHECK(nexus != NULL); - DCHECK(target()->is_keyed_load_stub()); } MUST_USE_RESULT MaybeHandle Load(Handle object, @@ -454,7 +424,6 @@ class StoreIC : public IC { protected: // Stub accessors. - Handle megamorphic_stub() override; Handle slow_stub() const; // Update the inline cache and the global stub cache based on the @@ -465,8 +434,6 @@ class StoreIC : public IC { CacheHolderFlag cache_holder) override; private: - inline void set_target(Code* code); - friend class IC; }; @@ -501,9 +468,7 @@ class KeyedStoreIC : public StoreIC { KeyedStoreIC(FrameDepth depth, Isolate* isolate, KeyedStoreICNexus* nexus = NULL) - : StoreIC(depth, isolate, nexus) { - DCHECK(target()->is_keyed_store_stub()); - } + : StoreIC(depth, isolate, nexus) {} MUST_USE_RESULT MaybeHandle Store(Handle object, Handle name, @@ -531,8 +496,6 @@ class KeyedStoreIC : public StoreIC { KeyedAccessStoreMode store_mode); private: - inline void set_target(Code* code); - Handle ComputeTransitionedMap(Handle map, KeyedAccessStoreMode store_mode); diff --git a/src/objects-inl.h b/src/objects-inl.h index b12ce93e47..e1a44e7461 100644 --- a/src/objects-inl.h +++ b/src/objects-inl.h @@ -5025,18 +5025,8 @@ bool Code::is_inline_cache_stub() { } } - -bool Code::is_keyed_stub() { - return is_keyed_load_stub() || is_keyed_store_stub(); -} - - bool Code::is_debug_stub() { return ic_state() == DEBUG_STUB; } bool Code::is_handler() { return kind() == HANDLER; } -bool Code::is_load_stub() { return kind() == LOAD_IC; } -bool Code::is_keyed_load_stub() { return kind() == KEYED_LOAD_IC; } -bool Code::is_store_stub() { return kind() == STORE_IC; } -bool Code::is_keyed_store_stub() { return kind() == KEYED_STORE_IC; } bool Code::is_call_stub() { return kind() == CALL_IC; } bool Code::is_binary_op_stub() { return kind() == BINARY_OP_IC; } bool Code::is_compare_ic_stub() { return kind() == COMPARE_IC; } diff --git a/src/objects.cc b/src/objects.cc index 092383ccac..36d6ea870c 100644 --- a/src/objects.cc +++ b/src/objects.cc @@ -13792,126 +13792,14 @@ void Code::FindAndReplace(const FindAndReplacePattern& pattern) { } -void Code::FindAllMaps(MapHandleList* maps) { - DCHECK(is_inline_cache_stub()); - DisallowHeapAllocation no_allocation; - int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT); - for (RelocIterator it(this, mask); !it.done(); it.next()) { - RelocInfo* info = it.rinfo(); - Object* object = info->target_object(); - if (object->IsWeakCell()) object = WeakCell::cast(object)->value(); - if (object->IsMap()) maps->Add(handle(Map::cast(object))); - } -} - - -Code* Code::FindFirstHandler() { - DCHECK(is_inline_cache_stub()); - DisallowHeapAllocation no_allocation; - int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET) | - RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT); - bool skip_next_handler = false; - for (RelocIterator it(this, mask); !it.done(); it.next()) { - RelocInfo* info = it.rinfo(); - if (info->rmode() == RelocInfo::EMBEDDED_OBJECT) { - Object* obj = info->target_object(); - skip_next_handler |= obj->IsWeakCell() && WeakCell::cast(obj)->cleared(); - } else { - Code* code = Code::GetCodeFromTargetAddress(info->target_address()); - if (code->kind() == Code::HANDLER) { - if (!skip_next_handler) return code; - skip_next_handler = false; - } - } - } - return NULL; -} - - -bool Code::FindHandlers(CodeHandleList* code_list, int length) { - DCHECK(is_inline_cache_stub()); - DisallowHeapAllocation no_allocation; - int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET) | - RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT); - bool skip_next_handler = false; - int i = 0; - for (RelocIterator it(this, mask); !it.done(); it.next()) { - if (i == length) return true; - RelocInfo* info = it.rinfo(); - if (info->rmode() == RelocInfo::EMBEDDED_OBJECT) { - Object* obj = info->target_object(); - skip_next_handler |= obj->IsWeakCell() && WeakCell::cast(obj)->cleared(); - } else { - Code* code = Code::GetCodeFromTargetAddress(info->target_address()); - // IC stubs with handlers never contain non-handler code objects before - // handler targets. - if (code->kind() != Code::HANDLER) break; - if (!skip_next_handler) { - code_list->Add(Handle(code)); - i++; - } - skip_next_handler = false; - } - } - return i == length; -} - - -MaybeHandle Code::FindHandlerForMap(Map* map) { - DCHECK(is_inline_cache_stub()); - int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET) | - RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT); - bool return_next = false; - for (RelocIterator it(this, mask); !it.done(); it.next()) { - RelocInfo* info = it.rinfo(); - if (info->rmode() == RelocInfo::EMBEDDED_OBJECT) { - Object* object = info->target_object(); - if (object->IsWeakCell()) object = WeakCell::cast(object)->value(); - if (object == map) return_next = true; - } else if (return_next) { - Code* code = Code::GetCodeFromTargetAddress(info->target_address()); - DCHECK(code->kind() == Code::HANDLER); - return handle(code); - } - } - return MaybeHandle(); -} - - -Name* Code::FindFirstName() { - DCHECK(is_inline_cache_stub()); - DisallowHeapAllocation no_allocation; - int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT); - for (RelocIterator it(this, mask); !it.done(); it.next()) { - RelocInfo* info = it.rinfo(); - Object* object = info->target_object(); - if (object->IsName()) return Name::cast(object); - } - return NULL; -} - - void Code::ClearInlineCaches() { - ClearInlineCaches(NULL); -} - - -void Code::ClearInlineCaches(Code::Kind kind) { - ClearInlineCaches(&kind); -} - - -void Code::ClearInlineCaches(Code::Kind* kind) { int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET) | RelocInfo::ModeMask(RelocInfo::CODE_TARGET_WITH_ID); for (RelocIterator it(this, mask); !it.done(); it.next()) { RelocInfo* info = it.rinfo(); Code* target(Code::GetCodeFromTargetAddress(info->target_address())); if (target->is_inline_cache_stub()) { - if (kind == NULL || *kind == target->kind()) { - IC::Clear(this->GetIsolate(), info->pc(), - info->host()->constant_pool()); - } + IC::Clear(this->GetIsolate(), info->pc(), info->host()->constant_pool()); } } } diff --git a/src/objects.h b/src/objects.h index 207034d74a..2d0f9ea868 100644 --- a/src/objects.h +++ b/src/objects.h @@ -5012,15 +5012,10 @@ class Code: public HeapObject { inline bool is_inline_cache_stub(); inline bool is_debug_stub(); inline bool is_handler(); - inline bool is_load_stub(); - inline bool is_keyed_load_stub(); - inline bool is_store_stub(); - inline bool is_keyed_store_stub(); inline bool is_call_stub(); inline bool is_binary_op_stub(); inline bool is_compare_ic_stub(); inline bool is_to_boolean_ic_stub(); - inline bool is_keyed_stub(); inline bool is_optimized_code(); inline bool is_wasm_code(); inline bool embeds_maps_weakly(); @@ -5127,20 +5122,6 @@ class Code: public HeapObject { // Find the first map in an IC stub. Map* FindFirstMap(); - void FindAllMaps(MapHandleList* maps); - - // Find the first handler in an IC stub. - Code* FindFirstHandler(); - - // Find |length| handlers and put them into |code_list|. Returns false if not - // enough handlers can be found. - bool FindHandlers(CodeHandleList* code_list, int length = -1); - - // Find the handler for |map|. - MaybeHandle FindHandlerForMap(Map* map); - - // Find the first name in an IC stub. - Name* FindFirstName(); class FindAndReplacePattern; // For each (map-to-find, object-to-replace) pair in the pattern, this @@ -5234,7 +5215,6 @@ class Code: public HeapObject { DECLARE_VERIFIER(Code) void ClearInlineCaches(); - void ClearInlineCaches(Kind kind); BailoutId TranslatePcOffsetToAstId(uint32_t pc_offset); uint32_t TranslateAstIdToPcOffset(BailoutId ast_id); @@ -5403,8 +5383,6 @@ class Code: public HeapObject { friend class RelocIterator; friend class Deoptimizer; // For FindCodeAgeSequence. - void ClearInlineCaches(Kind* kind); - // Code aging byte* FindCodeAgeSequence(); static void GetCodeAgeAndParity(Code* code, Age* age, diff --git a/src/type-info.cc b/src/type-info.cc index 952b27c19a..87429357e2 100644 --- a/src/type-info.cc +++ b/src/type-info.cc @@ -295,7 +295,7 @@ void TypeFeedbackOracle::KeyedPropertyReceiverTypes( *key_type = ELEMENT; } else { KeyedLoadICNexus nexus(feedback_vector_, slot); - CollectReceiverTypes(&nexus, receiver_types); + CollectReceiverTypes(&nexus, receiver_types); *is_string = HasOnlyStringMaps(receiver_types); *key_type = nexus.FindFirstName() != NULL ? PROPERTY : ELEMENT; } @@ -332,21 +332,20 @@ void TypeFeedbackOracle::CollectReceiverTypes(FeedbackVectorSlot slot, Code::Flags flags, SmallMapList* types) { StoreICNexus nexus(feedback_vector_, slot); - CollectReceiverTypes(&nexus, name, flags, types); + CollectReceiverTypes(&nexus, name, flags, types); } - -template -void TypeFeedbackOracle::CollectReceiverTypes(T* obj, Handle name, +void TypeFeedbackOracle::CollectReceiverTypes(FeedbackNexus* nexus, + Handle name, Code::Flags flags, SmallMapList* types) { if (FLAG_collect_megamorphic_maps_from_stub_cache && - obj->ic_state() == MEGAMORPHIC) { + nexus->ic_state() == MEGAMORPHIC) { types->Reserve(4, zone()); isolate()->stub_cache()->CollectMatchingMaps( types, name, flags, native_context_, zone()); } else { - CollectReceiverTypes(obj, types); + CollectReceiverTypes(nexus, types); } } @@ -356,23 +355,22 @@ void TypeFeedbackOracle::CollectReceiverTypes(FeedbackVectorSlot slot, FeedbackVectorSlotKind kind = feedback_vector_->GetKind(slot); if (kind == FeedbackVectorSlotKind::STORE_IC) { StoreICNexus nexus(feedback_vector_, slot); - CollectReceiverTypes(&nexus, types); + CollectReceiverTypes(&nexus, types); } else { DCHECK_EQ(FeedbackVectorSlotKind::KEYED_STORE_IC, kind); KeyedStoreICNexus nexus(feedback_vector_, slot); - CollectReceiverTypes(&nexus, types); + CollectReceiverTypes(&nexus, types); } } - -template -void TypeFeedbackOracle::CollectReceiverTypes(T* obj, SmallMapList* types) { +void TypeFeedbackOracle::CollectReceiverTypes(FeedbackNexus* nexus, + SmallMapList* types) { MapHandleList maps; - if (obj->ic_state() == MONOMORPHIC) { - Map* map = obj->FindFirstMap(); + if (nexus->ic_state() == MONOMORPHIC) { + Map* map = nexus->FindFirstMap(); if (map != NULL) maps.Add(handle(map)); - } else if (obj->ic_state() == POLYMORPHIC) { - obj->FindAllMaps(&maps); + } else if (nexus->ic_state() == POLYMORPHIC) { + nexus->FindAllMaps(&maps); } else { return; } diff --git a/src/type-info.h b/src/type-info.h index c4b0928fc4..3c734be0cd 100644 --- a/src/type-info.h +++ b/src/type-info.h @@ -17,7 +17,7 @@ namespace internal { // Forward declarations. class SmallMapList; - +class FeedbackNexus; class TypeFeedbackOracle: public ZoneObject { public: @@ -56,8 +56,7 @@ class TypeFeedbackOracle: public ZoneObject { SmallMapList* receiver_types); void CollectReceiverTypes(FeedbackVectorSlot slot, SmallMapList* types); - template - void CollectReceiverTypes(T* obj, SmallMapList* types); + void CollectReceiverTypes(FeedbackNexus* nexus, SmallMapList* types); static bool IsRelevantFeedback(Map* map, Context* native_context) { Object* constructor = map->GetConstructor(); @@ -98,9 +97,8 @@ class TypeFeedbackOracle: public ZoneObject { private: void CollectReceiverTypes(FeedbackVectorSlot slot, Handle name, Code::Flags flags, SmallMapList* types); - template - void CollectReceiverTypes(T* obj, Handle name, Code::Flags flags, - SmallMapList* types); + void CollectReceiverTypes(FeedbackNexus* nexus, Handle name, + Code::Flags flags, SmallMapList* types); // Returns true if there is at least one string map and if // all maps are string maps.