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 typedef void (Interpreter::*BytecodeGeneratorFunc)(InterpreterAssembler*); 80 81 // Generates handler for given |bytecode| and |operand_scale| using 82 // |generator| and installs it into the dispatch table. 83 void InstallBytecodeHandler(Zone* zone, Bytecode bytecode, 84 OperandScale operand_scale, 85 BytecodeGeneratorFunc generator); 86 87 // Generates code to perform the binary operation via |Generator|. 88 template <class Generator> 89 void DoBinaryOpWithFeedback(InterpreterAssembler* assembler); 90 91 // Generates code to perform the comparison via |Generator| while gathering 92 // type feedback. 93 void DoCompareOpWithFeedback(Token::Value compare_op, 94 InterpreterAssembler* assembler); 95 96 // Generates code to perform the bitwise binary operation corresponding to 97 // |bitwise_op| while gathering type feedback. 98 void DoBitwiseBinaryOp(Token::Value bitwise_op, 99 InterpreterAssembler* assembler); 100 101 // Generates code to perform the binary operation via |Generator| using 102 // an immediate value rather the accumulator as the rhs operand. 103 template <class Generator> 104 void DoBinaryOpWithImmediate(InterpreterAssembler* assembler); 105 106 // Generates code to perform the unary operation via |Generator| while 107 // gatering type feedback. 108 template <class Generator> 109 void DoUnaryOpWithFeedback(InterpreterAssembler* assembler); 110 111 // Generates code to perform the comparison operation associated with 112 // |compare_op|. 113 void DoCompareOp(Token::Value compare_op, InterpreterAssembler* assembler); 114 115 // Generates code to perform a global store via |ic|. 116 void DoStaGlobal(Callable ic, InterpreterAssembler* assembler); 117 118 // Generates code to perform a named property store via |ic|. 119 void DoStoreIC(Callable ic, InterpreterAssembler* assembler); 120 121 // Generates code to perform a keyed property store via |ic|. 122 void DoKeyedStoreIC(Callable ic, InterpreterAssembler* assembler); 123 124 // Generates code to perform a JS call that collects type feedback. 125 void DoJSCall(InterpreterAssembler* assembler, TailCallMode tail_call_mode); 126 127 // Generates code to perform delete via function_id. 128 void DoDelete(Runtime::FunctionId function_id, 129 InterpreterAssembler* assembler); 130 131 // Generates code to perform a lookup slot load via |function_id|. 132 void DoLdaLookupSlot(Runtime::FunctionId function_id, 133 InterpreterAssembler* assembler); 134 135 // Generates code to perform a lookup slot load via |function_id| that can 136 // fast path to a context slot load. 137 void DoLdaLookupContextSlot(Runtime::FunctionId function_id, 138 InterpreterAssembler* assembler); 139 140 // Generates code to perform a lookup slot load via |function_id| that can 141 // fast path to a global load. 142 void DoLdaLookupGlobalSlot(Runtime::FunctionId function_id, 143 InterpreterAssembler* assembler); 144 145 // Generates code to perform a lookup slot store depending on 146 // |language_mode|. 147 void DoStaLookupSlot(LanguageMode language_mode, 148 InterpreterAssembler* assembler); 149 150 // Generates code to load a global. 151 void BuildLoadGlobal(int slot_operand_index, int name_operand_index, 152 TypeofMode typeof_mode, InterpreterAssembler* assembler); 153 154 // Generates code to prepare the result for ForInPrepare. Cache data 155 // are placed into the consecutive series of registers starting at 156 // |output_register|. 157 void BuildForInPrepareResult(compiler::Node* output_register, 158 compiler::Node* cache_type, 159 compiler::Node* cache_array, 160 compiler::Node* cache_length, 161 InterpreterAssembler* assembler); 162 163 // Generates code to perform the unary operation via |callable|. 164 compiler::Node* BuildUnaryOp(Callable callable, 165 InterpreterAssembler* assembler); 166 167 uintptr_t GetDispatchCounter(Bytecode from, Bytecode to) const; 168 169 // Get dispatch table index of bytecode. 170 static size_t GetDispatchTableIndex(Bytecode bytecode, 171 OperandScale operand_scale); 172 173 bool IsDispatchTableInitialized(); 174 bool ShouldInitializeDispatchTable(); 175 176 static const int kNumberOfWideVariants = 3; 177 static const int kDispatchTableSize = kNumberOfWideVariants * (kMaxUInt8 + 1); 178 static const int kNumberOfBytecodes = static_cast<int>(Bytecode::kLast) + 1; 179 180 Isolate* isolate_; 181 Address dispatch_table_[kDispatchTableSize]; 182 std::unique_ptr<uintptr_t[]> bytecode_dispatch_counters_table_; 183 184 DISALLOW_COPY_AND_ASSIGN(Interpreter); 185 }; 186 187 } // namespace interpreter 188 } // namespace internal 189 } // namespace v8 190 191 #endif // V8_INTERPRETER_INTERPRETER_H_ 192