| 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 1398 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1409 void InstructionSelector::VisitFloat64RoundTruncate(Node* node) { | 1409 void InstructionSelector::VisitFloat64RoundTruncate(Node* node) { |
| 1410 VisitRR(this, kArm64Float64RoundTruncate, node); | 1410 VisitRR(this, kArm64Float64RoundTruncate, node); |
| 1411 } | 1411 } |
| 1412 | 1412 |
| 1413 | 1413 |
| 1414 void InstructionSelector::VisitFloat64RoundTiesAway(Node* node) { | 1414 void InstructionSelector::VisitFloat64RoundTiesAway(Node* node) { |
| 1415 VisitRR(this, kArm64Float64RoundTiesAway, node); | 1415 VisitRR(this, kArm64Float64RoundTiesAway, node); |
| 1416 } | 1416 } |
| 1417 | 1417 |
| 1418 | 1418 |
| 1419 void InstructionSelector::VisitCall(Node* node, BasicBlock* handler) { | 1419 void InstructionSelector::EmitPrepareArguments(NodeVector* arguments, |
| 1420 const CallDescriptor* descriptor, |
| 1421 Node* node) { |
| 1420 Arm64OperandGenerator g(this); | 1422 Arm64OperandGenerator g(this); |
| 1421 const CallDescriptor* descriptor = OpParameter<const CallDescriptor*>(node); | |
| 1422 | |
| 1423 FrameStateDescriptor* frame_state_descriptor = nullptr; | |
| 1424 if (descriptor->NeedsFrameState()) { | |
| 1425 frame_state_descriptor = GetFrameStateDescriptor( | |
| 1426 node->InputAt(static_cast<int>(descriptor->InputCount()))); | |
| 1427 } | |
| 1428 | |
| 1429 CallBuffer buffer(zone(), descriptor, frame_state_descriptor); | |
| 1430 | |
| 1431 // Compute InstructionOperands for inputs and outputs. | |
| 1432 // TODO(turbofan): on ARM64 it's probably better to use the code object in a | |
| 1433 // register if there are multiple uses of it. Improve constant pool and the | |
| 1434 // heuristics in the register allocator for where to emit constants. | |
| 1435 InitializeCallBuffer(node, &buffer, true, true); | |
| 1436 | 1423 |
| 1437 // Push the arguments to the stack. | 1424 // Push the arguments to the stack. |
| 1438 int aligned_push_count = static_cast<int>(buffer.pushed_nodes.size()); | 1425 int aligned_push_count = static_cast<int>(arguments->size()); |
| 1439 bool pushed_count_uneven = aligned_push_count & 1; | 1426 bool pushed_count_uneven = aligned_push_count & 1; |
| 1440 // TODO(dcarney): claim and poke probably take small immediates, | 1427 // TODO(dcarney): claim and poke probably take small immediates, |
| 1441 // loop here or whatever. | 1428 // loop here or whatever. |
| 1442 // Bump the stack pointer(s). | 1429 // Bump the stack pointer(s). |
| 1443 if (aligned_push_count > 0) { | 1430 if (aligned_push_count > 0) { |
| 1444 // TODO(dcarney): it would be better to bump the csp here only | 1431 // TODO(dcarney): it would be better to bump the csp here only |
| 1445 // and emit paired stores with increment for non c frames. | 1432 // and emit paired stores with increment for non c frames. |
| 1446 Emit(kArm64Claim, g.NoOutput(), g.TempImmediate(aligned_push_count)); | 1433 Emit(kArm64Claim, g.NoOutput(), g.TempImmediate(aligned_push_count)); |
| 1447 } | 1434 } |
| 1448 // Move arguments to the stack. | 1435 // Move arguments to the stack. |
| 1449 { | 1436 { |
| 1450 int slot = aligned_push_count - 1; | 1437 int slot = aligned_push_count - 1; |
| 1451 // Emit the uneven pushes. | 1438 // Emit the uneven pushes. |
| 1452 if (pushed_count_uneven) { | 1439 if (pushed_count_uneven) { |
| 1453 Node* input = buffer.pushed_nodes[slot]; | 1440 Node* input = (*arguments)[slot]; |
| 1454 Emit(kArm64Poke, g.NoOutput(), g.UseRegister(input), | 1441 Emit(kArm64Poke, g.NoOutput(), g.UseRegister(input), |
| 1455 g.TempImmediate(slot)); | 1442 g.TempImmediate(slot)); |
| 1456 slot--; | 1443 slot--; |
| 1457 } | 1444 } |
| 1458 // Now all pushes can be done in pairs. | 1445 // Now all pushes can be done in pairs. |
| 1459 for (; slot >= 0; slot -= 2) { | 1446 for (; slot >= 0; slot -= 2) { |
| 1460 Emit(kArm64PokePair, g.NoOutput(), | 1447 Emit(kArm64PokePair, g.NoOutput(), g.UseRegister((*arguments)[slot]), |
| 1461 g.UseRegister(buffer.pushed_nodes[slot]), | 1448 g.UseRegister((*arguments)[slot - 1]), g.TempImmediate(slot)); |
| 1462 g.UseRegister(buffer.pushed_nodes[slot - 1]), | |
| 1463 g.TempImmediate(slot)); | |
| 1464 } | 1449 } |
| 1465 } | 1450 } |
| 1466 | |
| 1467 // Pass label of exception handler block. | |
| 1468 CallDescriptor::Flags flags = descriptor->flags(); | |
| 1469 if (handler != nullptr) { | |
| 1470 DCHECK_EQ(IrOpcode::kIfException, handler->front()->opcode()); | |
| 1471 IfExceptionHint hint = OpParameter<IfExceptionHint>(handler->front()); | |
| 1472 if (hint == IfExceptionHint::kLocallyCaught) { | |
| 1473 flags |= CallDescriptor::kHasLocalCatchHandler; | |
| 1474 } | |
| 1475 flags |= CallDescriptor::kHasExceptionHandler; | |
| 1476 buffer.instruction_args.push_back(g.Label(handler)); | |
| 1477 } | |
| 1478 | |
| 1479 // Select the appropriate opcode based on the call type. | |
| 1480 InstructionCode opcode = kArchNop; | |
| 1481 switch (descriptor->kind()) { | |
| 1482 case CallDescriptor::kCallAddress: | |
| 1483 opcode = | |
| 1484 kArchCallCFunction | | |
| 1485 MiscField::encode(static_cast<int>(descriptor->CParameterCount())); | |
| 1486 break; | |
| 1487 case CallDescriptor::kCallCodeObject: | |
| 1488 opcode = kArchCallCodeObject | MiscField::encode(flags); | |
| 1489 break; | |
| 1490 case CallDescriptor::kCallJSFunction: | |
| 1491 opcode = kArchCallJSFunction | MiscField::encode(flags); | |
| 1492 break; | |
| 1493 case CallDescriptor::kLazyBailout: | |
| 1494 opcode = kArchLazyBailout | MiscField::encode(flags); | |
| 1495 break; | |
| 1496 } | |
| 1497 | |
| 1498 // Emit the call instruction. | |
| 1499 size_t const output_count = buffer.outputs.size(); | |
| 1500 auto* outputs = output_count ? &buffer.outputs.front() : nullptr; | |
| 1501 Emit(opcode, output_count, outputs, buffer.instruction_args.size(), | |
| 1502 &buffer.instruction_args.front())->MarkAsCall(); | |
| 1503 } | 1451 } |
| 1504 | 1452 |
| 1505 | 1453 |
| 1506 void InstructionSelector::VisitTailCall(Node* node) { | 1454 void InstructionSelector::VisitTailCall(Node* node) { |
| 1507 Arm64OperandGenerator g(this); | 1455 Arm64OperandGenerator g(this); |
| 1508 const CallDescriptor* descriptor = OpParameter<const CallDescriptor*>(node); | 1456 const CallDescriptor* descriptor = OpParameter<const CallDescriptor*>(node); |
| 1509 DCHECK_NE(0, descriptor->flags() & CallDescriptor::kSupportsTailCalls); | 1457 DCHECK_NE(0, descriptor->flags() & CallDescriptor::kSupportsTailCalls); |
| 1510 DCHECK_EQ(0, descriptor->flags() & CallDescriptor::kPatchableCallSite); | 1458 DCHECK_EQ(0, descriptor->flags() & CallDescriptor::kPatchableCallSite); |
| 1511 DCHECK_EQ(0, descriptor->flags() & CallDescriptor::kNeedsNopAfterCall); | 1459 DCHECK_EQ(0, descriptor->flags() & CallDescriptor::kNeedsNopAfterCall); |
| 1512 | 1460 |
| (...skipping 604 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2117 MachineOperatorBuilder::kFloat64RoundTruncate | | 2065 MachineOperatorBuilder::kFloat64RoundTruncate | |
| 2118 MachineOperatorBuilder::kFloat64RoundTiesAway | | 2066 MachineOperatorBuilder::kFloat64RoundTiesAway | |
| 2119 MachineOperatorBuilder::kWord32ShiftIsSafe | | 2067 MachineOperatorBuilder::kWord32ShiftIsSafe | |
| 2120 MachineOperatorBuilder::kInt32DivIsSafe | | 2068 MachineOperatorBuilder::kInt32DivIsSafe | |
| 2121 MachineOperatorBuilder::kUint32DivIsSafe; | 2069 MachineOperatorBuilder::kUint32DivIsSafe; |
| 2122 } | 2070 } |
| 2123 | 2071 |
| 2124 } // namespace compiler | 2072 } // namespace compiler |
| 2125 } // namespace internal | 2073 } // namespace internal |
| 2126 } // namespace v8 | 2074 } // namespace v8 |
| OLD | NEW |