| 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 |