V8 API Reference, 7.2.502.16 (for Deno 0.2.4)
runtime-interpreter.cc
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 } // namespace v8
Definition: libplatform.h:13