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 |