Cleanup IC-related code

BUG=

Review URL: https://codereview.chromium.org/1865863003

Cr-Commit-Position: refs/heads/master@{#35297}
This commit is contained in:
verwaest 2016-04-06 05:06:46 -07:00 committed by Commit bot
parent d16c3825fb
commit 787516891f
9 changed files with 111 additions and 410 deletions

View File

@ -265,8 +265,8 @@ void StaticMarkingVisitor<StaticVisitor>::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());

View File

@ -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<Map> IC::GetHandlerCacheHolder(Handle<Map> receiver_map,
bool receiver_is_holder, Isolate* isolate,
CacheHolderFlag* flag) {

View File

@ -95,8 +95,8 @@ const char* GetTransitionMarkModifier(KeyedAccessStoreMode mode) {
void IC::TraceIC(const char* type, Handle<Object> 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<Object> name) {
void IC::TraceIC(const char* type, Handle<Object> 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<Object> 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<KeyedStoreICNexus>()->GetKeyedAccessStoreMode();
modifier = GetTransitionMarkModifier(mode);
@ -146,7 +145,6 @@ void IC::TraceIC(const char* type, Handle<Object> 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<Object> receiver, Handle<String> 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<Object> receiver, Handle<String> name) {
}
bool IC::RecomputeHandlerForName(Handle<Object> 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> name, Handle<Code> 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> map = receiver_map();
MapHandleList maps;
CodeHandleList handlers;
@ -737,14 +704,11 @@ bool IC::UpdatePolymorphicIC(Handle<Name> name, Handle<Code> 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<Code> ic;
if (number_of_valid_maps == 1) {
ConfigureVectorState(name, receiver_map(), code);
@ -762,7 +726,6 @@ bool IC::UpdatePolymorphicIC(Handle<Name> name, Handle<Code> code) {
ConfigureVectorState(name, &maps, &handlers);
}
if (!UseVector()) set_target(*ic);
return true;
}
@ -777,7 +740,7 @@ void IC::CopyICToMegamorphicCache(Handle<Name> 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> name, Handle<Code> 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<Code> KeyedStoreIC::ChooseMegamorphicStub(Isolate* isolate,
}
Handle<Code> LoadIC::megamorphic_stub() {
DCHECK_EQ(Code::KEYED_LOAD_IC, kind());
return KeyedLoadIC::ChooseMegamorphicStub(isolate(), extra_ic_state());
}
Handle<Code> LoadIC::SimpleFieldLoad(FieldIndex index) {
LoadFieldStub stub(isolate(), index);
return stub.GetCode();
@ -1239,7 +1190,6 @@ static Handle<Object> TryConvertKey(Handle<Object> key, Isolate* isolate) {
Handle<Code> KeyedLoadIC::LoadElementStub(Handle<HeapObject> receiver) {
Handle<Code> null_handle;
Handle<Map> 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<Code> KeyedLoadIC::LoadElementStub(Handle<HeapObject> receiver) {
PropertyICCompiler::ComputeKeyedLoadMonomorphicHandler(
receiver_map, extra_ic_state());
ConfigureVectorState(Handle<Name>::null(), receiver_map, handler);
return null_handle;
return Handle<Code>();
}
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<Code>();
}
}
@ -1276,7 +1226,7 @@ Handle<Code> KeyedLoadIC::LoadElementStub(Handle<HeapObject> receiver) {
PropertyICCompiler::ComputeKeyedLoadMonomorphicHandler(
receiver_map, extra_ic_state());
ConfigureVectorState(Handle<Name>::null(), receiver_map, handler);
return null_handle;
return Handle<Code>();
}
DCHECK(state() != GENERIC);
@ -1287,21 +1237,21 @@ Handle<Code> KeyedLoadIC::LoadElementStub(Handle<HeapObject> 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<Code>();
}
// 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<Code>();
}
CodeHandleList handlers(target_receiver_maps.length());
ElementHandlerCompiler compiler(isolate());
compiler.CompileElementHandlers(&target_receiver_maps, &handlers);
ConfigureVectorState(Handle<Name>::null(), &target_receiver_maps, &handlers);
return null_handle;
return Handle<Code>();
}
@ -1316,7 +1266,7 @@ MaybeHandle<Object> KeyedLoadIC::Load(Handle<Object> object,
}
Handle<Object> load_handle;
Handle<Code> stub = megamorphic_stub();
Handle<Code> 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<Object> KeyedLoadIC::Load(Handle<Object> 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<Object> StoreIC::Store(Handle<Object> object, Handle<Name> 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<Code> CallIC::initialize_stub_in_optimized_code(
}
static Handle<Code> StoreICInitializeStubHelper(
Isolate* isolate, ExtraICState extra_state,
InlineCacheState initialization_state) {
Handle<Code> ic = PropertyICCompiler::ComputeStore(
isolate, initialization_state, extra_state);
return ic;
}
Handle<Code> StoreIC::initialize_stub(Isolate* isolate,
LanguageMode language_mode,
State initialization_state) {
@ -1564,26 +1501,10 @@ Handle<Code> 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<Code> 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<Code> StoreIC::slow_stub() const {
if (kind() == Code::STORE_IC) {
return isolate()->builtins()->StoreIC_Slow();
@ -1845,13 +1766,13 @@ Handle<Code> KeyedStoreIC::StoreElementStub(Handle<Map> 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<Code>();
}
// 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<Code>();
}
// Make sure all polymorphic handlers have the same store mode, otherwise the
@ -1862,7 +1783,7 @@ Handle<Code> KeyedStoreIC::StoreElementStub(Handle<Map> 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<Code>();
}
}
@ -1880,7 +1801,7 @@ Handle<Code> KeyedStoreIC::StoreElementStub(Handle<Map> 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<Code>();
}
}
@ -2003,7 +1924,6 @@ MaybeHandle<Object> KeyedStoreIC::Store(Handle<Object> object,
key = TryConvertKey(key, isolate());
Handle<Object> store_handle;
Handle<Code> stub = megamorphic_stub();
uint32_t index;
if ((key->IsInternalizedString() &&
@ -2064,6 +1984,7 @@ MaybeHandle<Object> KeyedStoreIC::Store(Handle<Object> object,
value, language_mode()),
Object);
Handle<Code> stub;
if (use_ic) {
if (!old_receiver_map.is_null()) {
if (sloppy_arguments_elements) {
@ -2087,12 +2008,11 @@ MaybeHandle<Object> KeyedStoreIC::Store(Handle<Object> 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<Object> BinaryOpIC::Transition(
Handle<AllocationSite> allocation_site, Handle<Object> left,
Handle<Object> 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<Object> result;
@ -2502,12 +2422,8 @@ MaybeHandle<Object> 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<Object> ToBooleanIC::ToBoolean(Handle<Object> object) {
ToBooleanICStub stub(isolate(), target()->extra_ic_state());
ToBooleanICStub stub(isolate(), extra_ic_state());
bool to_boolean_value = stub.UpdateStatus(object);
Handle<Code> code = stub.GetCode();
set_target(*code);

View File

@ -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<Map> GetHandlerCacheHolder(Handle<Map> receiver_map,
@ -82,9 +80,6 @@ class IC {
}
protected:
// Get the call-site target; used for determining the state.
Handle<Code> 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> name, Handle<Code> 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<Code> megamorphic_stub() {
UNREACHABLE();
return Handle<Code>::null();
}
bool ShouldRecomputeHandler(Handle<Object> receiver, Handle<String> name);
ExtraICState extra_ic_state() const { return extra_ic_state_; }
void set_extra_ic_state(ExtraICState state) { extra_ic_state_ = state; }
Handle<Map> receiver_map() { return receiver_map_; }
void update_receiver_map(Handle<Object> receiver) {
@ -201,8 +189,6 @@ class IC {
return target_maps_.length() > 0 ? *target_maps_.at(0) : NULL;
}
inline void UpdateTarget();
Handle<TypeFeedbackVector> 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<Code> 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<Code> slow_stub() const {
if (kind() == Code::LOAD_IC) {
return isolate()->builtins()->LoadIC_Slow();
@ -341,8 +314,6 @@ class LoadIC : public IC {
}
}
Handle<Code> 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<Object> Load(Handle<Object> object,
@ -454,7 +424,6 @@ class StoreIC : public IC {
protected:
// Stub accessors.
Handle<Code> megamorphic_stub() override;
Handle<Code> 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<Object> Store(Handle<Object> object,
Handle<Object> name,
@ -531,8 +496,6 @@ class KeyedStoreIC : public StoreIC {
KeyedAccessStoreMode store_mode);
private:
inline void set_target(Code* code);
Handle<Map> ComputeTransitionedMap(Handle<Map> map,
KeyedAccessStoreMode store_mode);

View File

@ -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; }

View File

@ -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>(code));
i++;
}
skip_next_handler = false;
}
}
return i == length;
}
MaybeHandle<Code> 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<Code>();
}
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());
}
}
}

View File

@ -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<Code> 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,

View File

@ -295,7 +295,7 @@ void TypeFeedbackOracle::KeyedPropertyReceiverTypes(
*key_type = ELEMENT;
} else {
KeyedLoadICNexus nexus(feedback_vector_, slot);
CollectReceiverTypes<FeedbackNexus>(&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<FeedbackNexus>(&nexus, name, flags, types);
CollectReceiverTypes(&nexus, name, flags, types);
}
template <class T>
void TypeFeedbackOracle::CollectReceiverTypes(T* obj, Handle<Name> name,
void TypeFeedbackOracle::CollectReceiverTypes(FeedbackNexus* nexus,
Handle<Name> 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<T>(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<FeedbackNexus>(&nexus, types);
CollectReceiverTypes(&nexus, types);
} else {
DCHECK_EQ(FeedbackVectorSlotKind::KEYED_STORE_IC, kind);
KeyedStoreICNexus nexus(feedback_vector_, slot);
CollectReceiverTypes<FeedbackNexus>(&nexus, types);
CollectReceiverTypes(&nexus, types);
}
}
template <class T>
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;
}

View File

@ -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 <class T>
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> name,
Code::Flags flags, SmallMapList* types);
template <class T>
void CollectReceiverTypes(T* obj, Handle<Name> name, Code::Flags flags,
SmallMapList* types);
void CollectReceiverTypes(FeedbackNexus* nexus, Handle<Name> name,
Code::Flags flags, SmallMapList* types);
// Returns true if there is at least one string map and if
// all maps are string maps.