Chromium Code Reviews| 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 627 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 638 __ LoadObject(result, compiler->bool_true()); | 638 __ LoadObject(result, compiler->bool_true()); |
| 639 __ Bind(&done); | 639 __ Bind(&done); |
| 640 } | 640 } |
| 641 } | 641 } |
| 642 | 642 |
| 643 | 643 |
| 644 static Condition TokenKindToMintCondition(Token::Kind kind) { | 644 static Condition TokenKindToMintCondition(Token::Kind kind) { |
| 645 switch (kind) { | 645 switch (kind) { |
| 646 case Token::kEQ: return EQUAL; | 646 case Token::kEQ: return EQUAL; |
| 647 case Token::kNE: return NOT_EQUAL; | 647 case Token::kNE: return NOT_EQUAL; |
| 648 case Token::kLT: return BELOW; | |
| 649 case Token::kGT: return ABOVE; | |
| 650 case Token::kLTE: return BELOW_EQUAL; | |
| 651 case Token::kGTE: return ABOVE_EQUAL; | |
| 648 default: | 652 default: |
| 649 UNIMPLEMENTED(); | 653 UNREACHABLE(); |
| 650 return OVERFLOW; | 654 return OVERFLOW; |
| 651 } | 655 } |
| 652 } | 656 } |
| 653 | 657 |
| 654 | 658 |
| 655 static void EmitUnboxedMintEqualityOp(FlowGraphCompiler* compiler, | 659 static void EmitUnboxedMintEqualityOp(FlowGraphCompiler* compiler, |
| 656 const LocationSummary& locs, | 660 const LocationSummary& locs, |
| 657 Token::Kind kind, | 661 Token::Kind kind, |
| 658 BranchInstr* branch) { | 662 BranchInstr* branch) { |
| 659 ASSERT(Token::IsEqualityOperator(kind)); | 663 ASSERT(Token::IsEqualityOperator(kind)); |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 675 __ j(true_condition, &is_true); | 679 __ j(true_condition, &is_true); |
| 676 __ LoadObject(result, compiler->bool_false()); | 680 __ LoadObject(result, compiler->bool_false()); |
| 677 __ jmp(&done); | 681 __ jmp(&done); |
| 678 __ Bind(&is_true); | 682 __ Bind(&is_true); |
| 679 __ LoadObject(result, compiler->bool_true()); | 683 __ LoadObject(result, compiler->bool_true()); |
| 680 __ Bind(&done); | 684 __ Bind(&done); |
| 681 } | 685 } |
| 682 } | 686 } |
| 683 | 687 |
| 684 | 688 |
| 689 static void EmitUnboxedMintComparisonOp(FlowGraphCompiler* compiler, | |
| 690 const LocationSummary& locs, | |
| 691 Token::Kind kind, | |
| 692 BranchInstr* branch) { | |
| 693 XmmRegister left = locs.in(0).xmm_reg(); | |
| 694 XmmRegister right = locs.in(1).xmm_reg(); | |
| 695 Register lo = locs.temp(0).reg(); | |
| 696 Register hi = locs.temp(1).reg(); | |
| 697 | |
| 698 __ pextrd(lo, left, Immediate(0)); // Lower half | |
| 699 __ pextrd(hi, left, Immediate(1)); // Upper half | |
| 700 __ subl(ESP, Immediate(2 * kWordSize)); | |
| 701 __ movq(Address(ESP, 0), right); | |
| 702 Label compare_lo, compare_done; | |
| 703 __ cmpl(hi, Address(ESP, 1 * kWordSize)); | |
| 704 __ j(EQUAL, &compare_lo); | |
| 705 __ jmp(&compare_done); | |
| 706 __ Bind(&compare_lo); | |
| 707 __ cmpl(lo, Address(ESP, 0 * kWordSize)); | |
|
Vyacheslav Egorov (Google)
2012/10/29 12:46:40
can you benchmark another pattern:
extract highe
| |
| 708 | |
| 709 __ Bind(&compare_done); | |
| 710 // Use popl to restore stack instead of add(ESP...) to preserve flags. | |
| 711 __ popl(lo); | |
| 712 __ popl(lo); | |
| 713 Condition true_condition = TokenKindToMintCondition(kind); | |
| 714 if (branch != NULL) { | |
| 715 branch->EmitBranchOnCondition(compiler, true_condition); | |
| 716 } else { | |
| 717 Register result = locs.out().reg(); | |
| 718 Label done, is_true; | |
| 719 __ j(true_condition, &is_true); | |
| 720 __ LoadObject(result, compiler->bool_false()); | |
| 721 __ jmp(&done); | |
| 722 __ Bind(&is_true); | |
| 723 __ LoadObject(result, compiler->bool_true()); | |
| 724 __ Bind(&done); | |
| 725 } | |
| 726 } | |
| 727 | |
| 728 | |
| 685 static Condition TokenKindToDoubleCondition(Token::Kind kind) { | 729 static Condition TokenKindToDoubleCondition(Token::Kind kind) { |
| 686 switch (kind) { | 730 switch (kind) { |
| 687 case Token::kEQ: return EQUAL; | 731 case Token::kEQ: return EQUAL; |
| 688 case Token::kNE: return NOT_EQUAL; | 732 case Token::kNE: return NOT_EQUAL; |
| 689 case Token::kLT: return BELOW; | 733 case Token::kLT: return BELOW; |
| 690 case Token::kGT: return ABOVE; | 734 case Token::kGT: return ABOVE; |
| 691 case Token::kLTE: return BELOW_EQUAL; | 735 case Token::kLTE: return BELOW_EQUAL; |
| 692 case Token::kGTE: return ABOVE_EQUAL; | 736 case Token::kGTE: return ABOVE_EQUAL; |
| 693 default: | 737 default: |
| 694 UNREACHABLE(); | 738 UNREACHABLE(); |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 794 } | 838 } |
| 795 Condition branch_condition = (kind() == Token::kNE) ? NOT_EQUAL : EQUAL; | 839 Condition branch_condition = (kind() == Token::kNE) ? NOT_EQUAL : EQUAL; |
| 796 __ CompareObject(EAX, compiler->bool_true()); | 840 __ CompareObject(EAX, compiler->bool_true()); |
| 797 branch->EmitBranchOnCondition(compiler, branch_condition); | 841 branch->EmitBranchOnCondition(compiler, branch_condition); |
| 798 } | 842 } |
| 799 | 843 |
| 800 | 844 |
| 801 LocationSummary* RelationalOpInstr::MakeLocationSummary() const { | 845 LocationSummary* RelationalOpInstr::MakeLocationSummary() const { |
| 802 const intptr_t kNumInputs = 2; | 846 const intptr_t kNumInputs = 2; |
| 803 const intptr_t kNumTemps = 0; | 847 const intptr_t kNumTemps = 0; |
| 848 if (operands_class_id() == kMintCid) { | |
| 849 const intptr_t kNumTemps = 2; | |
| 850 LocationSummary* locs = | |
| 851 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | |
| 852 locs->set_in(0, Location::RequiresXmmRegister()); | |
| 853 locs->set_in(1, Location::RequiresXmmRegister()); | |
| 854 locs->set_temp(0, Location::RequiresRegister()); | |
| 855 locs->set_temp(1, Location::RequiresRegister()); | |
| 856 locs->set_out(Location::RequiresRegister()); | |
| 857 return locs; | |
| 858 } | |
| 804 if (operands_class_id() == kDoubleCid) { | 859 if (operands_class_id() == kDoubleCid) { |
| 805 LocationSummary* summary = | 860 LocationSummary* summary = |
| 806 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 861 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 807 summary->set_in(0, Location::RequiresXmmRegister()); | 862 summary->set_in(0, Location::RequiresXmmRegister()); |
| 808 summary->set_in(1, Location::RequiresXmmRegister()); | 863 summary->set_in(1, Location::RequiresXmmRegister()); |
| 809 summary->set_out(Location::RequiresRegister()); | 864 summary->set_out(Location::RequiresRegister()); |
| 810 return summary; | 865 return summary; |
| 811 } else if (operands_class_id() == kSmiCid) { | 866 } else if (operands_class_id() == kSmiCid) { |
| 812 LocationSummary* summary = | 867 LocationSummary* summary = |
| 813 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 868 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 824 locs->set_out(Location::RegisterLocation(EAX)); | 879 locs->set_out(Location::RegisterLocation(EAX)); |
| 825 return locs; | 880 return locs; |
| 826 } | 881 } |
| 827 | 882 |
| 828 | 883 |
| 829 void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 884 void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 830 if (operands_class_id() == kSmiCid) { | 885 if (operands_class_id() == kSmiCid) { |
| 831 EmitSmiComparisonOp(compiler, *locs(), kind(), NULL); | 886 EmitSmiComparisonOp(compiler, *locs(), kind(), NULL); |
| 832 return; | 887 return; |
| 833 } | 888 } |
| 889 if (operands_class_id() == kMintCid) { | |
| 890 EmitUnboxedMintComparisonOp(compiler, *locs(), kind(), NULL); | |
| 891 return; | |
| 892 } | |
| 834 if (operands_class_id() == kDoubleCid) { | 893 if (operands_class_id() == kDoubleCid) { |
| 835 EmitDoubleComparisonOp(compiler, *locs(), kind(), NULL); | 894 EmitDoubleComparisonOp(compiler, *locs(), kind(), NULL); |
| 836 return; | 895 return; |
| 837 } | 896 } |
| 838 | 897 |
| 839 // Push arguments for the call. | 898 // Push arguments for the call. |
| 840 // TODO(fschneider): Split this instruction into different types to avoid | 899 // TODO(fschneider): Split this instruction into different types to avoid |
| 841 // explicitly pushing arguments to the call here. | 900 // explicitly pushing arguments to the call here. |
| 842 Register left = locs()->in(0).reg(); | 901 Register left = locs()->in(0).reg(); |
| 843 Register right = locs()->in(1).reg(); | 902 Register right = locs()->in(1).reg(); |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 883 locs()); | 942 locs()); |
| 884 } | 943 } |
| 885 | 944 |
| 886 | 945 |
| 887 void RelationalOpInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 946 void RelationalOpInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
| 888 BranchInstr* branch) { | 947 BranchInstr* branch) { |
| 889 if (operands_class_id() == kSmiCid) { | 948 if (operands_class_id() == kSmiCid) { |
| 890 EmitSmiComparisonOp(compiler, *locs(), kind(), branch); | 949 EmitSmiComparisonOp(compiler, *locs(), kind(), branch); |
| 891 return; | 950 return; |
| 892 } | 951 } |
| 952 if (operands_class_id() == kMintCid) { | |
| 953 EmitUnboxedMintComparisonOp(compiler, *locs(), kind(), branch); | |
| 954 return; | |
| 955 } | |
| 893 if (operands_class_id() == kDoubleCid) { | 956 if (operands_class_id() == kDoubleCid) { |
| 894 EmitDoubleComparisonOp(compiler, *locs(), kind(), branch); | 957 EmitDoubleComparisonOp(compiler, *locs(), kind(), branch); |
| 895 return; | 958 return; |
| 896 } | 959 } |
| 897 EmitNativeCode(compiler); | 960 EmitNativeCode(compiler); |
| 898 __ CompareObject(EAX, compiler->bool_true()); | 961 __ CompareObject(EAX, compiler->bool_true()); |
| 899 branch->EmitBranchOnCondition(compiler, EQUAL); | 962 branch->EmitBranchOnCondition(compiler, EQUAL); |
| 900 } | 963 } |
| 901 | 964 |
| 902 | 965 |
| (...skipping 1534 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2437 case Token::kBIT_AND: __ andpd(left, right); break; | 2500 case Token::kBIT_AND: __ andpd(left, right); break; |
| 2438 case Token::kBIT_OR: __ orpd(left, right); break; | 2501 case Token::kBIT_OR: __ orpd(left, right); break; |
| 2439 case Token::kBIT_XOR: __ xorpd(left, right); break; | 2502 case Token::kBIT_XOR: __ xorpd(left, right); break; |
| 2440 case Token::kADD: | 2503 case Token::kADD: |
| 2441 case Token::kSUB: { | 2504 case Token::kSUB: { |
| 2442 Register lo = locs()->temp(0).reg(); | 2505 Register lo = locs()->temp(0).reg(); |
| 2443 Register hi = locs()->temp(1).reg(); | 2506 Register hi = locs()->temp(1).reg(); |
| 2444 Label* deopt = compiler->AddDeoptStub(deopt_id(), | 2507 Label* deopt = compiler->AddDeoptStub(deopt_id(), |
| 2445 kDeoptBinaryMintOp); | 2508 kDeoptBinaryMintOp); |
| 2446 Label done, overflow; | 2509 Label done, overflow; |
| 2447 __ pextrd(lo, right, Immediate(0)); // Lower half left | 2510 __ pextrd(lo, right, Immediate(0)); // Lower half |
| 2448 __ pextrd(hi, right, Immediate(1)); // Upper half left | 2511 __ pextrd(hi, right, Immediate(1)); // Upper half |
| 2449 __ subl(ESP, Immediate(2 * kWordSize)); | 2512 __ subl(ESP, Immediate(2 * kWordSize)); |
| 2450 __ movq(Address(ESP, 0), left); | 2513 __ movq(Address(ESP, 0), left); |
| 2451 if (op_kind() == Token::kADD) { | 2514 if (op_kind() == Token::kADD) { |
| 2452 __ addl(Address(ESP, 0), lo); | 2515 __ addl(Address(ESP, 0), lo); |
| 2453 __ adcl(Address(ESP, 1 * kWordSize), hi); | 2516 __ adcl(Address(ESP, 1 * kWordSize), hi); |
| 2454 } else { | 2517 } else { |
| 2455 __ subl(Address(ESP, 0), lo); | 2518 __ subl(Address(ESP, 0), lo); |
| 2456 __ sbbl(Address(ESP, 1 * kWordSize), hi); | 2519 __ sbbl(Address(ESP, 1 * kWordSize), hi); |
| 2457 } | 2520 } |
| 2458 __ j(OVERFLOW, &overflow); | 2521 __ j(OVERFLOW, &overflow); |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2558 __ pcmpeqq(XMM0, XMM0); // Generate all 1's. | 2621 __ pcmpeqq(XMM0, XMM0); // Generate all 1's. |
| 2559 __ pxor(value, XMM0); | 2622 __ pxor(value, XMM0); |
| 2560 } | 2623 } |
| 2561 | 2624 |
| 2562 | 2625 |
| 2563 } // namespace dart | 2626 } // namespace dart |
| 2564 | 2627 |
| 2565 #undef __ | 2628 #undef __ |
| 2566 | 2629 |
| 2567 #endif // defined TARGET_ARCH_X64 | 2630 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |