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

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

Issue 559143003: Thread the Lithium instruction down to DeoptimizeIf and friends. (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/x87/lithium-codegen-x87.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/v8.h" 5 #include "src/v8.h"
6 6
7 #if V8_TARGET_ARCH_X87 7 #if V8_TARGET_ARCH_X87
8 8
9 #include "src/base/bits.h" 9 #include "src/base/bits.h"
10 #include "src/code-factory.h" 10 #include "src/code-factory.h"
(...skipping 989 matching lines...) Expand 10 before | Expand all | Expand 10 after
1000 int deoptimization_index = deoptimizations_.length(); 1000 int deoptimization_index = deoptimizations_.length();
1001 int pc_offset = masm()->pc_offset(); 1001 int pc_offset = masm()->pc_offset();
1002 environment->Register(deoptimization_index, 1002 environment->Register(deoptimization_index,
1003 translation.index(), 1003 translation.index(),
1004 (mode == Safepoint::kLazyDeopt) ? pc_offset : -1); 1004 (mode == Safepoint::kLazyDeopt) ? pc_offset : -1);
1005 deoptimizations_.Add(environment, zone()); 1005 deoptimizations_.Add(environment, zone());
1006 } 1006 }
1007 } 1007 }
1008 1008
1009 1009
1010 void LCodeGen::DeoptimizeIf(Condition cc, 1010 void LCodeGen::DeoptimizeIf(Condition cc, LInstruction* instr,
1011 LEnvironment* environment,
1012 Deoptimizer::BailoutType bailout_type) { 1011 Deoptimizer::BailoutType bailout_type) {
1012 LEnvironment* environment = instr->environment();
1013 RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt); 1013 RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt);
1014 DCHECK(environment->HasBeenRegistered()); 1014 DCHECK(environment->HasBeenRegistered());
1015 int id = environment->deoptimization_index(); 1015 int id = environment->deoptimization_index();
1016 DCHECK(info()->IsOptimizing() || info()->IsStub()); 1016 DCHECK(info()->IsOptimizing() || info()->IsStub());
1017 Address entry = 1017 Address entry =
1018 Deoptimizer::GetDeoptimizationEntry(isolate(), id, bailout_type); 1018 Deoptimizer::GetDeoptimizationEntry(isolate(), id, bailout_type);
1019 if (entry == NULL) { 1019 if (entry == NULL) {
1020 Abort(kBailoutWasNotPrepared); 1020 Abort(kBailoutWasNotPrepared);
1021 return; 1021 return;
1022 } 1022 }
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
1077 } 1077 }
1078 if (cc == no_condition) { 1078 if (cc == no_condition) {
1079 __ jmp(&jump_table_.last().label); 1079 __ jmp(&jump_table_.last().label);
1080 } else { 1080 } else {
1081 __ j(cc, &jump_table_.last().label); 1081 __ j(cc, &jump_table_.last().label);
1082 } 1082 }
1083 } 1083 }
1084 } 1084 }
1085 1085
1086 1086
1087 void LCodeGen::DeoptimizeIf(Condition cc, 1087 void LCodeGen::DeoptimizeIf(Condition cc, LInstruction* instr) {
1088 LEnvironment* environment) {
1089 Deoptimizer::BailoutType bailout_type = info()->IsStub() 1088 Deoptimizer::BailoutType bailout_type = info()->IsStub()
1090 ? Deoptimizer::LAZY 1089 ? Deoptimizer::LAZY
1091 : Deoptimizer::EAGER; 1090 : Deoptimizer::EAGER;
1092 DeoptimizeIf(cc, environment, bailout_type); 1091 DeoptimizeIf(cc, instr, bailout_type);
1093 } 1092 }
1094 1093
1095 1094
1096 void LCodeGen::PopulateDeoptimizationData(Handle<Code> code) { 1095 void LCodeGen::PopulateDeoptimizationData(Handle<Code> code) {
1097 int length = deoptimizations_.length(); 1096 int length = deoptimizations_.length();
1098 if (length == 0) return; 1097 if (length == 0) return;
1099 Handle<DeoptimizationInputData> data = 1098 Handle<DeoptimizationInputData> data =
1100 DeoptimizationInputData::New(isolate(), length, TENURED); 1099 DeoptimizationInputData::New(isolate(), length, TENURED);
1101 1100
1102 Handle<ByteArray> translations = 1101 Handle<ByteArray> translations =
(...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after
1311 int32_t mask = divisor < 0 ? -(divisor + 1) : (divisor - 1); 1310 int32_t mask = divisor < 0 ? -(divisor + 1) : (divisor - 1);
1312 Label dividend_is_not_negative, done; 1311 Label dividend_is_not_negative, done;
1313 if (hmod->CheckFlag(HValue::kLeftCanBeNegative)) { 1312 if (hmod->CheckFlag(HValue::kLeftCanBeNegative)) {
1314 __ test(dividend, dividend); 1313 __ test(dividend, dividend);
1315 __ j(not_sign, &dividend_is_not_negative, Label::kNear); 1314 __ j(not_sign, &dividend_is_not_negative, Label::kNear);
1316 // Note that this is correct even for kMinInt operands. 1315 // Note that this is correct even for kMinInt operands.
1317 __ neg(dividend); 1316 __ neg(dividend);
1318 __ and_(dividend, mask); 1317 __ and_(dividend, mask);
1319 __ neg(dividend); 1318 __ neg(dividend);
1320 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { 1319 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
1321 DeoptimizeIf(zero, instr->environment()); 1320 DeoptimizeIf(zero, instr);
1322 } 1321 }
1323 __ jmp(&done, Label::kNear); 1322 __ jmp(&done, Label::kNear);
1324 } 1323 }
1325 1324
1326 __ bind(&dividend_is_not_negative); 1325 __ bind(&dividend_is_not_negative);
1327 __ and_(dividend, mask); 1326 __ and_(dividend, mask);
1328 __ bind(&done); 1327 __ bind(&done);
1329 } 1328 }
1330 1329
1331 1330
1332 void LCodeGen::DoModByConstI(LModByConstI* instr) { 1331 void LCodeGen::DoModByConstI(LModByConstI* instr) {
1333 Register dividend = ToRegister(instr->dividend()); 1332 Register dividend = ToRegister(instr->dividend());
1334 int32_t divisor = instr->divisor(); 1333 int32_t divisor = instr->divisor();
1335 DCHECK(ToRegister(instr->result()).is(eax)); 1334 DCHECK(ToRegister(instr->result()).is(eax));
1336 1335
1337 if (divisor == 0) { 1336 if (divisor == 0) {
1338 DeoptimizeIf(no_condition, instr->environment()); 1337 DeoptimizeIf(no_condition, instr);
1339 return; 1338 return;
1340 } 1339 }
1341 1340
1342 __ TruncatingDiv(dividend, Abs(divisor)); 1341 __ TruncatingDiv(dividend, Abs(divisor));
1343 __ imul(edx, edx, Abs(divisor)); 1342 __ imul(edx, edx, Abs(divisor));
1344 __ mov(eax, dividend); 1343 __ mov(eax, dividend);
1345 __ sub(eax, edx); 1344 __ sub(eax, edx);
1346 1345
1347 // Check for negative zero. 1346 // Check for negative zero.
1348 HMod* hmod = instr->hydrogen(); 1347 HMod* hmod = instr->hydrogen();
1349 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { 1348 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
1350 Label remainder_not_zero; 1349 Label remainder_not_zero;
1351 __ j(not_zero, &remainder_not_zero, Label::kNear); 1350 __ j(not_zero, &remainder_not_zero, Label::kNear);
1352 __ cmp(dividend, Immediate(0)); 1351 __ cmp(dividend, Immediate(0));
1353 DeoptimizeIf(less, instr->environment()); 1352 DeoptimizeIf(less, instr);
1354 __ bind(&remainder_not_zero); 1353 __ bind(&remainder_not_zero);
1355 } 1354 }
1356 } 1355 }
1357 1356
1358 1357
1359 void LCodeGen::DoModI(LModI* instr) { 1358 void LCodeGen::DoModI(LModI* instr) {
1360 HMod* hmod = instr->hydrogen(); 1359 HMod* hmod = instr->hydrogen();
1361 1360
1362 Register left_reg = ToRegister(instr->left()); 1361 Register left_reg = ToRegister(instr->left());
1363 DCHECK(left_reg.is(eax)); 1362 DCHECK(left_reg.is(eax));
1364 Register right_reg = ToRegister(instr->right()); 1363 Register right_reg = ToRegister(instr->right());
1365 DCHECK(!right_reg.is(eax)); 1364 DCHECK(!right_reg.is(eax));
1366 DCHECK(!right_reg.is(edx)); 1365 DCHECK(!right_reg.is(edx));
1367 Register result_reg = ToRegister(instr->result()); 1366 Register result_reg = ToRegister(instr->result());
1368 DCHECK(result_reg.is(edx)); 1367 DCHECK(result_reg.is(edx));
1369 1368
1370 Label done; 1369 Label done;
1371 // Check for x % 0, idiv would signal a divide error. We have to 1370 // Check for x % 0, idiv would signal a divide error. We have to
1372 // deopt in this case because we can't return a NaN. 1371 // deopt in this case because we can't return a NaN.
1373 if (hmod->CheckFlag(HValue::kCanBeDivByZero)) { 1372 if (hmod->CheckFlag(HValue::kCanBeDivByZero)) {
1374 __ test(right_reg, Operand(right_reg)); 1373 __ test(right_reg, Operand(right_reg));
1375 DeoptimizeIf(zero, instr->environment()); 1374 DeoptimizeIf(zero, instr);
1376 } 1375 }
1377 1376
1378 // Check for kMinInt % -1, idiv would signal a divide error. We 1377 // Check for kMinInt % -1, idiv would signal a divide error. We
1379 // have to deopt if we care about -0, because we can't return that. 1378 // have to deopt if we care about -0, because we can't return that.
1380 if (hmod->CheckFlag(HValue::kCanOverflow)) { 1379 if (hmod->CheckFlag(HValue::kCanOverflow)) {
1381 Label no_overflow_possible; 1380 Label no_overflow_possible;
1382 __ cmp(left_reg, kMinInt); 1381 __ cmp(left_reg, kMinInt);
1383 __ j(not_equal, &no_overflow_possible, Label::kNear); 1382 __ j(not_equal, &no_overflow_possible, Label::kNear);
1384 __ cmp(right_reg, -1); 1383 __ cmp(right_reg, -1);
1385 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { 1384 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
1386 DeoptimizeIf(equal, instr->environment()); 1385 DeoptimizeIf(equal, instr);
1387 } else { 1386 } else {
1388 __ j(not_equal, &no_overflow_possible, Label::kNear); 1387 __ j(not_equal, &no_overflow_possible, Label::kNear);
1389 __ Move(result_reg, Immediate(0)); 1388 __ Move(result_reg, Immediate(0));
1390 __ jmp(&done, Label::kNear); 1389 __ jmp(&done, Label::kNear);
1391 } 1390 }
1392 __ bind(&no_overflow_possible); 1391 __ bind(&no_overflow_possible);
1393 } 1392 }
1394 1393
1395 // Sign extend dividend in eax into edx:eax. 1394 // Sign extend dividend in eax into edx:eax.
1396 __ cdq(); 1395 __ cdq();
1397 1396
1398 // If we care about -0, test if the dividend is <0 and the result is 0. 1397 // If we care about -0, test if the dividend is <0 and the result is 0.
1399 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { 1398 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
1400 Label positive_left; 1399 Label positive_left;
1401 __ test(left_reg, Operand(left_reg)); 1400 __ test(left_reg, Operand(left_reg));
1402 __ j(not_sign, &positive_left, Label::kNear); 1401 __ j(not_sign, &positive_left, Label::kNear);
1403 __ idiv(right_reg); 1402 __ idiv(right_reg);
1404 __ test(result_reg, Operand(result_reg)); 1403 __ test(result_reg, Operand(result_reg));
1405 DeoptimizeIf(zero, instr->environment()); 1404 DeoptimizeIf(zero, instr);
1406 __ jmp(&done, Label::kNear); 1405 __ jmp(&done, Label::kNear);
1407 __ bind(&positive_left); 1406 __ bind(&positive_left);
1408 } 1407 }
1409 __ idiv(right_reg); 1408 __ idiv(right_reg);
1410 __ bind(&done); 1409 __ bind(&done);
1411 } 1410 }
1412 1411
1413 1412
1414 void LCodeGen::DoDivByPowerOf2I(LDivByPowerOf2I* instr) { 1413 void LCodeGen::DoDivByPowerOf2I(LDivByPowerOf2I* instr) {
1415 Register dividend = ToRegister(instr->dividend()); 1414 Register dividend = ToRegister(instr->dividend());
1416 int32_t divisor = instr->divisor(); 1415 int32_t divisor = instr->divisor();
1417 Register result = ToRegister(instr->result()); 1416 Register result = ToRegister(instr->result());
1418 DCHECK(divisor == kMinInt || base::bits::IsPowerOfTwo32(Abs(divisor))); 1417 DCHECK(divisor == kMinInt || base::bits::IsPowerOfTwo32(Abs(divisor)));
1419 DCHECK(!result.is(dividend)); 1418 DCHECK(!result.is(dividend));
1420 1419
1421 // Check for (0 / -x) that will produce negative zero. 1420 // Check for (0 / -x) that will produce negative zero.
1422 HDiv* hdiv = instr->hydrogen(); 1421 HDiv* hdiv = instr->hydrogen();
1423 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) { 1422 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) {
1424 __ test(dividend, dividend); 1423 __ test(dividend, dividend);
1425 DeoptimizeIf(zero, instr->environment()); 1424 DeoptimizeIf(zero, instr);
1426 } 1425 }
1427 // Check for (kMinInt / -1). 1426 // Check for (kMinInt / -1).
1428 if (hdiv->CheckFlag(HValue::kCanOverflow) && divisor == -1) { 1427 if (hdiv->CheckFlag(HValue::kCanOverflow) && divisor == -1) {
1429 __ cmp(dividend, kMinInt); 1428 __ cmp(dividend, kMinInt);
1430 DeoptimizeIf(zero, instr->environment()); 1429 DeoptimizeIf(zero, instr);
1431 } 1430 }
1432 // Deoptimize if remainder will not be 0. 1431 // Deoptimize if remainder will not be 0.
1433 if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32) && 1432 if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32) &&
1434 divisor != 1 && divisor != -1) { 1433 divisor != 1 && divisor != -1) {
1435 int32_t mask = divisor < 0 ? -(divisor + 1) : (divisor - 1); 1434 int32_t mask = divisor < 0 ? -(divisor + 1) : (divisor - 1);
1436 __ test(dividend, Immediate(mask)); 1435 __ test(dividend, Immediate(mask));
1437 DeoptimizeIf(not_zero, instr->environment()); 1436 DeoptimizeIf(not_zero, instr);
1438 } 1437 }
1439 __ Move(result, dividend); 1438 __ Move(result, dividend);
1440 int32_t shift = WhichPowerOf2Abs(divisor); 1439 int32_t shift = WhichPowerOf2Abs(divisor);
1441 if (shift > 0) { 1440 if (shift > 0) {
1442 // The arithmetic shift is always OK, the 'if' is an optimization only. 1441 // The arithmetic shift is always OK, the 'if' is an optimization only.
1443 if (shift > 1) __ sar(result, 31); 1442 if (shift > 1) __ sar(result, 31);
1444 __ shr(result, 32 - shift); 1443 __ shr(result, 32 - shift);
1445 __ add(result, dividend); 1444 __ add(result, dividend);
1446 __ sar(result, shift); 1445 __ sar(result, shift);
1447 } 1446 }
1448 if (divisor < 0) __ neg(result); 1447 if (divisor < 0) __ neg(result);
1449 } 1448 }
1450 1449
1451 1450
1452 void LCodeGen::DoDivByConstI(LDivByConstI* instr) { 1451 void LCodeGen::DoDivByConstI(LDivByConstI* instr) {
1453 Register dividend = ToRegister(instr->dividend()); 1452 Register dividend = ToRegister(instr->dividend());
1454 int32_t divisor = instr->divisor(); 1453 int32_t divisor = instr->divisor();
1455 DCHECK(ToRegister(instr->result()).is(edx)); 1454 DCHECK(ToRegister(instr->result()).is(edx));
1456 1455
1457 if (divisor == 0) { 1456 if (divisor == 0) {
1458 DeoptimizeIf(no_condition, instr->environment()); 1457 DeoptimizeIf(no_condition, instr);
1459 return; 1458 return;
1460 } 1459 }
1461 1460
1462 // Check for (0 / -x) that will produce negative zero. 1461 // Check for (0 / -x) that will produce negative zero.
1463 HDiv* hdiv = instr->hydrogen(); 1462 HDiv* hdiv = instr->hydrogen();
1464 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) { 1463 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) {
1465 __ test(dividend, dividend); 1464 __ test(dividend, dividend);
1466 DeoptimizeIf(zero, instr->environment()); 1465 DeoptimizeIf(zero, instr);
1467 } 1466 }
1468 1467
1469 __ TruncatingDiv(dividend, Abs(divisor)); 1468 __ TruncatingDiv(dividend, Abs(divisor));
1470 if (divisor < 0) __ neg(edx); 1469 if (divisor < 0) __ neg(edx);
1471 1470
1472 if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32)) { 1471 if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32)) {
1473 __ mov(eax, edx); 1472 __ mov(eax, edx);
1474 __ imul(eax, eax, divisor); 1473 __ imul(eax, eax, divisor);
1475 __ sub(eax, dividend); 1474 __ sub(eax, dividend);
1476 DeoptimizeIf(not_equal, instr->environment()); 1475 DeoptimizeIf(not_equal, instr);
1477 } 1476 }
1478 } 1477 }
1479 1478
1480 1479
1481 // TODO(svenpanne) Refactor this to avoid code duplication with DoFlooringDivI. 1480 // TODO(svenpanne) Refactor this to avoid code duplication with DoFlooringDivI.
1482 void LCodeGen::DoDivI(LDivI* instr) { 1481 void LCodeGen::DoDivI(LDivI* instr) {
1483 HBinaryOperation* hdiv = instr->hydrogen(); 1482 HBinaryOperation* hdiv = instr->hydrogen();
1484 Register dividend = ToRegister(instr->dividend()); 1483 Register dividend = ToRegister(instr->dividend());
1485 Register divisor = ToRegister(instr->divisor()); 1484 Register divisor = ToRegister(instr->divisor());
1486 Register remainder = ToRegister(instr->temp()); 1485 Register remainder = ToRegister(instr->temp());
1487 DCHECK(dividend.is(eax)); 1486 DCHECK(dividend.is(eax));
1488 DCHECK(remainder.is(edx)); 1487 DCHECK(remainder.is(edx));
1489 DCHECK(ToRegister(instr->result()).is(eax)); 1488 DCHECK(ToRegister(instr->result()).is(eax));
1490 DCHECK(!divisor.is(eax)); 1489 DCHECK(!divisor.is(eax));
1491 DCHECK(!divisor.is(edx)); 1490 DCHECK(!divisor.is(edx));
1492 1491
1493 // Check for x / 0. 1492 // Check for x / 0.
1494 if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) { 1493 if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) {
1495 __ test(divisor, divisor); 1494 __ test(divisor, divisor);
1496 DeoptimizeIf(zero, instr->environment()); 1495 DeoptimizeIf(zero, instr);
1497 } 1496 }
1498 1497
1499 // Check for (0 / -x) that will produce negative zero. 1498 // Check for (0 / -x) that will produce negative zero.
1500 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) { 1499 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) {
1501 Label dividend_not_zero; 1500 Label dividend_not_zero;
1502 __ test(dividend, dividend); 1501 __ test(dividend, dividend);
1503 __ j(not_zero, &dividend_not_zero, Label::kNear); 1502 __ j(not_zero, &dividend_not_zero, Label::kNear);
1504 __ test(divisor, divisor); 1503 __ test(divisor, divisor);
1505 DeoptimizeIf(sign, instr->environment()); 1504 DeoptimizeIf(sign, instr);
1506 __ bind(&dividend_not_zero); 1505 __ bind(&dividend_not_zero);
1507 } 1506 }
1508 1507
1509 // Check for (kMinInt / -1). 1508 // Check for (kMinInt / -1).
1510 if (hdiv->CheckFlag(HValue::kCanOverflow)) { 1509 if (hdiv->CheckFlag(HValue::kCanOverflow)) {
1511 Label dividend_not_min_int; 1510 Label dividend_not_min_int;
1512 __ cmp(dividend, kMinInt); 1511 __ cmp(dividend, kMinInt);
1513 __ j(not_zero, &dividend_not_min_int, Label::kNear); 1512 __ j(not_zero, &dividend_not_min_int, Label::kNear);
1514 __ cmp(divisor, -1); 1513 __ cmp(divisor, -1);
1515 DeoptimizeIf(zero, instr->environment()); 1514 DeoptimizeIf(zero, instr);
1516 __ bind(&dividend_not_min_int); 1515 __ bind(&dividend_not_min_int);
1517 } 1516 }
1518 1517
1519 // Sign extend to edx (= remainder). 1518 // Sign extend to edx (= remainder).
1520 __ cdq(); 1519 __ cdq();
1521 __ idiv(divisor); 1520 __ idiv(divisor);
1522 1521
1523 if (!hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) { 1522 if (!hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) {
1524 // Deoptimize if remainder is not 0. 1523 // Deoptimize if remainder is not 0.
1525 __ test(remainder, remainder); 1524 __ test(remainder, remainder);
1526 DeoptimizeIf(not_zero, instr->environment()); 1525 DeoptimizeIf(not_zero, instr);
1527 } 1526 }
1528 } 1527 }
1529 1528
1530 1529
1531 void LCodeGen::DoFlooringDivByPowerOf2I(LFlooringDivByPowerOf2I* instr) { 1530 void LCodeGen::DoFlooringDivByPowerOf2I(LFlooringDivByPowerOf2I* instr) {
1532 Register dividend = ToRegister(instr->dividend()); 1531 Register dividend = ToRegister(instr->dividend());
1533 int32_t divisor = instr->divisor(); 1532 int32_t divisor = instr->divisor();
1534 DCHECK(dividend.is(ToRegister(instr->result()))); 1533 DCHECK(dividend.is(ToRegister(instr->result())));
1535 1534
1536 // If the divisor is positive, things are easy: There can be no deopts and we 1535 // If the divisor is positive, things are easy: There can be no deopts and we
1537 // can simply do an arithmetic right shift. 1536 // can simply do an arithmetic right shift.
1538 if (divisor == 1) return; 1537 if (divisor == 1) return;
1539 int32_t shift = WhichPowerOf2Abs(divisor); 1538 int32_t shift = WhichPowerOf2Abs(divisor);
1540 if (divisor > 1) { 1539 if (divisor > 1) {
1541 __ sar(dividend, shift); 1540 __ sar(dividend, shift);
1542 return; 1541 return;
1543 } 1542 }
1544 1543
1545 // If the divisor is negative, we have to negate and handle edge cases. 1544 // If the divisor is negative, we have to negate and handle edge cases.
1546 __ neg(dividend); 1545 __ neg(dividend);
1547 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 1546 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
1548 DeoptimizeIf(zero, instr->environment()); 1547 DeoptimizeIf(zero, instr);
1549 } 1548 }
1550 1549
1551 // Dividing by -1 is basically negation, unless we overflow. 1550 // Dividing by -1 is basically negation, unless we overflow.
1552 if (divisor == -1) { 1551 if (divisor == -1) {
1553 if (instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) { 1552 if (instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) {
1554 DeoptimizeIf(overflow, instr->environment()); 1553 DeoptimizeIf(overflow, instr);
1555 } 1554 }
1556 return; 1555 return;
1557 } 1556 }
1558 1557
1559 // If the negation could not overflow, simply shifting is OK. 1558 // If the negation could not overflow, simply shifting is OK.
1560 if (!instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) { 1559 if (!instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) {
1561 __ sar(dividend, shift); 1560 __ sar(dividend, shift);
1562 return; 1561 return;
1563 } 1562 }
1564 1563
1565 Label not_kmin_int, done; 1564 Label not_kmin_int, done;
1566 __ j(no_overflow, &not_kmin_int, Label::kNear); 1565 __ j(no_overflow, &not_kmin_int, Label::kNear);
1567 __ mov(dividend, Immediate(kMinInt / divisor)); 1566 __ mov(dividend, Immediate(kMinInt / divisor));
1568 __ jmp(&done, Label::kNear); 1567 __ jmp(&done, Label::kNear);
1569 __ bind(&not_kmin_int); 1568 __ bind(&not_kmin_int);
1570 __ sar(dividend, shift); 1569 __ sar(dividend, shift);
1571 __ bind(&done); 1570 __ bind(&done);
1572 } 1571 }
1573 1572
1574 1573
1575 void LCodeGen::DoFlooringDivByConstI(LFlooringDivByConstI* instr) { 1574 void LCodeGen::DoFlooringDivByConstI(LFlooringDivByConstI* instr) {
1576 Register dividend = ToRegister(instr->dividend()); 1575 Register dividend = ToRegister(instr->dividend());
1577 int32_t divisor = instr->divisor(); 1576 int32_t divisor = instr->divisor();
1578 DCHECK(ToRegister(instr->result()).is(edx)); 1577 DCHECK(ToRegister(instr->result()).is(edx));
1579 1578
1580 if (divisor == 0) { 1579 if (divisor == 0) {
1581 DeoptimizeIf(no_condition, instr->environment()); 1580 DeoptimizeIf(no_condition, instr);
1582 return; 1581 return;
1583 } 1582 }
1584 1583
1585 // Check for (0 / -x) that will produce negative zero. 1584 // Check for (0 / -x) that will produce negative zero.
1586 HMathFloorOfDiv* hdiv = instr->hydrogen(); 1585 HMathFloorOfDiv* hdiv = instr->hydrogen();
1587 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) { 1586 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) {
1588 __ test(dividend, dividend); 1587 __ test(dividend, dividend);
1589 DeoptimizeIf(zero, instr->environment()); 1588 DeoptimizeIf(zero, instr);
1590 } 1589 }
1591 1590
1592 // Easy case: We need no dynamic check for the dividend and the flooring 1591 // Easy case: We need no dynamic check for the dividend and the flooring
1593 // division is the same as the truncating division. 1592 // division is the same as the truncating division.
1594 if ((divisor > 0 && !hdiv->CheckFlag(HValue::kLeftCanBeNegative)) || 1593 if ((divisor > 0 && !hdiv->CheckFlag(HValue::kLeftCanBeNegative)) ||
1595 (divisor < 0 && !hdiv->CheckFlag(HValue::kLeftCanBePositive))) { 1594 (divisor < 0 && !hdiv->CheckFlag(HValue::kLeftCanBePositive))) {
1596 __ TruncatingDiv(dividend, Abs(divisor)); 1595 __ TruncatingDiv(dividend, Abs(divisor));
1597 if (divisor < 0) __ neg(edx); 1596 if (divisor < 0) __ neg(edx);
1598 return; 1597 return;
1599 } 1598 }
(...skipping 26 matching lines...) Expand all
1626 Register result = ToRegister(instr->result()); 1625 Register result = ToRegister(instr->result());
1627 DCHECK(dividend.is(eax)); 1626 DCHECK(dividend.is(eax));
1628 DCHECK(remainder.is(edx)); 1627 DCHECK(remainder.is(edx));
1629 DCHECK(result.is(eax)); 1628 DCHECK(result.is(eax));
1630 DCHECK(!divisor.is(eax)); 1629 DCHECK(!divisor.is(eax));
1631 DCHECK(!divisor.is(edx)); 1630 DCHECK(!divisor.is(edx));
1632 1631
1633 // Check for x / 0. 1632 // Check for x / 0.
1634 if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) { 1633 if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) {
1635 __ test(divisor, divisor); 1634 __ test(divisor, divisor);
1636 DeoptimizeIf(zero, instr->environment()); 1635 DeoptimizeIf(zero, instr);
1637 } 1636 }
1638 1637
1639 // Check for (0 / -x) that will produce negative zero. 1638 // Check for (0 / -x) that will produce negative zero.
1640 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) { 1639 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) {
1641 Label dividend_not_zero; 1640 Label dividend_not_zero;
1642 __ test(dividend, dividend); 1641 __ test(dividend, dividend);
1643 __ j(not_zero, &dividend_not_zero, Label::kNear); 1642 __ j(not_zero, &dividend_not_zero, Label::kNear);
1644 __ test(divisor, divisor); 1643 __ test(divisor, divisor);
1645 DeoptimizeIf(sign, instr->environment()); 1644 DeoptimizeIf(sign, instr);
1646 __ bind(&dividend_not_zero); 1645 __ bind(&dividend_not_zero);
1647 } 1646 }
1648 1647
1649 // Check for (kMinInt / -1). 1648 // Check for (kMinInt / -1).
1650 if (hdiv->CheckFlag(HValue::kCanOverflow)) { 1649 if (hdiv->CheckFlag(HValue::kCanOverflow)) {
1651 Label dividend_not_min_int; 1650 Label dividend_not_min_int;
1652 __ cmp(dividend, kMinInt); 1651 __ cmp(dividend, kMinInt);
1653 __ j(not_zero, &dividend_not_min_int, Label::kNear); 1652 __ j(not_zero, &dividend_not_min_int, Label::kNear);
1654 __ cmp(divisor, -1); 1653 __ cmp(divisor, -1);
1655 DeoptimizeIf(zero, instr->environment()); 1654 DeoptimizeIf(zero, instr);
1656 __ bind(&dividend_not_min_int); 1655 __ bind(&dividend_not_min_int);
1657 } 1656 }
1658 1657
1659 // Sign extend to edx (= remainder). 1658 // Sign extend to edx (= remainder).
1660 __ cdq(); 1659 __ cdq();
1661 __ idiv(divisor); 1660 __ idiv(divisor);
1662 1661
1663 Label done; 1662 Label done;
1664 __ test(remainder, remainder); 1663 __ test(remainder, remainder);
1665 __ j(zero, &done, Label::kNear); 1664 __ j(zero, &done, Label::kNear);
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
1723 __ imul(left, left, constant); 1722 __ imul(left, left, constant);
1724 } 1723 }
1725 } else { 1724 } else {
1726 if (instr->hydrogen()->representation().IsSmi()) { 1725 if (instr->hydrogen()->representation().IsSmi()) {
1727 __ SmiUntag(left); 1726 __ SmiUntag(left);
1728 } 1727 }
1729 __ imul(left, ToOperand(right)); 1728 __ imul(left, ToOperand(right));
1730 } 1729 }
1731 1730
1732 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { 1731 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) {
1733 DeoptimizeIf(overflow, instr->environment()); 1732 DeoptimizeIf(overflow, instr);
1734 } 1733 }
1735 1734
1736 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 1735 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
1737 // Bail out if the result is supposed to be negative zero. 1736 // Bail out if the result is supposed to be negative zero.
1738 Label done; 1737 Label done;
1739 __ test(left, Operand(left)); 1738 __ test(left, Operand(left));
1740 __ j(not_zero, &done, Label::kNear); 1739 __ j(not_zero, &done, Label::kNear);
1741 if (right->IsConstantOperand()) { 1740 if (right->IsConstantOperand()) {
1742 if (ToInteger32(LConstantOperand::cast(right)) < 0) { 1741 if (ToInteger32(LConstantOperand::cast(right)) < 0) {
1743 DeoptimizeIf(no_condition, instr->environment()); 1742 DeoptimizeIf(no_condition, instr);
1744 } else if (ToInteger32(LConstantOperand::cast(right)) == 0) { 1743 } else if (ToInteger32(LConstantOperand::cast(right)) == 0) {
1745 __ cmp(ToRegister(instr->temp()), Immediate(0)); 1744 __ cmp(ToRegister(instr->temp()), Immediate(0));
1746 DeoptimizeIf(less, instr->environment()); 1745 DeoptimizeIf(less, instr);
1747 } 1746 }
1748 } else { 1747 } else {
1749 // Test the non-zero operand for negative sign. 1748 // Test the non-zero operand for negative sign.
1750 __ or_(ToRegister(instr->temp()), ToOperand(right)); 1749 __ or_(ToRegister(instr->temp()), ToOperand(right));
1751 DeoptimizeIf(sign, instr->environment()); 1750 DeoptimizeIf(sign, instr);
1752 } 1751 }
1753 __ bind(&done); 1752 __ bind(&done);
1754 } 1753 }
1755 } 1754 }
1756 1755
1757 1756
1758 void LCodeGen::DoBitI(LBitI* instr) { 1757 void LCodeGen::DoBitI(LBitI* instr) {
1759 LOperand* left = instr->left(); 1758 LOperand* left = instr->left();
1760 LOperand* right = instr->right(); 1759 LOperand* right = instr->right();
1761 DCHECK(left->Equals(instr->result())); 1760 DCHECK(left->Equals(instr->result()));
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
1808 DCHECK(left->Equals(instr->result())); 1807 DCHECK(left->Equals(instr->result()));
1809 DCHECK(left->IsRegister()); 1808 DCHECK(left->IsRegister());
1810 if (right->IsRegister()) { 1809 if (right->IsRegister()) {
1811 DCHECK(ToRegister(right).is(ecx)); 1810 DCHECK(ToRegister(right).is(ecx));
1812 1811
1813 switch (instr->op()) { 1812 switch (instr->op()) {
1814 case Token::ROR: 1813 case Token::ROR:
1815 __ ror_cl(ToRegister(left)); 1814 __ ror_cl(ToRegister(left));
1816 if (instr->can_deopt()) { 1815 if (instr->can_deopt()) {
1817 __ test(ToRegister(left), ToRegister(left)); 1816 __ test(ToRegister(left), ToRegister(left));
1818 DeoptimizeIf(sign, instr->environment()); 1817 DeoptimizeIf(sign, instr);
1819 } 1818 }
1820 break; 1819 break;
1821 case Token::SAR: 1820 case Token::SAR:
1822 __ sar_cl(ToRegister(left)); 1821 __ sar_cl(ToRegister(left));
1823 break; 1822 break;
1824 case Token::SHR: 1823 case Token::SHR:
1825 __ shr_cl(ToRegister(left)); 1824 __ shr_cl(ToRegister(left));
1826 if (instr->can_deopt()) { 1825 if (instr->can_deopt()) {
1827 __ test(ToRegister(left), ToRegister(left)); 1826 __ test(ToRegister(left), ToRegister(left));
1828 DeoptimizeIf(sign, instr->environment()); 1827 DeoptimizeIf(sign, instr);
1829 } 1828 }
1830 break; 1829 break;
1831 case Token::SHL: 1830 case Token::SHL:
1832 __ shl_cl(ToRegister(left)); 1831 __ shl_cl(ToRegister(left));
1833 break; 1832 break;
1834 default: 1833 default:
1835 UNREACHABLE(); 1834 UNREACHABLE();
1836 break; 1835 break;
1837 } 1836 }
1838 } else { 1837 } else {
1839 int value = ToInteger32(LConstantOperand::cast(right)); 1838 int value = ToInteger32(LConstantOperand::cast(right));
1840 uint8_t shift_count = static_cast<uint8_t>(value & 0x1F); 1839 uint8_t shift_count = static_cast<uint8_t>(value & 0x1F);
1841 switch (instr->op()) { 1840 switch (instr->op()) {
1842 case Token::ROR: 1841 case Token::ROR:
1843 if (shift_count == 0 && instr->can_deopt()) { 1842 if (shift_count == 0 && instr->can_deopt()) {
1844 __ test(ToRegister(left), ToRegister(left)); 1843 __ test(ToRegister(left), ToRegister(left));
1845 DeoptimizeIf(sign, instr->environment()); 1844 DeoptimizeIf(sign, instr);
1846 } else { 1845 } else {
1847 __ ror(ToRegister(left), shift_count); 1846 __ ror(ToRegister(left), shift_count);
1848 } 1847 }
1849 break; 1848 break;
1850 case Token::SAR: 1849 case Token::SAR:
1851 if (shift_count != 0) { 1850 if (shift_count != 0) {
1852 __ sar(ToRegister(left), shift_count); 1851 __ sar(ToRegister(left), shift_count);
1853 } 1852 }
1854 break; 1853 break;
1855 case Token::SHR: 1854 case Token::SHR:
1856 if (shift_count != 0) { 1855 if (shift_count != 0) {
1857 __ shr(ToRegister(left), shift_count); 1856 __ shr(ToRegister(left), shift_count);
1858 } else if (instr->can_deopt()) { 1857 } else if (instr->can_deopt()) {
1859 __ test(ToRegister(left), ToRegister(left)); 1858 __ test(ToRegister(left), ToRegister(left));
1860 DeoptimizeIf(sign, instr->environment()); 1859 DeoptimizeIf(sign, instr);
1861 } 1860 }
1862 break; 1861 break;
1863 case Token::SHL: 1862 case Token::SHL:
1864 if (shift_count != 0) { 1863 if (shift_count != 0) {
1865 if (instr->hydrogen_value()->representation().IsSmi() && 1864 if (instr->hydrogen_value()->representation().IsSmi() &&
1866 instr->can_deopt()) { 1865 instr->can_deopt()) {
1867 if (shift_count != 1) { 1866 if (shift_count != 1) {
1868 __ shl(ToRegister(left), shift_count - 1); 1867 __ shl(ToRegister(left), shift_count - 1);
1869 } 1868 }
1870 __ SmiTag(ToRegister(left)); 1869 __ SmiTag(ToRegister(left));
1871 DeoptimizeIf(overflow, instr->environment()); 1870 DeoptimizeIf(overflow, instr);
1872 } else { 1871 } else {
1873 __ shl(ToRegister(left), shift_count); 1872 __ shl(ToRegister(left), shift_count);
1874 } 1873 }
1875 } 1874 }
1876 break; 1875 break;
1877 default: 1876 default:
1878 UNREACHABLE(); 1877 UNREACHABLE();
1879 break; 1878 break;
1880 } 1879 }
1881 } 1880 }
1882 } 1881 }
1883 1882
1884 1883
1885 void LCodeGen::DoSubI(LSubI* instr) { 1884 void LCodeGen::DoSubI(LSubI* instr) {
1886 LOperand* left = instr->left(); 1885 LOperand* left = instr->left();
1887 LOperand* right = instr->right(); 1886 LOperand* right = instr->right();
1888 DCHECK(left->Equals(instr->result())); 1887 DCHECK(left->Equals(instr->result()));
1889 1888
1890 if (right->IsConstantOperand()) { 1889 if (right->IsConstantOperand()) {
1891 __ sub(ToOperand(left), 1890 __ sub(ToOperand(left),
1892 ToImmediate(right, instr->hydrogen()->representation())); 1891 ToImmediate(right, instr->hydrogen()->representation()));
1893 } else { 1892 } else {
1894 __ sub(ToRegister(left), ToOperand(right)); 1893 __ sub(ToRegister(left), ToOperand(right));
1895 } 1894 }
1896 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { 1895 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) {
1897 DeoptimizeIf(overflow, instr->environment()); 1896 DeoptimizeIf(overflow, instr);
1898 } 1897 }
1899 } 1898 }
1900 1899
1901 1900
1902 void LCodeGen::DoConstantI(LConstantI* instr) { 1901 void LCodeGen::DoConstantI(LConstantI* instr) {
1903 __ Move(ToRegister(instr->result()), Immediate(instr->value())); 1902 __ Move(ToRegister(instr->result()), Immediate(instr->value()));
1904 } 1903 }
1905 1904
1906 1905
1907 void LCodeGen::DoConstantS(LConstantS* instr) { 1906 void LCodeGen::DoConstantS(LConstantS* instr) {
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
1947 void LCodeGen::DoDateField(LDateField* instr) { 1946 void LCodeGen::DoDateField(LDateField* instr) {
1948 Register object = ToRegister(instr->date()); 1947 Register object = ToRegister(instr->date());
1949 Register result = ToRegister(instr->result()); 1948 Register result = ToRegister(instr->result());
1950 Register scratch = ToRegister(instr->temp()); 1949 Register scratch = ToRegister(instr->temp());
1951 Smi* index = instr->index(); 1950 Smi* index = instr->index();
1952 Label runtime, done; 1951 Label runtime, done;
1953 DCHECK(object.is(result)); 1952 DCHECK(object.is(result));
1954 DCHECK(object.is(eax)); 1953 DCHECK(object.is(eax));
1955 1954
1956 __ test(object, Immediate(kSmiTagMask)); 1955 __ test(object, Immediate(kSmiTagMask));
1957 DeoptimizeIf(zero, instr->environment()); 1956 DeoptimizeIf(zero, instr);
1958 __ CmpObjectType(object, JS_DATE_TYPE, scratch); 1957 __ CmpObjectType(object, JS_DATE_TYPE, scratch);
1959 DeoptimizeIf(not_equal, instr->environment()); 1958 DeoptimizeIf(not_equal, instr);
1960 1959
1961 if (index->value() == 0) { 1960 if (index->value() == 0) {
1962 __ mov(result, FieldOperand(object, JSDate::kValueOffset)); 1961 __ mov(result, FieldOperand(object, JSDate::kValueOffset));
1963 } else { 1962 } else {
1964 if (index->value() < JSDate::kFirstUncachedField) { 1963 if (index->value() < JSDate::kFirstUncachedField) {
1965 ExternalReference stamp = ExternalReference::date_cache_stamp(isolate()); 1964 ExternalReference stamp = ExternalReference::date_cache_stamp(isolate());
1966 __ mov(scratch, Operand::StaticVariable(stamp)); 1965 __ mov(scratch, Operand::StaticVariable(stamp));
1967 __ cmp(scratch, FieldOperand(object, JSDate::kCacheStampOffset)); 1966 __ cmp(scratch, FieldOperand(object, JSDate::kCacheStampOffset));
1968 __ j(not_equal, &runtime, Label::kNear); 1967 __ j(not_equal, &runtime, Label::kNear);
1969 __ mov(result, FieldOperand(object, JSDate::kValueOffset + 1968 __ mov(result, FieldOperand(object, JSDate::kValueOffset +
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
2079 __ lea(ToRegister(instr->result()), address); 2078 __ lea(ToRegister(instr->result()), address);
2080 } 2079 }
2081 } else { 2080 } else {
2082 if (right->IsConstantOperand()) { 2081 if (right->IsConstantOperand()) {
2083 __ add(ToOperand(left), 2082 __ add(ToOperand(left),
2084 ToImmediate(right, instr->hydrogen()->representation())); 2083 ToImmediate(right, instr->hydrogen()->representation()));
2085 } else { 2084 } else {
2086 __ add(ToRegister(left), ToOperand(right)); 2085 __ add(ToRegister(left), ToOperand(right));
2087 } 2086 }
2088 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { 2087 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) {
2089 DeoptimizeIf(overflow, instr->environment()); 2088 DeoptimizeIf(overflow, instr);
2090 } 2089 }
2091 } 2090 }
2092 } 2091 }
2093 2092
2094 2093
2095 void LCodeGen::DoMathMinMax(LMathMinMax* instr) { 2094 void LCodeGen::DoMathMinMax(LMathMinMax* instr) {
2096 LOperand* left = instr->left(); 2095 LOperand* left = instr->left();
2097 LOperand* right = instr->right(); 2096 LOperand* right = instr->right();
2098 DCHECK(left->Equals(instr->result())); 2097 DCHECK(left->Equals(instr->result()));
2099 HMathMinMax::Operation operation = instr->hydrogen()->operation(); 2098 HMathMinMax::Operation operation = instr->hydrogen()->operation();
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after
2263 } 2262 }
2264 2263
2265 if (expected.Contains(ToBooleanStub::SMI)) { 2264 if (expected.Contains(ToBooleanStub::SMI)) {
2266 // Smis: 0 -> false, all other -> true. 2265 // Smis: 0 -> false, all other -> true.
2267 __ test(reg, Operand(reg)); 2266 __ test(reg, Operand(reg));
2268 __ j(equal, instr->FalseLabel(chunk_)); 2267 __ j(equal, instr->FalseLabel(chunk_));
2269 __ JumpIfSmi(reg, instr->TrueLabel(chunk_)); 2268 __ JumpIfSmi(reg, instr->TrueLabel(chunk_));
2270 } else if (expected.NeedsMap()) { 2269 } else if (expected.NeedsMap()) {
2271 // If we need a map later and have a Smi -> deopt. 2270 // If we need a map later and have a Smi -> deopt.
2272 __ test(reg, Immediate(kSmiTagMask)); 2271 __ test(reg, Immediate(kSmiTagMask));
2273 DeoptimizeIf(zero, instr->environment()); 2272 DeoptimizeIf(zero, instr);
2274 } 2273 }
2275 2274
2276 Register map = no_reg; // Keep the compiler happy. 2275 Register map = no_reg; // Keep the compiler happy.
2277 if (expected.NeedsMap()) { 2276 if (expected.NeedsMap()) {
2278 map = ToRegister(instr->temp()); 2277 map = ToRegister(instr->temp());
2279 DCHECK(!map.is(reg)); 2278 DCHECK(!map.is(reg));
2280 __ mov(map, FieldOperand(reg, HeapObject::kMapOffset)); 2279 __ mov(map, FieldOperand(reg, HeapObject::kMapOffset));
2281 2280
2282 if (expected.CanBeUndetectable()) { 2281 if (expected.CanBeUndetectable()) {
2283 // Undetectable -> false. 2282 // Undetectable -> false.
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
2320 __ fld_d(FieldOperand(reg, HeapNumber::kValueOffset)); 2319 __ fld_d(FieldOperand(reg, HeapNumber::kValueOffset));
2321 __ FCmp(); 2320 __ FCmp();
2322 __ j(zero, instr->FalseLabel(chunk_)); 2321 __ j(zero, instr->FalseLabel(chunk_));
2323 __ jmp(instr->TrueLabel(chunk_)); 2322 __ jmp(instr->TrueLabel(chunk_));
2324 __ bind(&not_heap_number); 2323 __ bind(&not_heap_number);
2325 } 2324 }
2326 2325
2327 if (!expected.IsGeneric()) { 2326 if (!expected.IsGeneric()) {
2328 // We've seen something for the first time -> deopt. 2327 // We've seen something for the first time -> deopt.
2329 // This can only happen if we are not generic already. 2328 // This can only happen if we are not generic already.
2330 DeoptimizeIf(no_condition, instr->environment()); 2329 DeoptimizeIf(no_condition, instr);
2331 } 2330 }
2332 } 2331 }
2333 } 2332 }
2334 } 2333 }
2335 2334
2336 2335
2337 void LCodeGen::EmitGoto(int block) { 2336 void LCodeGen::EmitGoto(int block) {
2338 if (!IsNextEmittedBlock(block)) { 2337 if (!IsNextEmittedBlock(block)) {
2339 __ jmp(chunk_->GetAssemblyLabel(LookupDestination(block))); 2338 __ jmp(chunk_->GetAssemblyLabel(LookupDestination(block)));
2340 } 2339 }
(...skipping 615 matching lines...) Expand 10 before | Expand all | Expand 10 after
2956 info()->AddNoFrameRange(no_frame_start, masm_->pc_offset()); 2955 info()->AddNoFrameRange(no_frame_start, masm_->pc_offset());
2957 } 2956 }
2958 } 2957 }
2959 2958
2960 2959
2961 void LCodeGen::DoLoadGlobalCell(LLoadGlobalCell* instr) { 2960 void LCodeGen::DoLoadGlobalCell(LLoadGlobalCell* instr) {
2962 Register result = ToRegister(instr->result()); 2961 Register result = ToRegister(instr->result());
2963 __ mov(result, Operand::ForCell(instr->hydrogen()->cell().handle())); 2962 __ mov(result, Operand::ForCell(instr->hydrogen()->cell().handle()));
2964 if (instr->hydrogen()->RequiresHoleCheck()) { 2963 if (instr->hydrogen()->RequiresHoleCheck()) {
2965 __ cmp(result, factory()->the_hole_value()); 2964 __ cmp(result, factory()->the_hole_value());
2966 DeoptimizeIf(equal, instr->environment()); 2965 DeoptimizeIf(equal, instr);
2967 } 2966 }
2968 } 2967 }
2969 2968
2970 2969
2971 template <class T> 2970 template <class T>
2972 void LCodeGen::EmitVectorLoadICRegisters(T* instr) { 2971 void LCodeGen::EmitVectorLoadICRegisters(T* instr) {
2973 DCHECK(FLAG_vector_ics); 2972 DCHECK(FLAG_vector_ics);
2974 Register vector = ToRegister(instr->temp_vector()); 2973 Register vector = ToRegister(instr->temp_vector());
2975 DCHECK(vector.is(VectorLoadICDescriptor::VectorRegister())); 2974 DCHECK(vector.is(VectorLoadICDescriptor::VectorRegister()));
2976 __ mov(vector, instr->hydrogen()->feedback_vector()); 2975 __ mov(vector, instr->hydrogen()->feedback_vector());
(...skipping 23 matching lines...) Expand all
3000 void LCodeGen::DoStoreGlobalCell(LStoreGlobalCell* instr) { 2999 void LCodeGen::DoStoreGlobalCell(LStoreGlobalCell* instr) {
3001 Register value = ToRegister(instr->value()); 3000 Register value = ToRegister(instr->value());
3002 Handle<PropertyCell> cell_handle = instr->hydrogen()->cell().handle(); 3001 Handle<PropertyCell> cell_handle = instr->hydrogen()->cell().handle();
3003 3002
3004 // If the cell we are storing to contains the hole it could have 3003 // If the cell we are storing to contains the hole it could have
3005 // been deleted from the property dictionary. In that case, we need 3004 // been deleted from the property dictionary. In that case, we need
3006 // to update the property details in the property dictionary to mark 3005 // to update the property details in the property dictionary to mark
3007 // it as no longer deleted. We deoptimize in that case. 3006 // it as no longer deleted. We deoptimize in that case.
3008 if (instr->hydrogen()->RequiresHoleCheck()) { 3007 if (instr->hydrogen()->RequiresHoleCheck()) {
3009 __ cmp(Operand::ForCell(cell_handle), factory()->the_hole_value()); 3008 __ cmp(Operand::ForCell(cell_handle), factory()->the_hole_value());
3010 DeoptimizeIf(equal, instr->environment()); 3009 DeoptimizeIf(equal, instr);
3011 } 3010 }
3012 3011
3013 // Store the value. 3012 // Store the value.
3014 __ mov(Operand::ForCell(cell_handle), value); 3013 __ mov(Operand::ForCell(cell_handle), value);
3015 // Cells are always rescanned, so no write barrier here. 3014 // Cells are always rescanned, so no write barrier here.
3016 } 3015 }
3017 3016
3018 3017
3019 void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) { 3018 void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) {
3020 Register context = ToRegister(instr->context()); 3019 Register context = ToRegister(instr->context());
3021 Register result = ToRegister(instr->result()); 3020 Register result = ToRegister(instr->result());
3022 __ mov(result, ContextOperand(context, instr->slot_index())); 3021 __ mov(result, ContextOperand(context, instr->slot_index()));
3023 3022
3024 if (instr->hydrogen()->RequiresHoleCheck()) { 3023 if (instr->hydrogen()->RequiresHoleCheck()) {
3025 __ cmp(result, factory()->the_hole_value()); 3024 __ cmp(result, factory()->the_hole_value());
3026 if (instr->hydrogen()->DeoptimizesOnHole()) { 3025 if (instr->hydrogen()->DeoptimizesOnHole()) {
3027 DeoptimizeIf(equal, instr->environment()); 3026 DeoptimizeIf(equal, instr);
3028 } else { 3027 } else {
3029 Label is_not_hole; 3028 Label is_not_hole;
3030 __ j(not_equal, &is_not_hole, Label::kNear); 3029 __ j(not_equal, &is_not_hole, Label::kNear);
3031 __ mov(result, factory()->undefined_value()); 3030 __ mov(result, factory()->undefined_value());
3032 __ bind(&is_not_hole); 3031 __ bind(&is_not_hole);
3033 } 3032 }
3034 } 3033 }
3035 } 3034 }
3036 3035
3037 3036
3038 void LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) { 3037 void LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) {
3039 Register context = ToRegister(instr->context()); 3038 Register context = ToRegister(instr->context());
3040 Register value = ToRegister(instr->value()); 3039 Register value = ToRegister(instr->value());
3041 3040
3042 Label skip_assignment; 3041 Label skip_assignment;
3043 3042
3044 Operand target = ContextOperand(context, instr->slot_index()); 3043 Operand target = ContextOperand(context, instr->slot_index());
3045 if (instr->hydrogen()->RequiresHoleCheck()) { 3044 if (instr->hydrogen()->RequiresHoleCheck()) {
3046 __ cmp(target, factory()->the_hole_value()); 3045 __ cmp(target, factory()->the_hole_value());
3047 if (instr->hydrogen()->DeoptimizesOnHole()) { 3046 if (instr->hydrogen()->DeoptimizesOnHole()) {
3048 DeoptimizeIf(equal, instr->environment()); 3047 DeoptimizeIf(equal, instr);
3049 } else { 3048 } else {
3050 __ j(not_equal, &skip_assignment, Label::kNear); 3049 __ j(not_equal, &skip_assignment, Label::kNear);
3051 } 3050 }
3052 } 3051 }
3053 3052
3054 __ mov(target, value); 3053 __ mov(target, value);
3055 if (instr->hydrogen()->NeedsWriteBarrier()) { 3054 if (instr->hydrogen()->NeedsWriteBarrier()) {
3056 SmiCheck check_needed = 3055 SmiCheck check_needed =
3057 instr->hydrogen()->value()->type().IsHeapObject() 3056 instr->hydrogen()->value()->type().IsHeapObject()
3058 ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; 3057 ? OMIT_SMI_CHECK : INLINE_SMI_CHECK;
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
3135 Register function = ToRegister(instr->function()); 3134 Register function = ToRegister(instr->function());
3136 Register temp = ToRegister(instr->temp()); 3135 Register temp = ToRegister(instr->temp());
3137 Register result = ToRegister(instr->result()); 3136 Register result = ToRegister(instr->result());
3138 3137
3139 // Get the prototype or initial map from the function. 3138 // Get the prototype or initial map from the function.
3140 __ mov(result, 3139 __ mov(result,
3141 FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset)); 3140 FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset));
3142 3141
3143 // Check that the function has a prototype or an initial map. 3142 // Check that the function has a prototype or an initial map.
3144 __ cmp(Operand(result), Immediate(factory()->the_hole_value())); 3143 __ cmp(Operand(result), Immediate(factory()->the_hole_value()));
3145 DeoptimizeIf(equal, instr->environment()); 3144 DeoptimizeIf(equal, instr);
3146 3145
3147 // If the function does not have an initial map, we're done. 3146 // If the function does not have an initial map, we're done.
3148 Label done; 3147 Label done;
3149 __ CmpObjectType(result, MAP_TYPE, temp); 3148 __ CmpObjectType(result, MAP_TYPE, temp);
3150 __ j(not_equal, &done, Label::kNear); 3149 __ j(not_equal, &done, Label::kNear);
3151 3150
3152 // Get the prototype from the initial map. 3151 // Get the prototype from the initial map.
3153 __ mov(result, FieldOperand(result, Map::kPrototypeOffset)); 3152 __ mov(result, FieldOperand(result, Map::kPrototypeOffset));
3154 3153
3155 // All done. 3154 // All done.
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
3226 break; 3225 break;
3227 case EXTERNAL_INT32_ELEMENTS: 3226 case EXTERNAL_INT32_ELEMENTS:
3228 case INT32_ELEMENTS: 3227 case INT32_ELEMENTS:
3229 __ mov(result, operand); 3228 __ mov(result, operand);
3230 break; 3229 break;
3231 case EXTERNAL_UINT32_ELEMENTS: 3230 case EXTERNAL_UINT32_ELEMENTS:
3232 case UINT32_ELEMENTS: 3231 case UINT32_ELEMENTS:
3233 __ mov(result, operand); 3232 __ mov(result, operand);
3234 if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) { 3233 if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) {
3235 __ test(result, Operand(result)); 3234 __ test(result, Operand(result));
3236 DeoptimizeIf(negative, instr->environment()); 3235 DeoptimizeIf(negative, instr);
3237 } 3236 }
3238 break; 3237 break;
3239 case EXTERNAL_FLOAT32_ELEMENTS: 3238 case EXTERNAL_FLOAT32_ELEMENTS:
3240 case EXTERNAL_FLOAT64_ELEMENTS: 3239 case EXTERNAL_FLOAT64_ELEMENTS:
3241 case FLOAT32_ELEMENTS: 3240 case FLOAT32_ELEMENTS:
3242 case FLOAT64_ELEMENTS: 3241 case FLOAT64_ELEMENTS:
3243 case FAST_SMI_ELEMENTS: 3242 case FAST_SMI_ELEMENTS:
3244 case FAST_ELEMENTS: 3243 case FAST_ELEMENTS:
3245 case FAST_DOUBLE_ELEMENTS: 3244 case FAST_DOUBLE_ELEMENTS:
3246 case FAST_HOLEY_SMI_ELEMENTS: 3245 case FAST_HOLEY_SMI_ELEMENTS:
3247 case FAST_HOLEY_ELEMENTS: 3246 case FAST_HOLEY_ELEMENTS:
3248 case FAST_HOLEY_DOUBLE_ELEMENTS: 3247 case FAST_HOLEY_DOUBLE_ELEMENTS:
3249 case DICTIONARY_ELEMENTS: 3248 case DICTIONARY_ELEMENTS:
3250 case SLOPPY_ARGUMENTS_ELEMENTS: 3249 case SLOPPY_ARGUMENTS_ELEMENTS:
3251 UNREACHABLE(); 3250 UNREACHABLE();
3252 break; 3251 break;
3253 } 3252 }
3254 } 3253 }
3255 } 3254 }
3256 3255
3257 3256
3258 void LCodeGen::DoLoadKeyedFixedDoubleArray(LLoadKeyed* instr) { 3257 void LCodeGen::DoLoadKeyedFixedDoubleArray(LLoadKeyed* instr) {
3259 if (instr->hydrogen()->RequiresHoleCheck()) { 3258 if (instr->hydrogen()->RequiresHoleCheck()) {
3260 Operand hole_check_operand = BuildFastArrayOperand( 3259 Operand hole_check_operand = BuildFastArrayOperand(
3261 instr->elements(), instr->key(), 3260 instr->elements(), instr->key(),
3262 instr->hydrogen()->key()->representation(), 3261 instr->hydrogen()->key()->representation(),
3263 FAST_DOUBLE_ELEMENTS, 3262 FAST_DOUBLE_ELEMENTS,
3264 instr->base_offset() + sizeof(kHoleNanLower32)); 3263 instr->base_offset() + sizeof(kHoleNanLower32));
3265 __ cmp(hole_check_operand, Immediate(kHoleNanUpper32)); 3264 __ cmp(hole_check_operand, Immediate(kHoleNanUpper32));
3266 DeoptimizeIf(equal, instr->environment()); 3265 DeoptimizeIf(equal, instr);
3267 } 3266 }
3268 3267
3269 Operand double_load_operand = BuildFastArrayOperand( 3268 Operand double_load_operand = BuildFastArrayOperand(
3270 instr->elements(), 3269 instr->elements(),
3271 instr->key(), 3270 instr->key(),
3272 instr->hydrogen()->key()->representation(), 3271 instr->hydrogen()->key()->representation(),
3273 FAST_DOUBLE_ELEMENTS, 3272 FAST_DOUBLE_ELEMENTS,
3274 instr->base_offset()); 3273 instr->base_offset());
3275 X87Mov(ToX87Register(instr->result()), double_load_operand); 3274 X87Mov(ToX87Register(instr->result()), double_load_operand);
3276 } 3275 }
3277 3276
3278 3277
3279 void LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) { 3278 void LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) {
3280 Register result = ToRegister(instr->result()); 3279 Register result = ToRegister(instr->result());
3281 3280
3282 // Load the result. 3281 // Load the result.
3283 __ mov(result, 3282 __ mov(result,
3284 BuildFastArrayOperand(instr->elements(), instr->key(), 3283 BuildFastArrayOperand(instr->elements(), instr->key(),
3285 instr->hydrogen()->key()->representation(), 3284 instr->hydrogen()->key()->representation(),
3286 FAST_ELEMENTS, instr->base_offset())); 3285 FAST_ELEMENTS, instr->base_offset()));
3287 3286
3288 // Check for the hole value. 3287 // Check for the hole value.
3289 if (instr->hydrogen()->RequiresHoleCheck()) { 3288 if (instr->hydrogen()->RequiresHoleCheck()) {
3290 if (IsFastSmiElementsKind(instr->hydrogen()->elements_kind())) { 3289 if (IsFastSmiElementsKind(instr->hydrogen()->elements_kind())) {
3291 __ test(result, Immediate(kSmiTagMask)); 3290 __ test(result, Immediate(kSmiTagMask));
3292 DeoptimizeIf(not_equal, instr->environment()); 3291 DeoptimizeIf(not_equal, instr);
3293 } else { 3292 } else {
3294 __ cmp(result, factory()->the_hole_value()); 3293 __ cmp(result, factory()->the_hole_value());
3295 DeoptimizeIf(equal, instr->environment()); 3294 DeoptimizeIf(equal, instr);
3296 } 3295 }
3297 } 3296 }
3298 } 3297 }
3299 3298
3300 3299
3301 void LCodeGen::DoLoadKeyed(LLoadKeyed* instr) { 3300 void LCodeGen::DoLoadKeyed(LLoadKeyed* instr) {
3302 if (instr->is_typed_elements()) { 3301 if (instr->is_typed_elements()) {
3303 DoLoadKeyedExternalArray(instr); 3302 DoLoadKeyedExternalArray(instr);
3304 } else if (instr->hydrogen()->representation().IsDouble()) { 3303 } else if (instr->hydrogen()->representation().IsDouble()) {
3305 DoLoadKeyedFixedDoubleArray(instr); 3304 DoLoadKeyedFixedDoubleArray(instr);
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after
3432 } 3431 }
3433 3432
3434 // Normal function. Replace undefined or null with global receiver. 3433 // Normal function. Replace undefined or null with global receiver.
3435 __ cmp(receiver, factory()->null_value()); 3434 __ cmp(receiver, factory()->null_value());
3436 __ j(equal, &global_object, Label::kNear); 3435 __ j(equal, &global_object, Label::kNear);
3437 __ cmp(receiver, factory()->undefined_value()); 3436 __ cmp(receiver, factory()->undefined_value());
3438 __ j(equal, &global_object, Label::kNear); 3437 __ j(equal, &global_object, Label::kNear);
3439 3438
3440 // The receiver should be a JS object. 3439 // The receiver should be a JS object.
3441 __ test(receiver, Immediate(kSmiTagMask)); 3440 __ test(receiver, Immediate(kSmiTagMask));
3442 DeoptimizeIf(equal, instr->environment()); 3441 DeoptimizeIf(equal, instr);
3443 __ CmpObjectType(receiver, FIRST_SPEC_OBJECT_TYPE, scratch); 3442 __ CmpObjectType(receiver, FIRST_SPEC_OBJECT_TYPE, scratch);
3444 DeoptimizeIf(below, instr->environment()); 3443 DeoptimizeIf(below, instr);
3445 3444
3446 __ jmp(&receiver_ok, Label::kNear); 3445 __ jmp(&receiver_ok, Label::kNear);
3447 __ bind(&global_object); 3446 __ bind(&global_object);
3448 __ mov(receiver, FieldOperand(function, JSFunction::kContextOffset)); 3447 __ mov(receiver, FieldOperand(function, JSFunction::kContextOffset));
3449 const int global_offset = Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX); 3448 const int global_offset = Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX);
3450 __ mov(receiver, Operand(receiver, global_offset)); 3449 __ mov(receiver, Operand(receiver, global_offset));
3451 const int proxy_offset = GlobalObject::kGlobalProxyOffset; 3450 const int proxy_offset = GlobalObject::kGlobalProxyOffset;
3452 __ mov(receiver, FieldOperand(receiver, proxy_offset)); 3451 __ mov(receiver, FieldOperand(receiver, proxy_offset));
3453 __ bind(&receiver_ok); 3452 __ bind(&receiver_ok);
3454 } 3453 }
3455 3454
3456 3455
3457 void LCodeGen::DoApplyArguments(LApplyArguments* instr) { 3456 void LCodeGen::DoApplyArguments(LApplyArguments* instr) {
3458 Register receiver = ToRegister(instr->receiver()); 3457 Register receiver = ToRegister(instr->receiver());
3459 Register function = ToRegister(instr->function()); 3458 Register function = ToRegister(instr->function());
3460 Register length = ToRegister(instr->length()); 3459 Register length = ToRegister(instr->length());
3461 Register elements = ToRegister(instr->elements()); 3460 Register elements = ToRegister(instr->elements());
3462 DCHECK(receiver.is(eax)); // Used for parameter count. 3461 DCHECK(receiver.is(eax)); // Used for parameter count.
3463 DCHECK(function.is(edi)); // Required by InvokeFunction. 3462 DCHECK(function.is(edi)); // Required by InvokeFunction.
3464 DCHECK(ToRegister(instr->result()).is(eax)); 3463 DCHECK(ToRegister(instr->result()).is(eax));
3465 3464
3466 // Copy the arguments to this function possibly from the 3465 // Copy the arguments to this function possibly from the
3467 // adaptor frame below it. 3466 // adaptor frame below it.
3468 const uint32_t kArgumentsLimit = 1 * KB; 3467 const uint32_t kArgumentsLimit = 1 * KB;
3469 __ cmp(length, kArgumentsLimit); 3468 __ cmp(length, kArgumentsLimit);
3470 DeoptimizeIf(above, instr->environment()); 3469 DeoptimizeIf(above, instr);
3471 3470
3472 __ push(receiver); 3471 __ push(receiver);
3473 __ mov(receiver, length); 3472 __ mov(receiver, length);
3474 3473
3475 // Loop through the arguments pushing them onto the execution 3474 // Loop through the arguments pushing them onto the execution
3476 // stack. 3475 // stack.
3477 Label invoke, loop; 3476 Label invoke, loop;
3478 // length is a small non-negative integer, due to the test above. 3477 // length is a small non-negative integer, due to the test above.
3479 __ test(length, Operand(length)); 3478 __ test(length, Operand(length));
3480 __ j(zero, &invoke, Label::kNear); 3479 __ j(zero, &invoke, Label::kNear);
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after
3653 } 3652 }
3654 3653
3655 RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT); 3654 RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT);
3656 } 3655 }
3657 3656
3658 3657
3659 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LMathAbs* instr) { 3658 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LMathAbs* instr) {
3660 Register input_reg = ToRegister(instr->value()); 3659 Register input_reg = ToRegister(instr->value());
3661 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), 3660 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset),
3662 factory()->heap_number_map()); 3661 factory()->heap_number_map());
3663 DeoptimizeIf(not_equal, instr->environment()); 3662 DeoptimizeIf(not_equal, instr);
3664 3663
3665 Label slow, allocated, done; 3664 Label slow, allocated, done;
3666 Register tmp = input_reg.is(eax) ? ecx : eax; 3665 Register tmp = input_reg.is(eax) ? ecx : eax;
3667 Register tmp2 = tmp.is(ecx) ? edx : input_reg.is(ecx) ? edx : ecx; 3666 Register tmp2 = tmp.is(ecx) ? edx : input_reg.is(ecx) ? edx : ecx;
3668 3667
3669 // Preserve the value of all registers. 3668 // Preserve the value of all registers.
3670 PushSafepointRegistersScope scope(this); 3669 PushSafepointRegistersScope scope(this);
3671 3670
3672 __ mov(tmp, FieldOperand(input_reg, HeapNumber::kExponentOffset)); 3671 __ mov(tmp, FieldOperand(input_reg, HeapNumber::kExponentOffset));
3673 // Check the sign of the argument. If the argument is positive, just 3672 // Check the sign of the argument. If the argument is positive, just
(...skipping 26 matching lines...) Expand all
3700 __ bind(&done); 3699 __ bind(&done);
3701 } 3700 }
3702 3701
3703 3702
3704 void LCodeGen::EmitIntegerMathAbs(LMathAbs* instr) { 3703 void LCodeGen::EmitIntegerMathAbs(LMathAbs* instr) {
3705 Register input_reg = ToRegister(instr->value()); 3704 Register input_reg = ToRegister(instr->value());
3706 __ test(input_reg, Operand(input_reg)); 3705 __ test(input_reg, Operand(input_reg));
3707 Label is_positive; 3706 Label is_positive;
3708 __ j(not_sign, &is_positive, Label::kNear); 3707 __ j(not_sign, &is_positive, Label::kNear);
3709 __ neg(input_reg); // Sets flags. 3708 __ neg(input_reg); // Sets flags.
3710 DeoptimizeIf(negative, instr->environment()); 3709 DeoptimizeIf(negative, instr);
3711 __ bind(&is_positive); 3710 __ bind(&is_positive);
3712 } 3711 }
3713 3712
3714 3713
3715 void LCodeGen::DoMathAbs(LMathAbs* instr) { 3714 void LCodeGen::DoMathAbs(LMathAbs* instr) {
3716 // Class for deferred case. 3715 // Class for deferred case.
3717 class DeferredMathAbsTaggedHeapNumber FINAL : public LDeferredCode { 3716 class DeferredMathAbsTaggedHeapNumber FINAL : public LDeferredCode {
3718 public: 3717 public:
3719 DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen, 3718 DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen,
3720 LMathAbs* instr, 3719 LMathAbs* instr,
(...skipping 305 matching lines...) Expand 10 before | Expand all | Expand 10 after
4026 instr->hydrogen()->index()->representation())); 4025 instr->hydrogen()->index()->representation()));
4027 } else { 4026 } else {
4028 __ cmp(ToRegister(instr->index()), ToOperand(instr->length())); 4027 __ cmp(ToRegister(instr->index()), ToOperand(instr->length()));
4029 } 4028 }
4030 if (FLAG_debug_code && instr->hydrogen()->skip_check()) { 4029 if (FLAG_debug_code && instr->hydrogen()->skip_check()) {
4031 Label done; 4030 Label done;
4032 __ j(NegateCondition(cc), &done, Label::kNear); 4031 __ j(NegateCondition(cc), &done, Label::kNear);
4033 __ int3(); 4032 __ int3();
4034 __ bind(&done); 4033 __ bind(&done);
4035 } else { 4034 } else {
4036 DeoptimizeIf(cc, instr->environment()); 4035 DeoptimizeIf(cc, instr);
4037 } 4036 }
4038 } 4037 }
4039 4038
4040 4039
4041 void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) { 4040 void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) {
4042 ElementsKind elements_kind = instr->elements_kind(); 4041 ElementsKind elements_kind = instr->elements_kind();
4043 LOperand* key = instr->key(); 4042 LOperand* key = instr->key();
4044 if (!key->IsConstantOperand() && 4043 if (!key->IsConstantOperand() &&
4045 ExternalArrayOpRequiresTemp(instr->hydrogen()->key()->representation(), 4044 ExternalArrayOpRequiresTemp(instr->hydrogen()->key()->representation(),
4046 elements_kind)) { 4045 elements_kind)) {
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after
4223 CodeFactory::KeyedStoreIC(isolate(), instr->strict_mode()).code(); 4222 CodeFactory::KeyedStoreIC(isolate(), instr->strict_mode()).code();
4224 CallCode(ic, RelocInfo::CODE_TARGET, instr); 4223 CallCode(ic, RelocInfo::CODE_TARGET, instr);
4225 } 4224 }
4226 4225
4227 4226
4228 void LCodeGen::DoTrapAllocationMemento(LTrapAllocationMemento* instr) { 4227 void LCodeGen::DoTrapAllocationMemento(LTrapAllocationMemento* instr) {
4229 Register object = ToRegister(instr->object()); 4228 Register object = ToRegister(instr->object());
4230 Register temp = ToRegister(instr->temp()); 4229 Register temp = ToRegister(instr->temp());
4231 Label no_memento_found; 4230 Label no_memento_found;
4232 __ TestJSArrayForAllocationMemento(object, temp, &no_memento_found); 4231 __ TestJSArrayForAllocationMemento(object, temp, &no_memento_found);
4233 DeoptimizeIf(equal, instr->environment()); 4232 DeoptimizeIf(equal, instr);
4234 __ bind(&no_memento_found); 4233 __ bind(&no_memento_found);
4235 } 4234 }
4236 4235
4237 4236
4238 void LCodeGen::DoTransitionElementsKind(LTransitionElementsKind* instr) { 4237 void LCodeGen::DoTransitionElementsKind(LTransitionElementsKind* instr) {
4239 Register object_reg = ToRegister(instr->object()); 4238 Register object_reg = ToRegister(instr->object());
4240 4239
4241 Handle<Map> from_map = instr->original_map(); 4240 Handle<Map> from_map = instr->original_map();
4242 Handle<Map> to_map = instr->transitioned_map(); 4241 Handle<Map> to_map = instr->transitioned_map();
4243 ElementsKind from_kind = instr->from_kind(); 4242 ElementsKind from_kind = instr->from_kind();
(...skipping 348 matching lines...) Expand 10 before | Expand all | Expand 10 after
4592 __ StoreToSafepointRegisterSlot(reg, eax); 4591 __ StoreToSafepointRegisterSlot(reg, eax);
4593 } 4592 }
4594 4593
4595 4594
4596 void LCodeGen::DoSmiTag(LSmiTag* instr) { 4595 void LCodeGen::DoSmiTag(LSmiTag* instr) {
4597 HChange* hchange = instr->hydrogen(); 4596 HChange* hchange = instr->hydrogen();
4598 Register input = ToRegister(instr->value()); 4597 Register input = ToRegister(instr->value());
4599 if (hchange->CheckFlag(HValue::kCanOverflow) && 4598 if (hchange->CheckFlag(HValue::kCanOverflow) &&
4600 hchange->value()->CheckFlag(HValue::kUint32)) { 4599 hchange->value()->CheckFlag(HValue::kUint32)) {
4601 __ test(input, Immediate(0xc0000000)); 4600 __ test(input, Immediate(0xc0000000));
4602 DeoptimizeIf(not_zero, instr->environment()); 4601 DeoptimizeIf(not_zero, instr);
4603 } 4602 }
4604 __ SmiTag(input); 4603 __ SmiTag(input);
4605 if (hchange->CheckFlag(HValue::kCanOverflow) && 4604 if (hchange->CheckFlag(HValue::kCanOverflow) &&
4606 !hchange->value()->CheckFlag(HValue::kUint32)) { 4605 !hchange->value()->CheckFlag(HValue::kUint32)) {
4607 DeoptimizeIf(overflow, instr->environment()); 4606 DeoptimizeIf(overflow, instr);
4608 } 4607 }
4609 } 4608 }
4610 4609
4611 4610
4612 void LCodeGen::DoSmiUntag(LSmiUntag* instr) { 4611 void LCodeGen::DoSmiUntag(LSmiUntag* instr) {
4613 LOperand* input = instr->value(); 4612 LOperand* input = instr->value();
4614 Register result = ToRegister(input); 4613 Register result = ToRegister(input);
4615 DCHECK(input->IsRegister() && input->Equals(instr->result())); 4614 DCHECK(input->IsRegister() && input->Equals(instr->result()));
4616 if (instr->needs_check()) { 4615 if (instr->needs_check()) {
4617 __ test(result, Immediate(kSmiTagMask)); 4616 __ test(result, Immediate(kSmiTagMask));
4618 DeoptimizeIf(not_zero, instr->environment()); 4617 DeoptimizeIf(not_zero, instr);
4619 } else { 4618 } else {
4620 __ AssertSmi(result); 4619 __ AssertSmi(result);
4621 } 4620 }
4622 __ SmiUntag(result); 4621 __ SmiUntag(result);
4623 } 4622 }
4624 4623
4625 4624
4626 void LCodeGen::EmitNumberUntagDNoSSE2(Register input_reg, 4625 void LCodeGen::EmitNumberUntagDNoSSE2(LNumberUntagD* instr, Register input_reg,
4627 Register temp_reg, 4626 Register temp_reg, X87Register res_reg,
4628 X87Register res_reg,
4629 bool can_convert_undefined_to_nan,
4630 bool deoptimize_on_minus_zero,
4631 LEnvironment* env,
4632 NumberUntagDMode mode) { 4627 NumberUntagDMode mode) {
4628 bool can_convert_undefined_to_nan =
4629 instr->hydrogen()->can_convert_undefined_to_nan();
4630 bool deoptimize_on_minus_zero = instr->hydrogen()->deoptimize_on_minus_zero();
4631
4633 Label load_smi, done; 4632 Label load_smi, done;
4634 4633
4635 X87PrepareToWrite(res_reg); 4634 X87PrepareToWrite(res_reg);
4636 if (mode == NUMBER_CANDIDATE_IS_ANY_TAGGED) { 4635 if (mode == NUMBER_CANDIDATE_IS_ANY_TAGGED) {
4637 // Smi check. 4636 // Smi check.
4638 __ JumpIfSmi(input_reg, &load_smi, Label::kNear); 4637 __ JumpIfSmi(input_reg, &load_smi, Label::kNear);
4639 4638
4640 // Heap number map check. 4639 // Heap number map check.
4641 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), 4640 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset),
4642 factory()->heap_number_map()); 4641 factory()->heap_number_map());
4643 if (!can_convert_undefined_to_nan) { 4642 if (!can_convert_undefined_to_nan) {
4644 DeoptimizeIf(not_equal, env); 4643 DeoptimizeIf(not_equal, instr);
4645 } else { 4644 } else {
4646 Label heap_number, convert; 4645 Label heap_number, convert;
4647 __ j(equal, &heap_number, Label::kNear); 4646 __ j(equal, &heap_number, Label::kNear);
4648 4647
4649 // Convert undefined (or hole) to NaN. 4648 // Convert undefined (or hole) to NaN.
4650 __ cmp(input_reg, factory()->undefined_value()); 4649 __ cmp(input_reg, factory()->undefined_value());
4651 DeoptimizeIf(not_equal, env); 4650 DeoptimizeIf(not_equal, instr);
4652 4651
4653 __ bind(&convert); 4652 __ bind(&convert);
4654 ExternalReference nan = 4653 ExternalReference nan =
4655 ExternalReference::address_of_canonical_non_hole_nan(); 4654 ExternalReference::address_of_canonical_non_hole_nan();
4656 __ fld_d(Operand::StaticVariable(nan)); 4655 __ fld_d(Operand::StaticVariable(nan));
4657 __ jmp(&done, Label::kNear); 4656 __ jmp(&done, Label::kNear);
4658 4657
4659 __ bind(&heap_number); 4658 __ bind(&heap_number);
4660 } 4659 }
4661 // Heap number to x87 conversion. 4660 // Heap number to x87 conversion.
4662 __ fld_d(FieldOperand(input_reg, HeapNumber::kValueOffset)); 4661 __ fld_d(FieldOperand(input_reg, HeapNumber::kValueOffset));
4663 if (deoptimize_on_minus_zero) { 4662 if (deoptimize_on_minus_zero) {
4664 __ fldz(); 4663 __ fldz();
4665 __ FCmp(); 4664 __ FCmp();
4666 __ fld_d(FieldOperand(input_reg, HeapNumber::kValueOffset)); 4665 __ fld_d(FieldOperand(input_reg, HeapNumber::kValueOffset));
4667 __ j(not_zero, &done, Label::kNear); 4666 __ j(not_zero, &done, Label::kNear);
4668 4667
4669 // Use general purpose registers to check if we have -0.0 4668 // Use general purpose registers to check if we have -0.0
4670 __ mov(temp_reg, FieldOperand(input_reg, HeapNumber::kExponentOffset)); 4669 __ mov(temp_reg, FieldOperand(input_reg, HeapNumber::kExponentOffset));
4671 __ test(temp_reg, Immediate(HeapNumber::kSignMask)); 4670 __ test(temp_reg, Immediate(HeapNumber::kSignMask));
4672 __ j(zero, &done, Label::kNear); 4671 __ j(zero, &done, Label::kNear);
4673 4672
4674 // Pop FPU stack before deoptimizing. 4673 // Pop FPU stack before deoptimizing.
4675 __ fstp(0); 4674 __ fstp(0);
4676 DeoptimizeIf(not_zero, env); 4675 DeoptimizeIf(not_zero, instr);
4677 } 4676 }
4678 __ jmp(&done, Label::kNear); 4677 __ jmp(&done, Label::kNear);
4679 } else { 4678 } else {
4680 DCHECK(mode == NUMBER_CANDIDATE_IS_SMI); 4679 DCHECK(mode == NUMBER_CANDIDATE_IS_SMI);
4681 } 4680 }
4682 4681
4683 __ bind(&load_smi); 4682 __ bind(&load_smi);
4684 // Clobbering a temp is faster than re-tagging the 4683 // Clobbering a temp is faster than re-tagging the
4685 // input register since we avoid dependencies. 4684 // input register since we avoid dependencies.
4686 __ mov(temp_reg, input_reg); 4685 __ mov(temp_reg, input_reg);
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
4720 4719
4721 __ bind(&check_bools); 4720 __ bind(&check_bools);
4722 __ cmp(input_reg, factory()->true_value()); 4721 __ cmp(input_reg, factory()->true_value());
4723 __ j(not_equal, &check_false, Label::kNear); 4722 __ j(not_equal, &check_false, Label::kNear);
4724 __ Move(input_reg, Immediate(1)); 4723 __ Move(input_reg, Immediate(1));
4725 __ jmp(done); 4724 __ jmp(done);
4726 4725
4727 __ bind(&check_false); 4726 __ bind(&check_false);
4728 __ cmp(input_reg, factory()->false_value()); 4727 __ cmp(input_reg, factory()->false_value());
4729 __ RecordComment("Deferred TaggedToI: cannot truncate"); 4728 __ RecordComment("Deferred TaggedToI: cannot truncate");
4730 DeoptimizeIf(not_equal, instr->environment()); 4729 DeoptimizeIf(not_equal, instr);
4731 __ Move(input_reg, Immediate(0)); 4730 __ Move(input_reg, Immediate(0));
4732 } else { 4731 } else {
4733 // TODO(olivf) Converting a number on the fpu is actually quite slow. We 4732 // TODO(olivf) Converting a number on the fpu is actually quite slow. We
4734 // should first try a fast conversion and then bailout to this slow case. 4733 // should first try a fast conversion and then bailout to this slow case.
4735 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), 4734 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset),
4736 isolate()->factory()->heap_number_map()); 4735 isolate()->factory()->heap_number_map());
4737 __ RecordComment("Deferred TaggedToI: not a heap number"); 4736 __ RecordComment("Deferred TaggedToI: not a heap number");
4738 DeoptimizeIf(not_equal, instr->environment()); 4737 DeoptimizeIf(not_equal, instr);
4739 4738
4740 __ sub(esp, Immediate(kPointerSize)); 4739 __ sub(esp, Immediate(kPointerSize));
4741 __ fld_d(FieldOperand(input_reg, HeapNumber::kValueOffset)); 4740 __ fld_d(FieldOperand(input_reg, HeapNumber::kValueOffset));
4742 4741
4743 if (instr->hydrogen()->GetMinusZeroMode() == FAIL_ON_MINUS_ZERO) { 4742 if (instr->hydrogen()->GetMinusZeroMode() == FAIL_ON_MINUS_ZERO) {
4744 Label no_precision_lost, not_nan, zero_check; 4743 Label no_precision_lost, not_nan, zero_check;
4745 __ fld(0); 4744 __ fld(0);
4746 4745
4747 __ fist_s(MemOperand(esp, 0)); 4746 __ fist_s(MemOperand(esp, 0));
4748 __ fild_s(MemOperand(esp, 0)); 4747 __ fild_s(MemOperand(esp, 0));
4749 __ FCmp(); 4748 __ FCmp();
4750 __ pop(input_reg); 4749 __ pop(input_reg);
4751 4750
4752 __ j(equal, &no_precision_lost, Label::kNear); 4751 __ j(equal, &no_precision_lost, Label::kNear);
4753 __ fstp(0); 4752 __ fstp(0);
4754 __ RecordComment("Deferred TaggedToI: lost precision"); 4753 __ RecordComment("Deferred TaggedToI: lost precision");
4755 DeoptimizeIf(no_condition, instr->environment()); 4754 DeoptimizeIf(no_condition, instr);
4756 __ bind(&no_precision_lost); 4755 __ bind(&no_precision_lost);
4757 4756
4758 __ j(parity_odd, &not_nan); 4757 __ j(parity_odd, &not_nan);
4759 __ fstp(0); 4758 __ fstp(0);
4760 __ RecordComment("Deferred TaggedToI: NaN"); 4759 __ RecordComment("Deferred TaggedToI: NaN");
4761 DeoptimizeIf(no_condition, instr->environment()); 4760 DeoptimizeIf(no_condition, instr);
4762 __ bind(&not_nan); 4761 __ bind(&not_nan);
4763 4762
4764 __ test(input_reg, Operand(input_reg)); 4763 __ test(input_reg, Operand(input_reg));
4765 __ j(zero, &zero_check, Label::kNear); 4764 __ j(zero, &zero_check, Label::kNear);
4766 __ fstp(0); 4765 __ fstp(0);
4767 __ jmp(done); 4766 __ jmp(done);
4768 4767
4769 __ bind(&zero_check); 4768 __ bind(&zero_check);
4770 // To check for minus zero, we load the value again as float, and check 4769 // To check for minus zero, we load the value again as float, and check
4771 // if that is still 0. 4770 // if that is still 0.
4772 __ sub(esp, Immediate(kPointerSize)); 4771 __ sub(esp, Immediate(kPointerSize));
4773 __ fstp_s(Operand(esp, 0)); 4772 __ fstp_s(Operand(esp, 0));
4774 __ pop(input_reg); 4773 __ pop(input_reg);
4775 __ test(input_reg, Operand(input_reg)); 4774 __ test(input_reg, Operand(input_reg));
4776 __ RecordComment("Deferred TaggedToI: minus zero"); 4775 __ RecordComment("Deferred TaggedToI: minus zero");
4777 DeoptimizeIf(not_zero, instr->environment()); 4776 DeoptimizeIf(not_zero, instr);
4778 } else { 4777 } else {
4779 __ fist_s(MemOperand(esp, 0)); 4778 __ fist_s(MemOperand(esp, 0));
4780 __ fild_s(MemOperand(esp, 0)); 4779 __ fild_s(MemOperand(esp, 0));
4781 __ FCmp(); 4780 __ FCmp();
4782 __ pop(input_reg); 4781 __ pop(input_reg);
4783 __ RecordComment("Deferred TaggedToI: lost precision"); 4782 __ RecordComment("Deferred TaggedToI: lost precision");
4784 DeoptimizeIf(not_equal, instr->environment()); 4783 DeoptimizeIf(not_equal, instr);
4785 __ RecordComment("Deferred TaggedToI: NaN"); 4784 __ RecordComment("Deferred TaggedToI: NaN");
4786 DeoptimizeIf(parity_even, instr->environment()); 4785 DeoptimizeIf(parity_even, instr);
4787 } 4786 }
4788 } 4787 }
4789 } 4788 }
4790 4789
4791 4790
4792 void LCodeGen::DoTaggedToI(LTaggedToI* instr) { 4791 void LCodeGen::DoTaggedToI(LTaggedToI* instr) {
4793 class DeferredTaggedToI FINAL : public LDeferredCode { 4792 class DeferredTaggedToI FINAL : public LDeferredCode {
4794 public: 4793 public:
4795 DeferredTaggedToI(LCodeGen* codegen, 4794 DeferredTaggedToI(LCodeGen* codegen,
4796 LTaggedToI* instr, 4795 LTaggedToI* instr,
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
4828 4827
4829 void LCodeGen::DoNumberUntagD(LNumberUntagD* instr) { 4828 void LCodeGen::DoNumberUntagD(LNumberUntagD* instr) {
4830 LOperand* input = instr->value(); 4829 LOperand* input = instr->value();
4831 DCHECK(input->IsRegister()); 4830 DCHECK(input->IsRegister());
4832 LOperand* temp = instr->temp(); 4831 LOperand* temp = instr->temp();
4833 DCHECK(temp->IsRegister()); 4832 DCHECK(temp->IsRegister());
4834 LOperand* result = instr->result(); 4833 LOperand* result = instr->result();
4835 DCHECK(result->IsDoubleRegister()); 4834 DCHECK(result->IsDoubleRegister());
4836 4835
4837 Register input_reg = ToRegister(input); 4836 Register input_reg = ToRegister(input);
4838 bool deoptimize_on_minus_zero =
4839 instr->hydrogen()->deoptimize_on_minus_zero();
4840 Register temp_reg = ToRegister(temp); 4837 Register temp_reg = ToRegister(temp);
4841 4838
4842 HValue* value = instr->hydrogen()->value(); 4839 HValue* value = instr->hydrogen()->value();
4843 NumberUntagDMode mode = value->representation().IsSmi() 4840 NumberUntagDMode mode = value->representation().IsSmi()
4844 ? NUMBER_CANDIDATE_IS_SMI : NUMBER_CANDIDATE_IS_ANY_TAGGED; 4841 ? NUMBER_CANDIDATE_IS_SMI : NUMBER_CANDIDATE_IS_ANY_TAGGED;
4845 4842
4846 EmitNumberUntagDNoSSE2(input_reg, 4843 EmitNumberUntagDNoSSE2(instr, input_reg, temp_reg, ToX87Register(result),
4847 temp_reg,
4848 ToX87Register(result),
4849 instr->hydrogen()->can_convert_undefined_to_nan(),
4850 deoptimize_on_minus_zero,
4851 instr->environment(),
4852 mode); 4844 mode);
4853 } 4845 }
4854 4846
4855 4847
4856 void LCodeGen::DoDoubleToI(LDoubleToI* instr) { 4848 void LCodeGen::DoDoubleToI(LDoubleToI* instr) {
4857 LOperand* input = instr->value(); 4849 LOperand* input = instr->value();
4858 DCHECK(input->IsDoubleRegister()); 4850 DCHECK(input->IsDoubleRegister());
4859 LOperand* result = instr->result(); 4851 LOperand* result = instr->result();
4860 DCHECK(result->IsRegister()); 4852 DCHECK(result->IsRegister());
4861 Register result_reg = ToRegister(result); 4853 Register result_reg = ToRegister(result);
4862 4854
4863 if (instr->truncating()) { 4855 if (instr->truncating()) {
4864 X87Register input_reg = ToX87Register(input); 4856 X87Register input_reg = ToX87Register(input);
4865 X87Fxch(input_reg); 4857 X87Fxch(input_reg);
4866 __ TruncateX87TOSToI(result_reg); 4858 __ TruncateX87TOSToI(result_reg);
4867 } else { 4859 } else {
4868 Label bailout, done; 4860 Label bailout, done;
4869 X87Register input_reg = ToX87Register(input); 4861 X87Register input_reg = ToX87Register(input);
4870 X87Fxch(input_reg); 4862 X87Fxch(input_reg);
4871 __ X87TOSToI(result_reg, instr->hydrogen()->GetMinusZeroMode(), 4863 __ X87TOSToI(result_reg, instr->hydrogen()->GetMinusZeroMode(),
4872 &bailout, Label::kNear); 4864 &bailout, Label::kNear);
4873 __ jmp(&done, Label::kNear); 4865 __ jmp(&done, Label::kNear);
4874 __ bind(&bailout); 4866 __ bind(&bailout);
4875 DeoptimizeIf(no_condition, instr->environment()); 4867 DeoptimizeIf(no_condition, instr);
4876 __ bind(&done); 4868 __ bind(&done);
4877 } 4869 }
4878 } 4870 }
4879 4871
4880 4872
4881 void LCodeGen::DoDoubleToSmi(LDoubleToSmi* instr) { 4873 void LCodeGen::DoDoubleToSmi(LDoubleToSmi* instr) {
4882 LOperand* input = instr->value(); 4874 LOperand* input = instr->value();
4883 DCHECK(input->IsDoubleRegister()); 4875 DCHECK(input->IsDoubleRegister());
4884 LOperand* result = instr->result(); 4876 LOperand* result = instr->result();
4885 DCHECK(result->IsRegister()); 4877 DCHECK(result->IsRegister());
4886 Register result_reg = ToRegister(result); 4878 Register result_reg = ToRegister(result);
4887 4879
4888 Label bailout, done; 4880 Label bailout, done;
4889 X87Register input_reg = ToX87Register(input); 4881 X87Register input_reg = ToX87Register(input);
4890 X87Fxch(input_reg); 4882 X87Fxch(input_reg);
4891 __ X87TOSToI(result_reg, instr->hydrogen()->GetMinusZeroMode(), 4883 __ X87TOSToI(result_reg, instr->hydrogen()->GetMinusZeroMode(),
4892 &bailout, Label::kNear); 4884 &bailout, Label::kNear);
4893 __ jmp(&done, Label::kNear); 4885 __ jmp(&done, Label::kNear);
4894 __ bind(&bailout); 4886 __ bind(&bailout);
4895 DeoptimizeIf(no_condition, instr->environment()); 4887 DeoptimizeIf(no_condition, instr);
4896 __ bind(&done); 4888 __ bind(&done);
4897 4889
4898 __ SmiTag(result_reg); 4890 __ SmiTag(result_reg);
4899 DeoptimizeIf(overflow, instr->environment()); 4891 DeoptimizeIf(overflow, instr);
4900 } 4892 }
4901 4893
4902 4894
4903 void LCodeGen::DoCheckSmi(LCheckSmi* instr) { 4895 void LCodeGen::DoCheckSmi(LCheckSmi* instr) {
4904 LOperand* input = instr->value(); 4896 LOperand* input = instr->value();
4905 __ test(ToOperand(input), Immediate(kSmiTagMask)); 4897 __ test(ToOperand(input), Immediate(kSmiTagMask));
4906 DeoptimizeIf(not_zero, instr->environment()); 4898 DeoptimizeIf(not_zero, instr);
4907 } 4899 }
4908 4900
4909 4901
4910 void LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) { 4902 void LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) {
4911 if (!instr->hydrogen()->value()->type().IsHeapObject()) { 4903 if (!instr->hydrogen()->value()->type().IsHeapObject()) {
4912 LOperand* input = instr->value(); 4904 LOperand* input = instr->value();
4913 __ test(ToOperand(input), Immediate(kSmiTagMask)); 4905 __ test(ToOperand(input), Immediate(kSmiTagMask));
4914 DeoptimizeIf(zero, instr->environment()); 4906 DeoptimizeIf(zero, instr);
4915 } 4907 }
4916 } 4908 }
4917 4909
4918 4910
4919 void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) { 4911 void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) {
4920 Register input = ToRegister(instr->value()); 4912 Register input = ToRegister(instr->value());
4921 Register temp = ToRegister(instr->temp()); 4913 Register temp = ToRegister(instr->temp());
4922 4914
4923 __ mov(temp, FieldOperand(input, HeapObject::kMapOffset)); 4915 __ mov(temp, FieldOperand(input, HeapObject::kMapOffset));
4924 4916
4925 if (instr->hydrogen()->is_interval_check()) { 4917 if (instr->hydrogen()->is_interval_check()) {
4926 InstanceType first; 4918 InstanceType first;
4927 InstanceType last; 4919 InstanceType last;
4928 instr->hydrogen()->GetCheckInterval(&first, &last); 4920 instr->hydrogen()->GetCheckInterval(&first, &last);
4929 4921
4930 __ cmpb(FieldOperand(temp, Map::kInstanceTypeOffset), 4922 __ cmpb(FieldOperand(temp, Map::kInstanceTypeOffset),
4931 static_cast<int8_t>(first)); 4923 static_cast<int8_t>(first));
4932 4924
4933 // If there is only one type in the interval check for equality. 4925 // If there is only one type in the interval check for equality.
4934 if (first == last) { 4926 if (first == last) {
4935 DeoptimizeIf(not_equal, instr->environment()); 4927 DeoptimizeIf(not_equal, instr);
4936 } else { 4928 } else {
4937 DeoptimizeIf(below, instr->environment()); 4929 DeoptimizeIf(below, instr);
4938 // Omit check for the last type. 4930 // Omit check for the last type.
4939 if (last != LAST_TYPE) { 4931 if (last != LAST_TYPE) {
4940 __ cmpb(FieldOperand(temp, Map::kInstanceTypeOffset), 4932 __ cmpb(FieldOperand(temp, Map::kInstanceTypeOffset),
4941 static_cast<int8_t>(last)); 4933 static_cast<int8_t>(last));
4942 DeoptimizeIf(above, instr->environment()); 4934 DeoptimizeIf(above, instr);
4943 } 4935 }
4944 } 4936 }
4945 } else { 4937 } else {
4946 uint8_t mask; 4938 uint8_t mask;
4947 uint8_t tag; 4939 uint8_t tag;
4948 instr->hydrogen()->GetCheckMaskAndTag(&mask, &tag); 4940 instr->hydrogen()->GetCheckMaskAndTag(&mask, &tag);
4949 4941
4950 if (base::bits::IsPowerOfTwo32(mask)) { 4942 if (base::bits::IsPowerOfTwo32(mask)) {
4951 DCHECK(tag == 0 || base::bits::IsPowerOfTwo32(tag)); 4943 DCHECK(tag == 0 || base::bits::IsPowerOfTwo32(tag));
4952 __ test_b(FieldOperand(temp, Map::kInstanceTypeOffset), mask); 4944 __ test_b(FieldOperand(temp, Map::kInstanceTypeOffset), mask);
4953 DeoptimizeIf(tag == 0 ? not_zero : zero, instr->environment()); 4945 DeoptimizeIf(tag == 0 ? not_zero : zero, instr);
4954 } else { 4946 } else {
4955 __ movzx_b(temp, FieldOperand(temp, Map::kInstanceTypeOffset)); 4947 __ movzx_b(temp, FieldOperand(temp, Map::kInstanceTypeOffset));
4956 __ and_(temp, mask); 4948 __ and_(temp, mask);
4957 __ cmp(temp, tag); 4949 __ cmp(temp, tag);
4958 DeoptimizeIf(not_equal, instr->environment()); 4950 DeoptimizeIf(not_equal, instr);
4959 } 4951 }
4960 } 4952 }
4961 } 4953 }
4962 4954
4963 4955
4964 void LCodeGen::DoCheckValue(LCheckValue* instr) { 4956 void LCodeGen::DoCheckValue(LCheckValue* instr) {
4965 Handle<HeapObject> object = instr->hydrogen()->object().handle(); 4957 Handle<HeapObject> object = instr->hydrogen()->object().handle();
4966 if (instr->hydrogen()->object_in_new_space()) { 4958 if (instr->hydrogen()->object_in_new_space()) {
4967 Register reg = ToRegister(instr->value()); 4959 Register reg = ToRegister(instr->value());
4968 Handle<Cell> cell = isolate()->factory()->NewCell(object); 4960 Handle<Cell> cell = isolate()->factory()->NewCell(object);
4969 __ cmp(reg, Operand::ForCell(cell)); 4961 __ cmp(reg, Operand::ForCell(cell));
4970 } else { 4962 } else {
4971 Operand operand = ToOperand(instr->value()); 4963 Operand operand = ToOperand(instr->value());
4972 __ cmp(operand, object); 4964 __ cmp(operand, object);
4973 } 4965 }
4974 DeoptimizeIf(not_equal, instr->environment()); 4966 DeoptimizeIf(not_equal, instr);
4975 } 4967 }
4976 4968
4977 4969
4978 void LCodeGen::DoDeferredInstanceMigration(LCheckMaps* instr, Register object) { 4970 void LCodeGen::DoDeferredInstanceMigration(LCheckMaps* instr, Register object) {
4979 { 4971 {
4980 PushSafepointRegistersScope scope(this); 4972 PushSafepointRegistersScope scope(this);
4981 __ push(object); 4973 __ push(object);
4982 __ xor_(esi, esi); 4974 __ xor_(esi, esi);
4983 __ CallRuntime(Runtime::kTryMigrateInstance); 4975 __ CallRuntime(Runtime::kTryMigrateInstance);
4984 RecordSafepointWithRegisters( 4976 RecordSafepointWithRegisters(
4985 instr->pointer_map(), 1, Safepoint::kNoLazyDeopt); 4977 instr->pointer_map(), 1, Safepoint::kNoLazyDeopt);
4986 4978
4987 __ test(eax, Immediate(kSmiTagMask)); 4979 __ test(eax, Immediate(kSmiTagMask));
4988 } 4980 }
4989 DeoptimizeIf(zero, instr->environment()); 4981 DeoptimizeIf(zero, instr);
4990 } 4982 }
4991 4983
4992 4984
4993 void LCodeGen::DoCheckMaps(LCheckMaps* instr) { 4985 void LCodeGen::DoCheckMaps(LCheckMaps* instr) {
4994 class DeferredCheckMaps FINAL : public LDeferredCode { 4986 class DeferredCheckMaps FINAL : public LDeferredCode {
4995 public: 4987 public:
4996 DeferredCheckMaps(LCodeGen* codegen, 4988 DeferredCheckMaps(LCodeGen* codegen,
4997 LCheckMaps* instr, 4989 LCheckMaps* instr,
4998 Register object, 4990 Register object,
4999 const X87Stack& x87_stack) 4991 const X87Stack& x87_stack)
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
5035 Handle<Map> map = maps->at(i).handle(); 5027 Handle<Map> map = maps->at(i).handle();
5036 __ CompareMap(reg, map); 5028 __ CompareMap(reg, map);
5037 __ j(equal, &success, Label::kNear); 5029 __ j(equal, &success, Label::kNear);
5038 } 5030 }
5039 5031
5040 Handle<Map> map = maps->at(maps->size() - 1).handle(); 5032 Handle<Map> map = maps->at(maps->size() - 1).handle();
5041 __ CompareMap(reg, map); 5033 __ CompareMap(reg, map);
5042 if (instr->hydrogen()->HasMigrationTarget()) { 5034 if (instr->hydrogen()->HasMigrationTarget()) {
5043 __ j(not_equal, deferred->entry()); 5035 __ j(not_equal, deferred->entry());
5044 } else { 5036 } else {
5045 DeoptimizeIf(not_equal, instr->environment()); 5037 DeoptimizeIf(not_equal, instr);
5046 } 5038 }
5047 5039
5048 __ bind(&success); 5040 __ bind(&success);
5049 } 5041 }
5050 5042
5051 5043
5052 void LCodeGen::DoClampDToUint8(LClampDToUint8* instr) { 5044 void LCodeGen::DoClampDToUint8(LClampDToUint8* instr) {
5053 UNREACHABLE(); 5045 UNREACHABLE();
5054 } 5046 }
5055 5047
(...skipping 17 matching lines...) Expand all
5073 __ JumpIfSmi(input_reg, &is_smi); 5065 __ JumpIfSmi(input_reg, &is_smi);
5074 5066
5075 // Check for heap number 5067 // Check for heap number
5076 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), 5068 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset),
5077 factory()->heap_number_map()); 5069 factory()->heap_number_map());
5078 __ j(equal, &heap_number, Label::kNear); 5070 __ j(equal, &heap_number, Label::kNear);
5079 5071
5080 // Check for undefined. Undefined is converted to zero for clamping 5072 // Check for undefined. Undefined is converted to zero for clamping
5081 // conversions. 5073 // conversions.
5082 __ cmp(input_reg, factory()->undefined_value()); 5074 __ cmp(input_reg, factory()->undefined_value());
5083 DeoptimizeIf(not_equal, instr->environment()); 5075 DeoptimizeIf(not_equal, instr);
5084 __ jmp(&zero_result, Label::kNear); 5076 __ jmp(&zero_result, Label::kNear);
5085 5077
5086 // Heap number 5078 // Heap number
5087 __ bind(&heap_number); 5079 __ bind(&heap_number);
5088 5080
5089 // Surprisingly, all of the hand-crafted bit-manipulations below are much 5081 // Surprisingly, all of the hand-crafted bit-manipulations below are much
5090 // faster than the x86 FPU built-in instruction, especially since "banker's 5082 // faster than the x86 FPU built-in instruction, especially since "banker's
5091 // rounding" would be additionally very expensive 5083 // rounding" would be additionally very expensive
5092 5084
5093 // Get exponent word. 5085 // Get exponent word.
(...skipping 436 matching lines...) Expand 10 before | Expand all | Expand 10 after
5530 void LCodeGen::DoDeoptimize(LDeoptimize* instr) { 5522 void LCodeGen::DoDeoptimize(LDeoptimize* instr) {
5531 Deoptimizer::BailoutType type = instr->hydrogen()->type(); 5523 Deoptimizer::BailoutType type = instr->hydrogen()->type();
5532 // TODO(danno): Stubs expect all deopts to be lazy for historical reasons (the 5524 // TODO(danno): Stubs expect all deopts to be lazy for historical reasons (the
5533 // needed return address), even though the implementation of LAZY and EAGER is 5525 // needed return address), even though the implementation of LAZY and EAGER is
5534 // now identical. When LAZY is eventually completely folded into EAGER, remove 5526 // now identical. When LAZY is eventually completely folded into EAGER, remove
5535 // the special case below. 5527 // the special case below.
5536 if (info()->IsStub() && type == Deoptimizer::EAGER) { 5528 if (info()->IsStub() && type == Deoptimizer::EAGER) {
5537 type = Deoptimizer::LAZY; 5529 type = Deoptimizer::LAZY;
5538 } 5530 }
5539 Comment(";;; deoptimize: %s", instr->hydrogen()->reason()); 5531 Comment(";;; deoptimize: %s", instr->hydrogen()->reason());
5540 DeoptimizeIf(no_condition, instr->environment(), type); 5532 DeoptimizeIf(no_condition, instr, type);
5541 } 5533 }
5542 5534
5543 5535
5544 void LCodeGen::DoDummy(LDummy* instr) { 5536 void LCodeGen::DoDummy(LDummy* instr) {
5545 // Nothing to see here, move on! 5537 // Nothing to see here, move on!
5546 } 5538 }
5547 5539
5548 5540
5549 void LCodeGen::DoDummyUse(LDummyUse* instr) { 5541 void LCodeGen::DoDummyUse(LDummyUse* instr) {
5550 // Nothing to see here, move on! 5542 // Nothing to see here, move on!
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
5627 DCHECK(!environment->HasBeenRegistered()); 5619 DCHECK(!environment->HasBeenRegistered());
5628 RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt); 5620 RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt);
5629 5621
5630 GenerateOsrPrologue(); 5622 GenerateOsrPrologue();
5631 } 5623 }
5632 5624
5633 5625
5634 void LCodeGen::DoForInPrepareMap(LForInPrepareMap* instr) { 5626 void LCodeGen::DoForInPrepareMap(LForInPrepareMap* instr) {
5635 DCHECK(ToRegister(instr->context()).is(esi)); 5627 DCHECK(ToRegister(instr->context()).is(esi));
5636 __ cmp(eax, isolate()->factory()->undefined_value()); 5628 __ cmp(eax, isolate()->factory()->undefined_value());
5637 DeoptimizeIf(equal, instr->environment()); 5629 DeoptimizeIf(equal, instr);
5638 5630
5639 __ cmp(eax, isolate()->factory()->null_value()); 5631 __ cmp(eax, isolate()->factory()->null_value());
5640 DeoptimizeIf(equal, instr->environment()); 5632 DeoptimizeIf(equal, instr);
5641 5633
5642 __ test(eax, Immediate(kSmiTagMask)); 5634 __ test(eax, Immediate(kSmiTagMask));
5643 DeoptimizeIf(zero, instr->environment()); 5635 DeoptimizeIf(zero, instr);
5644 5636
5645 STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE); 5637 STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE);
5646 __ CmpObjectType(eax, LAST_JS_PROXY_TYPE, ecx); 5638 __ CmpObjectType(eax, LAST_JS_PROXY_TYPE, ecx);
5647 DeoptimizeIf(below_equal, instr->environment()); 5639 DeoptimizeIf(below_equal, instr);
5648 5640
5649 Label use_cache, call_runtime; 5641 Label use_cache, call_runtime;
5650 __ CheckEnumCache(&call_runtime); 5642 __ CheckEnumCache(&call_runtime);
5651 5643
5652 __ mov(eax, FieldOperand(eax, HeapObject::kMapOffset)); 5644 __ mov(eax, FieldOperand(eax, HeapObject::kMapOffset));
5653 __ jmp(&use_cache, Label::kNear); 5645 __ jmp(&use_cache, Label::kNear);
5654 5646
5655 // Get the set of properties to enumerate. 5647 // Get the set of properties to enumerate.
5656 __ bind(&call_runtime); 5648 __ bind(&call_runtime);
5657 __ push(eax); 5649 __ push(eax);
5658 CallRuntime(Runtime::kGetPropertyNamesFast, 1, instr); 5650 CallRuntime(Runtime::kGetPropertyNamesFast, 1, instr);
5659 5651
5660 __ cmp(FieldOperand(eax, HeapObject::kMapOffset), 5652 __ cmp(FieldOperand(eax, HeapObject::kMapOffset),
5661 isolate()->factory()->meta_map()); 5653 isolate()->factory()->meta_map());
5662 DeoptimizeIf(not_equal, instr->environment()); 5654 DeoptimizeIf(not_equal, instr);
5663 __ bind(&use_cache); 5655 __ bind(&use_cache);
5664 } 5656 }
5665 5657
5666 5658
5667 void LCodeGen::DoForInCacheArray(LForInCacheArray* instr) { 5659 void LCodeGen::DoForInCacheArray(LForInCacheArray* instr) {
5668 Register map = ToRegister(instr->map()); 5660 Register map = ToRegister(instr->map());
5669 Register result = ToRegister(instr->result()); 5661 Register result = ToRegister(instr->result());
5670 Label load_cache, done; 5662 Label load_cache, done;
5671 __ EnumLength(result, map); 5663 __ EnumLength(result, map);
5672 __ cmp(result, Immediate(Smi::FromInt(0))); 5664 __ cmp(result, Immediate(Smi::FromInt(0)));
5673 __ j(not_equal, &load_cache, Label::kNear); 5665 __ j(not_equal, &load_cache, Label::kNear);
5674 __ mov(result, isolate()->factory()->empty_fixed_array()); 5666 __ mov(result, isolate()->factory()->empty_fixed_array());
5675 __ jmp(&done, Label::kNear); 5667 __ jmp(&done, Label::kNear);
5676 5668
5677 __ bind(&load_cache); 5669 __ bind(&load_cache);
5678 __ LoadInstanceDescriptors(map, result); 5670 __ LoadInstanceDescriptors(map, result);
5679 __ mov(result, 5671 __ mov(result,
5680 FieldOperand(result, DescriptorArray::kEnumCacheOffset)); 5672 FieldOperand(result, DescriptorArray::kEnumCacheOffset));
5681 __ mov(result, 5673 __ mov(result,
5682 FieldOperand(result, FixedArray::SizeFor(instr->idx()))); 5674 FieldOperand(result, FixedArray::SizeFor(instr->idx())));
5683 __ bind(&done); 5675 __ bind(&done);
5684 __ test(result, result); 5676 __ test(result, result);
5685 DeoptimizeIf(equal, instr->environment()); 5677 DeoptimizeIf(equal, instr);
5686 } 5678 }
5687 5679
5688 5680
5689 void LCodeGen::DoCheckMapValue(LCheckMapValue* instr) { 5681 void LCodeGen::DoCheckMapValue(LCheckMapValue* instr) {
5690 Register object = ToRegister(instr->value()); 5682 Register object = ToRegister(instr->value());
5691 __ cmp(ToRegister(instr->map()), 5683 __ cmp(ToRegister(instr->map()),
5692 FieldOperand(object, HeapObject::kMapOffset)); 5684 FieldOperand(object, HeapObject::kMapOffset));
5693 DeoptimizeIf(not_equal, instr->environment()); 5685 DeoptimizeIf(not_equal, instr);
5694 } 5686 }
5695 5687
5696 5688
5697 void LCodeGen::DoDeferredLoadMutableDouble(LLoadFieldByIndex* instr, 5689 void LCodeGen::DoDeferredLoadMutableDouble(LLoadFieldByIndex* instr,
5698 Register object, 5690 Register object,
5699 Register index) { 5691 Register index) {
5700 PushSafepointRegistersScope scope(this); 5692 PushSafepointRegistersScope scope(this);
5701 __ push(object); 5693 __ push(object);
5702 __ push(index); 5694 __ push(index);
5703 __ xor_(esi, esi); 5695 __ xor_(esi, esi);
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
5778 CallRuntime(Runtime::kPushBlockContext, 2, instr); 5770 CallRuntime(Runtime::kPushBlockContext, 2, instr);
5779 RecordSafepoint(Safepoint::kNoLazyDeopt); 5771 RecordSafepoint(Safepoint::kNoLazyDeopt);
5780 } 5772 }
5781 5773
5782 5774
5783 #undef __ 5775 #undef __
5784 5776
5785 } } // namespace v8::internal 5777 } } // namespace v8::internal
5786 5778
5787 #endif // V8_TARGET_ARCH_X87 5779 #endif // V8_TARGET_ARCH_X87
OLDNEW
« no previous file with comments | « src/x87/lithium-codegen-x87.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698