• 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/bytecodes.h"
13 #include "src/isolate-inl.h"
14 #include "src/ostreams.h"
15 
16 namespace v8 {
17 namespace internal {
18 
RUNTIME_FUNCTION(Runtime_InterpreterNewClosure)19 RUNTIME_FUNCTION(Runtime_InterpreterNewClosure) {
20   HandleScope scope(isolate);
21   DCHECK_EQ(2, args.length());
22   CONVERT_ARG_HANDLE_CHECKED(SharedFunctionInfo, shared, 0);
23   CONVERT_SMI_ARG_CHECKED(pretenured_flag, 1);
24   Handle<Context> context(isolate->context(), isolate);
25   return *isolate->factory()->NewFunctionFromSharedFunctionInfo(
26       shared, context, static_cast<PretenureFlag>(pretenured_flag));
27 }
28 
29 namespace {
30 
AdvanceToOffsetForTracing(interpreter::BytecodeArrayIterator & bytecode_iterator,int offset)31 void AdvanceToOffsetForTracing(
32     interpreter::BytecodeArrayIterator& bytecode_iterator, int offset) {
33   while (bytecode_iterator.current_offset() +
34              bytecode_iterator.current_bytecode_size() <=
35          offset) {
36     bytecode_iterator.Advance();
37   }
38   DCHECK(bytecode_iterator.current_offset() == offset ||
39          ((bytecode_iterator.current_offset() + 1) == offset &&
40           bytecode_iterator.current_operand_scale() >
41               interpreter::OperandScale::kSingle));
42 }
43 
PrintRegisters(std::ostream & os,bool is_input,interpreter::BytecodeArrayIterator & bytecode_iterator,Handle<Object> accumulator)44 void PrintRegisters(std::ostream& os, bool is_input,
45                     interpreter::BytecodeArrayIterator& bytecode_iterator,
46                     Handle<Object> accumulator) {
47   static const char kAccumulator[] = "accumulator";
48   static const int kRegFieldWidth = static_cast<int>(sizeof(kAccumulator) - 1);
49   static const char* kInputColourCode = "\033[0;36m";
50   static const char* kOutputColourCode = "\033[0;35m";
51   static const char* kNormalColourCode = "\033[0;m";
52   const char* kArrowDirection = is_input ? " -> " : " <- ";
53   if (FLAG_log_colour) {
54     os << (is_input ? kInputColourCode : kOutputColourCode);
55   }
56 
57   interpreter::Bytecode bytecode = bytecode_iterator.current_bytecode();
58 
59   // Print accumulator.
60   if ((is_input && interpreter::Bytecodes::ReadsAccumulator(bytecode)) ||
61       (!is_input && interpreter::Bytecodes::WritesAccumulator(bytecode))) {
62     os << "      [ " << kAccumulator << kArrowDirection;
63     accumulator->ShortPrint();
64     os << " ]" << std::endl;
65   }
66 
67   // Print the registers.
68   JavaScriptFrameIterator frame_iterator(
69       bytecode_iterator.bytecode_array()->GetIsolate());
70   InterpretedFrame* frame =
71       reinterpret_cast<InterpretedFrame*>(frame_iterator.frame());
72   int operand_count = interpreter::Bytecodes::NumberOfOperands(bytecode);
73   for (int operand_index = 0; operand_index < operand_count; operand_index++) {
74     interpreter::OperandType operand_type =
75         interpreter::Bytecodes::GetOperandType(bytecode, operand_index);
76     bool should_print =
77         is_input
78             ? interpreter::Bytecodes::IsRegisterInputOperandType(operand_type)
79             : interpreter::Bytecodes::IsRegisterOutputOperandType(operand_type);
80     if (should_print) {
81       interpreter::Register first_reg =
82           bytecode_iterator.GetRegisterOperand(operand_index);
83       int range = bytecode_iterator.GetRegisterOperandRange(operand_index);
84       for (int reg_index = first_reg.index();
85            reg_index < first_reg.index() + range; reg_index++) {
86         Object* reg_object = frame->ReadInterpreterRegister(reg_index);
87         os << "      [ " << std::setw(kRegFieldWidth)
88            << interpreter::Register(reg_index).ToString(
89                   bytecode_iterator.bytecode_array()->parameter_count())
90            << kArrowDirection;
91         reg_object->ShortPrint(os);
92         os << " ]" << std::endl;
93       }
94     }
95   }
96   if (FLAG_log_colour) {
97     os << kNormalColourCode;
98   }
99 }
100 
101 }  // namespace
102 
RUNTIME_FUNCTION(Runtime_InterpreterTraceBytecodeEntry)103 RUNTIME_FUNCTION(Runtime_InterpreterTraceBytecodeEntry) {
104   SealHandleScope shs(isolate);
105   DCHECK_EQ(3, args.length());
106   CONVERT_ARG_HANDLE_CHECKED(BytecodeArray, bytecode_array, 0);
107   CONVERT_SMI_ARG_CHECKED(bytecode_offset, 1);
108   CONVERT_ARG_HANDLE_CHECKED(Object, accumulator, 2);
109   OFStream os(stdout);
110 
111   int offset = bytecode_offset - BytecodeArray::kHeaderSize + kHeapObjectTag;
112   interpreter::BytecodeArrayIterator bytecode_iterator(bytecode_array);
113   AdvanceToOffsetForTracing(bytecode_iterator, offset);
114   if (offset == bytecode_iterator.current_offset()) {
115     // Print bytecode.
116     const uint8_t* base_address = bytecode_array->GetFirstBytecodeAddress();
117     const uint8_t* bytecode_address = base_address + offset;
118     os << " -> " << static_cast<const void*>(bytecode_address) << " @ "
119        << std::setw(4) << offset << " : ";
120     interpreter::Bytecodes::Decode(os, bytecode_address,
121                                    bytecode_array->parameter_count());
122     os << std::endl;
123     // Print all input registers and accumulator.
124     PrintRegisters(os, true, bytecode_iterator, accumulator);
125 
126     os << std::flush;
127   }
128   return isolate->heap()->undefined_value();
129 }
130 
RUNTIME_FUNCTION(Runtime_InterpreterTraceBytecodeExit)131 RUNTIME_FUNCTION(Runtime_InterpreterTraceBytecodeExit) {
132   SealHandleScope shs(isolate);
133   DCHECK_EQ(3, args.length());
134   CONVERT_ARG_HANDLE_CHECKED(BytecodeArray, bytecode_array, 0);
135   CONVERT_SMI_ARG_CHECKED(bytecode_offset, 1);
136   CONVERT_ARG_HANDLE_CHECKED(Object, accumulator, 2);
137 
138   int offset = bytecode_offset - BytecodeArray::kHeaderSize + kHeapObjectTag;
139   interpreter::BytecodeArrayIterator bytecode_iterator(bytecode_array);
140   AdvanceToOffsetForTracing(bytecode_iterator, offset);
141   // The offset comparison here ensures registers only printed when the
142   // (potentially) widened bytecode has completed. The iterator reports
143   // the offset as the offset of the prefix bytecode.
144   if (bytecode_iterator.current_operand_scale() ==
145           interpreter::OperandScale::kSingle ||
146       offset > bytecode_iterator.current_offset()) {
147     OFStream os(stdout);
148     // Print all output registers and accumulator.
149     PrintRegisters(os, false, bytecode_iterator, accumulator);
150     os << std::flush;
151   }
152   return isolate->heap()->undefined_value();
153 }
154 
RUNTIME_FUNCTION(Runtime_InterpreterClearPendingMessage)155 RUNTIME_FUNCTION(Runtime_InterpreterClearPendingMessage) {
156   SealHandleScope shs(isolate);
157   DCHECK_EQ(0, args.length());
158   Object* message = isolate->thread_local_top()->pending_message_obj_;
159   isolate->clear_pending_message();
160   return message;
161 }
162 
RUNTIME_FUNCTION(Runtime_InterpreterSetPendingMessage)163 RUNTIME_FUNCTION(Runtime_InterpreterSetPendingMessage) {
164   SealHandleScope shs(isolate);
165   DCHECK_EQ(1, args.length());
166   CONVERT_ARG_HANDLE_CHECKED(Object, message, 0);
167   isolate->thread_local_top()->pending_message_obj_ = *message;
168   return isolate->heap()->undefined_value();
169 }
170 
171 }  // namespace internal
172 }  // namespace v8
173