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 |