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 356 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
367 ? 0 | 367 ? 0 |
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 CallBufferFlags flags, |
378 bool call_address_immediate) { | 378 int stack_param_delta) { |
379 OperandGenerator g(this); | 379 OperandGenerator g(this); |
380 DCHECK_LE(call->op()->ValueOutputCount(), | 380 DCHECK_LE(call->op()->ValueOutputCount(), |
381 static_cast<int>(buffer->descriptor->ReturnCount())); | 381 static_cast<int>(buffer->descriptor->ReturnCount())); |
382 DCHECK_EQ( | 382 DCHECK_EQ( |
383 call->op()->ValueInputCount(), | 383 call->op()->ValueInputCount(), |
384 static_cast<int>(buffer->input_count() + buffer->frame_state_count())); | 384 static_cast<int>(buffer->input_count() + buffer->frame_state_count())); |
385 | 385 |
386 if (buffer->descriptor->ReturnCount() > 0) { | 386 if (buffer->descriptor->ReturnCount() > 0) { |
387 // Collect the projections that represent multiple outputs from this call. | 387 // Collect the projections that represent multiple outputs from this call. |
388 if (buffer->descriptor->ReturnCount() == 1) { | 388 if (buffer->descriptor->ReturnCount() == 1) { |
(...skipping 30 matching lines...) Expand all Loading... |
419 : g.DefineAsLocation(output, location, type); | 419 : g.DefineAsLocation(output, location, type); |
420 MarkAsRepresentation(type, op); | 420 MarkAsRepresentation(type, op); |
421 | 421 |
422 buffer->outputs.push_back(op); | 422 buffer->outputs.push_back(op); |
423 } | 423 } |
424 } | 424 } |
425 } | 425 } |
426 | 426 |
427 // The first argument is always the callee code. | 427 // The first argument is always the callee code. |
428 Node* callee = call->InputAt(0); | 428 Node* callee = call->InputAt(0); |
| 429 bool call_code_immediate = (flags & CALL_CODE_IMMEDIATE) != 0; |
| 430 bool call_address_immediate = (flags & CALL_ADDRESS_IMMEDIATE) != 0; |
429 switch (buffer->descriptor->kind()) { | 431 switch (buffer->descriptor->kind()) { |
430 case CallDescriptor::kCallCodeObject: | 432 case CallDescriptor::kCallCodeObject: |
431 buffer->instruction_args.push_back( | 433 buffer->instruction_args.push_back( |
432 (call_code_immediate && callee->opcode() == IrOpcode::kHeapConstant) | 434 (call_code_immediate && callee->opcode() == IrOpcode::kHeapConstant) |
433 ? g.UseImmediate(callee) | 435 ? g.UseImmediate(callee) |
434 : g.UseRegister(callee)); | 436 : g.UseRegister(callee)); |
435 break; | 437 break; |
436 case CallDescriptor::kCallAddress: | 438 case CallDescriptor::kCallAddress: |
437 buffer->instruction_args.push_back( | 439 buffer->instruction_args.push_back( |
438 (call_address_immediate && | 440 (call_address_immediate && |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
471 buffer->instruction_args.size()); | 473 buffer->instruction_args.size()); |
472 | 474 |
473 size_t input_count = static_cast<size_t>(buffer->input_count()); | 475 size_t input_count = static_cast<size_t>(buffer->input_count()); |
474 | 476 |
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; |
| 483 bool call_tail = (flags & CALL_TAIL) != 0; |
481 for (size_t index = 0; index < input_count; ++iter, ++index) { | 484 for (size_t index = 0; index < input_count; ++iter, ++index) { |
482 DCHECK(iter != call->inputs().end()); | 485 DCHECK(iter != call->inputs().end()); |
483 DCHECK((*iter)->op()->opcode() != IrOpcode::kFrameState); | 486 DCHECK((*iter)->op()->opcode() != IrOpcode::kFrameState); |
484 if (index == 0) continue; // The first argument (callee) is already done. | 487 if (index == 0) continue; // The first argument (callee) is already done. |
| 488 |
| 489 LinkageLocation location = buffer->descriptor->GetInputLocation(index); |
| 490 if (call_tail) { |
| 491 location = LinkageLocation::ConvertToTailCallerLocation( |
| 492 location, stack_param_delta); |
| 493 } |
485 InstructionOperand op = | 494 InstructionOperand op = |
486 g.UseLocation(*iter, buffer->descriptor->GetInputLocation(index), | 495 g.UseLocation(*iter, location, buffer->descriptor->GetInputType(index)); |
487 buffer->descriptor->GetInputType(index)); | 496 if (UnallocatedOperand::cast(op).HasFixedSlotPolicy() && !call_tail) { |
488 if (UnallocatedOperand::cast(op).HasFixedSlotPolicy()) { | |
489 int stack_index = -UnallocatedOperand::cast(op).fixed_slot_index() - 1; | 497 int stack_index = -UnallocatedOperand::cast(op).fixed_slot_index() - 1; |
490 if (static_cast<size_t>(stack_index) >= buffer->pushed_nodes.size()) { | 498 if (static_cast<size_t>(stack_index) >= buffer->pushed_nodes.size()) { |
491 buffer->pushed_nodes.resize(stack_index + 1, NULL); | 499 buffer->pushed_nodes.resize(stack_index + 1, NULL); |
492 } | 500 } |
493 DCHECK(!buffer->pushed_nodes[stack_index]); | 501 DCHECK(!buffer->pushed_nodes[stack_index]); |
494 buffer->pushed_nodes[stack_index] = *iter; | 502 buffer->pushed_nodes[stack_index] = *iter; |
495 pushed_count++; | 503 pushed_count++; |
496 } else { | 504 } else { |
497 buffer->instruction_args.push_back(op); | 505 buffer->instruction_args.push_back(op); |
498 } | 506 } |
(...skipping 660 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1159 node->InputAt(static_cast<int>(descriptor->InputCount()))); | 1167 node->InputAt(static_cast<int>(descriptor->InputCount()))); |
1160 } | 1168 } |
1161 | 1169 |
1162 CallBuffer buffer(zone(), descriptor, frame_state_descriptor); | 1170 CallBuffer buffer(zone(), descriptor, frame_state_descriptor); |
1163 | 1171 |
1164 // Compute InstructionOperands for inputs and outputs. | 1172 // Compute InstructionOperands for inputs and outputs. |
1165 // TODO(turbofan): on some architectures it's probably better to use | 1173 // 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. | 1174 // the code object in a register if there are multiple uses of it. |
1167 // Improve constant pool and the heuristics in the register allocator | 1175 // Improve constant pool and the heuristics in the register allocator |
1168 // for where to emit constants. | 1176 // for where to emit constants. |
1169 InitializeCallBuffer(node, &buffer, true, true); | 1177 CallBufferFlags call_buffer_flags = static_cast<CallBufferFlags>( |
| 1178 CALL_CODE_IMMEDIATE | CALL_ADDRESS_IMMEDIATE); |
| 1179 InitializeCallBuffer(node, &buffer, call_buffer_flags); |
1170 | 1180 |
1171 EmitPrepareArguments(&(buffer.pushed_nodes), descriptor, node); | 1181 EmitPrepareArguments(&(buffer.pushed_nodes), descriptor, node); |
1172 | 1182 |
1173 // Pass label of exception handler block. | 1183 // Pass label of exception handler block. |
1174 CallDescriptor::Flags flags = descriptor->flags(); | 1184 CallDescriptor::Flags flags = descriptor->flags(); |
1175 if (handler) { | 1185 if (handler) { |
1176 DCHECK_EQ(IrOpcode::kIfException, handler->front()->opcode()); | 1186 DCHECK_EQ(IrOpcode::kIfException, handler->front()->opcode()); |
1177 IfExceptionHint hint = OpParameter<IfExceptionHint>(handler->front()); | 1187 IfExceptionHint hint = OpParameter<IfExceptionHint>(handler->front()); |
1178 if (hint == IfExceptionHint::kLocallyCaught) { | 1188 if (hint == IfExceptionHint::kLocallyCaught) { |
1179 flags |= CallDescriptor::kHasLocalCatchHandler; | 1189 flags |= CallDescriptor::kHasLocalCatchHandler; |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1212 | 1222 |
1213 void InstructionSelector::VisitTailCall(Node* node) { | 1223 void InstructionSelector::VisitTailCall(Node* node) { |
1214 OperandGenerator g(this); | 1224 OperandGenerator g(this); |
1215 CallDescriptor const* descriptor = OpParameter<CallDescriptor const*>(node); | 1225 CallDescriptor const* descriptor = OpParameter<CallDescriptor const*>(node); |
1216 DCHECK_NE(0, descriptor->flags() & CallDescriptor::kSupportsTailCalls); | 1226 DCHECK_NE(0, descriptor->flags() & CallDescriptor::kSupportsTailCalls); |
1217 DCHECK_EQ(0, descriptor->flags() & CallDescriptor::kPatchableCallSite); | 1227 DCHECK_EQ(0, descriptor->flags() & CallDescriptor::kPatchableCallSite); |
1218 DCHECK_EQ(0, descriptor->flags() & CallDescriptor::kNeedsNopAfterCall); | 1228 DCHECK_EQ(0, descriptor->flags() & CallDescriptor::kNeedsNopAfterCall); |
1219 | 1229 |
1220 // TODO(turbofan): Relax restriction for stack parameters. | 1230 // TODO(turbofan): Relax restriction for stack parameters. |
1221 | 1231 |
1222 if (linkage()->GetIncomingDescriptor()->CanTailCall(node)) { | 1232 int stack_param_delta = 0; |
| 1233 if (linkage()->GetIncomingDescriptor()->CanTailCall(node, |
| 1234 &stack_param_delta)) { |
1223 CallBuffer buffer(zone(), descriptor, nullptr); | 1235 CallBuffer buffer(zone(), descriptor, nullptr); |
1224 | 1236 |
1225 // Compute InstructionOperands for inputs and outputs. | 1237 // Compute InstructionOperands for inputs and outputs. |
1226 InitializeCallBuffer(node, &buffer, true, IsTailCallAddressImmediate()); | 1238 CallBufferFlags flags = |
| 1239 static_cast<CallBufferFlags>(CALL_CODE_IMMEDIATE | CALL_TAIL); |
| 1240 if (IsTailCallAddressImmediate()) { |
| 1241 flags = static_cast<CallBufferFlags>(flags | CALL_ADDRESS_IMMEDIATE); |
| 1242 } |
| 1243 InitializeCallBuffer(node, &buffer, flags, stack_param_delta); |
1227 | 1244 |
1228 // Select the appropriate opcode based on the call type. | 1245 // Select the appropriate opcode based on the call type. |
1229 InstructionCode opcode; | 1246 InstructionCode opcode; |
1230 switch (descriptor->kind()) { | 1247 switch (descriptor->kind()) { |
1231 case CallDescriptor::kCallCodeObject: | 1248 case CallDescriptor::kCallCodeObject: |
1232 opcode = kArchTailCallCodeObject; | 1249 opcode = kArchTailCallCodeObject; |
1233 break; | 1250 break; |
1234 case CallDescriptor::kCallJSFunction: | 1251 case CallDescriptor::kCallJSFunction: |
1235 opcode = kArchTailCallJSFunction; | 1252 opcode = kArchTailCallJSFunction; |
1236 break; | 1253 break; |
1237 default: | 1254 default: |
1238 UNREACHABLE(); | 1255 UNREACHABLE(); |
1239 return; | 1256 return; |
1240 } | 1257 } |
1241 opcode |= MiscField::encode(descriptor->flags()); | 1258 opcode |= MiscField::encode(descriptor->flags()); |
1242 | 1259 |
| 1260 buffer.instruction_args.push_back(g.TempImmediate(stack_param_delta)); |
| 1261 |
1243 // Emit the tailcall instruction. | 1262 // Emit the tailcall instruction. |
1244 Emit(opcode, 0, nullptr, buffer.instruction_args.size(), | 1263 Emit(opcode, 0, nullptr, buffer.instruction_args.size(), |
1245 &buffer.instruction_args.front()); | 1264 &buffer.instruction_args.front()); |
1246 } else { | 1265 } else { |
1247 FrameStateDescriptor* frame_state_descriptor = | 1266 FrameStateDescriptor* frame_state_descriptor = |
1248 descriptor->NeedsFrameState() | 1267 descriptor->NeedsFrameState() |
1249 ? GetFrameStateDescriptor( | 1268 ? GetFrameStateDescriptor( |
1250 node->InputAt(static_cast<int>(descriptor->InputCount()))) | 1269 node->InputAt(static_cast<int>(descriptor->InputCount()))) |
1251 : nullptr; | 1270 : nullptr; |
1252 | 1271 |
1253 CallBuffer buffer(zone(), descriptor, frame_state_descriptor); | 1272 CallBuffer buffer(zone(), descriptor, frame_state_descriptor); |
1254 | 1273 |
1255 // Compute InstructionOperands for inputs and outputs. | 1274 // Compute InstructionOperands for inputs and outputs. |
1256 InitializeCallBuffer(node, &buffer, true, IsTailCallAddressImmediate()); | 1275 CallBufferFlags flags = CALL_CODE_IMMEDIATE; |
| 1276 if (IsTailCallAddressImmediate()) { |
| 1277 flags = static_cast<CallBufferFlags>(flags | CALL_ADDRESS_IMMEDIATE); |
| 1278 } |
| 1279 InitializeCallBuffer(node, &buffer, flags); |
1257 | 1280 |
1258 EmitPrepareArguments(&(buffer.pushed_nodes), descriptor, node); | 1281 EmitPrepareArguments(&(buffer.pushed_nodes), descriptor, node); |
1259 | 1282 |
1260 // Select the appropriate opcode based on the call type. | 1283 // Select the appropriate opcode based on the call type. |
1261 InstructionCode opcode; | 1284 InstructionCode opcode; |
1262 switch (descriptor->kind()) { | 1285 switch (descriptor->kind()) { |
1263 case CallDescriptor::kCallCodeObject: | 1286 case CallDescriptor::kCallCodeObject: |
1264 opcode = kArchCallCodeObject; | 1287 opcode = kArchCallCodeObject; |
1265 break; | 1288 break; |
1266 case CallDescriptor::kCallJSFunction: | 1289 case CallDescriptor::kCallJSFunction: |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1360 return new (instruction_zone()) FrameStateDescriptor( | 1383 return new (instruction_zone()) FrameStateDescriptor( |
1361 instruction_zone(), state_info.type(), state_info.bailout_id(), | 1384 instruction_zone(), state_info.type(), state_info.bailout_id(), |
1362 state_info.state_combine(), parameters, locals, stack, | 1385 state_info.state_combine(), parameters, locals, stack, |
1363 state_info.shared_info(), outer_state); | 1386 state_info.shared_info(), outer_state); |
1364 } | 1387 } |
1365 | 1388 |
1366 | 1389 |
1367 } // namespace compiler | 1390 } // namespace compiler |
1368 } // namespace internal | 1391 } // namespace internal |
1369 } // namespace v8 | 1392 } // namespace v8 |
OLD | NEW |