blob: 22ae9113d81cf087e1c526a17f227ad349153973 [file] [log] [blame]
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001// Copyright 2015 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "src/runtime/runtime-utils.h"
6
Ben Murdoch097c5b22016-05-18 11:27:45 +01007#include <iomanip>
8
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009#include "src/arguments.h"
Ben Murdoch097c5b22016-05-18 11:27:45 +010010#include "src/frames-inl.h"
11#include "src/interpreter/bytecode-array-iterator.h"
12#include "src/interpreter/bytecodes.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013#include "src/isolate-inl.h"
Ben Murdoch097c5b22016-05-18 11:27:45 +010014#include "src/ostreams.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015
16namespace v8 {
17namespace internal {
18
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019RUNTIME_FUNCTION(Runtime_InterpreterNewClosure) {
20 HandleScope scope(isolate);
21 DCHECK_EQ(2, args.length());
22 CONVERT_ARG_HANDLE_CHECKED(SharedFunctionInfo, shared, 0);
23 CONVERT_SMI_ARG_CHECKED(pretenured_flag, 1);
24 Handle<Context> context(isolate->context(), isolate);
25 return *isolate->factory()->NewFunctionFromSharedFunctionInfo(
26 shared, context, static_cast<PretenureFlag>(pretenured_flag));
27}
28
Ben Murdoch097c5b22016-05-18 11:27:45 +010029namespace {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000030
Ben Murdochda12d292016-06-02 14:46:10 +010031void AdvanceToOffsetForTracing(
32 interpreter::BytecodeArrayIterator& bytecode_iterator, int offset) {
33 while (bytecode_iterator.current_offset() +
34 bytecode_iterator.current_bytecode_size() <=
35 offset) {
36 bytecode_iterator.Advance();
37 }
38 DCHECK(bytecode_iterator.current_offset() == offset ||
39 ((bytecode_iterator.current_offset() + 1) == offset &&
40 bytecode_iterator.current_operand_scale() >
41 interpreter::OperandScale::kSingle));
42}
43
Ben Murdoch097c5b22016-05-18 11:27:45 +010044void PrintRegisters(std::ostream& os, bool is_input,
Ben Murdochda12d292016-06-02 14:46:10 +010045 interpreter::BytecodeArrayIterator& bytecode_iterator,
Ben Murdoch097c5b22016-05-18 11:27:45 +010046 Handle<Object> accumulator) {
Ben Murdochda12d292016-06-02 14:46:10 +010047 static const char kAccumulator[] = "accumulator";
48 static const int kRegFieldWidth = static_cast<int>(sizeof(kAccumulator) - 1);
Ben Murdoch097c5b22016-05-18 11:27:45 +010049 static const char* kInputColourCode = "\033[0;36m";
50 static const char* kOutputColourCode = "\033[0;35m";
51 static const char* kNormalColourCode = "\033[0;m";
52 const char* kArrowDirection = is_input ? " -> " : " <- ";
53 if (FLAG_log_colour) {
54 os << (is_input ? kInputColourCode : kOutputColourCode);
55 }
56
Ben Murdochda12d292016-06-02 14:46:10 +010057 interpreter::Bytecode bytecode = bytecode_iterator.current_bytecode();
58
Ben Murdoch097c5b22016-05-18 11:27:45 +010059 // Print accumulator.
Ben Murdochda12d292016-06-02 14:46:10 +010060 if ((is_input && interpreter::Bytecodes::ReadsAccumulator(bytecode)) ||
61 (!is_input && interpreter::Bytecodes::WritesAccumulator(bytecode))) {
62 os << " [ " << kAccumulator << kArrowDirection;
63 accumulator->ShortPrint();
64 os << " ]" << std::endl;
65 }
Ben Murdoch097c5b22016-05-18 11:27:45 +010066
67 // Find the location of the register file.
Ben Murdochda12d292016-06-02 14:46:10 +010068 JavaScriptFrameIterator frame_iterator(
69 bytecode_iterator.bytecode_array()->GetIsolate());
Ben Murdoch097c5b22016-05-18 11:27:45 +010070 JavaScriptFrame* frame = frame_iterator.frame();
71 Address register_file =
72 frame->fp() + InterpreterFrameConstants::kRegisterFilePointerFromFp;
73
74 // Print the registers.
Ben Murdoch097c5b22016-05-18 11:27:45 +010075 int operand_count = interpreter::Bytecodes::NumberOfOperands(bytecode);
76 for (int operand_index = 0; operand_index < operand_count; operand_index++) {
77 interpreter::OperandType operand_type =
78 interpreter::Bytecodes::GetOperandType(bytecode, operand_index);
79 bool should_print =
80 is_input
81 ? interpreter::Bytecodes::IsRegisterInputOperandType(operand_type)
82 : interpreter::Bytecodes::IsRegisterOutputOperandType(operand_type);
83 if (should_print) {
84 interpreter::Register first_reg =
85 bytecode_iterator.GetRegisterOperand(operand_index);
86 int range = bytecode_iterator.GetRegisterOperandRange(operand_index);
87 for (int reg_index = first_reg.index();
88 reg_index < first_reg.index() + range; reg_index++) {
89 Address reg_location = register_file - reg_index * kPointerSize;
90 Object* reg_object = Memory::Object_at(reg_location);
91 os << " [ " << std::setw(kRegFieldWidth)
92 << interpreter::Register(reg_index).ToString(
Ben Murdochda12d292016-06-02 14:46:10 +010093 bytecode_iterator.bytecode_array()->parameter_count())
Ben Murdoch097c5b22016-05-18 11:27:45 +010094 << kArrowDirection;
95 reg_object->ShortPrint(os);
96 os << " ]" << std::endl;
97 }
98 }
99 }
100 if (FLAG_log_colour) {
101 os << kNormalColourCode;
102 }
103}
104
105} // namespace
106
107RUNTIME_FUNCTION(Runtime_InterpreterTraceBytecodeEntry) {
108 SealHandleScope shs(isolate);
109 DCHECK_EQ(3, args.length());
110 CONVERT_ARG_HANDLE_CHECKED(BytecodeArray, bytecode_array, 0);
111 CONVERT_SMI_ARG_CHECKED(bytecode_offset, 1);
112 CONVERT_ARG_HANDLE_CHECKED(Object, accumulator, 2);
113 OFStream os(stdout);
114
Ben Murdochda12d292016-06-02 14:46:10 +0100115 int offset = bytecode_offset - BytecodeArray::kHeaderSize + kHeapObjectTag;
116 interpreter::BytecodeArrayIterator bytecode_iterator(bytecode_array);
117 AdvanceToOffsetForTracing(bytecode_iterator, offset);
118 if (offset == bytecode_iterator.current_offset()) {
119 // Print bytecode.
120 const uint8_t* bytecode_address =
121 reinterpret_cast<const uint8_t*>(*bytecode_array) + bytecode_offset;
122 os << " -> " << static_cast<const void*>(bytecode_address)
123 << " (" << bytecode_offset << ") : ";
124 interpreter::Bytecodes::Decode(os, bytecode_address,
125 bytecode_array->parameter_count());
126 os << std::endl;
127 // Print all input registers and accumulator.
128 PrintRegisters(os, true, bytecode_iterator, accumulator);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100129
Ben Murdochda12d292016-06-02 14:46:10 +0100130 os << std::flush;
131 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100132 return isolate->heap()->undefined_value();
133}
134
135RUNTIME_FUNCTION(Runtime_InterpreterTraceBytecodeExit) {
136 SealHandleScope shs(isolate);
137 DCHECK_EQ(3, args.length());
138 CONVERT_ARG_HANDLE_CHECKED(BytecodeArray, bytecode_array, 0);
139 CONVERT_SMI_ARG_CHECKED(bytecode_offset, 1);
140 CONVERT_ARG_HANDLE_CHECKED(Object, accumulator, 2);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100141
Ben Murdochda12d292016-06-02 14:46:10 +0100142 int offset = bytecode_offset - BytecodeArray::kHeaderSize + kHeapObjectTag;
143 interpreter::BytecodeArrayIterator bytecode_iterator(bytecode_array);
144 AdvanceToOffsetForTracing(bytecode_iterator, offset);
145 // The offset comparison here ensures registers only printed when the
146 // (potentially) widened bytecode has completed. The iterator reports
147 // the offset as the offset of the prefix bytecode.
148 if (bytecode_iterator.current_operand_scale() ==
149 interpreter::OperandScale::kSingle ||
150 offset > bytecode_iterator.current_offset()) {
151 OFStream os(stdout);
152 // Print all output registers and accumulator.
153 PrintRegisters(os, false, bytecode_iterator, accumulator);
154 os << std::flush;
155 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100156 return isolate->heap()->undefined_value();
157}
158
159RUNTIME_FUNCTION(Runtime_InterpreterClearPendingMessage) {
160 SealHandleScope shs(isolate);
161 DCHECK_EQ(0, args.length());
162 Object* message = isolate->thread_local_top()->pending_message_obj_;
163 isolate->clear_pending_message();
164 return message;
165}
166
167RUNTIME_FUNCTION(Runtime_InterpreterSetPendingMessage) {
168 SealHandleScope shs(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000169 DCHECK_EQ(1, args.length());
Ben Murdoch097c5b22016-05-18 11:27:45 +0100170 CONVERT_ARG_HANDLE_CHECKED(Object, message, 0);
171 isolate->thread_local_top()->pending_message_obj_ = *message;
172 return isolate->heap()->undefined_value();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000173}
174
175} // namespace internal
176} // namespace v8