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

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

Issue 10542079: Implement Smi binops ia32 (new compiler). (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 6 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
OLDNEW
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 736 matching lines...) Expand 10 before | Expand all | Expand 10 after
747 __ movl(Address(EBP, exception_var().index() * kWordSize), 747 __ movl(Address(EBP, exception_var().index() * kWordSize),
748 kExceptionObjectReg); 748 kExceptionObjectReg);
749 __ movl(Address(EBP, stacktrace_var().index() * kWordSize), 749 __ movl(Address(EBP, stacktrace_var().index() * kWordSize),
750 kStackTraceObjectReg); 750 kStackTraceObjectReg);
751 } 751 }
752 752
753 753
754 LocationSummary* BinaryOpComp::MakeLocationSummary() const { 754 LocationSummary* BinaryOpComp::MakeLocationSummary() const {
755 const intptr_t kNumInputs = 2; 755 const intptr_t kNumInputs = 2;
756 const intptr_t kNumTemps = 0; 756 const intptr_t kNumTemps = 0;
757 LocationSummary* summary = new LocationSummary(kNumInputs, kNumTemps); 757 if (operands_type() == kDoubleOperands) {
758 summary->set_in(0, Location::RequiresRegister()); 758 LocationSummary* summary = new LocationSummary(kNumInputs, kNumTemps);
759 summary->set_in(1, Location::RequiresRegister()); 759 summary->set_in(0, Location::RequiresRegister());
760 summary->set_out(Location::SameAsFirstInput()); 760 summary->set_in(1, Location::RequiresRegister());
761 return summary; 761 summary->set_out(Location::SameAsFirstInput());
762 } 762 return summary;
763 763 }
764 764 ASSERT(operands_type() == kSmiOperands);
765 void BinaryOpComp::EmitNativeCode(FlowGraphCompiler* compiler) { 765 if (op_kind() == Token::kTRUNCDIV) {
766 const intptr_t kNumTemps = 3;
767 LocationSummary* summary = new LocationSummary(kNumInputs, kNumTemps);
768 summary->set_in(0, Location::RegisterLocation(EAX));
769 summary->set_in(1, Location::RegisterLocation(ECX));
770 summary->set_out(Location::SameAsFirstInput());
771 summary->set_temp(0, Location::RegisterLocation(EBX));
772 // Will be used for for sign extension.
773 summary->set_temp(1, Location::RegisterLocation(EDX));
774 summary->set_temp(2, Location::RequiresRegister());
775 return summary;
776 } else if (op_kind() == Token::kSHR) {
777 const intptr_t kNumTemps = 1;
778 LocationSummary* summary = new LocationSummary(kNumInputs, kNumTemps);
779 summary->set_in(0, Location::RequiresRegister());
780 summary->set_in(1, Location::RegisterLocation(ECX));
781 summary->set_out(Location::SameAsFirstInput());
782 summary->set_temp(0, Location::RequiresRegister());
783 return summary;
784 } else if (op_kind() == Token::kSHL) {
785 const intptr_t kNumTemps = 2;
786 LocationSummary* summary = new LocationSummary(kNumInputs, kNumTemps);
787 summary->set_in(0, Location::RequiresRegister());
788 summary->set_in(1, Location::RequiresRegister());
789 summary->set_out(Location::SameAsFirstInput());
790 summary->set_temp(0, Location::RequiresRegister());
791 summary->set_temp(1, Location::RegisterLocation(ECX));
792 return summary;
793 } else {
794 const intptr_t kNumTemps = 1;
795 LocationSummary* summary = new LocationSummary(kNumInputs, kNumTemps);
796 summary->set_in(0, Location::RequiresRegister());
797 summary->set_in(1, Location::RequiresRegister());
798 summary->set_out(Location::SameAsFirstInput());
799 summary->set_temp(0, Location::RequiresRegister());
800 return summary;
801 }
802 }
803
804
805 static void EmitSmiBinaryOp(FlowGraphCompiler* compiler, BinaryOpComp* comp) {
806 Register left = comp->locs()->in(0).reg();
807 Register right = comp->locs()->in(1).reg();
808 Register result = comp->locs()->out().reg();
809 Register temp = comp->locs()->temp(0).reg();
810 ASSERT(left == result);
811 Label* deopt = compiler->AddDeoptStub(comp->instance_call()->cid(),
812 comp->instance_call()->token_index(),
813 comp->instance_call()->try_index(),
814 kDeoptSmiBinaryOp,
815 temp,
816 right);
817 __ movl(temp, left);
818 __ orl(left, right);
819 __ testl(left, Immediate(kSmiTagMask));
820 __ j(NOT_ZERO, deopt);
821 __ movl(left, temp);
822 switch (comp->op_kind()) {
823 case Token::kADD: {
824 __ addl(left, right);
825 __ j(OVERFLOW, deopt);
826 break;
827 }
828 case Token::kSUB: {
829 __ subl(left, right);
830 __ j(OVERFLOW, deopt);
831 break;
832 }
833 case Token::kMUL: {
834 __ SmiUntag(left);
835 __ imull(left, right);
836 __ j(OVERFLOW, deopt);
837 break;
838 }
839 case Token::kBIT_AND: {
840 // No overflow check.
841 __ andl(left, right);
842 break;
843 }
844 case Token::kBIT_OR: {
845 // No overflow check.
846 __ orl(left, right);
847 break;
848 }
849 case Token::kBIT_XOR: {
850 // No overflow check.
851 __ xorl(left, right);
852 break;
853 }
854 case Token::kTRUNCDIV: {
855 // Handle divide by zero in runtime.
856 // Deoptimization requires that temp and right are preserved.
857 __ testl(right, right);
858 __ j(ZERO, deopt);
859 ASSERT(left == EAX);
860 ASSERT((right != EDX) && (right != EAX));
861 ASSERT((temp != EDX) && (temp != EAX));
862 ASSERT(comp->locs()->temp(1).reg() == EDX);
863 ASSERT(result == EAX);
864 Register right_temp = comp->locs()->temp(2).reg();
865 __ movl(right_temp, right);
866 __ SmiUntag(left);
867 __ SmiUntag(right_temp);
868 __ cdq(); // Sign extend EAX -> EDX:EAX.
869 __ idivl(right_temp); // EAX: quotient, EDX: remainder.
870 // Check the corner case of dividing the 'MIN_SMI' with -1, in which
871 // case we cannot tag the result.
872 __ cmpl(result, Immediate(0x40000000));
873 __ j(EQUAL, deopt);
874 __ SmiTag(result);
875 break;
876 }
877 case Token::kSHR: {
878 // The count is masked to 5 bits on ia32.
879 const Immediate kCountLimit = Immediate(0x1F);
880 __ cmpl(right, Immediate(0));
881 __ j(LESS, deopt);
882 __ SmiUntag(right);
883 __ cmpl(right, kCountLimit);
884 Label count_ok;
885 __ j(LESS, &count_ok, Assembler::kNearJump);
886 __ movl(right, kCountLimit);
887 __ Bind(&count_ok);
888 ASSERT(right == ECX); // Count must be in ECX
889 __ SmiUntag(left);
890 __ sarl(left, right);
891 __ SmiTag(left);
892 break;
893 }
894 case Token::kSHL: {
895 // Check if count too large for handling it inlined.
896 __ cmpl(right,
897 Immediate(reinterpret_cast<int64_t>(Smi::New(Smi::kBits))));
898 __ j(ABOVE_EQUAL, deopt);
899 Register right_temp = comp->locs()->temp(1).reg();
900 ASSERT(right_temp == ECX); // Count must be in ECX
901 __ movl(right_temp, right);
902 __ SmiUntag(right_temp);
903 // Overflow test (preserve temp and right);
904 __ shll(left, right_temp);
905 __ sarl(left, right_temp);
906 __ cmpl(left, temp);
907 __ j(NOT_EQUAL, deopt); // Overflow.
908 // Shift for result now we know there is no overflow.
909 __ shll(left, right_temp);
910 break;
911 }
912 case Token::kDIV: {
913 // Dispatches to 'Double./'.
914 // TODO(srdjan): Implement as conversion to double and double division.
915 UNREACHABLE();
916 break;
917 }
918 case Token::kMOD: {
919 // TODO(srdjan): Implement.
920 UNREACHABLE();
921 break;
922 }
923 case Token::kOR:
924 case Token::kAND: {
925 // Flow graph builder has dissected this operation to guarantee correct
926 // behavior (short-circuit evaluation).
927 UNREACHABLE();
928 break;
929 }
930 default:
931 UNREACHABLE();
932 break;
933 }
934 }
935
936
937 static void EmitDoubleBinaryOp(FlowGraphCompiler* compiler,
938 BinaryOpComp* comp) {
766 // TODO(srdjan): Remove this code once BinaryOpComp has been implemeneted 939 // TODO(srdjan): Remove this code once BinaryOpComp has been implemeneted
767 // for all intended operations. 940 // for all intended operations.
768 Register left = locs()->in(0).reg(); 941 Register left = comp->locs()->in(0).reg();
769 Register right = locs()->in(1).reg(); 942 Register right = comp->locs()->in(1).reg();
770 __ pushl(left); 943 __ pushl(left);
771 __ pushl(right); 944 __ pushl(right);
772 InstanceCallComp* instance_call_comp = instance_call(); 945 InstanceCallComp* instance_call_comp = comp->instance_call();
773 instance_call_comp->EmitNativeCode(compiler); 946 instance_call_comp->EmitNativeCode(compiler);
774 if (locs()->out().reg() != EAX) { 947 __ MoveRegister(comp->locs()->out().reg(), EAX);
775 __ movl(locs()->out().reg(), EAX); 948 }
776 } 949
777 } 950
778 951 void BinaryOpComp::EmitNativeCode(FlowGraphCompiler* compiler) {
952 switch (operands_type()) {
953 case kSmiOperands:
954 EmitSmiBinaryOp(compiler, this);
955 break;
956
957 case kDoubleOperands:
958 EmitDoubleBinaryOp(compiler, this);
959 break;
960
961 default:
962 UNREACHABLE();
963 }
964 }
965
779 966
780 LocationSummary* UnarySmiOpComp::MakeLocationSummary() const { 967 LocationSummary* UnarySmiOpComp::MakeLocationSummary() const {
781 const intptr_t kNumInputs = 1; 968 const intptr_t kNumInputs = 1;
782 const intptr_t kNumTemps = 0; 969 const intptr_t kNumTemps = 0;
783 LocationSummary* summary = new LocationSummary(kNumInputs, kNumTemps); 970 LocationSummary* summary = new LocationSummary(kNumInputs, kNumTemps);
784 summary->set_in(0, Location::RequiresRegister()); 971 summary->set_in(0, Location::RequiresRegister());
785 summary->set_out(Location::SameAsFirstInput()); 972 summary->set_out(Location::SameAsFirstInput());
786 return summary; 973 return summary;
787 } 974 }
788 975
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
886 UNREACHABLE(); 1073 UNREACHABLE();
887 } 1074 }
888 } 1075 }
889 1076
890 1077
891 } // namespace dart 1078 } // namespace dart
892 1079
893 #undef __ 1080 #undef __
894 1081
895 #endif // defined TARGET_ARCH_X64 1082 #endif // defined TARGET_ARCH_X64
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698