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 <array> | |
8 #include <fstream> | 7 #include <fstream> |
9 #include <memory> | 8 #include <memory> |
10 | 9 |
11 #include "src/ast/prettyprinter.h" | 10 #include "src/ast/prettyprinter.h" |
12 #include "src/builtins/builtins-arguments.h" | 11 #include "src/builtins/builtins-arguments.h" |
13 #include "src/builtins/builtins-constructor.h" | 12 #include "src/builtins/builtins-constructor.h" |
14 #include "src/builtins/builtins-object.h" | 13 #include "src/builtins/builtins-object.h" |
15 #include "src/code-factory.h" | 14 #include "src/code-factory.h" |
16 #include "src/compilation-info.h" | 15 #include "src/compilation-info.h" |
17 #include "src/compiler.h" | 16 #include "src/compiler.h" |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
123 for (size_t index = 0; index < arraysize(dispatch_table_); ++index) { | 122 for (size_t index = 0; index < arraysize(dispatch_table_); ++index) { |
124 if (dispatch_table_[index] == nullptr) { | 123 if (dispatch_table_[index] == nullptr) { |
125 dispatch_table_[index] = dispatch_table_[illegal_index]; | 124 dispatch_table_[index] = dispatch_table_[illegal_index]; |
126 } | 125 } |
127 } | 126 } |
128 | 127 |
129 // Initialization should have been successful. | 128 // Initialization should have been successful. |
130 DCHECK(IsDispatchTableInitialized()); | 129 DCHECK(IsDispatchTableInitialized()); |
131 } | 130 } |
132 | 131 |
133 bool Interpreter::ReuseExistingHandler(Bytecode bytecode, | |
134 OperandScale operand_scale) { | |
135 size_t index = GetDispatchTableIndex(bytecode, operand_scale); | |
136 switch (bytecode) { | |
137 case Bytecode::kCallProperty: | |
138 case Bytecode::kCallProperty0: | |
139 case Bytecode::kCallProperty1: | |
140 case Bytecode::kCallProperty2: { | |
141 const int offset = static_cast<int>(Bytecode::kCallProperty) - | |
142 static_cast<int>(Bytecode::kCall); | |
143 STATIC_ASSERT(offset == | |
144 static_cast<int>(Bytecode::kCallProperty0) - | |
145 static_cast<int>(Bytecode::kCall0)); | |
146 STATIC_ASSERT(offset == | |
147 static_cast<int>(Bytecode::kCallProperty1) - | |
148 static_cast<int>(Bytecode::kCall1)); | |
149 STATIC_ASSERT(offset == | |
150 static_cast<int>(Bytecode::kCallProperty2) - | |
151 static_cast<int>(Bytecode::kCall2)); | |
152 CHECK_LT(offset, index); | |
153 dispatch_table_[index] = dispatch_table_[index - offset]; | |
154 return true; | |
155 break; | |
156 } | |
157 default: | |
158 return false; | |
159 } | |
160 } | |
161 | |
162 void Interpreter::InstallBytecodeHandler(Zone* zone, Bytecode bytecode, | 132 void Interpreter::InstallBytecodeHandler(Zone* zone, Bytecode bytecode, |
163 OperandScale operand_scale, | 133 OperandScale operand_scale, |
164 BytecodeGeneratorFunc generator) { | 134 BytecodeGeneratorFunc generator) { |
165 if (!Bytecodes::BytecodeHasHandler(bytecode, operand_scale)) return; | 135 if (!Bytecodes::BytecodeHasHandler(bytecode, operand_scale)) return; |
166 if (ReuseExistingHandler(bytecode, operand_scale)) return; | |
167 | 136 |
168 size_t index = GetDispatchTableIndex(bytecode, operand_scale); | |
169 InterpreterDispatchDescriptor descriptor(isolate_); | 137 InterpreterDispatchDescriptor descriptor(isolate_); |
170 compiler::CodeAssemblerState state( | 138 compiler::CodeAssemblerState state( |
171 isolate_, zone, descriptor, Code::ComputeFlags(Code::BYTECODE_HANDLER), | 139 isolate_, zone, descriptor, Code::ComputeFlags(Code::BYTECODE_HANDLER), |
172 Bytecodes::ToString(bytecode), Bytecodes::ReturnCount(bytecode)); | 140 Bytecodes::ToString(bytecode), Bytecodes::ReturnCount(bytecode)); |
173 InterpreterAssembler assembler(&state, bytecode, operand_scale); | 141 InterpreterAssembler assembler(&state, bytecode, operand_scale); |
174 if (Bytecodes::MakesCallAlongCriticalPath(bytecode)) { | 142 if (Bytecodes::MakesCallAlongCriticalPath(bytecode)) { |
175 assembler.SaveBytecodeOffset(); | 143 assembler.SaveBytecodeOffset(); |
176 } | 144 } |
177 (this->*generator)(&assembler); | 145 (this->*generator)(&assembler); |
178 Handle<Code> code = compiler::CodeAssembler::GenerateCode(&state); | 146 Handle<Code> code = compiler::CodeAssembler::GenerateCode(&state); |
| 147 size_t index = GetDispatchTableIndex(bytecode, operand_scale); |
179 dispatch_table_[index] = code->entry(); | 148 dispatch_table_[index] = code->entry(); |
180 TraceCodegen(code); | 149 TraceCodegen(code); |
181 PROFILE(isolate_, CodeCreateEvent( | 150 PROFILE(isolate_, CodeCreateEvent( |
182 CodeEventListener::BYTECODE_HANDLER_TAG, | 151 CodeEventListener::BYTECODE_HANDLER_TAG, |
183 AbstractCode::cast(*code), | 152 AbstractCode::cast(*code), |
184 Bytecodes::ToString(bytecode, operand_scale).c_str())); | 153 Bytecodes::ToString(bytecode, operand_scale).c_str())); |
185 } | 154 } |
186 | 155 |
187 Code* Interpreter::GetBytecodeHandler(Bytecode bytecode, | 156 Code* Interpreter::GetBytecodeHandler(Bytecode bytecode, |
188 OperandScale operand_scale) { | 157 OperandScale operand_scale) { |
(...skipping 1996 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2185 Node* slot_id = __ BytecodeOperandIdx(3); | 2154 Node* slot_id = __ BytecodeOperandIdx(3); |
2186 Node* feedback_vector = __ LoadFeedbackVector(); | 2155 Node* feedback_vector = __ LoadFeedbackVector(); |
2187 Node* context = __ GetContext(); | 2156 Node* context = __ GetContext(); |
2188 Node* result = | 2157 Node* result = |
2189 __ CallJSWithFeedback(function, context, receiver_arg, args_count, | 2158 __ CallJSWithFeedback(function, context, receiver_arg, args_count, |
2190 slot_id, feedback_vector, tail_call_mode); | 2159 slot_id, feedback_vector, tail_call_mode); |
2191 __ SetAccumulator(result); | 2160 __ SetAccumulator(result); |
2192 __ Dispatch(); | 2161 __ Dispatch(); |
2193 } | 2162 } |
2194 | 2163 |
2195 void Interpreter::DoJSCallN(InterpreterAssembler* assembler, int arg_count) { | |
2196 const int kReceiverOperandIndex = 1; | |
2197 const int kReceiverOperandCount = 1; | |
2198 const int kSlotOperandIndex = | |
2199 kReceiverOperandIndex + kReceiverOperandCount + arg_count; | |
2200 const int kBoilerplatParameterCount = 7; | |
2201 const int kReceiverParameterIndex = 5; | |
2202 | |
2203 Node* function_reg = __ BytecodeOperandReg(0); | |
2204 Node* function = __ LoadRegister(function_reg); | |
2205 std::array<Node*, Bytecodes::kMaxOperands + kBoilerplatParameterCount> temp; | |
2206 Callable call_ic = CodeFactory::CallIC(isolate_); | |
2207 temp[0] = __ HeapConstant(call_ic.code()); | |
2208 temp[1] = function; | |
2209 temp[2] = __ Int32Constant(arg_count); | |
2210 temp[3] = __ BytecodeOperandIdxInt32(kSlotOperandIndex); | |
2211 temp[4] = __ LoadFeedbackVector(); | |
2212 for (int i = 0; i < (arg_count + kReceiverOperandCount); ++i) { | |
2213 Node* reg = __ BytecodeOperandReg(i + kReceiverOperandIndex); | |
2214 temp[kReceiverParameterIndex + i] = __ LoadRegister(reg); | |
2215 } | |
2216 temp[kReceiverParameterIndex + arg_count + kReceiverOperandCount] = | |
2217 __ GetContext(); | |
2218 Node* result = __ CallStubN(call_ic.descriptor(), 1, | |
2219 arg_count + kBoilerplatParameterCount, &temp[0]); | |
2220 __ SetAccumulator(result); | |
2221 __ Dispatch(); | |
2222 } | |
2223 | |
2224 // Call <callable> <receiver> <arg_count> <feedback_slot_id> | 2164 // Call <callable> <receiver> <arg_count> <feedback_slot_id> |
2225 // | 2165 // |
2226 // Call a JSfunction or Callable in |callable| with the |receiver| and | 2166 // Call a JSfunction or Callable in |callable| with the |receiver| and |
2227 // |arg_count| arguments in subsequent registers. Collect type feedback | 2167 // |arg_count| arguments in subsequent registers. Collect type feedback |
2228 // into |feedback_slot_id| | 2168 // into |feedback_slot_id| |
2229 void Interpreter::DoCall(InterpreterAssembler* assembler) { | 2169 void Interpreter::DoCall(InterpreterAssembler* assembler) { |
2230 DoJSCall(assembler, TailCallMode::kDisallow); | 2170 DoJSCall(assembler, TailCallMode::kDisallow); |
2231 } | 2171 } |
2232 | 2172 |
2233 void Interpreter::DoCall0(InterpreterAssembler* assembler) { | 2173 // CallProperty <callable> <receiver> <arg_count> <feedback_slot_id> |
2234 DoJSCallN(assembler, 0); | 2174 // |
2235 } | 2175 // Call a JSfunction or Callable in |callable| with the |receiver| and |
2236 | 2176 // |arg_count| arguments in subsequent registers. Collect type feedback into |
2237 void Interpreter::DoCall1(InterpreterAssembler* assembler) { | 2177 // |feedback_slot_id|. The callable is known to be a property of the receiver. |
2238 DoJSCallN(assembler, 1); | |
2239 } | |
2240 | |
2241 void Interpreter::DoCall2(InterpreterAssembler* assembler) { | |
2242 DoJSCallN(assembler, 2); | |
2243 } | |
2244 | |
2245 void Interpreter::DoCallProperty(InterpreterAssembler* assembler) { | 2178 void Interpreter::DoCallProperty(InterpreterAssembler* assembler) { |
2246 // Same as Call | 2179 // TODO(leszeks): Look into making the interpreter use the fact that the |
2247 UNREACHABLE(); | 2180 // receiver is non-null. |
2248 } | 2181 DoJSCall(assembler, TailCallMode::kDisallow); |
2249 | |
2250 void Interpreter::DoCallProperty0(InterpreterAssembler* assembler) { | |
2251 // Same as Call0 | |
2252 UNREACHABLE(); | |
2253 } | |
2254 | |
2255 void Interpreter::DoCallProperty1(InterpreterAssembler* assembler) { | |
2256 // Same as Call1 | |
2257 UNREACHABLE(); | |
2258 } | |
2259 | |
2260 void Interpreter::DoCallProperty2(InterpreterAssembler* assembler) { | |
2261 // Same as Call2 | |
2262 UNREACHABLE(); | |
2263 } | 2182 } |
2264 | 2183 |
2265 // TailCall <callable> <receiver> <arg_count> <feedback_slot_id> | 2184 // TailCall <callable> <receiver> <arg_count> <feedback_slot_id> |
2266 // | 2185 // |
2267 // Tail call a JSfunction or Callable in |callable| with the |receiver| and | 2186 // Tail call a JSfunction or Callable in |callable| with the |receiver| and |
2268 // |arg_count| arguments in subsequent registers. Collect type feedback | 2187 // |arg_count| arguments in subsequent registers. Collect type feedback |
2269 // into |feedback_slot_id| | 2188 // into |feedback_slot_id| |
2270 void Interpreter::DoTailCall(InterpreterAssembler* assembler) { | 2189 void Interpreter::DoTailCall(InterpreterAssembler* assembler) { |
2271 DoJSCall(assembler, TailCallMode::kAllow); | 2190 DoJSCall(assembler, TailCallMode::kAllow); |
2272 } | 2191 } |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2312 // <first_return + 1> | 2231 // <first_return + 1> |
2313 void Interpreter::DoCallRuntimeForPair(InterpreterAssembler* assembler) { | 2232 void Interpreter::DoCallRuntimeForPair(InterpreterAssembler* assembler) { |
2314 // Call the runtime function. | 2233 // Call the runtime function. |
2315 Node* function_id = __ BytecodeOperandRuntimeId(0); | 2234 Node* function_id = __ BytecodeOperandRuntimeId(0); |
2316 Node* first_arg_reg = __ BytecodeOperandReg(1); | 2235 Node* first_arg_reg = __ BytecodeOperandReg(1); |
2317 Node* first_arg = __ RegisterLocation(first_arg_reg); | 2236 Node* first_arg = __ RegisterLocation(first_arg_reg); |
2318 Node* args_count = __ BytecodeOperandCount(2); | 2237 Node* args_count = __ BytecodeOperandCount(2); |
2319 Node* context = __ GetContext(); | 2238 Node* context = __ GetContext(); |
2320 Node* result_pair = | 2239 Node* result_pair = |
2321 __ CallRuntimeN(function_id, context, first_arg, args_count, 2); | 2240 __ CallRuntimeN(function_id, context, first_arg, args_count, 2); |
| 2241 |
2322 // Store the results in <first_return> and <first_return + 1> | 2242 // Store the results in <first_return> and <first_return + 1> |
2323 Node* first_return_reg = __ BytecodeOperandReg(3); | 2243 Node* first_return_reg = __ BytecodeOperandReg(3); |
2324 Node* second_return_reg = __ NextRegister(first_return_reg); | 2244 Node* second_return_reg = __ NextRegister(first_return_reg); |
2325 Node* result0 = __ Projection(0, result_pair); | 2245 Node* result0 = __ Projection(0, result_pair); |
2326 Node* result1 = __ Projection(1, result_pair); | 2246 Node* result1 = __ Projection(1, result_pair); |
2327 __ StoreRegister(result0, first_return_reg); | 2247 __ StoreRegister(result0, first_return_reg); |
2328 __ StoreRegister(result1, second_return_reg); | 2248 __ StoreRegister(result1, second_return_reg); |
2329 __ Dispatch(); | 2249 __ Dispatch(); |
2330 } | 2250 } |
2331 | 2251 |
(...skipping 1126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3458 __ StoreObjectField(generator, JSGeneratorObject::kContinuationOffset, | 3378 __ StoreObjectField(generator, JSGeneratorObject::kContinuationOffset, |
3459 __ SmiTag(new_state)); | 3379 __ SmiTag(new_state)); |
3460 __ SetAccumulator(old_state); | 3380 __ SetAccumulator(old_state); |
3461 | 3381 |
3462 __ Dispatch(); | 3382 __ Dispatch(); |
3463 } | 3383 } |
3464 | 3384 |
3465 } // namespace interpreter | 3385 } // namespace interpreter |
3466 } // namespace internal | 3386 } // namespace internal |
3467 } // namespace v8 | 3387 } // namespace v8 |
OLD | NEW |