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> |
7 #include <fstream> | 8 #include <fstream> |
8 #include <memory> | 9 #include <memory> |
9 | 10 |
10 #include "src/ast/prettyprinter.h" | 11 #include "src/ast/prettyprinter.h" |
11 #include "src/builtins/builtins-arguments.h" | 12 #include "src/builtins/builtins-arguments.h" |
12 #include "src/builtins/builtins-constructor.h" | 13 #include "src/builtins/builtins-constructor.h" |
13 #include "src/builtins/builtins-forin.h" | 14 #include "src/builtins/builtins-forin.h" |
14 #include "src/code-factory.h" | 15 #include "src/code-factory.h" |
15 #include "src/compilation-info.h" | 16 #include "src/compilation-info.h" |
16 #include "src/compiler.h" | 17 #include "src/compiler.h" |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
125 for (size_t index = 0; index < arraysize(dispatch_table_); ++index) { | 126 for (size_t index = 0; index < arraysize(dispatch_table_); ++index) { |
126 if (dispatch_table_[index] == nullptr) { | 127 if (dispatch_table_[index] == nullptr) { |
127 dispatch_table_[index] = dispatch_table_[illegal_index]; | 128 dispatch_table_[index] = dispatch_table_[illegal_index]; |
128 } | 129 } |
129 } | 130 } |
130 | 131 |
131 // Initialization should have been successful. | 132 // Initialization should have been successful. |
132 DCHECK(IsDispatchTableInitialized()); | 133 DCHECK(IsDispatchTableInitialized()); |
133 } | 134 } |
134 | 135 |
| 136 bool Interpreter::ReuseExistingHandler(Bytecode bytecode, |
| 137 OperandScale operand_scale) { |
| 138 size_t index = GetDispatchTableIndex(bytecode, operand_scale); |
| 139 switch (bytecode) { |
| 140 case Bytecode::kCallProperty: |
| 141 case Bytecode::kCallProperty0: |
| 142 case Bytecode::kCallProperty1: |
| 143 case Bytecode::kCallProperty2: { |
| 144 const int offset = static_cast<int>(Bytecode::kCallProperty) - |
| 145 static_cast<int>(Bytecode::kCall); |
| 146 STATIC_ASSERT(offset == |
| 147 static_cast<int>(Bytecode::kCallProperty0) - |
| 148 static_cast<int>(Bytecode::kCall0)); |
| 149 STATIC_ASSERT(offset == |
| 150 static_cast<int>(Bytecode::kCallProperty1) - |
| 151 static_cast<int>(Bytecode::kCall1)); |
| 152 STATIC_ASSERT(offset == |
| 153 static_cast<int>(Bytecode::kCallProperty2) - |
| 154 static_cast<int>(Bytecode::kCall2)); |
| 155 CHECK_LT(offset, index); |
| 156 dispatch_table_[index] = dispatch_table_[index - offset]; |
| 157 return true; |
| 158 break; |
| 159 } |
| 160 default: |
| 161 return false; |
| 162 } |
| 163 } |
| 164 |
135 void Interpreter::InstallBytecodeHandler(Zone* zone, Bytecode bytecode, | 165 void Interpreter::InstallBytecodeHandler(Zone* zone, Bytecode bytecode, |
136 OperandScale operand_scale, | 166 OperandScale operand_scale, |
137 BytecodeGeneratorFunc generator) { | 167 BytecodeGeneratorFunc generator) { |
138 if (!Bytecodes::BytecodeHasHandler(bytecode, operand_scale)) return; | 168 if (!Bytecodes::BytecodeHasHandler(bytecode, operand_scale)) return; |
| 169 if (ReuseExistingHandler(bytecode, operand_scale)) return; |
139 | 170 |
| 171 size_t index = GetDispatchTableIndex(bytecode, operand_scale); |
140 InterpreterDispatchDescriptor descriptor(isolate_); | 172 InterpreterDispatchDescriptor descriptor(isolate_); |
141 compiler::CodeAssemblerState state( | 173 compiler::CodeAssemblerState state( |
142 isolate_, zone, descriptor, Code::ComputeFlags(Code::BYTECODE_HANDLER), | 174 isolate_, zone, descriptor, Code::ComputeFlags(Code::BYTECODE_HANDLER), |
143 Bytecodes::ToString(bytecode), Bytecodes::ReturnCount(bytecode)); | 175 Bytecodes::ToString(bytecode), Bytecodes::ReturnCount(bytecode)); |
144 InterpreterAssembler assembler(&state, bytecode, operand_scale); | 176 InterpreterAssembler assembler(&state, bytecode, operand_scale); |
145 if (Bytecodes::MakesCallAlongCriticalPath(bytecode)) { | 177 if (Bytecodes::MakesCallAlongCriticalPath(bytecode)) { |
146 assembler.SaveBytecodeOffset(); | 178 assembler.SaveBytecodeOffset(); |
147 } | 179 } |
148 (this->*generator)(&assembler); | 180 (this->*generator)(&assembler); |
149 Handle<Code> code = compiler::CodeAssembler::GenerateCode(&state); | 181 Handle<Code> code = compiler::CodeAssembler::GenerateCode(&state); |
150 size_t index = GetDispatchTableIndex(bytecode, operand_scale); | |
151 dispatch_table_[index] = code->entry(); | 182 dispatch_table_[index] = code->entry(); |
152 TraceCodegen(code); | 183 TraceCodegen(code); |
153 PROFILE(isolate_, CodeCreateEvent( | 184 PROFILE(isolate_, CodeCreateEvent( |
154 CodeEventListener::BYTECODE_HANDLER_TAG, | 185 CodeEventListener::BYTECODE_HANDLER_TAG, |
155 AbstractCode::cast(*code), | 186 AbstractCode::cast(*code), |
156 Bytecodes::ToString(bytecode, operand_scale).c_str())); | 187 Bytecodes::ToString(bytecode, operand_scale).c_str())); |
157 } | 188 } |
158 | 189 |
159 Code* Interpreter::GetBytecodeHandler(Bytecode bytecode, | 190 Code* Interpreter::GetBytecodeHandler(Bytecode bytecode, |
160 OperandScale operand_scale) { | 191 OperandScale operand_scale) { |
(...skipping 2021 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2182 Node* slot_id = __ BytecodeOperandIdx(3); | 2213 Node* slot_id = __ BytecodeOperandIdx(3); |
2183 Node* feedback_vector = __ LoadFeedbackVector(); | 2214 Node* feedback_vector = __ LoadFeedbackVector(); |
2184 Node* context = __ GetContext(); | 2215 Node* context = __ GetContext(); |
2185 Node* result = | 2216 Node* result = |
2186 __ CallJSWithFeedback(function, context, receiver_arg, args_count, | 2217 __ CallJSWithFeedback(function, context, receiver_arg, args_count, |
2187 slot_id, feedback_vector, tail_call_mode); | 2218 slot_id, feedback_vector, tail_call_mode); |
2188 __ SetAccumulator(result); | 2219 __ SetAccumulator(result); |
2189 __ Dispatch(); | 2220 __ Dispatch(); |
2190 } | 2221 } |
2191 | 2222 |
| 2223 void Interpreter::DoJSCallN(InterpreterAssembler* assembler, int arg_count) { |
| 2224 const int kReceiverOperandIndex = 1; |
| 2225 const int kReceiverOperandCount = 1; |
| 2226 const int kSlotOperandIndex = |
| 2227 kReceiverOperandIndex + kReceiverOperandCount + arg_count; |
| 2228 const int kBoilerplatParameterCount = 7; |
| 2229 const int kReceiverParameterIndex = 5; |
| 2230 |
| 2231 Node* function_reg = __ BytecodeOperandReg(0); |
| 2232 Node* function = __ LoadRegister(function_reg); |
| 2233 std::array<Node*, Bytecodes::kMaxOperands + kBoilerplatParameterCount> temp; |
| 2234 Callable call_ic = CodeFactory::CallIC(isolate_); |
| 2235 temp[0] = __ HeapConstant(call_ic.code()); |
| 2236 temp[1] = function; |
| 2237 temp[2] = __ Int32Constant(arg_count); |
| 2238 temp[3] = __ BytecodeOperandIdxInt32(kSlotOperandIndex); |
| 2239 temp[4] = __ LoadFeedbackVector(); |
| 2240 for (int i = 0; i < (arg_count + kReceiverOperandCount); ++i) { |
| 2241 Node* reg = __ BytecodeOperandReg(i + kReceiverOperandIndex); |
| 2242 temp[kReceiverParameterIndex + i] = __ LoadRegister(reg); |
| 2243 } |
| 2244 temp[kReceiverParameterIndex + arg_count + kReceiverOperandCount] = |
| 2245 __ GetContext(); |
| 2246 Node* result = __ CallStubN(call_ic.descriptor(), 1, |
| 2247 arg_count + kBoilerplatParameterCount, &temp[0]); |
| 2248 __ SetAccumulator(result); |
| 2249 __ Dispatch(); |
| 2250 } |
| 2251 |
2192 // Call <callable> <receiver> <arg_count> <feedback_slot_id> | 2252 // Call <callable> <receiver> <arg_count> <feedback_slot_id> |
2193 // | 2253 // |
2194 // Call a JSfunction or Callable in |callable| with the |receiver| and | 2254 // Call a JSfunction or Callable in |callable| with the |receiver| and |
2195 // |arg_count| arguments in subsequent registers. Collect type feedback | 2255 // |arg_count| arguments in subsequent registers. Collect type feedback |
2196 // into |feedback_slot_id| | 2256 // into |feedback_slot_id| |
2197 void Interpreter::DoCall(InterpreterAssembler* assembler) { | 2257 void Interpreter::DoCall(InterpreterAssembler* assembler) { |
2198 DoJSCall(assembler, TailCallMode::kDisallow); | 2258 DoJSCall(assembler, TailCallMode::kDisallow); |
2199 } | 2259 } |
2200 | 2260 |
2201 // CallProperty <callable> <receiver> <arg_count> <feedback_slot_id> | 2261 void Interpreter::DoCall0(InterpreterAssembler* assembler) { |
2202 // | 2262 DoJSCallN(assembler, 0); |
2203 // Call a JSfunction or Callable in |callable| with the |receiver| and | 2263 } |
2204 // |arg_count| arguments in subsequent registers. Collect type feedback into | 2264 |
2205 // |feedback_slot_id|. The callable is known to be a property of the receiver. | 2265 void Interpreter::DoCall1(InterpreterAssembler* assembler) { |
| 2266 DoJSCallN(assembler, 1); |
| 2267 } |
| 2268 |
| 2269 void Interpreter::DoCall2(InterpreterAssembler* assembler) { |
| 2270 DoJSCallN(assembler, 2); |
| 2271 } |
| 2272 |
2206 void Interpreter::DoCallProperty(InterpreterAssembler* assembler) { | 2273 void Interpreter::DoCallProperty(InterpreterAssembler* assembler) { |
2207 // TODO(leszeks): Look into making the interpreter use the fact that the | 2274 // Same as Call |
2208 // receiver is non-null. | 2275 UNREACHABLE(); |
2209 DoJSCall(assembler, TailCallMode::kDisallow); | 2276 } |
| 2277 |
| 2278 void Interpreter::DoCallProperty0(InterpreterAssembler* assembler) { |
| 2279 // Same as Call0 |
| 2280 UNREACHABLE(); |
| 2281 } |
| 2282 |
| 2283 void Interpreter::DoCallProperty1(InterpreterAssembler* assembler) { |
| 2284 // Same as Call1 |
| 2285 UNREACHABLE(); |
| 2286 } |
| 2287 |
| 2288 void Interpreter::DoCallProperty2(InterpreterAssembler* assembler) { |
| 2289 // Same as Call2 |
| 2290 UNREACHABLE(); |
2210 } | 2291 } |
2211 | 2292 |
2212 // TailCall <callable> <receiver> <arg_count> <feedback_slot_id> | 2293 // TailCall <callable> <receiver> <arg_count> <feedback_slot_id> |
2213 // | 2294 // |
2214 // Tail call a JSfunction or Callable in |callable| with the |receiver| and | 2295 // Tail call a JSfunction or Callable in |callable| with the |receiver| and |
2215 // |arg_count| arguments in subsequent registers. Collect type feedback | 2296 // |arg_count| arguments in subsequent registers. Collect type feedback |
2216 // into |feedback_slot_id| | 2297 // into |feedback_slot_id| |
2217 void Interpreter::DoTailCall(InterpreterAssembler* assembler) { | 2298 void Interpreter::DoTailCall(InterpreterAssembler* assembler) { |
2218 DoJSCall(assembler, TailCallMode::kAllow); | 2299 DoJSCall(assembler, TailCallMode::kAllow); |
2219 } | 2300 } |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2259 // <first_return + 1> | 2340 // <first_return + 1> |
2260 void Interpreter::DoCallRuntimeForPair(InterpreterAssembler* assembler) { | 2341 void Interpreter::DoCallRuntimeForPair(InterpreterAssembler* assembler) { |
2261 // Call the runtime function. | 2342 // Call the runtime function. |
2262 Node* function_id = __ BytecodeOperandRuntimeId(0); | 2343 Node* function_id = __ BytecodeOperandRuntimeId(0); |
2263 Node* first_arg_reg = __ BytecodeOperandReg(1); | 2344 Node* first_arg_reg = __ BytecodeOperandReg(1); |
2264 Node* first_arg = __ RegisterLocation(first_arg_reg); | 2345 Node* first_arg = __ RegisterLocation(first_arg_reg); |
2265 Node* args_count = __ BytecodeOperandCount(2); | 2346 Node* args_count = __ BytecodeOperandCount(2); |
2266 Node* context = __ GetContext(); | 2347 Node* context = __ GetContext(); |
2267 Node* result_pair = | 2348 Node* result_pair = |
2268 __ CallRuntimeN(function_id, context, first_arg, args_count, 2); | 2349 __ CallRuntimeN(function_id, context, first_arg, args_count, 2); |
2269 | |
2270 // Store the results in <first_return> and <first_return + 1> | 2350 // Store the results in <first_return> and <first_return + 1> |
2271 Node* first_return_reg = __ BytecodeOperandReg(3); | 2351 Node* first_return_reg = __ BytecodeOperandReg(3); |
2272 Node* second_return_reg = __ NextRegister(first_return_reg); | 2352 Node* second_return_reg = __ NextRegister(first_return_reg); |
2273 Node* result0 = __ Projection(0, result_pair); | 2353 Node* result0 = __ Projection(0, result_pair); |
2274 Node* result1 = __ Projection(1, result_pair); | 2354 Node* result1 = __ Projection(1, result_pair); |
2275 __ StoreRegister(result0, first_return_reg); | 2355 __ StoreRegister(result0, first_return_reg); |
2276 __ StoreRegister(result1, second_return_reg); | 2356 __ StoreRegister(result1, second_return_reg); |
2277 __ Dispatch(); | 2357 __ Dispatch(); |
2278 } | 2358 } |
2279 | 2359 |
(...skipping 1118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3398 __ StoreObjectField(generator, JSGeneratorObject::kContinuationOffset, | 3478 __ StoreObjectField(generator, JSGeneratorObject::kContinuationOffset, |
3399 __ SmiTag(new_state)); | 3479 __ SmiTag(new_state)); |
3400 __ SetAccumulator(old_state); | 3480 __ SetAccumulator(old_state); |
3401 | 3481 |
3402 __ Dispatch(); | 3482 __ Dispatch(); |
3403 } | 3483 } |
3404 | 3484 |
3405 } // namespace interpreter | 3485 } // namespace interpreter |
3406 } // namespace internal | 3486 } // namespace internal |
3407 } // namespace v8 | 3487 } // namespace v8 |
OLD | NEW |