Index: src/ic/ic.cc |
diff --git a/src/ic/ic.cc b/src/ic/ic.cc |
index 93164f9d4affdaa4bd69454bc2f6cdb797daeefb..022fa73b50a9d97cc4a4aeacb62d2d4a41424ee3 100644 |
--- a/src/ic/ic.cc |
+++ b/src/ic/ic.cc |
@@ -21,6 +21,7 @@ |
#include "src/ic/handler-configuration-inl.h" |
#include "src/ic/ic-compiler.h" |
#include "src/ic/ic-inl.h" |
+#include "src/ic/ic-stats.h" |
#include "src/ic/stub-cache.h" |
#include "src/isolate-inl.h" |
#include "src/macro-assembler.h" |
@@ -29,6 +30,7 @@ |
#include "src/runtime/runtime-utils.h" |
#include "src/runtime/runtime.h" |
#include "src/tracing/trace-event.h" |
+#include "src/tracing/tracing-category-observer.h" |
namespace v8 { |
namespace internal { |
@@ -90,7 +92,7 @@ const char* GetTransitionMarkModifier(KeyedAccessStoreMode mode) { |
void IC::TraceIC(const char* type, Handle<Object> name) { |
- if (FLAG_trace_ic) { |
+ if (FLAG_ic_stats) { |
if (AddressIsDeoptimizedCode()) return; |
DCHECK(UseVector()); |
State new_state = nexus()->StateFromFeedback(); |
@@ -101,8 +103,17 @@ 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) return; |
- PrintF("[%s%s in ", is_keyed() ? "Keyed" : "", type); |
+ if (V8_LIKELY(!FLAG_ic_stats)) return; |
+ |
+ if (FLAG_ic_stats & |
+ v8::tracing::TracingCategoryObserver::ENABLED_BY_TRACING) { |
+ ICStats::instance()->Begin(); |
+ ICInfo& ic_info = ICStats::instance()->Current(); |
+ ic_info.type = is_keyed() ? "Keyed" : ""; |
+ ic_info.type += type; |
+ } else { |
+ PrintF("[%s%s in ", is_keyed() ? "Keyed" : "", type); |
+ } |
// TODO(jkummerow): Add support for "apply". The logic is roughly: |
// marker = [fp_ + kMarkerOffset]; |
@@ -121,8 +132,14 @@ void IC::TraceIC(const char* type, Handle<Object> name, State old_state, |
code_offset = |
static_cast<int>(pc() - function->code()->instruction_start()); |
} |
- JavaScriptFrame::PrintFunctionAndOffset(function, function->abstract_code(), |
- code_offset, stdout, true); |
+ if (FLAG_ic_stats & |
+ v8::tracing::TracingCategoryObserver::ENABLED_BY_TRACING) { |
+ JavaScriptFrame::CollectFunctionAndOffsetForICStats( |
+ function, function->abstract_code(), code_offset); |
+ } else { |
+ JavaScriptFrame::PrintFunctionAndOffset( |
+ function, function->abstract_code(), code_offset, stdout, true); |
+ } |
} |
const char* modifier = ""; |
@@ -135,17 +152,45 @@ void IC::TraceIC(const char* type, Handle<Object> name, State old_state, |
if (!receiver_map().is_null()) { |
map = *receiver_map(); |
} |
- PrintF(" (%c->%c%s) map=(%p", TransitionMarkFromState(old_state), |
- TransitionMarkFromState(new_state), modifier, |
- reinterpret_cast<void*>(map)); |
+ if (FLAG_ic_stats & |
+ v8::tracing::TracingCategoryObserver::ENABLED_BY_TRACING) { |
+ ICInfo& ic_info = ICStats::instance()->Current(); |
+ // Reverse enough space for IC transition state, the longest length is 17. |
+ ic_info.state.reserve(17); |
+ ic_info.state = "("; |
+ ic_info.state += TransitionMarkFromState(old_state); |
+ ic_info.state += "->"; |
+ ic_info.state += TransitionMarkFromState(new_state); |
+ ic_info.state += modifier; |
+ ic_info.state += ")"; |
+ ic_info.map = reinterpret_cast<void*>(map); |
+ } else { |
+ PrintF(" (%c->%c%s) map=(%p", TransitionMarkFromState(old_state), |
+ TransitionMarkFromState(new_state), modifier, |
+ reinterpret_cast<void*>(map)); |
+ } |
if (map != nullptr) { |
- PrintF(" dict=%u own=%u type=", map->is_dictionary_map(), |
- map->NumberOfOwnDescriptors()); |
- std::cout << map->instance_type(); |
+ if (FLAG_ic_stats & |
+ v8::tracing::TracingCategoryObserver::ENABLED_BY_TRACING) { |
+ ICInfo& ic_info = ICStats::instance()->Current(); |
+ ic_info.is_dictionary_map = map->is_dictionary_map(); |
+ ic_info.number_of_own_descriptors = map->NumberOfOwnDescriptors(); |
+ ic_info.instance_type = std::to_string(map->instance_type()); |
+ } else { |
+ PrintF(" dict=%u own=%u type=", map->is_dictionary_map(), |
+ map->NumberOfOwnDescriptors()); |
+ std::cout << map->instance_type(); |
+ } |
+ } |
+ if (FLAG_ic_stats & |
+ v8::tracing::TracingCategoryObserver::ENABLED_BY_TRACING) { |
+ // TODO(lpy) Add name as key field in ICStats. |
+ ICStats::instance()->End(); |
+ } else { |
+ PrintF(") "); |
+ name->ShortPrint(stdout); |
+ PrintF("]\n"); |
} |
- PrintF(") "); |
- name->ShortPrint(stdout); |
- PrintF("]\n"); |
} |
@@ -2912,7 +2957,19 @@ MaybeHandle<Object> BinaryOpIC::Transition( |
} |
set_target(*new_target); |
- if (FLAG_trace_ic) { |
+ if (FLAG_ic_stats & |
+ v8::tracing::TracingCategoryObserver::ENABLED_BY_TRACING) { |
+ auto ic_stats = ICStats::instance(); |
+ ic_stats->Begin(); |
+ ICInfo& ic_info = ic_stats->Current(); |
+ ic_info.type = "BinaryOpIC"; |
+ ic_info.state = old_state.ToString(); |
+ ic_info.state += " => "; |
+ ic_info.state += state.ToString(); |
+ JavaScriptFrame::CollectTopFrameForICStats(isolate()); |
+ ic_stats->End(); |
+ } else if (FLAG_ic_stats) { |
+ // if (FLAG_trace_ic) { |
OFStream os(stdout); |
os << "[BinaryOpIC" << old_state << " => " << state << " @ " |
<< static_cast<void*>(*new_target) << " <- "; |
@@ -2986,7 +3043,30 @@ Code* CompareIC::UpdateCaches(Handle<Object> x, Handle<Object> y) { |
Handle<Code> new_target = stub.GetCode(); |
set_target(*new_target); |
- if (FLAG_trace_ic) { |
+ if (FLAG_ic_stats & |
+ v8::tracing::TracingCategoryObserver::ENABLED_BY_TRACING) { |
+ auto ic_stats = ICStats::instance(); |
+ ic_stats->Begin(); |
+ ICInfo& ic_info = ic_stats->Current(); |
+ ic_info.type = "CompareIC"; |
+ JavaScriptFrame::CollectTopFrameForICStats(isolate()); |
+ ic_info.state = "(("; |
+ ic_info.state += CompareICState::GetStateName(old_stub.left()); |
+ ic_info.state += "+"; |
+ ic_info.state += CompareICState::GetStateName(old_stub.right()); |
+ ic_info.state += "="; |
+ ic_info.state += CompareICState::GetStateName(old_stub.state()); |
+ ic_info.state += ")->("; |
+ ic_info.state += CompareICState::GetStateName(new_left); |
+ ic_info.state += "+"; |
+ ic_info.state += CompareICState::GetStateName(new_right); |
+ ic_info.state += "="; |
+ ic_info.state += CompareICState::GetStateName(state); |
+ ic_info.state += "))#"; |
+ ic_info.state += Token::Name(op_); |
+ ic_stats->End(); |
+ } else if (FLAG_ic_stats) { |
+ // if (FLAG_trace_ic) { |
PrintF("[CompareIC in "); |
JavaScriptFrame::PrintTop(isolate(), stdout, false, true); |
PrintF(" ((%s+%s=%s)->(%s+%s=%s))#%s @ %p]\n", |