| 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_IA32. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_IA32. |
| 6 #if defined(TARGET_ARCH_IA32) | 6 #if defined(TARGET_ARCH_IA32) |
| 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 1393 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1404 CheckStackOverflowSlowPath* slow_path = new CheckStackOverflowSlowPath(this); | 1404 CheckStackOverflowSlowPath* slow_path = new CheckStackOverflowSlowPath(this); |
| 1405 compiler->AddSlowPathCode(slow_path); | 1405 compiler->AddSlowPathCode(slow_path); |
| 1406 | 1406 |
| 1407 __ cmpl(ESP, | 1407 __ cmpl(ESP, |
| 1408 Address::Absolute(Isolate::Current()->stack_limit_address())); | 1408 Address::Absolute(Isolate::Current()->stack_limit_address())); |
| 1409 __ j(BELOW_EQUAL, slow_path->entry_label()); | 1409 __ j(BELOW_EQUAL, slow_path->entry_label()); |
| 1410 __ Bind(slow_path->exit_label()); | 1410 __ Bind(slow_path->exit_label()); |
| 1411 } | 1411 } |
| 1412 | 1412 |
| 1413 | 1413 |
| 1414 LocationSummary* BinaryOpComp::MakeLocationSummary() const { | 1414 LocationSummary* BinarySmiOpComp::MakeLocationSummary() const { |
| 1415 const intptr_t kNumInputs = 2; | 1415 const intptr_t kNumInputs = 2; |
| 1416 | |
| 1417 // Double operation are handled in DoubleBinaryOpComp. | |
| 1418 ASSERT(operands_type() != kDoubleOperands); | |
| 1419 | |
| 1420 if (operands_type() == kMintOperands) { | |
| 1421 ASSERT(op_kind() == Token::kBIT_AND); | |
| 1422 const intptr_t kNumTemps = 1; | |
| 1423 LocationSummary* summary = | |
| 1424 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | |
| 1425 summary->set_in(0, Location::RegisterLocation(EAX)); | |
| 1426 summary->set_in(1, Location::RegisterLocation(ECX)); | |
| 1427 summary->set_temp(0, Location::RegisterLocation(EDX)); | |
| 1428 summary->set_out(Location::RegisterLocation(EAX)); | |
| 1429 return summary; | |
| 1430 } | |
| 1431 | |
| 1432 ASSERT(operands_type() == kSmiOperands); | |
| 1433 | |
| 1434 if (op_kind() == Token::kTRUNCDIV) { | 1416 if (op_kind() == Token::kTRUNCDIV) { |
| 1435 const intptr_t kNumTemps = 3; | 1417 const intptr_t kNumTemps = 3; |
| 1436 LocationSummary* summary = | 1418 LocationSummary* summary = |
| 1437 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1419 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 1438 summary->set_in(0, Location::RegisterLocation(EAX)); | 1420 summary->set_in(0, Location::RegisterLocation(EAX)); |
| 1439 summary->set_in(1, Location::RegisterLocation(ECX)); | 1421 summary->set_in(1, Location::RegisterLocation(ECX)); |
| 1440 summary->set_out(Location::SameAsFirstInput()); | 1422 summary->set_out(Location::SameAsFirstInput()); |
| 1441 summary->set_temp(0, Location::RegisterLocation(EBX)); | 1423 summary->set_temp(0, Location::RegisterLocation(EBX)); |
| 1442 // Will be used for for sign extension. | 1424 // Will be used for for sign extension. |
| 1443 summary->set_temp(1, Location::RegisterLocation(EDX)); | 1425 summary->set_temp(1, Location::RegisterLocation(EDX)); |
| (...skipping 25 matching lines...) Expand all Loading... |
| 1469 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1451 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 1470 summary->set_in(0, Location::RequiresRegister()); | 1452 summary->set_in(0, Location::RequiresRegister()); |
| 1471 summary->set_in(1, Location::RequiresRegister()); | 1453 summary->set_in(1, Location::RequiresRegister()); |
| 1472 summary->set_out(Location::SameAsFirstInput()); | 1454 summary->set_out(Location::SameAsFirstInput()); |
| 1473 summary->set_temp(0, Location::RequiresRegister()); | 1455 summary->set_temp(0, Location::RequiresRegister()); |
| 1474 return summary; | 1456 return summary; |
| 1475 } | 1457 } |
| 1476 } | 1458 } |
| 1477 | 1459 |
| 1478 | 1460 |
| 1479 static void EmitSmiBinaryOp(FlowGraphCompiler* compiler, BinaryOpComp* comp) { | 1461 void BinarySmiOpComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1480 Register left = comp->locs()->in(0).reg(); | 1462 Register left = locs()->in(0).reg(); |
| 1481 Register right = comp->locs()->in(1).reg(); | 1463 Register right = locs()->in(1).reg(); |
| 1482 Register result = comp->locs()->out().reg(); | 1464 Register result = locs()->out().reg(); |
| 1483 Register temp = comp->locs()->temp(0).reg(); | 1465 Register temp = locs()->temp(0).reg(); |
| 1484 ASSERT(left == result); | 1466 ASSERT(left == result); |
| 1485 const bool left_is_smi = comp->left()->ResultCid() == kSmiCid; | 1467 const bool left_is_smi = this->left()->ResultCid() == kSmiCid; |
| 1486 const bool right_is_smi = comp->right()->ResultCid() == kSmiCid; | 1468 const bool right_is_smi = this->right()->ResultCid() == kSmiCid; |
| 1487 bool can_deopt; | 1469 bool can_deopt; |
| 1488 switch (comp->op_kind()) { | 1470 switch (op_kind()) { |
| 1489 case Token::kBIT_AND: | 1471 case Token::kBIT_AND: |
| 1490 case Token::kBIT_OR: | 1472 case Token::kBIT_OR: |
| 1491 case Token::kBIT_XOR: | 1473 case Token::kBIT_XOR: |
| 1492 can_deopt = !(right_is_smi && left_is_smi); | 1474 can_deopt = !(right_is_smi && left_is_smi); |
| 1493 break; | 1475 break; |
| 1494 default: | 1476 default: |
| 1495 can_deopt = true; | 1477 can_deopt = true; |
| 1496 } | 1478 } |
| 1497 Label* deopt = NULL; | 1479 Label* deopt = NULL; |
| 1498 if (can_deopt) { | 1480 if (can_deopt) { |
| 1499 deopt = compiler->AddDeoptStub(comp->instance_call()->deopt_id(), | 1481 deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), |
| 1500 comp->instance_call()->try_index(), | 1482 instance_call()->try_index(), |
| 1501 kDeoptSmiBinaryOp); | 1483 kDeoptBinarySmiOp); |
| 1502 } | 1484 } |
| 1503 if (!left_is_smi || !right_is_smi) { | 1485 if (!left_is_smi || !right_is_smi) { |
| 1504 __ movl(temp, left); | 1486 __ movl(temp, left); |
| 1505 __ orl(temp, right); | 1487 __ orl(temp, right); |
| 1506 __ testl(temp, Immediate(kSmiTagMask)); | 1488 __ testl(temp, Immediate(kSmiTagMask)); |
| 1507 __ j(NOT_ZERO, deopt); | 1489 __ j(NOT_ZERO, deopt); |
| 1508 } | 1490 } |
| 1509 switch (comp->op_kind()) { | 1491 switch (op_kind()) { |
| 1510 case Token::kADD: { | 1492 case Token::kADD: { |
| 1511 __ addl(left, right); | 1493 __ addl(left, right); |
| 1512 __ j(OVERFLOW, deopt); | 1494 __ j(OVERFLOW, deopt); |
| 1513 break; | 1495 break; |
| 1514 } | 1496 } |
| 1515 case Token::kSUB: { | 1497 case Token::kSUB: { |
| 1516 __ subl(left, right); | 1498 __ subl(left, right); |
| 1517 __ j(OVERFLOW, deopt); | 1499 __ j(OVERFLOW, deopt); |
| 1518 break; | 1500 break; |
| 1519 } | 1501 } |
| (...skipping 19 matching lines...) Expand all Loading... |
| 1539 break; | 1521 break; |
| 1540 } | 1522 } |
| 1541 case Token::kTRUNCDIV: { | 1523 case Token::kTRUNCDIV: { |
| 1542 // Handle divide by zero in runtime. | 1524 // Handle divide by zero in runtime. |
| 1543 // Deoptimization requires that temp and right are preserved. | 1525 // Deoptimization requires that temp and right are preserved. |
| 1544 __ testl(right, right); | 1526 __ testl(right, right); |
| 1545 __ j(ZERO, deopt); | 1527 __ j(ZERO, deopt); |
| 1546 ASSERT(left == EAX); | 1528 ASSERT(left == EAX); |
| 1547 ASSERT((right != EDX) && (right != EAX)); | 1529 ASSERT((right != EDX) && (right != EAX)); |
| 1548 ASSERT((temp != EDX) && (temp != EAX)); | 1530 ASSERT((temp != EDX) && (temp != EAX)); |
| 1549 ASSERT(comp->locs()->temp(1).reg() == EDX); | 1531 ASSERT(locs()->temp(1).reg() == EDX); |
| 1550 ASSERT(result == EAX); | 1532 ASSERT(result == EAX); |
| 1551 Register right_temp = comp->locs()->temp(2).reg(); | 1533 Register right_temp = locs()->temp(2).reg(); |
| 1552 __ movl(right_temp, right); | 1534 __ movl(right_temp, right); |
| 1553 __ SmiUntag(left); | 1535 __ SmiUntag(left); |
| 1554 __ SmiUntag(right_temp); | 1536 __ SmiUntag(right_temp); |
| 1555 __ cdq(); // Sign extend EAX -> EDX:EAX. | 1537 __ cdq(); // Sign extend EAX -> EDX:EAX. |
| 1556 __ idivl(right_temp); // EAX: quotient, EDX: remainder. | 1538 __ idivl(right_temp); // EAX: quotient, EDX: remainder. |
| 1557 // Check the corner case of dividing the 'MIN_SMI' with -1, in which | 1539 // Check the corner case of dividing the 'MIN_SMI' with -1, in which |
| 1558 // case we cannot tag the result. | 1540 // case we cannot tag the result. |
| 1559 __ cmpl(result, Immediate(0x40000000)); | 1541 __ cmpl(result, Immediate(0x40000000)); |
| 1560 __ j(EQUAL, deopt); | 1542 __ j(EQUAL, deopt); |
| 1561 __ SmiTag(result); | 1543 __ SmiTag(result); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 1578 __ SmiTag(left); | 1560 __ SmiTag(left); |
| 1579 break; | 1561 break; |
| 1580 } | 1562 } |
| 1581 case Token::kSHL: { | 1563 case Token::kSHL: { |
| 1582 Label call_method, done; | 1564 Label call_method, done; |
| 1583 // Check if count too large for handling it inlined. | 1565 // Check if count too large for handling it inlined. |
| 1584 __ movl(temp, left); | 1566 __ movl(temp, left); |
| 1585 __ cmpl(right, | 1567 __ cmpl(right, |
| 1586 Immediate(reinterpret_cast<int64_t>(Smi::New(Smi::kBits)))); | 1568 Immediate(reinterpret_cast<int64_t>(Smi::New(Smi::kBits)))); |
| 1587 __ j(ABOVE_EQUAL, &call_method, Assembler::kNearJump); | 1569 __ j(ABOVE_EQUAL, &call_method, Assembler::kNearJump); |
| 1588 Register right_temp = comp->locs()->temp(1).reg(); | 1570 Register right_temp = locs()->temp(1).reg(); |
| 1589 ASSERT(right_temp == ECX); // Count must be in ECX | 1571 ASSERT(right_temp == ECX); // Count must be in ECX |
| 1590 __ movl(right_temp, right); | 1572 __ movl(right_temp, right); |
| 1591 __ SmiUntag(right_temp); | 1573 __ SmiUntag(right_temp); |
| 1592 // Overflow test (preserve temp and right); | 1574 // Overflow test (preserve temp and right); |
| 1593 __ shll(left, right_temp); | 1575 __ shll(left, right_temp); |
| 1594 __ sarl(left, right_temp); | 1576 __ sarl(left, right_temp); |
| 1595 __ cmpl(left, temp); | 1577 __ cmpl(left, temp); |
| 1596 __ j(NOT_EQUAL, &call_method, Assembler::kNearJump); // Overflow. | 1578 __ j(NOT_EQUAL, &call_method, Assembler::kNearJump); // Overflow. |
| 1597 // Shift for result now we know there is no overflow. | 1579 // Shift for result now we know there is no overflow. |
| 1598 __ shll(left, right_temp); | 1580 __ shll(left, right_temp); |
| 1599 __ jmp(&done); | 1581 __ jmp(&done); |
| 1600 { | 1582 { |
| 1601 __ Bind(&call_method); | 1583 __ Bind(&call_method); |
| 1602 Function& target = Function::ZoneHandle( | 1584 Function& target = Function::ZoneHandle( |
| 1603 comp->ic_data()->GetTargetForReceiverClassId(kSmiCid)); | 1585 ic_data()->GetTargetForReceiverClassId(kSmiCid)); |
| 1604 ASSERT(!target.IsNull()); | 1586 ASSERT(!target.IsNull()); |
| 1605 const intptr_t kArgumentCount = 2; | 1587 const intptr_t kArgumentCount = 2; |
| 1606 __ pushl(temp); | 1588 __ pushl(temp); |
| 1607 __ pushl(right); | 1589 __ pushl(right); |
| 1608 compiler->GenerateStaticCall( | 1590 compiler->GenerateStaticCall( |
| 1609 comp->instance_call()->deopt_id(), | 1591 instance_call()->deopt_id(), |
| 1610 comp->instance_call()->token_pos(), | 1592 instance_call()->token_pos(), |
| 1611 comp->instance_call()->try_index(), | 1593 instance_call()->try_index(), |
| 1612 target, | 1594 target, |
| 1613 kArgumentCount, | 1595 kArgumentCount, |
| 1614 Array::Handle(), // No argument names. | 1596 Array::Handle(), // No argument names. |
| 1615 comp->locs()->stack_bitmap()); | 1597 locs()->stack_bitmap()); |
| 1616 ASSERT(result == EAX); | 1598 ASSERT(result == EAX); |
| 1617 } | 1599 } |
| 1618 __ Bind(&done); | 1600 __ Bind(&done); |
| 1619 break; | 1601 break; |
| 1620 } | 1602 } |
| 1621 case Token::kDIV: { | 1603 case Token::kDIV: { |
| 1622 // Dispatches to 'Double./'. | 1604 // Dispatches to 'Double./'. |
| 1623 // TODO(srdjan): Implement as conversion to double and double division. | 1605 // TODO(srdjan): Implement as conversion to double and double division. |
| 1624 UNREACHABLE(); | 1606 UNREACHABLE(); |
| 1625 break; | 1607 break; |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1636 UNREACHABLE(); | 1618 UNREACHABLE(); |
| 1637 break; | 1619 break; |
| 1638 } | 1620 } |
| 1639 default: | 1621 default: |
| 1640 UNREACHABLE(); | 1622 UNREACHABLE(); |
| 1641 break; | 1623 break; |
| 1642 } | 1624 } |
| 1643 } | 1625 } |
| 1644 | 1626 |
| 1645 | 1627 |
| 1646 static void EmitMintBinaryOp(FlowGraphCompiler* compiler, BinaryOpComp* comp) { | 1628 LocationSummary* BinaryMintOpComp::MakeLocationSummary() const { |
| 1629 const intptr_t kNumInputs = 2; |
| 1630 ASSERT(op_kind() == Token::kBIT_AND); |
| 1631 const intptr_t kNumTemps = 1; |
| 1632 LocationSummary* summary = |
| 1633 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
| 1634 summary->set_in(0, Location::RegisterLocation(EAX)); |
| 1635 summary->set_in(1, Location::RegisterLocation(ECX)); |
| 1636 summary->set_temp(0, Location::RegisterLocation(EDX)); |
| 1637 summary->set_out(Location::RegisterLocation(EAX)); |
| 1638 return summary; |
| 1639 } |
| 1640 |
| 1641 |
| 1642 void BinaryMintOpComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1647 // TODO(regis): For now, we only support Token::kBIT_AND for a Mint or Smi | 1643 // TODO(regis): For now, we only support Token::kBIT_AND for a Mint or Smi |
| 1648 // receiver and a Mint or Smi argument. We fall back to the run time call if | 1644 // receiver and a Mint or Smi argument. We fall back to the run time call if |
| 1649 // both receiver and argument are Mint or if one of them is Mint and the other | 1645 // both receiver and argument are Mint or if one of them is Mint and the other |
| 1650 // is a negative Smi. | 1646 // is a negative Smi. |
| 1651 Register left = comp->locs()->in(0).reg(); | 1647 Register left = locs()->in(0).reg(); |
| 1652 Register right = comp->locs()->in(1).reg(); | 1648 Register right = locs()->in(1).reg(); |
| 1653 Register result = comp->locs()->out().reg(); | 1649 Register result = locs()->out().reg(); |
| 1654 Register temp = comp->locs()->temp(0).reg(); | 1650 Register temp = locs()->temp(0).reg(); |
| 1655 ASSERT(left == result); | 1651 ASSERT(left == result); |
| 1656 ASSERT(comp->op_kind() == Token::kBIT_AND); | 1652 ASSERT(op_kind() == Token::kBIT_AND); |
| 1657 Label* deopt = compiler->AddDeoptStub(comp->instance_call()->deopt_id(), | 1653 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), |
| 1658 comp->instance_call()->try_index(), | 1654 instance_call()->try_index(), |
| 1659 kDeoptMintBinaryOp); | 1655 kDeoptBinaryMintOp); |
| 1660 Label mint_static_call, smi_static_call, non_smi, smi_smi, done; | 1656 Label mint_static_call, smi_static_call, non_smi, smi_smi, done; |
| 1661 __ testl(left, Immediate(kSmiTagMask)); // Is receiver Smi? | 1657 __ testl(left, Immediate(kSmiTagMask)); // Is receiver Smi? |
| 1662 __ j(NOT_ZERO, &non_smi); | 1658 __ j(NOT_ZERO, &non_smi); |
| 1663 __ testl(right, Immediate(kSmiTagMask)); // Is argument Smi? | 1659 __ testl(right, Immediate(kSmiTagMask)); // Is argument Smi? |
| 1664 __ j(ZERO, &smi_smi); | 1660 __ j(ZERO, &smi_smi); |
| 1665 __ CompareClassId(right, kMintCid, temp); // Is argument Mint? | 1661 __ CompareClassId(right, kMintCid, temp); // Is argument Mint? |
| 1666 __ j(NOT_EQUAL, deopt); // Argument neither Smi nor Mint. | 1662 __ j(NOT_EQUAL, deopt); // Argument neither Smi nor Mint. |
| 1667 __ cmpl(left, Immediate(0)); | 1663 __ cmpl(left, Immediate(0)); |
| 1668 __ j(LESS, &smi_static_call); // Negative Smi receiver, Mint argument. | 1664 __ j(LESS, &smi_static_call); // Negative Smi receiver, Mint argument. |
| 1669 | 1665 |
| (...skipping 16 matching lines...) Expand all Loading... |
| 1686 // Load lower receiver Mint word, convert to Smi. It is OK to loose bits. | 1682 // Load lower receiver Mint word, convert to Smi. It is OK to loose bits. |
| 1687 __ movl(result, FieldAddress(left, Mint::value_offset())); | 1683 __ movl(result, FieldAddress(left, Mint::value_offset())); |
| 1688 __ SmiTag(result); | 1684 __ SmiTag(result); |
| 1689 __ Bind(&smi_smi); | 1685 __ Bind(&smi_smi); |
| 1690 __ andl(result, right); | 1686 __ andl(result, right); |
| 1691 __ jmp(&done); | 1687 __ jmp(&done); |
| 1692 | 1688 |
| 1693 __ Bind(&smi_static_call); | 1689 __ Bind(&smi_static_call); |
| 1694 { | 1690 { |
| 1695 Function& target = Function::ZoneHandle( | 1691 Function& target = Function::ZoneHandle( |
| 1696 comp->ic_data()->GetTargetForReceiverClassId(kSmiCid)); | 1692 ic_data()->GetTargetForReceiverClassId(kSmiCid)); |
| 1697 if (target.IsNull()) { | 1693 if (target.IsNull()) { |
| 1698 __ jmp(deopt); | 1694 __ jmp(deopt); |
| 1699 } else { | 1695 } else { |
| 1700 __ pushl(left); | 1696 __ pushl(left); |
| 1701 __ pushl(right); | 1697 __ pushl(right); |
| 1702 compiler->GenerateStaticCall( | 1698 compiler->GenerateStaticCall( |
| 1703 comp->instance_call()->deopt_id(), | 1699 instance_call()->deopt_id(), |
| 1704 comp->instance_call()->token_pos(), | 1700 instance_call()->token_pos(), |
| 1705 comp->instance_call()->try_index(), | 1701 instance_call()->try_index(), |
| 1706 target, | 1702 target, |
| 1707 comp->instance_call()->ArgumentCount(), | 1703 instance_call()->ArgumentCount(), |
| 1708 comp->instance_call()->argument_names(), | 1704 instance_call()->argument_names(), |
| 1709 comp->locs()->stack_bitmap()); | 1705 locs()->stack_bitmap()); |
| 1710 ASSERT(result == EAX); | 1706 ASSERT(result == EAX); |
| 1711 __ jmp(&done); | 1707 __ jmp(&done); |
| 1712 } | 1708 } |
| 1713 } | 1709 } |
| 1714 | 1710 |
| 1715 __ Bind(&mint_static_call); | 1711 __ Bind(&mint_static_call); |
| 1716 { | 1712 { |
| 1717 Function& target = Function::ZoneHandle( | 1713 Function& target = Function::ZoneHandle( |
| 1718 comp->ic_data()->GetTargetForReceiverClassId(kMintCid)); | 1714 ic_data()->GetTargetForReceiverClassId(kMintCid)); |
| 1719 if (target.IsNull()) { | 1715 if (target.IsNull()) { |
| 1720 __ jmp(deopt); | 1716 __ jmp(deopt); |
| 1721 } else { | 1717 } else { |
| 1722 __ pushl(left); | 1718 __ pushl(left); |
| 1723 __ pushl(right); | 1719 __ pushl(right); |
| 1724 compiler->GenerateStaticCall( | 1720 compiler->GenerateStaticCall( |
| 1725 comp->instance_call()->deopt_id(), | 1721 instance_call()->deopt_id(), |
| 1726 comp->instance_call()->token_pos(), | 1722 instance_call()->token_pos(), |
| 1727 comp->instance_call()->try_index(), | 1723 instance_call()->try_index(), |
| 1728 target, | 1724 target, |
| 1729 comp->instance_call()->ArgumentCount(), | 1725 instance_call()->ArgumentCount(), |
| 1730 comp->instance_call()->argument_names(), | 1726 instance_call()->argument_names(), |
| 1731 comp->locs()->stack_bitmap()); | 1727 locs()->stack_bitmap()); |
| 1732 ASSERT(result == EAX); | 1728 ASSERT(result == EAX); |
| 1733 } | 1729 } |
| 1734 } | 1730 } |
| 1735 __ Bind(&done); | 1731 __ Bind(&done); |
| 1736 } | 1732 } |
| 1737 | 1733 |
| 1738 | 1734 |
| 1739 void BinaryOpComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1735 LocationSummary* BinaryDoubleOpComp::MakeLocationSummary() const { |
| 1740 switch (operands_type()) { | |
| 1741 case kSmiOperands: | |
| 1742 EmitSmiBinaryOp(compiler, this); | |
| 1743 break; | |
| 1744 | |
| 1745 case kMintOperands: | |
| 1746 EmitMintBinaryOp(compiler, this); | |
| 1747 break; | |
| 1748 | |
| 1749 default: | |
| 1750 UNREACHABLE(); | |
| 1751 } | |
| 1752 } | |
| 1753 | |
| 1754 | |
| 1755 LocationSummary* DoubleBinaryOpComp::MakeLocationSummary() const { | |
| 1756 return MakeCallSummary(); // Calls into a stub for allocation. | 1736 return MakeCallSummary(); // Calls into a stub for allocation. |
| 1757 } | 1737 } |
| 1758 | 1738 |
| 1759 | 1739 |
| 1760 void DoubleBinaryOpComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1740 void BinaryDoubleOpComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1761 Register left = EBX; | 1741 Register left = EBX; |
| 1762 Register right = ECX; | 1742 Register right = ECX; |
| 1763 Register temp = EDX; | 1743 Register temp = EDX; |
| 1764 Register result = locs()->out().reg(); | 1744 Register result = locs()->out().reg(); |
| 1765 | 1745 |
| 1766 const Class& double_class = compiler->double_class(); | 1746 const Class& double_class = compiler->double_class(); |
| 1767 const Code& stub = | 1747 const Code& stub = |
| 1768 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); | 1748 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); |
| 1769 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); | 1749 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); |
| 1770 compiler->GenerateCall(instance_call()->token_pos(), | 1750 compiler->GenerateCall(instance_call()->token_pos(), |
| 1771 instance_call()->try_index(), | 1751 instance_call()->try_index(), |
| 1772 &label, | 1752 &label, |
| 1773 PcDescriptors::kOther, | 1753 PcDescriptors::kOther, |
| 1774 locs()->stack_bitmap()); | 1754 locs()->stack_bitmap()); |
| 1775 // Newly allocated object is now in the result register (RAX). | 1755 // Newly allocated object is now in the result register (RAX). |
| 1776 ASSERT(result == EAX); | 1756 ASSERT(result == EAX); |
| 1777 __ movl(right, Address(ESP, 0)); | 1757 __ movl(right, Address(ESP, 0)); |
| 1778 __ movl(left, Address(ESP, kWordSize)); | 1758 __ movl(left, Address(ESP, kWordSize)); |
| 1779 | 1759 |
| 1780 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), | 1760 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), |
| 1781 instance_call()->try_index(), | 1761 instance_call()->try_index(), |
| 1782 kDeoptDoubleBinaryOp); | 1762 kDeoptBinaryDoubleOp); |
| 1783 | 1763 |
| 1784 // Binary operation of two Smi's produces a Smi not a double. | 1764 // Binary operation of two Smi's produces a Smi not a double. |
| 1785 __ movl(temp, left); | 1765 __ movl(temp, left); |
| 1786 __ orl(temp, right); | 1766 __ orl(temp, right); |
| 1787 __ testl(temp, Immediate(kSmiTagMask)); | 1767 __ testl(temp, Immediate(kSmiTagMask)); |
| 1788 __ j(ZERO, deopt); | 1768 __ j(ZERO, deopt); |
| 1789 | 1769 |
| 1790 compiler->LoadDoubleOrSmiToXmm(XMM0, left, temp, deopt); | 1770 compiler->LoadDoubleOrSmiToXmm(XMM0, left, temp, deopt); |
| 1791 compiler->LoadDoubleOrSmiToXmm(XMM1, right, temp, deopt); | 1771 compiler->LoadDoubleOrSmiToXmm(XMM1, right, temp, deopt); |
| 1792 | 1772 |
| (...skipping 417 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2210 } | 2190 } |
| 2211 } | 2191 } |
| 2212 __ Bind(&is_ok); | 2192 __ Bind(&is_ok); |
| 2213 } | 2193 } |
| 2214 | 2194 |
| 2215 } // namespace dart | 2195 } // namespace dart |
| 2216 | 2196 |
| 2217 #undef __ | 2197 #undef __ |
| 2218 | 2198 |
| 2219 #endif // defined TARGET_ARCH_X64 | 2199 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |