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