| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_X64. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_X64. |
| 6 #if defined(TARGET_ARCH_X64) | 6 #if defined(TARGET_ARCH_X64) |
| 7 | 7 |
| 8 #include "vm/intermediate_language.h" | 8 #include "vm/intermediate_language.h" |
| 9 | 9 |
| 10 #include "lib/error.h" | 10 #include "lib/error.h" |
| (...skipping 1409 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1420 | 1420 |
| 1421 Register temp = locs()->temp(0).reg(); | 1421 Register temp = locs()->temp(0).reg(); |
| 1422 // Generate stack overflow check. | 1422 // Generate stack overflow check. |
| 1423 __ movq(temp, Immediate(Isolate::Current()->stack_limit_address())); | 1423 __ movq(temp, Immediate(Isolate::Current()->stack_limit_address())); |
| 1424 __ cmpq(RSP, Address(temp, 0)); | 1424 __ cmpq(RSP, Address(temp, 0)); |
| 1425 __ j(BELOW_EQUAL, slow_path->entry_label()); | 1425 __ j(BELOW_EQUAL, slow_path->entry_label()); |
| 1426 __ Bind(slow_path->exit_label()); | 1426 __ Bind(slow_path->exit_label()); |
| 1427 } | 1427 } |
| 1428 | 1428 |
| 1429 | 1429 |
| 1430 LocationSummary* BinaryOpComp::MakeLocationSummary() const { | 1430 LocationSummary* BinarySmiOpComp::MakeLocationSummary() const { |
| 1431 const intptr_t kNumInputs = 2; | 1431 const intptr_t kNumInputs = 2; |
| 1432 | |
| 1433 // Double operation are handled in DoubleBinaryOpComp. | |
| 1434 ASSERT(operands_type() != kDoubleOperands); | |
| 1435 | |
| 1436 if (operands_type() == kMintOperands) { | |
| 1437 ASSERT(op_kind() == Token::kBIT_AND); | |
| 1438 const intptr_t kNumTemps = 0; | |
| 1439 LocationSummary* summary = | |
| 1440 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | |
| 1441 summary->set_in(0, Location::RegisterLocation(RAX)); | |
| 1442 summary->set_in(1, Location::RegisterLocation(RCX)); | |
| 1443 summary->set_out(Location::RegisterLocation(RAX)); | |
| 1444 return summary; | |
| 1445 } | |
| 1446 | |
| 1447 ASSERT(operands_type() == kSmiOperands); | |
| 1448 | |
| 1449 if (op_kind() == Token::kTRUNCDIV) { | 1432 if (op_kind() == Token::kTRUNCDIV) { |
| 1450 const intptr_t kNumTemps = 3; | 1433 const intptr_t kNumTemps = 3; |
| 1451 LocationSummary* summary = | 1434 LocationSummary* summary = |
| 1452 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1435 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 1453 summary->set_in(0, Location::RegisterLocation(RAX)); | 1436 summary->set_in(0, Location::RegisterLocation(RAX)); |
| 1454 summary->set_in(1, Location::RegisterLocation(RCX)); | 1437 summary->set_in(1, Location::RegisterLocation(RCX)); |
| 1455 summary->set_out(Location::SameAsFirstInput()); | 1438 summary->set_out(Location::SameAsFirstInput()); |
| 1456 summary->set_temp(0, Location::RegisterLocation(RBX)); | 1439 summary->set_temp(0, Location::RegisterLocation(RBX)); |
| 1457 // Will be used for for sign extension. | 1440 // Will be used for for sign extension. |
| 1458 summary->set_temp(1, Location::RegisterLocation(RDX)); | 1441 summary->set_temp(1, Location::RegisterLocation(RDX)); |
| (...skipping 25 matching lines...) Expand all Loading... |
| 1484 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1467 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 1485 summary->set_in(0, Location::RequiresRegister()); | 1468 summary->set_in(0, Location::RequiresRegister()); |
| 1486 summary->set_in(1, Location::RequiresRegister()); | 1469 summary->set_in(1, Location::RequiresRegister()); |
| 1487 summary->set_out(Location::SameAsFirstInput()); | 1470 summary->set_out(Location::SameAsFirstInput()); |
| 1488 summary->set_temp(0, Location::RequiresRegister()); | 1471 summary->set_temp(0, Location::RequiresRegister()); |
| 1489 return summary; | 1472 return summary; |
| 1490 } | 1473 } |
| 1491 } | 1474 } |
| 1492 | 1475 |
| 1493 | 1476 |
| 1494 static void EmitSmiBinaryOp(FlowGraphCompiler* compiler, BinaryOpComp* comp) { | 1477 void BinarySmiOpComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1495 Register left = comp->locs()->in(0).reg(); | 1478 Register left = locs()->in(0).reg(); |
| 1496 Register right = comp->locs()->in(1).reg(); | 1479 Register right = locs()->in(1).reg(); |
| 1497 Register result = comp->locs()->out().reg(); | 1480 Register result = locs()->out().reg(); |
| 1498 Register temp = comp->locs()->temp(0).reg(); | 1481 Register temp = locs()->temp(0).reg(); |
| 1499 ASSERT(left == result); | 1482 ASSERT(left == result); |
| 1500 const bool left_is_smi = comp->left()->ResultCid() == kSmiCid; | 1483 const bool left_is_smi = this->left()->ResultCid() == kSmiCid; |
| 1501 const bool right_is_smi = comp->right()->ResultCid() == kSmiCid; | 1484 const bool right_is_smi = this->right()->ResultCid() == kSmiCid; |
| 1502 bool can_deopt; | 1485 bool can_deopt; |
| 1503 switch (comp->op_kind()) { | 1486 switch (op_kind()) { |
| 1504 case Token::kBIT_AND: | 1487 case Token::kBIT_AND: |
| 1505 case Token::kBIT_OR: | 1488 case Token::kBIT_OR: |
| 1506 case Token::kBIT_XOR: | 1489 case Token::kBIT_XOR: |
| 1507 can_deopt = !(right_is_smi && left_is_smi); | 1490 can_deopt = !(right_is_smi && left_is_smi); |
| 1508 break; | 1491 break; |
| 1509 default: | 1492 default: |
| 1510 can_deopt = true; | 1493 can_deopt = true; |
| 1511 } | 1494 } |
| 1512 Label* deopt = NULL; | 1495 Label* deopt = NULL; |
| 1513 if (can_deopt) { | 1496 if (can_deopt) { |
| 1514 deopt = compiler->AddDeoptStub(comp->instance_call()->deopt_id(), | 1497 deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), |
| 1515 comp->instance_call()->try_index(), | 1498 instance_call()->try_index(), |
| 1516 kDeoptSmiBinaryOp); | 1499 kDeoptBinarySmiOp); |
| 1517 } | 1500 } |
| 1518 if (!left_is_smi || !right_is_smi) { | 1501 if (!left_is_smi || !right_is_smi) { |
| 1519 __ movq(temp, left); | 1502 __ movq(temp, left); |
| 1520 __ orq(temp, right); | 1503 __ orq(temp, right); |
| 1521 __ testq(temp, Immediate(kSmiTagMask)); | 1504 __ testq(temp, Immediate(kSmiTagMask)); |
| 1522 __ j(NOT_ZERO, deopt); | 1505 __ j(NOT_ZERO, deopt); |
| 1523 } | 1506 } |
| 1524 switch (comp->op_kind()) { | 1507 switch (op_kind()) { |
| 1525 case Token::kADD: { | 1508 case Token::kADD: { |
| 1526 __ addq(left, right); | 1509 __ addq(left, right); |
| 1527 __ j(OVERFLOW, deopt); | 1510 __ j(OVERFLOW, deopt); |
| 1528 break; | 1511 break; |
| 1529 } | 1512 } |
| 1530 case Token::kSUB: { | 1513 case Token::kSUB: { |
| 1531 __ subq(left, right); | 1514 __ subq(left, right); |
| 1532 __ j(OVERFLOW, deopt); | 1515 __ j(OVERFLOW, deopt); |
| 1533 break; | 1516 break; |
| 1534 } | 1517 } |
| (...skipping 19 matching lines...) Expand all Loading... |
| 1554 break; | 1537 break; |
| 1555 } | 1538 } |
| 1556 case Token::kTRUNCDIV: { | 1539 case Token::kTRUNCDIV: { |
| 1557 // Handle divide by zero in runtime. | 1540 // Handle divide by zero in runtime. |
| 1558 // Deoptimization requires that temp and right are preserved. | 1541 // Deoptimization requires that temp and right are preserved. |
| 1559 __ testq(right, right); | 1542 __ testq(right, right); |
| 1560 __ j(ZERO, deopt); | 1543 __ j(ZERO, deopt); |
| 1561 ASSERT(left == RAX); | 1544 ASSERT(left == RAX); |
| 1562 ASSERT((right != RDX) && (right != RAX)); | 1545 ASSERT((right != RDX) && (right != RAX)); |
| 1563 ASSERT((temp != RDX) && (temp != RAX)); | 1546 ASSERT((temp != RDX) && (temp != RAX)); |
| 1564 ASSERT(comp->locs()->temp(1).reg() == RDX); | 1547 ASSERT(locs()->temp(1).reg() == RDX); |
| 1565 ASSERT(result == RAX); | 1548 ASSERT(result == RAX); |
| 1566 Register right_temp = comp->locs()->temp(2).reg(); | 1549 Register right_temp = locs()->temp(2).reg(); |
| 1567 __ movq(right_temp, right); | 1550 __ movq(right_temp, right); |
| 1568 __ SmiUntag(left); | 1551 __ SmiUntag(left); |
| 1569 __ SmiUntag(right_temp); | 1552 __ SmiUntag(right_temp); |
| 1570 __ cqo(); // Sign extend RAX -> RDX:RAX. | 1553 __ cqo(); // Sign extend RAX -> RDX:RAX. |
| 1571 __ idivq(right_temp); // RAX: quotient, RDX: remainder. | 1554 __ idivq(right_temp); // RAX: quotient, RDX: remainder. |
| 1572 // Check the corner case of dividing the 'MIN_SMI' with -1, in which | 1555 // Check the corner case of dividing the 'MIN_SMI' with -1, in which |
| 1573 // case we cannot tag the result. | 1556 // case we cannot tag the result. |
| 1574 __ cmpq(result, Immediate(0x4000000000000000)); | 1557 __ cmpq(result, Immediate(0x4000000000000000)); |
| 1575 __ j(EQUAL, deopt); | 1558 __ j(EQUAL, deopt); |
| 1576 __ SmiTag(result); | 1559 __ SmiTag(result); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 1593 __ SmiTag(left); | 1576 __ SmiTag(left); |
| 1594 break; | 1577 break; |
| 1595 } | 1578 } |
| 1596 case Token::kSHL: { | 1579 case Token::kSHL: { |
| 1597 Label call_method, done; | 1580 Label call_method, done; |
| 1598 // Check if count too large for handling it inlined. | 1581 // Check if count too large for handling it inlined. |
| 1599 __ movq(temp, left); | 1582 __ movq(temp, left); |
| 1600 __ cmpq(right, | 1583 __ cmpq(right, |
| 1601 Immediate(reinterpret_cast<int64_t>(Smi::New(Smi::kBits)))); | 1584 Immediate(reinterpret_cast<int64_t>(Smi::New(Smi::kBits)))); |
| 1602 __ j(ABOVE_EQUAL, &call_method, Assembler::kNearJump); | 1585 __ j(ABOVE_EQUAL, &call_method, Assembler::kNearJump); |
| 1603 Register right_temp = comp->locs()->temp(1).reg(); | 1586 Register right_temp = locs()->temp(1).reg(); |
| 1604 ASSERT(right_temp == RCX); // Count must be in RCX | 1587 ASSERT(right_temp == RCX); // Count must be in RCX |
| 1605 __ movq(right_temp, right); | 1588 __ movq(right_temp, right); |
| 1606 __ SmiUntag(right_temp); | 1589 __ SmiUntag(right_temp); |
| 1607 // Overflow test (preserve temp and right); | 1590 // Overflow test (preserve temp and right); |
| 1608 __ shlq(left, right_temp); | 1591 __ shlq(left, right_temp); |
| 1609 __ sarq(left, right_temp); | 1592 __ sarq(left, right_temp); |
| 1610 __ cmpq(left, temp); | 1593 __ cmpq(left, temp); |
| 1611 __ j(NOT_EQUAL, &call_method, Assembler::kNearJump); // Overflow. | 1594 __ j(NOT_EQUAL, &call_method, Assembler::kNearJump); // Overflow. |
| 1612 // Shift for result now we know there is no overflow. | 1595 // Shift for result now we know there is no overflow. |
| 1613 __ shlq(left, right_temp); | 1596 __ shlq(left, right_temp); |
| 1614 __ jmp(&done); | 1597 __ jmp(&done); |
| 1615 { | 1598 { |
| 1616 __ Bind(&call_method); | 1599 __ Bind(&call_method); |
| 1617 Function& target = Function::ZoneHandle( | 1600 Function& target = Function::ZoneHandle( |
| 1618 comp->ic_data()->GetTargetForReceiverClassId(kSmiCid)); | 1601 ic_data()->GetTargetForReceiverClassId(kSmiCid)); |
| 1619 ASSERT(!target.IsNull()); | 1602 ASSERT(!target.IsNull()); |
| 1620 const intptr_t kArgumentCount = 2; | 1603 const intptr_t kArgumentCount = 2; |
| 1621 __ pushq(temp); | 1604 __ pushq(temp); |
| 1622 __ pushq(right); | 1605 __ pushq(right); |
| 1623 compiler->GenerateStaticCall( | 1606 compiler->GenerateStaticCall( |
| 1624 comp->instance_call()->deopt_id(), | 1607 instance_call()->deopt_id(), |
| 1625 comp->instance_call()->token_pos(), | 1608 instance_call()->token_pos(), |
| 1626 comp->instance_call()->try_index(), | 1609 instance_call()->try_index(), |
| 1627 target, | 1610 target, |
| 1628 kArgumentCount, | 1611 kArgumentCount, |
| 1629 Array::Handle(), // No argument names. | 1612 Array::Handle(), // No argument names. |
| 1630 comp->locs()->stack_bitmap()); | 1613 locs()->stack_bitmap()); |
| 1631 ASSERT(result == RAX); | 1614 ASSERT(result == RAX); |
| 1632 } | 1615 } |
| 1633 __ Bind(&done); | 1616 __ Bind(&done); |
| 1634 break; | 1617 break; |
| 1635 } | 1618 } |
| 1636 case Token::kDIV: { | 1619 case Token::kDIV: { |
| 1637 // Dispatches to 'Double./'. | 1620 // Dispatches to 'Double./'. |
| 1638 // TODO(srdjan): Implement as conversion to double and double division. | 1621 // TODO(srdjan): Implement as conversion to double and double division. |
| 1639 UNREACHABLE(); | 1622 UNREACHABLE(); |
| 1640 break; | 1623 break; |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1651 UNREACHABLE(); | 1634 UNREACHABLE(); |
| 1652 break; | 1635 break; |
| 1653 } | 1636 } |
| 1654 default: | 1637 default: |
| 1655 UNREACHABLE(); | 1638 UNREACHABLE(); |
| 1656 break; | 1639 break; |
| 1657 } | 1640 } |
| 1658 } | 1641 } |
| 1659 | 1642 |
| 1660 | 1643 |
| 1661 static void EmitMintBinaryOp(FlowGraphCompiler* compiler, BinaryOpComp* comp) { | 1644 LocationSummary* BinaryMintOpComp::MakeLocationSummary() const { |
| 1645 ASSERT(op_kind() == Token::kBIT_AND); |
| 1646 const intptr_t kNumInputs = 2; |
| 1647 const intptr_t kNumTemps = 0; |
| 1648 LocationSummary* summary = |
| 1649 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
| 1650 summary->set_in(0, Location::RegisterLocation(RAX)); |
| 1651 summary->set_in(1, Location::RegisterLocation(RCX)); |
| 1652 summary->set_out(Location::RegisterLocation(RAX)); |
| 1653 return summary; |
| 1654 } |
| 1655 |
| 1656 |
| 1657 void BinaryMintOpComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1662 // TODO(regis): For now, we only support Token::kBIT_AND for a Mint or Smi | 1658 // TODO(regis): For now, we only support Token::kBIT_AND for a Mint or Smi |
| 1663 // receiver and a Mint or Smi argument. We fall back to the run time call if | 1659 // receiver and a Mint or Smi argument. We fall back to the run time call if |
| 1664 // both receiver and argument are Mint or if one of them is Mint and the other | 1660 // both receiver and argument are Mint or if one of them is Mint and the other |
| 1665 // is a negative Smi. | 1661 // is a negative Smi. |
| 1666 Register left = comp->locs()->in(0).reg(); | 1662 Register left = locs()->in(0).reg(); |
| 1667 Register right = comp->locs()->in(1).reg(); | 1663 Register right = locs()->in(1).reg(); |
| 1668 Register result = comp->locs()->out().reg(); | 1664 Register result = locs()->out().reg(); |
| 1669 ASSERT(left == result); | 1665 ASSERT(left == result); |
| 1670 ASSERT(comp->op_kind() == Token::kBIT_AND); | 1666 ASSERT(op_kind() == Token::kBIT_AND); |
| 1671 Label* deopt = compiler->AddDeoptStub(comp->instance_call()->deopt_id(), | 1667 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), |
| 1672 comp->instance_call()->try_index(), | 1668 instance_call()->try_index(), |
| 1673 kDeoptMintBinaryOp); | 1669 kDeoptBinaryMintOp); |
| 1674 Label mint_static_call, smi_static_call, non_smi, smi_smi, done; | 1670 Label mint_static_call, smi_static_call, non_smi, smi_smi, done; |
| 1675 __ testq(left, Immediate(kSmiTagMask)); // Is receiver Smi? | 1671 __ testq(left, Immediate(kSmiTagMask)); // Is receiver Smi? |
| 1676 __ j(NOT_ZERO, &non_smi); | 1672 __ j(NOT_ZERO, &non_smi); |
| 1677 __ testq(right, Immediate(kSmiTagMask)); // Is argument Smi? | 1673 __ testq(right, Immediate(kSmiTagMask)); // Is argument Smi? |
| 1678 __ j(ZERO, &smi_smi); | 1674 __ j(ZERO, &smi_smi); |
| 1679 __ CompareClassId(right, kMintCid); // Is argument Mint? | 1675 __ CompareClassId(right, kMintCid); // Is argument Mint? |
| 1680 __ j(NOT_EQUAL, deopt); // Argument neither Smi nor Mint. | 1676 __ j(NOT_EQUAL, deopt); // Argument neither Smi nor Mint. |
| 1681 __ cmpq(left, Immediate(0)); | 1677 __ cmpq(left, Immediate(0)); |
| 1682 __ j(LESS, &smi_static_call); // Negative Smi receiver, Mint argument. | 1678 __ j(LESS, &smi_static_call); // Negative Smi receiver, Mint argument. |
| 1683 | 1679 |
| (...skipping 16 matching lines...) Expand all Loading... |
| 1700 // Load lower receiver Mint word, convert to Smi. It is OK to loose bits. | 1696 // Load lower receiver Mint word, convert to Smi. It is OK to loose bits. |
| 1701 __ movq(result, FieldAddress(left, Mint::value_offset())); | 1697 __ movq(result, FieldAddress(left, Mint::value_offset())); |
| 1702 __ SmiTag(result); | 1698 __ SmiTag(result); |
| 1703 __ Bind(&smi_smi); | 1699 __ Bind(&smi_smi); |
| 1704 __ andq(result, right); | 1700 __ andq(result, right); |
| 1705 __ jmp(&done); | 1701 __ jmp(&done); |
| 1706 | 1702 |
| 1707 __ Bind(&smi_static_call); | 1703 __ Bind(&smi_static_call); |
| 1708 { | 1704 { |
| 1709 Function& target = Function::ZoneHandle( | 1705 Function& target = Function::ZoneHandle( |
| 1710 comp->ic_data()->GetTargetForReceiverClassId(kSmiCid)); | 1706 ic_data()->GetTargetForReceiverClassId(kSmiCid)); |
| 1711 if (target.IsNull()) { | 1707 if (target.IsNull()) { |
| 1712 __ jmp(deopt); | 1708 __ jmp(deopt); |
| 1713 } else { | 1709 } else { |
| 1714 __ pushq(left); | 1710 __ pushq(left); |
| 1715 __ pushq(right); | 1711 __ pushq(right); |
| 1716 compiler->GenerateStaticCall( | 1712 compiler->GenerateStaticCall( |
| 1717 comp->instance_call()->deopt_id(), | 1713 instance_call()->deopt_id(), |
| 1718 comp->instance_call()->token_pos(), | 1714 instance_call()->token_pos(), |
| 1719 comp->instance_call()->try_index(), | 1715 instance_call()->try_index(), |
| 1720 target, | 1716 target, |
| 1721 comp->instance_call()->ArgumentCount(), | 1717 instance_call()->ArgumentCount(), |
| 1722 comp->instance_call()->argument_names(), | 1718 instance_call()->argument_names(), |
| 1723 comp->locs()->stack_bitmap()); | 1719 locs()->stack_bitmap()); |
| 1724 ASSERT(result == RAX); | 1720 ASSERT(result == RAX); |
| 1725 __ jmp(&done); | 1721 __ jmp(&done); |
| 1726 } | 1722 } |
| 1727 } | 1723 } |
| 1728 | 1724 |
| 1729 __ Bind(&mint_static_call); | 1725 __ Bind(&mint_static_call); |
| 1730 { | 1726 { |
| 1731 Function& target = Function::ZoneHandle( | 1727 Function& target = Function::ZoneHandle( |
| 1732 comp->ic_data()->GetTargetForReceiverClassId(kMintCid)); | 1728 ic_data()->GetTargetForReceiverClassId(kMintCid)); |
| 1733 if (target.IsNull()) { | 1729 if (target.IsNull()) { |
| 1734 __ jmp(deopt); | 1730 __ jmp(deopt); |
| 1735 } else { | 1731 } else { |
| 1736 __ pushq(left); | 1732 __ pushq(left); |
| 1737 __ pushq(right); | 1733 __ pushq(right); |
| 1738 compiler->GenerateStaticCall( | 1734 compiler->GenerateStaticCall( |
| 1739 comp->instance_call()->deopt_id(), | 1735 instance_call()->deopt_id(), |
| 1740 comp->instance_call()->token_pos(), | 1736 instance_call()->token_pos(), |
| 1741 comp->instance_call()->try_index(), | 1737 instance_call()->try_index(), |
| 1742 target, | 1738 target, |
| 1743 comp->instance_call()->ArgumentCount(), | 1739 instance_call()->ArgumentCount(), |
| 1744 comp->instance_call()->argument_names(), | 1740 instance_call()->argument_names(), |
| 1745 comp->locs()->stack_bitmap()); | 1741 locs()->stack_bitmap()); |
| 1746 ASSERT(result == RAX); | 1742 ASSERT(result == RAX); |
| 1747 } | 1743 } |
| 1748 } | 1744 } |
| 1749 __ Bind(&done); | 1745 __ Bind(&done); |
| 1750 } | 1746 } |
| 1751 | 1747 |
| 1752 | 1748 |
| 1753 void BinaryOpComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1749 LocationSummary* BinaryDoubleOpComp::MakeLocationSummary() const { |
| 1754 switch (operands_type()) { | |
| 1755 case kSmiOperands: | |
| 1756 EmitSmiBinaryOp(compiler, this); | |
| 1757 break; | |
| 1758 | |
| 1759 case kMintOperands: | |
| 1760 EmitMintBinaryOp(compiler, this); | |
| 1761 break; | |
| 1762 | |
| 1763 default: | |
| 1764 UNREACHABLE(); | |
| 1765 } | |
| 1766 } | |
| 1767 | |
| 1768 | |
| 1769 LocationSummary* DoubleBinaryOpComp::MakeLocationSummary() const { | |
| 1770 return MakeCallSummary(); // Calls into a stub for allocation. | 1750 return MakeCallSummary(); // Calls into a stub for allocation. |
| 1771 } | 1751 } |
| 1772 | 1752 |
| 1773 | 1753 |
| 1774 void DoubleBinaryOpComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1754 void BinaryDoubleOpComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1775 Register left = RBX; | 1755 Register left = RBX; |
| 1776 Register right = RCX; | 1756 Register right = RCX; |
| 1777 Register temp = RDX; | 1757 Register temp = RDX; |
| 1778 Register result = locs()->out().reg(); | 1758 Register result = locs()->out().reg(); |
| 1779 | 1759 |
| 1780 const Class& double_class = compiler->double_class(); | 1760 const Class& double_class = compiler->double_class(); |
| 1781 const Code& stub = | 1761 const Code& stub = |
| 1782 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); | 1762 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); |
| 1783 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); | 1763 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); |
| 1784 compiler->GenerateCall(instance_call()->token_pos(), | 1764 compiler->GenerateCall(instance_call()->token_pos(), |
| 1785 instance_call()->try_index(), | 1765 instance_call()->try_index(), |
| 1786 &label, | 1766 &label, |
| 1787 PcDescriptors::kOther, | 1767 PcDescriptors::kOther, |
| 1788 locs()->stack_bitmap()); | 1768 locs()->stack_bitmap()); |
| 1789 // Newly allocated object is now in the result register (RAX). | 1769 // Newly allocated object is now in the result register (RAX). |
| 1790 ASSERT(result == RAX); | 1770 ASSERT(result == RAX); |
| 1791 __ movq(right, Address(RSP, 0)); | 1771 __ movq(right, Address(RSP, 0)); |
| 1792 __ movq(left, Address(RSP, kWordSize)); | 1772 __ movq(left, Address(RSP, kWordSize)); |
| 1793 | 1773 |
| 1794 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), | 1774 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), |
| 1795 instance_call()->try_index(), | 1775 instance_call()->try_index(), |
| 1796 kDeoptDoubleBinaryOp); | 1776 kDeoptBinaryDoubleOp); |
| 1797 | 1777 |
| 1798 // Binary operation of two Smi's produces a Smi not a double. | 1778 // Binary operation of two Smi's produces a Smi not a double. |
| 1799 __ movq(temp, left); | 1779 __ movq(temp, left); |
| 1800 __ orq(temp, right); | 1780 __ orq(temp, right); |
| 1801 __ testq(temp, Immediate(kSmiTagMask)); | 1781 __ testq(temp, Immediate(kSmiTagMask)); |
| 1802 __ j(ZERO, deopt); | 1782 __ j(ZERO, deopt); |
| 1803 | 1783 |
| 1804 compiler->LoadDoubleOrSmiToXmm(XMM0, left, temp, deopt); | 1784 compiler->LoadDoubleOrSmiToXmm(XMM0, left, temp, deopt); |
| 1805 compiler->LoadDoubleOrSmiToXmm(XMM1, right, temp, deopt); | 1785 compiler->LoadDoubleOrSmiToXmm(XMM1, right, temp, deopt); |
| 1806 | 1786 |
| (...skipping 416 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2223 } | 2203 } |
| 2224 } | 2204 } |
| 2225 __ Bind(&is_ok); | 2205 __ Bind(&is_ok); |
| 2226 } | 2206 } |
| 2227 | 2207 |
| 2228 } // namespace dart | 2208 } // namespace dart |
| 2229 | 2209 |
| 2230 #undef __ | 2210 #undef __ |
| 2231 | 2211 |
| 2232 #endif // defined TARGET_ARCH_X64 | 2212 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |