runtime-interpreter.cc 7.15 KB
Newer Older
1 2 3 4 5 6
// 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.

#include "src/runtime/runtime-utils.h"

7 8
#include <iomanip>

9
#include "src/arguments.h"
10
#include "src/frames-inl.h"
11
#include "src/interpreter/bytecode-array-iterator.h"
12 13 14
#include "src/interpreter/bytecode-decoder.h"
#include "src/interpreter/bytecode-flags.h"
#include "src/interpreter/bytecode-register.h"
15
#include "src/interpreter/bytecodes.h"
16
#include "src/isolate-inl.h"
17
#include "src/ostreams.h"
18 19 20 21

namespace v8 {
namespace internal {

22 23
RUNTIME_FUNCTION(Runtime_InterpreterNewClosure) {
  HandleScope scope(isolate);
24
  DCHECK_EQ(4, args.length());
25
  CONVERT_ARG_HANDLE_CHECKED(SharedFunctionInfo, shared, 0);
26
  CONVERT_ARG_HANDLE_CHECKED(FeedbackVector, vector, 1);
27
  CONVERT_SMI_ARG_CHECKED(index, 2);
28
  CONVERT_SMI_ARG_CHECKED(pretenured_flag, 3);
29
  Handle<Context> context(isolate->context(), isolate);
30
  FeedbackSlot slot = FeedbackVector::ToSlot(index);
31
  Handle<Cell> vector_cell(Cell::cast(vector->Get(slot)), isolate);
32
  return *isolate->factory()->NewFunctionFromSharedFunctionInfo(
33 34
      shared, context, vector_cell,
      static_cast<PretenureFlag>(pretenured_flag));
35 36
}

37 38
#ifdef V8_TRACE_IGNITION

39 40
namespace {

41 42 43 44 45 46 47
void AdvanceToOffsetForTracing(
    interpreter::BytecodeArrayIterator& bytecode_iterator, int offset) {
  while (bytecode_iterator.current_offset() +
             bytecode_iterator.current_bytecode_size() <=
         offset) {
    bytecode_iterator.Advance();
  }
48 49 50 51
  DCHECK(bytecode_iterator.current_offset() == offset ||
         ((bytecode_iterator.current_offset() + 1) == offset &&
          bytecode_iterator.current_operand_scale() >
              interpreter::OperandScale::kSingle));
52 53
}

54
void PrintRegisters(std::ostream& os, bool is_input,
55
                    interpreter::BytecodeArrayIterator& bytecode_iterator,
56
                    Handle<Object> accumulator) {
57 58
  static const char kAccumulator[] = "accumulator";
  static const int kRegFieldWidth = static_cast<int>(sizeof(kAccumulator) - 1);
59 60 61 62 63 64 65 66
  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);
  }

67 68
  interpreter::Bytecode bytecode = bytecode_iterator.current_bytecode();

69
  // Print accumulator.
70 71 72 73 74 75
  if ((is_input && interpreter::Bytecodes::ReadsAccumulator(bytecode)) ||
      (!is_input && interpreter::Bytecodes::WritesAccumulator(bytecode))) {
    os << "      [ " << kAccumulator << kArrowDirection;
    accumulator->ShortPrint();
    os << " ]" << std::endl;
  }
76

77
  // Print the registers.
78 79
  JavaScriptFrameIterator frame_iterator(
      bytecode_iterator.bytecode_array()->GetIsolate());
80 81
  InterpretedFrame* frame =
      reinterpret_cast<InterpretedFrame*>(frame_iterator.frame());
82 83 84 85 86 87 88 89 90 91 92 93 94 95
  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++) {
96
        Object* reg_object = frame->ReadInterpreterRegister(reg_index);
97 98
        os << "      [ " << std::setw(kRegFieldWidth)
           << interpreter::Register(reg_index).ToString(
99
                  bytecode_iterator.bytecode_array()->parameter_count())
100 101 102 103 104 105 106 107 108 109 110 111 112 113
           << kArrowDirection;
        reg_object->ShortPrint(os);
        os << " ]" << std::endl;
      }
    }
  }
  if (FLAG_log_colour) {
    os << kNormalColourCode;
  }
}

}  // namespace

RUNTIME_FUNCTION(Runtime_InterpreterTraceBytecodeEntry) {
114 115 116 117
  if (!FLAG_trace_ignition) {
    return isolate->heap()->undefined_value();
  }

118 119 120 121 122 123
  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);

124 125 126 127
  int offset = bytecode_offset - BytecodeArray::kHeaderSize + kHeapObjectTag;
  interpreter::BytecodeArrayIterator bytecode_iterator(bytecode_array);
  AdvanceToOffsetForTracing(bytecode_iterator, offset);
  if (offset == bytecode_iterator.current_offset()) {
128 129
    OFStream os(stdout);

130
    // Print bytecode.
131 132 133 134
    const uint8_t* base_address = bytecode_array->GetFirstBytecodeAddress();
    const uint8_t* bytecode_address = base_address + offset;
    os << " -> " << static_cast<const void*>(bytecode_address) << " @ "
       << std::setw(4) << offset << " : ";
135 136
    interpreter::BytecodeDecoder::Decode(os, bytecode_address,
                                         bytecode_array->parameter_count());
137 138 139 140 141 142
    os << std::endl;
    // Print all input registers and accumulator.
    PrintRegisters(os, true, bytecode_iterator, accumulator);

    os << std::flush;
  }
143 144 145 146
  return isolate->heap()->undefined_value();
}

RUNTIME_FUNCTION(Runtime_InterpreterTraceBytecodeExit) {
147 148 149 150
  if (!FLAG_trace_ignition) {
    return isolate->heap()->undefined_value();
  }

151 152 153 154 155 156
  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);

157 158 159 160 161 162 163 164 165 166 167 168 169 170
  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()) {
    OFStream os(stdout);
    // Print all output registers and accumulator.
    PrintRegisters(os, false, bytecode_iterator, accumulator);
    os << std::flush;
  }
171 172 173
  return isolate->heap()->undefined_value();
}

174 175
#endif

176 177 178 179 180 181 182 183 184 185 186 187 188 189
RUNTIME_FUNCTION(Runtime_InterpreterAdvanceBytecodeOffset) {
  SealHandleScope shs(isolate);
  DCHECK_EQ(2, args.length());
  CONVERT_ARG_HANDLE_CHECKED(BytecodeArray, bytecode_array, 0);
  CONVERT_SMI_ARG_CHECKED(bytecode_offset, 1);
  interpreter::BytecodeArrayIterator it(bytecode_array);
  int offset = bytecode_offset - BytecodeArray::kHeaderSize + kHeapObjectTag;
  while (it.current_offset() < offset) it.Advance();
  DCHECK_EQ(offset, it.current_offset());
  it.Advance();  // Advance by one bytecode.
  offset = it.current_offset() + BytecodeArray::kHeaderSize - kHeapObjectTag;
  return Smi::FromInt(offset);
}

190 191
}  // namespace internal
}  // namespace v8