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

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

Issue 597003003: X87: Made the detailed reason for deopts mandatory on x87. Unified and improved things. (Closed) Base URL: https://chromium.googlesource.com/external/v8.git@bleeding_edge
Patch Set: Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/x87/lithium-codegen-x87.h ('k') | src/x87/macro-assembler-x87.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/v8.h" 5 #include "src/v8.h"
6 6
7 #if V8_TARGET_ARCH_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 1395 matching lines...) Expand 10 before | Expand all | Expand 10 after
1406 int32_t mask = divisor < 0 ? -(divisor + 1) : (divisor - 1); 1406 int32_t mask = divisor < 0 ? -(divisor + 1) : (divisor - 1);
1407 Label dividend_is_not_negative, done; 1407 Label dividend_is_not_negative, done;
1408 if (hmod->CheckFlag(HValue::kLeftCanBeNegative)) { 1408 if (hmod->CheckFlag(HValue::kLeftCanBeNegative)) {
1409 __ test(dividend, dividend); 1409 __ test(dividend, dividend);
1410 __ j(not_sign, &dividend_is_not_negative, Label::kNear); 1410 __ j(not_sign, &dividend_is_not_negative, Label::kNear);
1411 // Note that this is correct even for kMinInt operands. 1411 // Note that this is correct even for kMinInt operands.
1412 __ neg(dividend); 1412 __ neg(dividend);
1413 __ and_(dividend, mask); 1413 __ and_(dividend, mask);
1414 __ neg(dividend); 1414 __ neg(dividend);
1415 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { 1415 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
1416 DeoptimizeIf(zero, instr); 1416 DeoptimizeIf(zero, instr, "minus zero");
1417 } 1417 }
1418 __ jmp(&done, Label::kNear); 1418 __ jmp(&done, Label::kNear);
1419 } 1419 }
1420 1420
1421 __ bind(&dividend_is_not_negative); 1421 __ bind(&dividend_is_not_negative);
1422 __ and_(dividend, mask); 1422 __ and_(dividend, mask);
1423 __ bind(&done); 1423 __ bind(&done);
1424 } 1424 }
1425 1425
1426 1426
1427 void LCodeGen::DoModByConstI(LModByConstI* instr) { 1427 void LCodeGen::DoModByConstI(LModByConstI* instr) {
1428 Register dividend = ToRegister(instr->dividend()); 1428 Register dividend = ToRegister(instr->dividend());
1429 int32_t divisor = instr->divisor(); 1429 int32_t divisor = instr->divisor();
1430 DCHECK(ToRegister(instr->result()).is(eax)); 1430 DCHECK(ToRegister(instr->result()).is(eax));
1431 1431
1432 if (divisor == 0) { 1432 if (divisor == 0) {
1433 DeoptimizeIf(no_condition, instr); 1433 DeoptimizeIf(no_condition, instr, "division by zero");
1434 return; 1434 return;
1435 } 1435 }
1436 1436
1437 __ TruncatingDiv(dividend, Abs(divisor)); 1437 __ TruncatingDiv(dividend, Abs(divisor));
1438 __ imul(edx, edx, Abs(divisor)); 1438 __ imul(edx, edx, Abs(divisor));
1439 __ mov(eax, dividend); 1439 __ mov(eax, dividend);
1440 __ sub(eax, edx); 1440 __ sub(eax, edx);
1441 1441
1442 // Check for negative zero. 1442 // Check for negative zero.
1443 HMod* hmod = instr->hydrogen(); 1443 HMod* hmod = instr->hydrogen();
1444 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { 1444 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
1445 Label remainder_not_zero; 1445 Label remainder_not_zero;
1446 __ j(not_zero, &remainder_not_zero, Label::kNear); 1446 __ j(not_zero, &remainder_not_zero, Label::kNear);
1447 __ cmp(dividend, Immediate(0)); 1447 __ cmp(dividend, Immediate(0));
1448 DeoptimizeIf(less, instr); 1448 DeoptimizeIf(less, instr, "minus zero");
1449 __ bind(&remainder_not_zero); 1449 __ bind(&remainder_not_zero);
1450 } 1450 }
1451 } 1451 }
1452 1452
1453 1453
1454 void LCodeGen::DoModI(LModI* instr) { 1454 void LCodeGen::DoModI(LModI* instr) {
1455 HMod* hmod = instr->hydrogen(); 1455 HMod* hmod = instr->hydrogen();
1456 1456
1457 Register left_reg = ToRegister(instr->left()); 1457 Register left_reg = ToRegister(instr->left());
1458 DCHECK(left_reg.is(eax)); 1458 DCHECK(left_reg.is(eax));
1459 Register right_reg = ToRegister(instr->right()); 1459 Register right_reg = ToRegister(instr->right());
1460 DCHECK(!right_reg.is(eax)); 1460 DCHECK(!right_reg.is(eax));
1461 DCHECK(!right_reg.is(edx)); 1461 DCHECK(!right_reg.is(edx));
1462 Register result_reg = ToRegister(instr->result()); 1462 Register result_reg = ToRegister(instr->result());
1463 DCHECK(result_reg.is(edx)); 1463 DCHECK(result_reg.is(edx));
1464 1464
1465 Label done; 1465 Label done;
1466 // Check for x % 0, idiv would signal a divide error. We have to 1466 // Check for x % 0, idiv would signal a divide error. We have to
1467 // deopt in this case because we can't return a NaN. 1467 // deopt in this case because we can't return a NaN.
1468 if (hmod->CheckFlag(HValue::kCanBeDivByZero)) { 1468 if (hmod->CheckFlag(HValue::kCanBeDivByZero)) {
1469 __ test(right_reg, Operand(right_reg)); 1469 __ test(right_reg, Operand(right_reg));
1470 DeoptimizeIf(zero, instr); 1470 DeoptimizeIf(zero, instr, "division by zero");
1471 } 1471 }
1472 1472
1473 // Check for kMinInt % -1, idiv would signal a divide error. We 1473 // Check for kMinInt % -1, idiv would signal a divide error. We
1474 // have to deopt if we care about -0, because we can't return that. 1474 // have to deopt if we care about -0, because we can't return that.
1475 if (hmod->CheckFlag(HValue::kCanOverflow)) { 1475 if (hmod->CheckFlag(HValue::kCanOverflow)) {
1476 Label no_overflow_possible; 1476 Label no_overflow_possible;
1477 __ cmp(left_reg, kMinInt); 1477 __ cmp(left_reg, kMinInt);
1478 __ j(not_equal, &no_overflow_possible, Label::kNear); 1478 __ j(not_equal, &no_overflow_possible, Label::kNear);
1479 __ cmp(right_reg, -1); 1479 __ cmp(right_reg, -1);
1480 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { 1480 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
1481 DeoptimizeIf(equal, instr); 1481 DeoptimizeIf(equal, instr, "minus zero");
1482 } else { 1482 } else {
1483 __ j(not_equal, &no_overflow_possible, Label::kNear); 1483 __ j(not_equal, &no_overflow_possible, Label::kNear);
1484 __ Move(result_reg, Immediate(0)); 1484 __ Move(result_reg, Immediate(0));
1485 __ jmp(&done, Label::kNear); 1485 __ jmp(&done, Label::kNear);
1486 } 1486 }
1487 __ bind(&no_overflow_possible); 1487 __ bind(&no_overflow_possible);
1488 } 1488 }
1489 1489
1490 // Sign extend dividend in eax into edx:eax. 1490 // Sign extend dividend in eax into edx:eax.
1491 __ cdq(); 1491 __ cdq();
1492 1492
1493 // If we care about -0, test if the dividend is <0 and the result is 0. 1493 // If we care about -0, test if the dividend is <0 and the result is 0.
1494 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { 1494 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
1495 Label positive_left; 1495 Label positive_left;
1496 __ test(left_reg, Operand(left_reg)); 1496 __ test(left_reg, Operand(left_reg));
1497 __ j(not_sign, &positive_left, Label::kNear); 1497 __ j(not_sign, &positive_left, Label::kNear);
1498 __ idiv(right_reg); 1498 __ idiv(right_reg);
1499 __ test(result_reg, Operand(result_reg)); 1499 __ test(result_reg, Operand(result_reg));
1500 DeoptimizeIf(zero, instr); 1500 DeoptimizeIf(zero, instr, "minus zero");
1501 __ jmp(&done, Label::kNear); 1501 __ jmp(&done, Label::kNear);
1502 __ bind(&positive_left); 1502 __ bind(&positive_left);
1503 } 1503 }
1504 __ idiv(right_reg); 1504 __ idiv(right_reg);
1505 __ bind(&done); 1505 __ bind(&done);
1506 } 1506 }
1507 1507
1508 1508
1509 void LCodeGen::DoDivByPowerOf2I(LDivByPowerOf2I* instr) { 1509 void LCodeGen::DoDivByPowerOf2I(LDivByPowerOf2I* instr) {
1510 Register dividend = ToRegister(instr->dividend()); 1510 Register dividend = ToRegister(instr->dividend());
1511 int32_t divisor = instr->divisor(); 1511 int32_t divisor = instr->divisor();
1512 Register result = ToRegister(instr->result()); 1512 Register result = ToRegister(instr->result());
1513 DCHECK(divisor == kMinInt || base::bits::IsPowerOfTwo32(Abs(divisor))); 1513 DCHECK(divisor == kMinInt || base::bits::IsPowerOfTwo32(Abs(divisor)));
1514 DCHECK(!result.is(dividend)); 1514 DCHECK(!result.is(dividend));
1515 1515
1516 // Check for (0 / -x) that will produce negative zero. 1516 // Check for (0 / -x) that will produce negative zero.
1517 HDiv* hdiv = instr->hydrogen(); 1517 HDiv* hdiv = instr->hydrogen();
1518 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) { 1518 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) {
1519 __ test(dividend, dividend); 1519 __ test(dividend, dividend);
1520 DeoptimizeIf(zero, instr); 1520 DeoptimizeIf(zero, instr, "minus zero");
1521 } 1521 }
1522 // Check for (kMinInt / -1). 1522 // Check for (kMinInt / -1).
1523 if (hdiv->CheckFlag(HValue::kCanOverflow) && divisor == -1) { 1523 if (hdiv->CheckFlag(HValue::kCanOverflow) && divisor == -1) {
1524 __ cmp(dividend, kMinInt); 1524 __ cmp(dividend, kMinInt);
1525 DeoptimizeIf(zero, instr); 1525 DeoptimizeIf(zero, instr, "overflow");
1526 } 1526 }
1527 // Deoptimize if remainder will not be 0. 1527 // Deoptimize if remainder will not be 0.
1528 if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32) && 1528 if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32) &&
1529 divisor != 1 && divisor != -1) { 1529 divisor != 1 && divisor != -1) {
1530 int32_t mask = divisor < 0 ? -(divisor + 1) : (divisor - 1); 1530 int32_t mask = divisor < 0 ? -(divisor + 1) : (divisor - 1);
1531 __ test(dividend, Immediate(mask)); 1531 __ test(dividend, Immediate(mask));
1532 DeoptimizeIf(not_zero, instr); 1532 DeoptimizeIf(not_zero, instr, "lost precision");
1533 } 1533 }
1534 __ Move(result, dividend); 1534 __ Move(result, dividend);
1535 int32_t shift = WhichPowerOf2Abs(divisor); 1535 int32_t shift = WhichPowerOf2Abs(divisor);
1536 if (shift > 0) { 1536 if (shift > 0) {
1537 // The arithmetic shift is always OK, the 'if' is an optimization only. 1537 // The arithmetic shift is always OK, the 'if' is an optimization only.
1538 if (shift > 1) __ sar(result, 31); 1538 if (shift > 1) __ sar(result, 31);
1539 __ shr(result, 32 - shift); 1539 __ shr(result, 32 - shift);
1540 __ add(result, dividend); 1540 __ add(result, dividend);
1541 __ sar(result, shift); 1541 __ sar(result, shift);
1542 } 1542 }
1543 if (divisor < 0) __ neg(result); 1543 if (divisor < 0) __ neg(result);
1544 } 1544 }
1545 1545
1546 1546
1547 void LCodeGen::DoDivByConstI(LDivByConstI* instr) { 1547 void LCodeGen::DoDivByConstI(LDivByConstI* instr) {
1548 Register dividend = ToRegister(instr->dividend()); 1548 Register dividend = ToRegister(instr->dividend());
1549 int32_t divisor = instr->divisor(); 1549 int32_t divisor = instr->divisor();
1550 DCHECK(ToRegister(instr->result()).is(edx)); 1550 DCHECK(ToRegister(instr->result()).is(edx));
1551 1551
1552 if (divisor == 0) { 1552 if (divisor == 0) {
1553 DeoptimizeIf(no_condition, instr); 1553 DeoptimizeIf(no_condition, instr, "division by zero");
1554 return; 1554 return;
1555 } 1555 }
1556 1556
1557 // Check for (0 / -x) that will produce negative zero. 1557 // Check for (0 / -x) that will produce negative zero.
1558 HDiv* hdiv = instr->hydrogen(); 1558 HDiv* hdiv = instr->hydrogen();
1559 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) { 1559 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) {
1560 __ test(dividend, dividend); 1560 __ test(dividend, dividend);
1561 DeoptimizeIf(zero, instr); 1561 DeoptimizeIf(zero, instr, "minus zero");
1562 } 1562 }
1563 1563
1564 __ TruncatingDiv(dividend, Abs(divisor)); 1564 __ TruncatingDiv(dividend, Abs(divisor));
1565 if (divisor < 0) __ neg(edx); 1565 if (divisor < 0) __ neg(edx);
1566 1566
1567 if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32)) { 1567 if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32)) {
1568 __ mov(eax, edx); 1568 __ mov(eax, edx);
1569 __ imul(eax, eax, divisor); 1569 __ imul(eax, eax, divisor);
1570 __ sub(eax, dividend); 1570 __ sub(eax, dividend);
1571 DeoptimizeIf(not_equal, instr); 1571 DeoptimizeIf(not_equal, instr, "lost precision");
1572 } 1572 }
1573 } 1573 }
1574 1574
1575 1575
1576 // TODO(svenpanne) Refactor this to avoid code duplication with DoFlooringDivI. 1576 // TODO(svenpanne) Refactor this to avoid code duplication with DoFlooringDivI.
1577 void LCodeGen::DoDivI(LDivI* instr) { 1577 void LCodeGen::DoDivI(LDivI* instr) {
1578 HBinaryOperation* hdiv = instr->hydrogen(); 1578 HBinaryOperation* hdiv = instr->hydrogen();
1579 Register dividend = ToRegister(instr->dividend()); 1579 Register dividend = ToRegister(instr->dividend());
1580 Register divisor = ToRegister(instr->divisor()); 1580 Register divisor = ToRegister(instr->divisor());
1581 Register remainder = ToRegister(instr->temp()); 1581 Register remainder = ToRegister(instr->temp());
1582 DCHECK(dividend.is(eax)); 1582 DCHECK(dividend.is(eax));
1583 DCHECK(remainder.is(edx)); 1583 DCHECK(remainder.is(edx));
1584 DCHECK(ToRegister(instr->result()).is(eax)); 1584 DCHECK(ToRegister(instr->result()).is(eax));
1585 DCHECK(!divisor.is(eax)); 1585 DCHECK(!divisor.is(eax));
1586 DCHECK(!divisor.is(edx)); 1586 DCHECK(!divisor.is(edx));
1587 1587
1588 // Check for x / 0. 1588 // Check for x / 0.
1589 if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) { 1589 if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) {
1590 __ test(divisor, divisor); 1590 __ test(divisor, divisor);
1591 DeoptimizeIf(zero, instr); 1591 DeoptimizeIf(zero, instr, "division by zero");
1592 } 1592 }
1593 1593
1594 // Check for (0 / -x) that will produce negative zero. 1594 // Check for (0 / -x) that will produce negative zero.
1595 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) { 1595 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) {
1596 Label dividend_not_zero; 1596 Label dividend_not_zero;
1597 __ test(dividend, dividend); 1597 __ test(dividend, dividend);
1598 __ j(not_zero, &dividend_not_zero, Label::kNear); 1598 __ j(not_zero, &dividend_not_zero, Label::kNear);
1599 __ test(divisor, divisor); 1599 __ test(divisor, divisor);
1600 DeoptimizeIf(sign, instr); 1600 DeoptimizeIf(sign, instr, "minus zero");
1601 __ bind(&dividend_not_zero); 1601 __ bind(&dividend_not_zero);
1602 } 1602 }
1603 1603
1604 // Check for (kMinInt / -1). 1604 // Check for (kMinInt / -1).
1605 if (hdiv->CheckFlag(HValue::kCanOverflow)) { 1605 if (hdiv->CheckFlag(HValue::kCanOverflow)) {
1606 Label dividend_not_min_int; 1606 Label dividend_not_min_int;
1607 __ cmp(dividend, kMinInt); 1607 __ cmp(dividend, kMinInt);
1608 __ j(not_zero, &dividend_not_min_int, Label::kNear); 1608 __ j(not_zero, &dividend_not_min_int, Label::kNear);
1609 __ cmp(divisor, -1); 1609 __ cmp(divisor, -1);
1610 DeoptimizeIf(zero, instr); 1610 DeoptimizeIf(zero, instr, "overflow");
1611 __ bind(&dividend_not_min_int); 1611 __ bind(&dividend_not_min_int);
1612 } 1612 }
1613 1613
1614 // Sign extend to edx (= remainder). 1614 // Sign extend to edx (= remainder).
1615 __ cdq(); 1615 __ cdq();
1616 __ idiv(divisor); 1616 __ idiv(divisor);
1617 1617
1618 if (!hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) { 1618 if (!hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) {
1619 // Deoptimize if remainder is not 0. 1619 // Deoptimize if remainder is not 0.
1620 __ test(remainder, remainder); 1620 __ test(remainder, remainder);
1621 DeoptimizeIf(not_zero, instr); 1621 DeoptimizeIf(not_zero, instr, "lost precision");
1622 } 1622 }
1623 } 1623 }
1624 1624
1625 1625
1626 void LCodeGen::DoFlooringDivByPowerOf2I(LFlooringDivByPowerOf2I* instr) { 1626 void LCodeGen::DoFlooringDivByPowerOf2I(LFlooringDivByPowerOf2I* instr) {
1627 Register dividend = ToRegister(instr->dividend()); 1627 Register dividend = ToRegister(instr->dividend());
1628 int32_t divisor = instr->divisor(); 1628 int32_t divisor = instr->divisor();
1629 DCHECK(dividend.is(ToRegister(instr->result()))); 1629 DCHECK(dividend.is(ToRegister(instr->result())));
1630 1630
1631 // If the divisor is positive, things are easy: There can be no deopts and we 1631 // If the divisor is positive, things are easy: There can be no deopts and we
1632 // can simply do an arithmetic right shift. 1632 // can simply do an arithmetic right shift.
1633 if (divisor == 1) return; 1633 if (divisor == 1) return;
1634 int32_t shift = WhichPowerOf2Abs(divisor); 1634 int32_t shift = WhichPowerOf2Abs(divisor);
1635 if (divisor > 1) { 1635 if (divisor > 1) {
1636 __ sar(dividend, shift); 1636 __ sar(dividend, shift);
1637 return; 1637 return;
1638 } 1638 }
1639 1639
1640 // If the divisor is negative, we have to negate and handle edge cases. 1640 // If the divisor is negative, we have to negate and handle edge cases.
1641 __ neg(dividend); 1641 __ neg(dividend);
1642 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 1642 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
1643 DeoptimizeIf(zero, instr); 1643 DeoptimizeIf(zero, instr, "minus zero");
1644 } 1644 }
1645 1645
1646 // Dividing by -1 is basically negation, unless we overflow. 1646 // Dividing by -1 is basically negation, unless we overflow.
1647 if (divisor == -1) { 1647 if (divisor == -1) {
1648 if (instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) { 1648 if (instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) {
1649 DeoptimizeIf(overflow, instr); 1649 DeoptimizeIf(overflow, instr, "overflow");
1650 } 1650 }
1651 return; 1651 return;
1652 } 1652 }
1653 1653
1654 // If the negation could not overflow, simply shifting is OK. 1654 // If the negation could not overflow, simply shifting is OK.
1655 if (!instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) { 1655 if (!instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) {
1656 __ sar(dividend, shift); 1656 __ sar(dividend, shift);
1657 return; 1657 return;
1658 } 1658 }
1659 1659
1660 Label not_kmin_int, done; 1660 Label not_kmin_int, done;
1661 __ j(no_overflow, &not_kmin_int, Label::kNear); 1661 __ j(no_overflow, &not_kmin_int, Label::kNear);
1662 __ mov(dividend, Immediate(kMinInt / divisor)); 1662 __ mov(dividend, Immediate(kMinInt / divisor));
1663 __ jmp(&done, Label::kNear); 1663 __ jmp(&done, Label::kNear);
1664 __ bind(&not_kmin_int); 1664 __ bind(&not_kmin_int);
1665 __ sar(dividend, shift); 1665 __ sar(dividend, shift);
1666 __ bind(&done); 1666 __ bind(&done);
1667 } 1667 }
1668 1668
1669 1669
1670 void LCodeGen::DoFlooringDivByConstI(LFlooringDivByConstI* instr) { 1670 void LCodeGen::DoFlooringDivByConstI(LFlooringDivByConstI* instr) {
1671 Register dividend = ToRegister(instr->dividend()); 1671 Register dividend = ToRegister(instr->dividend());
1672 int32_t divisor = instr->divisor(); 1672 int32_t divisor = instr->divisor();
1673 DCHECK(ToRegister(instr->result()).is(edx)); 1673 DCHECK(ToRegister(instr->result()).is(edx));
1674 1674
1675 if (divisor == 0) { 1675 if (divisor == 0) {
1676 DeoptimizeIf(no_condition, instr); 1676 DeoptimizeIf(no_condition, instr, "division by zero");
1677 return; 1677 return;
1678 } 1678 }
1679 1679
1680 // Check for (0 / -x) that will produce negative zero. 1680 // Check for (0 / -x) that will produce negative zero.
1681 HMathFloorOfDiv* hdiv = instr->hydrogen(); 1681 HMathFloorOfDiv* hdiv = instr->hydrogen();
1682 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) { 1682 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) {
1683 __ test(dividend, dividend); 1683 __ test(dividend, dividend);
1684 DeoptimizeIf(zero, instr); 1684 DeoptimizeIf(zero, instr, "minus zero");
1685 } 1685 }
1686 1686
1687 // Easy case: We need no dynamic check for the dividend and the flooring 1687 // Easy case: We need no dynamic check for the dividend and the flooring
1688 // division is the same as the truncating division. 1688 // division is the same as the truncating division.
1689 if ((divisor > 0 && !hdiv->CheckFlag(HValue::kLeftCanBeNegative)) || 1689 if ((divisor > 0 && !hdiv->CheckFlag(HValue::kLeftCanBeNegative)) ||
1690 (divisor < 0 && !hdiv->CheckFlag(HValue::kLeftCanBePositive))) { 1690 (divisor < 0 && !hdiv->CheckFlag(HValue::kLeftCanBePositive))) {
1691 __ TruncatingDiv(dividend, Abs(divisor)); 1691 __ TruncatingDiv(dividend, Abs(divisor));
1692 if (divisor < 0) __ neg(edx); 1692 if (divisor < 0) __ neg(edx);
1693 return; 1693 return;
1694 } 1694 }
(...skipping 26 matching lines...) Expand all
1721 Register result = ToRegister(instr->result()); 1721 Register result = ToRegister(instr->result());
1722 DCHECK(dividend.is(eax)); 1722 DCHECK(dividend.is(eax));
1723 DCHECK(remainder.is(edx)); 1723 DCHECK(remainder.is(edx));
1724 DCHECK(result.is(eax)); 1724 DCHECK(result.is(eax));
1725 DCHECK(!divisor.is(eax)); 1725 DCHECK(!divisor.is(eax));
1726 DCHECK(!divisor.is(edx)); 1726 DCHECK(!divisor.is(edx));
1727 1727
1728 // Check for x / 0. 1728 // Check for x / 0.
1729 if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) { 1729 if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) {
1730 __ test(divisor, divisor); 1730 __ test(divisor, divisor);
1731 DeoptimizeIf(zero, instr); 1731 DeoptimizeIf(zero, instr, "division by zero");
1732 } 1732 }
1733 1733
1734 // Check for (0 / -x) that will produce negative zero. 1734 // Check for (0 / -x) that will produce negative zero.
1735 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) { 1735 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) {
1736 Label dividend_not_zero; 1736 Label dividend_not_zero;
1737 __ test(dividend, dividend); 1737 __ test(dividend, dividend);
1738 __ j(not_zero, &dividend_not_zero, Label::kNear); 1738 __ j(not_zero, &dividend_not_zero, Label::kNear);
1739 __ test(divisor, divisor); 1739 __ test(divisor, divisor);
1740 DeoptimizeIf(sign, instr); 1740 DeoptimizeIf(sign, instr, "minus zero");
1741 __ bind(&dividend_not_zero); 1741 __ bind(&dividend_not_zero);
1742 } 1742 }
1743 1743
1744 // Check for (kMinInt / -1). 1744 // Check for (kMinInt / -1).
1745 if (hdiv->CheckFlag(HValue::kCanOverflow)) { 1745 if (hdiv->CheckFlag(HValue::kCanOverflow)) {
1746 Label dividend_not_min_int; 1746 Label dividend_not_min_int;
1747 __ cmp(dividend, kMinInt); 1747 __ cmp(dividend, kMinInt);
1748 __ j(not_zero, &dividend_not_min_int, Label::kNear); 1748 __ j(not_zero, &dividend_not_min_int, Label::kNear);
1749 __ cmp(divisor, -1); 1749 __ cmp(divisor, -1);
1750 DeoptimizeIf(zero, instr); 1750 DeoptimizeIf(zero, instr, "overflow");
1751 __ bind(&dividend_not_min_int); 1751 __ bind(&dividend_not_min_int);
1752 } 1752 }
1753 1753
1754 // Sign extend to edx (= remainder). 1754 // Sign extend to edx (= remainder).
1755 __ cdq(); 1755 __ cdq();
1756 __ idiv(divisor); 1756 __ idiv(divisor);
1757 1757
1758 Label done; 1758 Label done;
1759 __ test(remainder, remainder); 1759 __ test(remainder, remainder);
1760 __ j(zero, &done, Label::kNear); 1760 __ j(zero, &done, Label::kNear);
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
1818 __ imul(left, left, constant); 1818 __ imul(left, left, constant);
1819 } 1819 }
1820 } else { 1820 } else {
1821 if (instr->hydrogen()->representation().IsSmi()) { 1821 if (instr->hydrogen()->representation().IsSmi()) {
1822 __ SmiUntag(left); 1822 __ SmiUntag(left);
1823 } 1823 }
1824 __ imul(left, ToOperand(right)); 1824 __ imul(left, ToOperand(right));
1825 } 1825 }
1826 1826
1827 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { 1827 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) {
1828 DeoptimizeIf(overflow, instr); 1828 DeoptimizeIf(overflow, instr, "overflow");
1829 } 1829 }
1830 1830
1831 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 1831 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
1832 // Bail out if the result is supposed to be negative zero. 1832 // Bail out if the result is supposed to be negative zero.
1833 Label done; 1833 Label done;
1834 __ test(left, Operand(left)); 1834 __ test(left, Operand(left));
1835 __ j(not_zero, &done); 1835 __ j(not_zero, &done);
1836 if (right->IsConstantOperand()) { 1836 if (right->IsConstantOperand()) {
1837 if (ToInteger32(LConstantOperand::cast(right)) < 0) { 1837 if (ToInteger32(LConstantOperand::cast(right)) < 0) {
1838 DeoptimizeIf(no_condition, instr); 1838 DeoptimizeIf(no_condition, instr, "minus zero");
1839 } else if (ToInteger32(LConstantOperand::cast(right)) == 0) { 1839 } else if (ToInteger32(LConstantOperand::cast(right)) == 0) {
1840 __ cmp(ToRegister(instr->temp()), Immediate(0)); 1840 __ cmp(ToRegister(instr->temp()), Immediate(0));
1841 DeoptimizeIf(less, instr); 1841 DeoptimizeIf(less, instr, "minus zero");
1842 } 1842 }
1843 } else { 1843 } else {
1844 // Test the non-zero operand for negative sign. 1844 // Test the non-zero operand for negative sign.
1845 __ or_(ToRegister(instr->temp()), ToOperand(right)); 1845 __ or_(ToRegister(instr->temp()), ToOperand(right));
1846 DeoptimizeIf(sign, instr); 1846 DeoptimizeIf(sign, instr, "minus zero");
1847 } 1847 }
1848 __ bind(&done); 1848 __ bind(&done);
1849 } 1849 }
1850 } 1850 }
1851 1851
1852 1852
1853 void LCodeGen::DoBitI(LBitI* instr) { 1853 void LCodeGen::DoBitI(LBitI* instr) {
1854 LOperand* left = instr->left(); 1854 LOperand* left = instr->left();
1855 LOperand* right = instr->right(); 1855 LOperand* right = instr->right();
1856 DCHECK(left->Equals(instr->result())); 1856 DCHECK(left->Equals(instr->result()));
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
1909 case Token::ROR: 1909 case Token::ROR:
1910 __ ror_cl(ToRegister(left)); 1910 __ ror_cl(ToRegister(left));
1911 break; 1911 break;
1912 case Token::SAR: 1912 case Token::SAR:
1913 __ sar_cl(ToRegister(left)); 1913 __ sar_cl(ToRegister(left));
1914 break; 1914 break;
1915 case Token::SHR: 1915 case Token::SHR:
1916 __ shr_cl(ToRegister(left)); 1916 __ shr_cl(ToRegister(left));
1917 if (instr->can_deopt()) { 1917 if (instr->can_deopt()) {
1918 __ test(ToRegister(left), ToRegister(left)); 1918 __ test(ToRegister(left), ToRegister(left));
1919 DeoptimizeIf(sign, instr); 1919 DeoptimizeIf(sign, instr, "negative value");
1920 } 1920 }
1921 break; 1921 break;
1922 case Token::SHL: 1922 case Token::SHL:
1923 __ shl_cl(ToRegister(left)); 1923 __ shl_cl(ToRegister(left));
1924 break; 1924 break;
1925 default: 1925 default:
1926 UNREACHABLE(); 1926 UNREACHABLE();
1927 break; 1927 break;
1928 } 1928 }
1929 } else { 1929 } else {
1930 int value = ToInteger32(LConstantOperand::cast(right)); 1930 int value = ToInteger32(LConstantOperand::cast(right));
1931 uint8_t shift_count = static_cast<uint8_t>(value & 0x1F); 1931 uint8_t shift_count = static_cast<uint8_t>(value & 0x1F);
1932 switch (instr->op()) { 1932 switch (instr->op()) {
1933 case Token::ROR: 1933 case Token::ROR:
1934 if (shift_count == 0 && instr->can_deopt()) { 1934 if (shift_count == 0 && instr->can_deopt()) {
1935 __ test(ToRegister(left), ToRegister(left)); 1935 __ test(ToRegister(left), ToRegister(left));
1936 DeoptimizeIf(sign, instr); 1936 DeoptimizeIf(sign, instr, "negative value");
1937 } else { 1937 } else {
1938 __ ror(ToRegister(left), shift_count); 1938 __ ror(ToRegister(left), shift_count);
1939 } 1939 }
1940 break; 1940 break;
1941 case Token::SAR: 1941 case Token::SAR:
1942 if (shift_count != 0) { 1942 if (shift_count != 0) {
1943 __ sar(ToRegister(left), shift_count); 1943 __ sar(ToRegister(left), shift_count);
1944 } 1944 }
1945 break; 1945 break;
1946 case Token::SHR: 1946 case Token::SHR:
1947 if (shift_count != 0) { 1947 if (shift_count != 0) {
1948 __ shr(ToRegister(left), shift_count); 1948 __ shr(ToRegister(left), shift_count);
1949 } else if (instr->can_deopt()) { 1949 } else if (instr->can_deopt()) {
1950 __ test(ToRegister(left), ToRegister(left)); 1950 __ test(ToRegister(left), ToRegister(left));
1951 DeoptimizeIf(sign, instr); 1951 DeoptimizeIf(sign, instr, "negative value");
1952 } 1952 }
1953 break; 1953 break;
1954 case Token::SHL: 1954 case Token::SHL:
1955 if (shift_count != 0) { 1955 if (shift_count != 0) {
1956 if (instr->hydrogen_value()->representation().IsSmi() && 1956 if (instr->hydrogen_value()->representation().IsSmi() &&
1957 instr->can_deopt()) { 1957 instr->can_deopt()) {
1958 if (shift_count != 1) { 1958 if (shift_count != 1) {
1959 __ shl(ToRegister(left), shift_count - 1); 1959 __ shl(ToRegister(left), shift_count - 1);
1960 } 1960 }
1961 __ SmiTag(ToRegister(left)); 1961 __ SmiTag(ToRegister(left));
1962 DeoptimizeIf(overflow, instr); 1962 DeoptimizeIf(overflow, instr, "overflow");
1963 } else { 1963 } else {
1964 __ shl(ToRegister(left), shift_count); 1964 __ shl(ToRegister(left), shift_count);
1965 } 1965 }
1966 } 1966 }
1967 break; 1967 break;
1968 default: 1968 default:
1969 UNREACHABLE(); 1969 UNREACHABLE();
1970 break; 1970 break;
1971 } 1971 }
1972 } 1972 }
1973 } 1973 }
1974 1974
1975 1975
1976 void LCodeGen::DoSubI(LSubI* instr) { 1976 void LCodeGen::DoSubI(LSubI* instr) {
1977 LOperand* left = instr->left(); 1977 LOperand* left = instr->left();
1978 LOperand* right = instr->right(); 1978 LOperand* right = instr->right();
1979 DCHECK(left->Equals(instr->result())); 1979 DCHECK(left->Equals(instr->result()));
1980 1980
1981 if (right->IsConstantOperand()) { 1981 if (right->IsConstantOperand()) {
1982 __ sub(ToOperand(left), 1982 __ sub(ToOperand(left),
1983 ToImmediate(right, instr->hydrogen()->representation())); 1983 ToImmediate(right, instr->hydrogen()->representation()));
1984 } else { 1984 } else {
1985 __ sub(ToRegister(left), ToOperand(right)); 1985 __ sub(ToRegister(left), ToOperand(right));
1986 } 1986 }
1987 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { 1987 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) {
1988 DeoptimizeIf(overflow, instr); 1988 DeoptimizeIf(overflow, instr, "overflow");
1989 } 1989 }
1990 } 1990 }
1991 1991
1992 1992
1993 void LCodeGen::DoConstantI(LConstantI* instr) { 1993 void LCodeGen::DoConstantI(LConstantI* instr) {
1994 __ Move(ToRegister(instr->result()), Immediate(instr->value())); 1994 __ Move(ToRegister(instr->result()), Immediate(instr->value()));
1995 } 1995 }
1996 1996
1997 1997
1998 void LCodeGen::DoConstantS(LConstantS* instr) { 1998 void LCodeGen::DoConstantS(LConstantS* instr) {
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
2038 void LCodeGen::DoDateField(LDateField* instr) { 2038 void LCodeGen::DoDateField(LDateField* instr) {
2039 Register object = ToRegister(instr->date()); 2039 Register object = ToRegister(instr->date());
2040 Register result = ToRegister(instr->result()); 2040 Register result = ToRegister(instr->result());
2041 Register scratch = ToRegister(instr->temp()); 2041 Register scratch = ToRegister(instr->temp());
2042 Smi* index = instr->index(); 2042 Smi* index = instr->index();
2043 Label runtime, done; 2043 Label runtime, done;
2044 DCHECK(object.is(result)); 2044 DCHECK(object.is(result));
2045 DCHECK(object.is(eax)); 2045 DCHECK(object.is(eax));
2046 2046
2047 __ test(object, Immediate(kSmiTagMask)); 2047 __ test(object, Immediate(kSmiTagMask));
2048 DeoptimizeIf(zero, instr); 2048 DeoptimizeIf(zero, instr, "Smi");
2049 __ CmpObjectType(object, JS_DATE_TYPE, scratch); 2049 __ CmpObjectType(object, JS_DATE_TYPE, scratch);
2050 DeoptimizeIf(not_equal, instr); 2050 DeoptimizeIf(not_equal, instr, "not a date object");
2051 2051
2052 if (index->value() == 0) { 2052 if (index->value() == 0) {
2053 __ mov(result, FieldOperand(object, JSDate::kValueOffset)); 2053 __ mov(result, FieldOperand(object, JSDate::kValueOffset));
2054 } else { 2054 } else {
2055 if (index->value() < JSDate::kFirstUncachedField) { 2055 if (index->value() < JSDate::kFirstUncachedField) {
2056 ExternalReference stamp = ExternalReference::date_cache_stamp(isolate()); 2056 ExternalReference stamp = ExternalReference::date_cache_stamp(isolate());
2057 __ mov(scratch, Operand::StaticVariable(stamp)); 2057 __ mov(scratch, Operand::StaticVariable(stamp));
2058 __ cmp(scratch, FieldOperand(object, JSDate::kCacheStampOffset)); 2058 __ cmp(scratch, FieldOperand(object, JSDate::kCacheStampOffset));
2059 __ j(not_equal, &runtime, Label::kNear); 2059 __ j(not_equal, &runtime, Label::kNear);
2060 __ mov(result, FieldOperand(object, JSDate::kValueOffset + 2060 __ mov(result, FieldOperand(object, JSDate::kValueOffset +
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
2170 __ lea(ToRegister(instr->result()), address); 2170 __ lea(ToRegister(instr->result()), address);
2171 } 2171 }
2172 } else { 2172 } else {
2173 if (right->IsConstantOperand()) { 2173 if (right->IsConstantOperand()) {
2174 __ add(ToOperand(left), 2174 __ add(ToOperand(left),
2175 ToImmediate(right, instr->hydrogen()->representation())); 2175 ToImmediate(right, instr->hydrogen()->representation()));
2176 } else { 2176 } else {
2177 __ add(ToRegister(left), ToOperand(right)); 2177 __ add(ToRegister(left), ToOperand(right));
2178 } 2178 }
2179 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { 2179 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) {
2180 DeoptimizeIf(overflow, instr); 2180 DeoptimizeIf(overflow, instr, "overflow");
2181 } 2181 }
2182 } 2182 }
2183 } 2183 }
2184 2184
2185 2185
2186 void LCodeGen::DoMathMinMax(LMathMinMax* instr) { 2186 void LCodeGen::DoMathMinMax(LMathMinMax* instr) {
2187 LOperand* left = instr->left(); 2187 LOperand* left = instr->left();
2188 LOperand* right = instr->right(); 2188 LOperand* right = instr->right();
2189 DCHECK(left->Equals(instr->result())); 2189 DCHECK(left->Equals(instr->result()));
2190 HMathMinMax::Operation operation = instr->hydrogen()->operation(); 2190 HMathMinMax::Operation operation = instr->hydrogen()->operation();
(...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after
2415 } 2415 }
2416 2416
2417 if (expected.Contains(ToBooleanStub::SMI)) { 2417 if (expected.Contains(ToBooleanStub::SMI)) {
2418 // Smis: 0 -> false, all other -> true. 2418 // Smis: 0 -> false, all other -> true.
2419 __ test(reg, Operand(reg)); 2419 __ test(reg, Operand(reg));
2420 __ j(equal, instr->FalseLabel(chunk_)); 2420 __ j(equal, instr->FalseLabel(chunk_));
2421 __ JumpIfSmi(reg, instr->TrueLabel(chunk_)); 2421 __ JumpIfSmi(reg, instr->TrueLabel(chunk_));
2422 } else if (expected.NeedsMap()) { 2422 } else if (expected.NeedsMap()) {
2423 // If we need a map later and have a Smi -> deopt. 2423 // If we need a map later and have a Smi -> deopt.
2424 __ test(reg, Immediate(kSmiTagMask)); 2424 __ test(reg, Immediate(kSmiTagMask));
2425 DeoptimizeIf(zero, instr); 2425 DeoptimizeIf(zero, instr, "Smi");
2426 } 2426 }
2427 2427
2428 Register map = no_reg; // Keep the compiler happy. 2428 Register map = no_reg; // Keep the compiler happy.
2429 if (expected.NeedsMap()) { 2429 if (expected.NeedsMap()) {
2430 map = ToRegister(instr->temp()); 2430 map = ToRegister(instr->temp());
2431 DCHECK(!map.is(reg)); 2431 DCHECK(!map.is(reg));
2432 __ mov(map, FieldOperand(reg, HeapObject::kMapOffset)); 2432 __ mov(map, FieldOperand(reg, HeapObject::kMapOffset));
2433 2433
2434 if (expected.CanBeUndetectable()) { 2434 if (expected.CanBeUndetectable()) {
2435 // Undetectable -> false. 2435 // Undetectable -> false.
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
2472 __ fld_d(FieldOperand(reg, HeapNumber::kValueOffset)); 2472 __ fld_d(FieldOperand(reg, HeapNumber::kValueOffset));
2473 __ FCmp(); 2473 __ FCmp();
2474 __ j(zero, instr->FalseLabel(chunk_)); 2474 __ j(zero, instr->FalseLabel(chunk_));
2475 __ jmp(instr->TrueLabel(chunk_)); 2475 __ jmp(instr->TrueLabel(chunk_));
2476 __ bind(&not_heap_number); 2476 __ bind(&not_heap_number);
2477 } 2477 }
2478 2478
2479 if (!expected.IsGeneric()) { 2479 if (!expected.IsGeneric()) {
2480 // We've seen something for the first time -> deopt. 2480 // We've seen something for the first time -> deopt.
2481 // This can only happen if we are not generic already. 2481 // This can only happen if we are not generic already.
2482 DeoptimizeIf(no_condition, instr); 2482 DeoptimizeIf(no_condition, instr, "unexpected object");
2483 } 2483 }
2484 } 2484 }
2485 } 2485 }
2486 } 2486 }
2487 2487
2488 2488
2489 void LCodeGen::EmitGoto(int block) { 2489 void LCodeGen::EmitGoto(int block) {
2490 if (!IsNextEmittedBlock(block)) { 2490 if (!IsNextEmittedBlock(block)) {
2491 __ jmp(chunk_->GetAssemblyLabel(LookupDestination(block))); 2491 __ jmp(chunk_->GetAssemblyLabel(LookupDestination(block)));
2492 } 2492 }
(...skipping 618 matching lines...) Expand 10 before | Expand all | Expand 10 after
3111 info()->AddNoFrameRange(no_frame_start, masm_->pc_offset()); 3111 info()->AddNoFrameRange(no_frame_start, masm_->pc_offset());
3112 } 3112 }
3113 } 3113 }
3114 3114
3115 3115
3116 void LCodeGen::DoLoadGlobalCell(LLoadGlobalCell* instr) { 3116 void LCodeGen::DoLoadGlobalCell(LLoadGlobalCell* instr) {
3117 Register result = ToRegister(instr->result()); 3117 Register result = ToRegister(instr->result());
3118 __ mov(result, Operand::ForCell(instr->hydrogen()->cell().handle())); 3118 __ mov(result, Operand::ForCell(instr->hydrogen()->cell().handle()));
3119 if (instr->hydrogen()->RequiresHoleCheck()) { 3119 if (instr->hydrogen()->RequiresHoleCheck()) {
3120 __ cmp(result, factory()->the_hole_value()); 3120 __ cmp(result, factory()->the_hole_value());
3121 DeoptimizeIf(equal, instr); 3121 DeoptimizeIf(equal, instr, "hole");
3122 } 3122 }
3123 } 3123 }
3124 3124
3125 3125
3126 template <class T> 3126 template <class T>
3127 void LCodeGen::EmitVectorLoadICRegisters(T* instr) { 3127 void LCodeGen::EmitVectorLoadICRegisters(T* instr) {
3128 DCHECK(FLAG_vector_ics); 3128 DCHECK(FLAG_vector_ics);
3129 Register vector = ToRegister(instr->temp_vector()); 3129 Register vector = ToRegister(instr->temp_vector());
3130 DCHECK(vector.is(VectorLoadICDescriptor::VectorRegister())); 3130 DCHECK(vector.is(VectorLoadICDescriptor::VectorRegister()));
3131 __ mov(vector, instr->hydrogen()->feedback_vector()); 3131 __ mov(vector, instr->hydrogen()->feedback_vector());
(...skipping 23 matching lines...) Expand all
3155 void LCodeGen::DoStoreGlobalCell(LStoreGlobalCell* instr) { 3155 void LCodeGen::DoStoreGlobalCell(LStoreGlobalCell* instr) {
3156 Register value = ToRegister(instr->value()); 3156 Register value = ToRegister(instr->value());
3157 Handle<PropertyCell> cell_handle = instr->hydrogen()->cell().handle(); 3157 Handle<PropertyCell> cell_handle = instr->hydrogen()->cell().handle();
3158 3158
3159 // If the cell we are storing to contains the hole it could have 3159 // If the cell we are storing to contains the hole it could have
3160 // been deleted from the property dictionary. In that case, we need 3160 // been deleted from the property dictionary. In that case, we need
3161 // to update the property details in the property dictionary to mark 3161 // to update the property details in the property dictionary to mark
3162 // it as no longer deleted. We deoptimize in that case. 3162 // it as no longer deleted. We deoptimize in that case.
3163 if (instr->hydrogen()->RequiresHoleCheck()) { 3163 if (instr->hydrogen()->RequiresHoleCheck()) {
3164 __ cmp(Operand::ForCell(cell_handle), factory()->the_hole_value()); 3164 __ cmp(Operand::ForCell(cell_handle), factory()->the_hole_value());
3165 DeoptimizeIf(equal, instr); 3165 DeoptimizeIf(equal, instr, "hole");
3166 } 3166 }
3167 3167
3168 // Store the value. 3168 // Store the value.
3169 __ mov(Operand::ForCell(cell_handle), value); 3169 __ mov(Operand::ForCell(cell_handle), value);
3170 // Cells are always rescanned, so no write barrier here. 3170 // Cells are always rescanned, so no write barrier here.
3171 } 3171 }
3172 3172
3173 3173
3174 void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) { 3174 void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) {
3175 Register context = ToRegister(instr->context()); 3175 Register context = ToRegister(instr->context());
3176 Register result = ToRegister(instr->result()); 3176 Register result = ToRegister(instr->result());
3177 __ mov(result, ContextOperand(context, instr->slot_index())); 3177 __ mov(result, ContextOperand(context, instr->slot_index()));
3178 3178
3179 if (instr->hydrogen()->RequiresHoleCheck()) { 3179 if (instr->hydrogen()->RequiresHoleCheck()) {
3180 __ cmp(result, factory()->the_hole_value()); 3180 __ cmp(result, factory()->the_hole_value());
3181 if (instr->hydrogen()->DeoptimizesOnHole()) { 3181 if (instr->hydrogen()->DeoptimizesOnHole()) {
3182 DeoptimizeIf(equal, instr); 3182 DeoptimizeIf(equal, instr, "hole");
3183 } else { 3183 } else {
3184 Label is_not_hole; 3184 Label is_not_hole;
3185 __ j(not_equal, &is_not_hole, Label::kNear); 3185 __ j(not_equal, &is_not_hole, Label::kNear);
3186 __ mov(result, factory()->undefined_value()); 3186 __ mov(result, factory()->undefined_value());
3187 __ bind(&is_not_hole); 3187 __ bind(&is_not_hole);
3188 } 3188 }
3189 } 3189 }
3190 } 3190 }
3191 3191
3192 3192
3193 void LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) { 3193 void LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) {
3194 Register context = ToRegister(instr->context()); 3194 Register context = ToRegister(instr->context());
3195 Register value = ToRegister(instr->value()); 3195 Register value = ToRegister(instr->value());
3196 3196
3197 Label skip_assignment; 3197 Label skip_assignment;
3198 3198
3199 Operand target = ContextOperand(context, instr->slot_index()); 3199 Operand target = ContextOperand(context, instr->slot_index());
3200 if (instr->hydrogen()->RequiresHoleCheck()) { 3200 if (instr->hydrogen()->RequiresHoleCheck()) {
3201 __ cmp(target, factory()->the_hole_value()); 3201 __ cmp(target, factory()->the_hole_value());
3202 if (instr->hydrogen()->DeoptimizesOnHole()) { 3202 if (instr->hydrogen()->DeoptimizesOnHole()) {
3203 DeoptimizeIf(equal, instr); 3203 DeoptimizeIf(equal, instr, "hole");
3204 } else { 3204 } else {
3205 __ j(not_equal, &skip_assignment, Label::kNear); 3205 __ j(not_equal, &skip_assignment, Label::kNear);
3206 } 3206 }
3207 } 3207 }
3208 3208
3209 __ mov(target, value); 3209 __ mov(target, value);
3210 if (instr->hydrogen()->NeedsWriteBarrier()) { 3210 if (instr->hydrogen()->NeedsWriteBarrier()) {
3211 SmiCheck check_needed = 3211 SmiCheck check_needed =
3212 instr->hydrogen()->value()->type().IsHeapObject() 3212 instr->hydrogen()->value()->type().IsHeapObject()
3213 ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; 3213 ? OMIT_SMI_CHECK : INLINE_SMI_CHECK;
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
3286 Register function = ToRegister(instr->function()); 3286 Register function = ToRegister(instr->function());
3287 Register temp = ToRegister(instr->temp()); 3287 Register temp = ToRegister(instr->temp());
3288 Register result = ToRegister(instr->result()); 3288 Register result = ToRegister(instr->result());
3289 3289
3290 // Get the prototype or initial map from the function. 3290 // Get the prototype or initial map from the function.
3291 __ mov(result, 3291 __ mov(result,
3292 FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset)); 3292 FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset));
3293 3293
3294 // Check that the function has a prototype or an initial map. 3294 // Check that the function has a prototype or an initial map.
3295 __ cmp(Operand(result), Immediate(factory()->the_hole_value())); 3295 __ cmp(Operand(result), Immediate(factory()->the_hole_value()));
3296 DeoptimizeIf(equal, instr); 3296 DeoptimizeIf(equal, instr, "hole");
3297 3297
3298 // If the function does not have an initial map, we're done. 3298 // If the function does not have an initial map, we're done.
3299 Label done; 3299 Label done;
3300 __ CmpObjectType(result, MAP_TYPE, temp); 3300 __ CmpObjectType(result, MAP_TYPE, temp);
3301 __ j(not_equal, &done, Label::kNear); 3301 __ j(not_equal, &done, Label::kNear);
3302 3302
3303 // Get the prototype from the initial map. 3303 // Get the prototype from the initial map.
3304 __ mov(result, FieldOperand(result, Map::kPrototypeOffset)); 3304 __ mov(result, FieldOperand(result, Map::kPrototypeOffset));
3305 3305
3306 // All done. 3306 // All done.
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
3377 break; 3377 break;
3378 case EXTERNAL_INT32_ELEMENTS: 3378 case EXTERNAL_INT32_ELEMENTS:
3379 case INT32_ELEMENTS: 3379 case INT32_ELEMENTS:
3380 __ mov(result, operand); 3380 __ mov(result, operand);
3381 break; 3381 break;
3382 case EXTERNAL_UINT32_ELEMENTS: 3382 case EXTERNAL_UINT32_ELEMENTS:
3383 case UINT32_ELEMENTS: 3383 case UINT32_ELEMENTS:
3384 __ mov(result, operand); 3384 __ mov(result, operand);
3385 if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) { 3385 if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) {
3386 __ test(result, Operand(result)); 3386 __ test(result, Operand(result));
3387 DeoptimizeIf(negative, instr); 3387 DeoptimizeIf(negative, instr, "negative value");
3388 } 3388 }
3389 break; 3389 break;
3390 case EXTERNAL_FLOAT32_ELEMENTS: 3390 case EXTERNAL_FLOAT32_ELEMENTS:
3391 case EXTERNAL_FLOAT64_ELEMENTS: 3391 case EXTERNAL_FLOAT64_ELEMENTS:
3392 case FLOAT32_ELEMENTS: 3392 case FLOAT32_ELEMENTS:
3393 case FLOAT64_ELEMENTS: 3393 case FLOAT64_ELEMENTS:
3394 case FAST_SMI_ELEMENTS: 3394 case FAST_SMI_ELEMENTS:
3395 case FAST_ELEMENTS: 3395 case FAST_ELEMENTS:
3396 case FAST_DOUBLE_ELEMENTS: 3396 case FAST_DOUBLE_ELEMENTS:
3397 case FAST_HOLEY_SMI_ELEMENTS: 3397 case FAST_HOLEY_SMI_ELEMENTS:
3398 case FAST_HOLEY_ELEMENTS: 3398 case FAST_HOLEY_ELEMENTS:
3399 case FAST_HOLEY_DOUBLE_ELEMENTS: 3399 case FAST_HOLEY_DOUBLE_ELEMENTS:
3400 case DICTIONARY_ELEMENTS: 3400 case DICTIONARY_ELEMENTS:
3401 case SLOPPY_ARGUMENTS_ELEMENTS: 3401 case SLOPPY_ARGUMENTS_ELEMENTS:
3402 UNREACHABLE(); 3402 UNREACHABLE();
3403 break; 3403 break;
3404 } 3404 }
3405 } 3405 }
3406 } 3406 }
3407 3407
3408 3408
3409 void LCodeGen::DoLoadKeyedFixedDoubleArray(LLoadKeyed* instr) { 3409 void LCodeGen::DoLoadKeyedFixedDoubleArray(LLoadKeyed* instr) {
3410 if (instr->hydrogen()->RequiresHoleCheck()) { 3410 if (instr->hydrogen()->RequiresHoleCheck()) {
3411 Operand hole_check_operand = BuildFastArrayOperand( 3411 Operand hole_check_operand = BuildFastArrayOperand(
3412 instr->elements(), instr->key(), 3412 instr->elements(), instr->key(),
3413 instr->hydrogen()->key()->representation(), 3413 instr->hydrogen()->key()->representation(),
3414 FAST_DOUBLE_ELEMENTS, 3414 FAST_DOUBLE_ELEMENTS,
3415 instr->base_offset() + sizeof(kHoleNanLower32)); 3415 instr->base_offset() + sizeof(kHoleNanLower32));
3416 __ cmp(hole_check_operand, Immediate(kHoleNanUpper32)); 3416 __ cmp(hole_check_operand, Immediate(kHoleNanUpper32));
3417 DeoptimizeIf(equal, instr); 3417 DeoptimizeIf(equal, instr, "hole");
3418 } 3418 }
3419 3419
3420 Operand double_load_operand = BuildFastArrayOperand( 3420 Operand double_load_operand = BuildFastArrayOperand(
3421 instr->elements(), 3421 instr->elements(),
3422 instr->key(), 3422 instr->key(),
3423 instr->hydrogen()->key()->representation(), 3423 instr->hydrogen()->key()->representation(),
3424 FAST_DOUBLE_ELEMENTS, 3424 FAST_DOUBLE_ELEMENTS,
3425 instr->base_offset()); 3425 instr->base_offset());
3426 X87Mov(ToX87Register(instr->result()), double_load_operand); 3426 X87Mov(ToX87Register(instr->result()), double_load_operand);
3427 } 3427 }
3428 3428
3429 3429
3430 void LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) { 3430 void LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) {
3431 Register result = ToRegister(instr->result()); 3431 Register result = ToRegister(instr->result());
3432 3432
3433 // Load the result. 3433 // Load the result.
3434 __ mov(result, 3434 __ mov(result,
3435 BuildFastArrayOperand(instr->elements(), instr->key(), 3435 BuildFastArrayOperand(instr->elements(), instr->key(),
3436 instr->hydrogen()->key()->representation(), 3436 instr->hydrogen()->key()->representation(),
3437 FAST_ELEMENTS, instr->base_offset())); 3437 FAST_ELEMENTS, instr->base_offset()));
3438 3438
3439 // Check for the hole value. 3439 // Check for the hole value.
3440 if (instr->hydrogen()->RequiresHoleCheck()) { 3440 if (instr->hydrogen()->RequiresHoleCheck()) {
3441 if (IsFastSmiElementsKind(instr->hydrogen()->elements_kind())) { 3441 if (IsFastSmiElementsKind(instr->hydrogen()->elements_kind())) {
3442 __ test(result, Immediate(kSmiTagMask)); 3442 __ test(result, Immediate(kSmiTagMask));
3443 DeoptimizeIf(not_equal, instr); 3443 DeoptimizeIf(not_equal, instr, "not a Smi");
3444 } else { 3444 } else {
3445 __ cmp(result, factory()->the_hole_value()); 3445 __ cmp(result, factory()->the_hole_value());
3446 DeoptimizeIf(equal, instr); 3446 DeoptimizeIf(equal, instr, "hole");
3447 } 3447 }
3448 } 3448 }
3449 } 3449 }
3450 3450
3451 3451
3452 void LCodeGen::DoLoadKeyed(LLoadKeyed* instr) { 3452 void LCodeGen::DoLoadKeyed(LLoadKeyed* instr) {
3453 if (instr->is_typed_elements()) { 3453 if (instr->is_typed_elements()) {
3454 DoLoadKeyedExternalArray(instr); 3454 DoLoadKeyedExternalArray(instr);
3455 } else if (instr->hydrogen()->representation().IsDouble()) { 3455 } else if (instr->hydrogen()->representation().IsDouble()) {
3456 DoLoadKeyedFixedDoubleArray(instr); 3456 DoLoadKeyedFixedDoubleArray(instr);
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after
3583 } 3583 }
3584 3584
3585 // Normal function. Replace undefined or null with global receiver. 3585 // Normal function. Replace undefined or null with global receiver.
3586 __ cmp(receiver, factory()->null_value()); 3586 __ cmp(receiver, factory()->null_value());
3587 __ j(equal, &global_object, Label::kNear); 3587 __ j(equal, &global_object, Label::kNear);
3588 __ cmp(receiver, factory()->undefined_value()); 3588 __ cmp(receiver, factory()->undefined_value());
3589 __ j(equal, &global_object, Label::kNear); 3589 __ j(equal, &global_object, Label::kNear);
3590 3590
3591 // The receiver should be a JS object. 3591 // The receiver should be a JS object.
3592 __ test(receiver, Immediate(kSmiTagMask)); 3592 __ test(receiver, Immediate(kSmiTagMask));
3593 DeoptimizeIf(equal, instr); 3593 DeoptimizeIf(equal, instr, "Smi");
3594 __ CmpObjectType(receiver, FIRST_SPEC_OBJECT_TYPE, scratch); 3594 __ CmpObjectType(receiver, FIRST_SPEC_OBJECT_TYPE, scratch);
3595 DeoptimizeIf(below, instr); 3595 DeoptimizeIf(below, instr, "not a JavaScript object");
3596 3596
3597 __ jmp(&receiver_ok, Label::kNear); 3597 __ jmp(&receiver_ok, Label::kNear);
3598 __ bind(&global_object); 3598 __ bind(&global_object);
3599 __ mov(receiver, FieldOperand(function, JSFunction::kContextOffset)); 3599 __ mov(receiver, FieldOperand(function, JSFunction::kContextOffset));
3600 const int global_offset = Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX); 3600 const int global_offset = Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX);
3601 __ mov(receiver, Operand(receiver, global_offset)); 3601 __ mov(receiver, Operand(receiver, global_offset));
3602 const int proxy_offset = GlobalObject::kGlobalProxyOffset; 3602 const int proxy_offset = GlobalObject::kGlobalProxyOffset;
3603 __ mov(receiver, FieldOperand(receiver, proxy_offset)); 3603 __ mov(receiver, FieldOperand(receiver, proxy_offset));
3604 __ bind(&receiver_ok); 3604 __ bind(&receiver_ok);
3605 } 3605 }
3606 3606
3607 3607
3608 void LCodeGen::DoApplyArguments(LApplyArguments* instr) { 3608 void LCodeGen::DoApplyArguments(LApplyArguments* instr) {
3609 Register receiver = ToRegister(instr->receiver()); 3609 Register receiver = ToRegister(instr->receiver());
3610 Register function = ToRegister(instr->function()); 3610 Register function = ToRegister(instr->function());
3611 Register length = ToRegister(instr->length()); 3611 Register length = ToRegister(instr->length());
3612 Register elements = ToRegister(instr->elements()); 3612 Register elements = ToRegister(instr->elements());
3613 DCHECK(receiver.is(eax)); // Used for parameter count. 3613 DCHECK(receiver.is(eax)); // Used for parameter count.
3614 DCHECK(function.is(edi)); // Required by InvokeFunction. 3614 DCHECK(function.is(edi)); // Required by InvokeFunction.
3615 DCHECK(ToRegister(instr->result()).is(eax)); 3615 DCHECK(ToRegister(instr->result()).is(eax));
3616 3616
3617 // Copy the arguments to this function possibly from the 3617 // Copy the arguments to this function possibly from the
3618 // adaptor frame below it. 3618 // adaptor frame below it.
3619 const uint32_t kArgumentsLimit = 1 * KB; 3619 const uint32_t kArgumentsLimit = 1 * KB;
3620 __ cmp(length, kArgumentsLimit); 3620 __ cmp(length, kArgumentsLimit);
3621 DeoptimizeIf(above, instr); 3621 DeoptimizeIf(above, instr, "too many arguments");
3622 3622
3623 __ push(receiver); 3623 __ push(receiver);
3624 __ mov(receiver, length); 3624 __ mov(receiver, length);
3625 3625
3626 // Loop through the arguments pushing them onto the execution 3626 // Loop through the arguments pushing them onto the execution
3627 // stack. 3627 // stack.
3628 Label invoke, loop; 3628 Label invoke, loop;
3629 // length is a small non-negative integer, due to the test above. 3629 // length is a small non-negative integer, due to the test above.
3630 __ test(length, Operand(length)); 3630 __ test(length, Operand(length));
3631 __ j(zero, &invoke, Label::kNear); 3631 __ j(zero, &invoke, Label::kNear);
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after
3804 } 3804 }
3805 3805
3806 RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT); 3806 RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT);
3807 } 3807 }
3808 3808
3809 3809
3810 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LMathAbs* instr) { 3810 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LMathAbs* instr) {
3811 Register input_reg = ToRegister(instr->value()); 3811 Register input_reg = ToRegister(instr->value());
3812 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), 3812 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset),
3813 factory()->heap_number_map()); 3813 factory()->heap_number_map());
3814 DeoptimizeIf(not_equal, instr); 3814 DeoptimizeIf(not_equal, instr, "not a heap number");
3815 3815
3816 Label slow, allocated, done; 3816 Label slow, allocated, done;
3817 Register tmp = input_reg.is(eax) ? ecx : eax; 3817 Register tmp = input_reg.is(eax) ? ecx : eax;
3818 Register tmp2 = tmp.is(ecx) ? edx : input_reg.is(ecx) ? edx : ecx; 3818 Register tmp2 = tmp.is(ecx) ? edx : input_reg.is(ecx) ? edx : ecx;
3819 3819
3820 // Preserve the value of all registers. 3820 // Preserve the value of all registers.
3821 PushSafepointRegistersScope scope(this); 3821 PushSafepointRegistersScope scope(this);
3822 3822
3823 __ mov(tmp, FieldOperand(input_reg, HeapNumber::kExponentOffset)); 3823 __ mov(tmp, FieldOperand(input_reg, HeapNumber::kExponentOffset));
3824 // Check the sign of the argument. If the argument is positive, just 3824 // Check the sign of the argument. If the argument is positive, just
(...skipping 26 matching lines...) Expand all
3851 __ bind(&done); 3851 __ bind(&done);
3852 } 3852 }
3853 3853
3854 3854
3855 void LCodeGen::EmitIntegerMathAbs(LMathAbs* instr) { 3855 void LCodeGen::EmitIntegerMathAbs(LMathAbs* instr) {
3856 Register input_reg = ToRegister(instr->value()); 3856 Register input_reg = ToRegister(instr->value());
3857 __ test(input_reg, Operand(input_reg)); 3857 __ test(input_reg, Operand(input_reg));
3858 Label is_positive; 3858 Label is_positive;
3859 __ j(not_sign, &is_positive, Label::kNear); 3859 __ j(not_sign, &is_positive, Label::kNear);
3860 __ neg(input_reg); // Sets flags. 3860 __ neg(input_reg); // Sets flags.
3861 DeoptimizeIf(negative, instr); 3861 DeoptimizeIf(negative, instr, "overflow");
3862 __ bind(&is_positive); 3862 __ bind(&is_positive);
3863 } 3863 }
3864 3864
3865 3865
3866 void LCodeGen::DoMathAbs(LMathAbs* instr) { 3866 void LCodeGen::DoMathAbs(LMathAbs* instr) {
3867 // Class for deferred case. 3867 // Class for deferred case.
3868 class DeferredMathAbsTaggedHeapNumber FINAL : public LDeferredCode { 3868 class DeferredMathAbsTaggedHeapNumber FINAL : public LDeferredCode {
3869 public: 3869 public:
3870 DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen, 3870 DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen,
3871 LMathAbs* instr, 3871 LMathAbs* instr,
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
3903 void LCodeGen::DoMathFloor(LMathFloor* instr) { 3903 void LCodeGen::DoMathFloor(LMathFloor* instr) {
3904 Register output_reg = ToRegister(instr->result()); 3904 Register output_reg = ToRegister(instr->result());
3905 X87Register input_reg = ToX87Register(instr->value()); 3905 X87Register input_reg = ToX87Register(instr->value());
3906 X87Fxch(input_reg); 3906 X87Fxch(input_reg);
3907 3907
3908 Label not_minus_zero, done; 3908 Label not_minus_zero, done;
3909 // Deoptimize on unordered. 3909 // Deoptimize on unordered.
3910 __ fldz(); 3910 __ fldz();
3911 __ fld(1); 3911 __ fld(1);
3912 __ FCmp(); 3912 __ FCmp();
3913 DeoptimizeIf(parity_even, instr); 3913 DeoptimizeIf(parity_even, instr, "NaN");
3914 __ j(below, &not_minus_zero, Label::kNear); 3914 __ j(below, &not_minus_zero, Label::kNear);
3915 3915
3916 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 3916 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
3917 // Check for negative zero. 3917 // Check for negative zero.
3918 __ j(not_equal, &not_minus_zero, Label::kNear); 3918 __ j(not_equal, &not_minus_zero, Label::kNear);
3919 // +- 0.0. 3919 // +- 0.0.
3920 __ fld(0); 3920 __ fld(0);
3921 __ FXamSign(); 3921 __ FXamSign();
3922 DeoptimizeIf(not_zero, instr); 3922 DeoptimizeIf(not_zero, instr, "minus zero");
3923 __ Move(output_reg, Immediate(0)); 3923 __ Move(output_reg, Immediate(0));
3924 __ jmp(&done, Label::kFar); 3924 __ jmp(&done, Label::kFar);
3925 } 3925 }
3926 3926
3927 // Positive input. 3927 // Positive input.
3928 // rc=01B, round down. 3928 // rc=01B, round down.
3929 __ bind(&not_minus_zero); 3929 __ bind(&not_minus_zero);
3930 __ fnclex(); 3930 __ fnclex();
3931 __ X87SetRC(0x0400); 3931 __ X87SetRC(0x0400);
3932 __ sub(esp, Immediate(kPointerSize)); 3932 __ sub(esp, Immediate(kPointerSize));
3933 __ fist_s(Operand(esp, 0)); 3933 __ fist_s(Operand(esp, 0));
3934 __ pop(output_reg); 3934 __ pop(output_reg);
3935 __ X87CheckIA(); 3935 __ X87CheckIA();
3936 DeoptimizeIf(equal, instr); 3936 DeoptimizeIf(equal, instr, "overflow");
3937 __ fnclex(); 3937 __ fnclex();
3938 __ X87SetRC(0x0000); 3938 __ X87SetRC(0x0000);
3939 __ bind(&done); 3939 __ bind(&done);
3940 } 3940 }
3941 3941
3942 3942
3943 void LCodeGen::DoMathRound(LMathRound* instr) { 3943 void LCodeGen::DoMathRound(LMathRound* instr) {
3944 X87Register input_reg = ToX87Register(instr->value()); 3944 X87Register input_reg = ToX87Register(instr->value());
3945 Register result = ToRegister(instr->result()); 3945 Register result = ToRegister(instr->result());
3946 X87Fxch(input_reg); 3946 X87Fxch(input_reg);
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after
4073 __ push(exponent); 4073 __ push(exponent);
4074 __ fild_s(MemOperand(esp, 0)); 4074 __ fild_s(MemOperand(esp, 0));
4075 __ pop(exponent); 4075 __ pop(exponent);
4076 } else if (exponent_type.IsTagged()) { 4076 } else if (exponent_type.IsTagged()) {
4077 Register exponent = ToRegister(instr->right()); 4077 Register exponent = ToRegister(instr->right());
4078 Register temp = exponent.is(ecx) ? eax : ecx; 4078 Register temp = exponent.is(ecx) ? eax : ecx;
4079 Label no_deopt, done; 4079 Label no_deopt, done;
4080 X87LoadForUsage(base); 4080 X87LoadForUsage(base);
4081 __ JumpIfSmi(exponent, &no_deopt); 4081 __ JumpIfSmi(exponent, &no_deopt);
4082 __ CmpObjectType(exponent, HEAP_NUMBER_TYPE, temp); 4082 __ CmpObjectType(exponent, HEAP_NUMBER_TYPE, temp);
4083 DeoptimizeIf(not_equal, instr); 4083 DeoptimizeIf(not_equal, instr, "not a heap number");
4084 // Heap number(double) 4084 // Heap number(double)
4085 __ fld_d(FieldOperand(exponent, HeapNumber::kValueOffset)); 4085 __ fld_d(FieldOperand(exponent, HeapNumber::kValueOffset));
4086 __ jmp(&done); 4086 __ jmp(&done);
4087 // SMI 4087 // SMI
4088 __ bind(&no_deopt); 4088 __ bind(&no_deopt);
4089 __ SmiUntag(exponent); 4089 __ SmiUntag(exponent);
4090 __ push(exponent); 4090 __ push(exponent);
4091 __ fild_s(MemOperand(esp, 0)); 4091 __ fild_s(MemOperand(esp, 0));
4092 __ pop(exponent); 4092 __ pop(exponent);
4093 __ bind(&done); 4093 __ bind(&done);
(...skipping 382 matching lines...) Expand 10 before | Expand all | Expand 10 after
4476 instr->hydrogen()->index()->representation())); 4476 instr->hydrogen()->index()->representation()));
4477 } else { 4477 } else {
4478 __ cmp(ToRegister(instr->index()), ToOperand(instr->length())); 4478 __ cmp(ToRegister(instr->index()), ToOperand(instr->length()));
4479 } 4479 }
4480 if (FLAG_debug_code && instr->hydrogen()->skip_check()) { 4480 if (FLAG_debug_code && instr->hydrogen()->skip_check()) {
4481 Label done; 4481 Label done;
4482 __ j(NegateCondition(cc), &done, Label::kNear); 4482 __ j(NegateCondition(cc), &done, Label::kNear);
4483 __ int3(); 4483 __ int3();
4484 __ bind(&done); 4484 __ bind(&done);
4485 } else { 4485 } else {
4486 DeoptimizeIf(cc, instr); 4486 DeoptimizeIf(cc, instr, "out of bounds");
4487 } 4487 }
4488 } 4488 }
4489 4489
4490 4490
4491 void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) { 4491 void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) {
4492 ElementsKind elements_kind = instr->elements_kind(); 4492 ElementsKind elements_kind = instr->elements_kind();
4493 LOperand* key = instr->key(); 4493 LOperand* key = instr->key();
4494 if (!key->IsConstantOperand() && 4494 if (!key->IsConstantOperand() &&
4495 ExternalArrayOpRequiresTemp(instr->hydrogen()->key()->representation(), 4495 ExternalArrayOpRequiresTemp(instr->hydrogen()->key()->representation(),
4496 elements_kind)) { 4496 elements_kind)) {
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after
4669 CodeFactory::KeyedStoreIC(isolate(), instr->strict_mode()).code(); 4669 CodeFactory::KeyedStoreIC(isolate(), instr->strict_mode()).code();
4670 CallCode(ic, RelocInfo::CODE_TARGET, instr); 4670 CallCode(ic, RelocInfo::CODE_TARGET, instr);
4671 } 4671 }
4672 4672
4673 4673
4674 void LCodeGen::DoTrapAllocationMemento(LTrapAllocationMemento* instr) { 4674 void LCodeGen::DoTrapAllocationMemento(LTrapAllocationMemento* instr) {
4675 Register object = ToRegister(instr->object()); 4675 Register object = ToRegister(instr->object());
4676 Register temp = ToRegister(instr->temp()); 4676 Register temp = ToRegister(instr->temp());
4677 Label no_memento_found; 4677 Label no_memento_found;
4678 __ TestJSArrayForAllocationMemento(object, temp, &no_memento_found); 4678 __ TestJSArrayForAllocationMemento(object, temp, &no_memento_found);
4679 DeoptimizeIf(equal, instr); 4679 DeoptimizeIf(equal, instr, "memento found");
4680 __ bind(&no_memento_found); 4680 __ bind(&no_memento_found);
4681 } 4681 }
4682 4682
4683 4683
4684 void LCodeGen::DoTransitionElementsKind(LTransitionElementsKind* instr) { 4684 void LCodeGen::DoTransitionElementsKind(LTransitionElementsKind* instr) {
4685 Register object_reg = ToRegister(instr->object()); 4685 Register object_reg = ToRegister(instr->object());
4686 4686
4687 Handle<Map> from_map = instr->original_map(); 4687 Handle<Map> from_map = instr->original_map();
4688 Handle<Map> to_map = instr->transitioned_map(); 4688 Handle<Map> to_map = instr->transitioned_map();
4689 ElementsKind from_kind = instr->from_kind(); 4689 ElementsKind from_kind = instr->from_kind();
(...skipping 350 matching lines...) Expand 10 before | Expand all | Expand 10 after
5040 __ StoreToSafepointRegisterSlot(reg, eax); 5040 __ StoreToSafepointRegisterSlot(reg, eax);
5041 } 5041 }
5042 5042
5043 5043
5044 void LCodeGen::DoSmiTag(LSmiTag* instr) { 5044 void LCodeGen::DoSmiTag(LSmiTag* instr) {
5045 HChange* hchange = instr->hydrogen(); 5045 HChange* hchange = instr->hydrogen();
5046 Register input = ToRegister(instr->value()); 5046 Register input = ToRegister(instr->value());
5047 if (hchange->CheckFlag(HValue::kCanOverflow) && 5047 if (hchange->CheckFlag(HValue::kCanOverflow) &&
5048 hchange->value()->CheckFlag(HValue::kUint32)) { 5048 hchange->value()->CheckFlag(HValue::kUint32)) {
5049 __ test(input, Immediate(0xc0000000)); 5049 __ test(input, Immediate(0xc0000000));
5050 DeoptimizeIf(not_zero, instr); 5050 DeoptimizeIf(not_zero, instr, "overflow");
5051 } 5051 }
5052 __ SmiTag(input); 5052 __ SmiTag(input);
5053 if (hchange->CheckFlag(HValue::kCanOverflow) && 5053 if (hchange->CheckFlag(HValue::kCanOverflow) &&
5054 !hchange->value()->CheckFlag(HValue::kUint32)) { 5054 !hchange->value()->CheckFlag(HValue::kUint32)) {
5055 DeoptimizeIf(overflow, instr); 5055 DeoptimizeIf(overflow, instr, "overflow");
5056 } 5056 }
5057 } 5057 }
5058 5058
5059 5059
5060 void LCodeGen::DoSmiUntag(LSmiUntag* instr) { 5060 void LCodeGen::DoSmiUntag(LSmiUntag* instr) {
5061 LOperand* input = instr->value(); 5061 LOperand* input = instr->value();
5062 Register result = ToRegister(input); 5062 Register result = ToRegister(input);
5063 DCHECK(input->IsRegister() && input->Equals(instr->result())); 5063 DCHECK(input->IsRegister() && input->Equals(instr->result()));
5064 if (instr->needs_check()) { 5064 if (instr->needs_check()) {
5065 __ test(result, Immediate(kSmiTagMask)); 5065 __ test(result, Immediate(kSmiTagMask));
5066 DeoptimizeIf(not_zero, instr); 5066 DeoptimizeIf(not_zero, instr, "not a Smi");
5067 } else { 5067 } else {
5068 __ AssertSmi(result); 5068 __ AssertSmi(result);
5069 } 5069 }
5070 __ SmiUntag(result); 5070 __ SmiUntag(result);
5071 } 5071 }
5072 5072
5073 5073
5074 void LCodeGen::EmitNumberUntagDNoSSE2(LNumberUntagD* instr, Register input_reg, 5074 void LCodeGen::EmitNumberUntagDNoSSE2(LNumberUntagD* instr, Register input_reg,
5075 Register temp_reg, X87Register res_reg, 5075 Register temp_reg, X87Register res_reg,
5076 NumberUntagDMode mode) { 5076 NumberUntagDMode mode) {
5077 bool can_convert_undefined_to_nan = 5077 bool can_convert_undefined_to_nan =
5078 instr->hydrogen()->can_convert_undefined_to_nan(); 5078 instr->hydrogen()->can_convert_undefined_to_nan();
5079 bool deoptimize_on_minus_zero = instr->hydrogen()->deoptimize_on_minus_zero(); 5079 bool deoptimize_on_minus_zero = instr->hydrogen()->deoptimize_on_minus_zero();
5080 5080
5081 Label load_smi, done; 5081 Label load_smi, done;
5082 5082
5083 X87PrepareToWrite(res_reg); 5083 X87PrepareToWrite(res_reg);
5084 if (mode == NUMBER_CANDIDATE_IS_ANY_TAGGED) { 5084 if (mode == NUMBER_CANDIDATE_IS_ANY_TAGGED) {
5085 // Smi check. 5085 // Smi check.
5086 __ JumpIfSmi(input_reg, &load_smi); 5086 __ JumpIfSmi(input_reg, &load_smi);
5087 5087
5088 // Heap number map check. 5088 // Heap number map check.
5089 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), 5089 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset),
5090 factory()->heap_number_map()); 5090 factory()->heap_number_map());
5091 if (!can_convert_undefined_to_nan) { 5091 if (!can_convert_undefined_to_nan) {
5092 DeoptimizeIf(not_equal, instr); 5092 DeoptimizeIf(not_equal, instr, "not a heap number");
5093 } else { 5093 } else {
5094 Label heap_number, convert; 5094 Label heap_number, convert;
5095 __ j(equal, &heap_number); 5095 __ j(equal, &heap_number);
5096 5096
5097 // Convert undefined (or hole) to NaN. 5097 // Convert undefined (or hole) to NaN.
5098 __ cmp(input_reg, factory()->undefined_value()); 5098 __ cmp(input_reg, factory()->undefined_value());
5099 DeoptimizeIf(not_equal, instr); 5099 DeoptimizeIf(not_equal, instr, "not a heap number/undefined");
5100 5100
5101 __ bind(&convert); 5101 __ bind(&convert);
5102 ExternalReference nan = 5102 ExternalReference nan =
5103 ExternalReference::address_of_canonical_non_hole_nan(); 5103 ExternalReference::address_of_canonical_non_hole_nan();
5104 __ fld_d(Operand::StaticVariable(nan)); 5104 __ fld_d(Operand::StaticVariable(nan));
5105 __ jmp(&done, Label::kNear); 5105 __ jmp(&done, Label::kNear);
5106 5106
5107 __ bind(&heap_number); 5107 __ bind(&heap_number);
5108 } 5108 }
5109 // Heap number to x87 conversion. 5109 // Heap number to x87 conversion.
5110 __ fld_d(FieldOperand(input_reg, HeapNumber::kValueOffset)); 5110 __ fld_d(FieldOperand(input_reg, HeapNumber::kValueOffset));
5111 if (deoptimize_on_minus_zero) { 5111 if (deoptimize_on_minus_zero) {
5112 __ fldz(); 5112 __ fldz();
5113 __ FCmp(); 5113 __ FCmp();
5114 __ fld_d(FieldOperand(input_reg, HeapNumber::kValueOffset)); 5114 __ fld_d(FieldOperand(input_reg, HeapNumber::kValueOffset));
5115 __ j(not_zero, &done, Label::kNear); 5115 __ j(not_zero, &done, Label::kNear);
5116 5116
5117 // Use general purpose registers to check if we have -0.0 5117 // Use general purpose registers to check if we have -0.0
5118 __ mov(temp_reg, FieldOperand(input_reg, HeapNumber::kExponentOffset)); 5118 __ mov(temp_reg, FieldOperand(input_reg, HeapNumber::kExponentOffset));
5119 __ test(temp_reg, Immediate(HeapNumber::kSignMask)); 5119 __ test(temp_reg, Immediate(HeapNumber::kSignMask));
5120 __ j(zero, &done, Label::kNear); 5120 __ j(zero, &done, Label::kNear);
5121 5121
5122 // Pop FPU stack before deoptimizing. 5122 // Pop FPU stack before deoptimizing.
5123 __ fstp(0); 5123 __ fstp(0);
5124 DeoptimizeIf(not_zero, instr); 5124 DeoptimizeIf(not_zero, instr, "minus zero");
5125 } 5125 }
5126 __ jmp(&done, Label::kNear); 5126 __ jmp(&done, Label::kNear);
5127 } else { 5127 } else {
5128 DCHECK(mode == NUMBER_CANDIDATE_IS_SMI); 5128 DCHECK(mode == NUMBER_CANDIDATE_IS_SMI);
5129 } 5129 }
5130 5130
5131 __ bind(&load_smi); 5131 __ bind(&load_smi);
5132 // Clobbering a temp is faster than re-tagging the 5132 // Clobbering a temp is faster than re-tagging the
5133 // input register since we avoid dependencies. 5133 // input register since we avoid dependencies.
5134 __ mov(temp_reg, input_reg); 5134 __ mov(temp_reg, input_reg);
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
5167 __ jmp(done); 5167 __ jmp(done);
5168 5168
5169 __ bind(&check_bools); 5169 __ bind(&check_bools);
5170 __ cmp(input_reg, factory()->true_value()); 5170 __ cmp(input_reg, factory()->true_value());
5171 __ j(not_equal, &check_false, Label::kNear); 5171 __ j(not_equal, &check_false, Label::kNear);
5172 __ Move(input_reg, Immediate(1)); 5172 __ Move(input_reg, Immediate(1));
5173 __ jmp(done); 5173 __ jmp(done);
5174 5174
5175 __ bind(&check_false); 5175 __ bind(&check_false);
5176 __ cmp(input_reg, factory()->false_value()); 5176 __ cmp(input_reg, factory()->false_value());
5177 DeoptimizeIf(not_equal, instr, "cannot truncate"); 5177 DeoptimizeIf(not_equal, instr, "not a heap number/undefined/true/false");
5178 __ Move(input_reg, Immediate(0)); 5178 __ Move(input_reg, Immediate(0));
5179 } else { 5179 } else {
5180 // TODO(olivf) Converting a number on the fpu is actually quite slow. We 5180 // TODO(olivf) Converting a number on the fpu is actually quite slow. We
5181 // should first try a fast conversion and then bailout to this slow case. 5181 // should first try a fast conversion and then bailout to this slow case.
5182 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), 5182 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset),
5183 isolate()->factory()->heap_number_map()); 5183 isolate()->factory()->heap_number_map());
5184 DeoptimizeIf(not_equal, instr, "not a heap number"); 5184 DeoptimizeIf(not_equal, instr, "not a heap number");
5185 5185
5186 __ sub(esp, Immediate(kPointerSize)); 5186 __ sub(esp, Immediate(kPointerSize));
5187 __ fld_d(FieldOperand(input_reg, HeapNumber::kValueOffset)); 5187 __ fld_d(FieldOperand(input_reg, HeapNumber::kValueOffset));
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
5292 DCHECK(input->IsDoubleRegister()); 5292 DCHECK(input->IsDoubleRegister());
5293 LOperand* result = instr->result(); 5293 LOperand* result = instr->result();
5294 DCHECK(result->IsRegister()); 5294 DCHECK(result->IsRegister());
5295 Register result_reg = ToRegister(result); 5295 Register result_reg = ToRegister(result);
5296 5296
5297 if (instr->truncating()) { 5297 if (instr->truncating()) {
5298 X87Register input_reg = ToX87Register(input); 5298 X87Register input_reg = ToX87Register(input);
5299 X87Fxch(input_reg); 5299 X87Fxch(input_reg);
5300 __ TruncateX87TOSToI(result_reg); 5300 __ TruncateX87TOSToI(result_reg);
5301 } else { 5301 } else {
5302 Label bailout, done; 5302 Label lost_precision, is_nan, minus_zero, done;
5303 X87Register input_reg = ToX87Register(input); 5303 X87Register input_reg = ToX87Register(input);
5304 X87Fxch(input_reg); 5304 X87Fxch(input_reg);
5305 __ X87TOSToI(result_reg, instr->hydrogen()->GetMinusZeroMode(), 5305 __ X87TOSToI(result_reg, instr->hydrogen()->GetMinusZeroMode(),
5306 &bailout, Label::kNear); 5306 &lost_precision, &is_nan, &minus_zero, Label::kNear);
5307 __ jmp(&done, Label::kNear); 5307 __ jmp(&done, Label::kNear);
5308 __ bind(&bailout); 5308 __ bind(&lost_precision);
5309 DeoptimizeIf(no_condition, instr); 5309 DeoptimizeIf(no_condition, instr, "lost precision");
5310 __ bind(&is_nan);
5311 DeoptimizeIf(no_condition, instr, "NaN");
5312 __ bind(&minus_zero);
5313 DeoptimizeIf(no_condition, instr, "minus zero");
5310 __ bind(&done); 5314 __ bind(&done);
5311 } 5315 }
5312 } 5316 }
5313 5317
5314 5318
5315 void LCodeGen::DoDoubleToSmi(LDoubleToSmi* instr) { 5319 void LCodeGen::DoDoubleToSmi(LDoubleToSmi* instr) {
5316 LOperand* input = instr->value(); 5320 LOperand* input = instr->value();
5317 DCHECK(input->IsDoubleRegister()); 5321 DCHECK(input->IsDoubleRegister());
5318 LOperand* result = instr->result(); 5322 LOperand* result = instr->result();
5319 DCHECK(result->IsRegister()); 5323 DCHECK(result->IsRegister());
5320 Register result_reg = ToRegister(result); 5324 Register result_reg = ToRegister(result);
5321 5325
5322 Label bailout, done; 5326 Label lost_precision, is_nan, minus_zero, done;
5323 X87Register input_reg = ToX87Register(input); 5327 X87Register input_reg = ToX87Register(input);
5324 X87Fxch(input_reg); 5328 X87Fxch(input_reg);
5325 __ X87TOSToI(result_reg, instr->hydrogen()->GetMinusZeroMode(), 5329 __ X87TOSToI(result_reg, instr->hydrogen()->GetMinusZeroMode(),
5326 &bailout, Label::kNear); 5330 &lost_precision, &is_nan, &minus_zero,
5331 DeoptEveryNTimes() ? Label::kFar : Label::kNear);
5327 __ jmp(&done, Label::kNear); 5332 __ jmp(&done, Label::kNear);
5328 __ bind(&bailout); 5333 __ bind(&lost_precision);
5329 DeoptimizeIf(no_condition, instr); 5334 DeoptimizeIf(no_condition, instr, "lost precision");
5335 __ bind(&is_nan);
5336 DeoptimizeIf(no_condition, instr, "NaN");
5337 __ bind(&minus_zero);
5338 DeoptimizeIf(no_condition, instr, "minus zero");
5330 __ bind(&done); 5339 __ bind(&done);
5331
5332 __ SmiTag(result_reg); 5340 __ SmiTag(result_reg);
5333 DeoptimizeIf(overflow, instr); 5341 DeoptimizeIf(overflow, instr, "overflow");
5334 } 5342 }
5335 5343
5336 5344
5337 void LCodeGen::DoCheckSmi(LCheckSmi* instr) { 5345 void LCodeGen::DoCheckSmi(LCheckSmi* instr) {
5338 LOperand* input = instr->value(); 5346 LOperand* input = instr->value();
5339 __ test(ToOperand(input), Immediate(kSmiTagMask)); 5347 __ test(ToOperand(input), Immediate(kSmiTagMask));
5340 DeoptimizeIf(not_zero, instr); 5348 DeoptimizeIf(not_zero, instr, "not a Smi");
5341 } 5349 }
5342 5350
5343 5351
5344 void LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) { 5352 void LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) {
5345 if (!instr->hydrogen()->value()->type().IsHeapObject()) { 5353 if (!instr->hydrogen()->value()->type().IsHeapObject()) {
5346 LOperand* input = instr->value(); 5354 LOperand* input = instr->value();
5347 __ test(ToOperand(input), Immediate(kSmiTagMask)); 5355 __ test(ToOperand(input), Immediate(kSmiTagMask));
5348 DeoptimizeIf(zero, instr); 5356 DeoptimizeIf(zero, instr, "Smi");
5349 } 5357 }
5350 } 5358 }
5351 5359
5352 5360
5353 void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) { 5361 void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) {
5354 Register input = ToRegister(instr->value()); 5362 Register input = ToRegister(instr->value());
5355 Register temp = ToRegister(instr->temp()); 5363 Register temp = ToRegister(instr->temp());
5356 5364
5357 __ mov(temp, FieldOperand(input, HeapObject::kMapOffset)); 5365 __ mov(temp, FieldOperand(input, HeapObject::kMapOffset));
5358 5366
5359 if (instr->hydrogen()->is_interval_check()) { 5367 if (instr->hydrogen()->is_interval_check()) {
5360 InstanceType first; 5368 InstanceType first;
5361 InstanceType last; 5369 InstanceType last;
5362 instr->hydrogen()->GetCheckInterval(&first, &last); 5370 instr->hydrogen()->GetCheckInterval(&first, &last);
5363 5371
5364 __ cmpb(FieldOperand(temp, Map::kInstanceTypeOffset), 5372 __ cmpb(FieldOperand(temp, Map::kInstanceTypeOffset),
5365 static_cast<int8_t>(first)); 5373 static_cast<int8_t>(first));
5366 5374
5367 // If there is only one type in the interval check for equality. 5375 // If there is only one type in the interval check for equality.
5368 if (first == last) { 5376 if (first == last) {
5369 DeoptimizeIf(not_equal, instr); 5377 DeoptimizeIf(not_equal, instr, "wrong instance type");
5370 } else { 5378 } else {
5371 DeoptimizeIf(below, instr); 5379 DeoptimizeIf(below, instr, "wrong instance type");
5372 // Omit check for the last type. 5380 // Omit check for the last type.
5373 if (last != LAST_TYPE) { 5381 if (last != LAST_TYPE) {
5374 __ cmpb(FieldOperand(temp, Map::kInstanceTypeOffset), 5382 __ cmpb(FieldOperand(temp, Map::kInstanceTypeOffset),
5375 static_cast<int8_t>(last)); 5383 static_cast<int8_t>(last));
5376 DeoptimizeIf(above, instr); 5384 DeoptimizeIf(above, instr, "wrong instance type");
5377 } 5385 }
5378 } 5386 }
5379 } else { 5387 } else {
5380 uint8_t mask; 5388 uint8_t mask;
5381 uint8_t tag; 5389 uint8_t tag;
5382 instr->hydrogen()->GetCheckMaskAndTag(&mask, &tag); 5390 instr->hydrogen()->GetCheckMaskAndTag(&mask, &tag);
5383 5391
5384 if (base::bits::IsPowerOfTwo32(mask)) { 5392 if (base::bits::IsPowerOfTwo32(mask)) {
5385 DCHECK(tag == 0 || base::bits::IsPowerOfTwo32(tag)); 5393 DCHECK(tag == 0 || base::bits::IsPowerOfTwo32(tag));
5386 __ test_b(FieldOperand(temp, Map::kInstanceTypeOffset), mask); 5394 __ test_b(FieldOperand(temp, Map::kInstanceTypeOffset), mask);
5387 DeoptimizeIf(tag == 0 ? not_zero : zero, instr); 5395 DeoptimizeIf(tag == 0 ? not_zero : zero, instr, "wrong instance type");
5388 } else { 5396 } else {
5389 __ movzx_b(temp, FieldOperand(temp, Map::kInstanceTypeOffset)); 5397 __ movzx_b(temp, FieldOperand(temp, Map::kInstanceTypeOffset));
5390 __ and_(temp, mask); 5398 __ and_(temp, mask);
5391 __ cmp(temp, tag); 5399 __ cmp(temp, tag);
5392 DeoptimizeIf(not_equal, instr); 5400 DeoptimizeIf(not_equal, instr, "wrong instance type");
5393 } 5401 }
5394 } 5402 }
5395 } 5403 }
5396 5404
5397 5405
5398 void LCodeGen::DoCheckValue(LCheckValue* instr) { 5406 void LCodeGen::DoCheckValue(LCheckValue* instr) {
5399 Handle<HeapObject> object = instr->hydrogen()->object().handle(); 5407 Handle<HeapObject> object = instr->hydrogen()->object().handle();
5400 if (instr->hydrogen()->object_in_new_space()) { 5408 if (instr->hydrogen()->object_in_new_space()) {
5401 Register reg = ToRegister(instr->value()); 5409 Register reg = ToRegister(instr->value());
5402 Handle<Cell> cell = isolate()->factory()->NewCell(object); 5410 Handle<Cell> cell = isolate()->factory()->NewCell(object);
5403 __ cmp(reg, Operand::ForCell(cell)); 5411 __ cmp(reg, Operand::ForCell(cell));
5404 } else { 5412 } else {
5405 Operand operand = ToOperand(instr->value()); 5413 Operand operand = ToOperand(instr->value());
5406 __ cmp(operand, object); 5414 __ cmp(operand, object);
5407 } 5415 }
5408 DeoptimizeIf(not_equal, instr); 5416 DeoptimizeIf(not_equal, instr, "value mismatch");
5409 } 5417 }
5410 5418
5411 5419
5412 void LCodeGen::DoDeferredInstanceMigration(LCheckMaps* instr, Register object) { 5420 void LCodeGen::DoDeferredInstanceMigration(LCheckMaps* instr, Register object) {
5413 { 5421 {
5414 PushSafepointRegistersScope scope(this); 5422 PushSafepointRegistersScope scope(this);
5415 __ push(object); 5423 __ push(object);
5416 __ xor_(esi, esi); 5424 __ xor_(esi, esi);
5417 __ CallRuntimeSaveDoubles(Runtime::kTryMigrateInstance); 5425 __ CallRuntimeSaveDoubles(Runtime::kTryMigrateInstance);
5418 RecordSafepointWithRegisters( 5426 RecordSafepointWithRegisters(
5419 instr->pointer_map(), 1, Safepoint::kNoLazyDeopt); 5427 instr->pointer_map(), 1, Safepoint::kNoLazyDeopt);
5420 5428
5421 __ test(eax, Immediate(kSmiTagMask)); 5429 __ test(eax, Immediate(kSmiTagMask));
5422 } 5430 }
5423 DeoptimizeIf(zero, instr); 5431 DeoptimizeIf(zero, instr, "instance migration failed");
5424 } 5432 }
5425 5433
5426 5434
5427 void LCodeGen::DoCheckMaps(LCheckMaps* instr) { 5435 void LCodeGen::DoCheckMaps(LCheckMaps* instr) {
5428 class DeferredCheckMaps FINAL : public LDeferredCode { 5436 class DeferredCheckMaps FINAL : public LDeferredCode {
5429 public: 5437 public:
5430 DeferredCheckMaps(LCodeGen* codegen, 5438 DeferredCheckMaps(LCodeGen* codegen,
5431 LCheckMaps* instr, 5439 LCheckMaps* instr,
5432 Register object, 5440 Register object,
5433 const X87Stack& x87_stack) 5441 const X87Stack& x87_stack)
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
5469 Handle<Map> map = maps->at(i).handle(); 5477 Handle<Map> map = maps->at(i).handle();
5470 __ CompareMap(reg, map); 5478 __ CompareMap(reg, map);
5471 __ j(equal, &success, Label::kNear); 5479 __ j(equal, &success, Label::kNear);
5472 } 5480 }
5473 5481
5474 Handle<Map> map = maps->at(maps->size() - 1).handle(); 5482 Handle<Map> map = maps->at(maps->size() - 1).handle();
5475 __ CompareMap(reg, map); 5483 __ CompareMap(reg, map);
5476 if (instr->hydrogen()->HasMigrationTarget()) { 5484 if (instr->hydrogen()->HasMigrationTarget()) {
5477 __ j(not_equal, deferred->entry()); 5485 __ j(not_equal, deferred->entry());
5478 } else { 5486 } else {
5479 DeoptimizeIf(not_equal, instr); 5487 DeoptimizeIf(not_equal, instr, "wrong map");
5480 } 5488 }
5481 5489
5482 __ bind(&success); 5490 __ bind(&success);
5483 } 5491 }
5484 5492
5485 5493
5486 void LCodeGen::DoClampDToUint8(LClampDToUint8* instr) { 5494 void LCodeGen::DoClampDToUint8(LClampDToUint8* instr) {
5487 X87Register value_reg = ToX87Register(instr->unclamped()); 5495 X87Register value_reg = ToX87Register(instr->unclamped());
5488 Register result_reg = ToRegister(instr->result()); 5496 Register result_reg = ToRegister(instr->result());
5489 X87Fxch(value_reg); 5497 X87Fxch(value_reg);
(...skipping 20 matching lines...) Expand all
5510 __ JumpIfSmi(input_reg, &is_smi); 5518 __ JumpIfSmi(input_reg, &is_smi);
5511 5519
5512 // Check for heap number 5520 // Check for heap number
5513 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), 5521 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset),
5514 factory()->heap_number_map()); 5522 factory()->heap_number_map());
5515 __ j(equal, &heap_number, Label::kNear); 5523 __ j(equal, &heap_number, Label::kNear);
5516 5524
5517 // Check for undefined. Undefined is converted to zero for clamping 5525 // Check for undefined. Undefined is converted to zero for clamping
5518 // conversions. 5526 // conversions.
5519 __ cmp(input_reg, factory()->undefined_value()); 5527 __ cmp(input_reg, factory()->undefined_value());
5520 DeoptimizeIf(not_equal, instr); 5528 DeoptimizeIf(not_equal, instr, "not a heap number/undefined");
5521 __ jmp(&zero_result, Label::kNear); 5529 __ jmp(&zero_result, Label::kNear);
5522 5530
5523 // Heap number 5531 // Heap number
5524 __ bind(&heap_number); 5532 __ bind(&heap_number);
5525 5533
5526 // Surprisingly, all of the hand-crafted bit-manipulations below are much 5534 // Surprisingly, all of the hand-crafted bit-manipulations below are much
5527 // faster than the x86 FPU built-in instruction, especially since "banker's 5535 // faster than the x86 FPU built-in instruction, especially since "banker's
5528 // rounding" would be additionally very expensive 5536 // rounding" would be additionally very expensive
5529 5537
5530 // Get exponent word. 5538 // Get exponent word.
(...skipping 552 matching lines...) Expand 10 before | Expand all | Expand 10 after
6083 DCHECK(!environment->HasBeenRegistered()); 6091 DCHECK(!environment->HasBeenRegistered());
6084 RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt); 6092 RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt);
6085 6093
6086 GenerateOsrPrologue(); 6094 GenerateOsrPrologue();
6087 } 6095 }
6088 6096
6089 6097
6090 void LCodeGen::DoForInPrepareMap(LForInPrepareMap* instr) { 6098 void LCodeGen::DoForInPrepareMap(LForInPrepareMap* instr) {
6091 DCHECK(ToRegister(instr->context()).is(esi)); 6099 DCHECK(ToRegister(instr->context()).is(esi));
6092 __ cmp(eax, isolate()->factory()->undefined_value()); 6100 __ cmp(eax, isolate()->factory()->undefined_value());
6093 DeoptimizeIf(equal, instr); 6101 DeoptimizeIf(equal, instr, "undefined");
6094 6102
6095 __ cmp(eax, isolate()->factory()->null_value()); 6103 __ cmp(eax, isolate()->factory()->null_value());
6096 DeoptimizeIf(equal, instr); 6104 DeoptimizeIf(equal, instr, "null");
6097 6105
6098 __ test(eax, Immediate(kSmiTagMask)); 6106 __ test(eax, Immediate(kSmiTagMask));
6099 DeoptimizeIf(zero, instr); 6107 DeoptimizeIf(zero, instr, "Smi");
6100 6108
6101 STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE); 6109 STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE);
6102 __ CmpObjectType(eax, LAST_JS_PROXY_TYPE, ecx); 6110 __ CmpObjectType(eax, LAST_JS_PROXY_TYPE, ecx);
6103 DeoptimizeIf(below_equal, instr); 6111 DeoptimizeIf(below_equal, instr, "wrong instance type");
6104 6112
6105 Label use_cache, call_runtime; 6113 Label use_cache, call_runtime;
6106 __ CheckEnumCache(&call_runtime); 6114 __ CheckEnumCache(&call_runtime);
6107 6115
6108 __ mov(eax, FieldOperand(eax, HeapObject::kMapOffset)); 6116 __ mov(eax, FieldOperand(eax, HeapObject::kMapOffset));
6109 __ jmp(&use_cache, Label::kNear); 6117 __ jmp(&use_cache, Label::kNear);
6110 6118
6111 // Get the set of properties to enumerate. 6119 // Get the set of properties to enumerate.
6112 __ bind(&call_runtime); 6120 __ bind(&call_runtime);
6113 __ push(eax); 6121 __ push(eax);
6114 CallRuntime(Runtime::kGetPropertyNamesFast, 1, instr); 6122 CallRuntime(Runtime::kGetPropertyNamesFast, 1, instr);
6115 6123
6116 __ cmp(FieldOperand(eax, HeapObject::kMapOffset), 6124 __ cmp(FieldOperand(eax, HeapObject::kMapOffset),
6117 isolate()->factory()->meta_map()); 6125 isolate()->factory()->meta_map());
6118 DeoptimizeIf(not_equal, instr); 6126 DeoptimizeIf(not_equal, instr, "wrong map");
6119 __ bind(&use_cache); 6127 __ bind(&use_cache);
6120 } 6128 }
6121 6129
6122 6130
6123 void LCodeGen::DoForInCacheArray(LForInCacheArray* instr) { 6131 void LCodeGen::DoForInCacheArray(LForInCacheArray* instr) {
6124 Register map = ToRegister(instr->map()); 6132 Register map = ToRegister(instr->map());
6125 Register result = ToRegister(instr->result()); 6133 Register result = ToRegister(instr->result());
6126 Label load_cache, done; 6134 Label load_cache, done;
6127 __ EnumLength(result, map); 6135 __ EnumLength(result, map);
6128 __ cmp(result, Immediate(Smi::FromInt(0))); 6136 __ cmp(result, Immediate(Smi::FromInt(0)));
6129 __ j(not_equal, &load_cache, Label::kNear); 6137 __ j(not_equal, &load_cache, Label::kNear);
6130 __ mov(result, isolate()->factory()->empty_fixed_array()); 6138 __ mov(result, isolate()->factory()->empty_fixed_array());
6131 __ jmp(&done, Label::kNear); 6139 __ jmp(&done, Label::kNear);
6132 6140
6133 __ bind(&load_cache); 6141 __ bind(&load_cache);
6134 __ LoadInstanceDescriptors(map, result); 6142 __ LoadInstanceDescriptors(map, result);
6135 __ mov(result, 6143 __ mov(result,
6136 FieldOperand(result, DescriptorArray::kEnumCacheOffset)); 6144 FieldOperand(result, DescriptorArray::kEnumCacheOffset));
6137 __ mov(result, 6145 __ mov(result,
6138 FieldOperand(result, FixedArray::SizeFor(instr->idx()))); 6146 FieldOperand(result, FixedArray::SizeFor(instr->idx())));
6139 __ bind(&done); 6147 __ bind(&done);
6140 __ test(result, result); 6148 __ test(result, result);
6141 DeoptimizeIf(equal, instr); 6149 DeoptimizeIf(equal, instr, "no cache");
6142 } 6150 }
6143 6151
6144 6152
6145 void LCodeGen::DoCheckMapValue(LCheckMapValue* instr) { 6153 void LCodeGen::DoCheckMapValue(LCheckMapValue* instr) {
6146 Register object = ToRegister(instr->value()); 6154 Register object = ToRegister(instr->value());
6147 __ cmp(ToRegister(instr->map()), 6155 __ cmp(ToRegister(instr->map()),
6148 FieldOperand(object, HeapObject::kMapOffset)); 6156 FieldOperand(object, HeapObject::kMapOffset));
6149 DeoptimizeIf(not_equal, instr); 6157 DeoptimizeIf(not_equal, instr, "wrong map");
6150 } 6158 }
6151 6159
6152 6160
6153 void LCodeGen::DoDeferredLoadMutableDouble(LLoadFieldByIndex* instr, 6161 void LCodeGen::DoDeferredLoadMutableDouble(LLoadFieldByIndex* instr,
6154 Register object, 6162 Register object,
6155 Register index) { 6163 Register index) {
6156 PushSafepointRegistersScope scope(this); 6164 PushSafepointRegistersScope scope(this);
6157 __ push(object); 6165 __ push(object);
6158 __ push(index); 6166 __ push(index);
6159 __ xor_(esi, esi); 6167 __ xor_(esi, esi);
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
6234 CallRuntime(Runtime::kPushBlockContext, 2, instr); 6242 CallRuntime(Runtime::kPushBlockContext, 2, instr);
6235 RecordSafepoint(Safepoint::kNoLazyDeopt); 6243 RecordSafepoint(Safepoint::kNoLazyDeopt);
6236 } 6244 }
6237 6245
6238 6246
6239 #undef __ 6247 #undef __
6240 6248
6241 } } // namespace v8::internal 6249 } } // namespace v8::internal
6242 6250
6243 #endif // V8_TARGET_ARCH_X87 6251 #endif // V8_TARGET_ARCH_X87
OLDNEW
« no previous file with comments | « src/x87/lithium-codegen-x87.h ('k') | src/x87/macro-assembler-x87.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698