| 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.
|
|
|