• 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 <iomanip>
6 
7 #include "src/arguments-inl.h"
8 #include "src/frames-inl.h"
9 #include "src/interpreter/bytecode-array-iterator.h"
10 #include "src/interpreter/bytecode-decoder.h"
11 #include "src/interpreter/bytecode-flags.h"
12 #include "src/interpreter/bytecode-register.h"
13 #include "src/interpreter/bytecodes.h"
14 #include "src/interpreter/interpreter.h"
15 #include "src/isolate-inl.h"
16 #include "src/ostreams.h"
17 #include "src/runtime/runtime-utils.h"
18 #include "src/snapshot/snapshot.h"
19 
20 namespace v8 {
21 namespace internal {
22 
RUNTIME_FUNCTION(Runtime_InterpreterDeserializeLazy)23 RUNTIME_FUNCTION(Runtime_InterpreterDeserializeLazy) {
24   HandleScope scope(isolate);
25 
26   DCHECK(FLAG_lazy_handler_deserialization);
27   DCHECK(FLAG_lazy_deserialization);
28   DCHECK_EQ(2, args.length());
29   CONVERT_SMI_ARG_CHECKED(bytecode_int, 0);
30   CONVERT_SMI_ARG_CHECKED(operand_scale_int, 1);
31 
32   using interpreter::Bytecode;
33   using interpreter::Bytecodes;
34   using interpreter::OperandScale;
35 
36   Bytecode bytecode = Bytecodes::FromByte(bytecode_int);
37   OperandScale operand_scale = static_cast<OperandScale>(operand_scale_int);
38 
39   return isolate->interpreter()->GetAndMaybeDeserializeBytecodeHandler(
40       bytecode, operand_scale);
41 }
42 
43 #ifdef V8_TRACE_IGNITION
44 
45 namespace {
46 
AdvanceToOffsetForTracing(interpreter::BytecodeArrayIterator & bytecode_iterator,int offset)47 void AdvanceToOffsetForTracing(
48     interpreter::BytecodeArrayIterator& bytecode_iterator, int offset) {
49   while (bytecode_iterator.current_offset() +
50              bytecode_iterator.current_bytecode_size() <=
51          offset) {
52     bytecode_iterator.Advance();
53   }
54   DCHECK(bytecode_iterator.current_offset() == offset ||
55          ((bytecode_iterator.current_offset() + 1) == offset &&
56           bytecode_iterator.current_operand_scale() >
57               interpreter::OperandScale::kSingle));
58 }
59 
PrintRegisters(Isolate * isolate,std::ostream & os,bool is_input,interpreter::BytecodeArrayIterator & bytecode_iterator,Handle<Object> accumulator)60 void PrintRegisters(Isolate* isolate, std::ostream& os, bool is_input,
61                     interpreter::BytecodeArrayIterator& bytecode_iterator,
62                     Handle<Object> accumulator) {
63   static const char kAccumulator[] = "accumulator";
64   static const int kRegFieldWidth = static_cast<int>(sizeof(kAccumulator) - 1);
65   static const char* kInputColourCode = "\033[0;36m";
66   static const char* kOutputColourCode = "\033[0;35m";
67   static const char* kNormalColourCode = "\033[0;m";
68   const char* kArrowDirection = is_input ? " -> " : " <- ";
69   if (FLAG_log_colour) {
70     os << (is_input ? kInputColourCode : kOutputColourCode);
71   }
72 
73   interpreter::Bytecode bytecode = bytecode_iterator.current_bytecode();
74 
75   // Print accumulator.
76   if ((is_input && interpreter::Bytecodes::ReadsAccumulator(bytecode)) ||
77       (!is_input && interpreter::Bytecodes::WritesAccumulator(bytecode))) {
78     os << "      [ " << kAccumulator << kArrowDirection;
79     accumulator->ShortPrint();
80     os << " ]" << std::endl;
81   }
82 
83   // Print the registers.
84   JavaScriptFrameIterator frame_iterator(isolate);
85   InterpretedFrame* frame =
86       reinterpret_cast<InterpretedFrame*>(frame_iterator.frame());
87   int operand_count = interpreter::Bytecodes::NumberOfOperands(bytecode);
88   for (int operand_index = 0; operand_index < operand_count; operand_index++) {
89     interpreter::OperandType operand_type =
90         interpreter::Bytecodes::GetOperandType(bytecode, operand_index);
91     bool should_print =
92         is_input
93             ? interpreter::Bytecodes::IsRegisterInputOperandType(operand_type)
94             : interpreter::Bytecodes::IsRegisterOutputOperandType(operand_type);
95     if (should_print) {
96       interpreter::Register first_reg =
97           bytecode_iterator.GetRegisterOperand(operand_index);
98       int range = bytecode_iterator.GetRegisterOperandRange(operand_index);
99       for (int reg_index = first_reg.index();
100            reg_index < first_reg.index() + range; reg_index++) {
101         Object* reg_object = frame->ReadInterpreterRegister(reg_index);
102         os << "      [ " << std::setw(kRegFieldWidth)
103            << interpreter::Register(reg_index).ToString(
104                   bytecode_iterator.bytecode_array()->parameter_count())
105            << kArrowDirection;
106         reg_object->ShortPrint(os);
107         os << " ]" << std::endl;
108       }
109     }
110   }
111   if (FLAG_log_colour) {
112     os << kNormalColourCode;
113   }
114 }
115 
116 }  // namespace
117 
RUNTIME_FUNCTION(Runtime_InterpreterTraceBytecodeEntry)118 RUNTIME_FUNCTION(Runtime_InterpreterTraceBytecodeEntry) {
119   if (!FLAG_trace_ignition) {
120     return ReadOnlyRoots(isolate).undefined_value();
121   }
122 
123   SealHandleScope shs(isolate);
124   DCHECK_EQ(3, args.length());
125   CONVERT_ARG_HANDLE_CHECKED(BytecodeArray, bytecode_array, 0);
126   CONVERT_SMI_ARG_CHECKED(bytecode_offset, 1);
127   CONVERT_ARG_HANDLE_CHECKED(Object, accumulator, 2);
128 
129   int offset = bytecode_offset - BytecodeArray::kHeaderSize + kHeapObjectTag;
130   interpreter::BytecodeArrayIterator bytecode_iterator(bytecode_array);
131   AdvanceToOffsetForTracing(bytecode_iterator, offset);
132   if (offset == bytecode_iterator.current_offset()) {
133     StdoutStream os;
134 
135     // Print bytecode.
136     const uint8_t* base_address = reinterpret_cast<const uint8_t*>(
137         bytecode_array->GetFirstBytecodeAddress());
138     const uint8_t* bytecode_address = base_address + offset;
139     os << " -> " << static_cast<const void*>(bytecode_address) << " @ "
140        << std::setw(4) << offset << " : ";
141     interpreter::BytecodeDecoder::Decode(os, bytecode_address,
142                                          bytecode_array->parameter_count());
143     os << std::endl;
144     // Print all input registers and accumulator.
145     PrintRegisters(isolate, os, true, bytecode_iterator, accumulator);
146 
147     os << std::flush;
148   }
149   return ReadOnlyRoots(isolate).undefined_value();
150 }
151 
RUNTIME_FUNCTION(Runtime_InterpreterTraceBytecodeExit)152 RUNTIME_FUNCTION(Runtime_InterpreterTraceBytecodeExit) {
153   if (!FLAG_trace_ignition) {
154     return ReadOnlyRoots(isolate).undefined_value();
155   }
156 
157   SealHandleScope shs(isolate);
158   DCHECK_EQ(3, args.length());
159   CONVERT_ARG_HANDLE_CHECKED(BytecodeArray, bytecode_array, 0);
160   CONVERT_SMI_ARG_CHECKED(bytecode_offset, 1);
161   CONVERT_ARG_HANDLE_CHECKED(Object, accumulator, 2);
162 
163   int offset = bytecode_offset - BytecodeArray::kHeaderSize + kHeapObjectTag;
164   interpreter::BytecodeArrayIterator bytecode_iterator(bytecode_array);
165   AdvanceToOffsetForTracing(bytecode_iterator, offset);
166   // The offset comparison here ensures registers only printed when the
167   // (potentially) widened bytecode has completed. The iterator reports
168   // the offset as the offset of the prefix bytecode.
169   if (bytecode_iterator.current_operand_scale() ==
170           interpreter::OperandScale::kSingle ||
171       offset > bytecode_iterator.current_offset()) {
172     StdoutStream os;
173     // Print all output registers and accumulator.
174     PrintRegisters(isolate, os, false, bytecode_iterator, accumulator);
175     os << std::flush;
176   }
177   return ReadOnlyRoots(isolate).undefined_value();
178 }
179 
180 #endif
181 
182 #ifdef V8_TRACE_FEEDBACK_UPDATES
183 
RUNTIME_FUNCTION(Runtime_InterpreterTraceUpdateFeedback)184 RUNTIME_FUNCTION(Runtime_InterpreterTraceUpdateFeedback) {
185   if (!FLAG_trace_feedback_updates) {
186     return ReadOnlyRoots(isolate).undefined_value();
187   }
188 
189   SealHandleScope shs(isolate);
190   DCHECK_EQ(3, args.length());
191   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
192   CONVERT_SMI_ARG_CHECKED(slot, 1);
193   CONVERT_ARG_CHECKED(String, reason, 2);
194 
195   int slot_count = function->feedback_vector()->metadata()->slot_count();
196 
197   StdoutStream os;
198   os << "[Feedback slot " << slot << "/" << slot_count << " in ";
199   function->shared()->ShortPrint(os);
200   os << " updated to ";
201   function->feedback_vector()->FeedbackSlotPrint(os, FeedbackSlot(slot));
202   os << " - ";
203 
204   StringCharacterStream stream(reason);
205   while (stream.HasMore()) {
206     uint16_t character = stream.GetNext();
207     PrintF("%c", character);
208   }
209 
210   os << "]" << std::endl;
211 
212   return ReadOnlyRoots(isolate).undefined_value();
213 }
214 
215 #endif
216 
217 }  // namespace internal
218 }  // namespace v8
219