Home | History | Annotate | Download | only in runtime
      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 "src/runtime/runtime-utils.h"
      6 
      7 #include <iomanip>
      8 
      9 #include "src/arguments.h"
     10 #include "src/frames-inl.h"
     11 #include "src/interpreter/bytecode-array-iterator.h"
     12 #include "src/interpreter/bytecode-decoder.h"
     13 #include "src/interpreter/bytecode-flags.h"
     14 #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 namespace v8 {
     20 namespace internal {
     21 
     22 RUNTIME_FUNCTION(Runtime_InterpreterNewClosure) {
     23   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       shared, context, vector_cell,
     34       static_cast<PretenureFlag>(pretenured_flag));
     35 }
     36 
     37 namespace {
     38 
     39 void AdvanceToOffsetForTracing(
     40     interpreter::BytecodeArrayIterator& bytecode_iterator, int offset) {
     41   while (bytecode_iterator.current_offset() +
     42              bytecode_iterator.current_bytecode_size() <=
     43          offset) {
     44     bytecode_iterator.Advance();
     45   }
     46   DCHECK(bytecode_iterator.current_offset() == offset ||
     47          ((bytecode_iterator.current_offset() + 1) == offset &&
     48           bytecode_iterator.current_operand_scale() >
     49               interpreter::OperandScale::kSingle));
     50 }
     51 
     52 void PrintRegisters(std::ostream& os, bool is_input,
     53                     interpreter::BytecodeArrayIterator& bytecode_iterator,
     54                     Handle<Object> accumulator) {
     55   static const char kAccumulator[] = "accumulator";
     56   static const int kRegFieldWidth = static_cast<int>(sizeof(kAccumulator) - 1);
     57   static const char* kInputColourCode = "\033[0;36m";
     58   static const char* kOutputColourCode = "\033[0;35m";
     59   static const char* kNormalColourCode = "\033[0;m";
     60   const char* kArrowDirection = is_input ? " -> " : " <- ";
     61   if (FLAG_log_colour) {
     62     os << (is_input ? kInputColourCode : kOutputColourCode);
     63   }
     64 
     65   interpreter::Bytecode bytecode = bytecode_iterator.current_bytecode();
     66 
     67   // Print accumulator.
     68   if ((is_input && interpreter::Bytecodes::ReadsAccumulator(bytecode)) ||
     69       (!is_input && interpreter::Bytecodes::WritesAccumulator(bytecode))) {
     70     os << "      [ " << kAccumulator << kArrowDirection;
     71     accumulator->ShortPrint();
     72     os << " ]" << std::endl;
     73   }
     74 
     75   // Print the registers.
     76   JavaScriptFrameIterator frame_iterator(
     77       bytecode_iterator.bytecode_array()->GetIsolate());
     78   InterpretedFrame* frame =
     79       reinterpret_cast<InterpretedFrame*>(frame_iterator.frame());
     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
     86             ? interpreter::Bytecodes::IsRegisterInputOperandType(operand_type)
     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       for (int reg_index = first_reg.index();
     93            reg_index < first_reg.index() + range; reg_index++) {
     94         Object* reg_object = frame->ReadInterpreterRegister(reg_index);
     95         os << "      [ " << std::setw(kRegFieldWidth)
     96            << interpreter::Register(reg_index).ToString(
     97                   bytecode_iterator.bytecode_array()->parameter_count())
     98            << kArrowDirection;
     99         reg_object->ShortPrint(os);
    100         os << " ]" << std::endl;
    101       }
    102     }
    103   }
    104   if (FLAG_log_colour) {
    105     os << kNormalColourCode;
    106   }
    107 }
    108 
    109 }  // namespace
    110 
    111 RUNTIME_FUNCTION(Runtime_InterpreterTraceBytecodeEntry) {
    112   SealHandleScope shs(isolate);
    113   DCHECK_EQ(3, args.length());
    114   CONVERT_ARG_HANDLE_CHECKED(BytecodeArray, bytecode_array, 0);
    115   CONVERT_SMI_ARG_CHECKED(bytecode_offset, 1);
    116   CONVERT_ARG_HANDLE_CHECKED(Object, accumulator, 2);
    117   OFStream os(stdout);
    118 
    119   int offset = bytecode_offset - BytecodeArray::kHeaderSize + kHeapObjectTag;
    120   interpreter::BytecodeArrayIterator bytecode_iterator(bytecode_array);
    121   AdvanceToOffsetForTracing(bytecode_iterator, offset);
    122   if (offset == bytecode_iterator.current_offset()) {
    123     // Print bytecode.
    124     const uint8_t* base_address = bytecode_array->GetFirstBytecodeAddress();
    125     const uint8_t* bytecode_address = base_address + offset;
    126     os << " -> " << static_cast<const void*>(bytecode_address) << " @ "
    127        << std::setw(4) << offset << " : ";
    128     interpreter::BytecodeDecoder::Decode(os, bytecode_address,
    129                                          bytecode_array->parameter_count());
    130     os << std::endl;
    131     // Print all input registers and accumulator.
    132     PrintRegisters(os, true, bytecode_iterator, accumulator);
    133 
    134     os << std::flush;
    135   }
    136   return isolate->heap()->undefined_value();
    137 }
    138 
    139 RUNTIME_FUNCTION(Runtime_InterpreterTraceBytecodeExit) {
    140   SealHandleScope shs(isolate);
    141   DCHECK_EQ(3, args.length());
    142   CONVERT_ARG_HANDLE_CHECKED(BytecodeArray, bytecode_array, 0);
    143   CONVERT_SMI_ARG_CHECKED(bytecode_offset, 1);
    144   CONVERT_ARG_HANDLE_CHECKED(Object, accumulator, 2);
    145 
    146   int offset = bytecode_offset - BytecodeArray::kHeaderSize + kHeapObjectTag;
    147   interpreter::BytecodeArrayIterator bytecode_iterator(bytecode_array);
    148   AdvanceToOffsetForTracing(bytecode_iterator, offset);
    149   // The offset comparison here ensures registers only printed when the
    150   // (potentially) widened bytecode has completed. The iterator reports
    151   // the offset as the offset of the prefix bytecode.
    152   if (bytecode_iterator.current_operand_scale() ==
    153           interpreter::OperandScale::kSingle ||
    154       offset > bytecode_iterator.current_offset()) {
    155     OFStream os(stdout);
    156     // Print all output registers and accumulator.
    157     PrintRegisters(os, false, bytecode_iterator, accumulator);
    158     os << std::flush;
    159   }
    160   return isolate->heap()->undefined_value();
    161 }
    162 
    163 RUNTIME_FUNCTION(Runtime_InterpreterAdvanceBytecodeOffset) {
    164   SealHandleScope shs(isolate);
    165   DCHECK_EQ(2, args.length());
    166   CONVERT_ARG_HANDLE_CHECKED(BytecodeArray, bytecode_array, 0);
    167   CONVERT_SMI_ARG_CHECKED(bytecode_offset, 1);
    168   interpreter::BytecodeArrayIterator it(bytecode_array);
    169   int offset = bytecode_offset - BytecodeArray::kHeaderSize + kHeapObjectTag;
    170   while (it.current_offset() < offset) it.Advance();
    171   DCHECK_EQ(offset, it.current_offset());
    172   it.Advance();  // Advance by one bytecode.
    173   offset = it.current_offset() + BytecodeArray::kHeaderSize - kHeapObjectTag;
    174   return Smi::FromInt(offset);
    175 }
    176 
    177 }  // namespace internal
    178 }  // namespace v8
    179