Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 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/compiler/instruction-selector.h" | 5 #include "src/compiler/instruction-selector.h" |
| 6 | 6 |
| 7 #include <limits> | 7 #include <limits> |
| 8 | 8 |
| 9 #include "src/base/adapters.h" | 9 #include "src/base/adapters.h" |
| 10 #include "src/compiler/instruction-selector-impl.h" | 10 #include "src/compiler/instruction-selector-impl.h" |
| (...skipping 357 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 368 : (frame_state_descriptor->GetTotalSize() + | 368 : (frame_state_descriptor->GetTotalSize() + |
| 369 1); // Include deopt id. | 369 1); // Include deopt id. |
| 370 } | 370 } |
| 371 }; | 371 }; |
| 372 | 372 |
| 373 | 373 |
| 374 // TODO(bmeurer): Get rid of the CallBuffer business and make | 374 // TODO(bmeurer): Get rid of the CallBuffer business and make |
| 375 // InstructionSelector::VisitCall platform independent instead. | 375 // InstructionSelector::VisitCall platform independent instead. |
| 376 void InstructionSelector::InitializeCallBuffer(Node* call, CallBuffer* buffer, | 376 void InstructionSelector::InitializeCallBuffer(Node* call, CallBuffer* buffer, |
| 377 bool call_code_immediate, | 377 bool call_code_immediate, |
| 378 bool call_address_immediate) { | 378 bool call_address_immediate, |
| 379 bool call_tail, | |
| 380 int stack_param_delta) { | |
| 379 OperandGenerator g(this); | 381 OperandGenerator g(this); |
| 380 DCHECK_LE(call->op()->ValueOutputCount(), | 382 DCHECK_LE(call->op()->ValueOutputCount(), |
| 381 static_cast<int>(buffer->descriptor->ReturnCount())); | 383 static_cast<int>(buffer->descriptor->ReturnCount())); |
| 382 DCHECK_EQ( | 384 DCHECK_EQ( |
| 383 call->op()->ValueInputCount(), | 385 call->op()->ValueInputCount(), |
| 384 static_cast<int>(buffer->input_count() + buffer->frame_state_count())); | 386 static_cast<int>(buffer->input_count() + buffer->frame_state_count())); |
| 385 | 387 |
| 386 if (buffer->descriptor->ReturnCount() > 0) { | 388 if (buffer->descriptor->ReturnCount() > 0) { |
| 387 // Collect the projections that represent multiple outputs from this call. | 389 // Collect the projections that represent multiple outputs from this call. |
| 388 if (buffer->descriptor->ReturnCount() == 1) { | 390 if (buffer->descriptor->ReturnCount() == 1) { |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 475 // Split the arguments into pushed_nodes and instruction_args. Pushed | 477 // Split the arguments into pushed_nodes and instruction_args. Pushed |
| 476 // arguments require an explicit push instruction before the call and do | 478 // arguments require an explicit push instruction before the call and do |
| 477 // not appear as arguments to the call. Everything else ends up | 479 // not appear as arguments to the call. Everything else ends up |
| 478 // as an InstructionOperand argument to the call. | 480 // as an InstructionOperand argument to the call. |
| 479 auto iter(call->inputs().begin()); | 481 auto iter(call->inputs().begin()); |
| 480 size_t pushed_count = 0; | 482 size_t pushed_count = 0; |
| 481 for (size_t index = 0; index < input_count; ++iter, ++index) { | 483 for (size_t index = 0; index < input_count; ++iter, ++index) { |
| 482 DCHECK(iter != call->inputs().end()); | 484 DCHECK(iter != call->inputs().end()); |
| 483 DCHECK((*iter)->op()->opcode() != IrOpcode::kFrameState); | 485 DCHECK((*iter)->op()->opcode() != IrOpcode::kFrameState); |
| 484 if (index == 0) continue; // The first argument (callee) is already done. | 486 if (index == 0) continue; // The first argument (callee) is already done. |
| 487 | |
| 488 LinkageLocation location = buffer->descriptor->GetInputLocation(index); | |
| 489 if (call_tail) { | |
| 490 location = LinkageLocation::ConvertToTailCallerLocation( | |
| 491 buffer->descriptor->GetInputLocation(index), stack_param_delta); | |
|
Jarin
2015/11/12 13:45:12
Replace 'buffer->descriptor->GetInputLocation(inde
danno
2015/11/13 10:04:17
Done.
| |
| 492 } | |
| 485 InstructionOperand op = | 493 InstructionOperand op = |
| 486 g.UseLocation(*iter, buffer->descriptor->GetInputLocation(index), | 494 g.UseLocation(*iter, location, buffer->descriptor->GetInputType(index)); |
| 487 buffer->descriptor->GetInputType(index)); | 495 if (UnallocatedOperand::cast(op).HasFixedSlotPolicy() && !call_tail) { |
| 488 if (UnallocatedOperand::cast(op).HasFixedSlotPolicy()) { | |
| 489 int stack_index = -UnallocatedOperand::cast(op).fixed_slot_index() - 1; | 496 int stack_index = -UnallocatedOperand::cast(op).fixed_slot_index() - 1; |
| 490 if (static_cast<size_t>(stack_index) >= buffer->pushed_nodes.size()) { | 497 if (static_cast<size_t>(stack_index) >= buffer->pushed_nodes.size()) { |
| 491 buffer->pushed_nodes.resize(stack_index + 1, NULL); | 498 buffer->pushed_nodes.resize(stack_index + 1, NULL); |
| 492 } | 499 } |
| 493 DCHECK(!buffer->pushed_nodes[stack_index]); | 500 DCHECK(!buffer->pushed_nodes[stack_index]); |
| 494 buffer->pushed_nodes[stack_index] = *iter; | 501 buffer->pushed_nodes[stack_index] = *iter; |
| 495 pushed_count++; | 502 pushed_count++; |
| 496 } else { | 503 } else { |
| 497 buffer->instruction_args.push_back(op); | 504 buffer->instruction_args.push_back(op); |
| 498 } | 505 } |
| (...skipping 660 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1159 node->InputAt(static_cast<int>(descriptor->InputCount()))); | 1166 node->InputAt(static_cast<int>(descriptor->InputCount()))); |
| 1160 } | 1167 } |
| 1161 | 1168 |
| 1162 CallBuffer buffer(zone(), descriptor, frame_state_descriptor); | 1169 CallBuffer buffer(zone(), descriptor, frame_state_descriptor); |
| 1163 | 1170 |
| 1164 // Compute InstructionOperands for inputs and outputs. | 1171 // Compute InstructionOperands for inputs and outputs. |
| 1165 // TODO(turbofan): on some architectures it's probably better to use | 1172 // TODO(turbofan): on some architectures it's probably better to use |
| 1166 // the code object in a register if there are multiple uses of it. | 1173 // the code object in a register if there are multiple uses of it. |
| 1167 // Improve constant pool and the heuristics in the register allocator | 1174 // Improve constant pool and the heuristics in the register allocator |
| 1168 // for where to emit constants. | 1175 // for where to emit constants. |
| 1169 InitializeCallBuffer(node, &buffer, true, true); | 1176 InitializeCallBuffer(node, &buffer, true, true, false); |
|
Jarin
2015/11/12 13:45:12
Hmm, the bool parameters are getting a bit out of
danno
2015/11/13 10:04:17
Done.
| |
| 1170 | 1177 |
| 1171 EmitPrepareArguments(&(buffer.pushed_nodes), descriptor, node); | 1178 EmitPrepareArguments(&(buffer.pushed_nodes), descriptor, node); |
| 1172 | 1179 |
| 1173 // Pass label of exception handler block. | 1180 // Pass label of exception handler block. |
| 1174 CallDescriptor::Flags flags = descriptor->flags(); | 1181 CallDescriptor::Flags flags = descriptor->flags(); |
| 1175 if (handler) { | 1182 if (handler) { |
| 1176 DCHECK_EQ(IrOpcode::kIfException, handler->front()->opcode()); | 1183 DCHECK_EQ(IrOpcode::kIfException, handler->front()->opcode()); |
| 1177 IfExceptionHint hint = OpParameter<IfExceptionHint>(handler->front()); | 1184 IfExceptionHint hint = OpParameter<IfExceptionHint>(handler->front()); |
| 1178 if (hint == IfExceptionHint::kLocallyCaught) { | 1185 if (hint == IfExceptionHint::kLocallyCaught) { |
| 1179 flags |= CallDescriptor::kHasLocalCatchHandler; | 1186 flags |= CallDescriptor::kHasLocalCatchHandler; |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1212 | 1219 |
| 1213 void InstructionSelector::VisitTailCall(Node* node) { | 1220 void InstructionSelector::VisitTailCall(Node* node) { |
| 1214 OperandGenerator g(this); | 1221 OperandGenerator g(this); |
| 1215 CallDescriptor const* descriptor = OpParameter<CallDescriptor const*>(node); | 1222 CallDescriptor const* descriptor = OpParameter<CallDescriptor const*>(node); |
| 1216 DCHECK_NE(0, descriptor->flags() & CallDescriptor::kSupportsTailCalls); | 1223 DCHECK_NE(0, descriptor->flags() & CallDescriptor::kSupportsTailCalls); |
| 1217 DCHECK_EQ(0, descriptor->flags() & CallDescriptor::kPatchableCallSite); | 1224 DCHECK_EQ(0, descriptor->flags() & CallDescriptor::kPatchableCallSite); |
| 1218 DCHECK_EQ(0, descriptor->flags() & CallDescriptor::kNeedsNopAfterCall); | 1225 DCHECK_EQ(0, descriptor->flags() & CallDescriptor::kNeedsNopAfterCall); |
| 1219 | 1226 |
| 1220 // TODO(turbofan): Relax restriction for stack parameters. | 1227 // TODO(turbofan): Relax restriction for stack parameters. |
| 1221 | 1228 |
| 1222 if (linkage()->GetIncomingDescriptor()->CanTailCall(node)) { | 1229 int stack_param_delta = 0; |
| 1230 if (linkage()->GetIncomingDescriptor()->CanTailCall(node, | |
| 1231 &stack_param_delta)) { | |
| 1223 CallBuffer buffer(zone(), descriptor, nullptr); | 1232 CallBuffer buffer(zone(), descriptor, nullptr); |
| 1224 | 1233 |
| 1225 // Compute InstructionOperands for inputs and outputs. | 1234 // Compute InstructionOperands for inputs and outputs. |
| 1226 InitializeCallBuffer(node, &buffer, true, IsTailCallAddressImmediate()); | 1235 InitializeCallBuffer(node, &buffer, true, IsTailCallAddressImmediate(), |
| 1236 true, stack_param_delta); | |
| 1227 | 1237 |
| 1228 // Select the appropriate opcode based on the call type. | 1238 // Select the appropriate opcode based on the call type. |
| 1229 InstructionCode opcode; | 1239 InstructionCode opcode; |
| 1230 switch (descriptor->kind()) { | 1240 switch (descriptor->kind()) { |
| 1231 case CallDescriptor::kCallCodeObject: | 1241 case CallDescriptor::kCallCodeObject: |
| 1232 opcode = kArchTailCallCodeObject; | 1242 opcode = kArchTailCallCodeObject; |
| 1233 break; | 1243 break; |
| 1234 case CallDescriptor::kCallJSFunction: | 1244 case CallDescriptor::kCallJSFunction: |
| 1235 opcode = kArchTailCallJSFunction; | 1245 opcode = kArchTailCallJSFunction; |
| 1236 break; | 1246 break; |
| 1237 default: | 1247 default: |
| 1238 UNREACHABLE(); | 1248 UNREACHABLE(); |
| 1239 return; | 1249 return; |
| 1240 } | 1250 } |
| 1241 opcode |= MiscField::encode(descriptor->flags()); | 1251 opcode |= MiscField::encode(descriptor->flags()); |
| 1242 | 1252 |
| 1253 buffer.instruction_args.push_back(g.TempImmediate(stack_param_delta)); | |
| 1254 | |
| 1243 // Emit the tailcall instruction. | 1255 // Emit the tailcall instruction. |
| 1244 Emit(opcode, 0, nullptr, buffer.instruction_args.size(), | 1256 Emit(opcode, 0, nullptr, buffer.instruction_args.size(), |
| 1245 &buffer.instruction_args.front()); | 1257 &buffer.instruction_args.front()); |
| 1246 } else { | 1258 } else { |
| 1247 FrameStateDescriptor* frame_state_descriptor = | 1259 FrameStateDescriptor* frame_state_descriptor = |
| 1248 descriptor->NeedsFrameState() | 1260 descriptor->NeedsFrameState() |
| 1249 ? GetFrameStateDescriptor( | 1261 ? GetFrameStateDescriptor( |
| 1250 node->InputAt(static_cast<int>(descriptor->InputCount()))) | 1262 node->InputAt(static_cast<int>(descriptor->InputCount()))) |
| 1251 : nullptr; | 1263 : nullptr; |
| 1252 | 1264 |
| 1253 CallBuffer buffer(zone(), descriptor, frame_state_descriptor); | 1265 CallBuffer buffer(zone(), descriptor, frame_state_descriptor); |
| 1254 | 1266 |
| 1255 // Compute InstructionOperands for inputs and outputs. | 1267 // Compute InstructionOperands for inputs and outputs. |
| 1256 InitializeCallBuffer(node, &buffer, true, IsTailCallAddressImmediate()); | 1268 InitializeCallBuffer(node, &buffer, true, IsTailCallAddressImmediate(), |
| 1269 false); | |
| 1257 | 1270 |
| 1258 EmitPrepareArguments(&(buffer.pushed_nodes), descriptor, node); | 1271 EmitPrepareArguments(&(buffer.pushed_nodes), descriptor, node); |
| 1259 | 1272 |
| 1260 // Select the appropriate opcode based on the call type. | 1273 // Select the appropriate opcode based on the call type. |
| 1261 InstructionCode opcode; | 1274 InstructionCode opcode; |
| 1262 switch (descriptor->kind()) { | 1275 switch (descriptor->kind()) { |
| 1263 case CallDescriptor::kCallCodeObject: | 1276 case CallDescriptor::kCallCodeObject: |
| 1264 opcode = kArchCallCodeObject; | 1277 opcode = kArchCallCodeObject; |
| 1265 break; | 1278 break; |
| 1266 case CallDescriptor::kCallJSFunction: | 1279 case CallDescriptor::kCallJSFunction: |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1360 return new (instruction_zone()) FrameStateDescriptor( | 1373 return new (instruction_zone()) FrameStateDescriptor( |
| 1361 instruction_zone(), state_info.type(), state_info.bailout_id(), | 1374 instruction_zone(), state_info.type(), state_info.bailout_id(), |
| 1362 state_info.state_combine(), parameters, locals, stack, | 1375 state_info.state_combine(), parameters, locals, stack, |
| 1363 state_info.shared_info(), outer_state); | 1376 state_info.shared_info(), outer_state); |
| 1364 } | 1377 } |
| 1365 | 1378 |
| 1366 | 1379 |
| 1367 } // namespace compiler | 1380 } // namespace compiler |
| 1368 } // namespace internal | 1381 } // namespace internal |
| 1369 } // namespace v8 | 1382 } // namespace v8 |
| OLD | NEW |