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

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

Issue 10533053: Implement inlined version of binary arithmetic operations for doubles. (Closed) Base URL: https://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_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 732 matching lines...) Expand 10 before | Expand all | Expand 10 after
743 ASSERT(!stacktrace_var().is_captured()); 743 ASSERT(!stacktrace_var().is_captured());
744 __ movq(Address(RBP, exception_var().index() * kWordSize), 744 __ movq(Address(RBP, exception_var().index() * kWordSize),
745 kExceptionObjectReg); 745 kExceptionObjectReg);
746 __ movq(Address(RBP, stacktrace_var().index() * kWordSize), 746 __ movq(Address(RBP, stacktrace_var().index() * kWordSize),
747 kStackTraceObjectReg); 747 kStackTraceObjectReg);
748 } 748 }
749 749
750 750
751 LocationSummary* BinaryOpComp::MakeLocationSummary() const { 751 LocationSummary* BinaryOpComp::MakeLocationSummary() const {
752 const intptr_t kNumInputs = 2; 752 const intptr_t kNumInputs = 2;
753
754 if (operands_type() == kDoubleOperands) {
755 const intptr_t kNumTemps = 1;
756 LocationSummary* summary = new LocationSummary(kNumInputs, kNumTemps);
757 summary->set_in(0, Location::RequiresRegister());
758 summary->set_in(1, Location::RequiresRegister());
759 summary->set_out(Location::RegisterLocation(RAX));
760 summary->set_temp(0, Location::RequiresRegister());
761 return summary;
762 }
763
764 ASSERT(operands_type() == kSmiOperands);
765
753 if (op_kind() == Token::kTRUNCDIV) { 766 if (op_kind() == Token::kTRUNCDIV) {
754 const intptr_t kNumTemps = 3; 767 const intptr_t kNumTemps = 3;
755 LocationSummary* summary = new LocationSummary(kNumInputs, kNumTemps); 768 LocationSummary* summary = new LocationSummary(kNumInputs, kNumTemps);
756 summary->set_in(0, Location::RegisterLocation(RAX)); 769 summary->set_in(0, Location::RegisterLocation(RAX));
757 summary->set_in(1, Location::RegisterLocation(RCX)); 770 summary->set_in(1, Location::RegisterLocation(RCX));
758 summary->set_out(Location::SameAsFirstInput()); 771 summary->set_out(Location::SameAsFirstInput());
759 summary->set_temp(0, Location::RegisterLocation(RBX)); 772 summary->set_temp(0, Location::RegisterLocation(RBX));
760 // Will be used for for sign extension. 773 // Will be used for for sign extension.
761 summary->set_temp(1, Location::RegisterLocation(RDX)); 774 summary->set_temp(1, Location::RegisterLocation(RDX));
762 summary->set_temp(2, Location::RequiresRegister()); 775 summary->set_temp(2, Location::RequiresRegister());
(...skipping 21 matching lines...) Expand all
784 summary->set_in(0, Location::RequiresRegister()); 797 summary->set_in(0, Location::RequiresRegister());
785 summary->set_in(1, Location::RequiresRegister()); 798 summary->set_in(1, Location::RequiresRegister());
786 summary->set_out(Location::SameAsFirstInput()); 799 summary->set_out(Location::SameAsFirstInput());
787 summary->set_temp(0, Location::RequiresRegister()); 800 summary->set_temp(0, Location::RequiresRegister());
788 return summary; 801 return summary;
789 } 802 }
790 } 803 }
791 804
792 805
793 // TODO(srdjan): Implement variations. 806 // TODO(srdjan): Implement variations.
794 static bool TryEmitSmiBinaryOp(FlowGraphCompiler* compiler, 807 static void EmitSmiBinaryOp(FlowGraphCompiler* compiler, BinaryOpComp* comp) {
795 BinaryOpComp* comp) {
796 ASSERT((comp->ic_data() != NULL));
797 const ICData& ic_data = *comp->ic_data();
798 if (ic_data.IsNull()) return false;
799 if (ic_data.num_args_tested() != 2) return false;
800 if (ic_data.NumberOfChecks() != 1) return false;
801 Function& target = Function::Handle();
802 GrowableArray<const Class*> classes;
803 ic_data.GetCheckAt(0, &classes, &target);
804 const Class& smi_class =
805 Class::Handle(Isolate::Current()->object_store()->smi_class());
806 if ((classes[0]->raw() != smi_class.raw()) ||
807 (classes[1]->raw() != smi_class.raw())) {
808 return false;
809 }
810 // TODO(srdjan): need to allocate a temporary register (now using r10) 808 // TODO(srdjan): need to allocate a temporary register (now using r10)
811 Register left = comp->locs()->in(0).reg(); 809 Register left = comp->locs()->in(0).reg();
812 Register right = comp->locs()->in(1).reg(); 810 Register right = comp->locs()->in(1).reg();
813 Register result = comp->locs()->out().reg(); 811 Register result = comp->locs()->out().reg();
814 Register temp = comp->locs()->temp(0).reg(); 812 Register temp = comp->locs()->temp(0).reg();
815 ASSERT(left == result); 813 ASSERT(left == result);
816 Label* deopt = compiler->AddDeoptStub(comp->instance_call()->cid(), 814 Label* deopt = compiler->AddDeoptStub(comp->instance_call()->cid(),
817 comp->instance_call()->token_index(), 815 comp->instance_call()->token_index(),
818 comp->instance_call()->try_index(), 816 comp->instance_call()->try_index(),
819 kDeoptSmiBinaryOp, 817 kDeoptSmiBinaryOp,
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
875 // Check the corner case of dividing the 'MIN_SMI' with -1, in which 873 // Check the corner case of dividing the 'MIN_SMI' with -1, in which
876 // case we cannot tag the result. 874 // case we cannot tag the result.
877 __ cmpq(result, Immediate(0x4000000000000000)); 875 __ cmpq(result, Immediate(0x4000000000000000));
878 __ j(EQUAL, deopt); 876 __ j(EQUAL, deopt);
879 __ SmiTag(result); 877 __ SmiTag(result);
880 break; 878 break;
881 } 879 }
882 case Token::kDIV: { 880 case Token::kDIV: {
883 // Dispatches to 'Double./'. 881 // Dispatches to 'Double./'.
884 // TODO(srdjan): Implement as conversion to double and double division. 882 // TODO(srdjan): Implement as conversion to double and double division.
885 return false; 883 UNREACHABLE();
884 return;
Mads Ager (google) 2012/06/08 09:15:53 Why 'return' here and 'break' below?
Vyacheslav Egorov (Google) 2012/06/08 11:11:13 Done.
886 } 885 }
887 case Token::kMOD: { 886 case Token::kMOD: {
888 // TODO(srdjan): Implement. 887 // TODO(srdjan): Implement.
889 return false; 888 UNREACHABLE();
889 return;
890 } 890 }
891 case Token::kSHR: { 891 case Token::kSHR: {
892 const Immediate kCountLimit = Immediate(0x1F); 892 const Immediate kCountLimit = Immediate(0x1F);
893 __ cmpq(right, Immediate(0)); 893 __ cmpq(right, Immediate(0));
894 __ j(LESS, deopt); 894 __ j(LESS, deopt);
895 __ SmiUntag(right); 895 __ SmiUntag(right);
896 __ cmpq(right, kCountLimit); 896 __ cmpq(right, kCountLimit);
897 Label count_ok; 897 Label count_ok;
898 __ j(LESS, &count_ok, Assembler::kNearJump); 898 __ j(LESS, &count_ok, Assembler::kNearJump);
899 __ movq(right, kCountLimit); 899 __ movq(right, kCountLimit);
(...skipping 20 matching lines...) Expand all
920 __ j(NOT_EQUAL, deopt); // Overflow. 920 __ j(NOT_EQUAL, deopt); // Overflow.
921 // Shift for result now we know there is no overflow. 921 // Shift for result now we know there is no overflow.
922 __ shlq(left, right_temp); 922 __ shlq(left, right_temp);
923 break; 923 break;
924 } 924 }
925 case Token::kOR: 925 case Token::kOR:
926 case Token::kAND: { 926 case Token::kAND: {
927 // Flow graph builder has dissected this operation to guarantee correct 927 // Flow graph builder has dissected this operation to guarantee correct
928 // behavior (short-circuit evaluation). 928 // behavior (short-circuit evaluation).
929 UNREACHABLE(); 929 UNREACHABLE();
930 return false; 930 break;
931 } 931 }
932 default: 932 default:
933 UNREACHABLE(); 933 UNREACHABLE();
934 return false; 934 break;
935 } 935 }
936 return;
Mads Ager (google) 2012/06/08 09:15:53 Why the explicit return?
Vyacheslav Egorov (Google) 2012/06/08 11:11:13 Done.
937 }
938
939
940 static void LoadDoubleOrSmi(FlowGraphCompiler* compiler,
srdjan 2012/06/08 05:18:22 LoadDoubleOrSmiToXMM?
srdjan 2012/06/08 05:18:22 WHy not move it into FlowGraphCompiler and elimina
Vyacheslav Egorov (Google) 2012/06/08 11:11:13 Done.
Vyacheslav Egorov (Google) 2012/06/08 11:11:13 Done.
941 XmmRegister result,
942 Register reg,
943 Register temp,
944 Label* not_double_or_smi) {
945 Label is_smi, done;
946 __ testq(reg, Immediate(kSmiTagMask));
947 __ j(ZERO, &is_smi);
948 __ CompareClassId(reg, kDouble);
949 __ j(NOT_EQUAL, not_double_or_smi);
950 __ movsd(result, FieldAddress(reg, Double::value_offset()));
951 __ jmp(&done);
952 __ Bind(&is_smi);
953 __ movq(temp, reg);
954 __ SmiUntag(temp);
955 __ cvtsi2sd(result, temp);
956 __ Bind(&done);
957 }
958
959
960
961 static bool EmitDoubleBinaryOp(FlowGraphCompiler* compiler,
962 BinaryOpComp* comp) {
963 Register left = comp->locs()->in(0).reg();
964 Register right = comp->locs()->in(1).reg();
965 Register temp = comp->locs()->temp(0).reg();
966 Register result = comp->locs()->out().reg();
967
968
969 const Class& double_class =
970 Class::ZoneHandle(Isolate::Current()->object_store()->double_class());
971 const Code& stub =
972 Code::Handle(StubCode::GetAllocationStubForClass(double_class));
973 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint());
974 __ pushq(left);
975 __ pushq(right);
976 compiler->GenerateCall(comp->instance_call()->token_index(),
977 comp->instance_call()->try_index(),
978 &label,
979 PcDescriptors::kOther);
980 // Newly allocated object is now in result register (RAX).
981 ASSERT(result == RAX);
982 __ popq(right);
983 __ popq(left);
984
985 Label* deopt = compiler->AddDeoptStub(comp->instance_call()->cid(),
986 comp->instance_call()->token_index(),
987 comp->instance_call()->try_index(),
988 kDeoptDoubleBinaryOp,
989 left,
990 right);
991
992 LoadDoubleOrSmi(compiler, XMM0, left, temp, deopt);
993 LoadDoubleOrSmi(compiler, XMM1, right, temp, deopt);
994
995 switch (comp->op_kind()) {
996 case Token::kADD: __ addsd(XMM0, XMM1); break;
997 case Token::kSUB: __ subsd(XMM0, XMM1); break;
998 case Token::kMUL: __ mulsd(XMM0, XMM1); break;
999 case Token::kDIV: __ divsd(XMM0, XMM1); break;
1000 default: UNREACHABLE();
1001 }
1002
1003 __ movsd(FieldAddress(result, Double::value_offset()), XMM0);
936 return true; 1004 return true;
937 } 1005 }
938 1006
1007
939 void BinaryOpComp::EmitNativeCode(FlowGraphCompiler* compiler) { 1008 void BinaryOpComp::EmitNativeCode(FlowGraphCompiler* compiler) {
940 if (TryEmitSmiBinaryOp(compiler, this)) { 1009 switch (operands_type()) {
941 // Operation inlined. 1010 case kSmiOperands:
942 return; 1011 EmitSmiBinaryOp(compiler, this);
943 } 1012 break;
944 // TODO(srdjan): Remove this code once BinaryOpComp has been implemeneted 1013
945 // for all intended operations. 1014 case kDoubleOperands:
946 Register left = locs()->in(0).reg(); 1015 EmitDoubleBinaryOp(compiler, this);
947 Register right = locs()->in(1).reg(); 1016 break;
948 __ pushq(left); 1017
949 __ pushq(right); 1018 default:
950 InstanceCallComp* instance_call_comp = instance_call(); 1019 UNREACHABLE();
951 instance_call_comp->EmitNativeCode(compiler);
952 if (locs()->out().reg() != RAX) {
953 __ movq(locs()->out().reg(), RAX);
954 } 1020 }
955 } 1021 }
956 1022
957 1023
958 LocationSummary* UnarySmiOpComp::MakeLocationSummary() const { 1024 LocationSummary* UnarySmiOpComp::MakeLocationSummary() const {
959 const intptr_t kNumInputs = 1; 1025 const intptr_t kNumInputs = 1;
960 const intptr_t kNumTemps = 0; 1026 const intptr_t kNumTemps = 0;
961 LocationSummary* summary = new LocationSummary(kNumInputs, kNumTemps); 1027 LocationSummary* summary = new LocationSummary(kNumInputs, kNumTemps);
962 summary->set_in(0, Location::RequiresRegister()); 1028 summary->set_in(0, Location::RequiresRegister());
963 summary->set_out(Location::SameAsFirstInput()); 1029 summary->set_out(Location::SameAsFirstInput());
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
1063 } else { 1129 } else {
1064 UNREACHABLE(); 1130 UNREACHABLE();
1065 } 1131 }
1066 } 1132 }
1067 1133
1068 } // namespace dart 1134 } // namespace dart
1069 1135
1070 #undef __ 1136 #undef __
1071 1137
1072 #endif // defined TARGET_ARCH_X64 1138 #endif // defined TARGET_ARCH_X64
OLDNEW
« runtime/vm/intermediate_language.h ('K') | « runtime/vm/intermediate_language.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698