Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(580)

Side by Side Diff: src/interpreter/interpreter.cc

Issue 2684993002: [interpreter] Create custom call opcodes for specific argument counts (Closed)
Patch Set: Latest Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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...) Expand 10 before | Expand all | Expand 10 after
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...) Expand 10 before | Expand all | Expand 10 after
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...) Expand 10 before | Expand all | Expand 10 after
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...) Expand 10 before | Expand all | Expand 10 after
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698