[runtime] Refine runtime call stats for IC misses.
Now we are able to distinguish different kind of misses based on which handler/stub did we actually use. Review-Url: https://codereview.chromium.org/1969733002 Cr-Commit-Position: refs/heads/master@{#36175}
This commit is contained in:
parent
bf90d9a33a
commit
61b49b3c09
@ -288,6 +288,15 @@ void RuntimeCallStats::Leave(Isolate* isolate, RuntimeCallTimer* timer) {
|
||||
stats->current_timer_ = timer->Stop();
|
||||
}
|
||||
|
||||
// static
|
||||
void RuntimeCallStats::CorrectCurrentCounterId(Isolate* isolate,
|
||||
CounterId counter_id) {
|
||||
RuntimeCallStats* stats = isolate->counters()->runtime_call_stats();
|
||||
DCHECK_NOT_NULL(stats->current_timer_);
|
||||
RuntimeCallCounter* counter = &(stats->*counter_id);
|
||||
stats->current_timer_->counter_ = counter;
|
||||
}
|
||||
|
||||
void RuntimeCallStats::Print(std::ostream& os) {
|
||||
RuntimeCallStatEntries entries;
|
||||
|
||||
@ -299,6 +308,10 @@ void RuntimeCallStats::Print(std::ostream& os) {
|
||||
BUILTIN_LIST_C(PRINT_COUNTER)
|
||||
#undef PRINT_COUNTER
|
||||
|
||||
#define PRINT_COUNTER(name) entries.Add(&this->Handler_##name);
|
||||
FOR_EACH_HANDLER_COUNTER(PRINT_COUNTER)
|
||||
#undef PRINT_COUNTER
|
||||
|
||||
entries.Add(&this->ExternalCallback);
|
||||
entries.Add(&this->GC);
|
||||
entries.Add(&this->UnexpectedStubMiss);
|
||||
|
@ -501,12 +501,12 @@ class RuntimeCallTimer {
|
||||
counter_ = counter;
|
||||
parent_ = parent;
|
||||
timer_.Start();
|
||||
counter_->count++;
|
||||
}
|
||||
|
||||
inline RuntimeCallTimer* Stop() {
|
||||
base::TimeDelta delta = timer_.Elapsed();
|
||||
timer_.Stop();
|
||||
counter_->count++;
|
||||
counter_->time += delta;
|
||||
if (parent_ != NULL) {
|
||||
// Adjust parent timer so that it does not include sub timer's time.
|
||||
@ -520,6 +520,46 @@ class RuntimeCallTimer {
|
||||
base::ElapsedTimer timer_;
|
||||
};
|
||||
|
||||
#define FOR_EACH_HANDLER_COUNTER(V) \
|
||||
V(IC_HandlerCacheHit) \
|
||||
V(KeyedLoadIC_LoadIndexedStringStub) \
|
||||
V(KeyedLoadIC_LoadIndexedInterceptorStub) \
|
||||
V(KeyedLoadIC_KeyedLoadSloppyArgumentsStub) \
|
||||
V(KeyedLoadIC_LoadFastElementStub) \
|
||||
V(KeyedLoadIC_LoadDictionaryElementStub) \
|
||||
V(KeyedLoadIC_PolymorphicElement) \
|
||||
V(KeyedStoreIC_KeyedStoreSloppyArgumentsStub) \
|
||||
V(KeyedStoreIC_StoreFastElementStub) \
|
||||
V(KeyedStoreIC_StoreElementStub) \
|
||||
V(KeyedStoreIC_Polymorphic) \
|
||||
V(LoadIC_FunctionPrototypeStub) \
|
||||
V(LoadIC_ArrayBufferViewLoadFieldStub) \
|
||||
V(LoadIC_LoadApiGetterStub) \
|
||||
V(LoadIC_LoadCallback) \
|
||||
V(LoadIC_LoadConstant) \
|
||||
V(LoadIC_LoadConstantStub) \
|
||||
V(LoadIC_LoadField) \
|
||||
V(LoadIC_LoadFieldStub) \
|
||||
V(LoadIC_LoadGlobal) \
|
||||
V(LoadIC_LoadInterceptor) \
|
||||
V(LoadIC_LoadNonexistent) \
|
||||
V(LoadIC_LoadNormal) \
|
||||
V(LoadIC_LoadScriptContextFieldStub) \
|
||||
V(LoadIC_LoadViaGetter) \
|
||||
V(LoadIC_SlowStub) \
|
||||
V(LoadIC_StringLengthStub) \
|
||||
V(StoreIC_SlowStub) \
|
||||
V(StoreIC_StoreCallback) \
|
||||
V(StoreIC_StoreField) \
|
||||
V(StoreIC_StoreFieldStub) \
|
||||
V(StoreIC_StoreGlobal) \
|
||||
V(StoreIC_StoreGlobalTransition) \
|
||||
V(StoreIC_StoreInterceptorStub) \
|
||||
V(StoreIC_StoreNormal) \
|
||||
V(StoreIC_StoreScriptContextFieldStub) \
|
||||
V(StoreIC_StoreTransition) \
|
||||
V(StoreIC_StoreViaSetter)
|
||||
|
||||
class RuntimeCallStats {
|
||||
public:
|
||||
typedef RuntimeCallCounter RuntimeCallStats::*CounterId;
|
||||
@ -538,6 +578,10 @@ class RuntimeCallStats {
|
||||
RuntimeCallCounter Builtin_##name = RuntimeCallCounter(#name);
|
||||
BUILTIN_LIST_C(CALL_BUILTIN_COUNTER)
|
||||
#undef CALL_BUILTIN_COUNTER
|
||||
#define CALL_BUILTIN_COUNTER(name) \
|
||||
RuntimeCallCounter Handler_##name = RuntimeCallCounter(#name);
|
||||
FOR_EACH_HANDLER_COUNTER(CALL_BUILTIN_COUNTER)
|
||||
#undef CALL_BUILTIN_COUNTER
|
||||
|
||||
// Starting measuring the time for a function. This will establish the
|
||||
// connection to the parent counter for properly calculating the own times.
|
||||
@ -549,6 +593,10 @@ class RuntimeCallStats {
|
||||
// parent.
|
||||
static void Leave(Isolate* isolate, RuntimeCallTimer* timer);
|
||||
|
||||
// Set counter id for the innermost measurement. It can be used to refine
|
||||
// event kind when a runtime entry counter is too generic.
|
||||
static void CorrectCurrentCounterId(Isolate* isolate, CounterId counter_id);
|
||||
|
||||
void Reset();
|
||||
void Print(std::ostream& os);
|
||||
|
||||
@ -559,6 +607,17 @@ class RuntimeCallStats {
|
||||
RuntimeCallTimer* current_timer_ = NULL;
|
||||
};
|
||||
|
||||
#define TRACE_RUNTIME_CALL_STATS(isolate, counter_name) \
|
||||
do { \
|
||||
if (FLAG_runtime_call_stats) { \
|
||||
RuntimeCallStats::CorrectCurrentCounterId( \
|
||||
isolate, &RuntimeCallStats::counter_name); \
|
||||
} \
|
||||
} while (false)
|
||||
|
||||
#define TRACE_HANDLER_STATS(isolate, counter_name) \
|
||||
TRACE_RUNTIME_CALL_STATS(isolate, Handler_##counter_name)
|
||||
|
||||
// A RuntimeCallTimerScopes wraps around a RuntimeCallTimer to measure the
|
||||
// the time of C++ scope.
|
||||
class RuntimeCallTimerScope {
|
||||
|
@ -67,6 +67,7 @@ Handle<Code> NamedLoadHandlerCompiler::ComputeLoadNonexistent(
|
||||
cache_name, stub_holder_map, Code::LOAD_IC, flag);
|
||||
if (!handler.is_null()) return handler;
|
||||
|
||||
TRACE_HANDLER_STATS(isolate, LoadIC_LoadNonexistent);
|
||||
NamedLoadHandlerCompiler compiler(isolate, receiver_map, last, flag);
|
||||
handler = compiler.CompileLoadNonexistent(cache_name);
|
||||
Map::UpdateCodeCache(stub_holder_map, cache_name, handler);
|
||||
|
@ -26,17 +26,22 @@ Handle<Code> PropertyICCompiler::ComputeKeyedLoadMonomorphicHandler(
|
||||
*receiver_map == isolate->get_initial_js_array_map(elements_kind);
|
||||
Handle<Code> stub;
|
||||
if (receiver_map->has_indexed_interceptor()) {
|
||||
TRACE_HANDLER_STATS(isolate, KeyedLoadIC_LoadIndexedInterceptorStub);
|
||||
stub = LoadIndexedInterceptorStub(isolate).GetCode();
|
||||
} else if (receiver_map->IsStringMap()) {
|
||||
TRACE_HANDLER_STATS(isolate, KeyedLoadIC_LoadIndexedStringStub);
|
||||
stub = LoadIndexedStringStub(isolate).GetCode();
|
||||
} else if (receiver_map->has_sloppy_arguments_elements()) {
|
||||
TRACE_HANDLER_STATS(isolate, KeyedLoadIC_KeyedLoadSloppyArgumentsStub);
|
||||
stub = KeyedLoadSloppyArgumentsStub(isolate).GetCode();
|
||||
} else if (receiver_map->has_fast_elements() ||
|
||||
receiver_map->has_fixed_typed_array_elements()) {
|
||||
TRACE_HANDLER_STATS(isolate, KeyedLoadIC_LoadFastElementStub);
|
||||
stub = LoadFastElementStub(isolate, is_js_array, elements_kind,
|
||||
convert_hole_to_undefined).GetCode();
|
||||
} else {
|
||||
DCHECK(receiver_map->has_dictionary_elements());
|
||||
TRACE_HANDLER_STATS(isolate, KeyedLoadIC_LoadDictionaryElementStub);
|
||||
stub = LoadDictionaryElementStub(isolate, LoadICState(extra_ic_state))
|
||||
.GetCode();
|
||||
}
|
||||
@ -126,12 +131,15 @@ Handle<Code> PropertyICCompiler::CompileKeyedStoreMonomorphicHandler(
|
||||
bool is_jsarray = receiver_map->instance_type() == JS_ARRAY_TYPE;
|
||||
Handle<Code> stub;
|
||||
if (receiver_map->has_sloppy_arguments_elements()) {
|
||||
TRACE_HANDLER_STATS(isolate(), KeyedStoreIC_KeyedStoreSloppyArgumentsStub);
|
||||
stub = KeyedStoreSloppyArgumentsStub(isolate(), store_mode).GetCode();
|
||||
} else if (receiver_map->has_fast_elements() ||
|
||||
receiver_map->has_fixed_typed_array_elements()) {
|
||||
TRACE_HANDLER_STATS(isolate(), KeyedStoreIC_StoreFastElementStub);
|
||||
stub = StoreFastElementStub(isolate(), is_jsarray, elements_kind,
|
||||
store_mode).GetCode();
|
||||
} else {
|
||||
TRACE_HANDLER_STATS(isolate(), KeyedStoreIC_StoreElementStub);
|
||||
stub = StoreElementStub(isolate(), elements_kind, store_mode).GetCode();
|
||||
}
|
||||
return stub;
|
||||
|
43
src/ic/ic.cc
43
src/ic/ic.cc
@ -631,6 +631,7 @@ MaybeHandle<Object> LoadIC::Load(Handle<Object> object, Handle<Name> name) {
|
||||
}
|
||||
|
||||
if (use_ic && LoadScriptContextFieldStub::Accepted(&lookup_result)) {
|
||||
TRACE_HANDLER_STATS(isolate(), LoadIC_LoadScriptContextFieldStub);
|
||||
LoadScriptContextFieldStub stub(isolate(), &lookup_result);
|
||||
PatchCache(name, stub.GetCode());
|
||||
}
|
||||
@ -835,6 +836,7 @@ Handle<Code> KeyedStoreIC::ChooseMegamorphicStub(Isolate* isolate,
|
||||
|
||||
|
||||
Handle<Code> LoadIC::SimpleFieldLoad(FieldIndex index) {
|
||||
TRACE_HANDLER_STATS(isolate(), LoadIC_LoadFieldStub);
|
||||
LoadFieldStub stub(isolate(), index);
|
||||
return stub.GetCode();
|
||||
}
|
||||
@ -946,7 +948,10 @@ Handle<Code> IC::ComputeHandler(LookupIterator* lookup, Handle<Object> value) {
|
||||
if (!code.is_null()) {
|
||||
Handle<Code> handler;
|
||||
if (maybe_handler_.ToHandle(&handler)) {
|
||||
if (!handler.is_identical_to(code)) return code;
|
||||
if (!handler.is_identical_to(code)) {
|
||||
TRACE_HANDLER_STATS(isolate(), IC_HandlerCacheHit);
|
||||
return code;
|
||||
}
|
||||
} else {
|
||||
// maybe_handler_ is only populated for MONOMORPHIC and POLYMORPHIC ICs.
|
||||
// In MEGAMORPHIC case, check if the handler in the megamorphic stub
|
||||
@ -955,8 +960,12 @@ Handle<Code> IC::ComputeHandler(LookupIterator* lookup, Handle<Object> value) {
|
||||
Map* map = Handle<HeapObject>::cast(lookup->GetReceiver())->map();
|
||||
Code* megamorphic_cached_code =
|
||||
isolate()->stub_cache()->Get(*lookup->name(), map, code->flags());
|
||||
if (megamorphic_cached_code != *code) return code;
|
||||
if (megamorphic_cached_code != *code) {
|
||||
TRACE_HANDLER_STATS(isolate(), IC_HandlerCacheHit);
|
||||
return code;
|
||||
}
|
||||
} else {
|
||||
TRACE_HANDLER_STATS(isolate(), IC_HandlerCacheHit);
|
||||
return code;
|
||||
}
|
||||
}
|
||||
@ -992,6 +1001,7 @@ Handle<Code> LoadIC::CompileHandler(LookupIterator* lookup,
|
||||
|
||||
if (receiver->IsStringWrapper() &&
|
||||
Name::Equals(isolate()->factory()->length_string(), lookup->name())) {
|
||||
TRACE_HANDLER_STATS(isolate(), LoadIC_StringLengthStub);
|
||||
StringLengthStub string_length_stub(isolate());
|
||||
return string_length_stub.GetCode();
|
||||
}
|
||||
@ -1004,6 +1014,7 @@ Handle<Code> LoadIC::CompileHandler(LookupIterator* lookup,
|
||||
->map()
|
||||
->has_non_instance_prototype()) {
|
||||
Handle<Code> stub;
|
||||
TRACE_HANDLER_STATS(isolate(), LoadIC_FunctionPrototypeStub);
|
||||
FunctionPrototypeStub function_prototype_stub(isolate());
|
||||
return function_prototype_stub.GetCode();
|
||||
}
|
||||
@ -1014,6 +1025,7 @@ Handle<Code> LoadIC::CompileHandler(LookupIterator* lookup,
|
||||
switch (lookup->state()) {
|
||||
case LookupIterator::INTERCEPTOR: {
|
||||
DCHECK(!holder->GetNamedInterceptor()->getter()->IsUndefined());
|
||||
TRACE_HANDLER_STATS(isolate(), LoadIC_LoadInterceptor);
|
||||
NamedLoadHandlerCompiler compiler(isolate(), map, holder, cache_holder);
|
||||
// Perform a lookup behind the interceptor. Copy the LookupIterator since
|
||||
// the original iterator will be used to fetch the value.
|
||||
@ -1035,6 +1047,7 @@ Handle<Code> LoadIC::CompileHandler(LookupIterator* lookup,
|
||||
}
|
||||
if (Accessors::IsJSArrayBufferViewFieldAccessor(map, lookup->name(),
|
||||
&object_offset)) {
|
||||
TRACE_HANDLER_STATS(isolate(), LoadIC_ArrayBufferViewLoadFieldStub);
|
||||
FieldIndex index = FieldIndex::ForInObjectOffset(object_offset, *map);
|
||||
ArrayBufferViewLoadFieldStub stub(isolate(), index);
|
||||
return stub.GetCode();
|
||||
@ -1052,10 +1065,12 @@ Handle<Code> LoadIC::CompileHandler(LookupIterator* lookup,
|
||||
NamedLoadHandlerCompiler compiler(isolate(), map, holder,
|
||||
cache_holder);
|
||||
if (call_optimization.is_simple_api_call()) {
|
||||
TRACE_HANDLER_STATS(isolate(), LoadIC_LoadCallback);
|
||||
int index = lookup->GetAccessorIndex();
|
||||
return compiler.CompileLoadCallback(lookup->name(),
|
||||
call_optimization, index);
|
||||
}
|
||||
TRACE_HANDLER_STATS(isolate(), LoadIC_LoadViaGetter);
|
||||
int expected_arguments = Handle<JSFunction>::cast(getter)
|
||||
->shared()
|
||||
->internal_formal_parameter_count();
|
||||
@ -1071,11 +1086,13 @@ Handle<Code> LoadIC::CompileHandler(LookupIterator* lookup,
|
||||
}
|
||||
if (!holder->HasFastProperties()) break;
|
||||
if (receiver_is_holder) {
|
||||
TRACE_HANDLER_STATS(isolate(), LoadIC_LoadApiGetterStub);
|
||||
int index = lookup->GetAccessorIndex();
|
||||
LoadApiGetterStub stub(isolate(), true, index);
|
||||
return stub.GetCode();
|
||||
}
|
||||
if (info->is_sloppy() && !receiver->IsJSReceiver()) break;
|
||||
TRACE_HANDLER_STATS(isolate(), LoadIC_LoadCallback);
|
||||
NamedLoadHandlerCompiler compiler(isolate(), map, holder,
|
||||
cache_holder);
|
||||
return compiler.CompileLoadCallback(lookup->name(), info);
|
||||
@ -1088,6 +1105,7 @@ Handle<Code> LoadIC::CompileHandler(LookupIterator* lookup,
|
||||
if (lookup->is_dictionary_holder()) {
|
||||
if (kind() != Code::LOAD_IC) break;
|
||||
if (holder->IsJSGlobalObject()) {
|
||||
TRACE_HANDLER_STATS(isolate(), LoadIC_LoadGlobal);
|
||||
NamedLoadHandlerCompiler compiler(isolate(), map, holder,
|
||||
cache_holder);
|
||||
Handle<PropertyCell> cell = lookup->GetPropertyCell();
|
||||
@ -1105,6 +1123,7 @@ Handle<Code> LoadIC::CompileHandler(LookupIterator* lookup,
|
||||
// property must be found in the object for the stub to be
|
||||
// applicable.
|
||||
if (!receiver_is_holder) break;
|
||||
TRACE_HANDLER_STATS(isolate(), LoadIC_LoadNormal);
|
||||
return isolate()->builtins()->LoadIC_Normal();
|
||||
}
|
||||
|
||||
@ -1114,6 +1133,7 @@ Handle<Code> LoadIC::CompileHandler(LookupIterator* lookup,
|
||||
if (receiver_is_holder) {
|
||||
return SimpleFieldLoad(field);
|
||||
}
|
||||
TRACE_HANDLER_STATS(isolate(), LoadIC_LoadField);
|
||||
NamedLoadHandlerCompiler compiler(isolate(), map, holder, cache_holder);
|
||||
return compiler.CompileLoadField(lookup->name(), field);
|
||||
}
|
||||
@ -1121,16 +1141,18 @@ Handle<Code> LoadIC::CompileHandler(LookupIterator* lookup,
|
||||
// -------------- Constant properties --------------
|
||||
DCHECK(lookup->property_details().type() == DATA_CONSTANT);
|
||||
if (receiver_is_holder) {
|
||||
TRACE_HANDLER_STATS(isolate(), LoadIC_LoadConstantStub);
|
||||
LoadConstantStub stub(isolate(), lookup->GetConstantIndex());
|
||||
return stub.GetCode();
|
||||
}
|
||||
TRACE_HANDLER_STATS(isolate(), LoadIC_LoadConstant);
|
||||
NamedLoadHandlerCompiler compiler(isolate(), map, holder, cache_holder);
|
||||
return compiler.CompileLoadConstant(lookup->name(),
|
||||
lookup->GetConstantIndex());
|
||||
}
|
||||
|
||||
case LookupIterator::INTEGER_INDEXED_EXOTIC:
|
||||
return slow_stub();
|
||||
break;
|
||||
case LookupIterator::ACCESS_CHECK:
|
||||
case LookupIterator::JSPROXY:
|
||||
case LookupIterator::NOT_FOUND:
|
||||
@ -1138,6 +1160,7 @@ Handle<Code> LoadIC::CompileHandler(LookupIterator* lookup,
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
TRACE_HANDLER_STATS(isolate(), LoadIC_SlowStub);
|
||||
return slow_stub();
|
||||
}
|
||||
|
||||
@ -1224,6 +1247,7 @@ void KeyedLoadIC::UpdateLoadElement(Handle<HeapObject> receiver) {
|
||||
}
|
||||
|
||||
CodeHandleList handlers(target_receiver_maps.length());
|
||||
TRACE_HANDLER_STATS(isolate(), KeyedLoadIC_PolymorphicElement);
|
||||
ElementHandlerCompiler compiler(isolate());
|
||||
compiler.CompileElementHandlers(&target_receiver_maps, &handlers);
|
||||
ConfigureVectorState(Handle<Name>(), &target_receiver_maps, &handlers);
|
||||
@ -1389,6 +1413,7 @@ MaybeHandle<Object> StoreIC::Store(Handle<Object> object, Handle<Name> name,
|
||||
|
||||
if (FLAG_use_ic &&
|
||||
StoreScriptContextFieldStub::Accepted(&lookup_result)) {
|
||||
TRACE_HANDLER_STATS(isolate(), StoreIC_StoreScriptContextFieldStub);
|
||||
StoreScriptContextFieldStub stub(isolate(), &lookup_result);
|
||||
PatchCache(name, stub.GetCode());
|
||||
}
|
||||
@ -1503,6 +1528,7 @@ Handle<Code> StoreIC::CompileHandler(LookupIterator* lookup,
|
||||
auto store_target = lookup->GetStoreTarget();
|
||||
if (store_target->IsJSGlobalObject()) {
|
||||
// TODO(dcarney): this currently just deopts. Use the transition cell.
|
||||
TRACE_HANDLER_STATS(isolate(), StoreIC_StoreGlobalTransition);
|
||||
auto cell = isolate()->factory()->NewPropertyCell();
|
||||
cell->set_value(*value);
|
||||
auto code = PropertyCellStoreHandler(
|
||||
@ -1519,12 +1545,14 @@ Handle<Code> StoreIC::CompileHandler(LookupIterator* lookup,
|
||||
}
|
||||
|
||||
DCHECK(lookup->IsCacheableTransition());
|
||||
TRACE_HANDLER_STATS(isolate(), StoreIC_StoreTransition);
|
||||
NamedStoreHandlerCompiler compiler(isolate(), receiver_map(), holder);
|
||||
return compiler.CompileStoreTransition(transition, lookup->name());
|
||||
}
|
||||
|
||||
case LookupIterator::INTERCEPTOR: {
|
||||
DCHECK(!holder->GetNamedInterceptor()->setter()->IsUndefined());
|
||||
TRACE_HANDLER_STATS(isolate(), StoreIC_StoreInterceptorStub);
|
||||
StoreInterceptorStub stub(isolate());
|
||||
return stub.GetCode();
|
||||
}
|
||||
@ -1553,6 +1581,7 @@ Handle<Code> StoreIC::CompileHandler(LookupIterator* lookup,
|
||||
break;
|
||||
}
|
||||
if (info->is_sloppy() && !receiver->IsJSReceiver()) break;
|
||||
TRACE_HANDLER_STATS(isolate(), StoreIC_StoreCallback);
|
||||
NamedStoreHandlerCompiler compiler(isolate(), receiver_map(), holder);
|
||||
return compiler.CompileStoreCallback(receiver, lookup->name(), info,
|
||||
language_mode());
|
||||
@ -1567,6 +1596,7 @@ Handle<Code> StoreIC::CompileHandler(LookupIterator* lookup,
|
||||
NamedStoreHandlerCompiler compiler(isolate(), receiver_map(), holder);
|
||||
if (call_optimization.is_simple_api_call()) {
|
||||
if (call_optimization.IsCompatibleReceiver(receiver, holder)) {
|
||||
TRACE_HANDLER_STATS(isolate(), StoreIC_StoreCallback);
|
||||
return compiler.CompileStoreCallback(receiver, lookup->name(),
|
||||
call_optimization,
|
||||
lookup->GetAccessorIndex());
|
||||
@ -1574,6 +1604,7 @@ Handle<Code> StoreIC::CompileHandler(LookupIterator* lookup,
|
||||
TRACE_GENERIC_IC(isolate(), "StoreIC", "incompatible receiver");
|
||||
break;
|
||||
}
|
||||
TRACE_HANDLER_STATS(isolate(), StoreIC_StoreViaSetter);
|
||||
int expected_arguments = JSFunction::cast(*setter)
|
||||
->shared()
|
||||
->internal_formal_parameter_count();
|
||||
@ -1587,6 +1618,7 @@ Handle<Code> StoreIC::CompileHandler(LookupIterator* lookup,
|
||||
case LookupIterator::DATA: {
|
||||
if (lookup->is_dictionary_holder()) {
|
||||
if (holder->IsJSGlobalObject()) {
|
||||
TRACE_HANDLER_STATS(isolate(), StoreIC_StoreGlobal);
|
||||
DCHECK(holder.is_identical_to(receiver) ||
|
||||
receiver->map()->prototype() == *holder);
|
||||
auto cell = lookup->GetPropertyCell();
|
||||
@ -1597,6 +1629,7 @@ Handle<Code> StoreIC::CompileHandler(LookupIterator* lookup,
|
||||
lookup->name(), cell, updated_type);
|
||||
return code;
|
||||
}
|
||||
TRACE_HANDLER_STATS(isolate(), StoreIC_StoreNormal);
|
||||
DCHECK(holder.is_identical_to(receiver));
|
||||
return isolate()->builtins()->StoreIC_Normal();
|
||||
}
|
||||
@ -1610,10 +1643,12 @@ Handle<Code> StoreIC::CompileHandler(LookupIterator* lookup,
|
||||
use_stub = !field_type->IsClass();
|
||||
}
|
||||
if (use_stub) {
|
||||
TRACE_HANDLER_STATS(isolate(), StoreIC_StoreFieldStub);
|
||||
StoreFieldStub stub(isolate(), lookup->GetFieldIndex(),
|
||||
lookup->representation());
|
||||
return stub.GetCode();
|
||||
}
|
||||
TRACE_HANDLER_STATS(isolate(), StoreIC_StoreField);
|
||||
NamedStoreHandlerCompiler compiler(isolate(), receiver_map(), holder);
|
||||
return compiler.CompileStoreField(lookup);
|
||||
}
|
||||
@ -1630,6 +1665,7 @@ Handle<Code> StoreIC::CompileHandler(LookupIterator* lookup,
|
||||
case LookupIterator::NOT_FOUND:
|
||||
UNREACHABLE();
|
||||
}
|
||||
TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub);
|
||||
return slow_stub();
|
||||
}
|
||||
|
||||
@ -1749,6 +1785,7 @@ void KeyedStoreIC::UpdateStoreElement(Handle<Map> receiver_map,
|
||||
}
|
||||
}
|
||||
|
||||
TRACE_HANDLER_STATS(isolate(), KeyedStoreIC_Polymorphic);
|
||||
MapHandleList transitioned_maps(target_receiver_maps.length());
|
||||
CodeHandleList handlers(target_receiver_maps.length());
|
||||
PropertyICCompiler::ComputeKeyedStorePolymorphicHandlers(
|
||||
|
Loading…
Reference in New Issue
Block a user