• Home
  • History
  • Annotate
  • 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  #ifndef V8_INTERPRETER_INTERPRETER_H_
6  #define V8_INTERPRETER_INTERPRETER_H_
7  
8  #include <memory>
9  
10  // Clients of this interface shouldn't depend on lots of interpreter internals.
11  // Do not include anything from src/interpreter other than
12  // src/interpreter/bytecodes.h here!
13  #include "src/base/macros.h"
14  #include "src/builtins/builtins.h"
15  #include "src/interpreter/bytecodes.h"
16  #include "src/parsing/token.h"
17  #include "src/runtime/runtime.h"
18  
19  namespace v8 {
20  namespace internal {
21  
22  class Isolate;
23  class Callable;
24  class CompilationInfo;
25  class CompilationJob;
26  
27  namespace compiler {
28  class Node;
29  }  // namespace compiler
30  
31  namespace interpreter {
32  
33  class InterpreterAssembler;
34  
35  class Interpreter {
36   public:
37    explicit Interpreter(Isolate* isolate);
~Interpreter()38    virtual ~Interpreter() {}
39  
40    // Initializes the interpreter dispatch table.
41    void Initialize();
42  
43    // Returns the interrupt budget which should be used for the profiler counter.
44    static int InterruptBudget();
45  
46    // Creates a compilation job which will generate bytecode for |info|.
47    static CompilationJob* NewCompilationJob(CompilationInfo* info);
48  
49    // Return bytecode handler for |bytecode|.
50    Code* GetBytecodeHandler(Bytecode bytecode, OperandScale operand_scale);
51  
52    // GC support.
53    void IterateDispatchTable(ObjectVisitor* v);
54  
55    // Disassembler support (only useful with ENABLE_DISASSEMBLER defined).
56    void TraceCodegen(Handle<Code> code);
57    const char* LookupNameOfBytecodeHandler(Code* code);
58  
59    V8_EXPORT_PRIVATE Local<v8::Object> GetDispatchCountersObject();
60  
dispatch_table_address()61    Address dispatch_table_address() {
62      return reinterpret_cast<Address>(&dispatch_table_[0]);
63    }
64  
bytecode_dispatch_counters_table()65    Address bytecode_dispatch_counters_table() {
66      return reinterpret_cast<Address>(bytecode_dispatch_counters_table_.get());
67    }
68  
69    // TODO(ignition): Tune code size multiplier.
70    static const int kCodeSizeMultiplier = 32;
71  
72   private:
73  // Bytecode handler generator functions.
74  #define DECLARE_BYTECODE_HANDLER_GENERATOR(Name, ...) \
75    void Do##Name(InterpreterAssembler* assembler);
76    BYTECODE_LIST(DECLARE_BYTECODE_HANDLER_GENERATOR)
77  #undef DECLARE_BYTECODE_HANDLER_GENERATOR
78  
79    // Generates code to perform the binary operation via |Generator|.
80    template <class Generator>
81    void DoBinaryOpWithFeedback(InterpreterAssembler* assembler);
82  
83    // Generates code to perform the comparison via |Generator| while gathering
84    // type feedback.
85    void DoCompareOpWithFeedback(Token::Value compare_op,
86                                 InterpreterAssembler* assembler);
87  
88    // Generates code to perform the bitwise binary operation corresponding to
89    // |bitwise_op| while gathering type feedback.
90    void DoBitwiseBinaryOp(Token::Value bitwise_op,
91                           InterpreterAssembler* assembler);
92  
93    // Generates code to perform the binary operation via |Generator| using
94    // an immediate value rather the accumulator as the rhs operand.
95    template <class Generator>
96    void DoBinaryOpWithImmediate(InterpreterAssembler* assembler);
97  
98    // Generates code to perform the unary operation via |Generator| while
99    // gatering type feedback.
100    template <class Generator>
101    void DoUnaryOpWithFeedback(InterpreterAssembler* assembler);
102  
103    // Generates code to perform the comparison operation associated with
104    // |compare_op|.
105    void DoCompareOp(Token::Value compare_op, InterpreterAssembler* assembler);
106  
107    // Generates code to perform a global store via |ic|.
108    void DoStaGlobal(Callable ic, InterpreterAssembler* assembler);
109  
110    // Generates code to perform a named property store via |ic|.
111    void DoStoreIC(Callable ic, InterpreterAssembler* assembler);
112  
113    // Generates code to perform a keyed property store via |ic|.
114    void DoKeyedStoreIC(Callable ic, InterpreterAssembler* assembler);
115  
116    // Generates code to perform a JS call that collects type feedback.
117    void DoJSCall(InterpreterAssembler* assembler, TailCallMode tail_call_mode);
118  
119    // Generates code to perform delete via function_id.
120    void DoDelete(Runtime::FunctionId function_id,
121                  InterpreterAssembler* assembler);
122  
123    // Generates code to perform a lookup slot load via |function_id|.
124    void DoLdaLookupSlot(Runtime::FunctionId function_id,
125                         InterpreterAssembler* assembler);
126  
127    // Generates code to perform a lookup slot load via |function_id| that can
128    // fast path to a context slot load.
129    void DoLdaLookupContextSlot(Runtime::FunctionId function_id,
130                                InterpreterAssembler* assembler);
131  
132    // Generates code to perform a lookup slot load via |function_id| that can
133    // fast path to a global load.
134    void DoLdaLookupGlobalSlot(Runtime::FunctionId function_id,
135                               InterpreterAssembler* assembler);
136  
137    // Generates code to perform a lookup slot store depending on
138    // |language_mode|.
139    void DoStaLookupSlot(LanguageMode language_mode,
140                         InterpreterAssembler* assembler);
141  
142    // Generates code to load a global.
143    compiler::Node* BuildLoadGlobal(Callable ic, compiler::Node* context,
144                                    compiler::Node* feedback_slot,
145                                    InterpreterAssembler* assembler);
146  
147    // Generates code to prepare the result for ForInPrepare. Cache data
148    // are placed into the consecutive series of registers starting at
149    // |output_register|.
150    void BuildForInPrepareResult(compiler::Node* output_register,
151                                 compiler::Node* cache_type,
152                                 compiler::Node* cache_array,
153                                 compiler::Node* cache_length,
154                                 InterpreterAssembler* assembler);
155  
156    // Generates code to perform the unary operation via |callable|.
157    compiler::Node* BuildUnaryOp(Callable callable,
158                                 InterpreterAssembler* assembler);
159  
160    uintptr_t GetDispatchCounter(Bytecode from, Bytecode to) const;
161  
162    // Get dispatch table index of bytecode.
163    static size_t GetDispatchTableIndex(Bytecode bytecode,
164                                        OperandScale operand_scale);
165  
166    bool IsDispatchTableInitialized();
167    bool ShouldInitializeDispatchTable();
168  
169    static const int kNumberOfWideVariants = 3;
170    static const int kDispatchTableSize = kNumberOfWideVariants * (kMaxUInt8 + 1);
171    static const int kNumberOfBytecodes = static_cast<int>(Bytecode::kLast) + 1;
172  
173    Isolate* isolate_;
174    Address dispatch_table_[kDispatchTableSize];
175    std::unique_ptr<uintptr_t[]> bytecode_dispatch_counters_table_;
176  
177    DISALLOW_COPY_AND_ASSIGN(Interpreter);
178  };
179  
180  }  // namespace interpreter
181  }  // namespace internal
182  }  // namespace v8
183  
184  #endif  // V8_INTERPRETER_INTERPRETER_H_
185