• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
RUNTIME_FUNCTION(Runtime_InterpreterNewClosure)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 
AdvanceToOffsetForTracing(interpreter::BytecodeArrayIterator & bytecode_iterator,int offset)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 
PrintRegisters(std::ostream & os,bool is_input,interpreter::BytecodeArrayIterator & bytecode_iterator,Handle<Object> accumulator)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 
RUNTIME_FUNCTION(Runtime_InterpreterTraceBytecodeEntry)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 
RUNTIME_FUNCTION(Runtime_InterpreterTraceBytecodeExit)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 
RUNTIME_FUNCTION(Runtime_InterpreterAdvanceBytecodeOffset)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