Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(256)

Side by Side Diff: runtime/vm/intrinsifier_ia32.cc

Issue 14205023: Fully implement integer modulo in intrinsifier, fall-through only for throwing exceptions. Also int… (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « runtime/vm/intrinsifier_arm.cc ('k') | runtime/vm/intrinsifier_mips.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, 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 // The intrinsic code below is executed before a method has built its frame. 5 // The intrinsic code below is executed before a method has built its frame.
6 // The return address is on the stack and the arguments below it. 6 // The return address is on the stack and the arguments below it.
7 // Registers EDX (arguments descriptor) and ECX (function) must be preserved. 7 // Registers EDX (arguments descriptor) and ECX (function) must be preserved.
8 // Each intrinsification method returns true if the corresponding 8 // Each intrinsification method returns true if the corresponding
9 // Dart method was intrinsified. 9 // Dart method was intrinsified.
10 10
(...skipping 649 matching lines...) Expand 10 before | Expand all | Expand 10 after
660 __ Bind(&fall_through); 660 __ Bind(&fall_through);
661 return false; 661 return false;
662 } 662 }
663 663
664 664
665 bool Intrinsifier::Integer_mul(Assembler* assembler) { 665 bool Intrinsifier::Integer_mul(Assembler* assembler) {
666 return Integer_mulFromInteger(assembler); 666 return Integer_mulFromInteger(assembler);
667 } 667 }
668 668
669 669
670 bool Intrinsifier::Integer_modulo(Assembler* assembler) { 670 // Optimizations:
671 Label fall_through, return_zero, try_modulo; 671 // - result is 0 if:
672 TestBothArgumentsSmis(assembler, &fall_through); 672 // - left is 0
673 // EAX: right argument (divisor) 673 // - left equals right
674 // Check if modulo by zero -> exception thrown in main function. 674 // - result is left if
675 // - left > 0 && left < right
676 // EAX: Tagged left (dividend).
677 // EBX: Tagged right (divisor).
678 // EDX: Untagged result (remainder).
679 void EmitRemainderOperation(Assembler* assembler) {
680 Label return_zero, modulo;
681 // Check for quick zero results.
675 __ cmpl(EAX, Immediate(0)); 682 __ cmpl(EAX, Immediate(0));
676 __ j(EQUAL, &fall_through, Assembler::kNearJump);
677 __ movl(EBX, Address(ESP, + 2 * kWordSize)); // Left argument (dividend).
678 __ cmpl(EBX, Immediate(0));
679 __ j(LESS, &fall_through, Assembler::kNearJump);
680 __ cmpl(EBX, EAX);
681 __ j(EQUAL, &return_zero, Assembler::kNearJump); 683 __ j(EQUAL, &return_zero, Assembler::kNearJump);
682 __ j(GREATER, &try_modulo, Assembler::kNearJump); 684 __ cmpl(EAX, EBX);
683 __ movl(EAX, EBX); // Return dividend as it is smaller than divisor. 685 __ j(EQUAL, &return_zero, Assembler::kNearJump);
686
687 // Check if result equals left.
688 __ cmpl(EAX, Immediate(0));
689 __ j(LESS, &modulo, Assembler::kNearJump);
690 // left is positive.
691 __ cmpl(EAX, EBX);
692 __ j(GREATER, &modulo, Assembler::kNearJump);
693 // left is less than right, result is left (EAX).
684 __ ret(); 694 __ ret();
695
685 __ Bind(&return_zero); 696 __ Bind(&return_zero);
686 __ xorl(EAX, EAX); // Return zero. 697 __ xorl(EAX, EAX);
687 __ ret(); 698 __ ret();
688 __ Bind(&try_modulo); 699
689 // EAX: right (non-null divisor). 700 __ Bind(&modulo);
690 __ movl(EBX, EAX);
691 __ SmiUntag(EBX); 701 __ SmiUntag(EBX);
692 __ movl(EAX, Address(ESP, + 2 * kWordSize)); // Left argument (dividend).
693 __ SmiUntag(EAX); 702 __ SmiUntag(EAX);
694 __ cdq(); 703 __ cdq();
695 __ idivl(EBX); 704 __ idivl(EBX);
705 }
706
707
708 // Implementation:
709 // res = left % right;
710 // if (res < 0) {
711 // if (right < 0) {
712 // res = res - right;
713 // } else {
714 // res = res + right;
715 // }
716 // }
717 bool Intrinsifier::Integer_modulo(Assembler* assembler) {
718 Label fall_through, subtract;
719 TestBothArgumentsSmis(assembler, &fall_through);
720 // EAX: right argument (divisor)
721 __ movl(EBX, EAX);
722 __ movl(EAX, Address(ESP, + 2 * kWordSize)); // Left argument (dividend).
723 // EAX: Tagged left (dividend).
724 // EBX: Tagged right (divisor).
725 // Check if modulo by zero -> exception thrown in main function.
726 __ cmpl(EBX, Immediate(0));
727 __ j(EQUAL, &fall_through, Assembler::kNearJump);
728 EmitRemainderOperation(assembler);
729 // Untagged remainder result in EDX.
730 Label done;
731 __ movl(EAX, EDX);
732 __ cmpl(EAX, Immediate(0));
733 __ j(GREATER_EQUAL, &done, Assembler::kNearJump);
734 // Result is negative, adjust it.
735 __ cmpl(EBX, Immediate(0));
736 __ j(LESS, &subtract, Assembler::kNearJump);
737 __ addl(EAX, EBX);
738 __ SmiTag(EAX);
739 __ ret();
740
741 __ Bind(&subtract);
742 __ subl(EAX, EBX);
743
744 __ Bind(&done);
745 // The remainder of two Smi-s is always a Smi, no overflow check needed.
746 __ SmiTag(EAX);
747 __ ret();
748
749 __ Bind(&fall_through);
750 return false;
751 }
752
753
754 bool Intrinsifier::Integer_remainder(Assembler* assembler) {
755 Label fall_through;
756 TestBothArgumentsSmis(assembler, &fall_through);
757 // EAX: right argument (divisor)
758 __ movl(EBX, EAX);
759 __ movl(EAX, Address(ESP, + 2 * kWordSize)); // Left argument (dividend).
760 // EAX: Tagged left (dividend).
761 // EBX: Tagged right (divisor).
762 // Check if modulo by zero -> exception thrown in main function.
763 __ cmpl(EBX, Immediate(0));
764 __ j(EQUAL, &fall_through, Assembler::kNearJump);
765 EmitRemainderOperation(assembler);
766 // Untagged remainder result in EDX.
696 __ movl(EAX, EDX); 767 __ movl(EAX, EDX);
697 __ SmiTag(EAX); 768 __ SmiTag(EAX);
698 __ ret(); 769 __ ret();
770
699 __ Bind(&fall_through); 771 __ Bind(&fall_through);
700 return false; 772 return false;
701 } 773 }
702 774
703 775
704 bool Intrinsifier::Integer_truncDivide(Assembler* assembler) { 776 bool Intrinsifier::Integer_truncDivide(Assembler* assembler) {
705 Label fall_through; 777 Label fall_through;
706 TestBothArgumentsSmis(assembler, &fall_through); 778 TestBothArgumentsSmis(assembler, &fall_through);
707 // EAX: right argument (divisor) 779 // EAX: right argument (divisor)
708 __ cmpl(EAX, Immediate(0)); 780 __ cmpl(EAX, Immediate(0));
(...skipping 897 matching lines...) Expand 10 before | Expand all | Expand 10 after
1606 __ j(LESS, &loop, Assembler::kNearJump); 1678 __ j(LESS, &loop, Assembler::kNearJump);
1607 __ ret(); 1679 __ ret();
1608 __ Bind(&fall_through); 1680 __ Bind(&fall_through);
1609 return false; 1681 return false;
1610 } 1682 }
1611 1683
1612 #undef __ 1684 #undef __
1613 } // namespace dart 1685 } // namespace dart
1614 1686
1615 #endif // defined TARGET_ARCH_IA32 1687 #endif // defined TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « runtime/vm/intrinsifier_arm.cc ('k') | runtime/vm/intrinsifier_mips.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698