Line data Source code
1 : // 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 <iomanip>
6 :
7 : #include "src/arguments-inl.h"
8 : #include "src/counters.h"
9 : #include "src/frames-inl.h"
10 : #include "src/interpreter/bytecode-array-iterator.h"
11 : #include "src/interpreter/bytecode-decoder.h"
12 : #include "src/interpreter/bytecode-flags.h"
13 : #include "src/interpreter/bytecode-register.h"
14 : #include "src/interpreter/bytecodes.h"
15 : #include "src/interpreter/interpreter.h"
16 : #include "src/isolate-inl.h"
17 : #include "src/ostreams.h"
18 : #include "src/runtime/runtime-utils.h"
19 : #include "src/snapshot/snapshot.h"
20 :
21 : namespace v8 {
22 : namespace internal {
23 :
24 : #ifdef V8_TRACE_IGNITION
25 :
26 : namespace {
27 :
28 : void AdvanceToOffsetForTracing(
29 : interpreter::BytecodeArrayIterator& bytecode_iterator, int offset) {
30 : while (bytecode_iterator.current_offset() +
31 : bytecode_iterator.current_bytecode_size() <=
32 : offset) {
33 : bytecode_iterator.Advance();
34 : }
35 : DCHECK(bytecode_iterator.current_offset() == offset ||
36 : ((bytecode_iterator.current_offset() + 1) == offset &&
37 : bytecode_iterator.current_operand_scale() >
38 : interpreter::OperandScale::kSingle));
39 : }
40 :
41 : void PrintRegisters(Isolate* isolate, std::ostream& os, bool is_input,
42 : interpreter::BytecodeArrayIterator& bytecode_iterator,
43 : Handle<Object> accumulator) {
44 : static const char kAccumulator[] = "accumulator";
45 : static const int kRegFieldWidth = static_cast<int>(sizeof(kAccumulator) - 1);
46 : static const char* kInputColourCode = "\033[0;36m";
47 : static const char* kOutputColourCode = "\033[0;35m";
48 : static const char* kNormalColourCode = "\033[0;m";
49 : const char* kArrowDirection = is_input ? " -> " : " <- ";
50 : if (FLAG_log_colour) {
51 : os << (is_input ? kInputColourCode : kOutputColourCode);
52 : }
53 :
54 : interpreter::Bytecode bytecode = bytecode_iterator.current_bytecode();
55 :
56 : // Print accumulator.
57 : if ((is_input && interpreter::Bytecodes::ReadsAccumulator(bytecode)) ||
58 : (!is_input && interpreter::Bytecodes::WritesAccumulator(bytecode))) {
59 : os << " [ " << kAccumulator << kArrowDirection;
60 : accumulator->ShortPrint();
61 : os << " ]" << std::endl;
62 : }
63 :
64 : // Print the registers.
65 : JavaScriptFrameIterator frame_iterator(isolate);
66 : InterpretedFrame* frame =
67 : reinterpret_cast<InterpretedFrame*>(frame_iterator.frame());
68 : int operand_count = interpreter::Bytecodes::NumberOfOperands(bytecode);
69 : for (int operand_index = 0; operand_index < operand_count; operand_index++) {
70 : interpreter::OperandType operand_type =
71 : interpreter::Bytecodes::GetOperandType(bytecode, operand_index);
72 : bool should_print =
73 : is_input
74 : ? interpreter::Bytecodes::IsRegisterInputOperandType(operand_type)
75 : : interpreter::Bytecodes::IsRegisterOutputOperandType(operand_type);
76 : if (should_print) {
77 : interpreter::Register first_reg =
78 : bytecode_iterator.GetRegisterOperand(operand_index);
79 : int range = bytecode_iterator.GetRegisterOperandRange(operand_index);
80 : for (int reg_index = first_reg.index();
81 : reg_index < first_reg.index() + range; reg_index++) {
82 : Object reg_object = frame->ReadInterpreterRegister(reg_index);
83 : os << " [ " << std::setw(kRegFieldWidth)
84 : << interpreter::Register(reg_index).ToString(
85 : bytecode_iterator.bytecode_array()->parameter_count())
86 : << kArrowDirection;
87 : reg_object->ShortPrint(os);
88 : os << " ]" << std::endl;
89 : }
90 : }
91 : }
92 : if (FLAG_log_colour) {
93 : os << kNormalColourCode;
94 : }
95 : }
96 :
97 : } // namespace
98 :
99 : RUNTIME_FUNCTION(Runtime_InterpreterTraceBytecodeEntry) {
100 : if (!FLAG_trace_ignition) {
101 : return ReadOnlyRoots(isolate).undefined_value();
102 : }
103 :
104 : SealHandleScope shs(isolate);
105 : DCHECK_EQ(3, args.length());
106 : CONVERT_ARG_HANDLE_CHECKED(BytecodeArray, bytecode_array, 0);
107 : CONVERT_SMI_ARG_CHECKED(bytecode_offset, 1);
108 : CONVERT_ARG_HANDLE_CHECKED(Object, accumulator, 2);
109 :
110 : int offset = bytecode_offset - BytecodeArray::kHeaderSize + kHeapObjectTag;
111 : interpreter::BytecodeArrayIterator bytecode_iterator(bytecode_array);
112 : AdvanceToOffsetForTracing(bytecode_iterator, offset);
113 : if (offset == bytecode_iterator.current_offset()) {
114 : StdoutStream os;
115 :
116 : // Print bytecode.
117 : const uint8_t* base_address = reinterpret_cast<const uint8_t*>(
118 : bytecode_array->GetFirstBytecodeAddress());
119 : const uint8_t* bytecode_address = base_address + offset;
120 : os << " -> " << static_cast<const void*>(bytecode_address) << " @ "
121 : << std::setw(4) << offset << " : ";
122 : interpreter::BytecodeDecoder::Decode(os, bytecode_address,
123 : bytecode_array->parameter_count());
124 : os << std::endl;
125 : // Print all input registers and accumulator.
126 : PrintRegisters(isolate, os, true, bytecode_iterator, accumulator);
127 :
128 : os << std::flush;
129 : }
130 : return ReadOnlyRoots(isolate).undefined_value();
131 : }
132 :
133 : RUNTIME_FUNCTION(Runtime_InterpreterTraceBytecodeExit) {
134 : if (!FLAG_trace_ignition) {
135 : return ReadOnlyRoots(isolate).undefined_value();
136 : }
137 :
138 : SealHandleScope shs(isolate);
139 : DCHECK_EQ(3, args.length());
140 : CONVERT_ARG_HANDLE_CHECKED(BytecodeArray, bytecode_array, 0);
141 : CONVERT_SMI_ARG_CHECKED(bytecode_offset, 1);
142 : CONVERT_ARG_HANDLE_CHECKED(Object, accumulator, 2);
143 :
144 : int offset = bytecode_offset - BytecodeArray::kHeaderSize + kHeapObjectTag;
145 : interpreter::BytecodeArrayIterator bytecode_iterator(bytecode_array);
146 : AdvanceToOffsetForTracing(bytecode_iterator, offset);
147 : // The offset comparison here ensures registers only printed when the
148 : // (potentially) widened bytecode has completed. The iterator reports
149 : // the offset as the offset of the prefix bytecode.
150 : if (bytecode_iterator.current_operand_scale() ==
151 : interpreter::OperandScale::kSingle ||
152 : offset > bytecode_iterator.current_offset()) {
153 : StdoutStream os;
154 : // Print all output registers and accumulator.
155 : PrintRegisters(isolate, os, false, bytecode_iterator, accumulator);
156 : os << std::flush;
157 : }
158 : return ReadOnlyRoots(isolate).undefined_value();
159 : }
160 :
161 : #endif
162 :
163 : #ifdef V8_TRACE_FEEDBACK_UPDATES
164 :
165 : RUNTIME_FUNCTION(Runtime_InterpreterTraceUpdateFeedback) {
166 : if (!FLAG_trace_feedback_updates) {
167 : return ReadOnlyRoots(isolate).undefined_value();
168 : }
169 :
170 : SealHandleScope shs(isolate);
171 : DCHECK_EQ(3, args.length());
172 : CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
173 : CONVERT_SMI_ARG_CHECKED(slot, 1);
174 : CONVERT_ARG_CHECKED(String, reason, 2);
175 :
176 : int slot_count = function->feedback_vector()->metadata()->slot_count();
177 :
178 : StdoutStream os;
179 : os << "[Feedback slot " << slot << "/" << slot_count << " in ";
180 : function->shared()->ShortPrint(os);
181 : os << " updated to ";
182 : function->feedback_vector()->FeedbackSlotPrint(os, FeedbackSlot(slot));
183 : os << " - ";
184 :
185 : StringCharacterStream stream(reason);
186 : while (stream.HasMore()) {
187 : uint16_t character = stream.GetNext();
188 : PrintF("%c", character);
189 : }
190 :
191 : os << "]" << std::endl;
192 :
193 : return ReadOnlyRoots(isolate).undefined_value();
194 : }
195 :
196 : #endif
197 :
198 : } // namespace internal
199 178779 : } // namespace v8
|