| OLD | NEW |
| 1 // Copyright 2015 the V8 project authors. All rights reserved. | 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 | 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 "src/interpreter/interpreter.h" | 5 #include "src/interpreter/interpreter.h" |
| 6 | 6 |
| 7 #include <fstream> |
| 8 |
| 7 #include "src/ast/prettyprinter.h" | 9 #include "src/ast/prettyprinter.h" |
| 8 #include "src/code-factory.h" | 10 #include "src/code-factory.h" |
| 9 #include "src/compiler.h" | 11 #include "src/compiler.h" |
| 10 #include "src/factory.h" | 12 #include "src/factory.h" |
| 11 #include "src/interpreter/bytecode-generator.h" | 13 #include "src/interpreter/bytecode-generator.h" |
| 12 #include "src/interpreter/bytecodes.h" | 14 #include "src/interpreter/bytecodes.h" |
| 13 #include "src/interpreter/interpreter-assembler.h" | 15 #include "src/interpreter/interpreter-assembler.h" |
| 14 #include "src/interpreter/interpreter-intrinsics.h" | 16 #include "src/interpreter/interpreter-intrinsics.h" |
| 15 #include "src/log.h" | 17 #include "src/log.h" |
| 16 #include "src/zone.h" | 18 #include "src/zone.h" |
| 17 | 19 |
| 18 namespace v8 { | 20 namespace v8 { |
| 19 namespace internal { | 21 namespace internal { |
| 20 namespace interpreter { | 22 namespace interpreter { |
| 21 | 23 |
| 22 using compiler::Node; | 24 using compiler::Node; |
| 23 | 25 |
| 24 #define __ assembler-> | 26 #define __ assembler-> |
| 25 | 27 |
| 26 Interpreter::Interpreter(Isolate* isolate) : isolate_(isolate) { | 28 Interpreter::Interpreter(Isolate* isolate) : isolate_(isolate) { |
| 27 memset(dispatch_table_, 0, sizeof(dispatch_table_)); | 29 memset(dispatch_table_, 0, sizeof(dispatch_table_)); |
| 28 } | 30 } |
| 29 | 31 |
| 30 void Interpreter::Initialize() { | 32 void Interpreter::Initialize() { |
| 31 DCHECK(FLAG_ignition); | 33 DCHECK(FLAG_ignition); |
| 32 if (IsDispatchTableInitialized()) return; | 34 if (IsDispatchTableInitialized()) return; |
| 33 Zone zone(isolate_->allocator()); | 35 Zone zone(isolate_->allocator()); |
| 34 HandleScope scope(isolate_); | 36 HandleScope scope(isolate_); |
| 35 | 37 |
| 38 if (FLAG_trace_ignition_dispatches) { |
| 39 static const int kBytecodeCount = static_cast<int>(Bytecode::kLast) + 1; |
| 40 bytecode_dispatch_count_table_.Reset( |
| 41 new uintptr_t[kBytecodeCount * kBytecodeCount]); |
| 42 memset(bytecode_dispatch_count_table_.get(), 0, |
| 43 sizeof(uintptr_t) * kBytecodeCount * kBytecodeCount); |
| 44 } |
| 45 |
| 36 // Generate bytecode handlers for all bytecodes and scales. | 46 // Generate bytecode handlers for all bytecodes and scales. |
| 37 for (OperandScale operand_scale = OperandScale::kSingle; | 47 for (OperandScale operand_scale = OperandScale::kSingle; |
| 38 operand_scale <= OperandScale::kMaxValid; | 48 operand_scale <= OperandScale::kMaxValid; |
| 39 operand_scale = Bytecodes::NextOperandScale(operand_scale)) { | 49 operand_scale = Bytecodes::NextOperandScale(operand_scale)) { |
| 40 #define GENERATE_CODE(Name, ...) \ | 50 #define GENERATE_CODE(Name, ...) \ |
| 41 { \ | 51 { \ |
| 42 if (Bytecodes::BytecodeHasHandler(Bytecode::k##Name, operand_scale)) { \ | 52 if (Bytecodes::BytecodeHasHandler(Bytecode::k##Name, operand_scale)) { \ |
| 43 InterpreterAssembler assembler(isolate_, &zone, Bytecode::k##Name, \ | 53 InterpreterAssembler assembler(isolate_, &zone, Bytecode::k##Name, \ |
| 44 operand_scale); \ | 54 operand_scale); \ |
| 45 Do##Name(&assembler); \ | 55 Do##Name(&assembler); \ |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 141 bytecodes->Print(os); | 151 bytecodes->Print(os); |
| 142 os << std::flush; | 152 os << std::flush; |
| 143 } | 153 } |
| 144 | 154 |
| 145 info->SetBytecodeArray(bytecodes); | 155 info->SetBytecodeArray(bytecodes); |
| 146 info->SetCode(info->isolate()->builtins()->InterpreterEntryTrampoline()); | 156 info->SetCode(info->isolate()->builtins()->InterpreterEntryTrampoline()); |
| 147 return true; | 157 return true; |
| 148 } | 158 } |
| 149 | 159 |
| 150 bool Interpreter::IsDispatchTableInitialized() { | 160 bool Interpreter::IsDispatchTableInitialized() { |
| 151 if (FLAG_trace_ignition || FLAG_trace_ignition_codegen) { | 161 if (FLAG_trace_ignition || FLAG_trace_ignition_codegen || |
| 152 // Regenerate table to add bytecode tracing operations | 162 FLAG_trace_ignition_dispatches) { |
| 153 // or to print the assembly code generated by TurboFan. | 163 // Regenerate table to add bytecode tracing operations, |
| 164 // print the assembly code generated by TurboFan, |
| 165 // or instrument handlers with dispatch counters. |
| 154 return false; | 166 return false; |
| 155 } | 167 } |
| 156 return dispatch_table_[0] != nullptr; | 168 return dispatch_table_[0] != nullptr; |
| 157 } | 169 } |
| 158 | 170 |
| 159 void Interpreter::TraceCodegen(Handle<Code> code) { | 171 void Interpreter::TraceCodegen(Handle<Code> code) { |
| 160 #ifdef ENABLE_DISASSEMBLER | 172 #ifdef ENABLE_DISASSEMBLER |
| 161 if (FLAG_trace_ignition_codegen) { | 173 if (FLAG_trace_ignition_codegen) { |
| 162 OFStream os(stdout); | 174 OFStream os(stdout); |
| 163 code->Disassemble(nullptr, os); | 175 code->Disassemble(nullptr, os); |
| 164 os << std::flush; | 176 os << std::flush; |
| 165 } | 177 } |
| 166 #endif // ENABLE_DISASSEMBLER | 178 #endif // ENABLE_DISASSEMBLER |
| 167 } | 179 } |
| 168 | 180 |
| 169 const char* Interpreter::LookupNameOfBytecodeHandler(Code* code) { | 181 const char* Interpreter::LookupNameOfBytecodeHandler(Code* code) { |
| 170 #ifdef ENABLE_DISASSEMBLER | 182 #ifdef ENABLE_DISASSEMBLER |
| 171 #define RETURN_NAME(Name, ...) \ | 183 #define RETURN_NAME(Name, ...) \ |
| 172 if (dispatch_table_[Bytecodes::ToByte(Bytecode::k##Name)] == code) { \ | 184 if (dispatch_table_[Bytecodes::ToByte(Bytecode::k##Name)] == code) { \ |
| 173 return #Name; \ | 185 return #Name; \ |
| 174 } | 186 } |
| 175 BYTECODE_LIST(RETURN_NAME) | 187 BYTECODE_LIST(RETURN_NAME) |
| 176 #undef RETURN_NAME | 188 #undef RETURN_NAME |
| 177 #endif // ENABLE_DISASSEMBLER | 189 #endif // ENABLE_DISASSEMBLER |
| 178 return nullptr; | 190 return nullptr; |
| 179 } | 191 } |
| 180 | 192 |
| 193 void Interpreter::WriteDispatchCounters() { |
| 194 std::ofstream stream(FLAG_trace_ignition_dispatches_output_file); |
| 195 static const int kBytecodeCount = static_cast<int>(Bytecode::kLast) + 1; |
| 196 |
| 197 // Output is a JSON-encoded object of objects. |
| 198 // |
| 199 // The keys on the top level object are source bytecodes, |
| 200 // and corresponding value are objects. Keys on these last are the |
| 201 // destinations of the dispatch and the value associated is a counter for |
| 202 // the correspondent source-destination dispatch chain. |
| 203 // |
| 204 // Only non-zero counters are written to file, but an entry in the top-level |
| 205 // object is always present, even if the value is empty because all counters |
| 206 // for that source are zero. |
| 207 |
| 208 stream << '{'; |
| 209 |
| 210 for (int from_index = 0; from_index < kBytecodeCount; ++from_index) { |
| 211 if (from_index > 0) stream << ",\n "; |
| 212 |
| 213 Bytecode from_bytecode = Bytecodes::FromByte(from_index); |
| 214 stream << "\"" << Bytecodes::ToString(from_bytecode) << "\": {"; |
| 215 |
| 216 bool emitted_first = false; |
| 217 for (int to_index = 0; to_index < kBytecodeCount; ++to_index) { |
| 218 uintptr_t counter = |
| 219 bytecode_dispatch_count_table_[from_index * kBytecodeCount + |
| 220 to_index]; |
| 221 if (counter > 0) { |
| 222 if (emitted_first) { |
| 223 stream << ", "; |
| 224 } else { |
| 225 emitted_first = true; |
| 226 } |
| 227 |
| 228 Bytecode to_bytecode = Bytecodes::FromByte(to_index); |
| 229 stream << '"' << Bytecodes::ToString(to_bytecode) << "\": " << counter; |
| 230 } |
| 231 } |
| 232 |
| 233 stream << "}"; |
| 234 } |
| 235 |
| 236 stream << '}'; |
| 237 } |
| 238 |
| 181 // LdaZero | 239 // LdaZero |
| 182 // | 240 // |
| 183 // Load literal '0' into the accumulator. | 241 // Load literal '0' into the accumulator. |
| 184 void Interpreter::DoLdaZero(InterpreterAssembler* assembler) { | 242 void Interpreter::DoLdaZero(InterpreterAssembler* assembler) { |
| 185 Node* zero_value = __ NumberConstant(0.0); | 243 Node* zero_value = __ NumberConstant(0.0); |
| 186 __ SetAccumulator(zero_value); | 244 __ SetAccumulator(zero_value); |
| 187 __ Dispatch(); | 245 __ Dispatch(); |
| 188 } | 246 } |
| 189 | 247 |
| 190 // LdaSmi <imm> | 248 // LdaSmi <imm> |
| (...skipping 1423 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1614 // Illegal | 1672 // Illegal |
| 1615 // | 1673 // |
| 1616 // An invalid bytecode aborting execution if dispatched. | 1674 // An invalid bytecode aborting execution if dispatched. |
| 1617 void Interpreter::DoIllegal(InterpreterAssembler* assembler) { | 1675 void Interpreter::DoIllegal(InterpreterAssembler* assembler) { |
| 1618 __ Abort(kInvalidBytecode); | 1676 __ Abort(kInvalidBytecode); |
| 1619 } | 1677 } |
| 1620 | 1678 |
| 1621 } // namespace interpreter | 1679 } // namespace interpreter |
| 1622 } // namespace internal | 1680 } // namespace internal |
| 1623 } // namespace v8 | 1681 } // namespace v8 |
| OLD | NEW |