Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(438)

Side by Side Diff: runtime/vm/intermediate_language_x64.cc

Issue 10879005: Split BinaryOp into BinarySmiOp and BinaryMintOp. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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
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
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
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
OLDNEW
« runtime/vm/intermediate_language.cc ('K') | « runtime/vm/intermediate_language_ia32.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698