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/base/adapters.h" | 5 #include "src/base/adapters.h" |
6 #include "src/base/bits.h" | 6 #include "src/base/bits.h" |
7 #include "src/compiler/instruction-selector-impl.h" | 7 #include "src/compiler/instruction-selector-impl.h" |
8 #include "src/compiler/node-matchers.h" | 8 #include "src/compiler/node-matchers.h" |
9 #include "src/compiler/node-properties.h" | 9 #include "src/compiler/node-properties.h" |
10 | 10 |
(...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
230 if (cont->IsSet()) { | 230 if (cont->IsSet()) { |
231 outputs[output_count++] = g.DefineAsRegister(cont->result()); | 231 outputs[output_count++] = g.DefineAsRegister(cont->result()); |
232 } | 232 } |
233 | 233 |
234 DCHECK_NE(0u, input_count); | 234 DCHECK_NE(0u, input_count); |
235 DCHECK_NE(0u, output_count); | 235 DCHECK_NE(0u, output_count); |
236 DCHECK_GE(arraysize(inputs), input_count); | 236 DCHECK_GE(arraysize(inputs), input_count); |
237 DCHECK_GE(arraysize(outputs), output_count); | 237 DCHECK_GE(arraysize(outputs), output_count); |
238 DCHECK_NE(kMode_None, AddressingModeField::decode(opcode)); | 238 DCHECK_NE(kMode_None, AddressingModeField::decode(opcode)); |
239 | 239 |
240 selector->Emit(cont->Encode(opcode), output_count, outputs, input_count, | 240 opcode = cont->Encode(opcode); |
241 inputs); | 241 if (cont->IsDeoptimize()) { |
| 242 selector->EmitDeoptimize(opcode, output_count, outputs, input_count, inputs, |
| 243 cont->frame_state()); |
| 244 } else { |
| 245 selector->Emit(opcode, output_count, outputs, input_count, inputs); |
| 246 } |
242 } | 247 } |
243 | 248 |
244 | 249 |
245 void VisitBinop(InstructionSelector* selector, Node* node, | 250 void VisitBinop(InstructionSelector* selector, Node* node, |
246 InstructionCode opcode, InstructionCode reverse_opcode) { | 251 InstructionCode opcode, InstructionCode reverse_opcode) { |
247 FlagsContinuation cont; | 252 FlagsContinuation cont; |
248 VisitBinop(selector, node, opcode, reverse_opcode, &cont); | 253 VisitBinop(selector, node, opcode, reverse_opcode, &cont); |
249 } | 254 } |
250 | 255 |
251 | 256 |
(...skipping 432 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
684 if (cont->IsSet()) { | 689 if (cont->IsSet()) { |
685 outputs[output_count++] = g.DefineAsRegister(cont->result()); | 690 outputs[output_count++] = g.DefineAsRegister(cont->result()); |
686 } | 691 } |
687 | 692 |
688 DCHECK_NE(0u, input_count); | 693 DCHECK_NE(0u, input_count); |
689 DCHECK_NE(0u, output_count); | 694 DCHECK_NE(0u, output_count); |
690 DCHECK_GE(arraysize(inputs), input_count); | 695 DCHECK_GE(arraysize(inputs), input_count); |
691 DCHECK_GE(arraysize(outputs), output_count); | 696 DCHECK_GE(arraysize(outputs), output_count); |
692 DCHECK_NE(kMode_None, AddressingModeField::decode(opcode)); | 697 DCHECK_NE(kMode_None, AddressingModeField::decode(opcode)); |
693 | 698 |
694 selector->Emit(cont->Encode(opcode), output_count, outputs, input_count, | 699 opcode = cont->Encode(opcode); |
695 inputs); | 700 if (cont->IsDeoptimize()) { |
| 701 selector->EmitDeoptimize(opcode, output_count, outputs, input_count, inputs, |
| 702 cont->frame_state()); |
| 703 } else { |
| 704 selector->Emit(opcode, output_count, outputs, input_count, inputs); |
| 705 } |
696 } | 706 } |
697 | 707 |
698 | 708 |
699 template <typename TryMatchShift> | 709 template <typename TryMatchShift> |
700 void VisitShift(InstructionSelector* selector, Node* node, | 710 void VisitShift(InstructionSelector* selector, Node* node, |
701 TryMatchShift try_match_shift) { | 711 TryMatchShift try_match_shift) { |
702 FlagsContinuation cont; | 712 FlagsContinuation cont; |
703 VisitShift(selector, node, try_match_shift, &cont); | 713 VisitShift(selector, node, try_match_shift, &cont); |
704 } | 714 } |
705 | 715 |
(...skipping 571 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1277 | 1287 |
1278 // Shared routine for multiple compare operations. | 1288 // Shared routine for multiple compare operations. |
1279 void VisitCompare(InstructionSelector* selector, InstructionCode opcode, | 1289 void VisitCompare(InstructionSelector* selector, InstructionCode opcode, |
1280 InstructionOperand left, InstructionOperand right, | 1290 InstructionOperand left, InstructionOperand right, |
1281 FlagsContinuation* cont) { | 1291 FlagsContinuation* cont) { |
1282 ArmOperandGenerator g(selector); | 1292 ArmOperandGenerator g(selector); |
1283 opcode = cont->Encode(opcode); | 1293 opcode = cont->Encode(opcode); |
1284 if (cont->IsBranch()) { | 1294 if (cont->IsBranch()) { |
1285 selector->Emit(opcode, g.NoOutput(), left, right, | 1295 selector->Emit(opcode, g.NoOutput(), left, right, |
1286 g.Label(cont->true_block()), g.Label(cont->false_block())); | 1296 g.Label(cont->true_block()), g.Label(cont->false_block())); |
| 1297 } else if (cont->IsDeoptimize()) { |
| 1298 selector->EmitDeoptimize(opcode, g.NoOutput(), left, right, |
| 1299 cont->frame_state()); |
1287 } else { | 1300 } else { |
1288 DCHECK(cont->IsSet()); | 1301 DCHECK(cont->IsSet()); |
1289 selector->Emit(opcode, g.DefineAsRegister(cont->result()), left, right); | 1302 selector->Emit(opcode, g.DefineAsRegister(cont->result()), left, right); |
1290 } | 1303 } |
1291 } | 1304 } |
1292 | 1305 |
1293 | 1306 |
1294 // Shared routine for multiple float32 compare operations. | 1307 // Shared routine for multiple float32 compare operations. |
1295 void VisitFloat32Compare(InstructionSelector* selector, Node* node, | 1308 void VisitFloat32Compare(InstructionSelector* selector, Node* node, |
1296 FlagsContinuation* cont) { | 1309 FlagsContinuation* cont) { |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1350 input_count++; | 1363 input_count++; |
1351 } else { | 1364 } else { |
1352 opcode |= AddressingModeField::encode(kMode_Operand2_R); | 1365 opcode |= AddressingModeField::encode(kMode_Operand2_R); |
1353 inputs[input_count++] = g.UseRegister(m.left().node()); | 1366 inputs[input_count++] = g.UseRegister(m.left().node()); |
1354 inputs[input_count++] = g.UseRegister(m.right().node()); | 1367 inputs[input_count++] = g.UseRegister(m.right().node()); |
1355 } | 1368 } |
1356 | 1369 |
1357 if (cont->IsBranch()) { | 1370 if (cont->IsBranch()) { |
1358 inputs[input_count++] = g.Label(cont->true_block()); | 1371 inputs[input_count++] = g.Label(cont->true_block()); |
1359 inputs[input_count++] = g.Label(cont->false_block()); | 1372 inputs[input_count++] = g.Label(cont->false_block()); |
1360 } else { | 1373 } else if (cont->IsSet()) { |
1361 DCHECK(cont->IsSet()); | |
1362 outputs[output_count++] = g.DefineAsRegister(cont->result()); | 1374 outputs[output_count++] = g.DefineAsRegister(cont->result()); |
1363 } | 1375 } |
1364 | 1376 |
1365 DCHECK_NE(0u, input_count); | 1377 DCHECK_NE(0u, input_count); |
1366 DCHECK_GE(arraysize(inputs), input_count); | 1378 DCHECK_GE(arraysize(inputs), input_count); |
1367 DCHECK_GE(arraysize(outputs), output_count); | 1379 DCHECK_GE(arraysize(outputs), output_count); |
1368 | 1380 |
1369 selector->Emit(cont->Encode(opcode), output_count, outputs, input_count, | 1381 opcode = cont->Encode(opcode); |
1370 inputs); | 1382 if (cont->IsDeoptimize()) { |
| 1383 selector->EmitDeoptimize(opcode, output_count, outputs, input_count, inputs, |
| 1384 cont->frame_state()); |
| 1385 } else { |
| 1386 selector->Emit(opcode, output_count, outputs, input_count, inputs); |
| 1387 } |
1371 } | 1388 } |
1372 | 1389 |
1373 | 1390 |
1374 void VisitWordCompare(InstructionSelector* selector, Node* node, | 1391 void VisitWordCompare(InstructionSelector* selector, Node* node, |
1375 FlagsContinuation* cont) { | 1392 FlagsContinuation* cont) { |
1376 VisitWordCompare(selector, node, kArmCmp, cont); | 1393 VisitWordCompare(selector, node, kArmCmp, cont); |
1377 } | 1394 } |
1378 | 1395 |
1379 | 1396 |
1380 // Shared routine for word comparisons against zero. | 1397 // Shared routine for word comparisons against zero. |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1475 } | 1492 } |
1476 | 1493 |
1477 // Continuation could not be combined with a compare, emit compare against 0. | 1494 // Continuation could not be combined with a compare, emit compare against 0. |
1478 ArmOperandGenerator g(selector); | 1495 ArmOperandGenerator g(selector); |
1479 InstructionCode const opcode = | 1496 InstructionCode const opcode = |
1480 cont->Encode(kArmTst) | AddressingModeField::encode(kMode_Operand2_R); | 1497 cont->Encode(kArmTst) | AddressingModeField::encode(kMode_Operand2_R); |
1481 InstructionOperand const value_operand = g.UseRegister(value); | 1498 InstructionOperand const value_operand = g.UseRegister(value); |
1482 if (cont->IsBranch()) { | 1499 if (cont->IsBranch()) { |
1483 selector->Emit(opcode, g.NoOutput(), value_operand, value_operand, | 1500 selector->Emit(opcode, g.NoOutput(), value_operand, value_operand, |
1484 g.Label(cont->true_block()), g.Label(cont->false_block())); | 1501 g.Label(cont->true_block()), g.Label(cont->false_block())); |
| 1502 } else if (cont->IsDeoptimize()) { |
| 1503 selector->EmitDeoptimize(opcode, g.NoOutput(), value_operand, value_operand, |
| 1504 cont->frame_state()); |
1485 } else { | 1505 } else { |
| 1506 DCHECK(cont->IsSet()); |
1486 selector->Emit(opcode, g.DefineAsRegister(cont->result()), value_operand, | 1507 selector->Emit(opcode, g.DefineAsRegister(cont->result()), value_operand, |
1487 value_operand); | 1508 value_operand); |
1488 } | 1509 } |
1489 } | 1510 } |
1490 | 1511 |
1491 } // namespace | 1512 } // namespace |
1492 | 1513 |
1493 | |
1494 void InstructionSelector::VisitBranch(Node* branch, BasicBlock* tbranch, | 1514 void InstructionSelector::VisitBranch(Node* branch, BasicBlock* tbranch, |
1495 BasicBlock* fbranch) { | 1515 BasicBlock* fbranch) { |
1496 FlagsContinuation cont(kNotEqual, tbranch, fbranch); | 1516 FlagsContinuation cont(kNotEqual, tbranch, fbranch); |
1497 VisitWordCompareZero(this, branch, branch->InputAt(0), &cont); | 1517 VisitWordCompareZero(this, branch, branch->InputAt(0), &cont); |
1498 } | 1518 } |
1499 | 1519 |
| 1520 void InstructionSelector::VisitDeoptimizeIf(Node* node) { |
| 1521 FlagsContinuation cont = |
| 1522 FlagsContinuation::ForDeoptimize(kNotEqual, node->InputAt(1)); |
| 1523 VisitWordCompareZero(this, node, node->InputAt(0), &cont); |
| 1524 } |
| 1525 |
| 1526 void InstructionSelector::VisitDeoptimizeUnless(Node* node) { |
| 1527 FlagsContinuation cont = |
| 1528 FlagsContinuation::ForDeoptimize(kEqual, node->InputAt(1)); |
| 1529 VisitWordCompareZero(this, node, node->InputAt(0), &cont); |
| 1530 } |
1500 | 1531 |
1501 void InstructionSelector::VisitSwitch(Node* node, const SwitchInfo& sw) { | 1532 void InstructionSelector::VisitSwitch(Node* node, const SwitchInfo& sw) { |
1502 ArmOperandGenerator g(this); | 1533 ArmOperandGenerator g(this); |
1503 InstructionOperand value_operand = g.UseRegister(node->InputAt(0)); | 1534 InstructionOperand value_operand = g.UseRegister(node->InputAt(0)); |
1504 | 1535 |
1505 // Emit either ArchTableSwitch or ArchLookupSwitch. | 1536 // Emit either ArchTableSwitch or ArchLookupSwitch. |
1506 size_t table_space_cost = 4 + sw.value_range; | 1537 size_t table_space_cost = 4 + sw.value_range; |
1507 size_t table_time_cost = 3; | 1538 size_t table_time_cost = 3; |
1508 size_t lookup_space_cost = 3 + 2 * sw.case_count; | 1539 size_t lookup_space_cost = 3 + 2 * sw.case_count; |
1509 size_t lookup_time_cost = sw.case_count; | 1540 size_t lookup_time_cost = sw.case_count; |
(...skipping 10 matching lines...) Expand all Loading... |
1520 // Generate a table lookup. | 1551 // Generate a table lookup. |
1521 return EmitTableSwitch(sw, index_operand); | 1552 return EmitTableSwitch(sw, index_operand); |
1522 } | 1553 } |
1523 | 1554 |
1524 // Generate a sequence of conditional jumps. | 1555 // Generate a sequence of conditional jumps. |
1525 return EmitLookupSwitch(sw, value_operand); | 1556 return EmitLookupSwitch(sw, value_operand); |
1526 } | 1557 } |
1527 | 1558 |
1528 | 1559 |
1529 void InstructionSelector::VisitWord32Equal(Node* const node) { | 1560 void InstructionSelector::VisitWord32Equal(Node* const node) { |
1530 FlagsContinuation cont(kEqual, node); | 1561 FlagsContinuation cont = FlagsContinuation::ForSet(kEqual, node); |
1531 Int32BinopMatcher m(node); | 1562 Int32BinopMatcher m(node); |
1532 if (m.right().Is(0)) { | 1563 if (m.right().Is(0)) { |
1533 return VisitWordCompareZero(this, m.node(), m.left().node(), &cont); | 1564 return VisitWordCompareZero(this, m.node(), m.left().node(), &cont); |
1534 } | 1565 } |
1535 VisitWordCompare(this, node, &cont); | 1566 VisitWordCompare(this, node, &cont); |
1536 } | 1567 } |
1537 | 1568 |
1538 | 1569 |
1539 void InstructionSelector::VisitInt32LessThan(Node* node) { | 1570 void InstructionSelector::VisitInt32LessThan(Node* node) { |
1540 FlagsContinuation cont(kSignedLessThan, node); | 1571 FlagsContinuation cont = FlagsContinuation::ForSet(kSignedLessThan, node); |
1541 VisitWordCompare(this, node, &cont); | 1572 VisitWordCompare(this, node, &cont); |
1542 } | 1573 } |
1543 | 1574 |
1544 | 1575 |
1545 void InstructionSelector::VisitInt32LessThanOrEqual(Node* node) { | 1576 void InstructionSelector::VisitInt32LessThanOrEqual(Node* node) { |
1546 FlagsContinuation cont(kSignedLessThanOrEqual, node); | 1577 FlagsContinuation cont = |
| 1578 FlagsContinuation::ForSet(kSignedLessThanOrEqual, node); |
1547 VisitWordCompare(this, node, &cont); | 1579 VisitWordCompare(this, node, &cont); |
1548 } | 1580 } |
1549 | 1581 |
1550 | 1582 |
1551 void InstructionSelector::VisitUint32LessThan(Node* node) { | 1583 void InstructionSelector::VisitUint32LessThan(Node* node) { |
1552 FlagsContinuation cont(kUnsignedLessThan, node); | 1584 FlagsContinuation cont = FlagsContinuation::ForSet(kUnsignedLessThan, node); |
1553 VisitWordCompare(this, node, &cont); | 1585 VisitWordCompare(this, node, &cont); |
1554 } | 1586 } |
1555 | 1587 |
1556 | 1588 |
1557 void InstructionSelector::VisitUint32LessThanOrEqual(Node* node) { | 1589 void InstructionSelector::VisitUint32LessThanOrEqual(Node* node) { |
1558 FlagsContinuation cont(kUnsignedLessThanOrEqual, node); | 1590 FlagsContinuation cont = |
| 1591 FlagsContinuation::ForSet(kUnsignedLessThanOrEqual, node); |
1559 VisitWordCompare(this, node, &cont); | 1592 VisitWordCompare(this, node, &cont); |
1560 } | 1593 } |
1561 | 1594 |
1562 | 1595 |
1563 void InstructionSelector::VisitInt32AddWithOverflow(Node* node) { | 1596 void InstructionSelector::VisitInt32AddWithOverflow(Node* node) { |
1564 if (Node* ovf = NodeProperties::FindProjection(node, 1)) { | 1597 if (Node* ovf = NodeProperties::FindProjection(node, 1)) { |
1565 FlagsContinuation cont(kOverflow, ovf); | 1598 FlagsContinuation cont = FlagsContinuation::ForSet(kOverflow, ovf); |
1566 return VisitBinop(this, node, kArmAdd, kArmAdd, &cont); | 1599 return VisitBinop(this, node, kArmAdd, kArmAdd, &cont); |
1567 } | 1600 } |
1568 FlagsContinuation cont; | 1601 FlagsContinuation cont; |
1569 VisitBinop(this, node, kArmAdd, kArmAdd, &cont); | 1602 VisitBinop(this, node, kArmAdd, kArmAdd, &cont); |
1570 } | 1603 } |
1571 | 1604 |
1572 | 1605 |
1573 void InstructionSelector::VisitInt32SubWithOverflow(Node* node) { | 1606 void InstructionSelector::VisitInt32SubWithOverflow(Node* node) { |
1574 if (Node* ovf = NodeProperties::FindProjection(node, 1)) { | 1607 if (Node* ovf = NodeProperties::FindProjection(node, 1)) { |
1575 FlagsContinuation cont(kOverflow, ovf); | 1608 FlagsContinuation cont = FlagsContinuation::ForSet(kOverflow, ovf); |
1576 return VisitBinop(this, node, kArmSub, kArmRsb, &cont); | 1609 return VisitBinop(this, node, kArmSub, kArmRsb, &cont); |
1577 } | 1610 } |
1578 FlagsContinuation cont; | 1611 FlagsContinuation cont; |
1579 VisitBinop(this, node, kArmSub, kArmRsb, &cont); | 1612 VisitBinop(this, node, kArmSub, kArmRsb, &cont); |
1580 } | 1613 } |
1581 | 1614 |
1582 | 1615 |
1583 void InstructionSelector::VisitFloat32Equal(Node* node) { | 1616 void InstructionSelector::VisitFloat32Equal(Node* node) { |
1584 FlagsContinuation cont(kEqual, node); | 1617 FlagsContinuation cont = FlagsContinuation::ForSet(kEqual, node); |
1585 VisitFloat32Compare(this, node, &cont); | 1618 VisitFloat32Compare(this, node, &cont); |
1586 } | 1619 } |
1587 | 1620 |
1588 | 1621 |
1589 void InstructionSelector::VisitFloat32LessThan(Node* node) { | 1622 void InstructionSelector::VisitFloat32LessThan(Node* node) { |
1590 FlagsContinuation cont(kFloatLessThan, node); | 1623 FlagsContinuation cont = FlagsContinuation::ForSet(kFloatLessThan, node); |
1591 VisitFloat32Compare(this, node, &cont); | 1624 VisitFloat32Compare(this, node, &cont); |
1592 } | 1625 } |
1593 | 1626 |
1594 | 1627 |
1595 void InstructionSelector::VisitFloat32LessThanOrEqual(Node* node) { | 1628 void InstructionSelector::VisitFloat32LessThanOrEqual(Node* node) { |
1596 FlagsContinuation cont(kFloatLessThanOrEqual, node); | 1629 FlagsContinuation cont = |
| 1630 FlagsContinuation::ForSet(kFloatLessThanOrEqual, node); |
1597 VisitFloat32Compare(this, node, &cont); | 1631 VisitFloat32Compare(this, node, &cont); |
1598 } | 1632 } |
1599 | 1633 |
1600 | 1634 |
1601 void InstructionSelector::VisitFloat64Equal(Node* node) { | 1635 void InstructionSelector::VisitFloat64Equal(Node* node) { |
1602 FlagsContinuation cont(kEqual, node); | 1636 FlagsContinuation cont = FlagsContinuation::ForSet(kEqual, node); |
1603 VisitFloat64Compare(this, node, &cont); | 1637 VisitFloat64Compare(this, node, &cont); |
1604 } | 1638 } |
1605 | 1639 |
1606 | 1640 |
1607 void InstructionSelector::VisitFloat64LessThan(Node* node) { | 1641 void InstructionSelector::VisitFloat64LessThan(Node* node) { |
1608 FlagsContinuation cont(kFloatLessThan, node); | 1642 FlagsContinuation cont = FlagsContinuation::ForSet(kFloatLessThan, node); |
1609 VisitFloat64Compare(this, node, &cont); | 1643 VisitFloat64Compare(this, node, &cont); |
1610 } | 1644 } |
1611 | 1645 |
1612 | 1646 |
1613 void InstructionSelector::VisitFloat64LessThanOrEqual(Node* node) { | 1647 void InstructionSelector::VisitFloat64LessThanOrEqual(Node* node) { |
1614 FlagsContinuation cont(kFloatLessThanOrEqual, node); | 1648 FlagsContinuation cont = |
| 1649 FlagsContinuation::ForSet(kFloatLessThanOrEqual, node); |
1615 VisitFloat64Compare(this, node, &cont); | 1650 VisitFloat64Compare(this, node, &cont); |
1616 } | 1651 } |
1617 | 1652 |
1618 | 1653 |
1619 void InstructionSelector::VisitFloat64ExtractLowWord32(Node* node) { | 1654 void InstructionSelector::VisitFloat64ExtractLowWord32(Node* node) { |
1620 VisitRR(this, kArmVmovLowU32F64, node); | 1655 VisitRR(this, kArmVmovLowU32F64, node); |
1621 } | 1656 } |
1622 | 1657 |
1623 | 1658 |
1624 void InstructionSelector::VisitFloat64ExtractHighWord32(Node* node) { | 1659 void InstructionSelector::VisitFloat64ExtractHighWord32(Node* node) { |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1677 MachineOperatorBuilder::kFloat64RoundTiesAway | | 1712 MachineOperatorBuilder::kFloat64RoundTiesAway | |
1678 MachineOperatorBuilder::kFloat32RoundTiesEven | | 1713 MachineOperatorBuilder::kFloat32RoundTiesEven | |
1679 MachineOperatorBuilder::kFloat64RoundTiesEven; | 1714 MachineOperatorBuilder::kFloat64RoundTiesEven; |
1680 } | 1715 } |
1681 return flags; | 1716 return flags; |
1682 } | 1717 } |
1683 | 1718 |
1684 } // namespace compiler | 1719 } // namespace compiler |
1685 } // namespace internal | 1720 } // namespace internal |
1686 } // namespace v8 | 1721 } // namespace v8 |
OLD | NEW |