Index: src/interpreter/interpreter.cc |
diff --git a/src/interpreter/interpreter.cc b/src/interpreter/interpreter.cc |
index 5084300dfee60294b3af19832d026410b5834c6f..c4fd9c04c4c3de74f44fcdb60eb2c1a8a23d077f 100644 |
--- a/src/interpreter/interpreter.cc |
+++ b/src/interpreter/interpreter.cc |
@@ -4,6 +4,8 @@ |
#include "src/interpreter/interpreter.h" |
+#include <fstream> |
+ |
#include "src/ast/prettyprinter.h" |
#include "src/code-factory.h" |
#include "src/compiler.h" |
@@ -33,6 +35,14 @@ void Interpreter::Initialize() { |
Zone zone(isolate_->allocator()); |
HandleScope scope(isolate_); |
+ if (FLAG_trace_ignition_dispatches) { |
+ static const int kBytecodeCount = static_cast<int>(Bytecode::kLast) + 1; |
+ bytecode_dispatch_count_table_.Reset( |
+ new uintptr_t[kBytecodeCount * kBytecodeCount]); |
+ memset(bytecode_dispatch_count_table_.get(), 0, |
+ sizeof(uintptr_t) * kBytecodeCount * kBytecodeCount); |
+ } |
+ |
// Generate bytecode handlers for all bytecodes and scales. |
for (OperandScale operand_scale = OperandScale::kSingle; |
operand_scale <= OperandScale::kMaxValid; |
@@ -148,9 +158,11 @@ bool Interpreter::MakeBytecode(CompilationInfo* info) { |
} |
bool Interpreter::IsDispatchTableInitialized() { |
- if (FLAG_trace_ignition || FLAG_trace_ignition_codegen) { |
- // Regenerate table to add bytecode tracing operations |
- // or to print the assembly code generated by TurboFan. |
+ if (FLAG_trace_ignition || FLAG_trace_ignition_codegen || |
+ FLAG_trace_ignition_dispatches) { |
+ // Regenerate table to add bytecode tracing operations, |
+ // print the assembly code generated by TurboFan, |
+ // or instrument handlers with dispatch counters. |
return false; |
} |
return dispatch_table_[0] != nullptr; |
@@ -178,6 +190,52 @@ const char* Interpreter::LookupNameOfBytecodeHandler(Code* code) { |
return nullptr; |
} |
+void Interpreter::WriteDispatchCounters() { |
+ std::ofstream stream(FLAG_trace_ignition_dispatches_output_file); |
+ static const int kBytecodeCount = static_cast<int>(Bytecode::kLast) + 1; |
+ |
+ // Output is a JSON-encoded object of objects. |
+ // |
+ // The keys on the top level object are source bytecodes, |
+ // and corresponding value are objects. Keys on these last are the |
+ // destinations of the dispatch and the value associated is a counter for |
+ // the correspondent source-destination dispatch chain. |
+ // |
+ // Only non-zero counters are written to file, but an entry in the top-level |
+ // object is always present, even if the value is empty because all counters |
+ // for that source are zero. |
+ |
+ stream << '{'; |
+ |
+ for (int from_index = 0; from_index < kBytecodeCount; ++from_index) { |
+ if (from_index > 0) stream << ",\n "; |
+ |
+ Bytecode from_bytecode = Bytecodes::FromByte(from_index); |
+ stream << "\"" << Bytecodes::ToString(from_bytecode) << "\": {"; |
+ |
+ bool emitted_first = false; |
+ for (int to_index = 0; to_index < kBytecodeCount; ++to_index) { |
+ uintptr_t counter = |
+ bytecode_dispatch_count_table_[from_index * kBytecodeCount + |
+ to_index]; |
+ if (counter > 0) { |
+ if (emitted_first) { |
+ stream << ", "; |
+ } else { |
+ emitted_first = true; |
+ } |
+ |
+ Bytecode to_bytecode = Bytecodes::FromByte(to_index); |
+ stream << '"' << Bytecodes::ToString(to_bytecode) << "\": " << counter; |
+ } |
+ } |
+ |
+ stream << "}"; |
+ } |
+ |
+ stream << '}'; |
+} |
+ |
// LdaZero |
// |
// Load literal '0' into the accumulator. |