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-impl.h" | 5 #include "src/compiler/instruction-selector-impl.h" |
6 #include "src/compiler/node-matchers.h" | 6 #include "src/compiler/node-matchers.h" |
7 #include "src/compiler/node-properties.h" | 7 #include "src/compiler/node-properties.h" |
8 | 8 |
9 namespace v8 { | 9 namespace v8 { |
10 namespace internal { | 10 namespace internal { |
(...skipping 1433 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1444 } | 1444 } |
1445 // Now all pushes can be done in pairs. | 1445 // Now all pushes can be done in pairs. |
1446 for (; slot >= 0; slot -= 2) { | 1446 for (; slot >= 0; slot -= 2) { |
1447 Emit(kArm64PokePair, g.NoOutput(), g.UseRegister((*arguments)[slot]), | 1447 Emit(kArm64PokePair, g.NoOutput(), g.UseRegister((*arguments)[slot]), |
1448 g.UseRegister((*arguments)[slot - 1]), g.TempImmediate(slot)); | 1448 g.UseRegister((*arguments)[slot - 1]), g.TempImmediate(slot)); |
1449 } | 1449 } |
1450 } | 1450 } |
1451 } | 1451 } |
1452 | 1452 |
1453 | 1453 |
1454 void InstructionSelector::VisitTailCall(Node* node) { | 1454 bool InstructionSelector::IsTailCallAddressImmediate() { return false; } |
1455 Arm64OperandGenerator g(this); | |
1456 const CallDescriptor* descriptor = OpParameter<const CallDescriptor*>(node); | |
1457 DCHECK_NE(0, descriptor->flags() & CallDescriptor::kSupportsTailCalls); | |
1458 DCHECK_EQ(0, descriptor->flags() & CallDescriptor::kPatchableCallSite); | |
1459 DCHECK_EQ(0, descriptor->flags() & CallDescriptor::kNeedsNopAfterCall); | |
1460 | |
1461 // TODO(turbofan): Relax restriction for stack parameters. | |
1462 if (linkage()->GetIncomingDescriptor()->CanTailCall(node)) { | |
1463 CallBuffer buffer(zone(), descriptor, nullptr); | |
1464 | |
1465 // Compute InstructionOperands for inputs and outputs. | |
1466 // TODO(turbofan): on ARM64 it's probably better to use the code object in a | |
1467 // register if there are multiple uses of it. Improve constant pool and the | |
1468 // heuristics in the register allocator for where to emit constants. | |
1469 InitializeCallBuffer(node, &buffer, true, false); | |
1470 | |
1471 // Select the appropriate opcode based on the call type. | |
1472 InstructionCode opcode; | |
1473 switch (descriptor->kind()) { | |
1474 case CallDescriptor::kCallCodeObject: | |
1475 opcode = kArchTailCallCodeObject; | |
1476 break; | |
1477 case CallDescriptor::kCallJSFunction: | |
1478 opcode = kArchTailCallJSFunction; | |
1479 break; | |
1480 default: | |
1481 UNREACHABLE(); | |
1482 return; | |
1483 } | |
1484 opcode |= MiscField::encode(descriptor->flags()); | |
1485 | |
1486 // Emit the tailcall instruction. | |
1487 Emit(opcode, 0, nullptr, buffer.instruction_args.size(), | |
1488 &buffer.instruction_args.front()); | |
1489 } else { | |
1490 FrameStateDescriptor* frame_state_descriptor = nullptr; | |
1491 if (descriptor->NeedsFrameState()) { | |
1492 frame_state_descriptor = GetFrameStateDescriptor( | |
1493 node->InputAt(static_cast<int>(descriptor->InputCount()))); | |
1494 } | |
1495 | |
1496 CallBuffer buffer(zone(), descriptor, frame_state_descriptor); | |
1497 | |
1498 // Compute InstructionOperands for inputs and outputs. | |
1499 // TODO(turbofan): on ARM64 it's probably better to use the code object in a | |
1500 // register if there are multiple uses of it. Improve constant pool and the | |
1501 // heuristics in the register allocator for where to emit constants. | |
1502 InitializeCallBuffer(node, &buffer, true, false); | |
1503 | |
1504 // Push the arguments to the stack. | |
1505 int aligned_push_count = static_cast<int>(buffer.pushed_nodes.size()); | |
1506 bool pushed_count_uneven = aligned_push_count & 1; | |
1507 // TODO(dcarney): claim and poke probably take small immediates, | |
1508 // loop here or whatever. | |
1509 // Bump the stack pointer(s). | |
1510 if (aligned_push_count > 0) { | |
1511 // TODO(dcarney): it would be better to bump the csp here only | |
1512 // and emit paired stores with increment for non c frames. | |
1513 Emit(kArm64Claim, g.NoOutput(), g.TempImmediate(aligned_push_count)); | |
1514 } | |
1515 // Move arguments to the stack. | |
1516 { | |
1517 int slot = aligned_push_count - 1; | |
1518 // Emit the uneven pushes. | |
1519 if (pushed_count_uneven) { | |
1520 Node* input = buffer.pushed_nodes[slot]; | |
1521 Emit(kArm64Poke, g.NoOutput(), g.UseRegister(input), | |
1522 g.TempImmediate(slot)); | |
1523 slot--; | |
1524 } | |
1525 // Now all pushes can be done in pairs. | |
1526 for (; slot >= 0; slot -= 2) { | |
1527 Emit(kArm64PokePair, g.NoOutput(), | |
1528 g.UseRegister(buffer.pushed_nodes[slot]), | |
1529 g.UseRegister(buffer.pushed_nodes[slot - 1]), | |
1530 g.TempImmediate(slot)); | |
1531 } | |
1532 } | |
1533 | |
1534 // Select the appropriate opcode based on the call type. | |
1535 InstructionCode opcode; | |
1536 switch (descriptor->kind()) { | |
1537 case CallDescriptor::kCallCodeObject: { | |
1538 opcode = kArchCallCodeObject; | |
1539 break; | |
1540 } | |
1541 case CallDescriptor::kCallJSFunction: | |
1542 opcode = kArchCallJSFunction; | |
1543 break; | |
1544 default: | |
1545 UNREACHABLE(); | |
1546 return; | |
1547 } | |
1548 opcode |= MiscField::encode(descriptor->flags()); | |
1549 | |
1550 // Emit the call instruction. | |
1551 size_t const output_count = buffer.outputs.size(); | |
1552 auto* outputs = output_count ? &buffer.outputs.front() : nullptr; | |
1553 Emit(opcode, output_count, outputs, buffer.instruction_args.size(), | |
1554 &buffer.instruction_args.front())->MarkAsCall(); | |
1555 Emit(kArchRet, 0, nullptr, output_count, outputs); | |
1556 } | |
1557 } | |
1558 | 1455 |
1559 | 1456 |
1560 namespace { | 1457 namespace { |
1561 | 1458 |
1562 // Shared routine for multiple compare operations. | 1459 // Shared routine for multiple compare operations. |
1563 void VisitCompare(InstructionSelector* selector, InstructionCode opcode, | 1460 void VisitCompare(InstructionSelector* selector, InstructionCode opcode, |
1564 InstructionOperand left, InstructionOperand right, | 1461 InstructionOperand left, InstructionOperand right, |
1565 FlagsContinuation* cont) { | 1462 FlagsContinuation* cont) { |
1566 Arm64OperandGenerator g(selector); | 1463 Arm64OperandGenerator g(selector); |
1567 opcode = cont->Encode(opcode); | 1464 opcode = cont->Encode(opcode); |
(...skipping 497 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2065 MachineOperatorBuilder::kFloat64RoundTruncate | | 1962 MachineOperatorBuilder::kFloat64RoundTruncate | |
2066 MachineOperatorBuilder::kFloat64RoundTiesAway | | 1963 MachineOperatorBuilder::kFloat64RoundTiesAway | |
2067 MachineOperatorBuilder::kWord32ShiftIsSafe | | 1964 MachineOperatorBuilder::kWord32ShiftIsSafe | |
2068 MachineOperatorBuilder::kInt32DivIsSafe | | 1965 MachineOperatorBuilder::kInt32DivIsSafe | |
2069 MachineOperatorBuilder::kUint32DivIsSafe; | 1966 MachineOperatorBuilder::kUint32DivIsSafe; |
2070 } | 1967 } |
2071 | 1968 |
2072 } // namespace compiler | 1969 } // namespace compiler |
2073 } // namespace internal | 1970 } // namespace internal |
2074 } // namespace v8 | 1971 } // namespace v8 |
OLD | NEW |