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