Commit 6399fce5 authored by rmcilroy's avatar rmcilroy Committed by Commit bot

[Interpreter] Add option to trace bytecode execution.

Adds --trace-ignition flag which allows tracing of bytecodes as they
execute. As well as printing out the bytecode, this also prints out the
input and output registers to each operation. The generated output looks
as follows:

 -> 0x350cb46d5264 (139) : 49 fc fb 03 07    Call r4, r5, #3, [7]
      [ accumulator -> 0x177fba00bc99 <JS Array[2]> ]
      [          r4 -> 0x350cb46ce099 <JS Function InstallFunctions (SharedFunctionInfo 0x350cb46470c1)> ]
      [          r5 -> 0x350cb46cddc1 <an Object with map 0x35fdf590a3a9> ]
      [          r6 -> 0x350cb46d3f11 <JS Function Proxy (SharedFunctionInfo 0x350cb46d3e61)> ]
      [          r7 -> 2 ]
      [ accumulator <- 0x350cb4604189 <undefined> ]
 -> 0x350cb46d5978 (47) : 4b f8 00 00 00    CallRuntime [248], r0, #0
      [ accumulator -> 0x350cb4604189 <undefined> ]
      [ accumulator <- 0x350cb4604189 <undefined> ]
 -> 0x350cb46d597d (52) : 23 09             Ldar a0
      [ accumulator -> 0x350cb4604189 <undefined> ]
      [          a0 -> 0x350cb46d3f11 <JS Function Proxy (SharedFunctionInfo 0x350cb46d3e61)> ]
      [ accumulator <- 0x350cb46d3f11 <JS Function Proxy (SharedFunctionInfo 0x350cb46d3e61)> ]
 -> 0x350cb46d597f (54) : 24 fd             Star r3
      [ accumulator -> 0x350cb46d3f11 <JS Function Proxy (SharedFunctionInfo 0x350cb46d3e61)> ]
      [ accumulator <- 0x350cb46d3f11 <JS Function Proxy (SharedFunctionInfo 0x350cb46d3e61)> ]
      [          r3 <- 0x350cb46d3f11 <JS Function Proxy (SharedFunctionInfo 0x350cb46d3e61)> ]

Also adds support for --print_source and --print-ast to the interpreter.

BUG=v8:4280
LOG=N

Review URL: https://codereview.chromium.org/1640213002

