| 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 |