Commit 61b49b3c authored by ishell's avatar ishell Committed by Commit bot

[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}
parent bf90d9a3
......@@ -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;
......
This diff is collapsed.
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