Commit 45adc5f8 authored by ishell@chromium.org's avatar ishell@chromium.org Committed by Commit Bot

[ic] Use FeedbackSlotKind instead of Code::Kind in IC class and friends.

Now we can inline vector-based IC dispatchers to bytecode handlers.

BUG=v8:5917

Change-Id: Ie81750f252a730240097e514e69b348f410a48b7
Reviewed-on: https://chromium-review.googlesource.com/439265Reviewed-by: 's avatarMichael Stanton <mvstanton@chromium.org>
Commit-Queue: Igor Sheludko <ishell@chromium.org>
Cr-Commit-Position: refs/heads/master@{#43028}
parent 72bad21c
...@@ -51,6 +51,7 @@ int FeedbackMetadata::GetSlotSize(FeedbackSlotKind kind) { ...@@ -51,6 +51,7 @@ int FeedbackMetadata::GetSlotSize(FeedbackSlotKind kind) {
case FeedbackSlotKind::GENERAL: case FeedbackSlotKind::GENERAL:
case FeedbackSlotKind::INTERPRETER_COMPARE_IC: case FeedbackSlotKind::INTERPRETER_COMPARE_IC:
case FeedbackSlotKind::INTERPRETER_BINARYOP_IC: case FeedbackSlotKind::INTERPRETER_BINARYOP_IC:
case FeedbackSlotKind::TO_BOOLEAN_IC:
case FeedbackSlotKind::LITERAL: case FeedbackSlotKind::LITERAL:
case FeedbackSlotKind::CREATE_CLOSURE: case FeedbackSlotKind::CREATE_CLOSURE:
return 1; return 1;
...@@ -225,6 +226,7 @@ void FeedbackVector::ComputeCounts(int* with_type_info, int* generic, ...@@ -225,6 +226,7 @@ void FeedbackVector::ComputeCounts(int* with_type_info, int* generic,
} }
break; break;
} }
case FeedbackSlotKind::TO_BOOLEAN_IC:
case FeedbackSlotKind::CREATE_CLOSURE: case FeedbackSlotKind::CREATE_CLOSURE:
case FeedbackSlotKind::GENERAL: case FeedbackSlotKind::GENERAL:
case FeedbackSlotKind::LITERAL: case FeedbackSlotKind::LITERAL:
......
...@@ -139,6 +139,8 @@ const char* FeedbackMetadata::Kind2String(FeedbackSlotKind kind) { ...@@ -139,6 +139,8 @@ const char* FeedbackMetadata::Kind2String(FeedbackSlotKind kind) {
return "INTERPRETER_BINARYOP_IC"; return "INTERPRETER_BINARYOP_IC";
case FeedbackSlotKind::INTERPRETER_COMPARE_IC: case FeedbackSlotKind::INTERPRETER_COMPARE_IC:
return "INTERPRETER_COMPARE_IC"; return "INTERPRETER_COMPARE_IC";
case FeedbackSlotKind::TO_BOOLEAN_IC:
return "TO_BOOLEAN_IC";
case FeedbackSlotKind::STORE_DATA_PROPERTY_IN_LITERAL_IC: case FeedbackSlotKind::STORE_DATA_PROPERTY_IN_LITERAL_IC:
return "STORE_DATA_PROPERTY_IN_LITERAL_IC"; return "STORE_DATA_PROPERTY_IN_LITERAL_IC";
case FeedbackSlotKind::CREATE_CLOSURE: case FeedbackSlotKind::CREATE_CLOSURE:
...@@ -191,6 +193,7 @@ Handle<FeedbackVector> FeedbackVector::New(Isolate* isolate, ...@@ -191,6 +193,7 @@ Handle<FeedbackVector> FeedbackVector::New(Isolate* isolate,
break; break;
case FeedbackSlotKind::INTERPRETER_COMPARE_IC: case FeedbackSlotKind::INTERPRETER_COMPARE_IC:
case FeedbackSlotKind::INTERPRETER_BINARYOP_IC: case FeedbackSlotKind::INTERPRETER_BINARYOP_IC:
case FeedbackSlotKind::TO_BOOLEAN_IC:
array->set(index, Smi::kZero, SKIP_WRITE_BARRIER); array->set(index, Smi::kZero, SKIP_WRITE_BARRIER);
break; break;
case FeedbackSlotKind::CREATE_CLOSURE: { case FeedbackSlotKind::CREATE_CLOSURE: {
...@@ -327,6 +330,7 @@ void FeedbackVector::ClearSlotsImpl(SharedFunctionInfo* shared, ...@@ -327,6 +330,7 @@ void FeedbackVector::ClearSlotsImpl(SharedFunctionInfo* shared,
nexus.Clear(shared->code()); nexus.Clear(shared->code());
break; break;
} }
case FeedbackSlotKind::TO_BOOLEAN_IC:
case FeedbackSlotKind::INVALID: case FeedbackSlotKind::INVALID:
case FeedbackSlotKind::KINDS_NUMBER: case FeedbackSlotKind::KINDS_NUMBER:
UNREACHABLE(); UNREACHABLE();
......
...@@ -33,6 +33,7 @@ enum class FeedbackSlotKind { ...@@ -33,6 +33,7 @@ enum class FeedbackSlotKind {
KEYED_STORE_STRICT_IC, KEYED_STORE_STRICT_IC,
INTERPRETER_BINARYOP_IC, INTERPRETER_BINARYOP_IC,
INTERPRETER_COMPARE_IC, INTERPRETER_COMPARE_IC,
TO_BOOLEAN_IC,
STORE_DATA_PROPERTY_IN_LITERAL_IC, STORE_DATA_PROPERTY_IN_LITERAL_IC,
CREATE_CLOSURE, CREATE_CLOSURE,
LITERAL, LITERAL,
......
...@@ -45,7 +45,10 @@ Code* IC::GetTargetAtAddress(Address address, Address constant_pool) { ...@@ -45,7 +45,10 @@ Code* IC::GetTargetAtAddress(Address address, Address constant_pool) {
// Convert target address to the code object. Code::GetCodeFromTargetAddress // Convert target address to the code object. Code::GetCodeFromTargetAddress
// is safe for use during GC where the map might be marked. // is safe for use during GC where the map might be marked.
Code* result = Code::GetCodeFromTargetAddress(target); Code* result = Code::GetCodeFromTargetAddress(target);
DCHECK(result->is_inline_cache_stub()); // The result can be an IC dispatcher (for vector-based ICs), an IC handler
// (for old-style patching ICs) or CEntryStub (for IC dispatchers inlined to
// bytecode handlers).
DCHECK(result->is_inline_cache_stub() || result->is_stub());
return result; return result;
} }
......
...@@ -143,7 +143,7 @@ void IC::TraceIC(const char* type, Handle<Object> name, State old_state, ...@@ -143,7 +143,7 @@ void IC::TraceIC(const char* type, Handle<Object> name, State old_state,
} }
const char* modifier = ""; const char* modifier = "";
if (kind() == Code::KEYED_STORE_IC) { if (IsKeyedStoreIC()) {
KeyedAccessStoreMode mode = KeyedAccessStoreMode mode =
casted_nexus<KeyedStoreICNexus>()->GetKeyedAccessStoreMode(); casted_nexus<KeyedStoreICNexus>()->GetKeyedAccessStoreMode();
modifier = GetTransitionMarkModifier(mode); modifier = GetTransitionMarkModifier(mode);
...@@ -196,10 +196,10 @@ void IC::TraceIC(const char* type, Handle<Object> name, State old_state, ...@@ -196,10 +196,10 @@ void IC::TraceIC(const char* type, Handle<Object> name, State old_state,
#define TRACE_IC(type, name) TraceIC(type, name) #define TRACE_IC(type, name) TraceIC(type, name)
IC::IC(FrameDepth depth, Isolate* isolate, FeedbackNexus* nexus) IC::IC(FrameDepth depth, Isolate* isolate, FeedbackNexus* nexus)
: isolate_(isolate), : isolate_(isolate),
vector_set_(false), vector_set_(false),
kind_(FeedbackSlotKind::INVALID),
target_maps_set_(false), target_maps_set_(false),
nexus_(nexus) { nexus_(nexus) {
// To improve the performance of the (much used) IC code, we unfold a few // To improve the performance of the (much used) IC code, we unfold a few
...@@ -247,11 +247,29 @@ IC::IC(FrameDepth depth, Isolate* isolate, FeedbackNexus* nexus) ...@@ -247,11 +247,29 @@ IC::IC(FrameDepth depth, Isolate* isolate, FeedbackNexus* nexus)
constant_pool_address_ = constant_pool; constant_pool_address_ = constant_pool;
} }
pc_address_ = StackFrame::ResolveReturnAddressLocation(pc_address); pc_address_ = StackFrame::ResolveReturnAddressLocation(pc_address);
Code* target = this->target(); if (nexus) {
kind_ = target->kind(); kind_ = nexus->kind();
state_ = UseVector() ? nexus->StateFromFeedback() : StateFromCode(target); DCHECK(UseVector());
state_ = nexus->StateFromFeedback();
extra_ic_state_ = kNoExtraICState;
} else {
Code* target = this->target();
Code::Kind kind = target->kind();
if (kind == Code::BINARY_OP_IC) {
kind_ = FeedbackSlotKind::INTERPRETER_BINARYOP_IC;
} else if (kind == Code::COMPARE_IC) {
kind_ = FeedbackSlotKind::INTERPRETER_COMPARE_IC;
} else if (kind == Code::TO_BOOLEAN_IC) {
kind_ = FeedbackSlotKind::TO_BOOLEAN_IC;
} else {
UNREACHABLE();
kind_ = FeedbackSlotKind::INVALID;
}
DCHECK(!UseVector());
state_ = StateFromCode(target);
extra_ic_state_ = target->extra_ic_state();
}
old_state_ = state_; old_state_ = state_;
extra_ic_state_ = target->extra_ic_state();
} }
// The ICs that don't pass slot and vector through the stack have to // The ICs that don't pass slot and vector through the stack have to
...@@ -350,7 +368,7 @@ bool IC::ShouldRecomputeHandler(Handle<String> name) { ...@@ -350,7 +368,7 @@ bool IC::ShouldRecomputeHandler(Handle<String> name) {
// This is a contextual access, always just update the handler and stay // This is a contextual access, always just update the handler and stay
// monomorphic. // monomorphic.
if (kind() == Code::LOAD_GLOBAL_IC) return true; if (IsLoadGlobalIC()) return true;
// The current map wasn't handled yet. There's no reason to stay monomorphic, // 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 // *unless* we're moving from a deprecated map to its replacement, or
...@@ -462,6 +480,7 @@ void IC::OnTypeFeedbackChanged(Isolate* isolate, Code* host) { ...@@ -462,6 +480,7 @@ void IC::OnTypeFeedbackChanged(Isolate* isolate, Code* host) {
void IC::PostPatching(Address address, Code* target, Code* old_target) { void IC::PostPatching(Address address, Code* target, Code* old_target) {
// Type vector based ICs update these statistics at a different time because // Type vector based ICs update these statistics at a different time because
// they don't always patch on state change. // they don't always patch on state change.
// TODO(ishell): DCHECK
if (ICUseVector(target->kind())) return; if (ICUseVector(target->kind())) return;
DCHECK(old_target->is_inline_cache_stub()); DCHECK(old_target->is_inline_cache_stub());
...@@ -583,13 +602,13 @@ void IC::ConfigureVectorState(IC::State new_state, Handle<Object> key) { ...@@ -583,13 +602,13 @@ void IC::ConfigureVectorState(IC::State new_state, Handle<Object> key) {
if (new_state == PREMONOMORPHIC) { if (new_state == PREMONOMORPHIC) {
nexus()->ConfigurePremonomorphic(); nexus()->ConfigurePremonomorphic();
} else if (new_state == MEGAMORPHIC) { } else if (new_state == MEGAMORPHIC) {
if (kind() == Code::LOAD_IC || kind() == Code::STORE_IC) { if (IsLoadIC() || IsStoreIC()) {
nexus()->ConfigureMegamorphic(); nexus()->ConfigureMegamorphic();
} else if (kind() == Code::KEYED_LOAD_IC) { } else if (IsKeyedLoadIC()) {
KeyedLoadICNexus* nexus = casted_nexus<KeyedLoadICNexus>(); KeyedLoadICNexus* nexus = casted_nexus<KeyedLoadICNexus>();
nexus->ConfigureMegamorphicKeyed(key->IsName() ? PROPERTY : ELEMENT); nexus->ConfigureMegamorphicKeyed(key->IsName() ? PROPERTY : ELEMENT);
} else { } else {
DCHECK(kind() == Code::KEYED_STORE_IC); DCHECK(IsKeyedStoreIC());
KeyedStoreICNexus* nexus = casted_nexus<KeyedStoreICNexus>(); KeyedStoreICNexus* nexus = casted_nexus<KeyedStoreICNexus>();
nexus->ConfigureMegamorphicKeyed(key->IsName() ? PROPERTY : ELEMENT); nexus->ConfigureMegamorphicKeyed(key->IsName() ? PROPERTY : ELEMENT);
} }
...@@ -604,20 +623,20 @@ void IC::ConfigureVectorState(IC::State new_state, Handle<Object> key) { ...@@ -604,20 +623,20 @@ void IC::ConfigureVectorState(IC::State new_state, Handle<Object> key) {
void IC::ConfigureVectorState(Handle<Name> name, Handle<Map> map, void IC::ConfigureVectorState(Handle<Name> name, Handle<Map> map,
Handle<Object> handler) { Handle<Object> handler) {
DCHECK(UseVector()); DCHECK(UseVector());
if (kind() == Code::LOAD_IC) { if (IsLoadIC()) {
LoadICNexus* nexus = casted_nexus<LoadICNexus>(); LoadICNexus* nexus = casted_nexus<LoadICNexus>();
nexus->ConfigureMonomorphic(map, handler); nexus->ConfigureMonomorphic(map, handler);
} else if (kind() == Code::LOAD_GLOBAL_IC) { } else if (IsLoadGlobalIC()) {
LoadGlobalICNexus* nexus = casted_nexus<LoadGlobalICNexus>(); LoadGlobalICNexus* nexus = casted_nexus<LoadGlobalICNexus>();
nexus->ConfigureHandlerMode(handler); nexus->ConfigureHandlerMode(handler);
} else if (kind() == Code::KEYED_LOAD_IC) { } else if (IsKeyedLoadIC()) {
KeyedLoadICNexus* nexus = casted_nexus<KeyedLoadICNexus>(); KeyedLoadICNexus* nexus = casted_nexus<KeyedLoadICNexus>();
nexus->ConfigureMonomorphic(name, map, handler); nexus->ConfigureMonomorphic(name, map, handler);
} else if (kind() == Code::STORE_IC) { } else if (IsStoreIC()) {
StoreICNexus* nexus = casted_nexus<StoreICNexus>(); StoreICNexus* nexus = casted_nexus<StoreICNexus>();
nexus->ConfigureMonomorphic(map, handler); nexus->ConfigureMonomorphic(map, handler);
} else { } else {
DCHECK(kind() == Code::KEYED_STORE_IC); DCHECK(IsKeyedStoreIC());
KeyedStoreICNexus* nexus = casted_nexus<KeyedStoreICNexus>(); KeyedStoreICNexus* nexus = casted_nexus<KeyedStoreICNexus>();
nexus->ConfigureMonomorphic(name, map, handler); nexus->ConfigureMonomorphic(name, map, handler);
} }
...@@ -629,17 +648,17 @@ void IC::ConfigureVectorState(Handle<Name> name, Handle<Map> map, ...@@ -629,17 +648,17 @@ void IC::ConfigureVectorState(Handle<Name> name, Handle<Map> map,
void IC::ConfigureVectorState(Handle<Name> name, MapHandleList* maps, void IC::ConfigureVectorState(Handle<Name> name, MapHandleList* maps,
List<Handle<Object>>* handlers) { List<Handle<Object>>* handlers) {
DCHECK(UseVector()); DCHECK(UseVector());
if (kind() == Code::LOAD_IC) { if (IsLoadIC()) {
LoadICNexus* nexus = casted_nexus<LoadICNexus>(); LoadICNexus* nexus = casted_nexus<LoadICNexus>();
nexus->ConfigurePolymorphic(maps, handlers); nexus->ConfigurePolymorphic(maps, handlers);
} else if (kind() == Code::KEYED_LOAD_IC) { } else if (IsKeyedLoadIC()) {
KeyedLoadICNexus* nexus = casted_nexus<KeyedLoadICNexus>(); KeyedLoadICNexus* nexus = casted_nexus<KeyedLoadICNexus>();
nexus->ConfigurePolymorphic(name, maps, handlers); nexus->ConfigurePolymorphic(name, maps, handlers);
} else if (kind() == Code::STORE_IC) { } else if (IsStoreIC()) {
StoreICNexus* nexus = casted_nexus<StoreICNexus>(); StoreICNexus* nexus = casted_nexus<StoreICNexus>();
nexus->ConfigurePolymorphic(maps, handlers); nexus->ConfigurePolymorphic(maps, handlers);
} else { } else {
DCHECK(kind() == Code::KEYED_STORE_IC); DCHECK(IsKeyedStoreIC());
KeyedStoreICNexus* nexus = casted_nexus<KeyedStoreICNexus>(); KeyedStoreICNexus* nexus = casted_nexus<KeyedStoreICNexus>();
nexus->ConfigurePolymorphic(name, maps, handlers); nexus->ConfigurePolymorphic(name, maps, handlers);
} }
...@@ -652,7 +671,7 @@ void IC::ConfigureVectorState(MapHandleList* maps, ...@@ -652,7 +671,7 @@ void IC::ConfigureVectorState(MapHandleList* maps,
MapHandleList* transitioned_maps, MapHandleList* transitioned_maps,
List<Handle<Object>>* handlers) { List<Handle<Object>>* handlers) {
DCHECK(UseVector()); DCHECK(UseVector());
DCHECK(kind() == Code::KEYED_STORE_IC); DCHECK(IsKeyedStoreIC());
KeyedStoreICNexus* nexus = casted_nexus<KeyedStoreICNexus>(); KeyedStoreICNexus* nexus = casted_nexus<KeyedStoreICNexus>();
nexus->ConfigurePolymorphic(maps, transitioned_maps, handlers); nexus->ConfigurePolymorphic(maps, transitioned_maps, handlers);
...@@ -843,12 +862,8 @@ bool IC::IsTransitionOfMonomorphicTarget(Map* source_map, Map* target_map) { ...@@ -843,12 +862,8 @@ bool IC::IsTransitionOfMonomorphicTarget(Map* source_map, Map* target_map) {
void IC::PatchCache(Handle<Name> name, Handle<Object> handler) { void IC::PatchCache(Handle<Name> name, Handle<Object> handler) {
DCHECK(IsHandler(*handler)); DCHECK(IsHandler(*handler));
// Currently only LoadIC and KeyedLoadIC support non-code handlers. // Currently only load and store ICs support non-code handlers.
DCHECK_IMPLIES(!handler->IsCode(), kind() == Code::LOAD_IC || DCHECK_IMPLIES(!handler->IsCode(), IsAnyLoad() || IsAnyStore());
kind() == Code::LOAD_GLOBAL_IC ||
kind() == Code::KEYED_LOAD_IC ||
kind() == Code::STORE_IC ||
kind() == Code::KEYED_STORE_IC);
switch (state()) { switch (state()) {
case UNINITIALIZED: case UNINITIALIZED:
case PREMONOMORPHIC: case PREMONOMORPHIC:
...@@ -856,7 +871,7 @@ void IC::PatchCache(Handle<Name> name, Handle<Object> handler) { ...@@ -856,7 +871,7 @@ void IC::PatchCache(Handle<Name> name, Handle<Object> handler) {
break; break;
case RECOMPUTE_HANDLER: case RECOMPUTE_HANDLER:
case MONOMORPHIC: case MONOMORPHIC:
if (kind() == Code::LOAD_GLOBAL_IC) { if (IsLoadGlobalIC()) {
UpdateMonomorphicIC(handler, name); UpdateMonomorphicIC(handler, name);
break; break;
} }
...@@ -1101,7 +1116,7 @@ bool IsCompatibleReceiver(LookupIterator* lookup, Handle<Map> receiver_map) { ...@@ -1101,7 +1116,7 @@ bool IsCompatibleReceiver(LookupIterator* lookup, Handle<Map> receiver_map) {
void LoadIC::UpdateCaches(LookupIterator* lookup) { void LoadIC::UpdateCaches(LookupIterator* lookup) {
if (state() == UNINITIALIZED && kind() != Code::LOAD_GLOBAL_IC) { if (state() == UNINITIALIZED && !IsLoadGlobalIC()) {
// This is the first time we execute this inline cache. Set the target to // This is the first time we execute this inline cache. Set the target to
// the pre monomorphic stub to delay setting the monomorphic state. // the pre monomorphic stub to delay setting the monomorphic state.
TRACE_HANDLER_STATS(isolate(), LoadIC_Premonomorphic); TRACE_HANDLER_STATS(isolate(), LoadIC_Premonomorphic);
...@@ -1115,15 +1130,14 @@ void LoadIC::UpdateCaches(LookupIterator* lookup) { ...@@ -1115,15 +1130,14 @@ void LoadIC::UpdateCaches(LookupIterator* lookup) {
lookup->state() == LookupIterator::ACCESS_CHECK) { lookup->state() == LookupIterator::ACCESS_CHECK) {
code = slow_stub(); code = slow_stub();
} else if (!lookup->IsFound()) { } else if (!lookup->IsFound()) {
if (kind() == Code::LOAD_IC || kind() == Code::LOAD_GLOBAL_IC) { if (IsLoadIC() || IsLoadGlobalIC()) {
TRACE_HANDLER_STATS(isolate(), LoadIC_LoadNonexistentDH); TRACE_HANDLER_STATS(isolate(), LoadIC_LoadNonexistentDH);
code = LoadNonExistent(receiver_map(), lookup->name()); code = LoadNonExistent(receiver_map(), lookup->name());
} else { } else {
code = slow_stub(); code = slow_stub();
} }
} else { } else {
if (kind() == Code::LOAD_GLOBAL_IC && if (IsLoadGlobalIC() && lookup->state() == LookupIterator::DATA &&
lookup->state() == LookupIterator::DATA &&
lookup->GetReceiver().is_identical_to(lookup->GetHolder<Object>())) { lookup->GetReceiver().is_identical_to(lookup->GetHolder<Object>())) {
DCHECK(lookup->GetReceiver()->IsJSGlobalObject()); DCHECK(lookup->GetReceiver()->IsJSGlobalObject());
// Now update the cell in the feedback vector. // Now update the cell in the feedback vector.
...@@ -1156,20 +1170,12 @@ void LoadIC::UpdateCaches(LookupIterator* lookup) { ...@@ -1156,20 +1170,12 @@ void LoadIC::UpdateCaches(LookupIterator* lookup) {
} }
StubCache* IC::stub_cache() { StubCache* IC::stub_cache() {
switch (kind()) { if (IsAnyLoad()) {
case Code::LOAD_IC: return isolate()->load_stub_cache();
case Code::KEYED_LOAD_IC: } else {
return isolate()->load_stub_cache(); DCHECK(IsAnyStore());
return isolate()->store_stub_cache();
case Code::STORE_IC:
case Code::KEYED_STORE_IC:
return isolate()->store_stub_cache();
default:
break;
} }
UNREACHABLE();
return nullptr;
} }
void IC::UpdateMegamorphicCache(Map* map, Name* name, Object* handler) { void IC::UpdateMegamorphicCache(Map* map, Name* name, Object* handler) {
...@@ -1179,8 +1185,7 @@ void IC::UpdateMegamorphicCache(Map* map, Name* name, Object* handler) { ...@@ -1179,8 +1185,7 @@ void IC::UpdateMegamorphicCache(Map* map, Name* name, Object* handler) {
void IC::TraceHandlerCacheHitStats(LookupIterator* lookup) { void IC::TraceHandlerCacheHitStats(LookupIterator* lookup) {
if (!FLAG_runtime_call_stats) return; if (!FLAG_runtime_call_stats) return;
if (kind() == Code::LOAD_IC || kind() == Code::LOAD_GLOBAL_IC || if (IsAnyLoad()) {
kind() == Code::KEYED_LOAD_IC) {
switch (lookup->state()) { switch (lookup->state()) {
case LookupIterator::ACCESS_CHECK: case LookupIterator::ACCESS_CHECK:
TRACE_HANDLER_STATS(isolate(), LoadIC_HandlerCacheHit_AccessCheck); TRACE_HANDLER_STATS(isolate(), LoadIC_HandlerCacheHit_AccessCheck);
...@@ -1207,7 +1212,7 @@ void IC::TraceHandlerCacheHitStats(LookupIterator* lookup) { ...@@ -1207,7 +1212,7 @@ void IC::TraceHandlerCacheHitStats(LookupIterator* lookup) {
TRACE_HANDLER_STATS(isolate(), LoadIC_HandlerCacheHit_Transition); TRACE_HANDLER_STATS(isolate(), LoadIC_HandlerCacheHit_Transition);
break; break;
} }
} else if (kind() == Code::STORE_IC || kind() == Code::KEYED_STORE_IC) { } else if (IsAnyStore()) {
switch (lookup->state()) { switch (lookup->state()) {
case LookupIterator::ACCESS_CHECK: case LookupIterator::ACCESS_CHECK:
TRACE_HANDLER_STATS(isolate(), StoreIC_HandlerCacheHit_AccessCheck); TRACE_HANDLER_STATS(isolate(), StoreIC_HandlerCacheHit_AccessCheck);
...@@ -1254,19 +1259,18 @@ Handle<Object> IC::ComputeHandler(LookupIterator* lookup, ...@@ -1254,19 +1259,18 @@ Handle<Object> IC::ComputeHandler(LookupIterator* lookup,
lookup->GetReceiver().is_identical_to(lookup->GetHolder<JSObject>()); lookup->GetReceiver().is_identical_to(lookup->GetHolder<JSObject>());
CacheHolderFlag flag; CacheHolderFlag flag;
Handle<Map> stub_holder_map; Handle<Map> stub_holder_map;
if (kind() == Code::LOAD_IC || kind() == Code::LOAD_GLOBAL_IC || if (IsAnyLoad()) {
kind() == Code::KEYED_LOAD_IC) {
stub_holder_map = IC::GetHandlerCacheHolder( stub_holder_map = IC::GetHandlerCacheHolder(
receiver_map(), receiver_is_holder, isolate(), &flag); receiver_map(), receiver_is_holder, isolate(), &flag);
} else { } else {
DCHECK(kind() == Code::STORE_IC || kind() == Code::KEYED_STORE_IC); DCHECK(IsAnyStore());
// Store handlers cannot be cached on prototypes. // Store handlers cannot be cached on prototypes.
flag = kCacheOnReceiver; flag = kCacheOnReceiver;
stub_holder_map = receiver_map(); stub_holder_map = receiver_map();
} }
Handle<Object> handler = PropertyHandlerCompiler::Find( Handle<Object> handler = PropertyHandlerCompiler::Find(
lookup->name(), stub_holder_map, kind(), flag); lookup->name(), stub_holder_map, handler_kind(), flag);
// Use the cached value if it exists, and if it is different from the // Use the cached value if it exists, and if it is different from the
// handler that just missed. // handler that just missed.
if (!handler.is_null()) { if (!handler.is_null()) {
...@@ -1384,7 +1388,7 @@ Handle<Object> LoadIC::GetMapIndependentHandler(LookupIterator* lookup) { ...@@ -1384,7 +1388,7 @@ Handle<Object> LoadIC::GetMapIndependentHandler(LookupIterator* lookup) {
TRACE_HANDLER_STATS(isolate(), LoadIC_LoadApiGetterDH); TRACE_HANDLER_STATS(isolate(), LoadIC_LoadApiGetterDH);
return smi_handler; return smi_handler;
} }
if (kind() != Code::LOAD_GLOBAL_IC) { if (!IsLoadGlobalIC()) {
TRACE_HANDLER_STATS(isolate(), LoadIC_LoadApiGetterFromPrototypeDH); TRACE_HANDLER_STATS(isolate(), LoadIC_LoadApiGetterFromPrototypeDH);
return LoadFromPrototype(map, holder, lookup->name(), smi_handler); return LoadFromPrototype(map, holder, lookup->name(), smi_handler);
} }
...@@ -1398,7 +1402,7 @@ Handle<Object> LoadIC::GetMapIndependentHandler(LookupIterator* lookup) { ...@@ -1398,7 +1402,7 @@ Handle<Object> LoadIC::GetMapIndependentHandler(LookupIterator* lookup) {
case LookupIterator::DATA: { case LookupIterator::DATA: {
DCHECK_EQ(kData, lookup->property_details().kind()); DCHECK_EQ(kData, lookup->property_details().kind());
if (lookup->is_dictionary_holder()) { if (lookup->is_dictionary_holder()) {
if (kind() != Code::LOAD_IC && kind() != Code::LOAD_GLOBAL_IC) { if (!IsLoadIC() && !IsLoadGlobalIC()) { // IsKeyedLoadIC()?
TRACE_HANDLER_STATS(isolate(), LoadIC_SlowStub); TRACE_HANDLER_STATS(isolate(), LoadIC_SlowStub);
return slow_stub(); return slow_stub();
} }
...@@ -1542,7 +1546,7 @@ Handle<Object> LoadIC::CompileHandler(LookupIterator* lookup, ...@@ -1542,7 +1546,7 @@ Handle<Object> LoadIC::CompileHandler(LookupIterator* lookup,
case LookupIterator::DATA: { case LookupIterator::DATA: {
DCHECK(lookup->is_dictionary_holder()); DCHECK(lookup->is_dictionary_holder());
DCHECK(kind() == Code::LOAD_IC || kind() == Code::LOAD_GLOBAL_IC); DCHECK(IsLoadIC() || IsLoadGlobalIC());
DCHECK(holder->IsJSGlobalObject()); DCHECK(holder->IsJSGlobalObject());
TRACE_HANDLER_STATS(isolate(), LoadIC_LoadGlobal); TRACE_HANDLER_STATS(isolate(), LoadIC_LoadGlobal);
NamedLoadHandlerCompiler compiler(isolate(), map, holder, cache_holder); NamedLoadHandlerCompiler compiler(isolate(), map, holder, cache_holder);
......
...@@ -45,15 +45,10 @@ class IC { ...@@ -45,15 +45,10 @@ class IC {
// Clear the inline cache to initial state. // Clear the inline cache to initial state.
static void Clear(Isolate* isolate, Address address, Address constant_pool); static void Clear(Isolate* isolate, Address address, Address constant_pool);
#ifdef DEBUG bool IsAnyLoad() const {
bool IsLoadStub() const { return IsLoadIC() || IsLoadGlobalIC() || IsKeyedLoadIC();
return kind_ == Code::LOAD_IC || kind_ == Code::LOAD_GLOBAL_IC ||
kind_ == Code::KEYED_LOAD_IC;
} }
bool IsStoreStub() const { bool IsAnyStore() const { return IsStoreIC() || IsKeyedStoreIC(); }
return kind_ == Code::STORE_IC || kind_ == Code::KEYED_STORE_IC;
}
#endif
static inline Handle<Map> GetHandlerCacheHolder(Handle<Map> receiver_map, static inline Handle<Map> GetHandlerCacheHolder(Handle<Map> receiver_map,
bool receiver_is_holder, bool receiver_is_holder,
...@@ -73,6 +68,11 @@ class IC { ...@@ -73,6 +68,11 @@ class IC {
kind == Code::KEYED_LOAD_IC || kind == Code::STORE_IC || kind == Code::KEYED_LOAD_IC || kind == Code::STORE_IC ||
kind == Code::KEYED_STORE_IC; kind == Code::KEYED_STORE_IC;
} }
static bool ICUseVector(FeedbackSlotKind kind) {
return IsLoadICKind(kind) || IsLoadGlobalICKind(kind) ||
IsKeyedLoadICKind(kind) || IsStoreICKind(kind) ||
IsKeyedStoreICKind(kind);
}
// The ICs that don't pass slot and vector through the stack have to // The ICs that don't pass slot and vector through the stack have to
// save/restore them in the dispatcher. // save/restore them in the dispatcher.
...@@ -164,15 +164,17 @@ class IC { ...@@ -164,15 +164,17 @@ class IC {
void CopyICToMegamorphicCache(Handle<Name> name); void CopyICToMegamorphicCache(Handle<Name> name);
bool IsTransitionOfMonomorphicTarget(Map* source_map, Map* target_map); bool IsTransitionOfMonomorphicTarget(Map* source_map, Map* target_map);
void PatchCache(Handle<Name> name, Handle<Object> code); void PatchCache(Handle<Name> name, Handle<Object> code);
Code::Kind kind() const { return kind_; } FeedbackSlotKind kind() const { return kind_; }
bool is_keyed() const { bool IsLoadIC() const { return IsLoadICKind(kind_); }
return kind_ == Code::KEYED_LOAD_IC || kind_ == Code::KEYED_STORE_IC; bool IsLoadGlobalIC() const { return IsLoadGlobalICKind(kind_); }
} bool IsKeyedLoadIC() const { return IsKeyedLoadICKind(kind_); }
bool IsStoreIC() const { return IsStoreICKind(kind_); }
bool IsKeyedStoreIC() const { return IsKeyedStoreICKind(kind_); }
bool is_keyed() const { return IsKeyedLoadIC() || IsKeyedStoreIC(); }
Code::Kind handler_kind() const { Code::Kind handler_kind() const {
if (kind_ == Code::KEYED_LOAD_IC) return Code::LOAD_IC; if (IsAnyLoad()) return Code::LOAD_IC;
DCHECK(kind_ == Code::LOAD_IC || kind_ == Code::STORE_IC || DCHECK(IsAnyStore());
kind_ == Code::KEYED_STORE_IC); return Code::STORE_IC;
return kind_;
} }
bool ShouldRecomputeHandler(Handle<String> name); bool ShouldRecomputeHandler(Handle<String> name);
...@@ -243,7 +245,7 @@ class IC { ...@@ -243,7 +245,7 @@ class IC {
bool vector_set_; bool vector_set_;
State old_state_; // For saving if we marked as prototype failure. State old_state_; // For saving if we marked as prototype failure.
State state_; State state_;
Code::Kind kind_; FeedbackSlotKind kind_;
Handle<Map> receiver_map_; Handle<Map> receiver_map_;
MaybeHandle<Object> maybe_handler_; MaybeHandle<Object> maybe_handler_;
...@@ -273,7 +275,7 @@ class LoadIC : public IC { ...@@ -273,7 +275,7 @@ class LoadIC : public IC {
LoadIC(FrameDepth depth, Isolate* isolate, FeedbackNexus* nexus = NULL) LoadIC(FrameDepth depth, Isolate* isolate, FeedbackNexus* nexus = NULL)
: IC(depth, isolate, nexus) { : IC(depth, isolate, nexus) {
DCHECK(nexus != NULL); DCHECK(nexus != NULL);
DCHECK(IsLoadStub()); DCHECK(IsAnyLoad());
} }
static bool ShouldThrowReferenceError(FeedbackSlotKind kind) { static bool ShouldThrowReferenceError(FeedbackSlotKind kind) {
...@@ -281,8 +283,7 @@ class LoadIC : public IC { ...@@ -281,8 +283,7 @@ class LoadIC : public IC {
} }
bool ShouldThrowReferenceError() const { bool ShouldThrowReferenceError() const {
return UseVector() && ShouldThrowReferenceError( return ShouldThrowReferenceError(kind());
nexus()->vector()->GetKind(nexus()->slot()));
} }
MUST_USE_RESULT MaybeHandle<Object> Load(Handle<Object> object, MUST_USE_RESULT MaybeHandle<Object> Load(Handle<Object> object,
...@@ -363,7 +364,7 @@ class StoreIC : public IC { ...@@ -363,7 +364,7 @@ class StoreIC : public IC {
public: public:
StoreIC(FrameDepth depth, Isolate* isolate, FeedbackNexus* nexus = NULL) StoreIC(FrameDepth depth, Isolate* isolate, FeedbackNexus* nexus = NULL)
: IC(depth, isolate, nexus) { : IC(depth, isolate, nexus) {
DCHECK(IsStoreStub()); DCHECK(IsAnyStore());
} }
LanguageMode language_mode() const { LanguageMode language_mode() const {
......
...@@ -4982,7 +4982,8 @@ bool Code::IsCodeStubOrIC() { ...@@ -4982,7 +4982,8 @@ bool Code::IsCodeStubOrIC() {
} }
ExtraICState Code::extra_ic_state() { ExtraICState Code::extra_ic_state() {
DCHECK(is_inline_cache_stub() || is_debug_stub()); DCHECK(is_binary_op_stub() || is_compare_ic_stub() ||
is_to_boolean_ic_stub() || is_debug_stub());
return ExtractExtraICStateFromFlags(flags()); return ExtractExtraICStateFromFlags(flags());
} }
...@@ -5279,6 +5280,7 @@ bool Code::is_debug_stub() { ...@@ -5279,6 +5280,7 @@ bool Code::is_debug_stub() {
return false; return false;
} }
bool Code::is_handler() { return kind() == HANDLER; } bool Code::is_handler() { return kind() == HANDLER; }
bool Code::is_stub() { return kind() == STUB; }
bool Code::is_binary_op_stub() { return kind() == BINARY_OP_IC; } bool Code::is_binary_op_stub() { return kind() == BINARY_OP_IC; }
bool Code::is_compare_ic_stub() { return kind() == COMPARE_IC; } bool Code::is_compare_ic_stub() { return kind() == COMPARE_IC; }
bool Code::is_to_boolean_ic_stub() { return kind() == TO_BOOLEAN_IC; } bool Code::is_to_boolean_ic_stub() { return kind() == TO_BOOLEAN_IC; }
......
...@@ -804,6 +804,7 @@ void FeedbackVector::FeedbackVectorPrint(std::ostream& os) { // NOLINT ...@@ -804,6 +804,7 @@ void FeedbackVector::FeedbackVectorPrint(std::ostream& os) { // NOLINT
case FeedbackSlotKind::LITERAL: case FeedbackSlotKind::LITERAL:
case FeedbackSlotKind::GENERAL: case FeedbackSlotKind::GENERAL:
break; break;
case FeedbackSlotKind::TO_BOOLEAN_IC:
case FeedbackSlotKind::INVALID: case FeedbackSlotKind::INVALID:
case FeedbackSlotKind::KINDS_NUMBER: case FeedbackSlotKind::KINDS_NUMBER:
UNREACHABLE(); UNREACHABLE();
......
...@@ -5059,6 +5059,7 @@ class Code: public HeapObject { ...@@ -5059,6 +5059,7 @@ class Code: public HeapObject {
inline bool is_inline_cache_stub(); inline bool is_inline_cache_stub();
inline bool is_debug_stub(); inline bool is_debug_stub();
inline bool is_handler(); inline bool is_handler();
inline bool is_stub();
inline bool is_binary_op_stub(); inline bool is_binary_op_stub();
inline bool is_compare_ic_stub(); inline bool is_compare_ic_stub();
inline bool is_to_boolean_ic_stub(); inline bool is_to_boolean_ic_stub();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment