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

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 970 matching lines...) Expand 10 before | Expand all | Expand 10 after
981 ASSERT(!exception_var().is_captured()); 981 ASSERT(!exception_var().is_captured());
982 ASSERT(!stacktrace_var().is_captured()); 982 ASSERT(!stacktrace_var().is_captured());
983 __ movq(Address(RBP, exception_var().index() * kWordSize), 983 __ movq(Address(RBP, exception_var().index() * kWordSize),
984 kExceptionObjectReg); 984 kExceptionObjectReg);
985 __ movq(Address(RBP, stacktrace_var().index() * kWordSize), 985 __ movq(Address(RBP, stacktrace_var().index() * kWordSize),
986 kStackTraceObjectReg); 986 kStackTraceObjectReg);
987 } 987 }
988 988
989 989
990 LocationSummary* BinaryOpComp::MakeLocationSummary() const { 990 LocationSummary* BinaryOpComp::MakeLocationSummary() const {
991 const intptr_t kNumTemps = 1;
992 const intptr_t kNumInputs = 2; 991 const intptr_t kNumInputs = 2;
993 LocationSummary* summary = new LocationSummary(kNumInputs, kNumTemps); 992 if (op_kind() == Token::kTRUNCDIV) {
994 summary->set_in(0, Location::RequiresRegister()); 993 const intptr_t kNumTemps = 3;
995 summary->set_in(1, Location::RequiresRegister()); 994 LocationSummary* summary = new LocationSummary(kNumInputs, kNumTemps);
996 summary->set_out(Location::SameAsFirstInput()); 995 summary->set_in(0, Location::RegisterLocation(RAX));
997 summary->set_temp(0, Location::RequiresRegister()); 996 summary->set_in(1, Location::RegisterLocation(RCX));
998 return summary; 997 summary->set_out(Location::SameAsFirstInput());
998 summary->set_temp(0, Location::RegisterLocation(RBX));
999 // Will be used for for sign extension.
1000 summary->set_temp(1, Location::RegisterLocation(RDX));
1001 summary->set_temp(2, Location::RequiresRegister());
1002 return summary;
1003 } else if (op_kind() == Token::kSHR) {
1004 const intptr_t kNumTemps = 1;
1005 LocationSummary* summary = new LocationSummary(kNumInputs, kNumTemps);
1006 summary->set_in(0, Location::RequiresRegister());
1007 summary->set_in(1, Location::RegisterLocation(RCX));
1008 summary->set_out(Location::SameAsFirstInput());
1009 summary->set_temp(0, Location::RequiresRegister());
1010 return summary;
1011 } else if (op_kind() == Token::kSHL) {
1012 const intptr_t kNumTemps = 2;
1013 LocationSummary* summary = new LocationSummary(kNumInputs, kNumTemps);
1014 summary->set_in(0, Location::RequiresRegister());
1015 summary->set_in(1, Location::RequiresRegister());
1016 summary->set_out(Location::SameAsFirstInput());
1017 summary->set_temp(0, Location::RequiresRegister());
1018 summary->set_temp(1, Location::RegisterLocation(RCX));
1019 return summary;
1020 } else {
1021 const intptr_t kNumTemps = 1;
1022 LocationSummary* summary = new LocationSummary(kNumInputs, kNumTemps);
1023 summary->set_in(0, Location::RequiresRegister());
1024 summary->set_in(1, Location::RequiresRegister());
1025 summary->set_out(Location::SameAsFirstInput());
1026 summary->set_temp(0, Location::RequiresRegister());
1027 return summary;
1028 }
999 } 1029 }
1000 1030
1001 1031
1002 // TODO(srdjan): Implement variations. 1032 // TODO(srdjan): Implement variations.
1003 static bool TryEmitSmiBinaryOp(FlowGraphCompiler* compiler, 1033 static bool TryEmitSmiBinaryOp(FlowGraphCompiler* compiler,
1004 BinaryOpComp* comp) { 1034 BinaryOpComp* comp) {
1005 ASSERT((comp->ic_data() != NULL)); 1035 ASSERT((comp->ic_data() != NULL));
1006 const ICData& ic_data = *comp->ic_data(); 1036 const ICData& ic_data = *comp->ic_data();
1007 if (ic_data.IsNull()) return false; 1037 if (ic_data.IsNull()) return false;
1008 if (ic_data.num_args_tested() != 2) return false; 1038 if (ic_data.num_args_tested() != 2) return false;
1009 if (ic_data.NumberOfChecks() != 1) return false; 1039 if (ic_data.NumberOfChecks() != 1) return false;
1010 Function& target = Function::Handle(); 1040 Function& target = Function::Handle();
1011 GrowableArray<const Class*> classes; 1041 GrowableArray<const Class*> classes;
1012 ic_data.GetCheckAt(0, &classes, &target); 1042 ic_data.GetCheckAt(0, &classes, &target);
1013 const Class& smi_class = 1043 const Class& smi_class =
1014 Class::Handle(Isolate::Current()->object_store()->smi_class()); 1044 Class::Handle(Isolate::Current()->object_store()->smi_class());
1015 if ((classes[0]->raw() != smi_class.raw()) || 1045 if ((classes[0]->raw() != smi_class.raw()) ||
1016 (classes[1]->raw() != smi_class.raw())) { 1046 (classes[1]->raw() != smi_class.raw())) {
1017 return false; 1047 return false;
1018 } 1048 }
1019 // TODO(srdjan): need to allocate a temporary register (now using r10) 1049 // TODO(srdjan): need to allocate a temporary register (now using r10)
1020 Register left = comp->locs()->in(0).reg(); 1050 Register left = comp->locs()->in(0).reg();
1021 Register right = comp->locs()->in(1).reg(); 1051 Register right = comp->locs()->in(1).reg();
1022 Register result = comp->locs()->out().reg(); 1052 Register result = comp->locs()->out().reg();
1023 Register temp = comp->locs()->temp(0).reg(); 1053 Register temp = comp->locs()->temp(0).reg();
1054 ASSERT(left == result);
1024 Label* deopt = compiler->AddDeoptStub(comp->instance_call()->cid(), 1055 Label* deopt = compiler->AddDeoptStub(comp->instance_call()->cid(),
1025 comp->instance_call()->token_index(), 1056 comp->instance_call()->token_index(),
1026 comp->instance_call()->try_index(), 1057 comp->instance_call()->try_index(),
1027 kDeoptSmiBinaryOp, 1058 kDeoptSmiBinaryOp,
1028 temp, 1059 temp,
1029 right); 1060 right);
1030 __ movq(temp, left); 1061 __ movq(temp, left);
1031 __ orq(left, right); 1062 __ orq(left, right);
1032 __ testq(left, Immediate(kSmiTagMask)); 1063 __ testq(left, Immediate(kSmiTagMask));
1033 __ j(NOT_ZERO, deopt); 1064 __ j(NOT_ZERO, deopt);
1034 __ movq(left, temp); 1065 __ movq(left, temp);
1035 switch (comp->op_kind()) { 1066 switch (comp->op_kind()) {
1036 case Token::kADD: { 1067 case Token::kADD: {
1037 __ addq(left, right); 1068 __ addq(left, right);
1038 __ j(OVERFLOW, deopt); 1069 __ j(OVERFLOW, deopt);
1039 if (result != left) {
1040 __ movq(result, left);
1041 }
1042 break; 1070 break;
1043 } 1071 }
1072 case Token::kSUB: {
1073 __ subq(left, right);
1074 __ j(OVERFLOW, deopt);
1075 break;
1076 }
1077 case Token::kMUL: {
1078 __ SmiUntag(left);
1079 __ imulq(left, right);
1080 __ j(OVERFLOW, deopt);
1081 break;
1082 }
1083 case Token::kBIT_AND: {
1084 // No overflow check.
1085 __ andq(left, right);
1086 break;
1087 }
1088 case Token::kBIT_OR: {
1089 // No overflow check.
1090 __ orq(left, right);
1091 break;
1092 }
1093 case Token::kBIT_XOR: {
1094 // No overflow check.
1095 __ xorq(left, right);
1096 break;
1097 }
1098 case Token::kTRUNCDIV: {
1099 // Handle divide by zero in runtime.
1100 // Deoptimization requires that temp and right are preserved.
1101 __ testq(right, right);
1102 __ j(ZERO, deopt);
1103 ASSERT(left == RAX);
1104 ASSERT((right != RDX) && (right != RAX));
1105 ASSERT((temp != RDX) && (temp != RAX));
1106 ASSERT(comp->locs()->temp(1).reg() == RDX);
1107 ASSERT(result == RAX);
1108 Register right_temp = comp->locs()->temp(2).reg();
1109 __ movq(right_temp, right);
1110 __ SmiUntag(left);
1111 __ SmiUntag(right_temp);
1112 __ cqo(); // Sign extend RAX -> RDX:RAX.
1113 __ idivq(right_temp); // RAX: quotient, RDX: remainder.
1114 // Check the corner case of dividing the 'MIN_SMI' with -1, in which
1115 // case we cannot tag the result.
1116 __ cmpq(result, Immediate(0x4000000000000000));
1117 __ j(EQUAL, deopt);
1118 __ SmiTag(result);
1119 break;
1120 }
1121 case Token::kDIV: {
1122 // Dispatches to 'Double./'.
1123 // TODO(srdjan): Implement as conversion to double and double division.
1124 return false;
1125 }
1126 case Token::kMOD: {
1127 // TODO(srdjan): Implement.
1128 return false;
1129 }
1130 case Token::kSHR: {
1131 const Immediate kCountLimit = Immediate(0x1F);
1132 __ cmpq(right, Immediate(0));
1133 __ j(LESS, deopt);
1134 __ SmiUntag(right);
1135 __ cmpq(right, kCountLimit);
1136 Label count_ok;
1137 __ j(LESS, &count_ok, Assembler::kNearJump);
1138 __ movq(right, kCountLimit);
1139 __ Bind(&count_ok);
1140 ASSERT(right == RCX); // Count must be in ECX
1141 __ SmiUntag(left);
1142 __ sarq(left, right);
1143 __ SmiTag(left);
1144 break;
1145 }
1146 case Token::kSHL: {
1147 // Check if count too large for handling it inlined.
1148 __ cmpq(right,
1149 Immediate(reinterpret_cast<int64_t>(Smi::New(Smi::kBits))));
1150 __ j(ABOVE_EQUAL, deopt);
1151 Register right_temp = comp->locs()->temp(1).reg();
1152 ASSERT(right_temp == RCX); // Count must be in RCX
1153 __ movq(right_temp, right);
1154 __ SmiUntag(right_temp);
1155 // Overflow test (preserve temp and right);
1156 __ shlq(left, right_temp);
1157 __ sarq(left, right_temp);
1158 __ cmpq(left, temp);
1159 __ j(NOT_EQUAL, deopt); // Overflow.
1160 // Shift for result now we know there is no overflow.
1161 __ shlq(left, right_temp);
1162 break;
1163 }
1164 case Token::kOR:
1165 case Token::kAND: {
1166 // Flow graph builder has dissected this operation to guarantee correct
1167 // behavior (short-circuit evaluation).
1168 UNREACHABLE();
1169 return false;
1170 }
1044 default: 1171 default:
1045 UNREACHABLE(); 1172 UNREACHABLE();
1173 return false;
1046 } 1174 }
1047 return true; 1175 return true;
1048 } 1176 }
1049 1177
1050 void BinaryOpComp::EmitNativeCode(FlowGraphCompiler* compiler) { 1178 void BinaryOpComp::EmitNativeCode(FlowGraphCompiler* compiler) {
1051 if (TryEmitSmiBinaryOp(compiler, this)) { 1179 if (TryEmitSmiBinaryOp(compiler, this)) {
1052 // Operation inlined. 1180 // Operation inlined.
1053 return; 1181 return;
1054 } 1182 }
1055 // TODO(srdjan): Remove this code once BinaryOpComp has been implemeneted 1183 // TODO(srdjan): Remove this code once BinaryOpComp has been implemeneted
1056 // for all intended operations. 1184 // for all intended operations.
1057 Register left = locs()->in(0).reg(); 1185 Register left = locs()->in(0).reg();
1058 Register right = locs()->in(1).reg(); 1186 Register right = locs()->in(1).reg();
1059 __ pushq(left); 1187 __ pushq(left);
1060 __ pushq(right); 1188 __ pushq(right);
1061 InstanceCallComp* instance_call_comp = instance_call(); 1189 InstanceCallComp* instance_call_comp = instance_call();
1062 instance_call_comp->EmitNativeCode(compiler); 1190 instance_call_comp->EmitNativeCode(compiler);
1063 if (locs()->out().reg() != RAX) { 1191 if (locs()->out().reg() != RAX) {
1064 __ movq(locs()->out().reg(), RAX); 1192 __ movq(locs()->out().reg(), RAX);
1065 } 1193 }
1066 } 1194 }
1067 1195
1068 } // namespace dart 1196 } // namespace dart
1069 1197
1070 #undef __ 1198 #undef __
1071 1199
1072 #endif // defined TARGET_ARCH_X64 1200 #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