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

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

Issue 598953002: Make the detailed reason for deopts mandatory on all platforms. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: rebased 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/arm/lithium-codegen-arm.h ('k') | src/arm64/lithium-codegen-arm64.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 #include "src/arm/lithium-codegen-arm.h" 7 #include "src/arm/lithium-codegen-arm.h"
8 #include "src/arm/lithium-gap-resolver-arm.h" 8 #include "src/arm/lithium-gap-resolver-arm.h"
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 1140 matching lines...) Expand 10 before | Expand all | Expand 10 after
1151 int32_t mask = divisor < 0 ? -(divisor + 1) : (divisor - 1); 1151 int32_t mask = divisor < 0 ? -(divisor + 1) : (divisor - 1);
1152 Label dividend_is_not_negative, done; 1152 Label dividend_is_not_negative, done;
1153 if (hmod->CheckFlag(HValue::kLeftCanBeNegative)) { 1153 if (hmod->CheckFlag(HValue::kLeftCanBeNegative)) {
1154 __ cmp(dividend, Operand::Zero()); 1154 __ cmp(dividend, Operand::Zero());
1155 __ b(pl, &dividend_is_not_negative); 1155 __ b(pl, &dividend_is_not_negative);
1156 // Note that this is correct even for kMinInt operands. 1156 // Note that this is correct even for kMinInt operands.
1157 __ rsb(dividend, dividend, Operand::Zero()); 1157 __ rsb(dividend, dividend, Operand::Zero());
1158 __ and_(dividend, dividend, Operand(mask)); 1158 __ and_(dividend, dividend, Operand(mask));
1159 __ rsb(dividend, dividend, Operand::Zero(), SetCC); 1159 __ rsb(dividend, dividend, Operand::Zero(), SetCC);
1160 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { 1160 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
1161 DeoptimizeIf(eq, instr); 1161 DeoptimizeIf(eq, instr, "minus zero");
1162 } 1162 }
1163 __ b(&done); 1163 __ b(&done);
1164 } 1164 }
1165 1165
1166 __ bind(&dividend_is_not_negative); 1166 __ bind(&dividend_is_not_negative);
1167 __ and_(dividend, dividend, Operand(mask)); 1167 __ and_(dividend, dividend, Operand(mask));
1168 __ bind(&done); 1168 __ bind(&done);
1169 } 1169 }
1170 1170
1171 1171
1172 void LCodeGen::DoModByConstI(LModByConstI* instr) { 1172 void LCodeGen::DoModByConstI(LModByConstI* instr) {
1173 Register dividend = ToRegister(instr->dividend()); 1173 Register dividend = ToRegister(instr->dividend());
1174 int32_t divisor = instr->divisor(); 1174 int32_t divisor = instr->divisor();
1175 Register result = ToRegister(instr->result()); 1175 Register result = ToRegister(instr->result());
1176 DCHECK(!dividend.is(result)); 1176 DCHECK(!dividend.is(result));
1177 1177
1178 if (divisor == 0) { 1178 if (divisor == 0) {
1179 DeoptimizeIf(al, instr); 1179 DeoptimizeIf(al, instr, "division by zero");
1180 return; 1180 return;
1181 } 1181 }
1182 1182
1183 __ TruncatingDiv(result, dividend, Abs(divisor)); 1183 __ TruncatingDiv(result, dividend, Abs(divisor));
1184 __ mov(ip, Operand(Abs(divisor))); 1184 __ mov(ip, Operand(Abs(divisor)));
1185 __ smull(result, ip, result, ip); 1185 __ smull(result, ip, result, ip);
1186 __ sub(result, dividend, result, SetCC); 1186 __ sub(result, dividend, result, SetCC);
1187 1187
1188 // Check for negative zero. 1188 // Check for negative zero.
1189 HMod* hmod = instr->hydrogen(); 1189 HMod* hmod = instr->hydrogen();
1190 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { 1190 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
1191 Label remainder_not_zero; 1191 Label remainder_not_zero;
1192 __ b(ne, &remainder_not_zero); 1192 __ b(ne, &remainder_not_zero);
1193 __ cmp(dividend, Operand::Zero()); 1193 __ cmp(dividend, Operand::Zero());
1194 DeoptimizeIf(lt, instr); 1194 DeoptimizeIf(lt, instr, "minus zero");
1195 __ bind(&remainder_not_zero); 1195 __ bind(&remainder_not_zero);
1196 } 1196 }
1197 } 1197 }
1198 1198
1199 1199
1200 void LCodeGen::DoModI(LModI* instr) { 1200 void LCodeGen::DoModI(LModI* instr) {
1201 HMod* hmod = instr->hydrogen(); 1201 HMod* hmod = instr->hydrogen();
1202 if (CpuFeatures::IsSupported(SUDIV)) { 1202 if (CpuFeatures::IsSupported(SUDIV)) {
1203 CpuFeatureScope scope(masm(), SUDIV); 1203 CpuFeatureScope scope(masm(), SUDIV);
1204 1204
1205 Register left_reg = ToRegister(instr->left()); 1205 Register left_reg = ToRegister(instr->left());
1206 Register right_reg = ToRegister(instr->right()); 1206 Register right_reg = ToRegister(instr->right());
1207 Register result_reg = ToRegister(instr->result()); 1207 Register result_reg = ToRegister(instr->result());
1208 1208
1209 Label done; 1209 Label done;
1210 // Check for x % 0, sdiv might signal an exception. We have to deopt in this 1210 // Check for x % 0, sdiv might signal an exception. We have to deopt in this
1211 // case because we can't return a NaN. 1211 // case because we can't return a NaN.
1212 if (hmod->CheckFlag(HValue::kCanBeDivByZero)) { 1212 if (hmod->CheckFlag(HValue::kCanBeDivByZero)) {
1213 __ cmp(right_reg, Operand::Zero()); 1213 __ cmp(right_reg, Operand::Zero());
1214 DeoptimizeIf(eq, instr); 1214 DeoptimizeIf(eq, instr, "division by zero");
1215 } 1215 }
1216 1216
1217 // Check for kMinInt % -1, sdiv will return kMinInt, which is not what we 1217 // Check for kMinInt % -1, sdiv will return kMinInt, which is not what we
1218 // want. We have to deopt if we care about -0, because we can't return that. 1218 // want. We have to deopt if we care about -0, because we can't return that.
1219 if (hmod->CheckFlag(HValue::kCanOverflow)) { 1219 if (hmod->CheckFlag(HValue::kCanOverflow)) {
1220 Label no_overflow_possible; 1220 Label no_overflow_possible;
1221 __ cmp(left_reg, Operand(kMinInt)); 1221 __ cmp(left_reg, Operand(kMinInt));
1222 __ b(ne, &no_overflow_possible); 1222 __ b(ne, &no_overflow_possible);
1223 __ cmp(right_reg, Operand(-1)); 1223 __ cmp(right_reg, Operand(-1));
1224 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { 1224 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
1225 DeoptimizeIf(eq, instr); 1225 DeoptimizeIf(eq, instr, "minus zero");
1226 } else { 1226 } else {
1227 __ b(ne, &no_overflow_possible); 1227 __ b(ne, &no_overflow_possible);
1228 __ mov(result_reg, Operand::Zero()); 1228 __ mov(result_reg, Operand::Zero());
1229 __ jmp(&done); 1229 __ jmp(&done);
1230 } 1230 }
1231 __ bind(&no_overflow_possible); 1231 __ bind(&no_overflow_possible);
1232 } 1232 }
1233 1233
1234 // For 'r3 = r1 % r2' we can have the following ARM code: 1234 // For 'r3 = r1 % r2' we can have the following ARM code:
1235 // sdiv r3, r1, r2 1235 // sdiv r3, r1, r2
1236 // mls r3, r3, r2, r1 1236 // mls r3, r3, r2, r1
1237 1237
1238 __ sdiv(result_reg, left_reg, right_reg); 1238 __ sdiv(result_reg, left_reg, right_reg);
1239 __ Mls(result_reg, result_reg, right_reg, left_reg); 1239 __ Mls(result_reg, result_reg, right_reg, left_reg);
1240 1240
1241 // If we care about -0, test if the dividend is <0 and the result is 0. 1241 // If we care about -0, test if the dividend is <0 and the result is 0.
1242 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { 1242 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
1243 __ cmp(result_reg, Operand::Zero()); 1243 __ cmp(result_reg, Operand::Zero());
1244 __ b(ne, &done); 1244 __ b(ne, &done);
1245 __ cmp(left_reg, Operand::Zero()); 1245 __ cmp(left_reg, Operand::Zero());
1246 DeoptimizeIf(lt, instr); 1246 DeoptimizeIf(lt, instr, "minus zero");
1247 } 1247 }
1248 __ bind(&done); 1248 __ bind(&done);
1249 1249
1250 } else { 1250 } else {
1251 // General case, without any SDIV support. 1251 // General case, without any SDIV support.
1252 Register left_reg = ToRegister(instr->left()); 1252 Register left_reg = ToRegister(instr->left());
1253 Register right_reg = ToRegister(instr->right()); 1253 Register right_reg = ToRegister(instr->right());
1254 Register result_reg = ToRegister(instr->result()); 1254 Register result_reg = ToRegister(instr->result());
1255 Register scratch = scratch0(); 1255 Register scratch = scratch0();
1256 DCHECK(!scratch.is(left_reg)); 1256 DCHECK(!scratch.is(left_reg));
1257 DCHECK(!scratch.is(right_reg)); 1257 DCHECK(!scratch.is(right_reg));
1258 DCHECK(!scratch.is(result_reg)); 1258 DCHECK(!scratch.is(result_reg));
1259 DwVfpRegister dividend = ToDoubleRegister(instr->temp()); 1259 DwVfpRegister dividend = ToDoubleRegister(instr->temp());
1260 DwVfpRegister divisor = ToDoubleRegister(instr->temp2()); 1260 DwVfpRegister divisor = ToDoubleRegister(instr->temp2());
1261 DCHECK(!divisor.is(dividend)); 1261 DCHECK(!divisor.is(dividend));
1262 LowDwVfpRegister quotient = double_scratch0(); 1262 LowDwVfpRegister quotient = double_scratch0();
1263 DCHECK(!quotient.is(dividend)); 1263 DCHECK(!quotient.is(dividend));
1264 DCHECK(!quotient.is(divisor)); 1264 DCHECK(!quotient.is(divisor));
1265 1265
1266 Label done; 1266 Label done;
1267 // Check for x % 0, we have to deopt in this case because we can't return a 1267 // Check for x % 0, we have to deopt in this case because we can't return a
1268 // NaN. 1268 // NaN.
1269 if (hmod->CheckFlag(HValue::kCanBeDivByZero)) { 1269 if (hmod->CheckFlag(HValue::kCanBeDivByZero)) {
1270 __ cmp(right_reg, Operand::Zero()); 1270 __ cmp(right_reg, Operand::Zero());
1271 DeoptimizeIf(eq, instr); 1271 DeoptimizeIf(eq, instr, "division by zero");
1272 } 1272 }
1273 1273
1274 __ Move(result_reg, left_reg); 1274 __ Move(result_reg, left_reg);
1275 // Load the arguments in VFP registers. The divisor value is preloaded 1275 // Load the arguments in VFP registers. The divisor value is preloaded
1276 // before. Be careful that 'right_reg' is only live on entry. 1276 // before. Be careful that 'right_reg' is only live on entry.
1277 // TODO(svenpanne) The last comments seems to be wrong nowadays. 1277 // TODO(svenpanne) The last comments seems to be wrong nowadays.
1278 __ vmov(double_scratch0().low(), left_reg); 1278 __ vmov(double_scratch0().low(), left_reg);
1279 __ vcvt_f64_s32(dividend, double_scratch0().low()); 1279 __ vcvt_f64_s32(dividend, double_scratch0().low());
1280 __ vmov(double_scratch0().low(), right_reg); 1280 __ vmov(double_scratch0().low(), right_reg);
1281 __ vcvt_f64_s32(divisor, double_scratch0().low()); 1281 __ vcvt_f64_s32(divisor, double_scratch0().low());
1282 1282
1283 // We do not care about the sign of the divisor. Note that we still handle 1283 // We do not care about the sign of the divisor. Note that we still handle
1284 // the kMinInt % -1 case correctly, though. 1284 // the kMinInt % -1 case correctly, though.
1285 __ vabs(divisor, divisor); 1285 __ vabs(divisor, divisor);
1286 // Compute the quotient and round it to a 32bit integer. 1286 // Compute the quotient and round it to a 32bit integer.
1287 __ vdiv(quotient, dividend, divisor); 1287 __ vdiv(quotient, dividend, divisor);
1288 __ vcvt_s32_f64(quotient.low(), quotient); 1288 __ vcvt_s32_f64(quotient.low(), quotient);
1289 __ vcvt_f64_s32(quotient, quotient.low()); 1289 __ vcvt_f64_s32(quotient, quotient.low());
1290 1290
1291 // Compute the remainder in result. 1291 // Compute the remainder in result.
1292 __ vmul(double_scratch0(), divisor, quotient); 1292 __ vmul(double_scratch0(), divisor, quotient);
1293 __ vcvt_s32_f64(double_scratch0().low(), double_scratch0()); 1293 __ vcvt_s32_f64(double_scratch0().low(), double_scratch0());
1294 __ vmov(scratch, double_scratch0().low()); 1294 __ vmov(scratch, double_scratch0().low());
1295 __ sub(result_reg, left_reg, scratch, SetCC); 1295 __ sub(result_reg, left_reg, scratch, SetCC);
1296 1296
1297 // If we care about -0, test if the dividend is <0 and the result is 0. 1297 // If we care about -0, test if the dividend is <0 and the result is 0.
1298 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { 1298 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
1299 __ b(ne, &done); 1299 __ b(ne, &done);
1300 __ cmp(left_reg, Operand::Zero()); 1300 __ cmp(left_reg, Operand::Zero());
1301 DeoptimizeIf(mi, instr); 1301 DeoptimizeIf(mi, instr, "minus zero");
1302 } 1302 }
1303 __ bind(&done); 1303 __ bind(&done);
1304 } 1304 }
1305 } 1305 }
1306 1306
1307 1307
1308 void LCodeGen::DoDivByPowerOf2I(LDivByPowerOf2I* instr) { 1308 void LCodeGen::DoDivByPowerOf2I(LDivByPowerOf2I* instr) {
1309 Register dividend = ToRegister(instr->dividend()); 1309 Register dividend = ToRegister(instr->dividend());
1310 int32_t divisor = instr->divisor(); 1310 int32_t divisor = instr->divisor();
1311 Register result = ToRegister(instr->result()); 1311 Register result = ToRegister(instr->result());
1312 DCHECK(divisor == kMinInt || base::bits::IsPowerOfTwo32(Abs(divisor))); 1312 DCHECK(divisor == kMinInt || base::bits::IsPowerOfTwo32(Abs(divisor)));
1313 DCHECK(!result.is(dividend)); 1313 DCHECK(!result.is(dividend));
1314 1314
1315 // Check for (0 / -x) that will produce negative zero. 1315 // Check for (0 / -x) that will produce negative zero.
1316 HDiv* hdiv = instr->hydrogen(); 1316 HDiv* hdiv = instr->hydrogen();
1317 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) { 1317 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) {
1318 __ cmp(dividend, Operand::Zero()); 1318 __ cmp(dividend, Operand::Zero());
1319 DeoptimizeIf(eq, instr); 1319 DeoptimizeIf(eq, instr, "minus zero");
1320 } 1320 }
1321 // Check for (kMinInt / -1). 1321 // Check for (kMinInt / -1).
1322 if (hdiv->CheckFlag(HValue::kCanOverflow) && divisor == -1) { 1322 if (hdiv->CheckFlag(HValue::kCanOverflow) && divisor == -1) {
1323 __ cmp(dividend, Operand(kMinInt)); 1323 __ cmp(dividend, Operand(kMinInt));
1324 DeoptimizeIf(eq, instr); 1324 DeoptimizeIf(eq, instr, "overflow");
1325 } 1325 }
1326 // Deoptimize if remainder will not be 0. 1326 // Deoptimize if remainder will not be 0.
1327 if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32) && 1327 if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32) &&
1328 divisor != 1 && divisor != -1) { 1328 divisor != 1 && divisor != -1) {
1329 int32_t mask = divisor < 0 ? -(divisor + 1) : (divisor - 1); 1329 int32_t mask = divisor < 0 ? -(divisor + 1) : (divisor - 1);
1330 __ tst(dividend, Operand(mask)); 1330 __ tst(dividend, Operand(mask));
1331 DeoptimizeIf(ne, instr); 1331 DeoptimizeIf(ne, instr, "lost precision");
1332 } 1332 }
1333 1333
1334 if (divisor == -1) { // Nice shortcut, not needed for correctness. 1334 if (divisor == -1) { // Nice shortcut, not needed for correctness.
1335 __ rsb(result, dividend, Operand(0)); 1335 __ rsb(result, dividend, Operand(0));
1336 return; 1336 return;
1337 } 1337 }
1338 int32_t shift = WhichPowerOf2Abs(divisor); 1338 int32_t shift = WhichPowerOf2Abs(divisor);
1339 if (shift == 0) { 1339 if (shift == 0) {
1340 __ mov(result, dividend); 1340 __ mov(result, dividend);
1341 } else if (shift == 1) { 1341 } else if (shift == 1) {
1342 __ add(result, dividend, Operand(dividend, LSR, 31)); 1342 __ add(result, dividend, Operand(dividend, LSR, 31));
1343 } else { 1343 } else {
1344 __ mov(result, Operand(dividend, ASR, 31)); 1344 __ mov(result, Operand(dividend, ASR, 31));
1345 __ add(result, dividend, Operand(result, LSR, 32 - shift)); 1345 __ add(result, dividend, Operand(result, LSR, 32 - shift));
1346 } 1346 }
1347 if (shift > 0) __ mov(result, Operand(result, ASR, shift)); 1347 if (shift > 0) __ mov(result, Operand(result, ASR, shift));
1348 if (divisor < 0) __ rsb(result, result, Operand(0)); 1348 if (divisor < 0) __ rsb(result, result, Operand(0));
1349 } 1349 }
1350 1350
1351 1351
1352 void LCodeGen::DoDivByConstI(LDivByConstI* instr) { 1352 void LCodeGen::DoDivByConstI(LDivByConstI* instr) {
1353 Register dividend = ToRegister(instr->dividend()); 1353 Register dividend = ToRegister(instr->dividend());
1354 int32_t divisor = instr->divisor(); 1354 int32_t divisor = instr->divisor();
1355 Register result = ToRegister(instr->result()); 1355 Register result = ToRegister(instr->result());
1356 DCHECK(!dividend.is(result)); 1356 DCHECK(!dividend.is(result));
1357 1357
1358 if (divisor == 0) { 1358 if (divisor == 0) {
1359 DeoptimizeIf(al, instr); 1359 DeoptimizeIf(al, instr, "division by zero");
1360 return; 1360 return;
1361 } 1361 }
1362 1362
1363 // Check for (0 / -x) that will produce negative zero. 1363 // Check for (0 / -x) that will produce negative zero.
1364 HDiv* hdiv = instr->hydrogen(); 1364 HDiv* hdiv = instr->hydrogen();
1365 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) { 1365 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) {
1366 __ cmp(dividend, Operand::Zero()); 1366 __ cmp(dividend, Operand::Zero());
1367 DeoptimizeIf(eq, instr); 1367 DeoptimizeIf(eq, instr, "minus zero");
1368 } 1368 }
1369 1369
1370 __ TruncatingDiv(result, dividend, Abs(divisor)); 1370 __ TruncatingDiv(result, dividend, Abs(divisor));
1371 if (divisor < 0) __ rsb(result, result, Operand::Zero()); 1371 if (divisor < 0) __ rsb(result, result, Operand::Zero());
1372 1372
1373 if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32)) { 1373 if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32)) {
1374 __ mov(ip, Operand(divisor)); 1374 __ mov(ip, Operand(divisor));
1375 __ smull(scratch0(), ip, result, ip); 1375 __ smull(scratch0(), ip, result, ip);
1376 __ sub(scratch0(), scratch0(), dividend, SetCC); 1376 __ sub(scratch0(), scratch0(), dividend, SetCC);
1377 DeoptimizeIf(ne, instr); 1377 DeoptimizeIf(ne, instr, "lost precision");
1378 } 1378 }
1379 } 1379 }
1380 1380
1381 1381
1382 // TODO(svenpanne) Refactor this to avoid code duplication with DoFlooringDivI. 1382 // TODO(svenpanne) Refactor this to avoid code duplication with DoFlooringDivI.
1383 void LCodeGen::DoDivI(LDivI* instr) { 1383 void LCodeGen::DoDivI(LDivI* instr) {
1384 HBinaryOperation* hdiv = instr->hydrogen(); 1384 HBinaryOperation* hdiv = instr->hydrogen();
1385 Register dividend = ToRegister(instr->dividend()); 1385 Register dividend = ToRegister(instr->dividend());
1386 Register divisor = ToRegister(instr->divisor()); 1386 Register divisor = ToRegister(instr->divisor());
1387 Register result = ToRegister(instr->result()); 1387 Register result = ToRegister(instr->result());
1388 1388
1389 // Check for x / 0. 1389 // Check for x / 0.
1390 if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) { 1390 if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) {
1391 __ cmp(divisor, Operand::Zero()); 1391 __ cmp(divisor, Operand::Zero());
1392 DeoptimizeIf(eq, instr); 1392 DeoptimizeIf(eq, instr, "division by zero");
1393 } 1393 }
1394 1394
1395 // Check for (0 / -x) that will produce negative zero. 1395 // Check for (0 / -x) that will produce negative zero.
1396 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) { 1396 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) {
1397 Label positive; 1397 Label positive;
1398 if (!instr->hydrogen_value()->CheckFlag(HValue::kCanBeDivByZero)) { 1398 if (!instr->hydrogen_value()->CheckFlag(HValue::kCanBeDivByZero)) {
1399 // Do the test only if it hadn't be done above. 1399 // Do the test only if it hadn't be done above.
1400 __ cmp(divisor, Operand::Zero()); 1400 __ cmp(divisor, Operand::Zero());
1401 } 1401 }
1402 __ b(pl, &positive); 1402 __ b(pl, &positive);
1403 __ cmp(dividend, Operand::Zero()); 1403 __ cmp(dividend, Operand::Zero());
1404 DeoptimizeIf(eq, instr); 1404 DeoptimizeIf(eq, instr, "minus zero");
1405 __ bind(&positive); 1405 __ bind(&positive);
1406 } 1406 }
1407 1407
1408 // Check for (kMinInt / -1). 1408 // Check for (kMinInt / -1).
1409 if (hdiv->CheckFlag(HValue::kCanOverflow) && 1409 if (hdiv->CheckFlag(HValue::kCanOverflow) &&
1410 (!CpuFeatures::IsSupported(SUDIV) || 1410 (!CpuFeatures::IsSupported(SUDIV) ||
1411 !hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32))) { 1411 !hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32))) {
1412 // We don't need to check for overflow when truncating with sdiv 1412 // We don't need to check for overflow when truncating with sdiv
1413 // support because, on ARM, sdiv kMinInt, -1 -> kMinInt. 1413 // support because, on ARM, sdiv kMinInt, -1 -> kMinInt.
1414 __ cmp(dividend, Operand(kMinInt)); 1414 __ cmp(dividend, Operand(kMinInt));
1415 __ cmp(divisor, Operand(-1), eq); 1415 __ cmp(divisor, Operand(-1), eq);
1416 DeoptimizeIf(eq, instr); 1416 DeoptimizeIf(eq, instr, "overflow");
1417 } 1417 }
1418 1418
1419 if (CpuFeatures::IsSupported(SUDIV)) { 1419 if (CpuFeatures::IsSupported(SUDIV)) {
1420 CpuFeatureScope scope(masm(), SUDIV); 1420 CpuFeatureScope scope(masm(), SUDIV);
1421 __ sdiv(result, dividend, divisor); 1421 __ sdiv(result, dividend, divisor);
1422 } else { 1422 } else {
1423 DoubleRegister vleft = ToDoubleRegister(instr->temp()); 1423 DoubleRegister vleft = ToDoubleRegister(instr->temp());
1424 DoubleRegister vright = double_scratch0(); 1424 DoubleRegister vright = double_scratch0();
1425 __ vmov(double_scratch0().low(), dividend); 1425 __ vmov(double_scratch0().low(), dividend);
1426 __ vcvt_f64_s32(vleft, double_scratch0().low()); 1426 __ vcvt_f64_s32(vleft, double_scratch0().low());
1427 __ vmov(double_scratch0().low(), divisor); 1427 __ vmov(double_scratch0().low(), divisor);
1428 __ vcvt_f64_s32(vright, double_scratch0().low()); 1428 __ vcvt_f64_s32(vright, double_scratch0().low());
1429 __ vdiv(vleft, vleft, vright); // vleft now contains the result. 1429 __ vdiv(vleft, vleft, vright); // vleft now contains the result.
1430 __ vcvt_s32_f64(double_scratch0().low(), vleft); 1430 __ vcvt_s32_f64(double_scratch0().low(), vleft);
1431 __ vmov(result, double_scratch0().low()); 1431 __ vmov(result, double_scratch0().low());
1432 } 1432 }
1433 1433
1434 if (!hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) { 1434 if (!hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) {
1435 // Compute remainder and deopt if it's not zero. 1435 // Compute remainder and deopt if it's not zero.
1436 Register remainder = scratch0(); 1436 Register remainder = scratch0();
1437 __ Mls(remainder, result, divisor, dividend); 1437 __ Mls(remainder, result, divisor, dividend);
1438 __ cmp(remainder, Operand::Zero()); 1438 __ cmp(remainder, Operand::Zero());
1439 DeoptimizeIf(ne, instr); 1439 DeoptimizeIf(ne, instr, "lost precision");
1440 } 1440 }
1441 } 1441 }
1442 1442
1443 1443
1444 void LCodeGen::DoMultiplyAddD(LMultiplyAddD* instr) { 1444 void LCodeGen::DoMultiplyAddD(LMultiplyAddD* instr) {
1445 DwVfpRegister addend = ToDoubleRegister(instr->addend()); 1445 DwVfpRegister addend = ToDoubleRegister(instr->addend());
1446 DwVfpRegister multiplier = ToDoubleRegister(instr->multiplier()); 1446 DwVfpRegister multiplier = ToDoubleRegister(instr->multiplier());
1447 DwVfpRegister multiplicand = ToDoubleRegister(instr->multiplicand()); 1447 DwVfpRegister multiplicand = ToDoubleRegister(instr->multiplicand());
1448 1448
1449 // This is computed in-place. 1449 // This is computed in-place.
(...skipping 30 matching lines...) Expand all
1480 // can simply do an arithmetic right shift. 1480 // can simply do an arithmetic right shift.
1481 int32_t shift = WhichPowerOf2Abs(divisor); 1481 int32_t shift = WhichPowerOf2Abs(divisor);
1482 if (divisor > 1) { 1482 if (divisor > 1) {
1483 __ mov(result, Operand(dividend, ASR, shift)); 1483 __ mov(result, Operand(dividend, ASR, shift));
1484 return; 1484 return;
1485 } 1485 }
1486 1486
1487 // If the divisor is negative, we have to negate and handle edge cases. 1487 // If the divisor is negative, we have to negate and handle edge cases.
1488 __ rsb(result, dividend, Operand::Zero(), SetCC); 1488 __ rsb(result, dividend, Operand::Zero(), SetCC);
1489 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 1489 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
1490 DeoptimizeIf(eq, instr); 1490 DeoptimizeIf(eq, instr, "minus zero");
1491 } 1491 }
1492 1492
1493 // Dividing by -1 is basically negation, unless we overflow. 1493 // Dividing by -1 is basically negation, unless we overflow.
1494 if (divisor == -1) { 1494 if (divisor == -1) {
1495 if (instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) { 1495 if (instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) {
1496 DeoptimizeIf(vs, instr); 1496 DeoptimizeIf(vs, instr, "overflow");
1497 } 1497 }
1498 return; 1498 return;
1499 } 1499 }
1500 1500
1501 // If the negation could not overflow, simply shifting is OK. 1501 // If the negation could not overflow, simply shifting is OK.
1502 if (!instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) { 1502 if (!instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) {
1503 __ mov(result, Operand(result, ASR, shift)); 1503 __ mov(result, Operand(result, ASR, shift));
1504 return; 1504 return;
1505 } 1505 }
1506 1506
1507 __ mov(result, Operand(kMinInt / divisor), LeaveCC, vs); 1507 __ mov(result, Operand(kMinInt / divisor), LeaveCC, vs);
1508 __ mov(result, Operand(result, ASR, shift), LeaveCC, vc); 1508 __ mov(result, Operand(result, ASR, shift), LeaveCC, vc);
1509 } 1509 }
1510 1510
1511 1511
1512 void LCodeGen::DoFlooringDivByConstI(LFlooringDivByConstI* instr) { 1512 void LCodeGen::DoFlooringDivByConstI(LFlooringDivByConstI* instr) {
1513 Register dividend = ToRegister(instr->dividend()); 1513 Register dividend = ToRegister(instr->dividend());
1514 int32_t divisor = instr->divisor(); 1514 int32_t divisor = instr->divisor();
1515 Register result = ToRegister(instr->result()); 1515 Register result = ToRegister(instr->result());
1516 DCHECK(!dividend.is(result)); 1516 DCHECK(!dividend.is(result));
1517 1517
1518 if (divisor == 0) { 1518 if (divisor == 0) {
1519 DeoptimizeIf(al, instr); 1519 DeoptimizeIf(al, instr, "division by zero");
1520 return; 1520 return;
1521 } 1521 }
1522 1522
1523 // Check for (0 / -x) that will produce negative zero. 1523 // Check for (0 / -x) that will produce negative zero.
1524 HMathFloorOfDiv* hdiv = instr->hydrogen(); 1524 HMathFloorOfDiv* hdiv = instr->hydrogen();
1525 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) { 1525 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) {
1526 __ cmp(dividend, Operand::Zero()); 1526 __ cmp(dividend, Operand::Zero());
1527 DeoptimizeIf(eq, instr); 1527 DeoptimizeIf(eq, instr, "minus zero");
1528 } 1528 }
1529 1529
1530 // Easy case: We need no dynamic check for the dividend and the flooring 1530 // Easy case: We need no dynamic check for the dividend and the flooring
1531 // division is the same as the truncating division. 1531 // division is the same as the truncating division.
1532 if ((divisor > 0 && !hdiv->CheckFlag(HValue::kLeftCanBeNegative)) || 1532 if ((divisor > 0 && !hdiv->CheckFlag(HValue::kLeftCanBeNegative)) ||
1533 (divisor < 0 && !hdiv->CheckFlag(HValue::kLeftCanBePositive))) { 1533 (divisor < 0 && !hdiv->CheckFlag(HValue::kLeftCanBePositive))) {
1534 __ TruncatingDiv(result, dividend, Abs(divisor)); 1534 __ TruncatingDiv(result, dividend, Abs(divisor));
1535 if (divisor < 0) __ rsb(result, result, Operand::Zero()); 1535 if (divisor < 0) __ rsb(result, result, Operand::Zero());
1536 return; 1536 return;
1537 } 1537 }
(...skipping 20 matching lines...) Expand all
1558 // TODO(svenpanne) Refactor this to avoid code duplication with DoDivI. 1558 // TODO(svenpanne) Refactor this to avoid code duplication with DoDivI.
1559 void LCodeGen::DoFlooringDivI(LFlooringDivI* instr) { 1559 void LCodeGen::DoFlooringDivI(LFlooringDivI* instr) {
1560 HBinaryOperation* hdiv = instr->hydrogen(); 1560 HBinaryOperation* hdiv = instr->hydrogen();
1561 Register left = ToRegister(instr->dividend()); 1561 Register left = ToRegister(instr->dividend());
1562 Register right = ToRegister(instr->divisor()); 1562 Register right = ToRegister(instr->divisor());
1563 Register result = ToRegister(instr->result()); 1563 Register result = ToRegister(instr->result());
1564 1564
1565 // Check for x / 0. 1565 // Check for x / 0.
1566 if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) { 1566 if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) {
1567 __ cmp(right, Operand::Zero()); 1567 __ cmp(right, Operand::Zero());
1568 DeoptimizeIf(eq, instr); 1568 DeoptimizeIf(eq, instr, "division by zero");
1569 } 1569 }
1570 1570
1571 // Check for (0 / -x) that will produce negative zero. 1571 // Check for (0 / -x) that will produce negative zero.
1572 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) { 1572 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) {
1573 Label positive; 1573 Label positive;
1574 if (!instr->hydrogen_value()->CheckFlag(HValue::kCanBeDivByZero)) { 1574 if (!instr->hydrogen_value()->CheckFlag(HValue::kCanBeDivByZero)) {
1575 // Do the test only if it hadn't be done above. 1575 // Do the test only if it hadn't be done above.
1576 __ cmp(right, Operand::Zero()); 1576 __ cmp(right, Operand::Zero());
1577 } 1577 }
1578 __ b(pl, &positive); 1578 __ b(pl, &positive);
1579 __ cmp(left, Operand::Zero()); 1579 __ cmp(left, Operand::Zero());
1580 DeoptimizeIf(eq, instr); 1580 DeoptimizeIf(eq, instr, "minus zero");
1581 __ bind(&positive); 1581 __ bind(&positive);
1582 } 1582 }
1583 1583
1584 // Check for (kMinInt / -1). 1584 // Check for (kMinInt / -1).
1585 if (hdiv->CheckFlag(HValue::kCanOverflow) && 1585 if (hdiv->CheckFlag(HValue::kCanOverflow) &&
1586 (!CpuFeatures::IsSupported(SUDIV) || 1586 (!CpuFeatures::IsSupported(SUDIV) ||
1587 !hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32))) { 1587 !hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32))) {
1588 // We don't need to check for overflow when truncating with sdiv 1588 // We don't need to check for overflow when truncating with sdiv
1589 // support because, on ARM, sdiv kMinInt, -1 -> kMinInt. 1589 // support because, on ARM, sdiv kMinInt, -1 -> kMinInt.
1590 __ cmp(left, Operand(kMinInt)); 1590 __ cmp(left, Operand(kMinInt));
1591 __ cmp(right, Operand(-1), eq); 1591 __ cmp(right, Operand(-1), eq);
1592 DeoptimizeIf(eq, instr); 1592 DeoptimizeIf(eq, instr, "overflow");
1593 } 1593 }
1594 1594
1595 if (CpuFeatures::IsSupported(SUDIV)) { 1595 if (CpuFeatures::IsSupported(SUDIV)) {
1596 CpuFeatureScope scope(masm(), SUDIV); 1596 CpuFeatureScope scope(masm(), SUDIV);
1597 __ sdiv(result, left, right); 1597 __ sdiv(result, left, right);
1598 } else { 1598 } else {
1599 DoubleRegister vleft = ToDoubleRegister(instr->temp()); 1599 DoubleRegister vleft = ToDoubleRegister(instr->temp());
1600 DoubleRegister vright = double_scratch0(); 1600 DoubleRegister vright = double_scratch0();
1601 __ vmov(double_scratch0().low(), left); 1601 __ vmov(double_scratch0().low(), left);
1602 __ vcvt_f64_s32(vleft, double_scratch0().low()); 1602 __ vcvt_f64_s32(vleft, double_scratch0().low());
(...skipping 25 matching lines...) Expand all
1628 instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero); 1628 instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero);
1629 bool overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow); 1629 bool overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow);
1630 1630
1631 if (right_op->IsConstantOperand()) { 1631 if (right_op->IsConstantOperand()) {
1632 int32_t constant = ToInteger32(LConstantOperand::cast(right_op)); 1632 int32_t constant = ToInteger32(LConstantOperand::cast(right_op));
1633 1633
1634 if (bailout_on_minus_zero && (constant < 0)) { 1634 if (bailout_on_minus_zero && (constant < 0)) {
1635 // The case of a null constant will be handled separately. 1635 // The case of a null constant will be handled separately.
1636 // If constant is negative and left is null, the result should be -0. 1636 // If constant is negative and left is null, the result should be -0.
1637 __ cmp(left, Operand::Zero()); 1637 __ cmp(left, Operand::Zero());
1638 DeoptimizeIf(eq, instr); 1638 DeoptimizeIf(eq, instr, "minus zero");
1639 } 1639 }
1640 1640
1641 switch (constant) { 1641 switch (constant) {
1642 case -1: 1642 case -1:
1643 if (overflow) { 1643 if (overflow) {
1644 __ rsb(result, left, Operand::Zero(), SetCC); 1644 __ rsb(result, left, Operand::Zero(), SetCC);
1645 DeoptimizeIf(vs, instr); 1645 DeoptimizeIf(vs, instr, "overflow");
1646 } else { 1646 } else {
1647 __ rsb(result, left, Operand::Zero()); 1647 __ rsb(result, left, Operand::Zero());
1648 } 1648 }
1649 break; 1649 break;
1650 case 0: 1650 case 0:
1651 if (bailout_on_minus_zero) { 1651 if (bailout_on_minus_zero) {
1652 // If left is strictly negative and the constant is null, the 1652 // If left is strictly negative and the constant is null, the
1653 // result is -0. Deoptimize if required, otherwise return 0. 1653 // result is -0. Deoptimize if required, otherwise return 0.
1654 __ cmp(left, Operand::Zero()); 1654 __ cmp(left, Operand::Zero());
1655 DeoptimizeIf(mi, instr); 1655 DeoptimizeIf(mi, instr, "minus zero");
1656 } 1656 }
1657 __ mov(result, Operand::Zero()); 1657 __ mov(result, Operand::Zero());
1658 break; 1658 break;
1659 case 1: 1659 case 1:
1660 __ Move(result, left); 1660 __ Move(result, left);
1661 break; 1661 break;
1662 default: 1662 default:
1663 // Multiplying by powers of two and powers of two plus or minus 1663 // Multiplying by powers of two and powers of two plus or minus
1664 // one can be done faster with shifted operands. 1664 // one can be done faster with shifted operands.
1665 // For other constants we emit standard code. 1665 // For other constants we emit standard code.
(...skipping 29 matching lines...) Expand all
1695 if (overflow) { 1695 if (overflow) {
1696 Register scratch = scratch0(); 1696 Register scratch = scratch0();
1697 // scratch:result = left * right. 1697 // scratch:result = left * right.
1698 if (instr->hydrogen()->representation().IsSmi()) { 1698 if (instr->hydrogen()->representation().IsSmi()) {
1699 __ SmiUntag(result, left); 1699 __ SmiUntag(result, left);
1700 __ smull(result, scratch, result, right); 1700 __ smull(result, scratch, result, right);
1701 } else { 1701 } else {
1702 __ smull(result, scratch, left, right); 1702 __ smull(result, scratch, left, right);
1703 } 1703 }
1704 __ cmp(scratch, Operand(result, ASR, 31)); 1704 __ cmp(scratch, Operand(result, ASR, 31));
1705 DeoptimizeIf(ne, instr); 1705 DeoptimizeIf(ne, instr, "overflow");
1706 } else { 1706 } else {
1707 if (instr->hydrogen()->representation().IsSmi()) { 1707 if (instr->hydrogen()->representation().IsSmi()) {
1708 __ SmiUntag(result, left); 1708 __ SmiUntag(result, left);
1709 __ mul(result, result, right); 1709 __ mul(result, result, right);
1710 } else { 1710 } else {
1711 __ mul(result, left, right); 1711 __ mul(result, left, right);
1712 } 1712 }
1713 } 1713 }
1714 1714
1715 if (bailout_on_minus_zero) { 1715 if (bailout_on_minus_zero) {
1716 Label done; 1716 Label done;
1717 __ teq(left, Operand(right)); 1717 __ teq(left, Operand(right));
1718 __ b(pl, &done); 1718 __ b(pl, &done);
1719 // Bail out if the result is minus zero. 1719 // Bail out if the result is minus zero.
1720 __ cmp(result, Operand::Zero()); 1720 __ cmp(result, Operand::Zero());
1721 DeoptimizeIf(eq, instr); 1721 DeoptimizeIf(eq, instr, "minus zero");
1722 __ bind(&done); 1722 __ bind(&done);
1723 } 1723 }
1724 } 1724 }
1725 } 1725 }
1726 1726
1727 1727
1728 void LCodeGen::DoBitI(LBitI* instr) { 1728 void LCodeGen::DoBitI(LBitI* instr) {
1729 LOperand* left_op = instr->left(); 1729 LOperand* left_op = instr->left();
1730 LOperand* right_op = instr->right(); 1730 LOperand* right_op = instr->right();
1731 DCHECK(left_op->IsRegister()); 1731 DCHECK(left_op->IsRegister());
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
1774 switch (instr->op()) { 1774 switch (instr->op()) {
1775 case Token::ROR: 1775 case Token::ROR:
1776 __ mov(result, Operand(left, ROR, scratch)); 1776 __ mov(result, Operand(left, ROR, scratch));
1777 break; 1777 break;
1778 case Token::SAR: 1778 case Token::SAR:
1779 __ mov(result, Operand(left, ASR, scratch)); 1779 __ mov(result, Operand(left, ASR, scratch));
1780 break; 1780 break;
1781 case Token::SHR: 1781 case Token::SHR:
1782 if (instr->can_deopt()) { 1782 if (instr->can_deopt()) {
1783 __ mov(result, Operand(left, LSR, scratch), SetCC); 1783 __ mov(result, Operand(left, LSR, scratch), SetCC);
1784 DeoptimizeIf(mi, instr); 1784 DeoptimizeIf(mi, instr, "negative value");
1785 } else { 1785 } else {
1786 __ mov(result, Operand(left, LSR, scratch)); 1786 __ mov(result, Operand(left, LSR, scratch));
1787 } 1787 }
1788 break; 1788 break;
1789 case Token::SHL: 1789 case Token::SHL:
1790 __ mov(result, Operand(left, LSL, scratch)); 1790 __ mov(result, Operand(left, LSL, scratch));
1791 break; 1791 break;
1792 default: 1792 default:
1793 UNREACHABLE(); 1793 UNREACHABLE();
1794 break; 1794 break;
(...skipping 16 matching lines...) Expand all
1811 } else { 1811 } else {
1812 __ Move(result, left); 1812 __ Move(result, left);
1813 } 1813 }
1814 break; 1814 break;
1815 case Token::SHR: 1815 case Token::SHR:
1816 if (shift_count != 0) { 1816 if (shift_count != 0) {
1817 __ mov(result, Operand(left, LSR, shift_count)); 1817 __ mov(result, Operand(left, LSR, shift_count));
1818 } else { 1818 } else {
1819 if (instr->can_deopt()) { 1819 if (instr->can_deopt()) {
1820 __ tst(left, Operand(0x80000000)); 1820 __ tst(left, Operand(0x80000000));
1821 DeoptimizeIf(ne, instr); 1821 DeoptimizeIf(ne, instr, "negative value");
1822 } 1822 }
1823 __ Move(result, left); 1823 __ Move(result, left);
1824 } 1824 }
1825 break; 1825 break;
1826 case Token::SHL: 1826 case Token::SHL:
1827 if (shift_count != 0) { 1827 if (shift_count != 0) {
1828 if (instr->hydrogen_value()->representation().IsSmi() && 1828 if (instr->hydrogen_value()->representation().IsSmi() &&
1829 instr->can_deopt()) { 1829 instr->can_deopt()) {
1830 if (shift_count != 1) { 1830 if (shift_count != 1) {
1831 __ mov(result, Operand(left, LSL, shift_count - 1)); 1831 __ mov(result, Operand(left, LSL, shift_count - 1));
1832 __ SmiTag(result, result, SetCC); 1832 __ SmiTag(result, result, SetCC);
1833 } else { 1833 } else {
1834 __ SmiTag(result, left, SetCC); 1834 __ SmiTag(result, left, SetCC);
1835 } 1835 }
1836 DeoptimizeIf(vs, instr); 1836 DeoptimizeIf(vs, instr, "overflow");
1837 } else { 1837 } else {
1838 __ mov(result, Operand(left, LSL, shift_count)); 1838 __ mov(result, Operand(left, LSL, shift_count));
1839 } 1839 }
1840 } else { 1840 } else {
1841 __ Move(result, left); 1841 __ Move(result, left);
1842 } 1842 }
1843 break; 1843 break;
1844 default: 1844 default:
1845 UNREACHABLE(); 1845 UNREACHABLE();
1846 break; 1846 break;
(...skipping 11 matching lines...) Expand all
1858 1858
1859 if (right->IsStackSlot()) { 1859 if (right->IsStackSlot()) {
1860 Register right_reg = EmitLoadRegister(right, ip); 1860 Register right_reg = EmitLoadRegister(right, ip);
1861 __ sub(ToRegister(result), ToRegister(left), Operand(right_reg), set_cond); 1861 __ sub(ToRegister(result), ToRegister(left), Operand(right_reg), set_cond);
1862 } else { 1862 } else {
1863 DCHECK(right->IsRegister() || right->IsConstantOperand()); 1863 DCHECK(right->IsRegister() || right->IsConstantOperand());
1864 __ sub(ToRegister(result), ToRegister(left), ToOperand(right), set_cond); 1864 __ sub(ToRegister(result), ToRegister(left), ToOperand(right), set_cond);
1865 } 1865 }
1866 1866
1867 if (can_overflow) { 1867 if (can_overflow) {
1868 DeoptimizeIf(vs, instr); 1868 DeoptimizeIf(vs, instr, "overflow");
1869 } 1869 }
1870 } 1870 }
1871 1871
1872 1872
1873 void LCodeGen::DoRSubI(LRSubI* instr) { 1873 void LCodeGen::DoRSubI(LRSubI* instr) {
1874 LOperand* left = instr->left(); 1874 LOperand* left = instr->left();
1875 LOperand* right = instr->right(); 1875 LOperand* right = instr->right();
1876 LOperand* result = instr->result(); 1876 LOperand* result = instr->result();
1877 bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow); 1877 bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow);
1878 SBit set_cond = can_overflow ? SetCC : LeaveCC; 1878 SBit set_cond = can_overflow ? SetCC : LeaveCC;
1879 1879
1880 if (right->IsStackSlot()) { 1880 if (right->IsStackSlot()) {
1881 Register right_reg = EmitLoadRegister(right, ip); 1881 Register right_reg = EmitLoadRegister(right, ip);
1882 __ rsb(ToRegister(result), ToRegister(left), Operand(right_reg), set_cond); 1882 __ rsb(ToRegister(result), ToRegister(left), Operand(right_reg), set_cond);
1883 } else { 1883 } else {
1884 DCHECK(right->IsRegister() || right->IsConstantOperand()); 1884 DCHECK(right->IsRegister() || right->IsConstantOperand());
1885 __ rsb(ToRegister(result), ToRegister(left), ToOperand(right), set_cond); 1885 __ rsb(ToRegister(result), ToRegister(left), ToOperand(right), set_cond);
1886 } 1886 }
1887 1887
1888 if (can_overflow) { 1888 if (can_overflow) {
1889 DeoptimizeIf(vs, instr); 1889 DeoptimizeIf(vs, instr, "overflow");
1890 } 1890 }
1891 } 1891 }
1892 1892
1893 1893
1894 void LCodeGen::DoConstantI(LConstantI* instr) { 1894 void LCodeGen::DoConstantI(LConstantI* instr) {
1895 __ mov(ToRegister(instr->result()), Operand(instr->value())); 1895 __ mov(ToRegister(instr->result()), Operand(instr->value()));
1896 } 1896 }
1897 1897
1898 1898
1899 void LCodeGen::DoConstantS(LConstantS* instr) { 1899 void LCodeGen::DoConstantS(LConstantS* instr) {
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
1933 Register result = ToRegister(instr->result()); 1933 Register result = ToRegister(instr->result());
1934 Register scratch = ToRegister(instr->temp()); 1934 Register scratch = ToRegister(instr->temp());
1935 Smi* index = instr->index(); 1935 Smi* index = instr->index();
1936 Label runtime, done; 1936 Label runtime, done;
1937 DCHECK(object.is(result)); 1937 DCHECK(object.is(result));
1938 DCHECK(object.is(r0)); 1938 DCHECK(object.is(r0));
1939 DCHECK(!scratch.is(scratch0())); 1939 DCHECK(!scratch.is(scratch0()));
1940 DCHECK(!scratch.is(object)); 1940 DCHECK(!scratch.is(object));
1941 1941
1942 __ SmiTst(object); 1942 __ SmiTst(object);
1943 DeoptimizeIf(eq, instr); 1943 DeoptimizeIf(eq, instr, "Smi");
1944 __ CompareObjectType(object, scratch, scratch, JS_DATE_TYPE); 1944 __ CompareObjectType(object, scratch, scratch, JS_DATE_TYPE);
1945 DeoptimizeIf(ne, instr); 1945 DeoptimizeIf(ne, instr, "not a date object");
1946 1946
1947 if (index->value() == 0) { 1947 if (index->value() == 0) {
1948 __ ldr(result, FieldMemOperand(object, JSDate::kValueOffset)); 1948 __ ldr(result, FieldMemOperand(object, JSDate::kValueOffset));
1949 } else { 1949 } else {
1950 if (index->value() < JSDate::kFirstUncachedField) { 1950 if (index->value() < JSDate::kFirstUncachedField) {
1951 ExternalReference stamp = ExternalReference::date_cache_stamp(isolate()); 1951 ExternalReference stamp = ExternalReference::date_cache_stamp(isolate());
1952 __ mov(scratch, Operand(stamp)); 1952 __ mov(scratch, Operand(stamp));
1953 __ ldr(scratch, MemOperand(scratch)); 1953 __ ldr(scratch, MemOperand(scratch));
1954 __ ldr(scratch0(), FieldMemOperand(object, JSDate::kCacheStampOffset)); 1954 __ ldr(scratch0(), FieldMemOperand(object, JSDate::kCacheStampOffset));
1955 __ cmp(scratch, scratch0()); 1955 __ cmp(scratch, scratch0());
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
2052 2052
2053 if (right->IsStackSlot()) { 2053 if (right->IsStackSlot()) {
2054 Register right_reg = EmitLoadRegister(right, ip); 2054 Register right_reg = EmitLoadRegister(right, ip);
2055 __ add(ToRegister(result), ToRegister(left), Operand(right_reg), set_cond); 2055 __ add(ToRegister(result), ToRegister(left), Operand(right_reg), set_cond);
2056 } else { 2056 } else {
2057 DCHECK(right->IsRegister() || right->IsConstantOperand()); 2057 DCHECK(right->IsRegister() || right->IsConstantOperand());
2058 __ add(ToRegister(result), ToRegister(left), ToOperand(right), set_cond); 2058 __ add(ToRegister(result), ToRegister(left), ToOperand(right), set_cond);
2059 } 2059 }
2060 2060
2061 if (can_overflow) { 2061 if (can_overflow) {
2062 DeoptimizeIf(vs, instr); 2062 DeoptimizeIf(vs, instr, "overflow");
2063 } 2063 }
2064 } 2064 }
2065 2065
2066 2066
2067 void LCodeGen::DoMathMinMax(LMathMinMax* instr) { 2067 void LCodeGen::DoMathMinMax(LMathMinMax* instr) {
2068 LOperand* left = instr->left(); 2068 LOperand* left = instr->left();
2069 LOperand* right = instr->right(); 2069 LOperand* right = instr->right();
2070 HMathMinMax::Operation operation = instr->hydrogen()->operation(); 2070 HMathMinMax::Operation operation = instr->hydrogen()->operation();
2071 if (instr->hydrogen()->representation().IsSmiOrInteger32()) { 2071 if (instr->hydrogen()->representation().IsSmiOrInteger32()) {
2072 Condition condition = (operation == HMathMinMax::kMathMin) ? le : ge; 2072 Condition condition = (operation == HMathMinMax::kMathMin) ? le : ge;
(...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after
2278 } 2278 }
2279 2279
2280 if (expected.Contains(ToBooleanStub::SMI)) { 2280 if (expected.Contains(ToBooleanStub::SMI)) {
2281 // Smis: 0 -> false, all other -> true. 2281 // Smis: 0 -> false, all other -> true.
2282 __ cmp(reg, Operand::Zero()); 2282 __ cmp(reg, Operand::Zero());
2283 __ b(eq, instr->FalseLabel(chunk_)); 2283 __ b(eq, instr->FalseLabel(chunk_));
2284 __ JumpIfSmi(reg, instr->TrueLabel(chunk_)); 2284 __ JumpIfSmi(reg, instr->TrueLabel(chunk_));
2285 } else if (expected.NeedsMap()) { 2285 } else if (expected.NeedsMap()) {
2286 // If we need a map later and have a Smi -> deopt. 2286 // If we need a map later and have a Smi -> deopt.
2287 __ SmiTst(reg); 2287 __ SmiTst(reg);
2288 DeoptimizeIf(eq, instr); 2288 DeoptimizeIf(eq, instr, "Smi");
2289 } 2289 }
2290 2290
2291 const Register map = scratch0(); 2291 const Register map = scratch0();
2292 if (expected.NeedsMap()) { 2292 if (expected.NeedsMap()) {
2293 __ ldr(map, FieldMemOperand(reg, HeapObject::kMapOffset)); 2293 __ ldr(map, FieldMemOperand(reg, HeapObject::kMapOffset));
2294 2294
2295 if (expected.CanBeUndetectable()) { 2295 if (expected.CanBeUndetectable()) {
2296 // Undetectable -> false. 2296 // Undetectable -> false.
2297 __ ldrb(ip, FieldMemOperand(map, Map::kBitFieldOffset)); 2297 __ ldrb(ip, FieldMemOperand(map, Map::kBitFieldOffset));
2298 __ tst(ip, Operand(1 << Map::kIsUndetectable)); 2298 __ tst(ip, Operand(1 << Map::kIsUndetectable));
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
2334 __ VFPCompareAndSetFlags(dbl_scratch, 0.0); 2334 __ VFPCompareAndSetFlags(dbl_scratch, 0.0);
2335 __ cmp(r0, r0, vs); // NaN -> false. 2335 __ cmp(r0, r0, vs); // NaN -> false.
2336 __ b(eq, instr->FalseLabel(chunk_)); // +0, -0 -> false. 2336 __ b(eq, instr->FalseLabel(chunk_)); // +0, -0 -> false.
2337 __ b(instr->TrueLabel(chunk_)); 2337 __ b(instr->TrueLabel(chunk_));
2338 __ bind(&not_heap_number); 2338 __ bind(&not_heap_number);
2339 } 2339 }
2340 2340
2341 if (!expected.IsGeneric()) { 2341 if (!expected.IsGeneric()) {
2342 // We've seen something for the first time -> deopt. 2342 // We've seen something for the first time -> deopt.
2343 // This can only happen if we are not generic already. 2343 // This can only happen if we are not generic already.
2344 DeoptimizeIf(al, instr); 2344 DeoptimizeIf(al, instr, "unexpected object");
2345 } 2345 }
2346 } 2346 }
2347 } 2347 }
2348 } 2348 }
2349 2349
2350 2350
2351 void LCodeGen::EmitGoto(int block) { 2351 void LCodeGen::EmitGoto(int block) {
2352 if (!IsNextEmittedBlock(block)) { 2352 if (!IsNextEmittedBlock(block)) {
2353 __ jmp(chunk_->GetAssemblyLabel(LookupDestination(block))); 2353 __ jmp(chunk_->GetAssemblyLabel(LookupDestination(block)));
2354 } 2354 }
(...skipping 624 matching lines...) Expand 10 before | Expand all | Expand 10 after
2979 } 2979 }
2980 2980
2981 2981
2982 void LCodeGen::DoLoadGlobalCell(LLoadGlobalCell* instr) { 2982 void LCodeGen::DoLoadGlobalCell(LLoadGlobalCell* instr) {
2983 Register result = ToRegister(instr->result()); 2983 Register result = ToRegister(instr->result());
2984 __ mov(ip, Operand(Handle<Object>(instr->hydrogen()->cell().handle()))); 2984 __ mov(ip, Operand(Handle<Object>(instr->hydrogen()->cell().handle())));
2985 __ ldr(result, FieldMemOperand(ip, Cell::kValueOffset)); 2985 __ ldr(result, FieldMemOperand(ip, Cell::kValueOffset));
2986 if (instr->hydrogen()->RequiresHoleCheck()) { 2986 if (instr->hydrogen()->RequiresHoleCheck()) {
2987 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); 2987 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
2988 __ cmp(result, ip); 2988 __ cmp(result, ip);
2989 DeoptimizeIf(eq, instr); 2989 DeoptimizeIf(eq, instr, "hole");
2990 } 2990 }
2991 } 2991 }
2992 2992
2993 2993
2994 template <class T> 2994 template <class T>
2995 void LCodeGen::EmitVectorLoadICRegisters(T* instr) { 2995 void LCodeGen::EmitVectorLoadICRegisters(T* instr) {
2996 DCHECK(FLAG_vector_ics); 2996 DCHECK(FLAG_vector_ics);
2997 Register vector = ToRegister(instr->temp_vector()); 2997 Register vector = ToRegister(instr->temp_vector());
2998 DCHECK(vector.is(VectorLoadICDescriptor::VectorRegister())); 2998 DCHECK(vector.is(VectorLoadICDescriptor::VectorRegister()));
2999 __ Move(vector, instr->hydrogen()->feedback_vector()); 2999 __ Move(vector, instr->hydrogen()->feedback_vector());
(...skipping 29 matching lines...) Expand all
3029 3029
3030 // If the cell we are storing to contains the hole it could have 3030 // If the cell we are storing to contains the hole it could have
3031 // been deleted from the property dictionary. In that case, we need 3031 // been deleted from the property dictionary. In that case, we need
3032 // to update the property details in the property dictionary to mark 3032 // to update the property details in the property dictionary to mark
3033 // it as no longer deleted. 3033 // it as no longer deleted.
3034 if (instr->hydrogen()->RequiresHoleCheck()) { 3034 if (instr->hydrogen()->RequiresHoleCheck()) {
3035 // We use a temp to check the payload (CompareRoot might clobber ip). 3035 // We use a temp to check the payload (CompareRoot might clobber ip).
3036 Register payload = ToRegister(instr->temp()); 3036 Register payload = ToRegister(instr->temp());
3037 __ ldr(payload, FieldMemOperand(cell, Cell::kValueOffset)); 3037 __ ldr(payload, FieldMemOperand(cell, Cell::kValueOffset));
3038 __ CompareRoot(payload, Heap::kTheHoleValueRootIndex); 3038 __ CompareRoot(payload, Heap::kTheHoleValueRootIndex);
3039 DeoptimizeIf(eq, instr); 3039 DeoptimizeIf(eq, instr, "hole");
3040 } 3040 }
3041 3041
3042 // Store the value. 3042 // Store the value.
3043 __ str(value, FieldMemOperand(cell, Cell::kValueOffset)); 3043 __ str(value, FieldMemOperand(cell, Cell::kValueOffset));
3044 // Cells are always rescanned, so no write barrier here. 3044 // Cells are always rescanned, so no write barrier here.
3045 } 3045 }
3046 3046
3047 3047
3048 void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) { 3048 void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) {
3049 Register context = ToRegister(instr->context()); 3049 Register context = ToRegister(instr->context());
3050 Register result = ToRegister(instr->result()); 3050 Register result = ToRegister(instr->result());
3051 __ ldr(result, ContextOperand(context, instr->slot_index())); 3051 __ ldr(result, ContextOperand(context, instr->slot_index()));
3052 if (instr->hydrogen()->RequiresHoleCheck()) { 3052 if (instr->hydrogen()->RequiresHoleCheck()) {
3053 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); 3053 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
3054 __ cmp(result, ip); 3054 __ cmp(result, ip);
3055 if (instr->hydrogen()->DeoptimizesOnHole()) { 3055 if (instr->hydrogen()->DeoptimizesOnHole()) {
3056 DeoptimizeIf(eq, instr); 3056 DeoptimizeIf(eq, instr, "hole");
3057 } else { 3057 } else {
3058 __ mov(result, Operand(factory()->undefined_value()), LeaveCC, eq); 3058 __ mov(result, Operand(factory()->undefined_value()), LeaveCC, eq);
3059 } 3059 }
3060 } 3060 }
3061 } 3061 }
3062 3062
3063 3063
3064 void LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) { 3064 void LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) {
3065 Register context = ToRegister(instr->context()); 3065 Register context = ToRegister(instr->context());
3066 Register value = ToRegister(instr->value()); 3066 Register value = ToRegister(instr->value());
3067 Register scratch = scratch0(); 3067 Register scratch = scratch0();
3068 MemOperand target = ContextOperand(context, instr->slot_index()); 3068 MemOperand target = ContextOperand(context, instr->slot_index());
3069 3069
3070 Label skip_assignment; 3070 Label skip_assignment;
3071 3071
3072 if (instr->hydrogen()->RequiresHoleCheck()) { 3072 if (instr->hydrogen()->RequiresHoleCheck()) {
3073 __ ldr(scratch, target); 3073 __ ldr(scratch, target);
3074 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); 3074 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
3075 __ cmp(scratch, ip); 3075 __ cmp(scratch, ip);
3076 if (instr->hydrogen()->DeoptimizesOnHole()) { 3076 if (instr->hydrogen()->DeoptimizesOnHole()) {
3077 DeoptimizeIf(eq, instr); 3077 DeoptimizeIf(eq, instr, "hole");
3078 } else { 3078 } else {
3079 __ b(ne, &skip_assignment); 3079 __ b(ne, &skip_assignment);
3080 } 3080 }
3081 } 3081 }
3082 3082
3083 __ str(value, target); 3083 __ str(value, target);
3084 if (instr->hydrogen()->NeedsWriteBarrier()) { 3084 if (instr->hydrogen()->NeedsWriteBarrier()) {
3085 SmiCheck check_needed = 3085 SmiCheck check_needed =
3086 instr->hydrogen()->value()->type().IsHeapObject() 3086 instr->hydrogen()->value()->type().IsHeapObject()
3087 ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; 3087 ? OMIT_SMI_CHECK : INLINE_SMI_CHECK;
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
3147 Register function = ToRegister(instr->function()); 3147 Register function = ToRegister(instr->function());
3148 Register result = ToRegister(instr->result()); 3148 Register result = ToRegister(instr->result());
3149 3149
3150 // Get the prototype or initial map from the function. 3150 // Get the prototype or initial map from the function.
3151 __ ldr(result, 3151 __ ldr(result,
3152 FieldMemOperand(function, JSFunction::kPrototypeOrInitialMapOffset)); 3152 FieldMemOperand(function, JSFunction::kPrototypeOrInitialMapOffset));
3153 3153
3154 // Check that the function has a prototype or an initial map. 3154 // Check that the function has a prototype or an initial map.
3155 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); 3155 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
3156 __ cmp(result, ip); 3156 __ cmp(result, ip);
3157 DeoptimizeIf(eq, instr); 3157 DeoptimizeIf(eq, instr, "hole");
3158 3158
3159 // If the function does not have an initial map, we're done. 3159 // If the function does not have an initial map, we're done.
3160 Label done; 3160 Label done;
3161 __ CompareObjectType(result, scratch, scratch, MAP_TYPE); 3161 __ CompareObjectType(result, scratch, scratch, MAP_TYPE);
3162 __ b(ne, &done); 3162 __ b(ne, &done);
3163 3163
3164 // Get the prototype from the initial map. 3164 // Get the prototype from the initial map.
3165 __ ldr(result, FieldMemOperand(result, Map::kPrototypeOffset)); 3165 __ ldr(result, FieldMemOperand(result, Map::kPrototypeOffset));
3166 3166
3167 // All done. 3167 // All done.
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
3273 break; 3273 break;
3274 case EXTERNAL_INT32_ELEMENTS: 3274 case EXTERNAL_INT32_ELEMENTS:
3275 case INT32_ELEMENTS: 3275 case INT32_ELEMENTS:
3276 __ ldr(result, mem_operand); 3276 __ ldr(result, mem_operand);
3277 break; 3277 break;
3278 case EXTERNAL_UINT32_ELEMENTS: 3278 case EXTERNAL_UINT32_ELEMENTS:
3279 case UINT32_ELEMENTS: 3279 case UINT32_ELEMENTS:
3280 __ ldr(result, mem_operand); 3280 __ ldr(result, mem_operand);
3281 if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) { 3281 if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) {
3282 __ cmp(result, Operand(0x80000000)); 3282 __ cmp(result, Operand(0x80000000));
3283 DeoptimizeIf(cs, instr); 3283 DeoptimizeIf(cs, instr, "negative value");
3284 } 3284 }
3285 break; 3285 break;
3286 case FLOAT32_ELEMENTS: 3286 case FLOAT32_ELEMENTS:
3287 case FLOAT64_ELEMENTS: 3287 case FLOAT64_ELEMENTS:
3288 case EXTERNAL_FLOAT32_ELEMENTS: 3288 case EXTERNAL_FLOAT32_ELEMENTS:
3289 case EXTERNAL_FLOAT64_ELEMENTS: 3289 case EXTERNAL_FLOAT64_ELEMENTS:
3290 case FAST_HOLEY_DOUBLE_ELEMENTS: 3290 case FAST_HOLEY_DOUBLE_ELEMENTS:
3291 case FAST_HOLEY_ELEMENTS: 3291 case FAST_HOLEY_ELEMENTS:
3292 case FAST_HOLEY_SMI_ELEMENTS: 3292 case FAST_HOLEY_SMI_ELEMENTS:
3293 case FAST_DOUBLE_ELEMENTS: 3293 case FAST_DOUBLE_ELEMENTS:
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
3326 int shift_size = (instr->hydrogen()->key()->representation().IsSmi()) 3326 int shift_size = (instr->hydrogen()->key()->representation().IsSmi())
3327 ? (element_size_shift - kSmiTagSize) : element_size_shift; 3327 ? (element_size_shift - kSmiTagSize) : element_size_shift;
3328 __ add(scratch, scratch, Operand(key, LSL, shift_size)); 3328 __ add(scratch, scratch, Operand(key, LSL, shift_size));
3329 } 3329 }
3330 3330
3331 __ vldr(result, scratch, 0); 3331 __ vldr(result, scratch, 0);
3332 3332
3333 if (instr->hydrogen()->RequiresHoleCheck()) { 3333 if (instr->hydrogen()->RequiresHoleCheck()) {
3334 __ ldr(scratch, MemOperand(scratch, sizeof(kHoleNanLower32))); 3334 __ ldr(scratch, MemOperand(scratch, sizeof(kHoleNanLower32)));
3335 __ cmp(scratch, Operand(kHoleNanUpper32)); 3335 __ cmp(scratch, Operand(kHoleNanUpper32));
3336 DeoptimizeIf(eq, instr); 3336 DeoptimizeIf(eq, instr, "hole");
3337 } 3337 }
3338 } 3338 }
3339 3339
3340 3340
3341 void LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) { 3341 void LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) {
3342 Register elements = ToRegister(instr->elements()); 3342 Register elements = ToRegister(instr->elements());
3343 Register result = ToRegister(instr->result()); 3343 Register result = ToRegister(instr->result());
3344 Register scratch = scratch0(); 3344 Register scratch = scratch0();
3345 Register store_base = scratch; 3345 Register store_base = scratch;
3346 int offset = instr->base_offset(); 3346 int offset = instr->base_offset();
(...skipping 13 matching lines...) Expand all
3360 } else { 3360 } else {
3361 __ add(scratch, elements, Operand(key, LSL, kPointerSizeLog2)); 3361 __ add(scratch, elements, Operand(key, LSL, kPointerSizeLog2));
3362 } 3362 }
3363 } 3363 }
3364 __ ldr(result, MemOperand(store_base, offset)); 3364 __ ldr(result, MemOperand(store_base, offset));
3365 3365
3366 // Check for the hole value. 3366 // Check for the hole value.
3367 if (instr->hydrogen()->RequiresHoleCheck()) { 3367 if (instr->hydrogen()->RequiresHoleCheck()) {
3368 if (IsFastSmiElementsKind(instr->hydrogen()->elements_kind())) { 3368 if (IsFastSmiElementsKind(instr->hydrogen()->elements_kind())) {
3369 __ SmiTst(result); 3369 __ SmiTst(result);
3370 DeoptimizeIf(ne, instr); 3370 DeoptimizeIf(ne, instr, "not a Smi");
3371 } else { 3371 } else {
3372 __ LoadRoot(scratch, Heap::kTheHoleValueRootIndex); 3372 __ LoadRoot(scratch, Heap::kTheHoleValueRootIndex);
3373 __ cmp(result, scratch); 3373 __ cmp(result, scratch);
3374 DeoptimizeIf(eq, instr); 3374 DeoptimizeIf(eq, instr, "hole");
3375 } 3375 }
3376 } 3376 }
3377 } 3377 }
3378 3378
3379 3379
3380 void LCodeGen::DoLoadKeyed(LLoadKeyed* instr) { 3380 void LCodeGen::DoLoadKeyed(LLoadKeyed* instr) {
3381 if (instr->is_typed_elements()) { 3381 if (instr->is_typed_elements()) {
3382 DoLoadKeyedExternalArray(instr); 3382 DoLoadKeyedExternalArray(instr);
3383 } else if (instr->hydrogen()->representation().IsDouble()) { 3383 } else if (instr->hydrogen()->representation().IsDouble()) {
3384 DoLoadKeyedFixedDoubleArray(instr); 3384 DoLoadKeyedFixedDoubleArray(instr);
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
3506 // Normal function. Replace undefined or null with global receiver. 3506 // Normal function. Replace undefined or null with global receiver.
3507 __ LoadRoot(scratch, Heap::kNullValueRootIndex); 3507 __ LoadRoot(scratch, Heap::kNullValueRootIndex);
3508 __ cmp(receiver, scratch); 3508 __ cmp(receiver, scratch);
3509 __ b(eq, &global_object); 3509 __ b(eq, &global_object);
3510 __ LoadRoot(scratch, Heap::kUndefinedValueRootIndex); 3510 __ LoadRoot(scratch, Heap::kUndefinedValueRootIndex);
3511 __ cmp(receiver, scratch); 3511 __ cmp(receiver, scratch);
3512 __ b(eq, &global_object); 3512 __ b(eq, &global_object);
3513 3513
3514 // Deoptimize if the receiver is not a JS object. 3514 // Deoptimize if the receiver is not a JS object.
3515 __ SmiTst(receiver); 3515 __ SmiTst(receiver);
3516 DeoptimizeIf(eq, instr); 3516 DeoptimizeIf(eq, instr, "Smi");
3517 __ CompareObjectType(receiver, scratch, scratch, FIRST_SPEC_OBJECT_TYPE); 3517 __ CompareObjectType(receiver, scratch, scratch, FIRST_SPEC_OBJECT_TYPE);
3518 DeoptimizeIf(lt, instr); 3518 DeoptimizeIf(lt, instr, "not a JavaScript object");
3519 3519
3520 __ b(&result_in_receiver); 3520 __ b(&result_in_receiver);
3521 __ bind(&global_object); 3521 __ bind(&global_object);
3522 __ ldr(result, FieldMemOperand(function, JSFunction::kContextOffset)); 3522 __ ldr(result, FieldMemOperand(function, JSFunction::kContextOffset));
3523 __ ldr(result, 3523 __ ldr(result,
3524 ContextOperand(result, Context::GLOBAL_OBJECT_INDEX)); 3524 ContextOperand(result, Context::GLOBAL_OBJECT_INDEX));
3525 __ ldr(result, FieldMemOperand(result, GlobalObject::kGlobalProxyOffset)); 3525 __ ldr(result, FieldMemOperand(result, GlobalObject::kGlobalProxyOffset));
3526 3526
3527 if (result.is(receiver)) { 3527 if (result.is(receiver)) {
3528 __ bind(&result_in_receiver); 3528 __ bind(&result_in_receiver);
(...skipping 14 matching lines...) Expand all
3543 Register elements = ToRegister(instr->elements()); 3543 Register elements = ToRegister(instr->elements());
3544 Register scratch = scratch0(); 3544 Register scratch = scratch0();
3545 DCHECK(receiver.is(r0)); // Used for parameter count. 3545 DCHECK(receiver.is(r0)); // Used for parameter count.
3546 DCHECK(function.is(r1)); // Required by InvokeFunction. 3546 DCHECK(function.is(r1)); // Required by InvokeFunction.
3547 DCHECK(ToRegister(instr->result()).is(r0)); 3547 DCHECK(ToRegister(instr->result()).is(r0));
3548 3548
3549 // Copy the arguments to this function possibly from the 3549 // Copy the arguments to this function possibly from the
3550 // adaptor frame below it. 3550 // adaptor frame below it.
3551 const uint32_t kArgumentsLimit = 1 * KB; 3551 const uint32_t kArgumentsLimit = 1 * KB;
3552 __ cmp(length, Operand(kArgumentsLimit)); 3552 __ cmp(length, Operand(kArgumentsLimit));
3553 DeoptimizeIf(hi, instr); 3553 DeoptimizeIf(hi, instr, "too many arguments");
3554 3554
3555 // Push the receiver and use the register to keep the original 3555 // Push the receiver and use the register to keep the original
3556 // number of arguments. 3556 // number of arguments.
3557 __ push(receiver); 3557 __ push(receiver);
3558 __ mov(receiver, length); 3558 __ mov(receiver, length);
3559 // The arguments are at a one pointer size offset from elements. 3559 // The arguments are at a one pointer size offset from elements.
3560 __ add(elements, elements, Operand(1 * kPointerSize)); 3560 __ add(elements, elements, Operand(1 * kPointerSize));
3561 3561
3562 // Loop through the arguments pushing them onto the execution 3562 // Loop through the arguments pushing them onto the execution
3563 // stack. 3563 // stack.
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
3673 DCHECK(instr->context() != NULL); 3673 DCHECK(instr->context() != NULL);
3674 DCHECK(ToRegister(instr->context()).is(cp)); 3674 DCHECK(ToRegister(instr->context()).is(cp));
3675 Register input = ToRegister(instr->value()); 3675 Register input = ToRegister(instr->value());
3676 Register result = ToRegister(instr->result()); 3676 Register result = ToRegister(instr->result());
3677 Register scratch = scratch0(); 3677 Register scratch = scratch0();
3678 3678
3679 // Deoptimize if not a heap number. 3679 // Deoptimize if not a heap number.
3680 __ ldr(scratch, FieldMemOperand(input, HeapObject::kMapOffset)); 3680 __ ldr(scratch, FieldMemOperand(input, HeapObject::kMapOffset));
3681 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex); 3681 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex);
3682 __ cmp(scratch, Operand(ip)); 3682 __ cmp(scratch, Operand(ip));
3683 DeoptimizeIf(ne, instr); 3683 DeoptimizeIf(ne, instr, "not a heap number");
3684 3684
3685 Label done; 3685 Label done;
3686 Register exponent = scratch0(); 3686 Register exponent = scratch0();
3687 scratch = no_reg; 3687 scratch = no_reg;
3688 __ ldr(exponent, FieldMemOperand(input, HeapNumber::kExponentOffset)); 3688 __ ldr(exponent, FieldMemOperand(input, HeapNumber::kExponentOffset));
3689 // Check the sign of the argument. If the argument is positive, just 3689 // Check the sign of the argument. If the argument is positive, just
3690 // return it. 3690 // return it.
3691 __ tst(exponent, Operand(HeapNumber::kSignMask)); 3691 __ tst(exponent, Operand(HeapNumber::kSignMask));
3692 // Move the input to the result if necessary. 3692 // Move the input to the result if necessary.
3693 __ Move(result, input); 3693 __ Move(result, input);
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
3741 void LCodeGen::EmitIntegerMathAbs(LMathAbs* instr) { 3741 void LCodeGen::EmitIntegerMathAbs(LMathAbs* instr) {
3742 Register input = ToRegister(instr->value()); 3742 Register input = ToRegister(instr->value());
3743 Register result = ToRegister(instr->result()); 3743 Register result = ToRegister(instr->result());
3744 __ cmp(input, Operand::Zero()); 3744 __ cmp(input, Operand::Zero());
3745 __ Move(result, input, pl); 3745 __ Move(result, input, pl);
3746 // We can make rsb conditional because the previous cmp instruction 3746 // We can make rsb conditional because the previous cmp instruction
3747 // will clear the V (overflow) flag and rsb won't set this flag 3747 // will clear the V (overflow) flag and rsb won't set this flag
3748 // if input is positive. 3748 // if input is positive.
3749 __ rsb(result, input, Operand::Zero(), SetCC, mi); 3749 __ rsb(result, input, Operand::Zero(), SetCC, mi);
3750 // Deoptimize on overflow. 3750 // Deoptimize on overflow.
3751 DeoptimizeIf(vs, instr); 3751 DeoptimizeIf(vs, instr, "overflow");
3752 } 3752 }
3753 3753
3754 3754
3755 void LCodeGen::DoMathAbs(LMathAbs* instr) { 3755 void LCodeGen::DoMathAbs(LMathAbs* instr) {
3756 // Class for deferred case. 3756 // Class for deferred case.
3757 class DeferredMathAbsTaggedHeapNumber FINAL : public LDeferredCode { 3757 class DeferredMathAbsTaggedHeapNumber FINAL : public LDeferredCode {
3758 public: 3758 public:
3759 DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen, LMathAbs* instr) 3759 DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen, LMathAbs* instr)
3760 : LDeferredCode(codegen), instr_(instr) { } 3760 : LDeferredCode(codegen), instr_(instr) { }
3761 virtual void Generate() OVERRIDE { 3761 virtual void Generate() OVERRIDE {
(...skipping 25 matching lines...) Expand all
3787 } 3787 }
3788 3788
3789 3789
3790 void LCodeGen::DoMathFloor(LMathFloor* instr) { 3790 void LCodeGen::DoMathFloor(LMathFloor* instr) {
3791 DwVfpRegister input = ToDoubleRegister(instr->value()); 3791 DwVfpRegister input = ToDoubleRegister(instr->value());
3792 Register result = ToRegister(instr->result()); 3792 Register result = ToRegister(instr->result());
3793 Register input_high = scratch0(); 3793 Register input_high = scratch0();
3794 Label done, exact; 3794 Label done, exact;
3795 3795
3796 __ TryInt32Floor(result, input, input_high, double_scratch0(), &done, &exact); 3796 __ TryInt32Floor(result, input, input_high, double_scratch0(), &done, &exact);
3797 DeoptimizeIf(al, instr); 3797 DeoptimizeIf(al, instr, "lost precision or NaN");
3798 3798
3799 __ bind(&exact); 3799 __ bind(&exact);
3800 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 3800 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
3801 // Test for -0. 3801 // Test for -0.
3802 __ cmp(result, Operand::Zero()); 3802 __ cmp(result, Operand::Zero());
3803 __ b(ne, &done); 3803 __ b(ne, &done);
3804 __ cmp(input_high, Operand::Zero()); 3804 __ cmp(input_high, Operand::Zero());
3805 DeoptimizeIf(mi, instr); 3805 DeoptimizeIf(mi, instr, "minus zero");
3806 } 3806 }
3807 __ bind(&done); 3807 __ bind(&done);
3808 } 3808 }
3809 3809
3810 3810
3811 void LCodeGen::DoMathRound(LMathRound* instr) { 3811 void LCodeGen::DoMathRound(LMathRound* instr) {
3812 DwVfpRegister input = ToDoubleRegister(instr->value()); 3812 DwVfpRegister input = ToDoubleRegister(instr->value());
3813 Register result = ToRegister(instr->result()); 3813 Register result = ToRegister(instr->result());
3814 DwVfpRegister double_scratch1 = ToDoubleRegister(instr->temp()); 3814 DwVfpRegister double_scratch1 = ToDoubleRegister(instr->temp());
3815 DwVfpRegister input_plus_dot_five = double_scratch1; 3815 DwVfpRegister input_plus_dot_five = double_scratch1;
3816 Register input_high = scratch0(); 3816 Register input_high = scratch0();
3817 DwVfpRegister dot_five = double_scratch0(); 3817 DwVfpRegister dot_five = double_scratch0();
3818 Label convert, done; 3818 Label convert, done;
3819 3819
3820 __ Vmov(dot_five, 0.5, scratch0()); 3820 __ Vmov(dot_five, 0.5, scratch0());
3821 __ vabs(double_scratch1, input); 3821 __ vabs(double_scratch1, input);
3822 __ VFPCompareAndSetFlags(double_scratch1, dot_five); 3822 __ VFPCompareAndSetFlags(double_scratch1, dot_five);
3823 // If input is in [-0.5, -0], the result is -0. 3823 // If input is in [-0.5, -0], the result is -0.
3824 // If input is in [+0, +0.5[, the result is +0. 3824 // If input is in [+0, +0.5[, the result is +0.
3825 // If the input is +0.5, the result is 1. 3825 // If the input is +0.5, the result is 1.
3826 __ b(hi, &convert); // Out of [-0.5, +0.5]. 3826 __ b(hi, &convert); // Out of [-0.5, +0.5].
3827 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 3827 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
3828 __ VmovHigh(input_high, input); 3828 __ VmovHigh(input_high, input);
3829 __ cmp(input_high, Operand::Zero()); 3829 __ cmp(input_high, Operand::Zero());
3830 DeoptimizeIf(mi, instr); // [-0.5, -0]. 3830 // [-0.5, -0].
3831 DeoptimizeIf(mi, instr, "minus zero");
3831 } 3832 }
3832 __ VFPCompareAndSetFlags(input, dot_five); 3833 __ VFPCompareAndSetFlags(input, dot_five);
3833 __ mov(result, Operand(1), LeaveCC, eq); // +0.5. 3834 __ mov(result, Operand(1), LeaveCC, eq); // +0.5.
3834 // Remaining cases: [+0, +0.5[ or [-0.5, +0.5[, depending on 3835 // Remaining cases: [+0, +0.5[ or [-0.5, +0.5[, depending on
3835 // flag kBailoutOnMinusZero. 3836 // flag kBailoutOnMinusZero.
3836 __ mov(result, Operand::Zero(), LeaveCC, ne); 3837 __ mov(result, Operand::Zero(), LeaveCC, ne);
3837 __ b(&done); 3838 __ b(&done);
3838 3839
3839 __ bind(&convert); 3840 __ bind(&convert);
3840 __ vadd(input_plus_dot_five, input, dot_five); 3841 __ vadd(input_plus_dot_five, input, dot_five);
3841 // Reuse dot_five (double_scratch0) as we no longer need this value. 3842 // Reuse dot_five (double_scratch0) as we no longer need this value.
3842 __ TryInt32Floor(result, input_plus_dot_five, input_high, double_scratch0(), 3843 __ TryInt32Floor(result, input_plus_dot_five, input_high, double_scratch0(),
3843 &done, &done); 3844 &done, &done);
3844 DeoptimizeIf(al, instr); 3845 DeoptimizeIf(al, instr, "lost precision or NaN");
3845 __ bind(&done); 3846 __ bind(&done);
3846 } 3847 }
3847 3848
3848 3849
3849 void LCodeGen::DoMathFround(LMathFround* instr) { 3850 void LCodeGen::DoMathFround(LMathFround* instr) {
3850 DwVfpRegister input_reg = ToDoubleRegister(instr->value()); 3851 DwVfpRegister input_reg = ToDoubleRegister(instr->value());
3851 DwVfpRegister output_reg = ToDoubleRegister(instr->result()); 3852 DwVfpRegister output_reg = ToDoubleRegister(instr->result());
3852 LowDwVfpRegister scratch = double_scratch0(); 3853 LowDwVfpRegister scratch = double_scratch0();
3853 __ vcvt_f32_f64(scratch.low(), input_reg); 3854 __ vcvt_f32_f64(scratch.low(), input_reg);
3854 __ vcvt_f64_f32(output_reg, scratch.low()); 3855 __ vcvt_f64_f32(output_reg, scratch.low());
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
3898 if (exponent_type.IsSmi()) { 3899 if (exponent_type.IsSmi()) {
3899 MathPowStub stub(isolate(), MathPowStub::TAGGED); 3900 MathPowStub stub(isolate(), MathPowStub::TAGGED);
3900 __ CallStub(&stub); 3901 __ CallStub(&stub);
3901 } else if (exponent_type.IsTagged()) { 3902 } else if (exponent_type.IsTagged()) {
3902 Label no_deopt; 3903 Label no_deopt;
3903 __ JumpIfSmi(tagged_exponent, &no_deopt); 3904 __ JumpIfSmi(tagged_exponent, &no_deopt);
3904 DCHECK(!r6.is(tagged_exponent)); 3905 DCHECK(!r6.is(tagged_exponent));
3905 __ ldr(r6, FieldMemOperand(tagged_exponent, HeapObject::kMapOffset)); 3906 __ ldr(r6, FieldMemOperand(tagged_exponent, HeapObject::kMapOffset));
3906 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex); 3907 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex);
3907 __ cmp(r6, Operand(ip)); 3908 __ cmp(r6, Operand(ip));
3908 DeoptimizeIf(ne, instr); 3909 DeoptimizeIf(ne, instr, "not a heap number");
3909 __ bind(&no_deopt); 3910 __ bind(&no_deopt);
3910 MathPowStub stub(isolate(), MathPowStub::TAGGED); 3911 MathPowStub stub(isolate(), MathPowStub::TAGGED);
3911 __ CallStub(&stub); 3912 __ CallStub(&stub);
3912 } else if (exponent_type.IsInteger32()) { 3913 } else if (exponent_type.IsInteger32()) {
3913 MathPowStub stub(isolate(), MathPowStub::INTEGER); 3914 MathPowStub stub(isolate(), MathPowStub::INTEGER);
3914 __ CallStub(&stub); 3915 __ CallStub(&stub);
3915 } else { 3916 } else {
3916 DCHECK(exponent_type.IsDouble()); 3917 DCHECK(exponent_type.IsDouble());
3917 MathPowStub stub(isolate(), MathPowStub::DOUBLE); 3918 MathPowStub stub(isolate(), MathPowStub::DOUBLE);
3918 __ CallStub(&stub); 3919 __ CallStub(&stub);
(...skipping 331 matching lines...) Expand 10 before | Expand all | Expand 10 after
4250 Register index = ToRegister(instr->index()); 4251 Register index = ToRegister(instr->index());
4251 Operand length = ToOperand(instr->length()); 4252 Operand length = ToOperand(instr->length());
4252 __ cmp(index, length); 4253 __ cmp(index, length);
4253 } 4254 }
4254 if (FLAG_debug_code && instr->hydrogen()->skip_check()) { 4255 if (FLAG_debug_code && instr->hydrogen()->skip_check()) {
4255 Label done; 4256 Label done;
4256 __ b(NegateCondition(cc), &done); 4257 __ b(NegateCondition(cc), &done);
4257 __ stop("eliminated bounds check failed"); 4258 __ stop("eliminated bounds check failed");
4258 __ bind(&done); 4259 __ bind(&done);
4259 } else { 4260 } else {
4260 DeoptimizeIf(cc, instr); 4261 DeoptimizeIf(cc, instr, "out of bounds");
4261 } 4262 }
4262 } 4263 }
4263 4264
4264 4265
4265 void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) { 4266 void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) {
4266 Register external_pointer = ToRegister(instr->elements()); 4267 Register external_pointer = ToRegister(instr->elements());
4267 Register key = no_reg; 4268 Register key = no_reg;
4268 ElementsKind elements_kind = instr->elements_kind(); 4269 ElementsKind elements_kind = instr->elements_kind();
4269 bool key_is_constant = instr->key()->IsConstantOperand(); 4270 bool key_is_constant = instr->key()->IsConstantOperand();
4270 int constant_key = 0; 4271 int constant_key = 0;
(...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after
4498 } 4499 }
4499 __ bind(&not_applicable); 4500 __ bind(&not_applicable);
4500 } 4501 }
4501 4502
4502 4503
4503 void LCodeGen::DoTrapAllocationMemento(LTrapAllocationMemento* instr) { 4504 void LCodeGen::DoTrapAllocationMemento(LTrapAllocationMemento* instr) {
4504 Register object = ToRegister(instr->object()); 4505 Register object = ToRegister(instr->object());
4505 Register temp = ToRegister(instr->temp()); 4506 Register temp = ToRegister(instr->temp());
4506 Label no_memento_found; 4507 Label no_memento_found;
4507 __ TestJSArrayForAllocationMemento(object, temp, &no_memento_found); 4508 __ TestJSArrayForAllocationMemento(object, temp, &no_memento_found);
4508 DeoptimizeIf(eq, instr); 4509 DeoptimizeIf(eq, instr, "memento found");
4509 __ bind(&no_memento_found); 4510 __ bind(&no_memento_found);
4510 } 4511 }
4511 4512
4512 4513
4513 void LCodeGen::DoStringAdd(LStringAdd* instr) { 4514 void LCodeGen::DoStringAdd(LStringAdd* instr) {
4514 DCHECK(ToRegister(instr->context()).is(cp)); 4515 DCHECK(ToRegister(instr->context()).is(cp));
4515 DCHECK(ToRegister(instr->left()).is(r1)); 4516 DCHECK(ToRegister(instr->left()).is(r1));
4516 DCHECK(ToRegister(instr->right()).is(r0)); 4517 DCHECK(ToRegister(instr->right()).is(r0));
4517 StringAddStub stub(isolate(), 4518 StringAddStub stub(isolate(),
4518 instr->hydrogen()->flags(), 4519 instr->hydrogen()->flags(),
(...skipping 313 matching lines...) Expand 10 before | Expand all | Expand 10 after
4832 } 4833 }
4833 4834
4834 4835
4835 void LCodeGen::DoSmiTag(LSmiTag* instr) { 4836 void LCodeGen::DoSmiTag(LSmiTag* instr) {
4836 HChange* hchange = instr->hydrogen(); 4837 HChange* hchange = instr->hydrogen();
4837 Register input = ToRegister(instr->value()); 4838 Register input = ToRegister(instr->value());
4838 Register output = ToRegister(instr->result()); 4839 Register output = ToRegister(instr->result());
4839 if (hchange->CheckFlag(HValue::kCanOverflow) && 4840 if (hchange->CheckFlag(HValue::kCanOverflow) &&
4840 hchange->value()->CheckFlag(HValue::kUint32)) { 4841 hchange->value()->CheckFlag(HValue::kUint32)) {
4841 __ tst(input, Operand(0xc0000000)); 4842 __ tst(input, Operand(0xc0000000));
4842 DeoptimizeIf(ne, instr); 4843 DeoptimizeIf(ne, instr, "overflow");
4843 } 4844 }
4844 if (hchange->CheckFlag(HValue::kCanOverflow) && 4845 if (hchange->CheckFlag(HValue::kCanOverflow) &&
4845 !hchange->value()->CheckFlag(HValue::kUint32)) { 4846 !hchange->value()->CheckFlag(HValue::kUint32)) {
4846 __ SmiTag(output, input, SetCC); 4847 __ SmiTag(output, input, SetCC);
4847 DeoptimizeIf(vs, instr); 4848 DeoptimizeIf(vs, instr, "overflow");
4848 } else { 4849 } else {
4849 __ SmiTag(output, input); 4850 __ SmiTag(output, input);
4850 } 4851 }
4851 } 4852 }
4852 4853
4853 4854
4854 void LCodeGen::DoSmiUntag(LSmiUntag* instr) { 4855 void LCodeGen::DoSmiUntag(LSmiUntag* instr) {
4855 Register input = ToRegister(instr->value()); 4856 Register input = ToRegister(instr->value());
4856 Register result = ToRegister(instr->result()); 4857 Register result = ToRegister(instr->result());
4857 if (instr->needs_check()) { 4858 if (instr->needs_check()) {
4858 STATIC_ASSERT(kHeapObjectTag == 1); 4859 STATIC_ASSERT(kHeapObjectTag == 1);
4859 // If the input is a HeapObject, SmiUntag will set the carry flag. 4860 // If the input is a HeapObject, SmiUntag will set the carry flag.
4860 __ SmiUntag(result, input, SetCC); 4861 __ SmiUntag(result, input, SetCC);
4861 DeoptimizeIf(cs, instr); 4862 DeoptimizeIf(cs, instr, "not a Smi");
4862 } else { 4863 } else {
4863 __ SmiUntag(result, input); 4864 __ SmiUntag(result, input);
4864 } 4865 }
4865 } 4866 }
4866 4867
4867 4868
4868 void LCodeGen::EmitNumberUntagD(LNumberUntagD* instr, Register input_reg, 4869 void LCodeGen::EmitNumberUntagD(LNumberUntagD* instr, Register input_reg,
4869 DwVfpRegister result_reg, 4870 DwVfpRegister result_reg,
4870 NumberUntagDMode mode) { 4871 NumberUntagDMode mode) {
4871 bool can_convert_undefined_to_nan = 4872 bool can_convert_undefined_to_nan =
4872 instr->hydrogen()->can_convert_undefined_to_nan(); 4873 instr->hydrogen()->can_convert_undefined_to_nan();
4873 bool deoptimize_on_minus_zero = instr->hydrogen()->deoptimize_on_minus_zero(); 4874 bool deoptimize_on_minus_zero = instr->hydrogen()->deoptimize_on_minus_zero();
4874 4875
4875 Register scratch = scratch0(); 4876 Register scratch = scratch0();
4876 SwVfpRegister flt_scratch = double_scratch0().low(); 4877 SwVfpRegister flt_scratch = double_scratch0().low();
4877 DCHECK(!result_reg.is(double_scratch0())); 4878 DCHECK(!result_reg.is(double_scratch0()));
4878 Label convert, load_smi, done; 4879 Label convert, load_smi, done;
4879 if (mode == NUMBER_CANDIDATE_IS_ANY_TAGGED) { 4880 if (mode == NUMBER_CANDIDATE_IS_ANY_TAGGED) {
4880 // Smi check. 4881 // Smi check.
4881 __ UntagAndJumpIfSmi(scratch, input_reg, &load_smi); 4882 __ UntagAndJumpIfSmi(scratch, input_reg, &load_smi);
4882 // Heap number map check. 4883 // Heap number map check.
4883 __ ldr(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset)); 4884 __ ldr(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset));
4884 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex); 4885 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex);
4885 __ cmp(scratch, Operand(ip)); 4886 __ cmp(scratch, Operand(ip));
4886 if (can_convert_undefined_to_nan) { 4887 if (can_convert_undefined_to_nan) {
4887 __ b(ne, &convert); 4888 __ b(ne, &convert);
4888 } else { 4889 } else {
4889 DeoptimizeIf(ne, instr); 4890 DeoptimizeIf(ne, instr, "not a heap number");
4890 } 4891 }
4891 // load heap number 4892 // load heap number
4892 __ vldr(result_reg, input_reg, HeapNumber::kValueOffset - kHeapObjectTag); 4893 __ vldr(result_reg, input_reg, HeapNumber::kValueOffset - kHeapObjectTag);
4893 if (deoptimize_on_minus_zero) { 4894 if (deoptimize_on_minus_zero) {
4894 __ VmovLow(scratch, result_reg); 4895 __ VmovLow(scratch, result_reg);
4895 __ cmp(scratch, Operand::Zero()); 4896 __ cmp(scratch, Operand::Zero());
4896 __ b(ne, &done); 4897 __ b(ne, &done);
4897 __ VmovHigh(scratch, result_reg); 4898 __ VmovHigh(scratch, result_reg);
4898 __ cmp(scratch, Operand(HeapNumber::kSignMask)); 4899 __ cmp(scratch, Operand(HeapNumber::kSignMask));
4899 DeoptimizeIf(eq, instr); 4900 DeoptimizeIf(eq, instr, "minus zero");
4900 } 4901 }
4901 __ jmp(&done); 4902 __ jmp(&done);
4902 if (can_convert_undefined_to_nan) { 4903 if (can_convert_undefined_to_nan) {
4903 __ bind(&convert); 4904 __ bind(&convert);
4904 // Convert undefined (and hole) to NaN. 4905 // Convert undefined (and hole) to NaN.
4905 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); 4906 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
4906 __ cmp(input_reg, Operand(ip)); 4907 __ cmp(input_reg, Operand(ip));
4907 DeoptimizeIf(ne, instr); 4908 DeoptimizeIf(ne, instr, "not a heap number/undefined");
4908 __ LoadRoot(scratch, Heap::kNanValueRootIndex); 4909 __ LoadRoot(scratch, Heap::kNanValueRootIndex);
4909 __ vldr(result_reg, scratch, HeapNumber::kValueOffset - kHeapObjectTag); 4910 __ vldr(result_reg, scratch, HeapNumber::kValueOffset - kHeapObjectTag);
4910 __ jmp(&done); 4911 __ jmp(&done);
4911 } 4912 }
4912 } else { 4913 } else {
4913 __ SmiUntag(scratch, input_reg); 4914 __ SmiUntag(scratch, input_reg);
4914 DCHECK(mode == NUMBER_CANDIDATE_IS_SMI); 4915 DCHECK(mode == NUMBER_CANDIDATE_IS_SMI);
4915 } 4916 }
4916 // Smi to double register conversion 4917 // Smi to double register conversion
4917 __ bind(&load_smi); 4918 __ bind(&load_smi);
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
4965 __ bind(&check_bools); 4966 __ bind(&check_bools);
4966 __ LoadRoot(ip, Heap::kTrueValueRootIndex); 4967 __ LoadRoot(ip, Heap::kTrueValueRootIndex);
4967 __ cmp(scratch2, Operand(ip)); 4968 __ cmp(scratch2, Operand(ip));
4968 __ b(ne, &check_false); 4969 __ b(ne, &check_false);
4969 __ mov(input_reg, Operand(1)); 4970 __ mov(input_reg, Operand(1));
4970 __ b(&done); 4971 __ b(&done);
4971 4972
4972 __ bind(&check_false); 4973 __ bind(&check_false);
4973 __ LoadRoot(ip, Heap::kFalseValueRootIndex); 4974 __ LoadRoot(ip, Heap::kFalseValueRootIndex);
4974 __ cmp(scratch2, Operand(ip)); 4975 __ cmp(scratch2, Operand(ip));
4975 DeoptimizeIf(ne, instr, "cannot truncate"); 4976 DeoptimizeIf(ne, instr, "not a heap number/undefined/true/false");
4976 __ mov(input_reg, Operand::Zero()); 4977 __ mov(input_reg, Operand::Zero());
4977 } else { 4978 } else {
4978 DeoptimizeIf(ne, instr, "not a heap number"); 4979 DeoptimizeIf(ne, instr, "not a heap number");
4979 4980
4980 __ sub(ip, scratch2, Operand(kHeapObjectTag)); 4981 __ sub(ip, scratch2, Operand(kHeapObjectTag));
4981 __ vldr(double_scratch2, ip, HeapNumber::kValueOffset); 4982 __ vldr(double_scratch2, ip, HeapNumber::kValueOffset);
4982 __ TryDoubleToInt32Exact(input_reg, double_scratch2, double_scratch); 4983 __ TryDoubleToInt32Exact(input_reg, double_scratch2, double_scratch);
4983 DeoptimizeIf(ne, instr, "lost precision or NaN"); 4984 DeoptimizeIf(ne, instr, "lost precision or NaN");
4984 4985
4985 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 4986 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
5050 Register result_reg = ToRegister(instr->result()); 5051 Register result_reg = ToRegister(instr->result());
5051 Register scratch1 = scratch0(); 5052 Register scratch1 = scratch0();
5052 DwVfpRegister double_input = ToDoubleRegister(instr->value()); 5053 DwVfpRegister double_input = ToDoubleRegister(instr->value());
5053 LowDwVfpRegister double_scratch = double_scratch0(); 5054 LowDwVfpRegister double_scratch = double_scratch0();
5054 5055
5055 if (instr->truncating()) { 5056 if (instr->truncating()) {
5056 __ TruncateDoubleToI(result_reg, double_input); 5057 __ TruncateDoubleToI(result_reg, double_input);
5057 } else { 5058 } else {
5058 __ TryDoubleToInt32Exact(result_reg, double_input, double_scratch); 5059 __ TryDoubleToInt32Exact(result_reg, double_input, double_scratch);
5059 // Deoptimize if the input wasn't a int32 (inside a double). 5060 // Deoptimize if the input wasn't a int32 (inside a double).
5060 DeoptimizeIf(ne, instr); 5061 DeoptimizeIf(ne, instr, "lost precision or NaN");
5061 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 5062 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
5062 Label done; 5063 Label done;
5063 __ cmp(result_reg, Operand::Zero()); 5064 __ cmp(result_reg, Operand::Zero());
5064 __ b(ne, &done); 5065 __ b(ne, &done);
5065 __ VmovHigh(scratch1, double_input); 5066 __ VmovHigh(scratch1, double_input);
5066 __ tst(scratch1, Operand(HeapNumber::kSignMask)); 5067 __ tst(scratch1, Operand(HeapNumber::kSignMask));
5067 DeoptimizeIf(ne, instr); 5068 DeoptimizeIf(ne, instr, "minus zero");
5068 __ bind(&done); 5069 __ bind(&done);
5069 } 5070 }
5070 } 5071 }
5071 } 5072 }
5072 5073
5073 5074
5074 void LCodeGen::DoDoubleToSmi(LDoubleToSmi* instr) { 5075 void LCodeGen::DoDoubleToSmi(LDoubleToSmi* instr) {
5075 Register result_reg = ToRegister(instr->result()); 5076 Register result_reg = ToRegister(instr->result());
5076 Register scratch1 = scratch0(); 5077 Register scratch1 = scratch0();
5077 DwVfpRegister double_input = ToDoubleRegister(instr->value()); 5078 DwVfpRegister double_input = ToDoubleRegister(instr->value());
5078 LowDwVfpRegister double_scratch = double_scratch0(); 5079 LowDwVfpRegister double_scratch = double_scratch0();
5079 5080
5080 if (instr->truncating()) { 5081 if (instr->truncating()) {
5081 __ TruncateDoubleToI(result_reg, double_input); 5082 __ TruncateDoubleToI(result_reg, double_input);
5082 } else { 5083 } else {
5083 __ TryDoubleToInt32Exact(result_reg, double_input, double_scratch); 5084 __ TryDoubleToInt32Exact(result_reg, double_input, double_scratch);
5084 // Deoptimize if the input wasn't a int32 (inside a double). 5085 // Deoptimize if the input wasn't a int32 (inside a double).
5085 DeoptimizeIf(ne, instr); 5086 DeoptimizeIf(ne, instr, "lost precision or NaN");
5086 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 5087 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
5087 Label done; 5088 Label done;
5088 __ cmp(result_reg, Operand::Zero()); 5089 __ cmp(result_reg, Operand::Zero());
5089 __ b(ne, &done); 5090 __ b(ne, &done);
5090 __ VmovHigh(scratch1, double_input); 5091 __ VmovHigh(scratch1, double_input);
5091 __ tst(scratch1, Operand(HeapNumber::kSignMask)); 5092 __ tst(scratch1, Operand(HeapNumber::kSignMask));
5092 DeoptimizeIf(ne, instr); 5093 DeoptimizeIf(ne, instr, "minus zero");
5093 __ bind(&done); 5094 __ bind(&done);
5094 } 5095 }
5095 } 5096 }
5096 __ SmiTag(result_reg, SetCC); 5097 __ SmiTag(result_reg, SetCC);
5097 DeoptimizeIf(vs, instr); 5098 DeoptimizeIf(vs, instr, "overflow");
5098 } 5099 }
5099 5100
5100 5101
5101 void LCodeGen::DoCheckSmi(LCheckSmi* instr) { 5102 void LCodeGen::DoCheckSmi(LCheckSmi* instr) {
5102 LOperand* input = instr->value(); 5103 LOperand* input = instr->value();
5103 __ SmiTst(ToRegister(input)); 5104 __ SmiTst(ToRegister(input));
5104 DeoptimizeIf(ne, instr); 5105 DeoptimizeIf(ne, instr, "not a Smi");
5105 } 5106 }
5106 5107
5107 5108
5108 void LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) { 5109 void LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) {
5109 if (!instr->hydrogen()->value()->type().IsHeapObject()) { 5110 if (!instr->hydrogen()->value()->type().IsHeapObject()) {
5110 LOperand* input = instr->value(); 5111 LOperand* input = instr->value();
5111 __ SmiTst(ToRegister(input)); 5112 __ SmiTst(ToRegister(input));
5112 DeoptimizeIf(eq, instr); 5113 DeoptimizeIf(eq, instr, "Smi");
5113 } 5114 }
5114 } 5115 }
5115 5116
5116 5117
5117 void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) { 5118 void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) {
5118 Register input = ToRegister(instr->value()); 5119 Register input = ToRegister(instr->value());
5119 Register scratch = scratch0(); 5120 Register scratch = scratch0();
5120 5121
5121 __ ldr(scratch, FieldMemOperand(input, HeapObject::kMapOffset)); 5122 __ ldr(scratch, FieldMemOperand(input, HeapObject::kMapOffset));
5122 __ ldrb(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset)); 5123 __ ldrb(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset));
5123 5124
5124 if (instr->hydrogen()->is_interval_check()) { 5125 if (instr->hydrogen()->is_interval_check()) {
5125 InstanceType first; 5126 InstanceType first;
5126 InstanceType last; 5127 InstanceType last;
5127 instr->hydrogen()->GetCheckInterval(&first, &last); 5128 instr->hydrogen()->GetCheckInterval(&first, &last);
5128 5129
5129 __ cmp(scratch, Operand(first)); 5130 __ cmp(scratch, Operand(first));
5130 5131
5131 // If there is only one type in the interval check for equality. 5132 // If there is only one type in the interval check for equality.
5132 if (first == last) { 5133 if (first == last) {
5133 DeoptimizeIf(ne, instr); 5134 DeoptimizeIf(ne, instr, "wrong instance type");
5134 } else { 5135 } else {
5135 DeoptimizeIf(lo, instr); 5136 DeoptimizeIf(lo, instr, "wrong instance type");
5136 // Omit check for the last type. 5137 // Omit check for the last type.
5137 if (last != LAST_TYPE) { 5138 if (last != LAST_TYPE) {
5138 __ cmp(scratch, Operand(last)); 5139 __ cmp(scratch, Operand(last));
5139 DeoptimizeIf(hi, instr); 5140 DeoptimizeIf(hi, instr, "wrong instance type");
5140 } 5141 }
5141 } 5142 }
5142 } else { 5143 } else {
5143 uint8_t mask; 5144 uint8_t mask;
5144 uint8_t tag; 5145 uint8_t tag;
5145 instr->hydrogen()->GetCheckMaskAndTag(&mask, &tag); 5146 instr->hydrogen()->GetCheckMaskAndTag(&mask, &tag);
5146 5147
5147 if (base::bits::IsPowerOfTwo32(mask)) { 5148 if (base::bits::IsPowerOfTwo32(mask)) {
5148 DCHECK(tag == 0 || base::bits::IsPowerOfTwo32(tag)); 5149 DCHECK(tag == 0 || base::bits::IsPowerOfTwo32(tag));
5149 __ tst(scratch, Operand(mask)); 5150 __ tst(scratch, Operand(mask));
5150 DeoptimizeIf(tag == 0 ? ne : eq, instr); 5151 DeoptimizeIf(tag == 0 ? ne : eq, instr, "wrong instance type");
5151 } else { 5152 } else {
5152 __ and_(scratch, scratch, Operand(mask)); 5153 __ and_(scratch, scratch, Operand(mask));
5153 __ cmp(scratch, Operand(tag)); 5154 __ cmp(scratch, Operand(tag));
5154 DeoptimizeIf(ne, instr); 5155 DeoptimizeIf(ne, instr, "wrong instance type");
5155 } 5156 }
5156 } 5157 }
5157 } 5158 }
5158 5159
5159 5160
5160 void LCodeGen::DoCheckValue(LCheckValue* instr) { 5161 void LCodeGen::DoCheckValue(LCheckValue* instr) {
5161 Register reg = ToRegister(instr->value()); 5162 Register reg = ToRegister(instr->value());
5162 Handle<HeapObject> object = instr->hydrogen()->object().handle(); 5163 Handle<HeapObject> object = instr->hydrogen()->object().handle();
5163 AllowDeferredHandleDereference smi_check; 5164 AllowDeferredHandleDereference smi_check;
5164 if (isolate()->heap()->InNewSpace(*object)) { 5165 if (isolate()->heap()->InNewSpace(*object)) {
5165 Register reg = ToRegister(instr->value()); 5166 Register reg = ToRegister(instr->value());
5166 Handle<Cell> cell = isolate()->factory()->NewCell(object); 5167 Handle<Cell> cell = isolate()->factory()->NewCell(object);
5167 __ mov(ip, Operand(Handle<Object>(cell))); 5168 __ mov(ip, Operand(Handle<Object>(cell)));
5168 __ ldr(ip, FieldMemOperand(ip, Cell::kValueOffset)); 5169 __ ldr(ip, FieldMemOperand(ip, Cell::kValueOffset));
5169 __ cmp(reg, ip); 5170 __ cmp(reg, ip);
5170 } else { 5171 } else {
5171 __ cmp(reg, Operand(object)); 5172 __ cmp(reg, Operand(object));
5172 } 5173 }
5173 DeoptimizeIf(ne, instr); 5174 DeoptimizeIf(ne, instr, "value mismatch");
5174 } 5175 }
5175 5176
5176 5177
5177 void LCodeGen::DoDeferredInstanceMigration(LCheckMaps* instr, Register object) { 5178 void LCodeGen::DoDeferredInstanceMigration(LCheckMaps* instr, Register object) {
5178 { 5179 {
5179 PushSafepointRegistersScope scope(this); 5180 PushSafepointRegistersScope scope(this);
5180 __ push(object); 5181 __ push(object);
5181 __ mov(cp, Operand::Zero()); 5182 __ mov(cp, Operand::Zero());
5182 __ CallRuntimeSaveDoubles(Runtime::kTryMigrateInstance); 5183 __ CallRuntimeSaveDoubles(Runtime::kTryMigrateInstance);
5183 RecordSafepointWithRegisters( 5184 RecordSafepointWithRegisters(
5184 instr->pointer_map(), 1, Safepoint::kNoLazyDeopt); 5185 instr->pointer_map(), 1, Safepoint::kNoLazyDeopt);
5185 __ StoreToSafepointRegisterSlot(r0, scratch0()); 5186 __ StoreToSafepointRegisterSlot(r0, scratch0());
5186 } 5187 }
5187 __ tst(scratch0(), Operand(kSmiTagMask)); 5188 __ tst(scratch0(), Operand(kSmiTagMask));
5188 DeoptimizeIf(eq, instr); 5189 DeoptimizeIf(eq, instr, "instance migration failed");
5189 } 5190 }
5190 5191
5191 5192
5192 void LCodeGen::DoCheckMaps(LCheckMaps* instr) { 5193 void LCodeGen::DoCheckMaps(LCheckMaps* instr) {
5193 class DeferredCheckMaps FINAL : public LDeferredCode { 5194 class DeferredCheckMaps FINAL : public LDeferredCode {
5194 public: 5195 public:
5195 DeferredCheckMaps(LCodeGen* codegen, LCheckMaps* instr, Register object) 5196 DeferredCheckMaps(LCodeGen* codegen, LCheckMaps* instr, Register object)
5196 : LDeferredCode(codegen), instr_(instr), object_(object) { 5197 : LDeferredCode(codegen), instr_(instr), object_(object) {
5197 SetExit(check_maps()); 5198 SetExit(check_maps());
5198 } 5199 }
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
5235 Handle<Map> map = maps->at(i).handle(); 5236 Handle<Map> map = maps->at(i).handle();
5236 __ CompareMap(map_reg, map, &success); 5237 __ CompareMap(map_reg, map, &success);
5237 __ b(eq, &success); 5238 __ b(eq, &success);
5238 } 5239 }
5239 5240
5240 Handle<Map> map = maps->at(maps->size() - 1).handle(); 5241 Handle<Map> map = maps->at(maps->size() - 1).handle();
5241 __ CompareMap(map_reg, map, &success); 5242 __ CompareMap(map_reg, map, &success);
5242 if (instr->hydrogen()->HasMigrationTarget()) { 5243 if (instr->hydrogen()->HasMigrationTarget()) {
5243 __ b(ne, deferred->entry()); 5244 __ b(ne, deferred->entry());
5244 } else { 5245 } else {
5245 DeoptimizeIf(ne, instr); 5246 DeoptimizeIf(ne, instr, "wrong map");
5246 } 5247 }
5247 5248
5248 __ bind(&success); 5249 __ bind(&success);
5249 } 5250 }
5250 5251
5251 5252
5252 void LCodeGen::DoClampDToUint8(LClampDToUint8* instr) { 5253 void LCodeGen::DoClampDToUint8(LClampDToUint8* instr) {
5253 DwVfpRegister value_reg = ToDoubleRegister(instr->unclamped()); 5254 DwVfpRegister value_reg = ToDoubleRegister(instr->unclamped());
5254 Register result_reg = ToRegister(instr->result()); 5255 Register result_reg = ToRegister(instr->result());
5255 __ ClampDoubleToUint8(result_reg, value_reg, double_scratch0()); 5256 __ ClampDoubleToUint8(result_reg, value_reg, double_scratch0());
(...skipping 18 matching lines...) Expand all
5274 __ UntagAndJumpIfSmi(result_reg, input_reg, &is_smi); 5275 __ UntagAndJumpIfSmi(result_reg, input_reg, &is_smi);
5275 5276
5276 // Check for heap number 5277 // Check for heap number
5277 __ ldr(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset)); 5278 __ ldr(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset));
5278 __ cmp(scratch, Operand(factory()->heap_number_map())); 5279 __ cmp(scratch, Operand(factory()->heap_number_map()));
5279 __ b(eq, &heap_number); 5280 __ b(eq, &heap_number);
5280 5281
5281 // Check for undefined. Undefined is converted to zero for clamping 5282 // Check for undefined. Undefined is converted to zero for clamping
5282 // conversions. 5283 // conversions.
5283 __ cmp(input_reg, Operand(factory()->undefined_value())); 5284 __ cmp(input_reg, Operand(factory()->undefined_value()));
5284 DeoptimizeIf(ne, instr); 5285 DeoptimizeIf(ne, instr, "not a heap number/undefined");
5285 __ mov(result_reg, Operand::Zero()); 5286 __ mov(result_reg, Operand::Zero());
5286 __ jmp(&done); 5287 __ jmp(&done);
5287 5288
5288 // Heap number 5289 // Heap number
5289 __ bind(&heap_number); 5290 __ bind(&heap_number);
5290 __ vldr(temp_reg, FieldMemOperand(input_reg, HeapNumber::kValueOffset)); 5291 __ vldr(temp_reg, FieldMemOperand(input_reg, HeapNumber::kValueOffset));
5291 __ ClampDoubleToUint8(result_reg, temp_reg, double_scratch0()); 5292 __ ClampDoubleToUint8(result_reg, temp_reg, double_scratch0());
5292 __ jmp(&done); 5293 __ jmp(&done);
5293 5294
5294 // smi 5295 // smi
(...skipping 449 matching lines...) Expand 10 before | Expand all | Expand 10 after
5744 DCHECK(!environment->HasBeenRegistered()); 5745 DCHECK(!environment->HasBeenRegistered());
5745 RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt); 5746 RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt);
5746 5747
5747 GenerateOsrPrologue(); 5748 GenerateOsrPrologue();
5748 } 5749 }
5749 5750
5750 5751
5751 void LCodeGen::DoForInPrepareMap(LForInPrepareMap* instr) { 5752 void LCodeGen::DoForInPrepareMap(LForInPrepareMap* instr) {
5752 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); 5753 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
5753 __ cmp(r0, ip); 5754 __ cmp(r0, ip);
5754 DeoptimizeIf(eq, instr); 5755 DeoptimizeIf(eq, instr, "undefined");
5755 5756
5756 Register null_value = r5; 5757 Register null_value = r5;
5757 __ LoadRoot(null_value, Heap::kNullValueRootIndex); 5758 __ LoadRoot(null_value, Heap::kNullValueRootIndex);
5758 __ cmp(r0, null_value); 5759 __ cmp(r0, null_value);
5759 DeoptimizeIf(eq, instr); 5760 DeoptimizeIf(eq, instr, "null");
5760 5761
5761 __ SmiTst(r0); 5762 __ SmiTst(r0);
5762 DeoptimizeIf(eq, instr); 5763 DeoptimizeIf(eq, instr, "Smi");
5763 5764
5764 STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE); 5765 STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE);
5765 __ CompareObjectType(r0, r1, r1, LAST_JS_PROXY_TYPE); 5766 __ CompareObjectType(r0, r1, r1, LAST_JS_PROXY_TYPE);
5766 DeoptimizeIf(le, instr); 5767 DeoptimizeIf(le, instr, "wrong instance type");
5767 5768
5768 Label use_cache, call_runtime; 5769 Label use_cache, call_runtime;
5769 __ CheckEnumCache(null_value, &call_runtime); 5770 __ CheckEnumCache(null_value, &call_runtime);
5770 5771
5771 __ ldr(r0, FieldMemOperand(r0, HeapObject::kMapOffset)); 5772 __ ldr(r0, FieldMemOperand(r0, HeapObject::kMapOffset));
5772 __ b(&use_cache); 5773 __ b(&use_cache);
5773 5774
5774 // Get the set of properties to enumerate. 5775 // Get the set of properties to enumerate.
5775 __ bind(&call_runtime); 5776 __ bind(&call_runtime);
5776 __ push(r0); 5777 __ push(r0);
5777 CallRuntime(Runtime::kGetPropertyNamesFast, 1, instr); 5778 CallRuntime(Runtime::kGetPropertyNamesFast, 1, instr);
5778 5779
5779 __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset)); 5780 __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset));
5780 __ LoadRoot(ip, Heap::kMetaMapRootIndex); 5781 __ LoadRoot(ip, Heap::kMetaMapRootIndex);
5781 __ cmp(r1, ip); 5782 __ cmp(r1, ip);
5782 DeoptimizeIf(ne, instr); 5783 DeoptimizeIf(ne, instr, "wrong map");
5783 __ bind(&use_cache); 5784 __ bind(&use_cache);
5784 } 5785 }
5785 5786
5786 5787
5787 void LCodeGen::DoForInCacheArray(LForInCacheArray* instr) { 5788 void LCodeGen::DoForInCacheArray(LForInCacheArray* instr) {
5788 Register map = ToRegister(instr->map()); 5789 Register map = ToRegister(instr->map());
5789 Register result = ToRegister(instr->result()); 5790 Register result = ToRegister(instr->result());
5790 Label load_cache, done; 5791 Label load_cache, done;
5791 __ EnumLength(result, map); 5792 __ EnumLength(result, map);
5792 __ cmp(result, Operand(Smi::FromInt(0))); 5793 __ cmp(result, Operand(Smi::FromInt(0)));
5793 __ b(ne, &load_cache); 5794 __ b(ne, &load_cache);
5794 __ mov(result, Operand(isolate()->factory()->empty_fixed_array())); 5795 __ mov(result, Operand(isolate()->factory()->empty_fixed_array()));
5795 __ jmp(&done); 5796 __ jmp(&done);
5796 5797
5797 __ bind(&load_cache); 5798 __ bind(&load_cache);
5798 __ LoadInstanceDescriptors(map, result); 5799 __ LoadInstanceDescriptors(map, result);
5799 __ ldr(result, 5800 __ ldr(result,
5800 FieldMemOperand(result, DescriptorArray::kEnumCacheOffset)); 5801 FieldMemOperand(result, DescriptorArray::kEnumCacheOffset));
5801 __ ldr(result, 5802 __ ldr(result,
5802 FieldMemOperand(result, FixedArray::SizeFor(instr->idx()))); 5803 FieldMemOperand(result, FixedArray::SizeFor(instr->idx())));
5803 __ cmp(result, Operand::Zero()); 5804 __ cmp(result, Operand::Zero());
5804 DeoptimizeIf(eq, instr); 5805 DeoptimizeIf(eq, instr, "no cache");
5805 5806
5806 __ bind(&done); 5807 __ bind(&done);
5807 } 5808 }
5808 5809
5809 5810
5810 void LCodeGen::DoCheckMapValue(LCheckMapValue* instr) { 5811 void LCodeGen::DoCheckMapValue(LCheckMapValue* instr) {
5811 Register object = ToRegister(instr->value()); 5812 Register object = ToRegister(instr->value());
5812 Register map = ToRegister(instr->map()); 5813 Register map = ToRegister(instr->map());
5813 __ ldr(scratch0(), FieldMemOperand(object, HeapObject::kMapOffset)); 5814 __ ldr(scratch0(), FieldMemOperand(object, HeapObject::kMapOffset));
5814 __ cmp(map, scratch0()); 5815 __ cmp(map, scratch0());
5815 DeoptimizeIf(ne, instr); 5816 DeoptimizeIf(ne, instr, "wrong map");
5816 } 5817 }
5817 5818
5818 5819
5819 void LCodeGen::DoDeferredLoadMutableDouble(LLoadFieldByIndex* instr, 5820 void LCodeGen::DoDeferredLoadMutableDouble(LLoadFieldByIndex* instr,
5820 Register result, 5821 Register result,
5821 Register object, 5822 Register object,
5822 Register index) { 5823 Register index) {
5823 PushSafepointRegistersScope scope(this); 5824 PushSafepointRegistersScope scope(this);
5824 __ Push(object); 5825 __ Push(object);
5825 __ Push(index); 5826 __ Push(index);
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
5902 __ Push(scope_info); 5903 __ Push(scope_info);
5903 __ push(ToRegister(instr->function())); 5904 __ push(ToRegister(instr->function()));
5904 CallRuntime(Runtime::kPushBlockContext, 2, instr); 5905 CallRuntime(Runtime::kPushBlockContext, 2, instr);
5905 RecordSafepoint(Safepoint::kNoLazyDeopt); 5906 RecordSafepoint(Safepoint::kNoLazyDeopt);
5906 } 5907 }
5907 5908
5908 5909
5909 #undef __ 5910 #undef __
5910 5911
5911 } } // namespace v8::internal 5912 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/arm/lithium-codegen-arm.h ('k') | src/arm64/lithium-codegen-arm64.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698