| 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 365 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 376 } | 376 } |
| 377 __ jmp(&done); | 377 __ jmp(&done); |
| 378 __ Bind(&next_test); | 378 __ Bind(&next_test); |
| 379 } | 379 } |
| 380 // Fall through leads to deoptimization | 380 // Fall through leads to deoptimization |
| 381 __ jmp(deopt); | 381 __ jmp(deopt); |
| 382 __ Bind(&done); | 382 __ Bind(&done); |
| 383 } | 383 } |
| 384 | 384 |
| 385 | 385 |
| 386 | |
| 387 // First test if receiver is NULL, in which case === is applied. | 386 // First test if receiver is NULL, in which case === is applied. |
| 388 // If type feedback was provided (lists of <class-id, target>), do a | 387 // If type feedback was provided (lists of <class-id, target>), do a |
| 389 // type by type check (either === or static call to the operator. | 388 // type by type check (either === or static call to the operator. |
| 390 static void EmitGenericEqualityCompare(FlowGraphCompiler* compiler, | 389 static void EmitGenericEqualityCompare(FlowGraphCompiler* compiler, |
| 391 EqualityCompareComp* comp) { | 390 EqualityCompareComp* comp) { |
| 392 const Immediate raw_null = | 391 const Immediate raw_null = |
| 393 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 392 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 394 Register left = comp->locs()->in(0).reg(); | 393 Register left = comp->locs()->in(0).reg(); |
| 395 Register right = comp->locs()->in(1).reg(); | 394 Register right = comp->locs()->in(1).reg(); |
| 396 Label done, non_null_compare; | 395 Label done, non_null_compare; |
| (...skipping 994 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1391 | 1390 |
| 1392 LocationSummary* BinaryOpComp::MakeLocationSummary() const { | 1391 LocationSummary* BinaryOpComp::MakeLocationSummary() const { |
| 1393 const intptr_t kNumInputs = 2; | 1392 const intptr_t kNumInputs = 2; |
| 1394 | 1393 |
| 1395 if (operands_type() == kDoubleOperands) { | 1394 if (operands_type() == kDoubleOperands) { |
| 1396 return MakeCallSummary(); // Calls into a stub for allocation. | 1395 return MakeCallSummary(); // Calls into a stub for allocation. |
| 1397 } | 1396 } |
| 1398 | 1397 |
| 1399 if (operands_type() == kMintOperands) { | 1398 if (operands_type() == kMintOperands) { |
| 1400 ASSERT(op_kind() == Token::kBIT_AND); | 1399 ASSERT(op_kind() == Token::kBIT_AND); |
| 1401 const intptr_t kNumTemps = 1; | 1400 const intptr_t kNumTemps = 0; |
| 1402 LocationSummary* summary = new LocationSummary(kNumInputs, kNumTemps); | 1401 LocationSummary* summary = |
| 1403 summary->set_in(0, Location::RequiresRegister()); | 1402 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
| 1403 summary->set_in(0, Location::RegisterLocation(RAX)); |
| 1404 summary->set_in(1, Location::RequiresRegister()); | 1404 summary->set_in(1, Location::RequiresRegister()); |
| 1405 summary->set_out(Location::SameAsFirstInput()); | 1405 summary->set_out(Location::SameAsFirstInput()); |
| 1406 summary->set_temp(0, Location::RequiresRegister()); | |
| 1407 return summary; | 1406 return summary; |
| 1408 } | 1407 } |
| 1409 | 1408 |
| 1410 ASSERT(operands_type() == kSmiOperands); | 1409 ASSERT(operands_type() == kSmiOperands); |
| 1411 | 1410 |
| 1412 if (op_kind() == Token::kTRUNCDIV) { | 1411 if (op_kind() == Token::kTRUNCDIV) { |
| 1413 const intptr_t kNumTemps = 3; | 1412 const intptr_t kNumTemps = 3; |
| 1414 LocationSummary* summary = new LocationSummary(kNumInputs, kNumTemps); | 1413 LocationSummary* summary = new LocationSummary(kNumInputs, kNumTemps); |
| 1415 summary->set_in(0, Location::RegisterLocation(RAX)); | 1414 summary->set_in(0, Location::RegisterLocation(RAX)); |
| 1416 summary->set_in(1, Location::RegisterLocation(RCX)); | 1415 summary->set_in(1, Location::RegisterLocation(RCX)); |
| (...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1576 } | 1575 } |
| 1577 default: | 1576 default: |
| 1578 UNREACHABLE(); | 1577 UNREACHABLE(); |
| 1579 break; | 1578 break; |
| 1580 } | 1579 } |
| 1581 } | 1580 } |
| 1582 | 1581 |
| 1583 | 1582 |
| 1584 static void EmitMintBinaryOp(FlowGraphCompiler* compiler, BinaryOpComp* comp) { | 1583 static void EmitMintBinaryOp(FlowGraphCompiler* compiler, BinaryOpComp* comp) { |
| 1585 // TODO(regis): For now, we only support Token::kBIT_AND for a Mint or Smi | 1584 // TODO(regis): For now, we only support Token::kBIT_AND for a Mint or Smi |
| 1586 // receiver and a Smi argument. | 1585 // receiver and a Mint or Smi argument. We fall back to the run time call if |
| 1586 // both receiver and argument are Mint or if one of them is Mint and the other |
| 1587 // is a negative Smi. |
| 1587 Register left = comp->locs()->in(0).reg(); | 1588 Register left = comp->locs()->in(0).reg(); |
| 1588 Register right = comp->locs()->in(1).reg(); | 1589 Register right = comp->locs()->in(1).reg(); |
| 1589 Register result = comp->locs()->out().reg(); | 1590 Register result = comp->locs()->out().reg(); |
| 1590 Register temp = comp->locs()->temp(0).reg(); | |
| 1591 ASSERT(left == result); | 1591 ASSERT(left == result); |
| 1592 ASSERT(comp->op_kind() == Token::kBIT_AND); |
| 1592 Label* deopt = compiler->AddDeoptStub(comp->instance_call()->cid(), | 1593 Label* deopt = compiler->AddDeoptStub(comp->instance_call()->cid(), |
| 1593 comp->instance_call()->token_index(), | 1594 comp->instance_call()->token_index(), |
| 1594 comp->instance_call()->try_index(), | 1595 comp->instance_call()->try_index(), |
| 1595 kDeoptMintBinaryOp, | 1596 kDeoptMintBinaryOp, |
| 1596 temp, | 1597 left, |
| 1597 right); | 1598 right); |
| 1598 __ testq(right, Immediate(kSmiTagMask)); // Argument must be Smi. | 1599 Label mint_static_call, smi_static_call, non_smi, smi_smi, done; |
| 1599 __ j(NOT_ZERO, deopt); | 1600 __ testq(left, Immediate(kSmiTagMask)); // Is receiver Smi? |
| 1600 __ testq(left, Immediate(kSmiTagMask)); // Receiver can be Smi. | 1601 __ j(NOT_ZERO, &non_smi); |
| 1601 Label two_smi; | 1602 __ testq(right, Immediate(kSmiTagMask)); // Is argument Smi? |
| 1602 __ j(ZERO, &two_smi); | 1603 __ j(ZERO, &smi_smi); |
| 1603 __ CompareClassId(left, kMint); // Receiver must be Mint. | 1604 __ CompareClassId(right, kMint); // Is argument Mint? |
| 1604 __ j(NOT_EQUAL, deopt); | 1605 __ j(NOT_EQUAL, deopt); // Argument neither Smi nor Mint. |
| 1606 __ cmpq(left, Immediate(0)); |
| 1607 __ j(LESS, &smi_static_call); // Negative Smi receiver, Mint argument. |
| 1605 | 1608 |
| 1606 ASSERT(comp->op_kind() == Token::kBIT_AND); | 1609 // Positive Smi receiver, Mint argument. |
| 1610 // Load lower argument Mint word, convert to Smi. It is OK to loose bits. |
| 1611 __ movq(right, FieldAddress(right, Mint::value_offset())); |
| 1612 __ SmiTag(right); |
| 1613 __ andq(result, right); |
| 1614 __ jmp(&done); |
| 1607 | 1615 |
| 1608 // Load lower Mint word, convert to Smi. It is OK to loose bits. | 1616 __ Bind(&non_smi); // Receiver is non-Smi. |
| 1609 ASSERT(result == left); | 1617 __ CompareClassId(left, kMint); // Is receiver Mint? |
| 1618 __ j(NOT_EQUAL, deopt); // Receiver neither Smi nor Mint. |
| 1619 __ testq(right, Immediate(kSmiTagMask)); // Is argument Smi? |
| 1620 __ j(NOT_ZERO, &mint_static_call); // Mint receiver, non-Smi argument. |
| 1621 __ cmpq(right, Immediate(0)); |
| 1622 __ j(LESS, &mint_static_call); // Mint receiver, negative Smi argument. |
| 1623 |
| 1624 // Mint receiver, positive Smi argument. |
| 1625 // Load lower receiver Mint word, convert to Smi. It is OK to loose bits. |
| 1610 __ movq(result, FieldAddress(left, Mint::value_offset())); | 1626 __ movq(result, FieldAddress(left, Mint::value_offset())); |
| 1611 __ SmiTag(result); | 1627 __ SmiTag(result); |
| 1612 __ Bind(&two_smi); | 1628 __ Bind(&smi_smi); |
| 1613 __ andq(result, right); | 1629 __ andq(result, right); |
| 1630 __ jmp(&done); |
| 1631 |
| 1632 __ Bind(&smi_static_call); |
| 1633 { |
| 1634 Function& target = Function::ZoneHandle( |
| 1635 comp->ic_data()->GetTargetForReceiverClassId(kSmi)); |
| 1636 if (target.IsNull()) { |
| 1637 __ jmp(deopt); |
| 1638 } else { |
| 1639 __ pushq(left); |
| 1640 __ pushq(right); |
| 1641 compiler->GenerateStaticCall(comp->instance_call()->cid(), |
| 1642 comp->instance_call()->token_index(), |
| 1643 comp->instance_call()->try_index(), |
| 1644 target, |
| 1645 comp->instance_call()->ArgumentCount(), |
| 1646 comp->instance_call()->argument_names()); |
| 1647 ASSERT(result == RAX); |
| 1648 __ jmp(&done); |
| 1649 } |
| 1650 } |
| 1651 |
| 1652 __ Bind(&mint_static_call); |
| 1653 { |
| 1654 Function& target = Function::ZoneHandle( |
| 1655 comp->ic_data()->GetTargetForReceiverClassId(kMint)); |
| 1656 if (target.IsNull()) { |
| 1657 __ jmp(deopt); |
| 1658 } else { |
| 1659 __ pushq(left); |
| 1660 __ pushq(right); |
| 1661 compiler->GenerateStaticCall(comp->instance_call()->cid(), |
| 1662 comp->instance_call()->token_index(), |
| 1663 comp->instance_call()->try_index(), |
| 1664 target, |
| 1665 comp->instance_call()->ArgumentCount(), |
| 1666 comp->instance_call()->argument_names()); |
| 1667 ASSERT(result == RAX); |
| 1668 } |
| 1669 } |
| 1670 __ Bind(&done); |
| 1614 } | 1671 } |
| 1615 | 1672 |
| 1616 | 1673 |
| 1617 static void EmitDoubleBinaryOp(FlowGraphCompiler* compiler, | 1674 static void EmitDoubleBinaryOp(FlowGraphCompiler* compiler, |
| 1618 BinaryOpComp* comp) { | 1675 BinaryOpComp* comp) { |
| 1619 Register left = RBX; | 1676 Register left = RBX; |
| 1620 Register right = RCX; | 1677 Register right = RCX; |
| 1621 Register temp = RDX; | 1678 Register temp = RDX; |
| 1622 Register result = comp->locs()->out().reg(); | 1679 Register result = comp->locs()->out().reg(); |
| 1623 | 1680 |
| (...skipping 268 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1892 instance_call()->argument_names()); | 1949 instance_call()->argument_names()); |
| 1893 } | 1950 } |
| 1894 __ Bind(&done); | 1951 __ Bind(&done); |
| 1895 } | 1952 } |
| 1896 | 1953 |
| 1897 } // namespace dart | 1954 } // namespace dart |
| 1898 | 1955 |
| 1899 #undef __ | 1956 #undef __ |
| 1900 | 1957 |
| 1901 #endif // defined TARGET_ARCH_X64 | 1958 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |