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

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

Issue 10440082: Fix a bug in ia32 shift left , implemented more inlined binary operations in x64. (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
« no previous file with comments | « runtime/vm/flow_graph_optimizer.cc ('k') | runtime/vm/locations.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) 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 "lib/error.h" 8 #include "lib/error.h"
9 #include "vm/flow_graph_compiler.h" 9 #include "vm/flow_graph_compiler.h"
10 #include "vm/locations.h" 10 #include "vm/locations.h"
(...skipping 872 matching lines...) Expand 10 before | Expand all | Expand 10 after
883 return NULL; 883 return NULL;
884 } 884 }
885 885
886 886
887 void CatchEntryComp::EmitNativeCode(FlowGraphCompiler* compiler) { 887 void CatchEntryComp::EmitNativeCode(FlowGraphCompiler* compiler) {
888 UNIMPLEMENTED(); 888 UNIMPLEMENTED();
889 } 889 }
890 890
891 891
892 LocationSummary* BinaryOpComp::MakeLocationSummary() const { 892 LocationSummary* BinaryOpComp::MakeLocationSummary() const {
893 const intptr_t kNumTemps = 1;
894 const intptr_t kNumInputs = 2; 893 const intptr_t kNumInputs = 2;
895 LocationSummary* summary = new LocationSummary(kNumInputs, kNumTemps); 894 if (op_kind() == Token::kTRUNCDIV) {
896 summary->set_in(0, Location::RequiresRegister()); 895 const intptr_t kNumTemps = 3;
897 summary->set_in(1, Location::RequiresRegister()); 896 LocationSummary* summary = new LocationSummary(kNumInputs, kNumTemps);
898 summary->set_out(Location::SameAsFirstInput()); 897 summary->set_in(0, Location::RegisterLocation(RAX));
899 summary->set_temp(0, Location::RequiresRegister()); 898 summary->set_in(1, Location::RegisterLocation(RCX));
900 return summary; 899 summary->set_out(Location::SameAsFirstInput());
900 summary->set_temp(0, Location::RegisterLocation(RBX));
901 // Will be used for for sign extension.
902 summary->set_temp(1, Location::RegisterLocation(RDX));
903 summary->set_temp(2, Location::RequiresRegister());
904 return summary;
905 } else if (op_kind() == Token::kSHR) {
906 const intptr_t kNumTemps = 1;
907 LocationSummary* summary = new LocationSummary(kNumInputs, kNumTemps);
908 summary->set_in(0, Location::RequiresRegister());
909 summary->set_in(1, Location::RegisterLocation(RCX));
910 summary->set_out(Location::SameAsFirstInput());
911 summary->set_temp(0, Location::RequiresRegister());
912 return summary;
913 } else if (op_kind() == Token::kSHL) {
914 const intptr_t kNumTemps = 2;
915 LocationSummary* summary = new LocationSummary(kNumInputs, kNumTemps);
916 summary->set_in(0, Location::RequiresRegister());
917 summary->set_in(1, Location::RequiresRegister());
918 summary->set_out(Location::SameAsFirstInput());
919 summary->set_temp(0, Location::RequiresRegister());
920 summary->set_temp(1, Location::RegisterLocation(RCX));
921 return summary;
922 } else {
923 const intptr_t kNumTemps = 1;
924 LocationSummary* summary = new LocationSummary(kNumInputs, kNumTemps);
925 summary->set_in(0, Location::RequiresRegister());
926 summary->set_in(1, Location::RequiresRegister());
927 summary->set_out(Location::SameAsFirstInput());
928 summary->set_temp(0, Location::RequiresRegister());
929 return summary;
930 }
901 } 931 }
902 932
903 933
904 // TODO(srdjan): Implement variations. 934 // TODO(srdjan): Implement variations.
905 static bool TryEmitSmiBinaryOp(FlowGraphCompiler* compiler, 935 static bool TryEmitSmiBinaryOp(FlowGraphCompiler* compiler,
906 BinaryOpComp* comp) { 936 BinaryOpComp* comp) {
907 ASSERT((comp->ic_data() != NULL)); 937 ASSERT((comp->ic_data() != NULL));
908 const ICData& ic_data = *comp->ic_data(); 938 const ICData& ic_data = *comp->ic_data();
909 if (ic_data.IsNull()) return false; 939 if (ic_data.IsNull()) return false;
910 if (ic_data.num_args_tested() != 2) return false; 940 if (ic_data.num_args_tested() != 2) return false;
911 if (ic_data.NumberOfChecks() != 1) return false; 941 if (ic_data.NumberOfChecks() != 1) return false;
912 Function& target = Function::Handle(); 942 Function& target = Function::Handle();
913 GrowableArray<const Class*> classes; 943 GrowableArray<const Class*> classes;
914 ic_data.GetCheckAt(0, &classes, &target); 944 ic_data.GetCheckAt(0, &classes, &target);
915 const Class& smi_class = 945 const Class& smi_class =
916 Class::Handle(Isolate::Current()->object_store()->smi_class()); 946 Class::Handle(Isolate::Current()->object_store()->smi_class());
917 if ((classes[0]->raw() != smi_class.raw()) || 947 if ((classes[0]->raw() != smi_class.raw()) ||
918 (classes[1]->raw() != smi_class.raw())) { 948 (classes[1]->raw() != smi_class.raw())) {
919 return false; 949 return false;
920 } 950 }
921 // TODO(srdjan): need to allocate a temporary register (now using r10) 951 // TODO(srdjan): need to allocate a temporary register (now using r10)
922 Register left = comp->locs()->in(0).reg(); 952 Register left = comp->locs()->in(0).reg();
923 Register right = comp->locs()->in(1).reg(); 953 Register right = comp->locs()->in(1).reg();
924 Register result = comp->locs()->out().reg(); 954 Register result = comp->locs()->out().reg();
925 Register temp = comp->locs()->temp(0).reg(); 955 Register temp = comp->locs()->temp(0).reg();
956 ASSERT(left == result);
926 Label* deopt = compiler->AddDeoptStub(comp->instance_call()->cid(), 957 Label* deopt = compiler->AddDeoptStub(comp->instance_call()->cid(),
927 comp->instance_call()->token_index(), 958 comp->instance_call()->token_index(),
928 comp->instance_call()->try_index(), 959 comp->instance_call()->try_index(),
929 kDeoptSmiBinaryOp, 960 kDeoptSmiBinaryOp,
930 temp, 961 temp,
931 right); 962 right);
932 __ movq(temp, left); 963 __ movq(temp, left);
933 __ orq(left, right); 964 __ orq(left, right);
934 __ testq(left, Immediate(kSmiTagMask)); 965 __ testq(left, Immediate(kSmiTagMask));
935 __ j(NOT_ZERO, deopt); 966 __ j(NOT_ZERO, deopt);
936 __ movq(left, temp); 967 __ movq(left, temp);
937 switch (comp->op_kind()) { 968 switch (comp->op_kind()) {
938 case Token::kADD: { 969 case Token::kADD: {
939 __ addq(left, right); 970 __ addq(left, right);
940 __ j(OVERFLOW, deopt); 971 __ j(OVERFLOW, deopt);
941 if (result != left) {
942 __ movq(result, left);
943 }
944 break; 972 break;
945 } 973 }
974 case Token::kSUB: {
975 __ subq(left, right);
976 __ j(OVERFLOW, deopt);
977 break;
978 }
979 case Token::kMUL: {
980 __ SmiUntag(left);
981 __ imulq(left, right);
982 __ j(OVERFLOW, deopt);
983 break;
984 }
985 case Token::kBIT_AND: {
986 // No overflow check.
987 __ andq(left, right);
988 break;
989 }
990 case Token::kBIT_OR: {
Florian Schneider 2012/05/30 14:21:12 Maybe also add the same comment as in the BIT_AND
srdjan 2012/05/30 17:03:13 Added it.
991 __ orq(left, right);
992 break;
993 }
994 case Token::kBIT_XOR: {
995 // No overflow check.
996 __ xorq(left, right);
997 break;
998 }
999 case Token::kTRUNCDIV: {
1000 // Handle divide by zero in runtime.
1001 // Deoptimization requires that temp and right are preserved.
1002 __ testq(right, right);
1003 __ j(ZERO, deopt);
1004 ASSERT(left == RAX);
1005 ASSERT((right != RDX) && (right != RAX));
1006 ASSERT((temp != RDX) && (temp != RAX));
1007 ASSERT(comp->locs()->temp(1).reg() == RDX);
1008 ASSERT(result == RAX);
1009 Register right_temp = comp->locs()->temp(2).reg();
1010 __ movq(right_temp, right);
1011 __ SmiUntag(left);
1012 __ SmiUntag(right_temp);
1013 __ cqo(); // Sign extend RAX -> RDX:RAX.
1014 __ idivq(right_temp); // RAX: quotient, RDX: remainder.
1015 // Check the corner case of dividing the 'MIN_SMI' with -1, in which
1016 // case we cannot tag the result.
1017 __ cmpq(result, Immediate(0x4000000000000000));
1018 __ j(EQUAL, deopt);
1019 __ SmiTag(result);
1020 break;
1021 }
1022 case Token::kDIV: {
1023 // Dispatches to 'Double./'.
1024 // TODO(srdjan): Implement as conversion to double and double division.
1025 return false;
1026 }
1027 case Token::kMOD: {
1028 // TODO(srdjan): Implement.
1029 return false;
1030 }
1031 case Token::kSHR: {
1032 const Immediate kCountLimit = Immediate(0x1F);
1033 __ cmpq(right, Immediate(0));
1034 __ j(LESS, deopt);
1035 __ SmiUntag(right);
1036 __ cmpq(right, kCountLimit);
1037 Label count_ok;
1038 __ j(LESS, &count_ok, Assembler::kNearJump);
1039 __ movq(right, kCountLimit);
1040 __ Bind(&count_ok);
1041 ASSERT(right == RCX); // Count must be in ECX
1042 __ SmiUntag(left);
1043 __ sarq(left, right);
1044 __ SmiTag(left);
1045 break;
1046 }
1047 case Token::kSHL: {
1048 // Check if count too large for handling it inlined.
1049 __ cmpq(right,
1050 Immediate(reinterpret_cast<int64_t>(Smi::New(Smi::kBits))));
1051 __ j(ABOVE_EQUAL, deopt);
1052 Register right_temp = comp->locs()->temp(1).reg();
1053 ASSERT(right_temp == RCX); // Count must be in RCX
1054 __ movq(right_temp, right);
1055 __ SmiUntag(right_temp);
1056 // Overflow test (preserve temp and right);
1057 __ shlq(left, right_temp);
1058 __ sarq(left, right_temp);
1059 __ cmpq(left, temp);
1060 __ j(NOT_EQUAL, deopt); // Overflow.
1061 // Shift for result now we know there is no overflow.
1062 __ shlq(left, right_temp);
1063 break;
1064 }
1065 case Token::kOR:
1066 case Token::kAND: {
1067 // Flow graph builder has dissected this operation to guarantee correct
1068 // behavior (short-circuit evaluation).
1069 UNREACHABLE();
1070 }
946 default: 1071 default:
947 UNREACHABLE(); 1072 // Not implemented.
1073 return false;
948 } 1074 }
949 return true; 1075 return true;
950 } 1076 }
951 1077
952 void BinaryOpComp::EmitNativeCode(FlowGraphCompiler* compiler) { 1078 void BinaryOpComp::EmitNativeCode(FlowGraphCompiler* compiler) {
953 if (TryEmitSmiBinaryOp(compiler, this)) { 1079 if (TryEmitSmiBinaryOp(compiler, this)) {
954 // Operation inlined. 1080 // Operation inlined.
955 return; 1081 return;
956 } 1082 }
957 // TODO(srdjan): Remove this code once BinaryOpComp has been implemeneted 1083 // TODO(srdjan): Remove this code once BinaryOpComp has been implemeneted
958 // for all intended operations. 1084 // for all intended operations.
959 Register left = locs()->in(0).reg(); 1085 Register left = locs()->in(0).reg();
960 Register right = locs()->in(1).reg(); 1086 Register right = locs()->in(1).reg();
961 __ pushq(left); 1087 __ pushq(left);
962 __ pushq(right); 1088 __ pushq(right);
963 InstanceCallComp* instance_call_comp = instance_call(); 1089 InstanceCallComp* instance_call_comp = instance_call();
964 instance_call_comp->EmitNativeCode(compiler); 1090 instance_call_comp->EmitNativeCode(compiler);
965 if (locs()->out().reg() != RAX) { 1091 if (locs()->out().reg() != RAX) {
966 __ movq(locs()->out().reg(), RAX); 1092 __ movq(locs()->out().reg(), RAX);
967 } 1093 }
968 } 1094 }
969 1095
970 } // namespace dart 1096 } // namespace dart
971 1097
972 #undef __ 1098 #undef __
973 1099
974 #endif // defined TARGET_ARCH_X64 1100 #endif // defined TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph_optimizer.cc ('k') | runtime/vm/locations.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698