Cr-Commit-Position: refs/heads/master@{#33594}
parent 87b6e880
...@@ -24,7 +24,6 @@ namespace v8 { ...@@ -24,7 +24,6 @@ namespace v8 {
namespace internal { namespace internal {
namespace compiler { namespace compiler {
InterpreterAssembler::InterpreterAssembler(Isolate* isolate, Zone* zone, InterpreterAssembler::InterpreterAssembler(Isolate* isolate, Zone* zone,
interpreter::Bytecode bytecode) interpreter::Bytecode bytecode)
: bytecode_(bytecode), : bytecode_(bytecode),
...@@ -35,12 +34,13 @@ InterpreterAssembler::InterpreterAssembler(Isolate* isolate, Zone* zone, ...@@ -35,12 +34,13 @@ InterpreterAssembler::InterpreterAssembler(Isolate* isolate, Zone* zone,
InstructionSelector::SupportedMachineOperatorFlags())), InstructionSelector::SupportedMachineOperatorFlags())),
accumulator_( accumulator_(
raw_assembler_->Parameter(Linkage::kInterpreterAccumulatorParameter)), raw_assembler_->Parameter(Linkage::kInterpreterAccumulatorParameter)),
bytecode_offset_(raw_assembler_->Parameter(
Linkage::kInterpreterBytecodeOffsetParameter)),
context_( context_(
raw_assembler_->Parameter(Linkage::kInterpreterContextParameter)), raw_assembler_->Parameter(Linkage::kInterpreterContextParameter)),
code_generated_(false) {} code_generated_(false) {
if (FLAG_trace_ignition) {
TraceBytecode(Runtime::kInterpreterTraceBytecodeEntry);
}
}
InterpreterAssembler::~InterpreterAssembler() {} InterpreterAssembler::~InterpreterAssembler() {}
...@@ -85,9 +85,10 @@ void InterpreterAssembler::SetContext(Node* value) { ...@@ -85,9 +85,10 @@ void InterpreterAssembler::SetContext(Node* value) {
context_ = value; context_ = value;
} }
Node* InterpreterAssembler::BytecodeOffset() {
Node* InterpreterAssembler::BytecodeOffset() { return bytecode_offset_; } return raw_assembler_->Parameter(
Linkage::kInterpreterBytecodeOffsetParameter);
}
Node* InterpreterAssembler::RegisterFileRawPointer() { Node* InterpreterAssembler::RegisterFileRawPointer() {
return raw_assembler_->Parameter(Linkage::kInterpreterRegisterFileParameter); return raw_assembler_->Parameter(Linkage::kInterpreterRegisterFileParameter);
...@@ -464,18 +465,11 @@ Node* InterpreterAssembler::CallConstruct(Node* new_target, Node* constructor, ...@@ -464,18 +465,11 @@ Node* InterpreterAssembler::CallConstruct(Node* new_target, Node* constructor,
void InterpreterAssembler::CallPrologue() { void InterpreterAssembler::CallPrologue() {
StoreRegister(SmiTag(bytecode_offset_), StoreRegister(SmiTag(BytecodeOffset()),
InterpreterFrameConstants::kBytecodeOffsetFromRegisterPointer); InterpreterFrameConstants::kBytecodeOffsetFromRegisterPointer);
} }
void InterpreterAssembler::CallEpilogue() {
// Restore the bytecode offset from the stack frame.
bytecode_offset_ = SmiUntag(LoadRegister(
InterpreterFrameConstants::kBytecodeOffsetFromRegisterPointer));
}
Node* InterpreterAssembler::CallN(CallDescriptor* descriptor, Node* code_target, Node* InterpreterAssembler::CallN(CallDescriptor* descriptor, Node* code_target,
Node** args) { Node** args) {
CallPrologue(); CallPrologue();
...@@ -491,7 +485,6 @@ Node* InterpreterAssembler::CallN(CallDescriptor* descriptor, Node* code_target, ...@@ -491,7 +485,6 @@ Node* InterpreterAssembler::CallN(CallDescriptor* descriptor, Node* code_target,
kUnexpectedStackPointer); kUnexpectedStackPointer);
} }
CallEpilogue();
return return_val; return return_val;
} }
...@@ -594,7 +587,6 @@ Node* InterpreterAssembler::CallRuntime(Runtime::FunctionId function_id, ...@@ -594,7 +587,6 @@ Node* InterpreterAssembler::CallRuntime(Runtime::FunctionId function_id,
CallPrologue(); CallPrologue();
Node* return_val = Node* return_val =
raw_assembler_->CallRuntime1(function_id, arg1, GetContext()); raw_assembler_->CallRuntime1(function_id, arg1, GetContext());
CallEpilogue();
return return_val; return return_val;
} }
...@@ -604,10 +596,16 @@ Node* InterpreterAssembler::CallRuntime(Runtime::FunctionId function_id, ...@@ -604,10 +596,16 @@ Node* InterpreterAssembler::CallRuntime(Runtime::FunctionId function_id,
CallPrologue(); CallPrologue();
Node* return_val = Node* return_val =
raw_assembler_->CallRuntime2(function_id, arg1, arg2, GetContext()); raw_assembler_->CallRuntime2(function_id, arg1, arg2, GetContext());
CallEpilogue();
return return_val; return return_val;
} }
Node* InterpreterAssembler::CallRuntime(Runtime::FunctionId function_id,
Node* arg1, Node* arg2, Node* arg3) {
CallPrologue();
Node* return_val =
raw_assembler_->CallRuntime3(function_id, arg1, arg2, arg3, GetContext());
return return_val;
}
Node* InterpreterAssembler::CallRuntime(Runtime::FunctionId function_id, Node* InterpreterAssembler::CallRuntime(Runtime::FunctionId function_id,
Node* arg1, Node* arg2, Node* arg3, Node* arg1, Node* arg2, Node* arg3,
...@@ -615,12 +613,15 @@ Node* InterpreterAssembler::CallRuntime(Runtime::FunctionId function_id, ...@@ -615,12 +613,15 @@ Node* InterpreterAssembler::CallRuntime(Runtime::FunctionId function_id,
CallPrologue(); CallPrologue();
Node* return_val = raw_assembler_->CallRuntime4(function_id, arg1, arg2, arg3, Node* return_val = raw_assembler_->CallRuntime4(function_id, arg1, arg2, arg3,
arg4, GetContext()); arg4, GetContext());
CallEpilogue();
return return_val; return return_val;
} }
void InterpreterAssembler::Return() { void InterpreterAssembler::Return() {
if (FLAG_trace_ignition) {
TraceBytecode(Runtime::kInterpreterTraceBytecodeExit);
}
Node* exit_trampoline_code_object = Node* exit_trampoline_code_object =
HeapConstant(isolate()->builtins()->InterpreterExitTrampoline()); HeapConstant(isolate()->builtins()->InterpreterExitTrampoline());
// If the order of the parameters you need to change the call signature below. // If the order of the parameters you need to change the call signature below.
...@@ -650,10 +651,8 @@ Node* InterpreterAssembler::Advance(Node* delta) { ...@@ -650,10 +651,8 @@ Node* InterpreterAssembler::Advance(Node* delta) {
return raw_assembler_->IntPtrAdd(BytecodeOffset(), delta); return raw_assembler_->IntPtrAdd(BytecodeOffset(), delta);
} }
void InterpreterAssembler::Jump(Node* delta) { DispatchTo(Advance(delta)); } void InterpreterAssembler::Jump(Node* delta) { DispatchTo(Advance(delta)); }
void InterpreterAssembler::JumpIfWordEqual(Node* lhs, Node* rhs, Node* delta) { void InterpreterAssembler::JumpIfWordEqual(Node* lhs, Node* rhs, Node* delta) {
RawMachineLabel match, no_match; RawMachineLabel match, no_match;
Node* condition = raw_assembler_->WordEqual(lhs, rhs); Node* condition = raw_assembler_->WordEqual(lhs, rhs);
...@@ -671,6 +670,9 @@ void InterpreterAssembler::Dispatch() { ...@@ -671,6 +670,9 @@ void InterpreterAssembler::Dispatch() {
void InterpreterAssembler::DispatchTo(Node* new_bytecode_offset) { void InterpreterAssembler::DispatchTo(Node* new_bytecode_offset) {
if (FLAG_trace_ignition) {
TraceBytecode(Runtime::kInterpreterTraceBytecodeExit);
}
Node* target_bytecode = raw_assembler_->Load( Node* target_bytecode = raw_assembler_->Load(
MachineType::Uint8(), BytecodeArrayTaggedPointer(), new_bytecode_offset); MachineType::Uint8(), BytecodeArrayTaggedPointer(), new_bytecode_offset);
...@@ -716,6 +718,10 @@ void InterpreterAssembler::AbortIfWordNotEqual(Node* lhs, Node* rhs, ...@@ -716,6 +718,10 @@ void InterpreterAssembler::AbortIfWordNotEqual(Node* lhs, Node* rhs,
raw_assembler_->Bind(&match); raw_assembler_->Bind(&match);
} }
void InterpreterAssembler::TraceBytecode(Runtime::FunctionId function_id) {
CallRuntime(function_id, BytecodeArrayTaggedPointer(),
SmiTag(BytecodeOffset()), GetAccumulator());
}
// static // static
bool InterpreterAssembler::TargetSupportsUnalignedAccess() { bool InterpreterAssembler::TargetSupportsUnalignedAccess() {
......
...@@ -137,6 +137,8 @@ class InterpreterAssembler { ...@@ -137,6 +137,8 @@ class InterpreterAssembler {
int return_size = 1); int return_size = 1);
Node* CallRuntime(Runtime::FunctionId function_id, Node* arg1); Node* CallRuntime(Runtime::FunctionId function_id, Node* arg1);
Node* CallRuntime(Runtime::FunctionId function_id, Node* arg1, Node* arg2); Node* CallRuntime(Runtime::FunctionId function_id, Node* arg1, Node* arg2);
Node* CallRuntime(Runtime::FunctionId function_id, Node* arg1, Node* arg2,
Node* arg3);
Node* CallRuntime(Runtime::FunctionId function_id, Node* arg1, Node* arg2, Node* CallRuntime(Runtime::FunctionId function_id, Node* arg1, Node* arg2,
Node* arg3, Node* arg4); Node* arg3, Node* arg4);
...@@ -176,7 +178,9 @@ class InterpreterAssembler { ...@@ -176,7 +178,9 @@ class InterpreterAssembler {
// Saves and restores interpreter bytecode offset to the interpreter stack // Saves and restores interpreter bytecode offset to the interpreter stack
// frame when performing a call. // frame when performing a call.
void CallPrologue(); void CallPrologue();
void CallEpilogue();
// Traces the current bytecode by calling |function_id|.
void TraceBytecode(Runtime::FunctionId function_id);
// Returns the offset of register |index| relative to RegisterFilePointer(). // Returns the offset of register |index| relative to RegisterFilePointer().
Node* RegisterFrameOffset(Node* index); Node* RegisterFrameOffset(Node* index);
...@@ -209,7 +213,6 @@ class InterpreterAssembler { ...@@ -209,7 +213,6 @@ class InterpreterAssembler {
base::SmartPointer<RawMachineAssembler> raw_assembler_; base::SmartPointer<RawMachineAssembler> raw_assembler_;
Node* accumulator_; Node* accumulator_;
Node* bytecode_offset_;
Node* context_; Node* context_;
bool code_generated_; bool code_generated_;
......
...@@ -183,6 +183,21 @@ Node* RawMachineAssembler::CallRuntime2(Runtime::FunctionId function, ...@@ -183,6 +183,21 @@ Node* RawMachineAssembler::CallRuntime2(Runtime::FunctionId function,
context); context);
} }
Node* RawMachineAssembler::CallRuntime3(Runtime::FunctionId function,
Node* arg1, Node* arg2, Node* arg3,
Node* context) {
CallDescriptor* descriptor = Linkage::GetRuntimeCallDescriptor(
zone(), function, 3, Operator::kNoProperties, CallDescriptor::kNoFlags);
int return_count = static_cast<int>(descriptor->ReturnCount());
Node* centry = HeapConstant(CEntryStub(isolate(), return_count).GetCode());
Node* ref = AddNode(
common()->ExternalConstant(ExternalReference(function, isolate())));
Node* arity = Int32Constant(3);
return AddNode(common()->Call(descriptor), centry, arg1, arg2, arg3, ref,
arity, context);
}
Node* RawMachineAssembler::CallRuntime4(Runtime::FunctionId function, Node* RawMachineAssembler::CallRuntime4(Runtime::FunctionId function,
Node* arg1, Node* arg2, Node* arg3, Node* arg1, Node* arg2, Node* arg3,
......
...@@ -569,6 +569,9 @@ class RawMachineAssembler { ...@@ -569,6 +569,9 @@ class RawMachineAssembler {
// Call to a runtime function with two arguments. // Call to a runtime function with two arguments.
Node* CallRuntime2(Runtime::FunctionId function, Node* arg1, Node* arg2, Node* CallRuntime2(Runtime::FunctionId function, Node* arg1, Node* arg2,
Node* context); Node* context);
// Call to a runtime function with three arguments.
Node* CallRuntime3(Runtime::FunctionId function, Node* arg1, Node* arg2,
Node* arg3, Node* context);
// Call to a runtime function with four arguments. // Call to a runtime function with four arguments.
Node* CallRuntime4(Runtime::FunctionId function, Node* arg1, Node* arg2, Node* CallRuntime4(Runtime::FunctionId function, Node* arg1, Node* arg2,
Node* arg3, Node* arg4, Node* context); Node* arg3, Node* arg4, Node* context);
......
...@@ -144,6 +144,11 @@ struct MaybeBoolFlag { ...@@ -144,6 +144,11 @@ struct MaybeBoolFlag {
#else #else
# define ENABLE_NEON_DEFAULT false # define ENABLE_NEON_DEFAULT false
#endif #endif
#ifdef V8_OS_WIN
# define ENABLE_LOG_COLOUR false
#else
# define ENABLE_LOG_COLOUR true
#endif
#define DEFINE_BOOL(nam, def, cmt) FLAG(BOOL, bool, nam, def, cmt) #define DEFINE_BOOL(nam, def, cmt) FLAG(BOOL, bool, nam, def, cmt)
#define DEFINE_BOOL_READONLY(nam, def, cmt) \ #define DEFINE_BOOL_READONLY(nam, def, cmt) \
...@@ -302,6 +307,8 @@ DEFINE_BOOL(ignition, false, "use ignition interpreter") ...@@ -302,6 +307,8 @@ DEFINE_BOOL(ignition, false, "use ignition interpreter")
DEFINE_STRING(ignition_filter, "*", "filter for ignition interpreter") DEFINE_STRING(ignition_filter, "*", "filter for ignition interpreter")
DEFINE_BOOL(print_bytecode, false, DEFINE_BOOL(print_bytecode, false,
"print bytecode generated by ignition interpreter") "print bytecode generated by ignition interpreter")
DEFINE_BOOL(trace_ignition, false,
"trace the bytecodes executed by the ignition interpreter")
DEFINE_BOOL(trace_ignition_codegen, false, DEFINE_BOOL(trace_ignition_codegen, false,
"trace the codegen of ignition interpreter bytecode handlers") "trace the codegen of ignition interpreter bytecode handlers")
...@@ -788,7 +795,8 @@ DEFINE_INT(sim_stack_size, 2 * MB / KB, ...@@ -788,7 +795,8 @@ DEFINE_INT(sim_stack_size, 2 * MB / KB,
"in kBytes (default is 2 MB)") "in kBytes (default is 2 MB)")
DEFINE_BOOL(log_regs_modified, true, DEFINE_BOOL(log_regs_modified, true,
"When logging register values, only print modified registers.") "When logging register values, only print modified registers.")
DEFINE_BOOL(log_colour, true, "When logging, try to use coloured output.") DEFINE_BOOL(log_colour, ENABLE_LOG_COLOUR,
"When logging, try to use coloured output.")
DEFINE_BOOL(ignore_asm_unimplemented_break, false, DEFINE_BOOL(ignore_asm_unimplemented_break, false,
"Don't break for ASM_UNIMPLEMENTED_BREAK macros.") "Don't break for ASM_UNIMPLEMENTED_BREAK macros.")
DEFINE_BOOL(trace_sim_messages, false, DEFINE_BOOL(trace_sim_messages, false,
......
...@@ -100,6 +100,36 @@ Register BytecodeArrayIterator::GetRegisterOperand(int operand_index) const { ...@@ -100,6 +100,36 @@ Register BytecodeArrayIterator::GetRegisterOperand(int operand_index) const {
return Register(); return Register();
} }
int BytecodeArrayIterator::GetRegisterOperandRange(int operand_index) const {
interpreter::OperandType operand_type =
Bytecodes::GetOperandType(current_bytecode(), operand_index);
DCHECK(Bytecodes::IsRegisterOperandType(operand_type));
switch (operand_type) {
case OperandType::kRegPair8:
case OperandType::kRegPair16:
case OperandType::kRegOutPair8:
case OperandType::kRegOutPair16:
return 2;
case OperandType::kRegOutTriple8:
case OperandType::kRegOutTriple16:
return 3;
default: {
if (operand_index + 1 !=
Bytecodes::NumberOfOperands(current_bytecode())) {
// TODO(oth): Ensure all bytecodes specify the full range of registers
// with kRegCount (currently Call/CallJSRuntime are off by one due to
// reciever.
OperandType next_operand_type =
Bytecodes::GetOperandType(current_bytecode(), operand_index + 1);
if (next_operand_type == OperandType::kRegCount8 ||
next_operand_type == OperandType::kRegCount16) {
return GetCountOperand(operand_index + 1);
}
}
return 1;
}
}
}
Handle<Object> BytecodeArrayIterator::GetConstantForIndexOperand( Handle<Object> BytecodeArrayIterator::GetConstantForIndexOperand(
int operand_index) const { int operand_index) const {
......
...@@ -21,6 +21,7 @@ class BytecodeArrayIterator { ...@@ -21,6 +21,7 @@ class BytecodeArrayIterator {
bool done() const; bool done() const;
Bytecode current_bytecode() const; Bytecode current_bytecode() const;
int current_bytecode_size() const; int current_bytecode_size() const;
void set_current_offset(int offset) { bytecode_offset_ = offset; }
int current_offset() const { return bytecode_offset_; } int current_offset() const { return bytecode_offset_; }
const Handle<BytecodeArray>& bytecode_array() const { const Handle<BytecodeArray>& bytecode_array() const {
return bytecode_array_; return bytecode_array_;
...@@ -30,6 +31,7 @@ class BytecodeArrayIterator { ...@@ -30,6 +31,7 @@ class BytecodeArrayIterator {
int GetIndexOperand(int operand_index) const; int GetIndexOperand(int operand_index) const;
int GetCountOperand(int operand_index) const; int GetCountOperand(int operand_index) const;
Register GetRegisterOperand(int operand_index) const; Register GetRegisterOperand(int operand_index) const;
int GetRegisterOperandRange(int operand_index) const;
Handle<Object> GetConstantForIndexOperand(int operand_index) const; Handle<Object> GetConstantForIndexOperand(int operand_index) const;
// Get the raw byte for the given operand. Note: you should prefer using the // Get the raw byte for the given operand. Note: you should prefer using the
......
...@@ -380,22 +380,7 @@ std::ostream& Bytecodes::Decode(std::ostream& os, const uint8_t* bytecode_start, ...@@ -380,22 +380,7 @@ std::ostream& Bytecodes::Decode(std::ostream& os, const uint8_t* bytecode_start,
case interpreter::OperandType::kRegOut8: case interpreter::OperandType::kRegOut8:
case interpreter::OperandType::kRegOut16: { case interpreter::OperandType::kRegOut16: {
Register reg = DecodeRegister(operand_start, op_type); Register reg = DecodeRegister(operand_start, op_type);
if (reg.is_current_context()) { os << reg.ToString(parameter_count);
os << "<context>";
} else if (reg.is_function_closure()) {
os << "<closure>";
} else if (reg.is_new_target()) {
os << "<new.target>";
} else if (reg.is_parameter()) {
int parameter_index = reg.ToParameterIndex(parameter_count);
if (parameter_index == 0) {
os << "<this>";
} else {
os << "a" << parameter_index - 1;
}
} else {
os << "r" << reg.index();
}
break; break;
} }
case interpreter::OperandType::kRegOutTriple8: case interpreter::OperandType::kRegOutTriple8:
...@@ -406,14 +391,10 @@ std::ostream& Bytecodes::Decode(std::ostream& os, const uint8_t* bytecode_start, ...@@ -406,14 +391,10 @@ std::ostream& Bytecodes::Decode(std::ostream& os, const uint8_t* bytecode_start,
case interpreter::OperandType::kRegPair8: case interpreter::OperandType::kRegPair8:
case interpreter::OperandType::kRegPair16: { case interpreter::OperandType::kRegPair16: {
range += 1; range += 1;
Register reg = DecodeRegister(operand_start, op_type); Register first_reg = DecodeRegister(operand_start, op_type);
if (reg.is_parameter()) { Register last_reg = Register(first_reg.index() + range);
int parameter_index = reg.ToParameterIndex(parameter_count); os << first_reg.ToString(parameter_count) << "-"
DCHECK_GT(parameter_index, 0); << last_reg.ToString(parameter_count);
os << "a" << parameter_index - range << "-" << parameter_index;
} else {
os << "r" << reg.index() << "-" << reg.index() + range;
}
break; break;
} }
case interpreter::OperandType::kNone: case interpreter::OperandType::kNone:
...@@ -427,7 +408,6 @@ std::ostream& Bytecodes::Decode(std::ostream& os, const uint8_t* bytecode_start, ...@@ -427,7 +408,6 @@ std::ostream& Bytecodes::Decode(std::ostream& os, const uint8_t* bytecode_start,
return os; return os;
} }
std::ostream& operator<<(std::ostream& os, const Bytecode& bytecode) { std::ostream& operator<<(std::ostream& os, const Bytecode& bytecode) {
return os << Bytecodes::ToString(bytecode); return os << Bytecodes::ToString(bytecode);
} }
...@@ -442,7 +422,6 @@ std::ostream& operator<<(std::ostream& os, const OperandSize& operand_size) { ...@@ -442,7 +422,6 @@ std::ostream& operator<<(std::ostream& os, const OperandSize& operand_size) {
return os << Bytecodes::OperandSizeToString(operand_size); return os << Bytecodes::OperandSizeToString(operand_size);
} }
static const int kLastParamRegisterIndex = static const int kLastParamRegisterIndex =
-InterpreterFrameConstants::kLastParamFromRegisterPointer / kPointerSize; -InterpreterFrameConstants::kLastParamFromRegisterPointer / kPointerSize;
static const int kFunctionClosureRegisterIndex = static const int kFunctionClosureRegisterIndex =
...@@ -569,6 +548,29 @@ bool Register::AreContiguous(Register reg1, Register reg2, Register reg3, ...@@ -569,6 +548,29 @@ bool Register::AreContiguous(Register reg1, Register reg2, Register reg3,
return true; return true;
} }
std::string Register::ToString(int parameter_count) {
if (is_current_context()) {
return std::string("<context>");
} else if (is_function_closure()) {
return std::string("<closure>");
} else if (is_new_target()) {
return std::string("<new.target>");
} else if (is_parameter()) {
int parameter_index = ToParameterIndex(parameter_count);
if (parameter_index == 0) {
return std::string("<this>");
} else {
std::ostringstream s;
s << "a" << parameter_index - 1;
return s.str();
}
} else {
std::ostringstream s;
s << "r" << index();
return s.str();
}
}
} // namespace interpreter } // namespace interpreter
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8
...@@ -344,6 +344,8 @@ class Register { ...@@ -344,6 +344,8 @@ class Register {
Register reg4 = Register(), Register reg4 = Register(),
Register reg5 = Register()); Register reg5 = Register());
std::string ToString(int parameter_count);
bool operator==(const Register& other) const { bool operator==(const Register& other) const {
return index() == other.index(); return index() == other.index();
} }
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
#include "src/interpreter/interpreter.h" #include "src/interpreter/interpreter.h"
#include "src/ast/prettyprinter.h"
#include "src/code-factory.h" #include "src/code-factory.h"
#include "src/compiler.h" #include "src/compiler.h"
#include "src/compiler/interpreter-assembler.h" #include "src/compiler/interpreter-assembler.h"
...@@ -60,6 +61,31 @@ void Interpreter::Initialize() { ...@@ -60,6 +61,31 @@ void Interpreter::Initialize() {
bool Interpreter::MakeBytecode(CompilationInfo* info) { bool Interpreter::MakeBytecode(CompilationInfo* info) {
if (FLAG_print_bytecode || FLAG_print_source || FLAG_print_ast) {
OFStream os(stdout);
base::SmartArrayPointer<char> name = info->GetDebugName();
os << "[generating bytecode for function: " << info->GetDebugName().get()
<< "]" << std::endl
<< std::flush;
}
#ifdef DEBUG
if (info->parse_info() && FLAG_print_source) {
OFStream os(stdout);
os << "--- Source from AST ---" << std::endl
<< PrettyPrinter(info->isolate()).PrintProgram(info->literal())
<< std::endl
<< std::flush;
}
if (info->parse_info() && FLAG_print_ast) {
OFStream os(stdout);
os << "--- AST ---" << std::endl
<< AstPrinter(info->isolate()).PrintProgram(info->literal()) << std::endl
<< std::flush;
}
#endif // DEBUG
BytecodeGenerator generator(info->isolate(), info->zone()); BytecodeGenerator generator(info->isolate(), info->zone());
info->EnsureFeedbackVector(); info->EnsureFeedbackVector();
Handle<BytecodeArray> bytecodes = generator.MakeBytecode(info); Handle<BytecodeArray> bytecodes = generator.MakeBytecode(info);
...@@ -78,11 +104,14 @@ bool Interpreter::MakeBytecode(CompilationInfo* info) { ...@@ -78,11 +104,14 @@ bool Interpreter::MakeBytecode(CompilationInfo* info) {
bool Interpreter::IsInterpreterTableInitialized( bool Interpreter::IsInterpreterTableInitialized(
Handle<FixedArray> handler_table) { Handle<FixedArray> handler_table) {
if (FLAG_trace_ignition) {
// Regenerate table to add bytecode tracing operations.
return false;
}
DCHECK(handler_table->length() == static_cast<int>(Bytecode::kLast) + 1); DCHECK(handler_table->length() == static_cast<int>(Bytecode::kLast) + 1);
return handler_table->get(0) != isolate_->heap()->undefined_value(); return handler_table->get(0) != isolate_->heap()->undefined_value();
} }
// LdaZero // LdaZero
// //
// Load literal '0' into the accumulator. // Load literal '0' into the accumulator.
......
...@@ -4448,8 +4448,6 @@ class BytecodeArray : public FixedArrayBase { ...@@ -4448,8 +4448,6 @@ class BytecodeArray : public FixedArrayBase {
kHandlerTableOffset + kPointerSize; kHandlerTableOffset + kPointerSize;
static const int kHeaderSize = kSourcePositionTableOffset + kPointerSize; static const int kHeaderSize = kSourcePositionTableOffset + kPointerSize;
static const int kAlignedSize = OBJECT_POINTER_ALIGN(kHeaderSize);
// Maximal memory consumption for a single BytecodeArray. // Maximal memory consumption for a single BytecodeArray.
static const int kMaxSize = 512 * MB; static const int kMaxSize = 512 * MB;
// Maximal length of a single BytecodeArray. // Maximal length of a single BytecodeArray.
......
...@@ -4,7 +4,12 @@ ...@@ -4,7 +4,12 @@
#include "src/runtime/runtime-utils.h" #include "src/runtime/runtime-utils.h"
#include <iomanip>
#include "src/arguments.h" #include "src/arguments.h"
#include "src/frames-inl.h"
#include "src/interpreter/bytecode-array-iterator.h"
#include "src/interpreter/bytecodes.h"
#include "src/isolate-inl.h" #include "src/isolate-inl.h"
namespace v8 { namespace v8 {
...@@ -147,5 +152,106 @@ RUNTIME_FUNCTION(Runtime_InterpreterNewClosure) { ...@@ -147,5 +152,106 @@ RUNTIME_FUNCTION(Runtime_InterpreterNewClosure) {
shared, context, static_cast<PretenureFlag>(pretenured_flag)); shared, context, static_cast<PretenureFlag>(pretenured_flag));
} }
namespace {
void PrintRegisters(std::ostream& os, bool is_input,
Handle<BytecodeArray> bytecode_array, int bytecode_offset,
Handle<Object> accumulator) {
static const int kRegFieldWidth = static_cast<int>(strlen("accumulator"));
static const char* kInputColourCode = "\033[0;36m";
static const char* kOutputColourCode = "\033[0;35m";
static const char* kNormalColourCode = "\033[0;m";
const char* kArrowDirection = is_input ? " -> " : " <- ";
if (FLAG_log_colour) {
os << (is_input ? kInputColourCode : kOutputColourCode);
}
// Print accumulator.
os << " [ accumulator" << kArrowDirection;
accumulator->ShortPrint();
os << " ]" << std::endl;
// Find the location of the register file.
JavaScriptFrameIterator frame_iterator(bytecode_array->GetIsolate());
JavaScriptFrame* frame = frame_iterator.frame();
Address register_file =
frame->fp() + InterpreterFrameConstants::kRegisterFilePointerFromFp;
// Print the registers.
interpreter::BytecodeArrayIterator bytecode_iterator(bytecode_array);
bytecode_iterator.set_current_offset(
bytecode_offset - BytecodeArray::kHeaderSize + kHeapObjectTag);
interpreter::Bytecode bytecode = bytecode_iterator.current_bytecode();
int operand_count = interpreter::Bytecodes::NumberOfOperands(bytecode);
for (int operand_index = 0; operand_index < operand_count; operand_index++) {
interpreter::OperandType operand_type =
interpreter::Bytecodes::GetOperandType(bytecode, operand_index);
bool should_print =
is_input
? interpreter::Bytecodes::IsRegisterInputOperandType(operand_type)
: interpreter::Bytecodes::IsRegisterOutputOperandType(operand_type);
if (should_print) {
interpreter::Register first_reg =
bytecode_iterator.GetRegisterOperand(operand_index);
int range = bytecode_iterator.GetRegisterOperandRange(operand_index);
for (int reg_index = first_reg.index();
reg_index < first_reg.index() + range; reg_index++) {
Address reg_location = register_file - reg_index * kPointerSize;
Object* reg_object = Memory::Object_at(reg_location);
os << " [ " << std::setw(kRegFieldWidth)
<< interpreter::Register(reg_index).ToString(
bytecode_array->parameter_count())
<< kArrowDirection;
reg_object->ShortPrint(os);
os << " ]" << std::endl;
}
}
}
if (FLAG_log_colour) {
os << kNormalColourCode;
}
}
} // namespace
RUNTIME_FUNCTION(Runtime_InterpreterTraceBytecodeEntry) {
SealHandleScope shs(isolate);
DCHECK_EQ(3, args.length());
CONVERT_ARG_HANDLE_CHECKED(BytecodeArray, bytecode_array, 0);
CONVERT_SMI_ARG_CHECKED(bytecode_offset, 1);
CONVERT_ARG_HANDLE_CHECKED(Object, accumulator, 2);
OFStream os(stdout);
// Print bytecode.
const uint8_t* bytecode_address =
reinterpret_cast<const uint8_t*>(*bytecode_array) + bytecode_offset;
Vector<char> buf = Vector<char>::New(50);
SNPrintF(buf, "%p", bytecode_address);
os << " -> " << buf.start() << " (" << bytecode_offset << ") : ";
interpreter::Bytecodes::Decode(os, bytecode_address,
bytecode_array->parameter_count());
os << std::endl;
// Print all input registers and accumulator.
PrintRegisters(os, true, bytecode_array, bytecode_offset, accumulator);
os << std::flush;
return isolate->heap()->undefined_value();
}
RUNTIME_FUNCTION(Runtime_InterpreterTraceBytecodeExit) {
SealHandleScope shs(isolate);
DCHECK_EQ(3, args.length());
CONVERT_ARG_HANDLE_CHECKED(BytecodeArray, bytecode_array, 0);
CONVERT_SMI_ARG_CHECKED(bytecode_offset, 1);
CONVERT_ARG_HANDLE_CHECKED(Object, accumulator, 2);
OFStream os(stdout);
// Print all output registers and accumulator.
PrintRegisters(os, false, bytecode_array, bytecode_offset, accumulator);
os << std::flush;
return isolate->heap()->undefined_value();
}
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8
...@@ -209,7 +209,6 @@ namespace internal { ...@@ -209,7 +209,6 @@ namespace internal {
F(ForInNext, 4, 1) \ F(ForInNext, 4, 1) \
F(ForInStep, 1, 1) F(ForInStep, 1, 1)
#define FOR_EACH_INTRINSIC_INTERPRETER(F) \ #define FOR_EACH_INTRINSIC_INTERPRETER(F) \
F(InterpreterEquals, 2, 1) \ F(InterpreterEquals, 2, 1) \
F(InterpreterNotEquals, 2, 1) \ F(InterpreterNotEquals, 2, 1) \
...@@ -222,8 +221,9 @@ namespace internal { ...@@ -222,8 +221,9 @@ namespace internal {
F(InterpreterToBoolean, 1, 1) \ F(InterpreterToBoolean, 1, 1) \
F(InterpreterLogicalNot, 1, 1) \ F(InterpreterLogicalNot, 1, 1) \
F(InterpreterTypeOf, 1, 1) \ F(InterpreterTypeOf, 1, 1) \
F(InterpreterNewClosure, 2, 1) F(InterpreterNewClosure, 2, 1) \
F(InterpreterTraceBytecodeEntry, 3, 1) \
F(InterpreterTraceBytecodeExit, 3, 1)
#define FOR_EACH_INTRINSIC_FUNCTION(F) \ #define FOR_EACH_INTRINSIC_FUNCTION(F) \
F(FunctionGetName, 1, 1) \ F(FunctionGetName, 1, 1) \
......
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