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

Side by Side Diff: src/ia32/lithium-codegen-ia32.cc

Issue 591393002: Made the detailed reason for deopts mandatory on ia32. Unified and improved things. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 6 years, 3 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 | « src/ia32/lithium-codegen-ia32.h ('k') | src/ia32/macro-assembler-ia32.h » ('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 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/v8.h" 5 #include "src/v8.h"
6 6
7 #if V8_TARGET_ARCH_IA32 7 #if V8_TARGET_ARCH_IA32
8 8
9 #include "src/base/bits.h" 9 #include "src/base/bits.h"
10 #include "src/code-factory.h" 10 #include "src/code-factory.h"
(...skipping 1103 matching lines...) Expand 10 before | Expand all | Expand 10 after
1114 int32_t mask = divisor < 0 ? -(divisor + 1) : (divisor - 1); 1114 int32_t mask = divisor < 0 ? -(divisor + 1) : (divisor - 1);
1115 Label dividend_is_not_negative, done; 1115 Label dividend_is_not_negative, done;
1116 if (hmod->CheckFlag(HValue::kLeftCanBeNegative)) { 1116 if (hmod->CheckFlag(HValue::kLeftCanBeNegative)) {
1117 __ test(dividend, dividend); 1117 __ test(dividend, dividend);
1118 __ j(not_sign, &dividend_is_not_negative, Label::kNear); 1118 __ j(not_sign, &dividend_is_not_negative, Label::kNear);
1119 // Note that this is correct even for kMinInt operands. 1119 // Note that this is correct even for kMinInt operands.
1120 __ neg(dividend); 1120 __ neg(dividend);
1121 __ and_(dividend, mask); 1121 __ and_(dividend, mask);
1122 __ neg(dividend); 1122 __ neg(dividend);
1123 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { 1123 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
1124 DeoptimizeIf(zero, instr); 1124 DeoptimizeIf(zero, instr, "minus zero");
1125 } 1125 }
1126 __ jmp(&done, Label::kNear); 1126 __ jmp(&done, Label::kNear);
1127 } 1127 }
1128 1128
1129 __ bind(&dividend_is_not_negative); 1129 __ bind(&dividend_is_not_negative);
1130 __ and_(dividend, mask); 1130 __ and_(dividend, mask);
1131 __ bind(&done); 1131 __ bind(&done);
1132 } 1132 }
1133 1133
1134 1134
1135 void LCodeGen::DoModByConstI(LModByConstI* instr) { 1135 void LCodeGen::DoModByConstI(LModByConstI* instr) {
1136 Register dividend = ToRegister(instr->dividend()); 1136 Register dividend = ToRegister(instr->dividend());
1137 int32_t divisor = instr->divisor(); 1137 int32_t divisor = instr->divisor();
1138 DCHECK(ToRegister(instr->result()).is(eax)); 1138 DCHECK(ToRegister(instr->result()).is(eax));
1139 1139
1140 if (divisor == 0) { 1140 if (divisor == 0) {
1141 DeoptimizeIf(no_condition, instr); 1141 DeoptimizeIf(no_condition, instr, "division by zero");
1142 return; 1142 return;
1143 } 1143 }
1144 1144
1145 __ TruncatingDiv(dividend, Abs(divisor)); 1145 __ TruncatingDiv(dividend, Abs(divisor));
1146 __ imul(edx, edx, Abs(divisor)); 1146 __ imul(edx, edx, Abs(divisor));
1147 __ mov(eax, dividend); 1147 __ mov(eax, dividend);
1148 __ sub(eax, edx); 1148 __ sub(eax, edx);
1149 1149
1150 // Check for negative zero. 1150 // Check for negative zero.
1151 HMod* hmod = instr->hydrogen(); 1151 HMod* hmod = instr->hydrogen();
1152 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { 1152 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
1153 Label remainder_not_zero; 1153 Label remainder_not_zero;
1154 __ j(not_zero, &remainder_not_zero, Label::kNear); 1154 __ j(not_zero, &remainder_not_zero, Label::kNear);
1155 __ cmp(dividend, Immediate(0)); 1155 __ cmp(dividend, Immediate(0));
1156 DeoptimizeIf(less, instr); 1156 DeoptimizeIf(less, instr, "minus zero");
1157 __ bind(&remainder_not_zero); 1157 __ bind(&remainder_not_zero);
1158 } 1158 }
1159 } 1159 }
1160 1160
1161 1161
1162 void LCodeGen::DoModI(LModI* instr) { 1162 void LCodeGen::DoModI(LModI* instr) {
1163 HMod* hmod = instr->hydrogen(); 1163 HMod* hmod = instr->hydrogen();
1164 1164
1165 Register left_reg = ToRegister(instr->left()); 1165 Register left_reg = ToRegister(instr->left());
1166 DCHECK(left_reg.is(eax)); 1166 DCHECK(left_reg.is(eax));
1167 Register right_reg = ToRegister(instr->right()); 1167 Register right_reg = ToRegister(instr->right());
1168 DCHECK(!right_reg.is(eax)); 1168 DCHECK(!right_reg.is(eax));
1169 DCHECK(!right_reg.is(edx)); 1169 DCHECK(!right_reg.is(edx));
1170 Register result_reg = ToRegister(instr->result()); 1170 Register result_reg = ToRegister(instr->result());
1171 DCHECK(result_reg.is(edx)); 1171 DCHECK(result_reg.is(edx));
1172 1172
1173 Label done; 1173 Label done;
1174 // Check for x % 0, idiv would signal a divide error. We have to 1174 // Check for x % 0, idiv would signal a divide error. We have to
1175 // deopt in this case because we can't return a NaN. 1175 // deopt in this case because we can't return a NaN.
1176 if (hmod->CheckFlag(HValue::kCanBeDivByZero)) { 1176 if (hmod->CheckFlag(HValue::kCanBeDivByZero)) {
1177 __ test(right_reg, Operand(right_reg)); 1177 __ test(right_reg, Operand(right_reg));
1178 DeoptimizeIf(zero, instr); 1178 DeoptimizeIf(zero, instr, "division by zero");
1179 } 1179 }
1180 1180
1181 // Check for kMinInt % -1, idiv would signal a divide error. We 1181 // Check for kMinInt % -1, idiv would signal a divide error. We
1182 // have to deopt if we care about -0, because we can't return that. 1182 // have to deopt if we care about -0, because we can't return that.
1183 if (hmod->CheckFlag(HValue::kCanOverflow)) { 1183 if (hmod->CheckFlag(HValue::kCanOverflow)) {
1184 Label no_overflow_possible; 1184 Label no_overflow_possible;
1185 __ cmp(left_reg, kMinInt); 1185 __ cmp(left_reg, kMinInt);
1186 __ j(not_equal, &no_overflow_possible, Label::kNear); 1186 __ j(not_equal, &no_overflow_possible, Label::kNear);
1187 __ cmp(right_reg, -1); 1187 __ cmp(right_reg, -1);
1188 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { 1188 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
1189 DeoptimizeIf(equal, instr); 1189 DeoptimizeIf(equal, instr, "minus zero");
1190 } else { 1190 } else {
1191 __ j(not_equal, &no_overflow_possible, Label::kNear); 1191 __ j(not_equal, &no_overflow_possible, Label::kNear);
1192 __ Move(result_reg, Immediate(0)); 1192 __ Move(result_reg, Immediate(0));
1193 __ jmp(&done, Label::kNear); 1193 __ jmp(&done, Label::kNear);
1194 } 1194 }
1195 __ bind(&no_overflow_possible); 1195 __ bind(&no_overflow_possible);
1196 } 1196 }
1197 1197
1198 // Sign extend dividend in eax into edx:eax. 1198 // Sign extend dividend in eax into edx:eax.
1199 __ cdq(); 1199 __ cdq();
1200 1200
1201 // If we care about -0, test if the dividend is <0 and the result is 0. 1201 // If we care about -0, test if the dividend is <0 and the result is 0.
1202 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { 1202 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
1203 Label positive_left; 1203 Label positive_left;
1204 __ test(left_reg, Operand(left_reg)); 1204 __ test(left_reg, Operand(left_reg));
1205 __ j(not_sign, &positive_left, Label::kNear); 1205 __ j(not_sign, &positive_left, Label::kNear);
1206 __ idiv(right_reg); 1206 __ idiv(right_reg);
1207 __ test(result_reg, Operand(result_reg)); 1207 __ test(result_reg, Operand(result_reg));
1208 DeoptimizeIf(zero, instr); 1208 DeoptimizeIf(zero, instr, "minus zero");
1209 __ jmp(&done, Label::kNear); 1209 __ jmp(&done, Label::kNear);
1210 __ bind(&positive_left); 1210 __ bind(&positive_left);
1211 } 1211 }
1212 __ idiv(right_reg); 1212 __ idiv(right_reg);
1213 __ bind(&done); 1213 __ bind(&done);
1214 } 1214 }
1215 1215
1216 1216
1217 void LCodeGen::DoDivByPowerOf2I(LDivByPowerOf2I* instr) { 1217 void LCodeGen::DoDivByPowerOf2I(LDivByPowerOf2I* instr) {
1218 Register dividend = ToRegister(instr->dividend()); 1218 Register dividend = ToRegister(instr->dividend());
1219 int32_t divisor = instr->divisor(); 1219 int32_t divisor = instr->divisor();
1220 Register result = ToRegister(instr->result()); 1220 Register result = ToRegister(instr->result());
1221 DCHECK(divisor == kMinInt || base::bits::IsPowerOfTwo32(Abs(divisor))); 1221 DCHECK(divisor == kMinInt || base::bits::IsPowerOfTwo32(Abs(divisor)));
1222 DCHECK(!result.is(dividend)); 1222 DCHECK(!result.is(dividend));
1223 1223
1224 // Check for (0 / -x) that will produce negative zero. 1224 // Check for (0 / -x) that will produce negative zero.
1225 HDiv* hdiv = instr->hydrogen(); 1225 HDiv* hdiv = instr->hydrogen();
1226 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) { 1226 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) {
1227 __ test(dividend, dividend); 1227 __ test(dividend, dividend);
1228 DeoptimizeIf(zero, instr); 1228 DeoptimizeIf(zero, instr, "minus zero");
1229 } 1229 }
1230 // Check for (kMinInt / -1). 1230 // Check for (kMinInt / -1).
1231 if (hdiv->CheckFlag(HValue::kCanOverflow) && divisor == -1) { 1231 if (hdiv->CheckFlag(HValue::kCanOverflow) && divisor == -1) {
1232 __ cmp(dividend, kMinInt); 1232 __ cmp(dividend, kMinInt);
1233 DeoptimizeIf(zero, instr); 1233 DeoptimizeIf(zero, instr, "overflow");
1234 } 1234 }
1235 // Deoptimize if remainder will not be 0. 1235 // Deoptimize if remainder will not be 0.
1236 if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32) && 1236 if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32) &&
1237 divisor != 1 && divisor != -1) { 1237 divisor != 1 && divisor != -1) {
1238 int32_t mask = divisor < 0 ? -(divisor + 1) : (divisor - 1); 1238 int32_t mask = divisor < 0 ? -(divisor + 1) : (divisor - 1);
1239 __ test(dividend, Immediate(mask)); 1239 __ test(dividend, Immediate(mask));
1240 DeoptimizeIf(not_zero, instr); 1240 DeoptimizeIf(not_zero, instr, "lost precision");
1241 } 1241 }
1242 __ Move(result, dividend); 1242 __ Move(result, dividend);
1243 int32_t shift = WhichPowerOf2Abs(divisor); 1243 int32_t shift = WhichPowerOf2Abs(divisor);
1244 if (shift > 0) { 1244 if (shift > 0) {
1245 // The arithmetic shift is always OK, the 'if' is an optimization only. 1245 // The arithmetic shift is always OK, the 'if' is an optimization only.
1246 if (shift > 1) __ sar(result, 31); 1246 if (shift > 1) __ sar(result, 31);
1247 __ shr(result, 32 - shift); 1247 __ shr(result, 32 - shift);
1248 __ add(result, dividend); 1248 __ add(result, dividend);
1249 __ sar(result, shift); 1249 __ sar(result, shift);
1250 } 1250 }
1251 if (divisor < 0) __ neg(result); 1251 if (divisor < 0) __ neg(result);
1252 } 1252 }
1253 1253
1254 1254
1255 void LCodeGen::DoDivByConstI(LDivByConstI* instr) { 1255 void LCodeGen::DoDivByConstI(LDivByConstI* instr) {
1256 Register dividend = ToRegister(instr->dividend()); 1256 Register dividend = ToRegister(instr->dividend());
1257 int32_t divisor = instr->divisor(); 1257 int32_t divisor = instr->divisor();
1258 DCHECK(ToRegister(instr->result()).is(edx)); 1258 DCHECK(ToRegister(instr->result()).is(edx));
1259 1259
1260 if (divisor == 0) { 1260 if (divisor == 0) {
1261 DeoptimizeIf(no_condition, instr); 1261 DeoptimizeIf(no_condition, instr, "division by zero");
1262 return; 1262 return;
1263 } 1263 }
1264 1264
1265 // Check for (0 / -x) that will produce negative zero. 1265 // Check for (0 / -x) that will produce negative zero.
1266 HDiv* hdiv = instr->hydrogen(); 1266 HDiv* hdiv = instr->hydrogen();
1267 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) { 1267 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) {
1268 __ test(dividend, dividend); 1268 __ test(dividend, dividend);
1269 DeoptimizeIf(zero, instr); 1269 DeoptimizeIf(zero, instr, "minus zero");
1270 } 1270 }
1271 1271
1272 __ TruncatingDiv(dividend, Abs(divisor)); 1272 __ TruncatingDiv(dividend, Abs(divisor));
1273 if (divisor < 0) __ neg(edx); 1273 if (divisor < 0) __ neg(edx);
1274 1274
1275 if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32)) { 1275 if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32)) {
1276 __ mov(eax, edx); 1276 __ mov(eax, edx);
1277 __ imul(eax, eax, divisor); 1277 __ imul(eax, eax, divisor);
1278 __ sub(eax, dividend); 1278 __ sub(eax, dividend);
1279 DeoptimizeIf(not_equal, instr); 1279 DeoptimizeIf(not_equal, instr, "lost precision");
1280 } 1280 }
1281 } 1281 }
1282 1282
1283 1283
1284 // TODO(svenpanne) Refactor this to avoid code duplication with DoFlooringDivI. 1284 // TODO(svenpanne) Refactor this to avoid code duplication with DoFlooringDivI.
1285 void LCodeGen::DoDivI(LDivI* instr) { 1285 void LCodeGen::DoDivI(LDivI* instr) {
1286 HBinaryOperation* hdiv = instr->hydrogen(); 1286 HBinaryOperation* hdiv = instr->hydrogen();
1287 Register dividend = ToRegister(instr->dividend()); 1287 Register dividend = ToRegister(instr->dividend());
1288 Register divisor = ToRegister(instr->divisor()); 1288 Register divisor = ToRegister(instr->divisor());
1289 Register remainder = ToRegister(instr->temp()); 1289 Register remainder = ToRegister(instr->temp());
1290 DCHECK(dividend.is(eax)); 1290 DCHECK(dividend.is(eax));
1291 DCHECK(remainder.is(edx)); 1291 DCHECK(remainder.is(edx));
1292 DCHECK(ToRegister(instr->result()).is(eax)); 1292 DCHECK(ToRegister(instr->result()).is(eax));
1293 DCHECK(!divisor.is(eax)); 1293 DCHECK(!divisor.is(eax));
1294 DCHECK(!divisor.is(edx)); 1294 DCHECK(!divisor.is(edx));
1295 1295
1296 // Check for x / 0. 1296 // Check for x / 0.
1297 if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) { 1297 if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) {
1298 __ test(divisor, divisor); 1298 __ test(divisor, divisor);
1299 DeoptimizeIf(zero, instr); 1299 DeoptimizeIf(zero, instr, "division by zero");
1300 } 1300 }
1301 1301
1302 // Check for (0 / -x) that will produce negative zero. 1302 // Check for (0 / -x) that will produce negative zero.
1303 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) { 1303 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) {
1304 Label dividend_not_zero; 1304 Label dividend_not_zero;
1305 __ test(dividend, dividend); 1305 __ test(dividend, dividend);
1306 __ j(not_zero, &dividend_not_zero, Label::kNear); 1306 __ j(not_zero, &dividend_not_zero, Label::kNear);
1307 __ test(divisor, divisor); 1307 __ test(divisor, divisor);
1308 DeoptimizeIf(sign, instr); 1308 DeoptimizeIf(sign, instr, "minus zero");
1309 __ bind(&dividend_not_zero); 1309 __ bind(&dividend_not_zero);
1310 } 1310 }
1311 1311
1312 // Check for (kMinInt / -1). 1312 // Check for (kMinInt / -1).
1313 if (hdiv->CheckFlag(HValue::kCanOverflow)) { 1313 if (hdiv->CheckFlag(HValue::kCanOverflow)) {
1314 Label dividend_not_min_int; 1314 Label dividend_not_min_int;
1315 __ cmp(dividend, kMinInt); 1315 __ cmp(dividend, kMinInt);
1316 __ j(not_zero, &dividend_not_min_int, Label::kNear); 1316 __ j(not_zero, &dividend_not_min_int, Label::kNear);
1317 __ cmp(divisor, -1); 1317 __ cmp(divisor, -1);
1318 DeoptimizeIf(zero, instr); 1318 DeoptimizeIf(zero, instr, "overflow");
1319 __ bind(&dividend_not_min_int); 1319 __ bind(&dividend_not_min_int);
1320 } 1320 }
1321 1321
1322 // Sign extend to edx (= remainder). 1322 // Sign extend to edx (= remainder).
1323 __ cdq(); 1323 __ cdq();
1324 __ idiv(divisor); 1324 __ idiv(divisor);
1325 1325
1326 if (!hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) { 1326 if (!hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) {
1327 // Deoptimize if remainder is not 0. 1327 // Deoptimize if remainder is not 0.
1328 __ test(remainder, remainder); 1328 __ test(remainder, remainder);
1329 DeoptimizeIf(not_zero, instr); 1329 DeoptimizeIf(not_zero, instr, "lost precision");
1330 } 1330 }
1331 } 1331 }
1332 1332
1333 1333
1334 void LCodeGen::DoFlooringDivByPowerOf2I(LFlooringDivByPowerOf2I* instr) { 1334 void LCodeGen::DoFlooringDivByPowerOf2I(LFlooringDivByPowerOf2I* instr) {
1335 Register dividend = ToRegister(instr->dividend()); 1335 Register dividend = ToRegister(instr->dividend());
1336 int32_t divisor = instr->divisor(); 1336 int32_t divisor = instr->divisor();
1337 DCHECK(dividend.is(ToRegister(instr->result()))); 1337 DCHECK(dividend.is(ToRegister(instr->result())));
1338 1338
1339 // If the divisor is positive, things are easy: There can be no deopts and we 1339 // If the divisor is positive, things are easy: There can be no deopts and we
1340 // can simply do an arithmetic right shift. 1340 // can simply do an arithmetic right shift.
1341 if (divisor == 1) return; 1341 if (divisor == 1) return;
1342 int32_t shift = WhichPowerOf2Abs(divisor); 1342 int32_t shift = WhichPowerOf2Abs(divisor);
1343 if (divisor > 1) { 1343 if (divisor > 1) {
1344 __ sar(dividend, shift); 1344 __ sar(dividend, shift);
1345 return; 1345 return;
1346 } 1346 }
1347 1347
1348 // If the divisor is negative, we have to negate and handle edge cases. 1348 // If the divisor is negative, we have to negate and handle edge cases.
1349 __ neg(dividend); 1349 __ neg(dividend);
1350 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 1350 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
1351 DeoptimizeIf(zero, instr); 1351 DeoptimizeIf(zero, instr, "minus zero");
1352 } 1352 }
1353 1353
1354 // Dividing by -1 is basically negation, unless we overflow. 1354 // Dividing by -1 is basically negation, unless we overflow.
1355 if (divisor == -1) { 1355 if (divisor == -1) {
1356 if (instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) { 1356 if (instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) {
1357 DeoptimizeIf(overflow, instr); 1357 DeoptimizeIf(overflow, instr, "overflow");
1358 } 1358 }
1359 return; 1359 return;
1360 } 1360 }
1361 1361
1362 // If the negation could not overflow, simply shifting is OK. 1362 // If the negation could not overflow, simply shifting is OK.
1363 if (!instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) { 1363 if (!instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) {
1364 __ sar(dividend, shift); 1364 __ sar(dividend, shift);
1365 return; 1365 return;
1366 } 1366 }
1367 1367
1368 Label not_kmin_int, done; 1368 Label not_kmin_int, done;
1369 __ j(no_overflow, &not_kmin_int, Label::kNear); 1369 __ j(no_overflow, &not_kmin_int, Label::kNear);
1370 __ mov(dividend, Immediate(kMinInt / divisor)); 1370 __ mov(dividend, Immediate(kMinInt / divisor));
1371 __ jmp(&done, Label::kNear); 1371 __ jmp(&done, Label::kNear);
1372 __ bind(&not_kmin_int); 1372 __ bind(&not_kmin_int);
1373 __ sar(dividend, shift); 1373 __ sar(dividend, shift);
1374 __ bind(&done); 1374 __ bind(&done);
1375 } 1375 }
1376 1376
1377 1377
1378 void LCodeGen::DoFlooringDivByConstI(LFlooringDivByConstI* instr) { 1378 void LCodeGen::DoFlooringDivByConstI(LFlooringDivByConstI* instr) {
1379 Register dividend = ToRegister(instr->dividend()); 1379 Register dividend = ToRegister(instr->dividend());
1380 int32_t divisor = instr->divisor(); 1380 int32_t divisor = instr->divisor();
1381 DCHECK(ToRegister(instr->result()).is(edx)); 1381 DCHECK(ToRegister(instr->result()).is(edx));
1382 1382
1383 if (divisor == 0) { 1383 if (divisor == 0) {
1384 DeoptimizeIf(no_condition, instr); 1384 DeoptimizeIf(no_condition, instr, "division by zero");
1385 return; 1385 return;
1386 } 1386 }
1387 1387
1388 // Check for (0 / -x) that will produce negative zero. 1388 // Check for (0 / -x) that will produce negative zero.
1389 HMathFloorOfDiv* hdiv = instr->hydrogen(); 1389 HMathFloorOfDiv* hdiv = instr->hydrogen();
1390 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) { 1390 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) {
1391 __ test(dividend, dividend); 1391 __ test(dividend, dividend);
1392 DeoptimizeIf(zero, instr); 1392 DeoptimizeIf(zero, instr, "minus zero");
1393 } 1393 }
1394 1394
1395 // Easy case: We need no dynamic check for the dividend and the flooring 1395 // Easy case: We need no dynamic check for the dividend and the flooring
1396 // division is the same as the truncating division. 1396 // division is the same as the truncating division.
1397 if ((divisor > 0 && !hdiv->CheckFlag(HValue::kLeftCanBeNegative)) || 1397 if ((divisor > 0 && !hdiv->CheckFlag(HValue::kLeftCanBeNegative)) ||
1398 (divisor < 0 && !hdiv->CheckFlag(HValue::kLeftCanBePositive))) { 1398 (divisor < 0 && !hdiv->CheckFlag(HValue::kLeftCanBePositive))) {
1399 __ TruncatingDiv(dividend, Abs(divisor)); 1399 __ TruncatingDiv(dividend, Abs(divisor));
1400 if (divisor < 0) __ neg(edx); 1400 if (divisor < 0) __ neg(edx);
1401 return; 1401 return;
1402 } 1402 }
(...skipping 26 matching lines...) Expand all
1429 Register result = ToRegister(instr->result()); 1429 Register result = ToRegister(instr->result());
1430 DCHECK(dividend.is(eax)); 1430 DCHECK(dividend.is(eax));
1431 DCHECK(remainder.is(edx)); 1431 DCHECK(remainder.is(edx));
1432 DCHECK(result.is(eax)); 1432 DCHECK(result.is(eax));
1433 DCHECK(!divisor.is(eax)); 1433 DCHECK(!divisor.is(eax));
1434 DCHECK(!divisor.is(edx)); 1434 DCHECK(!divisor.is(edx));
1435 1435
1436 // Check for x / 0. 1436 // Check for x / 0.
1437 if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) { 1437 if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) {
1438 __ test(divisor, divisor); 1438 __ test(divisor, divisor);
1439 DeoptimizeIf(zero, instr); 1439 DeoptimizeIf(zero, instr, "division by zero");
1440 } 1440 }
1441 1441
1442 // Check for (0 / -x) that will produce negative zero. 1442 // Check for (0 / -x) that will produce negative zero.
1443 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) { 1443 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) {
1444 Label dividend_not_zero; 1444 Label dividend_not_zero;
1445 __ test(dividend, dividend); 1445 __ test(dividend, dividend);
1446 __ j(not_zero, &dividend_not_zero, Label::kNear); 1446 __ j(not_zero, &dividend_not_zero, Label::kNear);
1447 __ test(divisor, divisor); 1447 __ test(divisor, divisor);
1448 DeoptimizeIf(sign, instr); 1448 DeoptimizeIf(sign, instr, "minus zero");
1449 __ bind(&dividend_not_zero); 1449 __ bind(&dividend_not_zero);
1450 } 1450 }
1451 1451
1452 // Check for (kMinInt / -1). 1452 // Check for (kMinInt / -1).
1453 if (hdiv->CheckFlag(HValue::kCanOverflow)) { 1453 if (hdiv->CheckFlag(HValue::kCanOverflow)) {
1454 Label dividend_not_min_int; 1454 Label dividend_not_min_int;
1455 __ cmp(dividend, kMinInt); 1455 __ cmp(dividend, kMinInt);
1456 __ j(not_zero, &dividend_not_min_int, Label::kNear); 1456 __ j(not_zero, &dividend_not_min_int, Label::kNear);
1457 __ cmp(divisor, -1); 1457 __ cmp(divisor, -1);
1458 DeoptimizeIf(zero, instr); 1458 DeoptimizeIf(zero, instr, "overflow");
1459 __ bind(&dividend_not_min_int); 1459 __ bind(&dividend_not_min_int);
1460 } 1460 }
1461 1461
1462 // Sign extend to edx (= remainder). 1462 // Sign extend to edx (= remainder).
1463 __ cdq(); 1463 __ cdq();
1464 __ idiv(divisor); 1464 __ idiv(divisor);
1465 1465
1466 Label done; 1466 Label done;
1467 __ test(remainder, remainder); 1467 __ test(remainder, remainder);
1468 __ j(zero, &done, Label::kNear); 1468 __ j(zero, &done, Label::kNear);
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
1526 __ imul(left, left, constant); 1526 __ imul(left, left, constant);
1527 } 1527 }
1528 } else { 1528 } else {
1529 if (instr->hydrogen()->representation().IsSmi()) { 1529 if (instr->hydrogen()->representation().IsSmi()) {
1530 __ SmiUntag(left); 1530 __ SmiUntag(left);
1531 } 1531 }
1532 __ imul(left, ToOperand(right)); 1532 __ imul(left, ToOperand(right));
1533 } 1533 }
1534 1534
1535 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { 1535 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) {
1536 DeoptimizeIf(overflow, instr); 1536 DeoptimizeIf(overflow, instr, "overflow");
1537 } 1537 }
1538 1538
1539 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 1539 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
1540 // Bail out if the result is supposed to be negative zero. 1540 // Bail out if the result is supposed to be negative zero.
1541 Label done; 1541 Label done;
1542 __ test(left, Operand(left)); 1542 __ test(left, Operand(left));
1543 __ j(not_zero, &done, Label::kNear); 1543 __ j(not_zero, &done, Label::kNear);
1544 if (right->IsConstantOperand()) { 1544 if (right->IsConstantOperand()) {
1545 if (ToInteger32(LConstantOperand::cast(right)) < 0) { 1545 if (ToInteger32(LConstantOperand::cast(right)) < 0) {
1546 DeoptimizeIf(no_condition, instr); 1546 DeoptimizeIf(no_condition, instr, "minus zero");
1547 } else if (ToInteger32(LConstantOperand::cast(right)) == 0) { 1547 } else if (ToInteger32(LConstantOperand::cast(right)) == 0) {
1548 __ cmp(ToRegister(instr->temp()), Immediate(0)); 1548 __ cmp(ToRegister(instr->temp()), Immediate(0));
1549 DeoptimizeIf(less, instr); 1549 DeoptimizeIf(less, instr, "minus zero");
1550 } 1550 }
1551 } else { 1551 } else {
1552 // Test the non-zero operand for negative sign. 1552 // Test the non-zero operand for negative sign.
1553 __ or_(ToRegister(instr->temp()), ToOperand(right)); 1553 __ or_(ToRegister(instr->temp()), ToOperand(right));
1554 DeoptimizeIf(sign, instr); 1554 DeoptimizeIf(sign, instr, "minus zero");
1555 } 1555 }
1556 __ bind(&done); 1556 __ bind(&done);
1557 } 1557 }
1558 } 1558 }
1559 1559
1560 1560
1561 void LCodeGen::DoBitI(LBitI* instr) { 1561 void LCodeGen::DoBitI(LBitI* instr) {
1562 LOperand* left = instr->left(); 1562 LOperand* left = instr->left();
1563 LOperand* right = instr->right(); 1563 LOperand* right = instr->right();
1564 DCHECK(left->Equals(instr->result())); 1564 DCHECK(left->Equals(instr->result()));
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
1617 case Token::ROR: 1617 case Token::ROR:
1618 __ ror_cl(ToRegister(left)); 1618 __ ror_cl(ToRegister(left));
1619 break; 1619 break;
1620 case Token::SAR: 1620 case Token::SAR:
1621 __ sar_cl(ToRegister(left)); 1621 __ sar_cl(ToRegister(left));
1622 break; 1622 break;
1623 case Token::SHR: 1623 case Token::SHR:
1624 __ shr_cl(ToRegister(left)); 1624 __ shr_cl(ToRegister(left));
1625 if (instr->can_deopt()) { 1625 if (instr->can_deopt()) {
1626 __ test(ToRegister(left), ToRegister(left)); 1626 __ test(ToRegister(left), ToRegister(left));
1627 DeoptimizeIf(sign, instr); 1627 DeoptimizeIf(sign, instr, "negative value");
1628 } 1628 }
1629 break; 1629 break;
1630 case Token::SHL: 1630 case Token::SHL:
1631 __ shl_cl(ToRegister(left)); 1631 __ shl_cl(ToRegister(left));
1632 break; 1632 break;
1633 default: 1633 default:
1634 UNREACHABLE(); 1634 UNREACHABLE();
1635 break; 1635 break;
1636 } 1636 }
1637 } else { 1637 } else {
1638 int value = ToInteger32(LConstantOperand::cast(right)); 1638 int value = ToInteger32(LConstantOperand::cast(right));
1639 uint8_t shift_count = static_cast<uint8_t>(value & 0x1F); 1639 uint8_t shift_count = static_cast<uint8_t>(value & 0x1F);
1640 switch (instr->op()) { 1640 switch (instr->op()) {
1641 case Token::ROR: 1641 case Token::ROR:
1642 if (shift_count == 0 && instr->can_deopt()) { 1642 if (shift_count == 0 && instr->can_deopt()) {
1643 __ test(ToRegister(left), ToRegister(left)); 1643 __ test(ToRegister(left), ToRegister(left));
1644 DeoptimizeIf(sign, instr); 1644 DeoptimizeIf(sign, instr, "negative value");
1645 } else { 1645 } else {
1646 __ ror(ToRegister(left), shift_count); 1646 __ ror(ToRegister(left), shift_count);
1647 } 1647 }
1648 break; 1648 break;
1649 case Token::SAR: 1649 case Token::SAR:
1650 if (shift_count != 0) { 1650 if (shift_count != 0) {
1651 __ sar(ToRegister(left), shift_count); 1651 __ sar(ToRegister(left), shift_count);
1652 } 1652 }
1653 break; 1653 break;
1654 case Token::SHR: 1654 case Token::SHR:
1655 if (shift_count != 0) { 1655 if (shift_count != 0) {
1656 __ shr(ToRegister(left), shift_count); 1656 __ shr(ToRegister(left), shift_count);
1657 } else if (instr->can_deopt()) { 1657 } else if (instr->can_deopt()) {
1658 __ test(ToRegister(left), ToRegister(left)); 1658 __ test(ToRegister(left), ToRegister(left));
1659 DeoptimizeIf(sign, instr); 1659 DeoptimizeIf(sign, instr, "negative value");
1660 } 1660 }
1661 break; 1661 break;
1662 case Token::SHL: 1662 case Token::SHL:
1663 if (shift_count != 0) { 1663 if (shift_count != 0) {
1664 if (instr->hydrogen_value()->representation().IsSmi() && 1664 if (instr->hydrogen_value()->representation().IsSmi() &&
1665 instr->can_deopt()) { 1665 instr->can_deopt()) {
1666 if (shift_count != 1) { 1666 if (shift_count != 1) {
1667 __ shl(ToRegister(left), shift_count - 1); 1667 __ shl(ToRegister(left), shift_count - 1);
1668 } 1668 }
1669 __ SmiTag(ToRegister(left)); 1669 __ SmiTag(ToRegister(left));
1670 DeoptimizeIf(overflow, instr); 1670 DeoptimizeIf(overflow, instr, "overflow");
1671 } else { 1671 } else {
1672 __ shl(ToRegister(left), shift_count); 1672 __ shl(ToRegister(left), shift_count);
1673 } 1673 }
1674 } 1674 }
1675 break; 1675 break;
1676 default: 1676 default:
1677 UNREACHABLE(); 1677 UNREACHABLE();
1678 break; 1678 break;
1679 } 1679 }
1680 } 1680 }
1681 } 1681 }
1682 1682
1683 1683
1684 void LCodeGen::DoSubI(LSubI* instr) { 1684 void LCodeGen::DoSubI(LSubI* instr) {
1685 LOperand* left = instr->left(); 1685 LOperand* left = instr->left();
1686 LOperand* right = instr->right(); 1686 LOperand* right = instr->right();
1687 DCHECK(left->Equals(instr->result())); 1687 DCHECK(left->Equals(instr->result()));
1688 1688
1689 if (right->IsConstantOperand()) { 1689 if (right->IsConstantOperand()) {
1690 __ sub(ToOperand(left), 1690 __ sub(ToOperand(left),
1691 ToImmediate(right, instr->hydrogen()->representation())); 1691 ToImmediate(right, instr->hydrogen()->representation()));
1692 } else { 1692 } else {
1693 __ sub(ToRegister(left), ToOperand(right)); 1693 __ sub(ToRegister(left), ToOperand(right));
1694 } 1694 }
1695 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { 1695 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) {
1696 DeoptimizeIf(overflow, instr); 1696 DeoptimizeIf(overflow, instr, "overflow");
1697 } 1697 }
1698 } 1698 }
1699 1699
1700 1700
1701 void LCodeGen::DoConstantI(LConstantI* instr) { 1701 void LCodeGen::DoConstantI(LConstantI* instr) {
1702 __ Move(ToRegister(instr->result()), Immediate(instr->value())); 1702 __ Move(ToRegister(instr->result()), Immediate(instr->value()));
1703 } 1703 }
1704 1704
1705 1705
1706 void LCodeGen::DoConstantS(LConstantS* instr) { 1706 void LCodeGen::DoConstantS(LConstantS* instr) {
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
1770 void LCodeGen::DoDateField(LDateField* instr) { 1770 void LCodeGen::DoDateField(LDateField* instr) {
1771 Register object = ToRegister(instr->date()); 1771 Register object = ToRegister(instr->date());
1772 Register result = ToRegister(instr->result()); 1772 Register result = ToRegister(instr->result());
1773 Register scratch = ToRegister(instr->temp()); 1773 Register scratch = ToRegister(instr->temp());
1774 Smi* index = instr->index(); 1774 Smi* index = instr->index();
1775 Label runtime, done; 1775 Label runtime, done;
1776 DCHECK(object.is(result)); 1776 DCHECK(object.is(result));
1777 DCHECK(object.is(eax)); 1777 DCHECK(object.is(eax));
1778 1778
1779 __ test(object, Immediate(kSmiTagMask)); 1779 __ test(object, Immediate(kSmiTagMask));
1780 DeoptimizeIf(zero, instr); 1780 DeoptimizeIf(zero, instr, "Smi");
1781 __ CmpObjectType(object, JS_DATE_TYPE, scratch); 1781 __ CmpObjectType(object, JS_DATE_TYPE, scratch);
1782 DeoptimizeIf(not_equal, instr); 1782 DeoptimizeIf(not_equal, instr, "not a date object");
1783 1783
1784 if (index->value() == 0) { 1784 if (index->value() == 0) {
1785 __ mov(result, FieldOperand(object, JSDate::kValueOffset)); 1785 __ mov(result, FieldOperand(object, JSDate::kValueOffset));
1786 } else { 1786 } else {
1787 if (index->value() < JSDate::kFirstUncachedField) { 1787 if (index->value() < JSDate::kFirstUncachedField) {
1788 ExternalReference stamp = ExternalReference::date_cache_stamp(isolate()); 1788 ExternalReference stamp = ExternalReference::date_cache_stamp(isolate());
1789 __ mov(scratch, Operand::StaticVariable(stamp)); 1789 __ mov(scratch, Operand::StaticVariable(stamp));
1790 __ cmp(scratch, FieldOperand(object, JSDate::kCacheStampOffset)); 1790 __ cmp(scratch, FieldOperand(object, JSDate::kCacheStampOffset));
1791 __ j(not_equal, &runtime, Label::kNear); 1791 __ j(not_equal, &runtime, Label::kNear);
1792 __ mov(result, FieldOperand(object, JSDate::kValueOffset + 1792 __ mov(result, FieldOperand(object, JSDate::kValueOffset +
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
1902 __ lea(ToRegister(instr->result()), address); 1902 __ lea(ToRegister(instr->result()), address);
1903 } 1903 }
1904 } else { 1904 } else {
1905 if (right->IsConstantOperand()) { 1905 if (right->IsConstantOperand()) {
1906 __ add(ToOperand(left), 1906 __ add(ToOperand(left),
1907 ToImmediate(right, instr->hydrogen()->representation())); 1907 ToImmediate(right, instr->hydrogen()->representation()));
1908 } else { 1908 } else {
1909 __ add(ToRegister(left), ToOperand(right)); 1909 __ add(ToRegister(left), ToOperand(right));
1910 } 1910 }
1911 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { 1911 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) {
1912 DeoptimizeIf(overflow, instr); 1912 DeoptimizeIf(overflow, instr, "overflow");
1913 } 1913 }
1914 } 1914 }
1915 } 1915 }
1916 1916
1917 1917
1918 void LCodeGen::DoMathMinMax(LMathMinMax* instr) { 1918 void LCodeGen::DoMathMinMax(LMathMinMax* instr) {
1919 LOperand* left = instr->left(); 1919 LOperand* left = instr->left();
1920 LOperand* right = instr->right(); 1920 LOperand* right = instr->right();
1921 DCHECK(left->Equals(instr->result())); 1921 DCHECK(left->Equals(instr->result()));
1922 HMathMinMax::Operation operation = instr->hydrogen()->operation(); 1922 HMathMinMax::Operation operation = instr->hydrogen()->operation();
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after
2126 } 2126 }
2127 2127
2128 if (expected.Contains(ToBooleanStub::SMI)) { 2128 if (expected.Contains(ToBooleanStub::SMI)) {
2129 // Smis: 0 -> false, all other -> true. 2129 // Smis: 0 -> false, all other -> true.
2130 __ test(reg, Operand(reg)); 2130 __ test(reg, Operand(reg));
2131 __ j(equal, instr->FalseLabel(chunk_)); 2131 __ j(equal, instr->FalseLabel(chunk_));
2132 __ JumpIfSmi(reg, instr->TrueLabel(chunk_)); 2132 __ JumpIfSmi(reg, instr->TrueLabel(chunk_));
2133 } else if (expected.NeedsMap()) { 2133 } else if (expected.NeedsMap()) {
2134 // If we need a map later and have a Smi -> deopt. 2134 // If we need a map later and have a Smi -> deopt.
2135 __ test(reg, Immediate(kSmiTagMask)); 2135 __ test(reg, Immediate(kSmiTagMask));
2136 DeoptimizeIf(zero, instr); 2136 DeoptimizeIf(zero, instr, "Smi");
2137 } 2137 }
2138 2138
2139 Register map = no_reg; // Keep the compiler happy. 2139 Register map = no_reg; // Keep the compiler happy.
2140 if (expected.NeedsMap()) { 2140 if (expected.NeedsMap()) {
2141 map = ToRegister(instr->temp()); 2141 map = ToRegister(instr->temp());
2142 DCHECK(!map.is(reg)); 2142 DCHECK(!map.is(reg));
2143 __ mov(map, FieldOperand(reg, HeapObject::kMapOffset)); 2143 __ mov(map, FieldOperand(reg, HeapObject::kMapOffset));
2144 2144
2145 if (expected.CanBeUndetectable()) { 2145 if (expected.CanBeUndetectable()) {
2146 // Undetectable -> false. 2146 // Undetectable -> false.
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
2183 __ xorps(xmm_scratch, xmm_scratch); 2183 __ xorps(xmm_scratch, xmm_scratch);
2184 __ ucomisd(xmm_scratch, FieldOperand(reg, HeapNumber::kValueOffset)); 2184 __ ucomisd(xmm_scratch, FieldOperand(reg, HeapNumber::kValueOffset));
2185 __ j(zero, instr->FalseLabel(chunk_)); 2185 __ j(zero, instr->FalseLabel(chunk_));
2186 __ jmp(instr->TrueLabel(chunk_)); 2186 __ jmp(instr->TrueLabel(chunk_));
2187 __ bind(&not_heap_number); 2187 __ bind(&not_heap_number);
2188 } 2188 }
2189 2189
2190 if (!expected.IsGeneric()) { 2190 if (!expected.IsGeneric()) {
2191 // We've seen something for the first time -> deopt. 2191 // We've seen something for the first time -> deopt.
2192 // This can only happen if we are not generic already. 2192 // This can only happen if we are not generic already.
2193 DeoptimizeIf(no_condition, instr); 2193 DeoptimizeIf(no_condition, instr, "unexpected object");
2194 } 2194 }
2195 } 2195 }
2196 } 2196 }
2197 } 2197 }
2198 2198
2199 2199
2200 void LCodeGen::EmitGoto(int block) { 2200 void LCodeGen::EmitGoto(int block) {
2201 if (!IsNextEmittedBlock(block)) { 2201 if (!IsNextEmittedBlock(block)) {
2202 __ jmp(chunk_->GetAssemblyLabel(LookupDestination(block))); 2202 __ jmp(chunk_->GetAssemblyLabel(LookupDestination(block)));
2203 } 2203 }
(...skipping 609 matching lines...) Expand 10 before | Expand all | Expand 10 after
2813 info()->AddNoFrameRange(no_frame_start, masm_->pc_offset()); 2813 info()->AddNoFrameRange(no_frame_start, masm_->pc_offset());
2814 } 2814 }
2815 } 2815 }
2816 2816
2817 2817
2818 void LCodeGen::DoLoadGlobalCell(LLoadGlobalCell* instr) { 2818 void LCodeGen::DoLoadGlobalCell(LLoadGlobalCell* instr) {
2819 Register result = ToRegister(instr->result()); 2819 Register result = ToRegister(instr->result());
2820 __ mov(result, Operand::ForCell(instr->hydrogen()->cell().handle())); 2820 __ mov(result, Operand::ForCell(instr->hydrogen()->cell().handle()));
2821 if (instr->hydrogen()->RequiresHoleCheck()) { 2821 if (instr->hydrogen()->RequiresHoleCheck()) {
2822 __ cmp(result, factory()->the_hole_value()); 2822 __ cmp(result, factory()->the_hole_value());
2823 DeoptimizeIf(equal, instr); 2823 DeoptimizeIf(equal, instr, "hole");
2824 } 2824 }
2825 } 2825 }
2826 2826
2827 2827
2828 template <class T> 2828 template <class T>
2829 void LCodeGen::EmitVectorLoadICRegisters(T* instr) { 2829 void LCodeGen::EmitVectorLoadICRegisters(T* instr) {
2830 DCHECK(FLAG_vector_ics); 2830 DCHECK(FLAG_vector_ics);
2831 Register vector = ToRegister(instr->temp_vector()); 2831 Register vector = ToRegister(instr->temp_vector());
2832 DCHECK(vector.is(VectorLoadICDescriptor::VectorRegister())); 2832 DCHECK(vector.is(VectorLoadICDescriptor::VectorRegister()));
2833 __ mov(vector, instr->hydrogen()->feedback_vector()); 2833 __ mov(vector, instr->hydrogen()->feedback_vector());
(...skipping 23 matching lines...) Expand all
2857 void LCodeGen::DoStoreGlobalCell(LStoreGlobalCell* instr) { 2857 void LCodeGen::DoStoreGlobalCell(LStoreGlobalCell* instr) {
2858 Register value = ToRegister(instr->value()); 2858 Register value = ToRegister(instr->value());
2859 Handle<PropertyCell> cell_handle = instr->hydrogen()->cell().handle(); 2859 Handle<PropertyCell> cell_handle = instr->hydrogen()->cell().handle();
2860 2860
2861 // If the cell we are storing to contains the hole it could have 2861 // If the cell we are storing to contains the hole it could have
2862 // been deleted from the property dictionary. In that case, we need 2862 // been deleted from the property dictionary. In that case, we need
2863 // to update the property details in the property dictionary to mark 2863 // to update the property details in the property dictionary to mark
2864 // it as no longer deleted. We deoptimize in that case. 2864 // it as no longer deleted. We deoptimize in that case.
2865 if (instr->hydrogen()->RequiresHoleCheck()) { 2865 if (instr->hydrogen()->RequiresHoleCheck()) {
2866 __ cmp(Operand::ForCell(cell_handle), factory()->the_hole_value()); 2866 __ cmp(Operand::ForCell(cell_handle), factory()->the_hole_value());
2867 DeoptimizeIf(equal, instr); 2867 DeoptimizeIf(equal, instr, "hole");
2868 } 2868 }
2869 2869
2870 // Store the value. 2870 // Store the value.
2871 __ mov(Operand::ForCell(cell_handle), value); 2871 __ mov(Operand::ForCell(cell_handle), value);
2872 // Cells are always rescanned, so no write barrier here. 2872 // Cells are always rescanned, so no write barrier here.
2873 } 2873 }
2874 2874
2875 2875
2876 void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) { 2876 void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) {
2877 Register context = ToRegister(instr->context()); 2877 Register context = ToRegister(instr->context());
2878 Register result = ToRegister(instr->result()); 2878 Register result = ToRegister(instr->result());
2879 __ mov(result, ContextOperand(context, instr->slot_index())); 2879 __ mov(result, ContextOperand(context, instr->slot_index()));
2880 2880
2881 if (instr->hydrogen()->RequiresHoleCheck()) { 2881 if (instr->hydrogen()->RequiresHoleCheck()) {
2882 __ cmp(result, factory()->the_hole_value()); 2882 __ cmp(result, factory()->the_hole_value());
2883 if (instr->hydrogen()->DeoptimizesOnHole()) { 2883 if (instr->hydrogen()->DeoptimizesOnHole()) {
2884 DeoptimizeIf(equal, instr); 2884 DeoptimizeIf(equal, instr, "hole");
2885 } else { 2885 } else {
2886 Label is_not_hole; 2886 Label is_not_hole;
2887 __ j(not_equal, &is_not_hole, Label::kNear); 2887 __ j(not_equal, &is_not_hole, Label::kNear);
2888 __ mov(result, factory()->undefined_value()); 2888 __ mov(result, factory()->undefined_value());
2889 __ bind(&is_not_hole); 2889 __ bind(&is_not_hole);
2890 } 2890 }
2891 } 2891 }
2892 } 2892 }
2893 2893
2894 2894
2895 void LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) { 2895 void LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) {
2896 Register context = ToRegister(instr->context()); 2896 Register context = ToRegister(instr->context());
2897 Register value = ToRegister(instr->value()); 2897 Register value = ToRegister(instr->value());
2898 2898
2899 Label skip_assignment; 2899 Label skip_assignment;
2900 2900
2901 Operand target = ContextOperand(context, instr->slot_index()); 2901 Operand target = ContextOperand(context, instr->slot_index());
2902 if (instr->hydrogen()->RequiresHoleCheck()) { 2902 if (instr->hydrogen()->RequiresHoleCheck()) {
2903 __ cmp(target, factory()->the_hole_value()); 2903 __ cmp(target, factory()->the_hole_value());
2904 if (instr->hydrogen()->DeoptimizesOnHole()) { 2904 if (instr->hydrogen()->DeoptimizesOnHole()) {
2905 DeoptimizeIf(equal, instr); 2905 DeoptimizeIf(equal, instr, "hole");
2906 } else { 2906 } else {
2907 __ j(not_equal, &skip_assignment, Label::kNear); 2907 __ j(not_equal, &skip_assignment, Label::kNear);
2908 } 2908 }
2909 } 2909 }
2910 2910
2911 __ mov(target, value); 2911 __ mov(target, value);
2912 if (instr->hydrogen()->NeedsWriteBarrier()) { 2912 if (instr->hydrogen()->NeedsWriteBarrier()) {
2913 SmiCheck check_needed = 2913 SmiCheck check_needed =
2914 instr->hydrogen()->value()->type().IsHeapObject() 2914 instr->hydrogen()->value()->type().IsHeapObject()
2915 ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; 2915 ? OMIT_SMI_CHECK : INLINE_SMI_CHECK;
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
2994 Register function = ToRegister(instr->function()); 2994 Register function = ToRegister(instr->function());
2995 Register temp = ToRegister(instr->temp()); 2995 Register temp = ToRegister(instr->temp());
2996 Register result = ToRegister(instr->result()); 2996 Register result = ToRegister(instr->result());
2997 2997
2998 // Get the prototype or initial map from the function. 2998 // Get the prototype or initial map from the function.
2999 __ mov(result, 2999 __ mov(result,
3000 FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset)); 3000 FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset));
3001 3001
3002 // Check that the function has a prototype or an initial map. 3002 // Check that the function has a prototype or an initial map.
3003 __ cmp(Operand(result), Immediate(factory()->the_hole_value())); 3003 __ cmp(Operand(result), Immediate(factory()->the_hole_value()));
3004 DeoptimizeIf(equal, instr); 3004 DeoptimizeIf(equal, instr, "hole");
3005 3005
3006 // If the function does not have an initial map, we're done. 3006 // If the function does not have an initial map, we're done.
3007 Label done; 3007 Label done;
3008 __ CmpObjectType(result, MAP_TYPE, temp); 3008 __ CmpObjectType(result, MAP_TYPE, temp);
3009 __ j(not_equal, &done, Label::kNear); 3009 __ j(not_equal, &done, Label::kNear);
3010 3010
3011 // Get the prototype from the initial map. 3011 // Get the prototype from the initial map.
3012 __ mov(result, FieldOperand(result, Map::kPrototypeOffset)); 3012 __ mov(result, FieldOperand(result, Map::kPrototypeOffset));
3013 3013
3014 // All done. 3014 // All done.
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
3087 break; 3087 break;
3088 case EXTERNAL_INT32_ELEMENTS: 3088 case EXTERNAL_INT32_ELEMENTS:
3089 case INT32_ELEMENTS: 3089 case INT32_ELEMENTS:
3090 __ mov(result, operand); 3090 __ mov(result, operand);
3091 break; 3091 break;
3092 case EXTERNAL_UINT32_ELEMENTS: 3092 case EXTERNAL_UINT32_ELEMENTS:
3093 case UINT32_ELEMENTS: 3093 case UINT32_ELEMENTS:
3094 __ mov(result, operand); 3094 __ mov(result, operand);
3095 if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) { 3095 if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) {
3096 __ test(result, Operand(result)); 3096 __ test(result, Operand(result));
3097 DeoptimizeIf(negative, instr); 3097 DeoptimizeIf(negative, instr, "negative value");
3098 } 3098 }
3099 break; 3099 break;
3100 case EXTERNAL_FLOAT32_ELEMENTS: 3100 case EXTERNAL_FLOAT32_ELEMENTS:
3101 case EXTERNAL_FLOAT64_ELEMENTS: 3101 case EXTERNAL_FLOAT64_ELEMENTS:
3102 case FLOAT32_ELEMENTS: 3102 case FLOAT32_ELEMENTS:
3103 case FLOAT64_ELEMENTS: 3103 case FLOAT64_ELEMENTS:
3104 case FAST_SMI_ELEMENTS: 3104 case FAST_SMI_ELEMENTS:
3105 case FAST_ELEMENTS: 3105 case FAST_ELEMENTS:
3106 case FAST_DOUBLE_ELEMENTS: 3106 case FAST_DOUBLE_ELEMENTS:
3107 case FAST_HOLEY_SMI_ELEMENTS: 3107 case FAST_HOLEY_SMI_ELEMENTS:
3108 case FAST_HOLEY_ELEMENTS: 3108 case FAST_HOLEY_ELEMENTS:
3109 case FAST_HOLEY_DOUBLE_ELEMENTS: 3109 case FAST_HOLEY_DOUBLE_ELEMENTS:
3110 case DICTIONARY_ELEMENTS: 3110 case DICTIONARY_ELEMENTS:
3111 case SLOPPY_ARGUMENTS_ELEMENTS: 3111 case SLOPPY_ARGUMENTS_ELEMENTS:
3112 UNREACHABLE(); 3112 UNREACHABLE();
3113 break; 3113 break;
3114 } 3114 }
3115 } 3115 }
3116 } 3116 }
3117 3117
3118 3118
3119 void LCodeGen::DoLoadKeyedFixedDoubleArray(LLoadKeyed* instr) { 3119 void LCodeGen::DoLoadKeyedFixedDoubleArray(LLoadKeyed* instr) {
3120 if (instr->hydrogen()->RequiresHoleCheck()) { 3120 if (instr->hydrogen()->RequiresHoleCheck()) {
3121 Operand hole_check_operand = BuildFastArrayOperand( 3121 Operand hole_check_operand = BuildFastArrayOperand(
3122 instr->elements(), instr->key(), 3122 instr->elements(), instr->key(),
3123 instr->hydrogen()->key()->representation(), 3123 instr->hydrogen()->key()->representation(),
3124 FAST_DOUBLE_ELEMENTS, 3124 FAST_DOUBLE_ELEMENTS,
3125 instr->base_offset() + sizeof(kHoleNanLower32)); 3125 instr->base_offset() + sizeof(kHoleNanLower32));
3126 __ cmp(hole_check_operand, Immediate(kHoleNanUpper32)); 3126 __ cmp(hole_check_operand, Immediate(kHoleNanUpper32));
3127 DeoptimizeIf(equal, instr); 3127 DeoptimizeIf(equal, instr, "hole");
3128 } 3128 }
3129 3129
3130 Operand double_load_operand = BuildFastArrayOperand( 3130 Operand double_load_operand = BuildFastArrayOperand(
3131 instr->elements(), 3131 instr->elements(),
3132 instr->key(), 3132 instr->key(),
3133 instr->hydrogen()->key()->representation(), 3133 instr->hydrogen()->key()->representation(),
3134 FAST_DOUBLE_ELEMENTS, 3134 FAST_DOUBLE_ELEMENTS,
3135 instr->base_offset()); 3135 instr->base_offset());
3136 XMMRegister result = ToDoubleRegister(instr->result()); 3136 XMMRegister result = ToDoubleRegister(instr->result());
3137 __ movsd(result, double_load_operand); 3137 __ movsd(result, double_load_operand);
3138 } 3138 }
3139 3139
3140 3140
3141 void LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) { 3141 void LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) {
3142 Register result = ToRegister(instr->result()); 3142 Register result = ToRegister(instr->result());
3143 3143
3144 // Load the result. 3144 // Load the result.
3145 __ mov(result, 3145 __ mov(result,
3146 BuildFastArrayOperand(instr->elements(), instr->key(), 3146 BuildFastArrayOperand(instr->elements(), instr->key(),
3147 instr->hydrogen()->key()->representation(), 3147 instr->hydrogen()->key()->representation(),
3148 FAST_ELEMENTS, instr->base_offset())); 3148 FAST_ELEMENTS, instr->base_offset()));
3149 3149
3150 // Check for the hole value. 3150 // Check for the hole value.
3151 if (instr->hydrogen()->RequiresHoleCheck()) { 3151 if (instr->hydrogen()->RequiresHoleCheck()) {
3152 if (IsFastSmiElementsKind(instr->hydrogen()->elements_kind())) { 3152 if (IsFastSmiElementsKind(instr->hydrogen()->elements_kind())) {
3153 __ test(result, Immediate(kSmiTagMask)); 3153 __ test(result, Immediate(kSmiTagMask));
3154 DeoptimizeIf(not_equal, instr); 3154 DeoptimizeIf(not_equal, instr, "not a Smi");
3155 } else { 3155 } else {
3156 __ cmp(result, factory()->the_hole_value()); 3156 __ cmp(result, factory()->the_hole_value());
3157 DeoptimizeIf(equal, instr); 3157 DeoptimizeIf(equal, instr, "hole");
3158 } 3158 }
3159 } 3159 }
3160 } 3160 }
3161 3161
3162 3162
3163 void LCodeGen::DoLoadKeyed(LLoadKeyed* instr) { 3163 void LCodeGen::DoLoadKeyed(LLoadKeyed* instr) {
3164 if (instr->is_typed_elements()) { 3164 if (instr->is_typed_elements()) {
3165 DoLoadKeyedExternalArray(instr); 3165 DoLoadKeyedExternalArray(instr);
3166 } else if (instr->hydrogen()->representation().IsDouble()) { 3166 } else if (instr->hydrogen()->representation().IsDouble()) {
3167 DoLoadKeyedFixedDoubleArray(instr); 3167 DoLoadKeyedFixedDoubleArray(instr);
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after
3294 } 3294 }
3295 3295
3296 // Normal function. Replace undefined or null with global receiver. 3296 // Normal function. Replace undefined or null with global receiver.
3297 __ cmp(receiver, factory()->null_value()); 3297 __ cmp(receiver, factory()->null_value());
3298 __ j(equal, &global_object, Label::kNear); 3298 __ j(equal, &global_object, Label::kNear);
3299 __ cmp(receiver, factory()->undefined_value()); 3299 __ cmp(receiver, factory()->undefined_value());
3300 __ j(equal, &global_object, Label::kNear); 3300 __ j(equal, &global_object, Label::kNear);
3301 3301
3302 // The receiver should be a JS object. 3302 // The receiver should be a JS object.
3303 __ test(receiver, Immediate(kSmiTagMask)); 3303 __ test(receiver, Immediate(kSmiTagMask));
3304 DeoptimizeIf(equal, instr); 3304 DeoptimizeIf(equal, instr, "Smi");
3305 __ CmpObjectType(receiver, FIRST_SPEC_OBJECT_TYPE, scratch); 3305 __ CmpObjectType(receiver, FIRST_SPEC_OBJECT_TYPE, scratch);
3306 DeoptimizeIf(below, instr); 3306 DeoptimizeIf(below, instr, "not a JavaScript object");
3307 3307
3308 __ jmp(&receiver_ok, Label::kNear); 3308 __ jmp(&receiver_ok, Label::kNear);
3309 __ bind(&global_object); 3309 __ bind(&global_object);
3310 __ mov(receiver, FieldOperand(function, JSFunction::kContextOffset)); 3310 __ mov(receiver, FieldOperand(function, JSFunction::kContextOffset));
3311 const int global_offset = Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX); 3311 const int global_offset = Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX);
3312 __ mov(receiver, Operand(receiver, global_offset)); 3312 __ mov(receiver, Operand(receiver, global_offset));
3313 const int proxy_offset = GlobalObject::kGlobalProxyOffset; 3313 const int proxy_offset = GlobalObject::kGlobalProxyOffset;
3314 __ mov(receiver, FieldOperand(receiver, proxy_offset)); 3314 __ mov(receiver, FieldOperand(receiver, proxy_offset));
3315 __ bind(&receiver_ok); 3315 __ bind(&receiver_ok);
3316 } 3316 }
3317 3317
3318 3318
3319 void LCodeGen::DoApplyArguments(LApplyArguments* instr) { 3319 void LCodeGen::DoApplyArguments(LApplyArguments* instr) {
3320 Register receiver = ToRegister(instr->receiver()); 3320 Register receiver = ToRegister(instr->receiver());
3321 Register function = ToRegister(instr->function()); 3321 Register function = ToRegister(instr->function());
3322 Register length = ToRegister(instr->length()); 3322 Register length = ToRegister(instr->length());
3323 Register elements = ToRegister(instr->elements()); 3323 Register elements = ToRegister(instr->elements());
3324 DCHECK(receiver.is(eax)); // Used for parameter count. 3324 DCHECK(receiver.is(eax)); // Used for parameter count.
3325 DCHECK(function.is(edi)); // Required by InvokeFunction. 3325 DCHECK(function.is(edi)); // Required by InvokeFunction.
3326 DCHECK(ToRegister(instr->result()).is(eax)); 3326 DCHECK(ToRegister(instr->result()).is(eax));
3327 3327
3328 // Copy the arguments to this function possibly from the 3328 // Copy the arguments to this function possibly from the
3329 // adaptor frame below it. 3329 // adaptor frame below it.
3330 const uint32_t kArgumentsLimit = 1 * KB; 3330 const uint32_t kArgumentsLimit = 1 * KB;
3331 __ cmp(length, kArgumentsLimit); 3331 __ cmp(length, kArgumentsLimit);
3332 DeoptimizeIf(above, instr); 3332 DeoptimizeIf(above, instr, "too many arguments");
3333 3333
3334 __ push(receiver); 3334 __ push(receiver);
3335 __ mov(receiver, length); 3335 __ mov(receiver, length);
3336 3336
3337 // Loop through the arguments pushing them onto the execution 3337 // Loop through the arguments pushing them onto the execution
3338 // stack. 3338 // stack.
3339 Label invoke, loop; 3339 Label invoke, loop;
3340 // length is a small non-negative integer, due to the test above. 3340 // length is a small non-negative integer, due to the test above.
3341 __ test(length, Operand(length)); 3341 __ test(length, Operand(length));
3342 __ j(zero, &invoke, Label::kNear); 3342 __ j(zero, &invoke, Label::kNear);
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after
3515 } 3515 }
3516 3516
3517 RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT); 3517 RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT);
3518 } 3518 }
3519 3519
3520 3520
3521 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LMathAbs* instr) { 3521 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LMathAbs* instr) {
3522 Register input_reg = ToRegister(instr->value()); 3522 Register input_reg = ToRegister(instr->value());
3523 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), 3523 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset),
3524 factory()->heap_number_map()); 3524 factory()->heap_number_map());
3525 DeoptimizeIf(not_equal, instr); 3525 DeoptimizeIf(not_equal, instr, "not a heap number");
3526 3526
3527 Label slow, allocated, done; 3527 Label slow, allocated, done;
3528 Register tmp = input_reg.is(eax) ? ecx : eax; 3528 Register tmp = input_reg.is(eax) ? ecx : eax;
3529 Register tmp2 = tmp.is(ecx) ? edx : input_reg.is(ecx) ? edx : ecx; 3529 Register tmp2 = tmp.is(ecx) ? edx : input_reg.is(ecx) ? edx : ecx;
3530 3530
3531 // Preserve the value of all registers. 3531 // Preserve the value of all registers.
3532 PushSafepointRegistersScope scope(this); 3532 PushSafepointRegistersScope scope(this);
3533 3533
3534 __ mov(tmp, FieldOperand(input_reg, HeapNumber::kExponentOffset)); 3534 __ mov(tmp, FieldOperand(input_reg, HeapNumber::kExponentOffset));
3535 // Check the sign of the argument. If the argument is positive, just 3535 // Check the sign of the argument. If the argument is positive, just
(...skipping 26 matching lines...) Expand all
3562 __ bind(&done); 3562 __ bind(&done);
3563 } 3563 }
3564 3564
3565 3565
3566 void LCodeGen::EmitIntegerMathAbs(LMathAbs* instr) { 3566 void LCodeGen::EmitIntegerMathAbs(LMathAbs* instr) {
3567 Register input_reg = ToRegister(instr->value()); 3567 Register input_reg = ToRegister(instr->value());
3568 __ test(input_reg, Operand(input_reg)); 3568 __ test(input_reg, Operand(input_reg));
3569 Label is_positive; 3569 Label is_positive;
3570 __ j(not_sign, &is_positive, Label::kNear); 3570 __ j(not_sign, &is_positive, Label::kNear);
3571 __ neg(input_reg); // Sets flags. 3571 __ neg(input_reg); // Sets flags.
3572 DeoptimizeIf(negative, instr); 3572 DeoptimizeIf(negative, instr, "overflow");
3573 __ bind(&is_positive); 3573 __ bind(&is_positive);
3574 } 3574 }
3575 3575
3576 3576
3577 void LCodeGen::DoMathAbs(LMathAbs* instr) { 3577 void LCodeGen::DoMathAbs(LMathAbs* instr) {
3578 // Class for deferred case. 3578 // Class for deferred case.
3579 class DeferredMathAbsTaggedHeapNumber FINAL : public LDeferredCode { 3579 class DeferredMathAbsTaggedHeapNumber FINAL : public LDeferredCode {
3580 public: 3580 public:
3581 DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen, 3581 DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen,
3582 LMathAbs* instr) 3582 LMathAbs* instr)
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
3620 if (CpuFeatures::IsSupported(SSE4_1)) { 3620 if (CpuFeatures::IsSupported(SSE4_1)) {
3621 CpuFeatureScope scope(masm(), SSE4_1); 3621 CpuFeatureScope scope(masm(), SSE4_1);
3622 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 3622 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
3623 // Deoptimize on negative zero. 3623 // Deoptimize on negative zero.
3624 Label non_zero; 3624 Label non_zero;
3625 __ xorps(xmm_scratch, xmm_scratch); // Zero the register. 3625 __ xorps(xmm_scratch, xmm_scratch); // Zero the register.
3626 __ ucomisd(input_reg, xmm_scratch); 3626 __ ucomisd(input_reg, xmm_scratch);
3627 __ j(not_equal, &non_zero, Label::kNear); 3627 __ j(not_equal, &non_zero, Label::kNear);
3628 __ movmskpd(output_reg, input_reg); 3628 __ movmskpd(output_reg, input_reg);
3629 __ test(output_reg, Immediate(1)); 3629 __ test(output_reg, Immediate(1));
3630 DeoptimizeIf(not_zero, instr); 3630 DeoptimizeIf(not_zero, instr, "minus zero");
3631 __ bind(&non_zero); 3631 __ bind(&non_zero);
3632 } 3632 }
3633 __ roundsd(xmm_scratch, input_reg, Assembler::kRoundDown); 3633 __ roundsd(xmm_scratch, input_reg, Assembler::kRoundDown);
3634 __ cvttsd2si(output_reg, Operand(xmm_scratch)); 3634 __ cvttsd2si(output_reg, Operand(xmm_scratch));
3635 // Overflow is signalled with minint. 3635 // Overflow is signalled with minint.
3636 __ cmp(output_reg, 0x1); 3636 __ cmp(output_reg, 0x1);
3637 DeoptimizeIf(overflow, instr); 3637 DeoptimizeIf(overflow, instr, "overflow");
3638 } else { 3638 } else {
3639 Label negative_sign, done; 3639 Label negative_sign, done;
3640 // Deoptimize on unordered. 3640 // Deoptimize on unordered.
3641 __ xorps(xmm_scratch, xmm_scratch); // Zero the register. 3641 __ xorps(xmm_scratch, xmm_scratch); // Zero the register.
3642 __ ucomisd(input_reg, xmm_scratch); 3642 __ ucomisd(input_reg, xmm_scratch);
3643 DeoptimizeIf(parity_even, instr); 3643 DeoptimizeIf(parity_even, instr, "NaN");
3644 __ j(below, &negative_sign, Label::kNear); 3644 __ j(below, &negative_sign, Label::kNear);
3645 3645
3646 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 3646 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
3647 // Check for negative zero. 3647 // Check for negative zero.
3648 Label positive_sign; 3648 Label positive_sign;
3649 __ j(above, &positive_sign, Label::kNear); 3649 __ j(above, &positive_sign, Label::kNear);
3650 __ movmskpd(output_reg, input_reg); 3650 __ movmskpd(output_reg, input_reg);
3651 __ test(output_reg, Immediate(1)); 3651 __ test(output_reg, Immediate(1));
3652 DeoptimizeIf(not_zero, instr); 3652 DeoptimizeIf(not_zero, instr, "minus zero");
3653 __ Move(output_reg, Immediate(0)); 3653 __ Move(output_reg, Immediate(0));
3654 __ jmp(&done, Label::kNear); 3654 __ jmp(&done, Label::kNear);
3655 __ bind(&positive_sign); 3655 __ bind(&positive_sign);
3656 } 3656 }
3657 3657
3658 // Use truncating instruction (OK because input is positive). 3658 // Use truncating instruction (OK because input is positive).
3659 __ cvttsd2si(output_reg, Operand(input_reg)); 3659 __ cvttsd2si(output_reg, Operand(input_reg));
3660 // Overflow is signalled with minint. 3660 // Overflow is signalled with minint.
3661 __ cmp(output_reg, 0x1); 3661 __ cmp(output_reg, 0x1);
3662 DeoptimizeIf(overflow, instr); 3662 DeoptimizeIf(overflow, instr, "overflow");
3663 __ jmp(&done, Label::kNear); 3663 __ jmp(&done, Label::kNear);
3664 3664
3665 // Non-zero negative reaches here. 3665 // Non-zero negative reaches here.
3666 __ bind(&negative_sign); 3666 __ bind(&negative_sign);
3667 // Truncate, then compare and compensate. 3667 // Truncate, then compare and compensate.
3668 __ cvttsd2si(output_reg, Operand(input_reg)); 3668 __ cvttsd2si(output_reg, Operand(input_reg));
3669 __ Cvtsi2sd(xmm_scratch, output_reg); 3669 __ Cvtsi2sd(xmm_scratch, output_reg);
3670 __ ucomisd(input_reg, xmm_scratch); 3670 __ ucomisd(input_reg, xmm_scratch);
3671 __ j(equal, &done, Label::kNear); 3671 __ j(equal, &done, Label::kNear);
3672 __ sub(output_reg, Immediate(1)); 3672 __ sub(output_reg, Immediate(1));
3673 DeoptimizeIf(overflow, instr); 3673 DeoptimizeIf(overflow, instr, "overflow");
3674 3674
3675 __ bind(&done); 3675 __ bind(&done);
3676 } 3676 }
3677 } 3677 }
3678 3678
3679 3679
3680 void LCodeGen::DoMathRound(LMathRound* instr) { 3680 void LCodeGen::DoMathRound(LMathRound* instr) {
3681 Register output_reg = ToRegister(instr->result()); 3681 Register output_reg = ToRegister(instr->result());
3682 XMMRegister input_reg = ToDoubleRegister(instr->value()); 3682 XMMRegister input_reg = ToDoubleRegister(instr->value());
3683 XMMRegister xmm_scratch = double_scratch0(); 3683 XMMRegister xmm_scratch = double_scratch0();
3684 XMMRegister input_temp = ToDoubleRegister(instr->temp()); 3684 XMMRegister input_temp = ToDoubleRegister(instr->temp());
3685 ExternalReference one_half = ExternalReference::address_of_one_half(); 3685 ExternalReference one_half = ExternalReference::address_of_one_half();
3686 ExternalReference minus_one_half = 3686 ExternalReference minus_one_half =
3687 ExternalReference::address_of_minus_one_half(); 3687 ExternalReference::address_of_minus_one_half();
3688 3688
3689 Label done, round_to_zero, below_one_half, do_not_compensate; 3689 Label done, round_to_zero, below_one_half, do_not_compensate;
3690 Label::Distance dist = DeoptEveryNTimes() ? Label::kFar : Label::kNear; 3690 Label::Distance dist = DeoptEveryNTimes() ? Label::kFar : Label::kNear;
3691 3691
3692 __ movsd(xmm_scratch, Operand::StaticVariable(one_half)); 3692 __ movsd(xmm_scratch, Operand::StaticVariable(one_half));
3693 __ ucomisd(xmm_scratch, input_reg); 3693 __ ucomisd(xmm_scratch, input_reg);
3694 __ j(above, &below_one_half, Label::kNear); 3694 __ j(above, &below_one_half, Label::kNear);
3695 3695
3696 // CVTTSD2SI rounds towards zero, since 0.5 <= x, we use floor(0.5 + x). 3696 // CVTTSD2SI rounds towards zero, since 0.5 <= x, we use floor(0.5 + x).
3697 __ addsd(xmm_scratch, input_reg); 3697 __ addsd(xmm_scratch, input_reg);
3698 __ cvttsd2si(output_reg, Operand(xmm_scratch)); 3698 __ cvttsd2si(output_reg, Operand(xmm_scratch));
3699 // Overflow is signalled with minint. 3699 // Overflow is signalled with minint.
3700 __ cmp(output_reg, 0x1); 3700 __ cmp(output_reg, 0x1);
3701 DeoptimizeIf(overflow, instr, "conversion overflow"); 3701 DeoptimizeIf(overflow, instr, "overflow");
3702 __ jmp(&done, dist); 3702 __ jmp(&done, dist);
3703 3703
3704 __ bind(&below_one_half); 3704 __ bind(&below_one_half);
3705 __ movsd(xmm_scratch, Operand::StaticVariable(minus_one_half)); 3705 __ movsd(xmm_scratch, Operand::StaticVariable(minus_one_half));
3706 __ ucomisd(xmm_scratch, input_reg); 3706 __ ucomisd(xmm_scratch, input_reg);
3707 __ j(below_equal, &round_to_zero, Label::kNear); 3707 __ j(below_equal, &round_to_zero, Label::kNear);
3708 3708
3709 // CVTTSD2SI rounds towards zero, we use ceil(x - (-0.5)) and then 3709 // CVTTSD2SI rounds towards zero, we use ceil(x - (-0.5)) and then
3710 // compare and compensate. 3710 // compare and compensate.
3711 __ movaps(input_temp, input_reg); // Do not alter input_reg. 3711 __ movaps(input_temp, input_reg); // Do not alter input_reg.
3712 __ subsd(input_temp, xmm_scratch); 3712 __ subsd(input_temp, xmm_scratch);
3713 __ cvttsd2si(output_reg, Operand(input_temp)); 3713 __ cvttsd2si(output_reg, Operand(input_temp));
3714 // Catch minint due to overflow, and to prevent overflow when compensating. 3714 // Catch minint due to overflow, and to prevent overflow when compensating.
3715 __ cmp(output_reg, 0x1); 3715 __ cmp(output_reg, 0x1);
3716 DeoptimizeIf(overflow, instr, "conversion overflow"); 3716 DeoptimizeIf(overflow, instr, "overflow");
3717 3717
3718 __ Cvtsi2sd(xmm_scratch, output_reg); 3718 __ Cvtsi2sd(xmm_scratch, output_reg);
3719 __ ucomisd(xmm_scratch, input_temp); 3719 __ ucomisd(xmm_scratch, input_temp);
3720 __ j(equal, &done, dist); 3720 __ j(equal, &done, dist);
3721 __ sub(output_reg, Immediate(1)); 3721 __ sub(output_reg, Immediate(1));
3722 // No overflow because we already ruled out minint. 3722 // No overflow because we already ruled out minint.
3723 __ jmp(&done, dist); 3723 __ jmp(&done, dist);
3724 3724
3725 __ bind(&round_to_zero); 3725 __ bind(&round_to_zero);
3726 // We return 0 for the input range [+0, 0.5[, or [-0.5, 0.5[ if 3726 // We return 0 for the input range [+0, 0.5[, or [-0.5, 0.5[ if
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
3798 DCHECK(ToDoubleRegister(instr->result()).is(xmm3)); 3798 DCHECK(ToDoubleRegister(instr->result()).is(xmm3));
3799 3799
3800 if (exponent_type.IsSmi()) { 3800 if (exponent_type.IsSmi()) {
3801 MathPowStub stub(isolate(), MathPowStub::TAGGED); 3801 MathPowStub stub(isolate(), MathPowStub::TAGGED);
3802 __ CallStub(&stub); 3802 __ CallStub(&stub);
3803 } else if (exponent_type.IsTagged()) { 3803 } else if (exponent_type.IsTagged()) {
3804 Label no_deopt; 3804 Label no_deopt;
3805 __ JumpIfSmi(tagged_exponent, &no_deopt); 3805 __ JumpIfSmi(tagged_exponent, &no_deopt);
3806 DCHECK(!ecx.is(tagged_exponent)); 3806 DCHECK(!ecx.is(tagged_exponent));
3807 __ CmpObjectType(tagged_exponent, HEAP_NUMBER_TYPE, ecx); 3807 __ CmpObjectType(tagged_exponent, HEAP_NUMBER_TYPE, ecx);
3808 DeoptimizeIf(not_equal, instr); 3808 DeoptimizeIf(not_equal, instr, "not a heap number");
3809 __ bind(&no_deopt); 3809 __ bind(&no_deopt);
3810 MathPowStub stub(isolate(), MathPowStub::TAGGED); 3810 MathPowStub stub(isolate(), MathPowStub::TAGGED);
3811 __ CallStub(&stub); 3811 __ CallStub(&stub);
3812 } else if (exponent_type.IsInteger32()) { 3812 } else if (exponent_type.IsInteger32()) {
3813 MathPowStub stub(isolate(), MathPowStub::INTEGER); 3813 MathPowStub stub(isolate(), MathPowStub::INTEGER);
3814 __ CallStub(&stub); 3814 __ CallStub(&stub);
3815 } else { 3815 } else {
3816 DCHECK(exponent_type.IsDouble()); 3816 DCHECK(exponent_type.IsDouble());
3817 MathPowStub stub(isolate(), MathPowStub::DOUBLE); 3817 MathPowStub stub(isolate(), MathPowStub::DOUBLE);
3818 __ CallStub(&stub); 3818 __ CallStub(&stub);
(...skipping 291 matching lines...) Expand 10 before | Expand all | Expand 10 after
4110 instr->hydrogen()->index()->representation())); 4110 instr->hydrogen()->index()->representation()));
4111 } else { 4111 } else {
4112 __ cmp(ToRegister(instr->index()), ToOperand(instr->length())); 4112 __ cmp(ToRegister(instr->index()), ToOperand(instr->length()));
4113 } 4113 }
4114 if (FLAG_debug_code && instr->hydrogen()->skip_check()) { 4114 if (FLAG_debug_code && instr->hydrogen()->skip_check()) {
4115 Label done; 4115 Label done;
4116 __ j(NegateCondition(cc), &done, Label::kNear); 4116 __ j(NegateCondition(cc), &done, Label::kNear);
4117 __ int3(); 4117 __ int3();
4118 __ bind(&done); 4118 __ bind(&done);
4119 } else { 4119 } else {
4120 DeoptimizeIf(cc, instr); 4120 DeoptimizeIf(cc, instr, "out of bounds");
4121 } 4121 }
4122 } 4122 }
4123 4123
4124 4124
4125 void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) { 4125 void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) {
4126 ElementsKind elements_kind = instr->elements_kind(); 4126 ElementsKind elements_kind = instr->elements_kind();
4127 LOperand* key = instr->key(); 4127 LOperand* key = instr->key();
4128 if (!key->IsConstantOperand() && 4128 if (!key->IsConstantOperand() &&
4129 ExternalArrayOpRequiresTemp(instr->hydrogen()->key()->representation(), 4129 ExternalArrayOpRequiresTemp(instr->hydrogen()->key()->representation(),
4130 elements_kind)) { 4130 elements_kind)) {
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after
4278 CodeFactory::KeyedStoreIC(isolate(), instr->strict_mode()).code(); 4278 CodeFactory::KeyedStoreIC(isolate(), instr->strict_mode()).code();
4279 CallCode(ic, RelocInfo::CODE_TARGET, instr); 4279 CallCode(ic, RelocInfo::CODE_TARGET, instr);
4280 } 4280 }
4281 4281
4282 4282
4283 void LCodeGen::DoTrapAllocationMemento(LTrapAllocationMemento* instr) { 4283 void LCodeGen::DoTrapAllocationMemento(LTrapAllocationMemento* instr) {
4284 Register object = ToRegister(instr->object()); 4284 Register object = ToRegister(instr->object());
4285 Register temp = ToRegister(instr->temp()); 4285 Register temp = ToRegister(instr->temp());
4286 Label no_memento_found; 4286 Label no_memento_found;
4287 __ TestJSArrayForAllocationMemento(object, temp, &no_memento_found); 4287 __ TestJSArrayForAllocationMemento(object, temp, &no_memento_found);
4288 DeoptimizeIf(equal, instr); 4288 DeoptimizeIf(equal, instr, "memento found");
4289 __ bind(&no_memento_found); 4289 __ bind(&no_memento_found);
4290 } 4290 }
4291 4291
4292 4292
4293 void LCodeGen::DoTransitionElementsKind(LTransitionElementsKind* instr) { 4293 void LCodeGen::DoTransitionElementsKind(LTransitionElementsKind* instr) {
4294 Register object_reg = ToRegister(instr->object()); 4294 Register object_reg = ToRegister(instr->object());
4295 4295
4296 Handle<Map> from_map = instr->original_map(); 4296 Handle<Map> from_map = instr->original_map();
4297 Handle<Map> to_map = instr->transitioned_map(); 4297 Handle<Map> to_map = instr->transitioned_map();
4298 ElementsKind from_kind = instr->from_kind(); 4298 ElementsKind from_kind = instr->from_kind();
(...skipping 324 matching lines...) Expand 10 before | Expand all | Expand 10 after
4623 __ StoreToSafepointRegisterSlot(reg, eax); 4623 __ StoreToSafepointRegisterSlot(reg, eax);
4624 } 4624 }
4625 4625
4626 4626
4627 void LCodeGen::DoSmiTag(LSmiTag* instr) { 4627 void LCodeGen::DoSmiTag(LSmiTag* instr) {
4628 HChange* hchange = instr->hydrogen(); 4628 HChange* hchange = instr->hydrogen();
4629 Register input = ToRegister(instr->value()); 4629 Register input = ToRegister(instr->value());
4630 if (hchange->CheckFlag(HValue::kCanOverflow) && 4630 if (hchange->CheckFlag(HValue::kCanOverflow) &&
4631 hchange->value()->CheckFlag(HValue::kUint32)) { 4631 hchange->value()->CheckFlag(HValue::kUint32)) {
4632 __ test(input, Immediate(0xc0000000)); 4632 __ test(input, Immediate(0xc0000000));
4633 DeoptimizeIf(not_zero, instr); 4633 DeoptimizeIf(not_zero, instr, "overflow");
4634 } 4634 }
4635 __ SmiTag(input); 4635 __ SmiTag(input);
4636 if (hchange->CheckFlag(HValue::kCanOverflow) && 4636 if (hchange->CheckFlag(HValue::kCanOverflow) &&
4637 !hchange->value()->CheckFlag(HValue::kUint32)) { 4637 !hchange->value()->CheckFlag(HValue::kUint32)) {
4638 DeoptimizeIf(overflow, instr); 4638 DeoptimizeIf(overflow, instr, "overflow");
4639 } 4639 }
4640 } 4640 }
4641 4641
4642 4642
4643 void LCodeGen::DoSmiUntag(LSmiUntag* instr) { 4643 void LCodeGen::DoSmiUntag(LSmiUntag* instr) {
4644 LOperand* input = instr->value(); 4644 LOperand* input = instr->value();
4645 Register result = ToRegister(input); 4645 Register result = ToRegister(input);
4646 DCHECK(input->IsRegister() && input->Equals(instr->result())); 4646 DCHECK(input->IsRegister() && input->Equals(instr->result()));
4647 if (instr->needs_check()) { 4647 if (instr->needs_check()) {
4648 __ test(result, Immediate(kSmiTagMask)); 4648 __ test(result, Immediate(kSmiTagMask));
4649 DeoptimizeIf(not_zero, instr); 4649 DeoptimizeIf(not_zero, instr, "not a Smi");
4650 } else { 4650 } else {
4651 __ AssertSmi(result); 4651 __ AssertSmi(result);
4652 } 4652 }
4653 __ SmiUntag(result); 4653 __ SmiUntag(result);
4654 } 4654 }
4655 4655
4656 4656
4657 void LCodeGen::EmitNumberUntagD(LNumberUntagD* instr, Register input_reg, 4657 void LCodeGen::EmitNumberUntagD(LNumberUntagD* instr, Register input_reg,
4658 Register temp_reg, XMMRegister result_reg, 4658 Register temp_reg, XMMRegister result_reg,
4659 NumberUntagDMode mode) { 4659 NumberUntagDMode mode) {
4660 bool can_convert_undefined_to_nan = 4660 bool can_convert_undefined_to_nan =
4661 instr->hydrogen()->can_convert_undefined_to_nan(); 4661 instr->hydrogen()->can_convert_undefined_to_nan();
4662 bool deoptimize_on_minus_zero = instr->hydrogen()->deoptimize_on_minus_zero(); 4662 bool deoptimize_on_minus_zero = instr->hydrogen()->deoptimize_on_minus_zero();
4663 4663
4664 Label convert, load_smi, done; 4664 Label convert, load_smi, done;
4665 4665
4666 if (mode == NUMBER_CANDIDATE_IS_ANY_TAGGED) { 4666 if (mode == NUMBER_CANDIDATE_IS_ANY_TAGGED) {
4667 // Smi check. 4667 // Smi check.
4668 __ JumpIfSmi(input_reg, &load_smi, Label::kNear); 4668 __ JumpIfSmi(input_reg, &load_smi, Label::kNear);
4669 4669
4670 // Heap number map check. 4670 // Heap number map check.
4671 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), 4671 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset),
4672 factory()->heap_number_map()); 4672 factory()->heap_number_map());
4673 if (can_convert_undefined_to_nan) { 4673 if (can_convert_undefined_to_nan) {
4674 __ j(not_equal, &convert, Label::kNear); 4674 __ j(not_equal, &convert, Label::kNear);
4675 } else { 4675 } else {
4676 DeoptimizeIf(not_equal, instr); 4676 DeoptimizeIf(not_equal, instr, "not a heap number");
4677 } 4677 }
4678 4678
4679 // Heap number to XMM conversion. 4679 // Heap number to XMM conversion.
4680 __ movsd(result_reg, FieldOperand(input_reg, HeapNumber::kValueOffset)); 4680 __ movsd(result_reg, FieldOperand(input_reg, HeapNumber::kValueOffset));
4681 4681
4682 if (deoptimize_on_minus_zero) { 4682 if (deoptimize_on_minus_zero) {
4683 XMMRegister xmm_scratch = double_scratch0(); 4683 XMMRegister xmm_scratch = double_scratch0();
4684 __ xorps(xmm_scratch, xmm_scratch); 4684 __ xorps(xmm_scratch, xmm_scratch);
4685 __ ucomisd(result_reg, xmm_scratch); 4685 __ ucomisd(result_reg, xmm_scratch);
4686 __ j(not_zero, &done, Label::kNear); 4686 __ j(not_zero, &done, Label::kNear);
4687 __ movmskpd(temp_reg, result_reg); 4687 __ movmskpd(temp_reg, result_reg);
4688 __ test_b(temp_reg, 1); 4688 __ test_b(temp_reg, 1);
4689 DeoptimizeIf(not_zero, instr); 4689 DeoptimizeIf(not_zero, instr, "minus zero");
4690 } 4690 }
4691 __ jmp(&done, Label::kNear); 4691 __ jmp(&done, Label::kNear);
4692 4692
4693 if (can_convert_undefined_to_nan) { 4693 if (can_convert_undefined_to_nan) {
4694 __ bind(&convert); 4694 __ bind(&convert);
4695 4695
4696 // Convert undefined (and hole) to NaN. 4696 // Convert undefined (and hole) to NaN.
4697 __ cmp(input_reg, factory()->undefined_value()); 4697 __ cmp(input_reg, factory()->undefined_value());
4698 DeoptimizeIf(not_equal, instr); 4698 DeoptimizeIf(not_equal, instr, "not a heap number/undefined");
4699 4699
4700 ExternalReference nan = 4700 ExternalReference nan =
4701 ExternalReference::address_of_canonical_non_hole_nan(); 4701 ExternalReference::address_of_canonical_non_hole_nan();
4702 __ movsd(result_reg, Operand::StaticVariable(nan)); 4702 __ movsd(result_reg, Operand::StaticVariable(nan));
4703 __ jmp(&done, Label::kNear); 4703 __ jmp(&done, Label::kNear);
4704 } 4704 }
4705 } else { 4705 } else {
4706 DCHECK(mode == NUMBER_CANDIDATE_IS_SMI); 4706 DCHECK(mode == NUMBER_CANDIDATE_IS_SMI);
4707 } 4707 }
4708 4708
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
4742 __ jmp(done); 4742 __ jmp(done);
4743 4743
4744 __ bind(&check_bools); 4744 __ bind(&check_bools);
4745 __ cmp(input_reg, factory()->true_value()); 4745 __ cmp(input_reg, factory()->true_value());
4746 __ j(not_equal, &check_false, Label::kNear); 4746 __ j(not_equal, &check_false, Label::kNear);
4747 __ Move(input_reg, Immediate(1)); 4747 __ Move(input_reg, Immediate(1));
4748 __ jmp(done); 4748 __ jmp(done);
4749 4749
4750 __ bind(&check_false); 4750 __ bind(&check_false);
4751 __ cmp(input_reg, factory()->false_value()); 4751 __ cmp(input_reg, factory()->false_value());
4752 DeoptimizeIf(not_equal, instr, "cannot truncate"); 4752 DeoptimizeIf(not_equal, instr, "not a heap number/undefined/true/false");
4753 __ Move(input_reg, Immediate(0)); 4753 __ Move(input_reg, Immediate(0));
4754 } else { 4754 } else {
4755 XMMRegister scratch = ToDoubleRegister(instr->temp()); 4755 XMMRegister scratch = ToDoubleRegister(instr->temp());
4756 DCHECK(!scratch.is(xmm0)); 4756 DCHECK(!scratch.is(xmm0));
4757 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), 4757 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset),
4758 isolate()->factory()->heap_number_map()); 4758 isolate()->factory()->heap_number_map());
4759 DeoptimizeIf(not_equal, instr, "not a heap number"); 4759 DeoptimizeIf(not_equal, instr, "not a heap number");
4760 __ movsd(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset)); 4760 __ movsd(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset));
4761 __ cvttsd2si(input_reg, Operand(xmm0)); 4761 __ cvttsd2si(input_reg, Operand(xmm0));
4762 __ Cvtsi2sd(scratch, Operand(input_reg)); 4762 __ Cvtsi2sd(scratch, Operand(input_reg));
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
4833 LOperand* input = instr->value(); 4833 LOperand* input = instr->value();
4834 DCHECK(input->IsDoubleRegister()); 4834 DCHECK(input->IsDoubleRegister());
4835 LOperand* result = instr->result(); 4835 LOperand* result = instr->result();
4836 DCHECK(result->IsRegister()); 4836 DCHECK(result->IsRegister());
4837 Register result_reg = ToRegister(result); 4837 Register result_reg = ToRegister(result);
4838 4838
4839 if (instr->truncating()) { 4839 if (instr->truncating()) {
4840 XMMRegister input_reg = ToDoubleRegister(input); 4840 XMMRegister input_reg = ToDoubleRegister(input);
4841 __ TruncateDoubleToI(result_reg, input_reg); 4841 __ TruncateDoubleToI(result_reg, input_reg);
4842 } else { 4842 } else {
4843 Label bailout, done; 4843 Label lost_precision, is_nan, minus_zero, done;
4844 XMMRegister input_reg = ToDoubleRegister(input); 4844 XMMRegister input_reg = ToDoubleRegister(input);
4845 XMMRegister xmm_scratch = double_scratch0(); 4845 XMMRegister xmm_scratch = double_scratch0();
4846 __ DoubleToI(result_reg, input_reg, xmm_scratch, 4846 __ DoubleToI(result_reg, input_reg, xmm_scratch,
4847 instr->hydrogen()->GetMinusZeroMode(), &bailout, Label::kNear); 4847 instr->hydrogen()->GetMinusZeroMode(), &lost_precision,
4848 &is_nan, &minus_zero,
4849 DeoptEveryNTimes() ? Label::kFar : Label::kNear);
4848 __ jmp(&done, Label::kNear); 4850 __ jmp(&done, Label::kNear);
4849 __ bind(&bailout); 4851 __ bind(&lost_precision);
4850 DeoptimizeIf(no_condition, instr); 4852 DeoptimizeIf(no_condition, instr, "lost precision");
4853 __ bind(&is_nan);
4854 DeoptimizeIf(no_condition, instr, "NaN");
4855 __ bind(&minus_zero);
4856 DeoptimizeIf(no_condition, instr, "minus zero");
4851 __ bind(&done); 4857 __ bind(&done);
4852 } 4858 }
4853 } 4859 }
4854 4860
4855 4861
4856 void LCodeGen::DoDoubleToSmi(LDoubleToSmi* instr) { 4862 void LCodeGen::DoDoubleToSmi(LDoubleToSmi* instr) {
4857 LOperand* input = instr->value(); 4863 LOperand* input = instr->value();
4858 DCHECK(input->IsDoubleRegister()); 4864 DCHECK(input->IsDoubleRegister());
4859 LOperand* result = instr->result(); 4865 LOperand* result = instr->result();
4860 DCHECK(result->IsRegister()); 4866 DCHECK(result->IsRegister());
4861 Register result_reg = ToRegister(result); 4867 Register result_reg = ToRegister(result);
4862 4868
4863 Label bailout, done; 4869 Label lost_precision, is_nan, minus_zero, done;
4864 XMMRegister input_reg = ToDoubleRegister(input); 4870 XMMRegister input_reg = ToDoubleRegister(input);
4865 XMMRegister xmm_scratch = double_scratch0(); 4871 XMMRegister xmm_scratch = double_scratch0();
4866 __ DoubleToI(result_reg, input_reg, xmm_scratch, 4872 __ DoubleToI(result_reg, input_reg, xmm_scratch,
4867 instr->hydrogen()->GetMinusZeroMode(), &bailout, Label::kNear); 4873 instr->hydrogen()->GetMinusZeroMode(), &lost_precision, &is_nan,
4874 &minus_zero, DeoptEveryNTimes() ? Label::kFar : Label::kNear);
4868 __ jmp(&done, Label::kNear); 4875 __ jmp(&done, Label::kNear);
4869 __ bind(&bailout); 4876 __ bind(&lost_precision);
4870 DeoptimizeIf(no_condition, instr); 4877 DeoptimizeIf(no_condition, instr, "lost precision");
4878 __ bind(&is_nan);
4879 DeoptimizeIf(no_condition, instr, "NaN");
4880 __ bind(&minus_zero);
4881 DeoptimizeIf(no_condition, instr, "minus zero");
4871 __ bind(&done); 4882 __ bind(&done);
4872
4873 __ SmiTag(result_reg); 4883 __ SmiTag(result_reg);
4874 DeoptimizeIf(overflow, instr); 4884 DeoptimizeIf(overflow, instr, "overflow");
4875 } 4885 }
4876 4886
4877 4887
4878 void LCodeGen::DoCheckSmi(LCheckSmi* instr) { 4888 void LCodeGen::DoCheckSmi(LCheckSmi* instr) {
4879 LOperand* input = instr->value(); 4889 LOperand* input = instr->value();
4880 __ test(ToOperand(input), Immediate(kSmiTagMask)); 4890 __ test(ToOperand(input), Immediate(kSmiTagMask));
4881 DeoptimizeIf(not_zero, instr); 4891 DeoptimizeIf(not_zero, instr, "not a Smi");
4882 } 4892 }
4883 4893
4884 4894
4885 void LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) { 4895 void LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) {
4886 if (!instr->hydrogen()->value()->type().IsHeapObject()) { 4896 if (!instr->hydrogen()->value()->type().IsHeapObject()) {
4887 LOperand* input = instr->value(); 4897 LOperand* input = instr->value();
4888 __ test(ToOperand(input), Immediate(kSmiTagMask)); 4898 __ test(ToOperand(input), Immediate(kSmiTagMask));
4889 DeoptimizeIf(zero, instr); 4899 DeoptimizeIf(zero, instr, "Smi");
4890 } 4900 }
4891 } 4901 }
4892 4902
4893 4903
4894 void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) { 4904 void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) {
4895 Register input = ToRegister(instr->value()); 4905 Register input = ToRegister(instr->value());
4896 Register temp = ToRegister(instr->temp()); 4906 Register temp = ToRegister(instr->temp());
4897 4907
4898 __ mov(temp, FieldOperand(input, HeapObject::kMapOffset)); 4908 __ mov(temp, FieldOperand(input, HeapObject::kMapOffset));
4899 4909
4900 if (instr->hydrogen()->is_interval_check()) { 4910 if (instr->hydrogen()->is_interval_check()) {
4901 InstanceType first; 4911 InstanceType first;
4902 InstanceType last; 4912 InstanceType last;
4903 instr->hydrogen()->GetCheckInterval(&first, &last); 4913 instr->hydrogen()->GetCheckInterval(&first, &last);
4904 4914
4905 __ cmpb(FieldOperand(temp, Map::kInstanceTypeOffset), 4915 __ cmpb(FieldOperand(temp, Map::kInstanceTypeOffset),
4906 static_cast<int8_t>(first)); 4916 static_cast<int8_t>(first));
4907 4917
4908 // If there is only one type in the interval check for equality. 4918 // If there is only one type in the interval check for equality.
4909 if (first == last) { 4919 if (first == last) {
4910 DeoptimizeIf(not_equal, instr); 4920 DeoptimizeIf(not_equal, instr, "wrong instance type");
4911 } else { 4921 } else {
4912 DeoptimizeIf(below, instr); 4922 DeoptimizeIf(below, instr, "wrong instance type");
4913 // Omit check for the last type. 4923 // Omit check for the last type.
4914 if (last != LAST_TYPE) { 4924 if (last != LAST_TYPE) {
4915 __ cmpb(FieldOperand(temp, Map::kInstanceTypeOffset), 4925 __ cmpb(FieldOperand(temp, Map::kInstanceTypeOffset),
4916 static_cast<int8_t>(last)); 4926 static_cast<int8_t>(last));
4917 DeoptimizeIf(above, instr); 4927 DeoptimizeIf(above, instr, "wrong instance type");
4918 } 4928 }
4919 } 4929 }
4920 } else { 4930 } else {
4921 uint8_t mask; 4931 uint8_t mask;
4922 uint8_t tag; 4932 uint8_t tag;
4923 instr->hydrogen()->GetCheckMaskAndTag(&mask, &tag); 4933 instr->hydrogen()->GetCheckMaskAndTag(&mask, &tag);
4924 4934
4925 if (base::bits::IsPowerOfTwo32(mask)) { 4935 if (base::bits::IsPowerOfTwo32(mask)) {
4926 DCHECK(tag == 0 || base::bits::IsPowerOfTwo32(tag)); 4936 DCHECK(tag == 0 || base::bits::IsPowerOfTwo32(tag));
4927 __ test_b(FieldOperand(temp, Map::kInstanceTypeOffset), mask); 4937 __ test_b(FieldOperand(temp, Map::kInstanceTypeOffset), mask);
4928 DeoptimizeIf(tag == 0 ? not_zero : zero, instr); 4938 DeoptimizeIf(tag == 0 ? not_zero : zero, instr, "wrong instance type");
4929 } else { 4939 } else {
4930 __ movzx_b(temp, FieldOperand(temp, Map::kInstanceTypeOffset)); 4940 __ movzx_b(temp, FieldOperand(temp, Map::kInstanceTypeOffset));
4931 __ and_(temp, mask); 4941 __ and_(temp, mask);
4932 __ cmp(temp, tag); 4942 __ cmp(temp, tag);
4933 DeoptimizeIf(not_equal, instr); 4943 DeoptimizeIf(not_equal, instr, "wrong instance type");
4934 } 4944 }
4935 } 4945 }
4936 } 4946 }
4937 4947
4938 4948
4939 void LCodeGen::DoCheckValue(LCheckValue* instr) { 4949 void LCodeGen::DoCheckValue(LCheckValue* instr) {
4940 Handle<HeapObject> object = instr->hydrogen()->object().handle(); 4950 Handle<HeapObject> object = instr->hydrogen()->object().handle();
4941 if (instr->hydrogen()->object_in_new_space()) { 4951 if (instr->hydrogen()->object_in_new_space()) {
4942 Register reg = ToRegister(instr->value()); 4952 Register reg = ToRegister(instr->value());
4943 Handle<Cell> cell = isolate()->factory()->NewCell(object); 4953 Handle<Cell> cell = isolate()->factory()->NewCell(object);
4944 __ cmp(reg, Operand::ForCell(cell)); 4954 __ cmp(reg, Operand::ForCell(cell));
4945 } else { 4955 } else {
4946 Operand operand = ToOperand(instr->value()); 4956 Operand operand = ToOperand(instr->value());
4947 __ cmp(operand, object); 4957 __ cmp(operand, object);
4948 } 4958 }
4949 DeoptimizeIf(not_equal, instr); 4959 DeoptimizeIf(not_equal, instr, "value mismatch");
4950 } 4960 }
4951 4961
4952 4962
4953 void LCodeGen::DoDeferredInstanceMigration(LCheckMaps* instr, Register object) { 4963 void LCodeGen::DoDeferredInstanceMigration(LCheckMaps* instr, Register object) {
4954 { 4964 {
4955 PushSafepointRegistersScope scope(this); 4965 PushSafepointRegistersScope scope(this);
4956 __ push(object); 4966 __ push(object);
4957 __ xor_(esi, esi); 4967 __ xor_(esi, esi);
4958 __ CallRuntimeSaveDoubles(Runtime::kTryMigrateInstance); 4968 __ CallRuntimeSaveDoubles(Runtime::kTryMigrateInstance);
4959 RecordSafepointWithRegisters( 4969 RecordSafepointWithRegisters(
4960 instr->pointer_map(), 1, Safepoint::kNoLazyDeopt); 4970 instr->pointer_map(), 1, Safepoint::kNoLazyDeopt);
4961 4971
4962 __ test(eax, Immediate(kSmiTagMask)); 4972 __ test(eax, Immediate(kSmiTagMask));
4963 } 4973 }
4964 DeoptimizeIf(zero, instr); 4974 DeoptimizeIf(zero, instr, "instance migration failed");
4965 } 4975 }
4966 4976
4967 4977
4968 void LCodeGen::DoCheckMaps(LCheckMaps* instr) { 4978 void LCodeGen::DoCheckMaps(LCheckMaps* instr) {
4969 class DeferredCheckMaps FINAL : public LDeferredCode { 4979 class DeferredCheckMaps FINAL : public LDeferredCode {
4970 public: 4980 public:
4971 DeferredCheckMaps(LCodeGen* codegen, LCheckMaps* instr, Register object) 4981 DeferredCheckMaps(LCodeGen* codegen, LCheckMaps* instr, Register object)
4972 : LDeferredCode(codegen), instr_(instr), object_(object) { 4982 : LDeferredCode(codegen), instr_(instr), object_(object) {
4973 SetExit(check_maps()); 4983 SetExit(check_maps());
4974 } 4984 }
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
5007 Handle<Map> map = maps->at(i).handle(); 5017 Handle<Map> map = maps->at(i).handle();
5008 __ CompareMap(reg, map); 5018 __ CompareMap(reg, map);
5009 __ j(equal, &success, Label::kNear); 5019 __ j(equal, &success, Label::kNear);
5010 } 5020 }
5011 5021
5012 Handle<Map> map = maps->at(maps->size() - 1).handle(); 5022 Handle<Map> map = maps->at(maps->size() - 1).handle();
5013 __ CompareMap(reg, map); 5023 __ CompareMap(reg, map);
5014 if (instr->hydrogen()->HasMigrationTarget()) { 5024 if (instr->hydrogen()->HasMigrationTarget()) {
5015 __ j(not_equal, deferred->entry()); 5025 __ j(not_equal, deferred->entry());
5016 } else { 5026 } else {
5017 DeoptimizeIf(not_equal, instr); 5027 DeoptimizeIf(not_equal, instr, "wrong map");
5018 } 5028 }
5019 5029
5020 __ bind(&success); 5030 __ bind(&success);
5021 } 5031 }
5022 5032
5023 5033
5024 void LCodeGen::DoClampDToUint8(LClampDToUint8* instr) { 5034 void LCodeGen::DoClampDToUint8(LClampDToUint8* instr) {
5025 XMMRegister value_reg = ToDoubleRegister(instr->unclamped()); 5035 XMMRegister value_reg = ToDoubleRegister(instr->unclamped());
5026 XMMRegister xmm_scratch = double_scratch0(); 5036 XMMRegister xmm_scratch = double_scratch0();
5027 Register result_reg = ToRegister(instr->result()); 5037 Register result_reg = ToRegister(instr->result());
(...skipping 18 matching lines...) Expand all
5046 __ JumpIfSmi(input_reg, &is_smi); 5056 __ JumpIfSmi(input_reg, &is_smi);
5047 5057
5048 // Check for heap number 5058 // Check for heap number
5049 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), 5059 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset),
5050 factory()->heap_number_map()); 5060 factory()->heap_number_map());
5051 __ j(equal, &heap_number, Label::kNear); 5061 __ j(equal, &heap_number, Label::kNear);
5052 5062
5053 // Check for undefined. Undefined is converted to zero for clamping 5063 // Check for undefined. Undefined is converted to zero for clamping
5054 // conversions. 5064 // conversions.
5055 __ cmp(input_reg, factory()->undefined_value()); 5065 __ cmp(input_reg, factory()->undefined_value());
5056 DeoptimizeIf(not_equal, instr); 5066 DeoptimizeIf(not_equal, instr, "not a heap number/undefined");
5057 __ mov(input_reg, 0); 5067 __ mov(input_reg, 0);
5058 __ jmp(&done, Label::kNear); 5068 __ jmp(&done, Label::kNear);
5059 5069
5060 // Heap number 5070 // Heap number
5061 __ bind(&heap_number); 5071 __ bind(&heap_number);
5062 __ movsd(xmm_scratch, FieldOperand(input_reg, HeapNumber::kValueOffset)); 5072 __ movsd(xmm_scratch, FieldOperand(input_reg, HeapNumber::kValueOffset));
5063 __ ClampDoubleToUint8(xmm_scratch, temp_xmm_reg, input_reg); 5073 __ ClampDoubleToUint8(xmm_scratch, temp_xmm_reg, input_reg);
5064 __ jmp(&done, Label::kNear); 5074 __ jmp(&done, Label::kNear);
5065 5075
5066 // smi 5076 // smi
(...skipping 469 matching lines...) Expand 10 before | Expand all | Expand 10 after
5536 DCHECK(!environment->HasBeenRegistered()); 5546 DCHECK(!environment->HasBeenRegistered());
5537 RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt); 5547 RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt);
5538 5548
5539 GenerateOsrPrologue(); 5549 GenerateOsrPrologue();
5540 } 5550 }
5541 5551
5542 5552
5543 void LCodeGen::DoForInPrepareMap(LForInPrepareMap* instr) { 5553 void LCodeGen::DoForInPrepareMap(LForInPrepareMap* instr) {
5544 DCHECK(ToRegister(instr->context()).is(esi)); 5554 DCHECK(ToRegister(instr->context()).is(esi));
5545 __ cmp(eax, isolate()->factory()->undefined_value()); 5555 __ cmp(eax, isolate()->factory()->undefined_value());
5546 DeoptimizeIf(equal, instr); 5556 DeoptimizeIf(equal, instr, "undefined");
5547 5557
5548 __ cmp(eax, isolate()->factory()->null_value()); 5558 __ cmp(eax, isolate()->factory()->null_value());
5549 DeoptimizeIf(equal, instr); 5559 DeoptimizeIf(equal, instr, "null");
5550 5560
5551 __ test(eax, Immediate(kSmiTagMask)); 5561 __ test(eax, Immediate(kSmiTagMask));
5552 DeoptimizeIf(zero, instr); 5562 DeoptimizeIf(zero, instr, "Smi");
5553 5563
5554 STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE); 5564 STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE);
5555 __ CmpObjectType(eax, LAST_JS_PROXY_TYPE, ecx); 5565 __ CmpObjectType(eax, LAST_JS_PROXY_TYPE, ecx);
5556 DeoptimizeIf(below_equal, instr); 5566 DeoptimizeIf(below_equal, instr, "wrong instance type");
5557 5567
5558 Label use_cache, call_runtime; 5568 Label use_cache, call_runtime;
5559 __ CheckEnumCache(&call_runtime); 5569 __ CheckEnumCache(&call_runtime);
5560 5570
5561 __ mov(eax, FieldOperand(eax, HeapObject::kMapOffset)); 5571 __ mov(eax, FieldOperand(eax, HeapObject::kMapOffset));
5562 __ jmp(&use_cache, Label::kNear); 5572 __ jmp(&use_cache, Label::kNear);
5563 5573
5564 // Get the set of properties to enumerate. 5574 // Get the set of properties to enumerate.
5565 __ bind(&call_runtime); 5575 __ bind(&call_runtime);
5566 __ push(eax); 5576 __ push(eax);
5567 CallRuntime(Runtime::kGetPropertyNamesFast, 1, instr); 5577 CallRuntime(Runtime::kGetPropertyNamesFast, 1, instr);
5568 5578
5569 __ cmp(FieldOperand(eax, HeapObject::kMapOffset), 5579 __ cmp(FieldOperand(eax, HeapObject::kMapOffset),
5570 isolate()->factory()->meta_map()); 5580 isolate()->factory()->meta_map());
5571 DeoptimizeIf(not_equal, instr); 5581 DeoptimizeIf(not_equal, instr, "wrong map");
5572 __ bind(&use_cache); 5582 __ bind(&use_cache);
5573 } 5583 }
5574 5584
5575 5585
5576 void LCodeGen::DoForInCacheArray(LForInCacheArray* instr) { 5586 void LCodeGen::DoForInCacheArray(LForInCacheArray* instr) {
5577 Register map = ToRegister(instr->map()); 5587 Register map = ToRegister(instr->map());
5578 Register result = ToRegister(instr->result()); 5588 Register result = ToRegister(instr->result());
5579 Label load_cache, done; 5589 Label load_cache, done;
5580 __ EnumLength(result, map); 5590 __ EnumLength(result, map);
5581 __ cmp(result, Immediate(Smi::FromInt(0))); 5591 __ cmp(result, Immediate(Smi::FromInt(0)));
5582 __ j(not_equal, &load_cache, Label::kNear); 5592 __ j(not_equal, &load_cache, Label::kNear);
5583 __ mov(result, isolate()->factory()->empty_fixed_array()); 5593 __ mov(result, isolate()->factory()->empty_fixed_array());
5584 __ jmp(&done, Label::kNear); 5594 __ jmp(&done, Label::kNear);
5585 5595
5586 __ bind(&load_cache); 5596 __ bind(&load_cache);
5587 __ LoadInstanceDescriptors(map, result); 5597 __ LoadInstanceDescriptors(map, result);
5588 __ mov(result, 5598 __ mov(result,
5589 FieldOperand(result, DescriptorArray::kEnumCacheOffset)); 5599 FieldOperand(result, DescriptorArray::kEnumCacheOffset));
5590 __ mov(result, 5600 __ mov(result,
5591 FieldOperand(result, FixedArray::SizeFor(instr->idx()))); 5601 FieldOperand(result, FixedArray::SizeFor(instr->idx())));
5592 __ bind(&done); 5602 __ bind(&done);
5593 __ test(result, result); 5603 __ test(result, result);
5594 DeoptimizeIf(equal, instr); 5604 DeoptimizeIf(equal, instr, "no cache");
5595 } 5605 }
5596 5606
5597 5607
5598 void LCodeGen::DoCheckMapValue(LCheckMapValue* instr) { 5608 void LCodeGen::DoCheckMapValue(LCheckMapValue* instr) {
5599 Register object = ToRegister(instr->value()); 5609 Register object = ToRegister(instr->value());
5600 __ cmp(ToRegister(instr->map()), 5610 __ cmp(ToRegister(instr->map()),
5601 FieldOperand(object, HeapObject::kMapOffset)); 5611 FieldOperand(object, HeapObject::kMapOffset));
5602 DeoptimizeIf(not_equal, instr); 5612 DeoptimizeIf(not_equal, instr, "wrong map");
5603 } 5613 }
5604 5614
5605 5615
5606 void LCodeGen::DoDeferredLoadMutableDouble(LLoadFieldByIndex* instr, 5616 void LCodeGen::DoDeferredLoadMutableDouble(LLoadFieldByIndex* instr,
5607 Register object, 5617 Register object,
5608 Register index) { 5618 Register index) {
5609 PushSafepointRegistersScope scope(this); 5619 PushSafepointRegistersScope scope(this);
5610 __ push(object); 5620 __ push(object);
5611 __ push(index); 5621 __ push(index);
5612 __ xor_(esi, esi); 5622 __ xor_(esi, esi);
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
5686 CallRuntime(Runtime::kPushBlockContext, 2, instr); 5696 CallRuntime(Runtime::kPushBlockContext, 2, instr);
5687 RecordSafepoint(Safepoint::kNoLazyDeopt); 5697 RecordSafepoint(Safepoint::kNoLazyDeopt);
5688 } 5698 }
5689 5699
5690 5700
5691 #undef __ 5701 #undef __
5692 5702
5693 } } // namespace v8::internal 5703 } } // namespace v8::internal
5694 5704
5695 #endif // V8_TARGET_ARCH_IA32 5705 #endif // V8_TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « src/ia32/lithium-codegen-ia32.h ('k') | src/ia32/macro-assembler-ia32.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698