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-object.h" | 14 #include "src/builtins/builtins-object.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 110 matching lines...) Loading... | |
127 | 128 |
128 // Initialization should have been successful. | 129 // Initialization should have been successful. |
129 DCHECK(IsDispatchTableInitialized()); | 130 DCHECK(IsDispatchTableInitialized()); |
130 } | 131 } |
131 | 132 |
132 void Interpreter::InstallBytecodeHandler(Zone* zone, Bytecode bytecode, | 133 void Interpreter::InstallBytecodeHandler(Zone* zone, Bytecode bytecode, |
133 OperandScale operand_scale, | 134 OperandScale operand_scale, |
134 BytecodeGeneratorFunc generator) { | 135 BytecodeGeneratorFunc generator) { |
135 if (!Bytecodes::BytecodeHasHandler(bytecode, operand_scale)) return; | 136 if (!Bytecodes::BytecodeHasHandler(bytecode, operand_scale)) return; |
136 | 137 |
137 InterpreterDispatchDescriptor descriptor(isolate_); | 138 size_t index = GetDispatchTableIndex(bytecode, operand_scale); |
138 compiler::CodeAssemblerState state( | 139 switch (bytecode) { |
139 isolate_, zone, descriptor, Code::ComputeFlags(Code::BYTECODE_HANDLER), | 140 case Bytecode::kCallProperty: |
140 Bytecodes::ToString(bytecode), Bytecodes::ReturnCount(bytecode)); | 141 case Bytecode::kCallProperty0: |
141 InterpreterAssembler assembler(&state, bytecode, operand_scale); | 142 case Bytecode::kCallProperty1: |
142 if (Bytecodes::MakesCallAlongCriticalPath(bytecode)) { | 143 case Bytecode::kCallProperty2: { |
143 assembler.SaveBytecodeOffset(); | 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)); | |
rmcilroy
2017/02/17 11:37:19
Can you also DCHECK that offset < index
danno
2017/02/17 17:18:43
Done.
| |
155 dispatch_table_[index] = dispatch_table_[index - offset]; | |
156 break; | |
157 } | |
rmcilroy
2017/02/17 11:37:19
Could we pull the duplication logic out to a separ
danno
2017/02/17 17:18:43
Done.
| |
158 | |
159 default: { | |
160 InterpreterDispatchDescriptor descriptor(isolate_); | |
161 compiler::CodeAssemblerState state( | |
162 isolate_, zone, descriptor, | |
163 Code::ComputeFlags(Code::BYTECODE_HANDLER), | |
164 Bytecodes::ToString(bytecode), Bytecodes::ReturnCount(bytecode)); | |
165 InterpreterAssembler assembler(&state, bytecode, operand_scale); | |
166 if (Bytecodes::MakesCallAlongCriticalPath(bytecode)) { | |
167 assembler.SaveBytecodeOffset(); | |
168 } | |
169 (this->*generator)(&assembler); | |
170 Handle<Code> code = compiler::CodeAssembler::GenerateCode(&state); | |
171 dispatch_table_[index] = code->entry(); | |
172 TraceCodegen(code); | |
173 PROFILE(isolate_, | |
174 CodeCreateEvent( | |
175 CodeEventListener::BYTECODE_HANDLER_TAG, | |
176 AbstractCode::cast(*code), | |
177 Bytecodes::ToString(bytecode, operand_scale).c_str())); | |
178 break; | |
179 } | |
144 } | 180 } |
145 (this->*generator)(&assembler); | |
146 Handle<Code> code = compiler::CodeAssembler::GenerateCode(&state); | |
147 size_t index = GetDispatchTableIndex(bytecode, operand_scale); | |
148 dispatch_table_[index] = code->entry(); | |
149 TraceCodegen(code); | |
150 PROFILE(isolate_, CodeCreateEvent( | |
151 CodeEventListener::BYTECODE_HANDLER_TAG, | |
152 AbstractCode::cast(*code), | |
153 Bytecodes::ToString(bytecode, operand_scale).c_str())); | |
154 } | 181 } |
155 | 182 |
156 Code* Interpreter::GetBytecodeHandler(Bytecode bytecode, | 183 Code* Interpreter::GetBytecodeHandler(Bytecode bytecode, |
157 OperandScale operand_scale) { | 184 OperandScale operand_scale) { |
158 DCHECK(IsDispatchTableInitialized()); | 185 DCHECK(IsDispatchTableInitialized()); |
159 DCHECK(Bytecodes::BytecodeHasHandler(bytecode, operand_scale)); | 186 DCHECK(Bytecodes::BytecodeHasHandler(bytecode, operand_scale)); |
160 size_t index = GetDispatchTableIndex(bytecode, operand_scale); | 187 size_t index = GetDispatchTableIndex(bytecode, operand_scale); |
161 Address code_entry = dispatch_table_[index]; | 188 Address code_entry = dispatch_table_[index]; |
162 return Code::GetCodeFromTargetAddress(code_entry); | 189 return Code::GetCodeFromTargetAddress(code_entry); |
163 } | 190 } |
(...skipping 1980 matching lines...) Loading... | |
2144 Node* slot_id = __ BytecodeOperandIdx(3); | 2171 Node* slot_id = __ BytecodeOperandIdx(3); |
2145 Node* feedback_vector = __ LoadFeedbackVector(); | 2172 Node* feedback_vector = __ LoadFeedbackVector(); |
2146 Node* context = __ GetContext(); | 2173 Node* context = __ GetContext(); |
2147 Node* result = | 2174 Node* result = |
2148 __ CallJSWithFeedback(function, context, receiver_arg, args_count, | 2175 __ CallJSWithFeedback(function, context, receiver_arg, args_count, |
2149 slot_id, feedback_vector, tail_call_mode); | 2176 slot_id, feedback_vector, tail_call_mode); |
2150 __ SetAccumulator(result); | 2177 __ SetAccumulator(result); |
2151 __ Dispatch(); | 2178 __ Dispatch(); |
2152 } | 2179 } |
2153 | 2180 |
2181 void Interpreter::DoJSCallN(InterpreterAssembler* assembler, int n) { | |
rmcilroy
2017/02/17 11:37:19
nit - n -> arg_count
danno
2017/02/17 17:18:43
Done.
| |
2182 const int kFunctionOperandCount = 1; | |
2183 const int kReceiverOperandCount = 1; | |
2184 const int kBoilerplatParameterCount = 7; | |
2185 const int kReceiveParameterOffset = 5; | |
rmcilroy
2017/02/17 11:37:19
nit - receiverParameterOffset
danno
2017/02/17 17:18:43
Done.
| |
2186 | |
2187 Node* function_reg = __ BytecodeOperandReg(0); | |
2188 Node* function = __ LoadRegister(function_reg); | |
2189 std::array<Node*, Bytecodes::kMaxOperands + kBoilerplatParameterCount> temp; | |
2190 for (int i = 0; i < (n + kReceiverOperandCount); ++i) { | |
rmcilroy
2017/02/17 11:37:19
nit - could you do these in-order (the for loop be
danno
2017/02/17 17:18:43
Done.
| |
2191 Node* reg = __ BytecodeOperandReg(i + kFunctionOperandCount); | |
rmcilroy
2017/02/17 11:37:19
nit - I find the use of kFunctionOperandCount and
danno
2017/02/17 17:18:43
Done.
| |
2192 temp[i + kReceiveParameterOffset] = __ LoadRegister(reg); | |
2193 } | |
2194 Callable call_ic = CodeFactory::CallIC(isolate_); | |
2195 temp[0] = __ HeapConstant(call_ic.code()); | |
2196 temp[1] = function; | |
2197 temp[2] = __ Int32Constant(n); | |
2198 temp[3] = __ BytecodeOperandIdxInt32(n + kFunctionOperandCount + | |
2199 kReceiverOperandCount); | |
2200 temp[4] = __ LoadFeedbackVector(); | |
2201 temp[n + 6] = __ GetContext(); | |
rmcilroy
2017/02/17 11:37:19
nit - temp[5 + kRecieverCount + n]
danno
2017/02/17 17:18:43
Done.
| |
2202 Node* result = __ CallStubN(call_ic.descriptor(), 1, | |
2203 n + kBoilerplatParameterCount, &temp[0]); | |
2204 __ SetAccumulator(result); | |
2205 __ Dispatch(); | |
2206 } | |
2207 | |
2154 // Call <callable> <receiver> <arg_count> <feedback_slot_id> | 2208 // Call <callable> <receiver> <arg_count> <feedback_slot_id> |
2155 // | 2209 // |
2156 // Call a JSfunction or Callable in |callable| with the |receiver| and | 2210 // Call a JSfunction or Callable in |callable| with the |receiver| and |
2157 // |arg_count| arguments in subsequent registers. Collect type feedback | 2211 // |arg_count| arguments in subsequent registers. Collect type feedback |
2158 // into |feedback_slot_id| | 2212 // into |feedback_slot_id| |
2159 void Interpreter::DoCall(InterpreterAssembler* assembler) { | 2213 void Interpreter::DoCall(InterpreterAssembler* assembler) { |
2160 DoJSCall(assembler, TailCallMode::kDisallow); | 2214 DoJSCall(assembler, TailCallMode::kDisallow); |
2161 } | 2215 } |
2162 | 2216 |
2163 // CallProperty <callable> <receiver> <arg_count> <feedback_slot_id> | 2217 void Interpreter::DoCall0(InterpreterAssembler* assembler) { |
2164 // | 2218 DoJSCallN(assembler, 0); |
2165 // Call a JSfunction or Callable in |callable| with the |receiver| and | 2219 } |
2166 // |arg_count| arguments in subsequent registers. Collect type feedback into | 2220 |
2167 // |feedback_slot_id|. The callable is known to be a property of the receiver. | 2221 void Interpreter::DoCall1(InterpreterAssembler* assembler) { |
2222 DoJSCallN(assembler, 1); | |
2223 } | |
2224 | |
2225 void Interpreter::DoCall2(InterpreterAssembler* assembler) { | |
2226 DoJSCallN(assembler, 2); | |
2227 } | |
2228 | |
2168 void Interpreter::DoCallProperty(InterpreterAssembler* assembler) { | 2229 void Interpreter::DoCallProperty(InterpreterAssembler* assembler) { |
2169 // TODO(leszeks): Look into making the interpreter use the fact that the | 2230 // Same as Call |
2170 // receiver is non-null. | 2231 UNREACHABLE(); |
2171 DoJSCall(assembler, TailCallMode::kDisallow); | 2232 } |
2233 | |
2234 void Interpreter::DoCallProperty0(InterpreterAssembler* assembler) { | |
2235 // Same as Call0 | |
2236 UNREACHABLE(); | |
2237 } | |
2238 | |
2239 void Interpreter::DoCallProperty1(InterpreterAssembler* assembler) { | |
2240 // Same as Call1 | |
2241 UNREACHABLE(); | |
2242 } | |
2243 | |
2244 void Interpreter::DoCallProperty2(InterpreterAssembler* assembler) { | |
2245 // Same as Call2 | |
2246 UNREACHABLE(); | |
2172 } | 2247 } |
2173 | 2248 |
2174 // TailCall <callable> <receiver> <arg_count> <feedback_slot_id> | 2249 // TailCall <callable> <receiver> <arg_count> <feedback_slot_id> |
2175 // | 2250 // |
2176 // Tail call a JSfunction or Callable in |callable| with the |receiver| and | 2251 // Tail call a JSfunction or Callable in |callable| with the |receiver| and |
2177 // |arg_count| arguments in subsequent registers. Collect type feedback | 2252 // |arg_count| arguments in subsequent registers. Collect type feedback |
2178 // into |feedback_slot_id| | 2253 // into |feedback_slot_id| |
2179 void Interpreter::DoTailCall(InterpreterAssembler* assembler) { | 2254 void Interpreter::DoTailCall(InterpreterAssembler* assembler) { |
2180 DoJSCall(assembler, TailCallMode::kAllow); | 2255 DoJSCall(assembler, TailCallMode::kAllow); |
2181 } | 2256 } |
(...skipping 39 matching lines...) Loading... | |
2221 // <first_return + 1> | 2296 // <first_return + 1> |
2222 void Interpreter::DoCallRuntimeForPair(InterpreterAssembler* assembler) { | 2297 void Interpreter::DoCallRuntimeForPair(InterpreterAssembler* assembler) { |
2223 // Call the runtime function. | 2298 // Call the runtime function. |
2224 Node* function_id = __ BytecodeOperandRuntimeId(0); | 2299 Node* function_id = __ BytecodeOperandRuntimeId(0); |
2225 Node* first_arg_reg = __ BytecodeOperandReg(1); | 2300 Node* first_arg_reg = __ BytecodeOperandReg(1); |
2226 Node* first_arg = __ RegisterLocation(first_arg_reg); | 2301 Node* first_arg = __ RegisterLocation(first_arg_reg); |
2227 Node* args_count = __ BytecodeOperandCount(2); | 2302 Node* args_count = __ BytecodeOperandCount(2); |
2228 Node* context = __ GetContext(); | 2303 Node* context = __ GetContext(); |
2229 Node* result_pair = | 2304 Node* result_pair = |
2230 __ CallRuntimeN(function_id, context, first_arg, args_count, 2); | 2305 __ CallRuntimeN(function_id, context, first_arg, args_count, 2); |
2231 | |
2232 // Store the results in <first_return> and <first_return + 1> | 2306 // Store the results in <first_return> and <first_return + 1> |
2233 Node* first_return_reg = __ BytecodeOperandReg(3); | 2307 Node* first_return_reg = __ BytecodeOperandReg(3); |
2234 Node* second_return_reg = __ NextRegister(first_return_reg); | 2308 Node* second_return_reg = __ NextRegister(first_return_reg); |
2235 Node* result0 = __ Projection(0, result_pair); | 2309 Node* result0 = __ Projection(0, result_pair); |
2236 Node* result1 = __ Projection(1, result_pair); | 2310 Node* result1 = __ Projection(1, result_pair); |
2237 __ StoreRegister(result0, first_return_reg); | 2311 __ StoreRegister(result0, first_return_reg); |
2238 __ StoreRegister(result1, second_return_reg); | 2312 __ StoreRegister(result1, second_return_reg); |
2239 __ Dispatch(); | 2313 __ Dispatch(); |
2240 } | 2314 } |
2241 | 2315 |
(...skipping 1126 matching lines...) Loading... | |
3368 __ StoreObjectField(generator, JSGeneratorObject::kContinuationOffset, | 3442 __ StoreObjectField(generator, JSGeneratorObject::kContinuationOffset, |
3369 __ SmiTag(new_state)); | 3443 __ SmiTag(new_state)); |
3370 __ SetAccumulator(old_state); | 3444 __ SetAccumulator(old_state); |
3371 | 3445 |
3372 __ Dispatch(); | 3446 __ Dispatch(); |
3373 } | 3447 } |
3374 | 3448 |
3375 } // namespace interpreter | 3449 } // namespace interpreter |
3376 } // namespace internal | 3450 } // namespace internal |
3377 } // namespace v8 | 3451 } // namespace v8 |
OLD | NEW |