| 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 264 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 275 locs->set_in(0, Location::RequiresXmmRegister()); | 275 locs->set_in(0, Location::RequiresXmmRegister()); |
| 276 locs->set_in(1, Location::RequiresXmmRegister()); | 276 locs->set_in(1, Location::RequiresXmmRegister()); |
| 277 locs->set_out(Location::RequiresRegister()); | 277 locs->set_out(Location::RequiresRegister()); |
| 278 return locs; | 278 return locs; |
| 279 } | 279 } |
| 280 if (receiver_class_id() == kSmiCid) { | 280 if (receiver_class_id() == kSmiCid) { |
| 281 const intptr_t kNumTemps = 0; | 281 const intptr_t kNumTemps = 0; |
| 282 LocationSummary* locs = | 282 LocationSummary* locs = |
| 283 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 283 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 284 locs->set_in(0, Location::RegisterOrConstant(left())); | 284 locs->set_in(0, Location::RegisterOrConstant(left())); |
| 285 locs->set_in(1, Location::RegisterOrConstant(right())); | 285 // Only one input can be a constant operand. The case of two constant |
| 286 // operands should be handled by constant propagation. |
| 287 locs->set_in(1, locs->in(0).IsConstant() |
| 288 ? Location::RequiresRegister() |
| 289 : Location::RegisterOrConstant(right())); |
| 286 locs->set_out(Location::RequiresRegister()); | 290 locs->set_out(Location::RequiresRegister()); |
| 287 return locs; | 291 return locs; |
| 288 } | 292 } |
| 289 if (is_checked_strict_equal) { | 293 if (is_checked_strict_equal) { |
| 290 const intptr_t kNumTemps = 1; | 294 const intptr_t kNumTemps = 1; |
| 291 LocationSummary* locs = | 295 LocationSummary* locs = |
| 292 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 296 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 293 locs->set_in(0, Location::RequiresRegister()); | 297 locs->set_in(0, Location::RequiresRegister()); |
| 294 locs->set_in(1, Location::RequiresRegister()); | 298 locs->set_in(1, Location::RequiresRegister()); |
| 295 locs->set_temp(0, Location::RequiresRegister()); | 299 locs->set_temp(0, Location::RequiresRegister()); |
| (...skipping 304 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 600 __ Bind(&done); | 604 __ Bind(&done); |
| 601 } | 605 } |
| 602 | 606 |
| 603 | 607 |
| 604 static void EmitSmiComparisonOp(FlowGraphCompiler* compiler, | 608 static void EmitSmiComparisonOp(FlowGraphCompiler* compiler, |
| 605 const LocationSummary& locs, | 609 const LocationSummary& locs, |
| 606 Token::Kind kind, | 610 Token::Kind kind, |
| 607 BranchInstr* branch) { | 611 BranchInstr* branch) { |
| 608 Location left = locs.in(0); | 612 Location left = locs.in(0); |
| 609 Location right = locs.in(1); | 613 Location right = locs.in(1); |
| 614 ASSERT(!left.IsConstant() || !right.IsConstant()); |
| 610 | 615 |
| 611 Condition true_condition = TokenKindToSmiCondition(kind); | 616 Condition true_condition = TokenKindToSmiCondition(kind); |
| 612 | 617 |
| 613 if (left.IsConstant() && right.IsConstant()) { | |
| 614 bool result = false; | |
| 615 // One of them could be NULL (for equality only). | |
| 616 if (left.constant().IsNull() || right.constant().IsNull()) { | |
| 617 ASSERT((kind == Token::kEQ) || (kind == Token::kNE)); | |
| 618 result = left.constant().IsNull() && right.constant().IsNull(); | |
| 619 if (kind == Token::kNE) { | |
| 620 result = !result; | |
| 621 } | |
| 622 } else { | |
| 623 // TODO(vegorov): should be eliminated earlier by constant propagation. | |
| 624 result = FlowGraphCompiler::EvaluateCondition( | |
| 625 true_condition, | |
| 626 Smi::Cast(left.constant()).Value(), | |
| 627 Smi::Cast(right.constant()).Value()); | |
| 628 } | |
| 629 | |
| 630 if (branch != NULL) { | |
| 631 branch->EmitBranchOnValue(compiler, result); | |
| 632 } else { | |
| 633 __ LoadObject(locs.out().reg(), result ? compiler->bool_true() | |
| 634 : compiler->bool_false()); | |
| 635 } | |
| 636 | |
| 637 return; | |
| 638 } | |
| 639 | |
| 640 if (left.IsConstant()) { | 618 if (left.IsConstant()) { |
| 641 __ CompareObject(right.reg(), left.constant()); | 619 __ CompareObject(right.reg(), left.constant()); |
| 642 true_condition = FlowGraphCompiler::FlipCondition(true_condition); | 620 true_condition = FlowGraphCompiler::FlipCondition(true_condition); |
| 643 } else if (right.IsConstant()) { | 621 } else if (right.IsConstant()) { |
| 644 __ CompareObject(left.reg(), right.constant()); | 622 __ CompareObject(left.reg(), right.constant()); |
| 645 } else { | 623 } else { |
| 646 __ cmpq(left.reg(), right.reg()); | 624 __ cmpq(left.reg(), right.reg()); |
| 647 } | 625 } |
| 648 | 626 |
| 649 if (branch != NULL) { | 627 if (branch != NULL) { |
| (...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 784 LocationSummary* summary = | 762 LocationSummary* summary = |
| 785 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 763 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 786 summary->set_in(0, Location::RequiresXmmRegister()); | 764 summary->set_in(0, Location::RequiresXmmRegister()); |
| 787 summary->set_in(1, Location::RequiresXmmRegister()); | 765 summary->set_in(1, Location::RequiresXmmRegister()); |
| 788 summary->set_out(Location::RequiresRegister()); | 766 summary->set_out(Location::RequiresRegister()); |
| 789 return summary; | 767 return summary; |
| 790 } else if (operands_class_id() == kSmiCid) { | 768 } else if (operands_class_id() == kSmiCid) { |
| 791 LocationSummary* summary = | 769 LocationSummary* summary = |
| 792 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 770 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 793 summary->set_in(0, Location::RegisterOrConstant(left())); | 771 summary->set_in(0, Location::RegisterOrConstant(left())); |
| 794 summary->set_in(1, Location::RegisterOrConstant(right())); | 772 // Only one input can be a constant operand. The case of two constant |
| 773 // operands should be handled by constant propagation. |
| 774 summary->set_in(1, summary->in(0).IsConstant() |
| 775 ? Location::RequiresRegister() |
| 776 : Location::RegisterOrConstant(right())); |
| 795 summary->set_out(Location::RequiresRegister()); | 777 summary->set_out(Location::RequiresRegister()); |
| 796 return summary; | 778 return summary; |
| 797 } | 779 } |
| 798 LocationSummary* locs = | 780 LocationSummary* locs = |
| 799 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 781 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
| 800 // Pick arbitrary fixed input registers because this is a call. | 782 // Pick arbitrary fixed input registers because this is a call. |
| 801 locs->set_in(0, Location::RegisterLocation(RAX)); | 783 locs->set_in(0, Location::RegisterLocation(RAX)); |
| 802 locs->set_in(1, Location::RegisterLocation(RCX)); | 784 locs->set_in(1, Location::RegisterLocation(RCX)); |
| 803 locs->set_out(Location::RegisterLocation(RAX)); | 785 locs->set_out(Location::RegisterLocation(RAX)); |
| 804 return locs; | 786 return locs; |
| (...skipping 785 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1590 summary->set_temp(0, Location::RegisterLocation(RBX)); | 1572 summary->set_temp(0, Location::RegisterLocation(RBX)); |
| 1591 // Will be used for for sign extension. | 1573 // Will be used for for sign extension. |
| 1592 summary->set_temp(1, Location::RegisterLocation(RDX)); | 1574 summary->set_temp(1, Location::RegisterLocation(RDX)); |
| 1593 summary->set_temp(2, Location::RequiresRegister()); | 1575 summary->set_temp(2, Location::RequiresRegister()); |
| 1594 return summary; | 1576 return summary; |
| 1595 } else if (op_kind() == Token::kSHR) { | 1577 } else if (op_kind() == Token::kSHR) { |
| 1596 const intptr_t kNumTemps = 0; | 1578 const intptr_t kNumTemps = 0; |
| 1597 LocationSummary* summary = | 1579 LocationSummary* summary = |
| 1598 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1580 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 1599 summary->set_in(0, Location::RequiresRegister()); | 1581 summary->set_in(0, Location::RequiresRegister()); |
| 1600 summary->set_in(1, Location::RegisterLocation(RCX)); | 1582 summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), RCX)); |
| 1601 summary->set_out(Location::SameAsFirstInput()); | 1583 summary->set_out(Location::SameAsFirstInput()); |
| 1602 return summary; | 1584 return summary; |
| 1603 } else if (op_kind() == Token::kSHL) { | 1585 } else if (op_kind() == Token::kSHL) { |
| 1604 const intptr_t kNumTemps = 1; | 1586 const intptr_t kNumTemps = 1; |
| 1605 LocationSummary* summary = | 1587 LocationSummary* summary = |
| 1606 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1588 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 1607 summary->set_in(0, Location::RequiresRegister()); | 1589 summary->set_in(0, Location::RequiresRegister()); |
| 1608 summary->set_in(1, Location::FixedRegisterOrConstant(right(), RCX)); | 1590 summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), RCX)); |
| 1609 summary->set_temp(0, Location::RequiresRegister()); | 1591 summary->set_temp(0, Location::RequiresRegister()); |
| 1610 summary->set_out(Location::SameAsFirstInput()); | 1592 summary->set_out(Location::SameAsFirstInput()); |
| 1611 return summary; | 1593 return summary; |
| 1612 } else { | 1594 } else { |
| 1613 const intptr_t kNumTemps = 0; | 1595 const intptr_t kNumTemps = 0; |
| 1614 LocationSummary* summary = | 1596 LocationSummary* summary = |
| 1615 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1597 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 1616 summary->set_in(0, Location::RequiresRegister()); | 1598 summary->set_in(0, Location::RequiresRegister()); |
| 1617 summary->set_in(1, Location::RequiresRegister()); | 1599 summary->set_in(1, Location::RegisterOrSmiConstant(right())); |
| 1618 summary->set_out(Location::SameAsFirstInput()); | 1600 summary->set_out(Location::SameAsFirstInput()); |
| 1619 return summary; | 1601 return summary; |
| 1620 } | 1602 } |
| 1621 } | 1603 } |
| 1622 | 1604 |
| 1623 | 1605 |
| 1624 void BinarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1606 void BinarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1625 Register left = locs()->in(0).reg(); | 1607 Register left = locs()->in(0).reg(); |
| 1626 Register result = locs()->out().reg(); | 1608 Register result = locs()->out().reg(); |
| 1627 ASSERT(left == result); | 1609 ASSERT(left == result); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 1640 case Token::kADD: { | 1622 case Token::kADD: { |
| 1641 __ addq(left, Immediate(imm)); | 1623 __ addq(left, Immediate(imm)); |
| 1642 if (deopt != NULL) __ j(OVERFLOW, deopt); | 1624 if (deopt != NULL) __ j(OVERFLOW, deopt); |
| 1643 break; | 1625 break; |
| 1644 } | 1626 } |
| 1645 case Token::kSUB: { | 1627 case Token::kSUB: { |
| 1646 __ subq(left, Immediate(imm)); | 1628 __ subq(left, Immediate(imm)); |
| 1647 if (deopt != NULL) __ j(OVERFLOW, deopt); | 1629 if (deopt != NULL) __ j(OVERFLOW, deopt); |
| 1648 break; | 1630 break; |
| 1649 } | 1631 } |
| 1632 case Token::kMUL: { |
| 1633 // Keep left value tagged and untag right value. |
| 1634 const intptr_t value = Smi::Cast(constant).Value(); |
| 1635 __ imulq(left, Immediate(value)); |
| 1636 if (deopt != NULL) __ j(OVERFLOW, deopt); |
| 1637 break; |
| 1638 } |
| 1650 case Token::kBIT_AND: { | 1639 case Token::kBIT_AND: { |
| 1651 // No overflow check. | 1640 // No overflow check. |
| 1652 __ andq(left, Immediate(imm)); | 1641 __ andq(left, Immediate(imm)); |
| 1653 break; | 1642 break; |
| 1654 } | 1643 } |
| 1655 case Token::kBIT_OR: { | 1644 case Token::kBIT_OR: { |
| 1656 // No overflow check. | 1645 // No overflow check. |
| 1657 __ orq(left, Immediate(imm)); | 1646 __ orq(left, Immediate(imm)); |
| 1658 break; | 1647 break; |
| 1659 } | 1648 } |
| (...skipping 580 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2240 __ testq(value, Immediate(kSmiTagMask)); | 2229 __ testq(value, Immediate(kSmiTagMask)); |
| 2241 __ j(NOT_ZERO, deopt); | 2230 __ j(NOT_ZERO, deopt); |
| 2242 } | 2231 } |
| 2243 | 2232 |
| 2244 | 2233 |
| 2245 LocationSummary* CheckArrayBoundInstr::MakeLocationSummary() const { | 2234 LocationSummary* CheckArrayBoundInstr::MakeLocationSummary() const { |
| 2246 const intptr_t kNumInputs = 2; | 2235 const intptr_t kNumInputs = 2; |
| 2247 const intptr_t kNumTemps = 0; | 2236 const intptr_t kNumTemps = 0; |
| 2248 LocationSummary* locs = | 2237 LocationSummary* locs = |
| 2249 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 2238 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 2250 locs->set_in(0, Location::RequiresRegister()); | 2239 locs->set_in(0, Location::RegisterOrSmiConstant(array())); |
| 2251 locs->set_in(1, Location::RegisterOrConstant(index())); | 2240 locs->set_in(1, Location::RegisterOrSmiConstant(index())); |
| 2252 return locs; | 2241 return locs; |
| 2253 } | 2242 } |
| 2254 | 2243 |
| 2255 | 2244 |
| 2256 void CheckArrayBoundInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2245 void CheckArrayBoundInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2257 Label* deopt = compiler->AddDeoptStub(deopt_id(), | 2246 Label* deopt = compiler->AddDeoptStub(deopt_id(), |
| 2258 kDeoptCheckArrayBound); | 2247 kDeoptCheckArrayBound); |
| 2259 if (locs()->in(0).IsConstant() && locs()->in(1).IsConstant()) { | 2248 if (locs()->in(0).IsConstant() && locs()->in(1).IsConstant()) { |
| 2260 // Unconditionally deoptimize for constant bounds checks because they | 2249 // Unconditionally deoptimize for constant bounds checks because they |
| 2261 // only occur only when index is out-of-bounds. | 2250 // only occur only when index is out-of-bounds. |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2344 | 2333 |
| 2345 void ShiftMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2334 void ShiftMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2346 UNIMPLEMENTED(); | 2335 UNIMPLEMENTED(); |
| 2347 } | 2336 } |
| 2348 | 2337 |
| 2349 } // namespace dart | 2338 } // namespace dart |
| 2350 | 2339 |
| 2351 #undef __ | 2340 #undef __ |
| 2352 | 2341 |
| 2353 #endif // defined TARGET_ARCH_X64 | 2342 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |