OLD | NEW |
1 // Copyright 2016 the V8 project authors. All rights reserved. | 1 // Copyright 2016 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "test/cctest/interpreter/bytecode-expectations-printer.h" | 5 #include "test/cctest/interpreter/bytecode-expectations-printer.h" |
6 | 6 |
| 7 #include <iomanip> |
7 #include <iostream> | 8 #include <iostream> |
8 #include <vector> | 9 #include <vector> |
9 | 10 |
10 #include "include/libplatform/libplatform.h" | 11 #include "include/libplatform/libplatform.h" |
11 #include "include/v8.h" | 12 #include "include/v8.h" |
12 | 13 |
13 #include "src/base/logging.h" | 14 #include "src/base/logging.h" |
14 #include "src/base/smart-pointers.h" | 15 #include "src/base/smart-pointers.h" |
15 #include "src/compiler.h" | 16 #include "src/compiler.h" |
16 #include "src/runtime/runtime.h" | 17 #include "src/runtime/runtime.h" |
17 | 18 |
18 #include "src/interpreter/bytecode-array-iterator.h" | 19 #include "src/interpreter/bytecode-array-iterator.h" |
19 #include "src/interpreter/bytecode-generator.h" | 20 #include "src/interpreter/bytecode-generator.h" |
20 #include "src/interpreter/bytecodes.h" | 21 #include "src/interpreter/bytecodes.h" |
21 #include "src/interpreter/interpreter.h" | 22 #include "src/interpreter/interpreter.h" |
| 23 #include "src/interpreter/source-position-table.h" |
22 | 24 |
23 namespace v8 { | 25 namespace v8 { |
24 namespace internal { | 26 namespace internal { |
25 namespace interpreter { | 27 namespace interpreter { |
26 | 28 |
27 // static | 29 // static |
28 const char* const BytecodeExpectationsPrinter::kDefaultTopFunctionName = | 30 const char* const BytecodeExpectationsPrinter::kDefaultTopFunctionName = |
29 "__genbckexp_wrapper__"; | 31 "__genbckexp_wrapper__"; |
| 32 const char* const BytecodeExpectationsPrinter::kIndent = " "; |
30 | 33 |
31 v8::Local<v8::String> BytecodeExpectationsPrinter::V8StringFromUTF8( | 34 v8::Local<v8::String> BytecodeExpectationsPrinter::V8StringFromUTF8( |
32 const char* data) const { | 35 const char* data) const { |
33 return v8::String::NewFromUtf8(isolate_, data, v8::NewStringType::kNormal) | 36 return v8::String::NewFromUtf8(isolate_, data, v8::NewStringType::kNormal) |
34 .ToLocalChecked(); | 37 .ToLocalChecked(); |
35 } | 38 } |
36 | 39 |
37 std::string BytecodeExpectationsPrinter::WrapCodeInFunction( | 40 std::string BytecodeExpectationsPrinter::WrapCodeInFunction( |
38 const char* function_name, const std::string& function_body) const { | 41 const char* function_name, const std::string& function_body) const { |
39 std::ostringstream program_stream; | 42 std::ostringstream program_stream; |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
95 } | 98 } |
96 } | 99 } |
97 | 100 |
98 namespace { | 101 namespace { |
99 i::Runtime::FunctionId IndexToFunctionId(uint32_t index) { | 102 i::Runtime::FunctionId IndexToFunctionId(uint32_t index) { |
100 return static_cast<i::Runtime::FunctionId>(index); | 103 return static_cast<i::Runtime::FunctionId>(index); |
101 } | 104 } |
102 } // namespace | 105 } // namespace |
103 | 106 |
104 void BytecodeExpectationsPrinter::PrintBytecodeOperand( | 107 void BytecodeExpectationsPrinter::PrintBytecodeOperand( |
105 std::ostream& stream, const BytecodeArrayIterator& bytecode_iter, | 108 std::ostream& stream, const BytecodeArrayIterator& bytecode_iterator, |
106 const Bytecode& bytecode, int op_index, int parameter_count) const { | 109 const Bytecode& bytecode, int op_index, int parameter_count) const { |
107 OperandType op_type = Bytecodes::GetOperandType(bytecode, op_index); | 110 OperandType op_type = Bytecodes::GetOperandType(bytecode, op_index); |
108 OperandSize op_size = Bytecodes::GetOperandSize( | 111 OperandSize op_size = Bytecodes::GetOperandSize( |
109 bytecode, op_index, bytecode_iter.current_operand_scale()); | 112 bytecode, op_index, bytecode_iterator.current_operand_scale()); |
110 | 113 |
111 const char* size_tag; | 114 const char* size_tag; |
112 switch (op_size) { | 115 switch (op_size) { |
113 case OperandSize::kByte: | 116 case OperandSize::kByte: |
114 size_tag = "8"; | 117 size_tag = "8"; |
115 break; | 118 break; |
116 case OperandSize::kShort: | 119 case OperandSize::kShort: |
117 size_tag = "16"; | 120 size_tag = "16"; |
118 break; | 121 break; |
119 case OperandSize::kQuad: | 122 case OperandSize::kQuad: |
120 size_tag = "32"; | 123 size_tag = "32"; |
121 break; | 124 break; |
122 default: | 125 default: |
123 UNREACHABLE(); | 126 UNREACHABLE(); |
124 return; | 127 return; |
125 } | 128 } |
126 | 129 |
127 if (Bytecodes::IsRegisterOperandType(op_type)) { | 130 if (Bytecodes::IsRegisterOperandType(op_type)) { |
128 Register register_value = bytecode_iter.GetRegisterOperand(op_index); | 131 Register register_value = bytecode_iterator.GetRegisterOperand(op_index); |
129 stream << 'R'; | 132 stream << 'R'; |
130 if (op_size != OperandSize::kByte) stream << size_tag; | 133 if (op_size != OperandSize::kByte) stream << size_tag; |
131 if (register_value.is_new_target()) { | 134 if (register_value.is_new_target()) { |
132 stream << "(new_target)"; | 135 stream << "(new_target)"; |
133 } else if (register_value.is_current_context()) { | 136 } else if (register_value.is_current_context()) { |
134 stream << "(context)"; | 137 stream << "(context)"; |
135 } else if (register_value.is_function_closure()) { | 138 } else if (register_value.is_function_closure()) { |
136 stream << "(closure)"; | 139 stream << "(closure)"; |
137 } else if (register_value.is_parameter()) { | 140 } else if (register_value.is_parameter()) { |
138 int parameter_index = register_value.ToParameterIndex(parameter_count); | 141 int parameter_index = register_value.ToParameterIndex(parameter_count); |
139 if (parameter_index == 0) { | 142 if (parameter_index == 0) { |
140 stream << "(this)"; | 143 stream << "(this)"; |
141 } else { | 144 } else { |
142 stream << "(arg" << (parameter_index - 1) << ')'; | 145 stream << "(arg" << (parameter_index - 1) << ')'; |
143 } | 146 } |
144 } else { | 147 } else { |
145 stream << '(' << register_value.index() << ')'; | 148 stream << '(' << register_value.index() << ')'; |
146 } | 149 } |
147 } else { | 150 } else { |
148 stream << 'U' << size_tag << '('; | 151 stream << 'U' << size_tag << '('; |
149 | 152 |
150 switch (op_type) { | 153 switch (op_type) { |
151 case OperandType::kFlag8: | 154 case OperandType::kFlag8: |
152 stream << bytecode_iter.GetFlagOperand(op_index); | 155 stream << bytecode_iterator.GetFlagOperand(op_index); |
153 break; | 156 break; |
154 case OperandType::kIdx: | 157 case OperandType::kIdx: |
155 stream << bytecode_iter.GetIndexOperand(op_index); | 158 stream << bytecode_iterator.GetIndexOperand(op_index); |
156 break; | 159 break; |
157 case OperandType::kImm: | 160 case OperandType::kImm: |
158 stream << bytecode_iter.GetImmediateOperand(op_index); | 161 stream << bytecode_iterator.GetImmediateOperand(op_index); |
159 break; | 162 break; |
160 case OperandType::kRegCount: | 163 case OperandType::kRegCount: |
161 stream << bytecode_iter.GetRegisterCountOperand(op_index); | 164 stream << bytecode_iterator.GetRegisterCountOperand(op_index); |
162 break; | 165 break; |
163 case OperandType::kRuntimeId: { | 166 case OperandType::kRuntimeId: { |
164 uint32_t operand = bytecode_iter.GetRuntimeIdOperand(op_index); | 167 uint32_t operand = bytecode_iterator.GetRuntimeIdOperand(op_index); |
165 stream << "Runtime::k" | 168 stream << "Runtime::k" |
166 << i::Runtime::FunctionForId(IndexToFunctionId(operand))->name; | 169 << i::Runtime::FunctionForId(IndexToFunctionId(operand))->name; |
167 break; | 170 break; |
168 } | 171 } |
169 default: | 172 default: |
170 UNREACHABLE(); | 173 UNREACHABLE(); |
171 } | 174 } |
172 | 175 |
173 stream << ')'; | 176 stream << ')'; |
174 } | 177 } |
175 } | 178 } |
176 | 179 |
177 void BytecodeExpectationsPrinter::PrintBytecode( | 180 void BytecodeExpectationsPrinter::PrintBytecode( |
178 std::ostream& stream, const BytecodeArrayIterator& bytecode_iter, | 181 std::ostream& stream, const BytecodeArrayIterator& bytecode_iterator, |
179 int parameter_count) const { | 182 int parameter_count) const { |
180 Bytecode bytecode = bytecode_iter.current_bytecode(); | 183 Bytecode bytecode = bytecode_iterator.current_bytecode(); |
181 OperandScale operand_scale = bytecode_iter.current_operand_scale(); | 184 OperandScale operand_scale = bytecode_iterator.current_operand_scale(); |
182 if (Bytecodes::OperandScaleRequiresPrefixBytecode(operand_scale)) { | 185 if (Bytecodes::OperandScaleRequiresPrefixBytecode(operand_scale)) { |
183 Bytecode prefix = Bytecodes::OperandScaleToPrefixBytecode(operand_scale); | 186 Bytecode prefix = Bytecodes::OperandScaleToPrefixBytecode(operand_scale); |
184 stream << "B(" << Bytecodes::ToString(prefix) << "), "; | 187 stream << "B(" << Bytecodes::ToString(prefix) << "), "; |
185 } | 188 } |
186 stream << "B(" << Bytecodes::ToString(bytecode) << ')'; | 189 stream << "B(" << Bytecodes::ToString(bytecode) << ')'; |
187 int operands_count = Bytecodes::NumberOfOperands(bytecode); | 190 int operands_count = Bytecodes::NumberOfOperands(bytecode); |
188 for (int op_index = 0; op_index < operands_count; ++op_index) { | 191 for (int op_index = 0; op_index < operands_count; ++op_index) { |
189 stream << ", "; | 192 stream << ", "; |
190 PrintBytecodeOperand(stream, bytecode_iter, bytecode, op_index, | 193 PrintBytecodeOperand(stream, bytecode_iterator, bytecode, op_index, |
191 parameter_count); | 194 parameter_count); |
192 } | 195 } |
193 } | 196 } |
194 | 197 |
| 198 void BytecodeExpectationsPrinter::PrintSourcePosition( |
| 199 std::ostream& stream, SourcePositionTableIterator& source_iterator, |
| 200 int bytecode_offset) const { |
| 201 static const size_t kPositionWidth = 4; |
| 202 if (!source_iterator.done() && |
| 203 source_iterator.bytecode_offset() == bytecode_offset) { |
| 204 stream << "/* " << std::setw(kPositionWidth) |
| 205 << source_iterator.source_position(); |
| 206 if (source_iterator.is_statement()) { |
| 207 stream << " S> */ "; |
| 208 } else { |
| 209 stream << " E> */ "; |
| 210 } |
| 211 source_iterator.Advance(); |
| 212 } else { |
| 213 stream << " " << std::setw(kPositionWidth) << ' ' << " "; |
| 214 } |
| 215 } |
| 216 |
195 void BytecodeExpectationsPrinter::PrintV8String(std::ostream& stream, | 217 void BytecodeExpectationsPrinter::PrintV8String(std::ostream& stream, |
196 i::String* string) const { | 218 i::String* string) const { |
197 stream << '"'; | 219 stream << '"'; |
198 for (int i = 0, length = string->length(); i < length; ++i) { | 220 for (int i = 0, length = string->length(); i < length; ++i) { |
199 stream << i::AsEscapedUC16ForJSON(string->Get(i)); | 221 stream << i::AsEscapedUC16ForJSON(string->Get(i)); |
200 } | 222 } |
201 stream << '"'; | 223 stream << '"'; |
202 } | 224 } |
203 | 225 |
204 void BytecodeExpectationsPrinter::PrintConstant( | 226 void BytecodeExpectationsPrinter::PrintConstant( |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
239 | 261 |
240 DCHECK_EQ(frame_size % kPointerSize, 0); | 262 DCHECK_EQ(frame_size % kPointerSize, 0); |
241 stream << "frame size: " << frame_size / kPointerSize | 263 stream << "frame size: " << frame_size / kPointerSize |
242 << "\nparameter count: " << bytecode_array->parameter_count() << '\n'; | 264 << "\nparameter count: " << bytecode_array->parameter_count() << '\n'; |
243 } | 265 } |
244 | 266 |
245 void BytecodeExpectationsPrinter::PrintBytecodeSequence( | 267 void BytecodeExpectationsPrinter::PrintBytecodeSequence( |
246 std::ostream& stream, i::Handle<i::BytecodeArray> bytecode_array) const { | 268 std::ostream& stream, i::Handle<i::BytecodeArray> bytecode_array) const { |
247 stream << "bytecode array length: " << bytecode_array->length() | 269 stream << "bytecode array length: " << bytecode_array->length() |
248 << "\nbytecodes: [\n"; | 270 << "\nbytecodes: [\n"; |
249 BytecodeArrayIterator bytecode_iter(bytecode_array); | 271 |
250 for (; !bytecode_iter.done(); bytecode_iter.Advance()) { | 272 SourcePositionTableIterator source_iterator( |
251 stream << " "; | 273 bytecode_array->source_position_table()); |
252 PrintBytecode(stream, bytecode_iter, bytecode_array->parameter_count()); | 274 BytecodeArrayIterator bytecode_iterator(bytecode_array); |
| 275 for (; !bytecode_iterator.done(); bytecode_iterator.Advance()) { |
| 276 stream << kIndent; |
| 277 PrintSourcePosition(stream, source_iterator, |
| 278 bytecode_iterator.current_offset()); |
| 279 PrintBytecode(stream, bytecode_iterator, bytecode_array->parameter_count()); |
253 stream << ",\n"; | 280 stream << ",\n"; |
254 } | 281 } |
255 stream << "]\n"; | 282 stream << "]\n"; |
256 } | 283 } |
257 | 284 |
258 void BytecodeExpectationsPrinter::PrintConstantPool( | 285 void BytecodeExpectationsPrinter::PrintConstantPool( |
259 std::ostream& stream, i::FixedArray* constant_pool) const { | 286 std::ostream& stream, i::FixedArray* constant_pool) const { |
260 stream << "constant pool: [\n"; | 287 stream << "constant pool: [\n"; |
261 int num_constants = constant_pool->length(); | 288 int num_constants = constant_pool->length(); |
262 if (num_constants > 0) { | 289 if (num_constants > 0) { |
263 for (int i = 0; i < num_constants; ++i) { | 290 for (int i = 0; i < num_constants; ++i) { |
264 stream << " "; | 291 stream << kIndent; |
265 PrintConstant(stream, i::FixedArray::get(constant_pool, i, i_isolate())); | 292 PrintConstant(stream, i::FixedArray::get(constant_pool, i, i_isolate())); |
266 stream << ",\n"; | 293 stream << ",\n"; |
267 } | 294 } |
268 } | 295 } |
269 stream << "]\n"; | 296 stream << "]\n"; |
270 } | 297 } |
271 | 298 |
272 void BytecodeExpectationsPrinter::PrintCodeSnippet( | 299 void BytecodeExpectationsPrinter::PrintCodeSnippet( |
273 std::ostream& stream, const std::string& body) const { | 300 std::ostream& stream, const std::string& body) const { |
274 stream << "snippet: \"\n"; | 301 stream << "snippet: \"\n"; |
275 std::stringstream body_stream(body); | 302 std::stringstream body_stream(body); |
276 std::string body_line; | 303 std::string body_line; |
277 while (std::getline(body_stream, body_line)) { | 304 while (std::getline(body_stream, body_line)) { |
278 stream << " "; | 305 stream << kIndent; |
279 PrintEscapedString(stream, body_line); | 306 PrintEscapedString(stream, body_line); |
280 stream << '\n'; | 307 stream << '\n'; |
281 } | 308 } |
282 stream << "\"\n"; | 309 stream << "\"\n"; |
283 } | 310 } |
284 | 311 |
285 void BytecodeExpectationsPrinter::PrintHandlers( | 312 void BytecodeExpectationsPrinter::PrintHandlers( |
286 std::ostream& stream, i::Handle<i::BytecodeArray> bytecode_array) const { | 313 std::ostream& stream, i::Handle<i::BytecodeArray> bytecode_array) const { |
287 stream << "handlers: [\n"; | 314 stream << "handlers: [\n"; |
288 HandlerTable* table = HandlerTable::cast(bytecode_array->handler_table()); | 315 HandlerTable* table = HandlerTable::cast(bytecode_array->handler_table()); |
(...skipping 29 matching lines...) Expand all Loading... |
318 | 345 |
319 stream << "---\n"; | 346 stream << "---\n"; |
320 PrintCodeSnippet(stream, snippet); | 347 PrintCodeSnippet(stream, snippet); |
321 PrintBytecodeArray(stream, bytecode_array); | 348 PrintBytecodeArray(stream, bytecode_array); |
322 stream << '\n'; | 349 stream << '\n'; |
323 } | 350 } |
324 | 351 |
325 } // namespace interpreter | 352 } // namespace interpreter |
326 } // namespace internal | 353 } // namespace internal |
327 } // namespace v8 | 354 } // namespace v8 |
OLD | NEW |