runtime-interpreter.cc 7.11 KB
Newer Older
1 2 3 4
// Copyright 2015 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

5 6
#include <iomanip>

7 8 9
#include "src/execution/arguments-inl.h"
#include "src/execution/frames-inl.h"
#include "src/execution/isolate-inl.h"
10
#include "src/interpreter/bytecode-array-iterator.h"
11 12 13
#include "src/interpreter/bytecode-decoder.h"
#include "src/interpreter/bytecode-flags.h"
#include "src/interpreter/bytecode-register.h"
14
#include "src/interpreter/bytecodes.h"
15
#include "src/interpreter/interpreter.h"
16
#include "src/logging/counters.h"
17
#include "src/runtime/runtime-utils.h"
18
#include "src/snapshot/snapshot.h"
19
#include "src/utils/ostreams.h"
20 21 22 23

namespace v8 {
namespace internal {

24 25
#ifdef V8_TRACE_IGNITION

26 27
namespace {

28
void AdvanceToOffsetForTracing(
29 30 31
    interpreter::BytecodeArrayIterator&
        bytecode_iterator,  // NOLINT(runtime/references)
    int offset) {
32 33 34 35 36
  while (bytecode_iterator.current_offset() +
             bytecode_iterator.current_bytecode_size() <=
         offset) {
    bytecode_iterator.Advance();
  }
37 38 39 40
  DCHECK(bytecode_iterator.current_offset() == offset ||
         ((bytecode_iterator.current_offset() + 1) == offset &&
          bytecode_iterator.current_operand_scale() >
              interpreter::OperandScale::kSingle));
41 42
}

43
void PrintRegisters(Isolate* isolate, std::ostream& os, bool is_input,
44 45
                    interpreter::BytecodeArrayIterator&
                        bytecode_iterator,  // NOLINT(runtime/references)
46
                    Handle<Object> accumulator) {
47 48
  static const char kAccumulator[] = "accumulator";
  static const int kRegFieldWidth = static_cast<int>(sizeof(kAccumulator) - 1);
49 50 51 52 53 54 55 56
  static const char* kInputColourCode = "\033[0;36m";
  static const char* kOutputColourCode = "\033[0;35m";
  static const char* kNormalColourCode = "\033[0;m";
  const char* kArrowDirection = is_input ? " -> " : " <- ";
  if (FLAG_log_colour) {
    os << (is_input ? kInputColourCode : kOutputColourCode);
  }

57 58
  interpreter::Bytecode bytecode = bytecode_iterator.current_bytecode();

59
  // Print accumulator.
60 61 62 63 64 65
  if ((is_input && interpreter::Bytecodes::ReadsAccumulator(bytecode)) ||
      (!is_input && interpreter::Bytecodes::WritesAccumulator(bytecode))) {
    os << "      [ " << kAccumulator << kArrowDirection;
    accumulator->ShortPrint();
    os << " ]" << std::endl;
  }
66

67
  // Print the registers.
68
  JavaScriptFrameIterator frame_iterator(isolate);
69 70
  InterpretedFrame* frame =
      reinterpret_cast<InterpretedFrame*>(frame_iterator.frame());
71 72 73 74 75 76 77 78 79 80 81 82 83 84
  int operand_count = interpreter::Bytecodes::NumberOfOperands(bytecode);
  for (int operand_index = 0; operand_index < operand_count; operand_index++) {
    interpreter::OperandType operand_type =
        interpreter::Bytecodes::GetOperandType(bytecode, operand_index);
    bool should_print =
        is_input
            ? interpreter::Bytecodes::IsRegisterInputOperandType(operand_type)
            : interpreter::Bytecodes::IsRegisterOutputOperandType(operand_type);
    if (should_print) {
      interpreter::Register first_reg =
          bytecode_iterator.GetRegisterOperand(operand_index);
      int range = bytecode_iterator.GetRegisterOperandRange(operand_index);
      for (int reg_index = first_reg.index();
           reg_index < first_reg.index() + range; reg_index++) {
85
        Object reg_object = frame->ReadInterpreterRegister(reg_index);
86 87
        os << "      [ " << std::setw(kRegFieldWidth)
           << interpreter::Register(reg_index).ToString(
88
                  bytecode_iterator.bytecode_array()->parameter_count())
89
           << kArrowDirection;
90
        reg_object.ShortPrint(os);
91 92 93 94 95 96 97 98 99 100 101 102
        os << " ]" << std::endl;
      }
    }
  }
  if (FLAG_log_colour) {
    os << kNormalColourCode;
  }
}

}  // namespace

RUNTIME_FUNCTION(Runtime_InterpreterTraceBytecodeEntry) {
103
  if (!FLAG_trace_ignition) {
104
    return ReadOnlyRoots(isolate).undefined_value();
105 106
  }

107 108 109 110 111 112
  SealHandleScope shs(isolate);
  DCHECK_EQ(3, args.length());
  CONVERT_ARG_HANDLE_CHECKED(BytecodeArray, bytecode_array, 0);
  CONVERT_SMI_ARG_CHECKED(bytecode_offset, 1);
  CONVERT_ARG_HANDLE_CHECKED(Object, accumulator, 2);

113 114 115 116
  int offset = bytecode_offset - BytecodeArray::kHeaderSize + kHeapObjectTag;
  interpreter::BytecodeArrayIterator bytecode_iterator(bytecode_array);
  AdvanceToOffsetForTracing(bytecode_iterator, offset);
  if (offset == bytecode_iterator.current_offset()) {
117
    StdoutStream os;
118

119
    // Print bytecode.
120 121
    const uint8_t* base_address = reinterpret_cast<const uint8_t*>(
        bytecode_array->GetFirstBytecodeAddress());
122 123 124
    const uint8_t* bytecode_address = base_address + offset;
    os << " -> " << static_cast<const void*>(bytecode_address) << " @ "
       << std::setw(4) << offset << " : ";
125 126
    interpreter::BytecodeDecoder::Decode(os, bytecode_address,
                                         bytecode_array->parameter_count());
127 128
    os << std::endl;
    // Print all input registers and accumulator.
129
    PrintRegisters(isolate, os, true, bytecode_iterator, accumulator);
130 131 132

    os << std::flush;
  }
133
  return ReadOnlyRoots(isolate).undefined_value();
134 135 136
}

RUNTIME_FUNCTION(Runtime_InterpreterTraceBytecodeExit) {
137
  if (!FLAG_trace_ignition) {
138
    return ReadOnlyRoots(isolate).undefined_value();
139 140
  }

141 142 143 144 145 146
  SealHandleScope shs(isolate);
  DCHECK_EQ(3, args.length());
  CONVERT_ARG_HANDLE_CHECKED(BytecodeArray, bytecode_array, 0);
  CONVERT_SMI_ARG_CHECKED(bytecode_offset, 1);
  CONVERT_ARG_HANDLE_CHECKED(Object, accumulator, 2);

147 148 149 150 151 152 153 154 155
  int offset = bytecode_offset - BytecodeArray::kHeaderSize + kHeapObjectTag;
  interpreter::BytecodeArrayIterator bytecode_iterator(bytecode_array);
  AdvanceToOffsetForTracing(bytecode_iterator, offset);
  // The offset comparison here ensures registers only printed when the
  // (potentially) widened bytecode has completed. The iterator reports
  // the offset as the offset of the prefix bytecode.
  if (bytecode_iterator.current_operand_scale() ==
          interpreter::OperandScale::kSingle ||
      offset > bytecode_iterator.current_offset()) {
156
    StdoutStream os;
157
    // Print all output registers and accumulator.
158
    PrintRegisters(isolate, os, false, bytecode_iterator, accumulator);
159 160
    os << std::flush;
  }
161
  return ReadOnlyRoots(isolate).undefined_value();
162 163
}

164 165
#endif

166 167 168 169
#ifdef V8_TRACE_FEEDBACK_UPDATES

RUNTIME_FUNCTION(Runtime_InterpreterTraceUpdateFeedback) {
  if (!FLAG_trace_feedback_updates) {
170
    return ReadOnlyRoots(isolate).undefined_value();
171 172 173 174 175 176 177 178
  }

  SealHandleScope shs(isolate);
  DCHECK_EQ(3, args.length());
  CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
  CONVERT_SMI_ARG_CHECKED(slot, 1);
  CONVERT_ARG_CHECKED(String, reason, 2);

179
  int slot_count = function->feedback_vector().metadata().slot_count();
180

181
  StdoutStream os;
182
  os << "[Feedback slot " << slot << "/" << slot_count << " in ";
183
  function->shared().ShortPrint(os);
184
  os << " updated to ";
185
  function->feedback_vector().FeedbackSlotPrint(os, FeedbackSlot(slot));
186 187 188 189 190 191 192 193 194 195
  os << " - ";

  StringCharacterStream stream(reason);
  while (stream.HasMore()) {
    uint16_t character = stream.GetNext();
    PrintF("%c", character);
  }

  os << "]" << std::endl;

196
  return ReadOnlyRoots(isolate).undefined_value();
197 198 199 200
}

#endif

201 202
}  // namespace internal
}  // namespace v8