| 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 244 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 255 UNREACHABLE(); | 255 UNREACHABLE(); |
| 256 return OVERFLOW; | 256 return OVERFLOW; |
| 257 } | 257 } |
| 258 } | 258 } |
| 259 | 259 |
| 260 | 260 |
| 261 LocationSummary* EqualityCompareInstr::MakeLocationSummary() const { | 261 LocationSummary* EqualityCompareInstr::MakeLocationSummary() const { |
| 262 const intptr_t kNumInputs = 2; | 262 const intptr_t kNumInputs = 2; |
| 263 const bool is_checked_strict_equal = | 263 const bool is_checked_strict_equal = |
| 264 HasICData() && ic_data()->AllTargetsHaveSameOwner(kInstanceCid); | 264 HasICData() && ic_data()->AllTargetsHaveSameOwner(kInstanceCid); |
| 265 if (receiver_class_id() == kMintCid) { |
| 266 const intptr_t kNumTemps = 1; |
| 267 LocationSummary* locs = |
| 268 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 269 locs->set_in(0, Location::RequiresXmmRegister()); |
| 270 locs->set_in(1, Location::RequiresXmmRegister()); |
| 271 locs->set_temp(0, Location::RequiresRegister()); |
| 272 locs->set_out(Location::RequiresRegister()); |
| 273 return locs; |
| 274 } |
| 265 if (receiver_class_id() == kDoubleCid) { | 275 if (receiver_class_id() == kDoubleCid) { |
| 266 const intptr_t kNumTemps = 0; | 276 const intptr_t kNumTemps = 0; |
| 267 LocationSummary* locs = | 277 LocationSummary* locs = |
| 268 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 278 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 269 locs->set_in(0, Location::RequiresXmmRegister()); | 279 locs->set_in(0, Location::RequiresXmmRegister()); |
| 270 locs->set_in(1, Location::RequiresXmmRegister()); | 280 locs->set_in(1, Location::RequiresXmmRegister()); |
| 271 locs->set_out(Location::RequiresRegister()); | 281 locs->set_out(Location::RequiresRegister()); |
| 272 return locs; | 282 return locs; |
| 273 } | 283 } |
| 274 if (receiver_class_id() == kSmiCid) { | 284 if (receiver_class_id() == kSmiCid) { |
| (...skipping 335 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 610 __ j(true_condition, &is_true); | 620 __ j(true_condition, &is_true); |
| 611 __ LoadObject(result, compiler->bool_false()); | 621 __ LoadObject(result, compiler->bool_false()); |
| 612 __ jmp(&done); | 622 __ jmp(&done); |
| 613 __ Bind(&is_true); | 623 __ Bind(&is_true); |
| 614 __ LoadObject(result, compiler->bool_true()); | 624 __ LoadObject(result, compiler->bool_true()); |
| 615 __ Bind(&done); | 625 __ Bind(&done); |
| 616 } | 626 } |
| 617 } | 627 } |
| 618 | 628 |
| 619 | 629 |
| 630 static Condition TokenKindToMintCondition(Token::Kind kind) { |
| 631 switch (kind) { |
| 632 case Token::kEQ: return EQUAL; |
| 633 case Token::kNE: return NOT_EQUAL; |
| 634 default: |
| 635 UNREACHABLE(); |
| 636 return OVERFLOW; |
| 637 } |
| 638 } |
| 639 |
| 640 |
| 641 static void EmitUnboxedMintEqualityOp(FlowGraphCompiler* compiler, |
| 642 const LocationSummary& locs, |
| 643 Token::Kind kind, |
| 644 BranchInstr* branch) { |
| 645 ASSERT(Token::IsEqualityOperator(kind)); |
| 646 XmmRegister left = locs.in(0).xmm_reg(); |
| 647 XmmRegister right = locs.in(1).xmm_reg(); |
| 648 Register temp = locs.temp(0).reg(); |
| 649 __ movaps(XMM0, left); |
| 650 __ pcmpeqq(XMM0, right); |
| 651 __ movd(temp, XMM0); |
| 652 |
| 653 Condition true_condition = TokenKindToMintCondition(kind); |
| 654 __ cmpl(temp, Immediate(-1)); |
| 655 |
| 656 if (branch != NULL) { |
| 657 branch->EmitBranchOnCondition(compiler, true_condition); |
| 658 } else { |
| 659 Register result = locs.out().reg(); |
| 660 Label done, is_true; |
| 661 __ j(true_condition, &is_true); |
| 662 __ LoadObject(result, compiler->bool_false()); |
| 663 __ jmp(&done); |
| 664 __ Bind(&is_true); |
| 665 __ LoadObject(result, compiler->bool_true()); |
| 666 __ Bind(&done); |
| 667 } |
| 668 } |
| 669 |
| 670 |
| 620 static Condition TokenKindToDoubleCondition(Token::Kind kind) { | 671 static Condition TokenKindToDoubleCondition(Token::Kind kind) { |
| 621 switch (kind) { | 672 switch (kind) { |
| 622 case Token::kEQ: return EQUAL; | 673 case Token::kEQ: return EQUAL; |
| 623 case Token::kNE: return NOT_EQUAL; | 674 case Token::kNE: return NOT_EQUAL; |
| 624 case Token::kLT: return BELOW; | 675 case Token::kLT: return BELOW; |
| 625 case Token::kGT: return ABOVE; | 676 case Token::kGT: return ABOVE; |
| 626 case Token::kLTE: return BELOW_EQUAL; | 677 case Token::kLTE: return BELOW_EQUAL; |
| 627 case Token::kGTE: return ABOVE_EQUAL; | 678 case Token::kGTE: return ABOVE_EQUAL; |
| 628 default: | 679 default: |
| 629 UNREACHABLE(); | 680 UNREACHABLE(); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 651 | 702 |
| 652 | 703 |
| 653 void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 704 void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 654 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); | 705 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); |
| 655 BranchInstr* kNoBranch = NULL; | 706 BranchInstr* kNoBranch = NULL; |
| 656 if (receiver_class_id() == kSmiCid) { | 707 if (receiver_class_id() == kSmiCid) { |
| 657 // Deoptimizes if both arguments not Smi. | 708 // Deoptimizes if both arguments not Smi. |
| 658 EmitSmiComparisonOp(compiler, *locs(), kind(), kNoBranch); | 709 EmitSmiComparisonOp(compiler, *locs(), kind(), kNoBranch); |
| 659 return; | 710 return; |
| 660 } | 711 } |
| 712 if (receiver_class_id() == kMintCid) { |
| 713 EmitUnboxedMintEqualityOp(compiler, *locs(), kind(), kNoBranch); |
| 714 return; |
| 715 } |
| 661 if (receiver_class_id() == kDoubleCid) { | 716 if (receiver_class_id() == kDoubleCid) { |
| 662 EmitDoubleComparisonOp(compiler, *locs(), kind(), kNoBranch); | 717 EmitDoubleComparisonOp(compiler, *locs(), kind(), kNoBranch); |
| 663 return; | 718 return; |
| 664 } | 719 } |
| 665 const bool is_checked_strict_equal = | 720 const bool is_checked_strict_equal = |
| 666 HasICData() && ic_data()->AllTargetsHaveSameOwner(kInstanceCid); | 721 HasICData() && ic_data()->AllTargetsHaveSameOwner(kInstanceCid); |
| 667 if (is_checked_strict_equal) { | 722 if (is_checked_strict_equal) { |
| 668 EmitCheckedStrictEqual(compiler, *ic_data(), *locs(), kind(), kNoBranch, | 723 EmitCheckedStrictEqual(compiler, *ic_data(), *locs(), kind(), kNoBranch, |
| 669 deopt_id()); | 724 deopt_id()); |
| 670 return; | 725 return; |
| (...skipping 13 matching lines...) Expand all Loading... |
| 684 | 739 |
| 685 | 740 |
| 686 void EqualityCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 741 void EqualityCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
| 687 BranchInstr* branch) { | 742 BranchInstr* branch) { |
| 688 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); | 743 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); |
| 689 if (receiver_class_id() == kSmiCid) { | 744 if (receiver_class_id() == kSmiCid) { |
| 690 // Deoptimizes if both arguments not Smi. | 745 // Deoptimizes if both arguments not Smi. |
| 691 EmitSmiComparisonOp(compiler, *locs(), kind(), branch); | 746 EmitSmiComparisonOp(compiler, *locs(), kind(), branch); |
| 692 return; | 747 return; |
| 693 } | 748 } |
| 749 if (receiver_class_id() == kMintCid) { |
| 750 EmitUnboxedMintEqualityOp(compiler, *locs(), kind(), branch); |
| 751 return; |
| 752 } |
| 694 if (receiver_class_id() == kDoubleCid) { | 753 if (receiver_class_id() == kDoubleCid) { |
| 695 EmitDoubleComparisonOp(compiler, *locs(), kind(), branch); | 754 EmitDoubleComparisonOp(compiler, *locs(), kind(), branch); |
| 696 return; | 755 return; |
| 697 } | 756 } |
| 698 const bool is_checked_strict_equal = | 757 const bool is_checked_strict_equal = |
| 699 HasICData() && ic_data()->AllTargetsHaveSameOwner(kInstanceCid); | 758 HasICData() && ic_data()->AllTargetsHaveSameOwner(kInstanceCid); |
| 700 if (is_checked_strict_equal) { | 759 if (is_checked_strict_equal) { |
| 701 EmitCheckedStrictEqual(compiler, *ic_data(), *locs(), kind(), branch, | 760 EmitCheckedStrictEqual(compiler, *ic_data(), *locs(), kind(), branch, |
| 702 deopt_id()); | 761 deopt_id()); |
| 703 return; | 762 return; |
| (...skipping 977 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1681 UNREACHABLE(); | 1740 UNREACHABLE(); |
| 1682 break; | 1741 break; |
| 1683 } | 1742 } |
| 1684 default: | 1743 default: |
| 1685 UNREACHABLE(); | 1744 UNREACHABLE(); |
| 1686 break; | 1745 break; |
| 1687 } | 1746 } |
| 1688 } | 1747 } |
| 1689 | 1748 |
| 1690 | 1749 |
| 1691 LocationSummary* BinaryMintOpInstr::MakeLocationSummary() const { | |
| 1692 const intptr_t kNumInputs = 2; | |
| 1693 ASSERT(op_kind() == Token::kBIT_AND); | |
| 1694 const intptr_t kNumTemps = 1; | |
| 1695 LocationSummary* summary = | |
| 1696 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | |
| 1697 summary->set_in(0, Location::RegisterLocation(EAX)); | |
| 1698 summary->set_in(1, Location::RegisterLocation(ECX)); | |
| 1699 summary->set_temp(0, Location::RegisterLocation(EDX)); | |
| 1700 summary->set_out(Location::RegisterLocation(EAX)); | |
| 1701 return summary; | |
| 1702 } | |
| 1703 | |
| 1704 | |
| 1705 void BinaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | |
| 1706 // TODO(regis): For now, we only support Token::kBIT_AND for a Mint or Smi | |
| 1707 // receiver and a Mint or Smi argument. We fall back to the run time call if | |
| 1708 // both receiver and argument are Mint or if one of them is Mint and the other | |
| 1709 // is a negative Smi. | |
| 1710 Register left = locs()->in(0).reg(); | |
| 1711 Register right = locs()->in(1).reg(); | |
| 1712 Register result = locs()->out().reg(); | |
| 1713 Register temp = locs()->temp(0).reg(); | |
| 1714 ASSERT(left == result); | |
| 1715 ASSERT(op_kind() == Token::kBIT_AND); | |
| 1716 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), | |
| 1717 kDeoptBinaryMintOp); | |
| 1718 Label mint_static_call, smi_static_call, non_smi, smi_smi, done; | |
| 1719 __ testl(left, Immediate(kSmiTagMask)); // Is receiver Smi? | |
| 1720 __ j(NOT_ZERO, &non_smi); | |
| 1721 __ testl(right, Immediate(kSmiTagMask)); // Is argument Smi? | |
| 1722 __ j(ZERO, &smi_smi); | |
| 1723 __ CompareClassId(right, kMintCid, temp); // Is argument Mint? | |
| 1724 __ j(NOT_EQUAL, deopt); // Argument neither Smi nor Mint. | |
| 1725 __ cmpl(left, Immediate(0)); | |
| 1726 __ j(LESS, &smi_static_call); // Negative Smi receiver, Mint argument. | |
| 1727 | |
| 1728 // Positive Smi receiver, Mint argument. | |
| 1729 // Load lower argument Mint word, convert to Smi. It is OK to loose bits. | |
| 1730 __ movl(right, FieldAddress(right, Mint::value_offset())); | |
| 1731 __ SmiTag(right); | |
| 1732 __ andl(result, right); | |
| 1733 __ jmp(&done); | |
| 1734 | |
| 1735 __ Bind(&non_smi); // Receiver is non-Smi. | |
| 1736 __ CompareClassId(left, kMintCid, temp); // Is receiver Mint? | |
| 1737 __ j(NOT_EQUAL, deopt); // Receiver neither Smi nor Mint. | |
| 1738 __ testl(right, Immediate(kSmiTagMask)); // Is argument Smi? | |
| 1739 __ j(NOT_ZERO, &mint_static_call); // Mint receiver, non-Smi argument. | |
| 1740 __ cmpl(right, Immediate(0)); | |
| 1741 __ j(LESS, &mint_static_call); // Mint receiver, negative Smi argument. | |
| 1742 | |
| 1743 // Mint receiver, positive Smi argument. | |
| 1744 // Load lower receiver Mint word, convert to Smi. It is OK to loose bits. | |
| 1745 __ movl(result, FieldAddress(left, Mint::value_offset())); | |
| 1746 __ SmiTag(result); | |
| 1747 __ Bind(&smi_smi); | |
| 1748 __ andl(result, right); | |
| 1749 __ jmp(&done); | |
| 1750 | |
| 1751 __ Bind(&smi_static_call); | |
| 1752 { | |
| 1753 Function& target = Function::ZoneHandle( | |
| 1754 ic_data()->GetTargetForReceiverClassId(kSmiCid)); | |
| 1755 if (target.IsNull()) { | |
| 1756 __ jmp(deopt); | |
| 1757 } else { | |
| 1758 __ pushl(left); | |
| 1759 __ pushl(right); | |
| 1760 compiler->GenerateStaticCall( | |
| 1761 instance_call()->deopt_id(), | |
| 1762 instance_call()->token_pos(), | |
| 1763 target, | |
| 1764 instance_call()->ArgumentCount(), | |
| 1765 instance_call()->argument_names(), | |
| 1766 locs()); | |
| 1767 ASSERT(result == EAX); | |
| 1768 __ jmp(&done); | |
| 1769 } | |
| 1770 } | |
| 1771 | |
| 1772 __ Bind(&mint_static_call); | |
| 1773 { | |
| 1774 Function& target = Function::ZoneHandle( | |
| 1775 ic_data()->GetTargetForReceiverClassId(kMintCid)); | |
| 1776 if (target.IsNull()) { | |
| 1777 __ jmp(deopt); | |
| 1778 } else { | |
| 1779 __ pushl(left); | |
| 1780 __ pushl(right); | |
| 1781 compiler->GenerateStaticCall( | |
| 1782 instance_call()->deopt_id(), | |
| 1783 instance_call()->token_pos(), | |
| 1784 target, | |
| 1785 instance_call()->ArgumentCount(), | |
| 1786 instance_call()->argument_names(), | |
| 1787 locs()); | |
| 1788 ASSERT(result == EAX); | |
| 1789 } | |
| 1790 } | |
| 1791 __ Bind(&done); | |
| 1792 } | |
| 1793 | |
| 1794 | |
| 1795 LocationSummary* CheckEitherNonSmiInstr::MakeLocationSummary() const { | 1750 LocationSummary* CheckEitherNonSmiInstr::MakeLocationSummary() const { |
| 1796 ASSERT((left()->ResultCid() != kDoubleCid) && | 1751 ASSERT((left()->ResultCid() != kDoubleCid) && |
| 1797 (right()->ResultCid() != kDoubleCid)); | 1752 (right()->ResultCid() != kDoubleCid)); |
| 1798 const intptr_t kNumInputs = 2; | 1753 const intptr_t kNumInputs = 2; |
| 1799 const intptr_t kNumTemps = 1; | 1754 const intptr_t kNumTemps = 1; |
| 1800 LocationSummary* summary = | 1755 LocationSummary* summary = |
| 1801 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1756 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 1802 summary->set_in(0, Location::RequiresRegister()); | 1757 summary->set_in(0, Location::RequiresRegister()); |
| 1803 summary->set_in(1, Location::RequiresRegister()); | 1758 summary->set_in(1, Location::RequiresRegister()); |
| 1804 summary->set_temp(0, Location::RequiresRegister()); | 1759 summary->set_temp(0, Location::RequiresRegister()); |
| (...skipping 409 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2214 __ j(ABOVE_EQUAL, deopt); | 2169 __ j(ABOVE_EQUAL, deopt); |
| 2215 } else { | 2170 } else { |
| 2216 Register receiver = locs()->in(0).reg(); | 2171 Register receiver = locs()->in(0).reg(); |
| 2217 Register index = locs()->in(1).reg(); | 2172 Register index = locs()->in(1).reg(); |
| 2218 __ cmpl(index, FieldAddress(receiver, length_offset)); | 2173 __ cmpl(index, FieldAddress(receiver, length_offset)); |
| 2219 __ j(ABOVE_EQUAL, deopt); | 2174 __ j(ABOVE_EQUAL, deopt); |
| 2220 } | 2175 } |
| 2221 } | 2176 } |
| 2222 | 2177 |
| 2223 | 2178 |
| 2179 LocationSummary* UnboxIntegerInstr::MakeLocationSummary() const { |
| 2180 const intptr_t kNumInputs = 1; |
| 2181 const intptr_t kNumTemps = CanDeoptimize() ? 1 : 0; |
| 2182 LocationSummary* summary = |
| 2183 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 2184 summary->set_in(0, Location::RequiresRegister()); |
| 2185 if (CanDeoptimize()) summary->set_temp(0, Location::RequiresRegister()); |
| 2186 summary->set_out(Location::RequiresXmmRegister()); |
| 2187 return summary; |
| 2188 } |
| 2189 |
| 2190 |
| 2191 void UnboxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2192 const intptr_t value_cid = value()->ResultCid(); |
| 2193 const Register value = locs()->in(0).reg(); |
| 2194 const XmmRegister result = locs()->out().xmm_reg(); |
| 2195 |
| 2196 if (value_cid == kMintCid) { |
| 2197 __ movsd(result, FieldAddress(value, Mint::value_offset())); |
| 2198 } else if (value_cid == kSmiCid) { |
| 2199 __ SmiUntag(value); // Untag input before conversion. |
| 2200 __ movd(result, value); |
| 2201 __ pmovsxdq(result, result); |
| 2202 __ SmiTag(value); // Restore input register. |
| 2203 } else { |
| 2204 Register temp = locs()->temp(0).reg(); |
| 2205 Label* deopt = compiler->AddDeoptStub(deopt_id_, kDeoptBinaryDoubleOp); |
| 2206 Label is_smi, done; |
| 2207 __ testl(value, Immediate(kSmiTagMask)); |
| 2208 __ j(ZERO, &is_smi); |
| 2209 __ CompareClassId(value, kMintCid, temp); |
| 2210 __ j(NOT_EQUAL, deopt); |
| 2211 __ movsd(result, FieldAddress(value, Mint::value_offset())); |
| 2212 __ jmp(&done); |
| 2213 __ Bind(&is_smi); |
| 2214 __ movl(temp, value); |
| 2215 __ SmiUntag(temp); |
| 2216 __ movd(result, temp); |
| 2217 __ pmovsxdq(result, result); |
| 2218 __ Bind(&done); |
| 2219 } |
| 2220 } |
| 2221 |
| 2222 |
| 2223 LocationSummary* BoxIntegerInstr::MakeLocationSummary() const { |
| 2224 const intptr_t kNumInputs = 1; |
| 2225 const intptr_t kNumTemps = 2; |
| 2226 LocationSummary* summary = |
| 2227 new LocationSummary(kNumInputs, |
| 2228 kNumTemps, |
| 2229 LocationSummary::kCallOnSlowPath); |
| 2230 summary->set_in(0, Location::RequiresXmmRegister()); |
| 2231 summary->set_temp(0, Location::RegisterLocation(EAX)); |
| 2232 summary->set_temp(1, Location::RegisterLocation(EDX)); |
| 2233 // TODO(fschneider): Save one temp by using result register as a temp. |
| 2234 summary->set_out(Location::RequiresRegister()); |
| 2235 return summary; |
| 2236 } |
| 2237 |
| 2238 |
| 2239 class BoxIntegerSlowPath : public SlowPathCode { |
| 2240 public: |
| 2241 explicit BoxIntegerSlowPath(BoxIntegerInstr* instruction) |
| 2242 : instruction_(instruction) { } |
| 2243 |
| 2244 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2245 __ Bind(entry_label()); |
| 2246 const Class& mint_class = |
| 2247 Class::ZoneHandle(Isolate::Current()->object_store()->mint_class()); |
| 2248 const Code& stub = |
| 2249 Code::Handle(StubCode::GetAllocationStubForClass(mint_class)); |
| 2250 const ExternalLabel label(mint_class.ToCString(), stub.EntryPoint()); |
| 2251 |
| 2252 LocationSummary* locs = instruction_->locs(); |
| 2253 locs->live_registers()->Remove(locs->out()); |
| 2254 // Temps contain untagged values. Must only save tagged values. |
| 2255 locs->live_registers()->Remove(locs->temp(0)); |
| 2256 locs->live_registers()->Remove(locs->temp(1)); |
| 2257 |
| 2258 compiler->SaveLiveRegisters(locs); |
| 2259 compiler->GenerateCall(0, // No token pos. |
| 2260 &label, |
| 2261 PcDescriptors::kOther, |
| 2262 locs); |
| 2263 if (EAX != locs->out().reg()) __ movl(locs->out().reg(), EAX); |
| 2264 compiler->RestoreLiveRegisters(locs); |
| 2265 |
| 2266 __ jmp(exit_label()); |
| 2267 } |
| 2268 |
| 2269 private: |
| 2270 BoxIntegerInstr* instruction_; |
| 2271 }; |
| 2272 |
| 2273 |
| 2274 void BoxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2275 BoxIntegerSlowPath* slow_path = new BoxIntegerSlowPath(this); |
| 2276 compiler->AddSlowPathCode(slow_path); |
| 2277 |
| 2278 Register out_reg = locs()->out().reg(); |
| 2279 XmmRegister value = locs()->in(0).xmm_reg(); |
| 2280 |
| 2281 // Check if result fits into a smi. |
| 2282 Label not_smi, done; |
| 2283 __ pextrd(EDX, value, Immediate(1)); // Upper half. |
| 2284 __ pextrd(EAX, value, Immediate(0)); // Lower half. |
| 2285 // 1. Compute (x + -kMinSmi) which has to be in the range |
| 2286 // 0 .. -kMinSmi+kMaxSmi for x to fit into a smi. |
| 2287 __ addl(EAX, Immediate(0x40000000)); |
| 2288 __ adcl(EDX, Immediate(0)); |
| 2289 // 2. Unsigned compare to -kMinSmi+kMaxSmi. |
| 2290 __ cmpl(EAX, Immediate(0x80000000)); |
| 2291 __ sbbl(EDX, Immediate(0)); |
| 2292 __ j(ABOVE_EQUAL, ¬_smi); |
| 2293 // 3. Restore lower half if results is a smi. |
| 2294 __ subl(EAX, Immediate(0x40000000)); |
| 2295 |
| 2296 __ SmiTag(EAX); |
| 2297 __ movl(out_reg, EAX); |
| 2298 __ jmp(&done); |
| 2299 |
| 2300 __ Bind(¬_smi); |
| 2301 AssemblerMacros::TryAllocate( |
| 2302 compiler->assembler(), |
| 2303 Class::ZoneHandle(Isolate::Current()->object_store()->mint_class()), |
| 2304 slow_path->entry_label(), |
| 2305 Assembler::kFarJump, |
| 2306 out_reg); |
| 2307 __ Bind(slow_path->exit_label()); |
| 2308 __ movsd(FieldAddress(out_reg, Mint::value_offset()), value); |
| 2309 __ Bind(&done); |
| 2310 } |
| 2311 |
| 2312 |
| 2313 LocationSummary* UnboxedMintBinaryOpInstr::MakeLocationSummary() const { |
| 2314 const intptr_t kNumInputs = 2; |
| 2315 const intptr_t kNumTemps = 0; |
| 2316 LocationSummary* summary = |
| 2317 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 2318 summary->set_in(0, Location::RequiresXmmRegister()); |
| 2319 summary->set_in(1, Location::RequiresXmmRegister()); |
| 2320 summary->set_out(Location::SameAsFirstInput()); |
| 2321 return summary; |
| 2322 } |
| 2323 |
| 2324 |
| 2325 void UnboxedMintBinaryOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2326 XmmRegister left = locs()->in(0).xmm_reg(); |
| 2327 XmmRegister right = locs()->in(1).xmm_reg(); |
| 2328 |
| 2329 ASSERT(locs()->out().xmm_reg() == left); |
| 2330 |
| 2331 switch (op_kind()) { |
| 2332 case Token::kBIT_AND: __ andpd(left, right); break; |
| 2333 case Token::kBIT_OR: __ orpd(left, right); break; |
| 2334 case Token::kBIT_XOR: __ xorpd(left, right); break; |
| 2335 default: UNREACHABLE(); |
| 2336 } |
| 2337 } |
| 2338 |
| 2339 |
| 2340 |
| 2224 } // namespace dart | 2341 } // namespace dart |
| 2225 | 2342 |
| 2226 #undef __ | 2343 #undef __ |
| 2227 | 2344 |
| 2228 #endif // defined TARGET_ARCH_X64 | 2345 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |