v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
runtime-trace.cc
Go to the documentation of this file.
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
19#include "src/utils/ostreams.h"
20
21namespace v8 {
22namespace internal {
23
24#ifdef V8_TRACE_UNOPTIMIZED
25
26namespace {
27
28void 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
41void PrintRegisterRange(UnoptimizedJSFrame* frame, std::ostream& os,
42 interpreter::BytecodeArrayIterator& bytecode_iterator,
43 const int& reg_field_width, const char* arrow_direction,
44 interpreter::Register first_reg, int range) {
45 for (int reg_index = first_reg.index(); reg_index < first_reg.index() + range;
46 reg_index++) {
47 Tagged<Object> reg_object = frame->ReadInterpreterRegister(reg_index);
48 os << " [ " << std::setw(reg_field_width)
49 << interpreter::Register(reg_index).ToString() << arrow_direction;
50 ShortPrint(reg_object, os);
51 os << " ]" << std::endl;
52 }
53}
54
55void PrintRegisters(UnoptimizedJSFrame* frame, std::ostream& os, bool is_input,
56 interpreter::BytecodeArrayIterator& bytecode_iterator,
57 Handle<Object> accumulator) {
58 static const char kAccumulator[] = "accumulator";
59 static const int kRegFieldWidth = static_cast<int>(sizeof(kAccumulator) - 1);
60 static const char* kInputColourCode = "\033[0;36m";
61 static const char* kOutputColourCode = "\033[0;35m";
62 static const char* kNormalColourCode = "\033[0;m";
63 const char* kArrowDirection = is_input ? " -> " : " <- ";
64 if (v8_flags.log_colour) {
65 os << (is_input ? kInputColourCode : kOutputColourCode);
66 }
67
68 interpreter::Bytecode bytecode = bytecode_iterator.current_bytecode();
69
70 // Print accumulator.
71 if ((is_input && interpreter::Bytecodes::ReadsAccumulator(bytecode)) ||
72 (!is_input &&
74 os << " [ " << kAccumulator << kArrowDirection;
75 ShortPrint(*accumulator, os);
76 os << " ]" << std::endl;
77 }
78
79 // Print the registers.
80 int operand_count = interpreter::Bytecodes::NumberOfOperands(bytecode);
81 for (int operand_index = 0; operand_index < operand_count; operand_index++) {
82 interpreter::OperandType operand_type =
83 interpreter::Bytecodes::GetOperandType(bytecode, operand_index);
84 bool should_print =
85 is_input
87 : interpreter::Bytecodes::IsRegisterOutputOperandType(operand_type);
88 if (should_print) {
89 interpreter::Register first_reg =
90 bytecode_iterator.GetRegisterOperand(operand_index);
91 int range = bytecode_iterator.GetRegisterOperandRange(operand_index);
92 PrintRegisterRange(frame, os, bytecode_iterator, kRegFieldWidth,
93 kArrowDirection, first_reg, range);
94 }
95 }
96 if (!is_input && interpreter::Bytecodes::IsShortStar(bytecode)) {
97 PrintRegisterRange(frame, os, bytecode_iterator, kRegFieldWidth,
98 kArrowDirection,
100 }
101 if (v8_flags.log_colour) {
102 os << kNormalColourCode;
103 }
104}
105
106} // namespace
107
108RUNTIME_FUNCTION(Runtime_TraceUnoptimizedBytecodeEntry) {
109 if (!v8_flags.trace_ignition && !v8_flags.trace_baseline_exec) {
110 return ReadOnlyRoots(isolate).undefined_value();
111 }
112
113 JavaScriptStackFrameIterator frame_iterator(isolate);
114 UnoptimizedJSFrame* frame =
115 reinterpret_cast<UnoptimizedJSFrame*>(frame_iterator.frame());
116
117 if (frame->is_interpreted() && !v8_flags.trace_ignition) {
118 return ReadOnlyRoots(isolate).undefined_value();
119 }
120 if (frame->is_baseline() && !v8_flags.trace_baseline_exec) {
121 return ReadOnlyRoots(isolate).undefined_value();
122 }
123
124 SealHandleScope shs(isolate);
125 DCHECK_EQ(3, args.length());
126 Handle<BytecodeArray> bytecode_array = args.at<BytecodeArray>(0);
127 int bytecode_offset = args.smi_value_at(1);
128 Handle<Object> accumulator = args.at(2);
129
130 int offset = bytecode_offset - BytecodeArray::kHeaderSize + kHeapObjectTag;
131 interpreter::BytecodeArrayIterator bytecode_iterator(bytecode_array);
132 AdvanceToOffsetForTracing(bytecode_iterator, offset);
133 if (offset == bytecode_iterator.current_offset()) {
134 StdoutStream os;
135
136 // Print bytecode.
137 const uint8_t* base_address = reinterpret_cast<const uint8_t*>(
138 bytecode_array->GetFirstBytecodeAddress());
139 const uint8_t* bytecode_address = base_address + offset;
140
141 if (frame->is_baseline()) {
142 os << "B-> ";
143 } else {
144 os << " -> ";
145 }
146 os << static_cast<const void*>(bytecode_address) << " @ " << std::setw(4)
147 << offset << " : ";
148 interpreter::BytecodeDecoder::Decode(os, bytecode_address);
149 os << std::endl;
150 // Print all input registers and accumulator.
151 PrintRegisters(frame, os, true, bytecode_iterator, accumulator);
152
153 os << std::flush;
154 }
155 return ReadOnlyRoots(isolate).undefined_value();
156}
157
158RUNTIME_FUNCTION(Runtime_TraceUnoptimizedBytecodeExit) {
159 if (!v8_flags.trace_ignition && !v8_flags.trace_baseline_exec) {
160 return ReadOnlyRoots(isolate).undefined_value();
161 }
162
163 JavaScriptStackFrameIterator frame_iterator(isolate);
164 UnoptimizedJSFrame* frame =
165 reinterpret_cast<UnoptimizedJSFrame*>(frame_iterator.frame());
166
167 if (frame->is_interpreted() && !v8_flags.trace_ignition) {
168 return ReadOnlyRoots(isolate).undefined_value();
169 }
170 if (frame->is_baseline() && !v8_flags.trace_baseline_exec) {
171 return ReadOnlyRoots(isolate).undefined_value();
172 }
173
174 SealHandleScope shs(isolate);
175 DCHECK_EQ(3, args.length());
176 Handle<BytecodeArray> bytecode_array = args.at<BytecodeArray>(0);
177 int bytecode_offset = args.smi_value_at(1);
178 Handle<Object> accumulator = args.at(2);
179
180 int offset = bytecode_offset - BytecodeArray::kHeaderSize + kHeapObjectTag;
181 interpreter::BytecodeArrayIterator bytecode_iterator(bytecode_array);
182 AdvanceToOffsetForTracing(bytecode_iterator, offset);
183 // The offset comparison here ensures registers only printed when the
184 // (potentially) widened bytecode has completed. The iterator reports
185 // the offset as the offset of the prefix bytecode.
186 if (bytecode_iterator.current_operand_scale() ==
187 interpreter::OperandScale::kSingle ||
188 offset > bytecode_iterator.current_offset()) {
189 StdoutStream os;
190
191 // Print all output registers and accumulator.
192 PrintRegisters(frame, os, false, bytecode_iterator, accumulator);
193 os << std::flush;
194 }
195 return ReadOnlyRoots(isolate).undefined_value();
196}
197
198#endif
199
200#ifdef V8_TRACE_FEEDBACK_UPDATES
201
202RUNTIME_FUNCTION(Runtime_TraceUpdateFeedback) {
203 if (!v8_flags.trace_feedback_updates) {
204 return ReadOnlyRoots(isolate).undefined_value();
205 }
206
207 SealHandleScope shs(isolate);
208 DCHECK_EQ(3, args.length());
209 Handle<FeedbackVector> vector = args.at<FeedbackVector>(0);
210 int slot = args.smi_value_at(1);
211 auto reason = Cast<String>(args[2]);
212
213 FeedbackVector::TraceFeedbackChange(isolate, *vector, FeedbackSlot(slot),
214 reason->ToCString().get());
215
216 return ReadOnlyRoots(isolate).undefined_value();
217}
218
219#endif
220
221} // namespace internal
222} // namespace v8
static constexpr int kHeaderSize
static std::ostream & Decode(std::ostream &os, const uint8_t *bytecode_start, bool with_hex=true)
static bool ReadsAccumulator(Bytecode bytecode)
Definition bytecodes.h:687
static OperandType GetOperandType(Bytecode bytecode, int i)
Definition bytecodes.h:894
static bool IsRegisterInputOperandType(OperandType operand_type)
Definition bytecodes.cc:222
static int NumberOfOperands(Bytecode bytecode)
Definition bytecodes.h:886
static constexpr bool IsShortStar(Bytecode bytecode)
Definition bytecodes.h:732
static bool WritesOrClobbersAccumulator(Bytecode bytecode)
Definition bytecodes.h:704
static constexpr Register FromShortStar(Bytecode bytecode)
#define RUNTIME_FUNCTION(Name)
Definition arguments.h:162
base::Vector< const DirectHandle< Object > > args
Definition execution.cc:74
int32_t offset
void ShortPrint(Tagged< Object > obj, FILE *out)
Definition objects.cc:1865
const int kHeapObjectTag
Definition v8-internal.h:72
V8_EXPORT_PRIVATE FlagValues v8_flags
Tagged< To > Cast(Tagged< From > value, const v8::SourceLocation &loc=INIT_SOURCE_LOCATION_IN_DEBUG)
Definition casting.h:150
Local< T > Handle
#define DCHECK(condition)
Definition logging.h:482
#define DCHECK_EQ(v1, v2)
Definition logging.h:485