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