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

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

Issue 874323003: Externalize deoptimization reasons. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: minor change Created 5 years, 10 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/x64/lithium-codegen-x64.cc ('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 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, "minus zero"); 1416 DeoptimizeIf(zero, instr, Deoptimizer::kMinusZero);
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, "division by zero"); 1433 DeoptimizeIf(no_condition, instr, Deoptimizer::kDivisionByZero);
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, "minus zero"); 1448 DeoptimizeIf(less, instr, Deoptimizer::kMinusZero);
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, "division by zero"); 1470 DeoptimizeIf(zero, instr, Deoptimizer::kDivisionByZero);
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, "minus zero"); 1481 DeoptimizeIf(equal, instr, Deoptimizer::kMinusZero);
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, "minus zero"); 1500 DeoptimizeIf(zero, instr, Deoptimizer::kMinusZero);
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, "minus zero"); 1520 DeoptimizeIf(zero, instr, Deoptimizer::kMinusZero);
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, "overflow"); 1525 DeoptimizeIf(zero, instr, Deoptimizer::kOverflow);
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, "lost precision"); 1532 DeoptimizeIf(not_zero, instr, Deoptimizer::kLostPrecision);
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, "division by zero"); 1553 DeoptimizeIf(no_condition, instr, Deoptimizer::kDivisionByZero);
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, "minus zero"); 1561 DeoptimizeIf(zero, instr, Deoptimizer::kMinusZero);
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, "lost precision"); 1571 DeoptimizeIf(not_equal, instr, Deoptimizer::kLostPrecision);
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, "division by zero"); 1591 DeoptimizeIf(zero, instr, Deoptimizer::kDivisionByZero);
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, "minus zero"); 1600 DeoptimizeIf(sign, instr, Deoptimizer::kMinusZero);
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, "overflow"); 1610 DeoptimizeIf(zero, instr, Deoptimizer::kOverflow);
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, "lost precision"); 1621 DeoptimizeIf(not_zero, instr, Deoptimizer::kLostPrecision);
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, "minus zero"); 1643 DeoptimizeIf(zero, instr, Deoptimizer::kMinusZero);
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, "overflow"); 1649 DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow);
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, "division by zero"); 1676 DeoptimizeIf(no_condition, instr, Deoptimizer::kDivisionByZero);
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, "minus zero"); 1684 DeoptimizeIf(zero, instr, Deoptimizer::kMinusZero);
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, "division by zero"); 1731 DeoptimizeIf(zero, instr, Deoptimizer::kDivisionByZero);
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, "minus zero"); 1740 DeoptimizeIf(sign, instr, Deoptimizer::kMinusZero);
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, "overflow"); 1750 DeoptimizeIf(zero, instr, Deoptimizer::kOverflow);
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, "overflow"); 1828 DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow);
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, "minus zero"); 1838 DeoptimizeIf(no_condition, instr, Deoptimizer::kMinusZero);
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, "minus zero"); 1841 DeoptimizeIf(less, instr, Deoptimizer::kMinusZero);
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, "minus zero"); 1846 DeoptimizeIf(sign, instr, Deoptimizer::kMinusZero);
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, "negative value"); 1919 DeoptimizeIf(sign, instr, Deoptimizer::kNegativeValue);
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, "negative value"); 1936 DeoptimizeIf(sign, instr, Deoptimizer::kNegativeValue);
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, "negative value"); 1951 DeoptimizeIf(sign, instr, Deoptimizer::kNegativeValue);
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, "overflow"); 1962 DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow);
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, "overflow"); 1988 DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow);
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 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
2037 void LCodeGen::DoDateField(LDateField* instr) { 2037 void LCodeGen::DoDateField(LDateField* instr) {
2038 Register object = ToRegister(instr->date()); 2038 Register object = ToRegister(instr->date());
2039 Register result = ToRegister(instr->result()); 2039 Register result = ToRegister(instr->result());
2040 Register scratch = ToRegister(instr->temp()); 2040 Register scratch = ToRegister(instr->temp());
2041 Smi* index = instr->index(); 2041 Smi* index = instr->index();
2042 Label runtime, done; 2042 Label runtime, done;
2043 DCHECK(object.is(result)); 2043 DCHECK(object.is(result));
2044 DCHECK(object.is(eax)); 2044 DCHECK(object.is(eax));
2045 2045
2046 __ test(object, Immediate(kSmiTagMask)); 2046 __ test(object, Immediate(kSmiTagMask));
2047 DeoptimizeIf(zero, instr, "Smi"); 2047 DeoptimizeIf(zero, instr, Deoptimizer::kSmi);
2048 __ CmpObjectType(object, JS_DATE_TYPE, scratch); 2048 __ CmpObjectType(object, JS_DATE_TYPE, scratch);
2049 DeoptimizeIf(not_equal, instr, "not a date object"); 2049 DeoptimizeIf(not_equal, instr, Deoptimizer::kNotADateObject);
2050 2050
2051 if (index->value() == 0) { 2051 if (index->value() == 0) {
2052 __ mov(result, FieldOperand(object, JSDate::kValueOffset)); 2052 __ mov(result, FieldOperand(object, JSDate::kValueOffset));
2053 } else { 2053 } else {
2054 if (index->value() < JSDate::kFirstUncachedField) { 2054 if (index->value() < JSDate::kFirstUncachedField) {
2055 ExternalReference stamp = ExternalReference::date_cache_stamp(isolate()); 2055 ExternalReference stamp = ExternalReference::date_cache_stamp(isolate());
2056 __ mov(scratch, Operand::StaticVariable(stamp)); 2056 __ mov(scratch, Operand::StaticVariable(stamp));
2057 __ cmp(scratch, FieldOperand(object, JSDate::kCacheStampOffset)); 2057 __ cmp(scratch, FieldOperand(object, JSDate::kCacheStampOffset));
2058 __ j(not_equal, &runtime, Label::kNear); 2058 __ j(not_equal, &runtime, Label::kNear);
2059 __ mov(result, FieldOperand(object, JSDate::kValueOffset + 2059 __ mov(result, FieldOperand(object, JSDate::kValueOffset +
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
2169 __ lea(ToRegister(instr->result()), address); 2169 __ lea(ToRegister(instr->result()), address);
2170 } 2170 }
2171 } else { 2171 } else {
2172 if (right->IsConstantOperand()) { 2172 if (right->IsConstantOperand()) {
2173 __ add(ToOperand(left), 2173 __ add(ToOperand(left),
2174 ToImmediate(right, instr->hydrogen()->representation())); 2174 ToImmediate(right, instr->hydrogen()->representation()));
2175 } else { 2175 } else {
2176 __ add(ToRegister(left), ToOperand(right)); 2176 __ add(ToRegister(left), ToOperand(right));
2177 } 2177 }
2178 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { 2178 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) {
2179 DeoptimizeIf(overflow, instr, "overflow"); 2179 DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow);
2180 } 2180 }
2181 } 2181 }
2182 } 2182 }
2183 2183
2184 2184
2185 void LCodeGen::DoMathMinMax(LMathMinMax* instr) { 2185 void LCodeGen::DoMathMinMax(LMathMinMax* instr) {
2186 LOperand* left = instr->left(); 2186 LOperand* left = instr->left();
2187 LOperand* right = instr->right(); 2187 LOperand* right = instr->right();
2188 DCHECK(left->Equals(instr->result())); 2188 DCHECK(left->Equals(instr->result()));
2189 HMathMinMax::Operation operation = instr->hydrogen()->operation(); 2189 HMathMinMax::Operation operation = instr->hydrogen()->operation();
(...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after
2412 } 2412 }
2413 2413
2414 if (expected.Contains(ToBooleanStub::SMI)) { 2414 if (expected.Contains(ToBooleanStub::SMI)) {
2415 // Smis: 0 -> false, all other -> true. 2415 // Smis: 0 -> false, all other -> true.
2416 __ test(reg, Operand(reg)); 2416 __ test(reg, Operand(reg));
2417 __ j(equal, instr->FalseLabel(chunk_)); 2417 __ j(equal, instr->FalseLabel(chunk_));
2418 __ JumpIfSmi(reg, instr->TrueLabel(chunk_)); 2418 __ JumpIfSmi(reg, instr->TrueLabel(chunk_));
2419 } else if (expected.NeedsMap()) { 2419 } else if (expected.NeedsMap()) {
2420 // If we need a map later and have a Smi -> deopt. 2420 // If we need a map later and have a Smi -> deopt.
2421 __ test(reg, Immediate(kSmiTagMask)); 2421 __ test(reg, Immediate(kSmiTagMask));
2422 DeoptimizeIf(zero, instr, "Smi"); 2422 DeoptimizeIf(zero, instr, Deoptimizer::kSmi);
2423 } 2423 }
2424 2424
2425 Register map = no_reg; // Keep the compiler happy. 2425 Register map = no_reg; // Keep the compiler happy.
2426 if (expected.NeedsMap()) { 2426 if (expected.NeedsMap()) {
2427 map = ToRegister(instr->temp()); 2427 map = ToRegister(instr->temp());
2428 DCHECK(!map.is(reg)); 2428 DCHECK(!map.is(reg));
2429 __ mov(map, FieldOperand(reg, HeapObject::kMapOffset)); 2429 __ mov(map, FieldOperand(reg, HeapObject::kMapOffset));
2430 2430
2431 if (expected.CanBeUndetectable()) { 2431 if (expected.CanBeUndetectable()) {
2432 // Undetectable -> false. 2432 // Undetectable -> false.
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
2469 __ fld_d(FieldOperand(reg, HeapNumber::kValueOffset)); 2469 __ fld_d(FieldOperand(reg, HeapNumber::kValueOffset));
2470 __ FCmp(); 2470 __ FCmp();
2471 __ j(zero, instr->FalseLabel(chunk_)); 2471 __ j(zero, instr->FalseLabel(chunk_));
2472 __ jmp(instr->TrueLabel(chunk_)); 2472 __ jmp(instr->TrueLabel(chunk_));
2473 __ bind(&not_heap_number); 2473 __ bind(&not_heap_number);
2474 } 2474 }
2475 2475
2476 if (!expected.IsGeneric()) { 2476 if (!expected.IsGeneric()) {
2477 // We've seen something for the first time -> deopt. 2477 // We've seen something for the first time -> deopt.
2478 // This can only happen if we are not generic already. 2478 // This can only happen if we are not generic already.
2479 DeoptimizeIf(no_condition, instr, "unexpected object"); 2479 DeoptimizeIf(no_condition, instr, Deoptimizer::kUnexpectedObject);
2480 } 2480 }
2481 } 2481 }
2482 } 2482 }
2483 } 2483 }
2484 2484
2485 2485
2486 void LCodeGen::EmitGoto(int block) { 2486 void LCodeGen::EmitGoto(int block) {
2487 if (!IsNextEmittedBlock(block)) { 2487 if (!IsNextEmittedBlock(block)) {
2488 __ jmp(chunk_->GetAssemblyLabel(LookupDestination(block))); 2488 __ jmp(chunk_->GetAssemblyLabel(LookupDestination(block)));
2489 } 2489 }
(...skipping 621 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, "hole"); 3121 DeoptimizeIf(equal, instr, Deoptimizer::kHole);
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_register = ToRegister(instr->temp_vector()); 3129 Register vector_register = ToRegister(instr->temp_vector());
3130 Register slot_register = VectorLoadICDescriptor::SlotRegister(); 3130 Register slot_register = VectorLoadICDescriptor::SlotRegister();
3131 DCHECK(vector_register.is(VectorLoadICDescriptor::VectorRegister())); 3131 DCHECK(vector_register.is(VectorLoadICDescriptor::VectorRegister()));
(...skipping 28 matching lines...) Expand all
3160 void LCodeGen::DoStoreGlobalCell(LStoreGlobalCell* instr) { 3160 void LCodeGen::DoStoreGlobalCell(LStoreGlobalCell* instr) {
3161 Register value = ToRegister(instr->value()); 3161 Register value = ToRegister(instr->value());
3162 Handle<PropertyCell> cell_handle = instr->hydrogen()->cell().handle(); 3162 Handle<PropertyCell> cell_handle = instr->hydrogen()->cell().handle();
3163 3163
3164 // If the cell we are storing to contains the hole it could have 3164 // If the cell we are storing to contains the hole it could have
3165 // been deleted from the property dictionary. In that case, we need 3165 // been deleted from the property dictionary. In that case, we need
3166 // to update the property details in the property dictionary to mark 3166 // to update the property details in the property dictionary to mark
3167 // it as no longer deleted. We deoptimize in that case. 3167 // it as no longer deleted. We deoptimize in that case.
3168 if (instr->hydrogen()->RequiresHoleCheck()) { 3168 if (instr->hydrogen()->RequiresHoleCheck()) {
3169 __ cmp(Operand::ForCell(cell_handle), factory()->the_hole_value()); 3169 __ cmp(Operand::ForCell(cell_handle), factory()->the_hole_value());
3170 DeoptimizeIf(equal, instr, "hole"); 3170 DeoptimizeIf(equal, instr, Deoptimizer::kHole);
3171 } 3171 }
3172 3172
3173 // Store the value. 3173 // Store the value.
3174 __ mov(Operand::ForCell(cell_handle), value); 3174 __ mov(Operand::ForCell(cell_handle), value);
3175 // Cells are always rescanned, so no write barrier here. 3175 // Cells are always rescanned, so no write barrier here.
3176 } 3176 }
3177 3177
3178 3178
3179 void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) { 3179 void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) {
3180 Register context = ToRegister(instr->context()); 3180 Register context = ToRegister(instr->context());
3181 Register result = ToRegister(instr->result()); 3181 Register result = ToRegister(instr->result());
3182 __ mov(result, ContextOperand(context, instr->slot_index())); 3182 __ mov(result, ContextOperand(context, instr->slot_index()));
3183 3183
3184 if (instr->hydrogen()->RequiresHoleCheck()) { 3184 if (instr->hydrogen()->RequiresHoleCheck()) {
3185 __ cmp(result, factory()->the_hole_value()); 3185 __ cmp(result, factory()->the_hole_value());
3186 if (instr->hydrogen()->DeoptimizesOnHole()) { 3186 if (instr->hydrogen()->DeoptimizesOnHole()) {
3187 DeoptimizeIf(equal, instr, "hole"); 3187 DeoptimizeIf(equal, instr, Deoptimizer::kHole);
3188 } else { 3188 } else {
3189 Label is_not_hole; 3189 Label is_not_hole;
3190 __ j(not_equal, &is_not_hole, Label::kNear); 3190 __ j(not_equal, &is_not_hole, Label::kNear);
3191 __ mov(result, factory()->undefined_value()); 3191 __ mov(result, factory()->undefined_value());
3192 __ bind(&is_not_hole); 3192 __ bind(&is_not_hole);
3193 } 3193 }
3194 } 3194 }
3195 } 3195 }
3196 3196
3197 3197
3198 void LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) { 3198 void LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) {
3199 Register context = ToRegister(instr->context()); 3199 Register context = ToRegister(instr->context());
3200 Register value = ToRegister(instr->value()); 3200 Register value = ToRegister(instr->value());
3201 3201
3202 Label skip_assignment; 3202 Label skip_assignment;
3203 3203
3204 Operand target = ContextOperand(context, instr->slot_index()); 3204 Operand target = ContextOperand(context, instr->slot_index());
3205 if (instr->hydrogen()->RequiresHoleCheck()) { 3205 if (instr->hydrogen()->RequiresHoleCheck()) {
3206 __ cmp(target, factory()->the_hole_value()); 3206 __ cmp(target, factory()->the_hole_value());
3207 if (instr->hydrogen()->DeoptimizesOnHole()) { 3207 if (instr->hydrogen()->DeoptimizesOnHole()) {
3208 DeoptimizeIf(equal, instr, "hole"); 3208 DeoptimizeIf(equal, instr, Deoptimizer::kHole);
3209 } else { 3209 } else {
3210 __ j(not_equal, &skip_assignment, Label::kNear); 3210 __ j(not_equal, &skip_assignment, Label::kNear);
3211 } 3211 }
3212 } 3212 }
3213 3213
3214 __ mov(target, value); 3214 __ mov(target, value);
3215 if (instr->hydrogen()->NeedsWriteBarrier()) { 3215 if (instr->hydrogen()->NeedsWriteBarrier()) {
3216 SmiCheck check_needed = 3216 SmiCheck check_needed =
3217 instr->hydrogen()->value()->type().IsHeapObject() 3217 instr->hydrogen()->value()->type().IsHeapObject()
3218 ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; 3218 ? OMIT_SMI_CHECK : INLINE_SMI_CHECK;
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
3292 Register function = ToRegister(instr->function()); 3292 Register function = ToRegister(instr->function());
3293 Register temp = ToRegister(instr->temp()); 3293 Register temp = ToRegister(instr->temp());
3294 Register result = ToRegister(instr->result()); 3294 Register result = ToRegister(instr->result());
3295 3295
3296 // Get the prototype or initial map from the function. 3296 // Get the prototype or initial map from the function.
3297 __ mov(result, 3297 __ mov(result,
3298 FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset)); 3298 FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset));
3299 3299
3300 // Check that the function has a prototype or an initial map. 3300 // Check that the function has a prototype or an initial map.
3301 __ cmp(Operand(result), Immediate(factory()->the_hole_value())); 3301 __ cmp(Operand(result), Immediate(factory()->the_hole_value()));
3302 DeoptimizeIf(equal, instr, "hole"); 3302 DeoptimizeIf(equal, instr, Deoptimizer::kHole);
3303 3303
3304 // If the function does not have an initial map, we're done. 3304 // If the function does not have an initial map, we're done.
3305 Label done; 3305 Label done;
3306 __ CmpObjectType(result, MAP_TYPE, temp); 3306 __ CmpObjectType(result, MAP_TYPE, temp);
3307 __ j(not_equal, &done, Label::kNear); 3307 __ j(not_equal, &done, Label::kNear);
3308 3308
3309 // Get the prototype from the initial map. 3309 // Get the prototype from the initial map.
3310 __ mov(result, FieldOperand(result, Map::kPrototypeOffset)); 3310 __ mov(result, FieldOperand(result, Map::kPrototypeOffset));
3311 3311
3312 // All done. 3312 // All done.
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
3383 break; 3383 break;
3384 case EXTERNAL_INT32_ELEMENTS: 3384 case EXTERNAL_INT32_ELEMENTS:
3385 case INT32_ELEMENTS: 3385 case INT32_ELEMENTS:
3386 __ mov(result, operand); 3386 __ mov(result, operand);
3387 break; 3387 break;
3388 case EXTERNAL_UINT32_ELEMENTS: 3388 case EXTERNAL_UINT32_ELEMENTS:
3389 case UINT32_ELEMENTS: 3389 case UINT32_ELEMENTS:
3390 __ mov(result, operand); 3390 __ mov(result, operand);
3391 if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) { 3391 if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) {
3392 __ test(result, Operand(result)); 3392 __ test(result, Operand(result));
3393 DeoptimizeIf(negative, instr, "negative value"); 3393 DeoptimizeIf(negative, instr, Deoptimizer::kNegativeValue);
3394 } 3394 }
3395 break; 3395 break;
3396 case EXTERNAL_FLOAT32_ELEMENTS: 3396 case EXTERNAL_FLOAT32_ELEMENTS:
3397 case EXTERNAL_FLOAT64_ELEMENTS: 3397 case EXTERNAL_FLOAT64_ELEMENTS:
3398 case FLOAT32_ELEMENTS: 3398 case FLOAT32_ELEMENTS:
3399 case FLOAT64_ELEMENTS: 3399 case FLOAT64_ELEMENTS:
3400 case FAST_SMI_ELEMENTS: 3400 case FAST_SMI_ELEMENTS:
3401 case FAST_ELEMENTS: 3401 case FAST_ELEMENTS:
3402 case FAST_DOUBLE_ELEMENTS: 3402 case FAST_DOUBLE_ELEMENTS:
3403 case FAST_HOLEY_SMI_ELEMENTS: 3403 case FAST_HOLEY_SMI_ELEMENTS:
3404 case FAST_HOLEY_ELEMENTS: 3404 case FAST_HOLEY_ELEMENTS:
3405 case FAST_HOLEY_DOUBLE_ELEMENTS: 3405 case FAST_HOLEY_DOUBLE_ELEMENTS:
3406 case DICTIONARY_ELEMENTS: 3406 case DICTIONARY_ELEMENTS:
3407 case SLOPPY_ARGUMENTS_ELEMENTS: 3407 case SLOPPY_ARGUMENTS_ELEMENTS:
3408 UNREACHABLE(); 3408 UNREACHABLE();
3409 break; 3409 break;
3410 } 3410 }
3411 } 3411 }
3412 } 3412 }
3413 3413
3414 3414
3415 void LCodeGen::DoLoadKeyedFixedDoubleArray(LLoadKeyed* instr) { 3415 void LCodeGen::DoLoadKeyedFixedDoubleArray(LLoadKeyed* instr) {
3416 if (instr->hydrogen()->RequiresHoleCheck()) { 3416 if (instr->hydrogen()->RequiresHoleCheck()) {
3417 Operand hole_check_operand = BuildFastArrayOperand( 3417 Operand hole_check_operand = BuildFastArrayOperand(
3418 instr->elements(), instr->key(), 3418 instr->elements(), instr->key(),
3419 instr->hydrogen()->key()->representation(), 3419 instr->hydrogen()->key()->representation(),
3420 FAST_DOUBLE_ELEMENTS, 3420 FAST_DOUBLE_ELEMENTS,
3421 instr->base_offset() + sizeof(kHoleNanLower32)); 3421 instr->base_offset() + sizeof(kHoleNanLower32));
3422 __ cmp(hole_check_operand, Immediate(kHoleNanUpper32)); 3422 __ cmp(hole_check_operand, Immediate(kHoleNanUpper32));
3423 DeoptimizeIf(equal, instr, "hole"); 3423 DeoptimizeIf(equal, instr, Deoptimizer::kHole);
3424 } 3424 }
3425 3425
3426 Operand double_load_operand = BuildFastArrayOperand( 3426 Operand double_load_operand = BuildFastArrayOperand(
3427 instr->elements(), 3427 instr->elements(),
3428 instr->key(), 3428 instr->key(),
3429 instr->hydrogen()->key()->representation(), 3429 instr->hydrogen()->key()->representation(),
3430 FAST_DOUBLE_ELEMENTS, 3430 FAST_DOUBLE_ELEMENTS,
3431 instr->base_offset()); 3431 instr->base_offset());
3432 X87Mov(ToX87Register(instr->result()), double_load_operand); 3432 X87Mov(ToX87Register(instr->result()), double_load_operand);
3433 } 3433 }
3434 3434
3435 3435
3436 void LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) { 3436 void LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) {
3437 Register result = ToRegister(instr->result()); 3437 Register result = ToRegister(instr->result());
3438 3438
3439 // Load the result. 3439 // Load the result.
3440 __ mov(result, 3440 __ mov(result,
3441 BuildFastArrayOperand(instr->elements(), instr->key(), 3441 BuildFastArrayOperand(instr->elements(), instr->key(),
3442 instr->hydrogen()->key()->representation(), 3442 instr->hydrogen()->key()->representation(),
3443 FAST_ELEMENTS, instr->base_offset())); 3443 FAST_ELEMENTS, instr->base_offset()));
3444 3444
3445 // Check for the hole value. 3445 // Check for the hole value.
3446 if (instr->hydrogen()->RequiresHoleCheck()) { 3446 if (instr->hydrogen()->RequiresHoleCheck()) {
3447 if (IsFastSmiElementsKind(instr->hydrogen()->elements_kind())) { 3447 if (IsFastSmiElementsKind(instr->hydrogen()->elements_kind())) {
3448 __ test(result, Immediate(kSmiTagMask)); 3448 __ test(result, Immediate(kSmiTagMask));
3449 DeoptimizeIf(not_equal, instr, "not a Smi"); 3449 DeoptimizeIf(not_equal, instr, Deoptimizer::kNotASmi);
3450 } else { 3450 } else {
3451 __ cmp(result, factory()->the_hole_value()); 3451 __ cmp(result, factory()->the_hole_value());
3452 DeoptimizeIf(equal, instr, "hole"); 3452 DeoptimizeIf(equal, instr, Deoptimizer::kHole);
3453 } 3453 }
3454 } 3454 }
3455 } 3455 }
3456 3456
3457 3457
3458 void LCodeGen::DoLoadKeyed(LLoadKeyed* instr) { 3458 void LCodeGen::DoLoadKeyed(LLoadKeyed* instr) {
3459 if (instr->is_typed_elements()) { 3459 if (instr->is_typed_elements()) {
3460 DoLoadKeyedExternalArray(instr); 3460 DoLoadKeyedExternalArray(instr);
3461 } else if (instr->hydrogen()->representation().IsDouble()) { 3461 } else if (instr->hydrogen()->representation().IsDouble()) {
3462 DoLoadKeyedFixedDoubleArray(instr); 3462 DoLoadKeyedFixedDoubleArray(instr);
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after
3589 } 3589 }
3590 3590
3591 // Normal function. Replace undefined or null with global receiver. 3591 // Normal function. Replace undefined or null with global receiver.
3592 __ cmp(receiver, factory()->null_value()); 3592 __ cmp(receiver, factory()->null_value());
3593 __ j(equal, &global_object, Label::kNear); 3593 __ j(equal, &global_object, Label::kNear);
3594 __ cmp(receiver, factory()->undefined_value()); 3594 __ cmp(receiver, factory()->undefined_value());
3595 __ j(equal, &global_object, Label::kNear); 3595 __ j(equal, &global_object, Label::kNear);
3596 3596
3597 // The receiver should be a JS object. 3597 // The receiver should be a JS object.
3598 __ test(receiver, Immediate(kSmiTagMask)); 3598 __ test(receiver, Immediate(kSmiTagMask));
3599 DeoptimizeIf(equal, instr, "Smi"); 3599 DeoptimizeIf(equal, instr, Deoptimizer::kSmi);
3600 __ CmpObjectType(receiver, FIRST_SPEC_OBJECT_TYPE, scratch); 3600 __ CmpObjectType(receiver, FIRST_SPEC_OBJECT_TYPE, scratch);
3601 DeoptimizeIf(below, instr, "not a JavaScript object"); 3601 DeoptimizeIf(below, instr, Deoptimizer::kNotAJavaScriptObject);
3602 3602
3603 __ jmp(&receiver_ok, Label::kNear); 3603 __ jmp(&receiver_ok, Label::kNear);
3604 __ bind(&global_object); 3604 __ bind(&global_object);
3605 __ mov(receiver, FieldOperand(function, JSFunction::kContextOffset)); 3605 __ mov(receiver, FieldOperand(function, JSFunction::kContextOffset));
3606 const int global_offset = Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX); 3606 const int global_offset = Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX);
3607 __ mov(receiver, Operand(receiver, global_offset)); 3607 __ mov(receiver, Operand(receiver, global_offset));
3608 const int proxy_offset = GlobalObject::kGlobalProxyOffset; 3608 const int proxy_offset = GlobalObject::kGlobalProxyOffset;
3609 __ mov(receiver, FieldOperand(receiver, proxy_offset)); 3609 __ mov(receiver, FieldOperand(receiver, proxy_offset));
3610 __ bind(&receiver_ok); 3610 __ bind(&receiver_ok);
3611 } 3611 }
3612 3612
3613 3613
3614 void LCodeGen::DoApplyArguments(LApplyArguments* instr) { 3614 void LCodeGen::DoApplyArguments(LApplyArguments* instr) {
3615 Register receiver = ToRegister(instr->receiver()); 3615 Register receiver = ToRegister(instr->receiver());
3616 Register function = ToRegister(instr->function()); 3616 Register function = ToRegister(instr->function());
3617 Register length = ToRegister(instr->length()); 3617 Register length = ToRegister(instr->length());
3618 Register elements = ToRegister(instr->elements()); 3618 Register elements = ToRegister(instr->elements());
3619 DCHECK(receiver.is(eax)); // Used for parameter count. 3619 DCHECK(receiver.is(eax)); // Used for parameter count.
3620 DCHECK(function.is(edi)); // Required by InvokeFunction. 3620 DCHECK(function.is(edi)); // Required by InvokeFunction.
3621 DCHECK(ToRegister(instr->result()).is(eax)); 3621 DCHECK(ToRegister(instr->result()).is(eax));
3622 3622
3623 // Copy the arguments to this function possibly from the 3623 // Copy the arguments to this function possibly from the
3624 // adaptor frame below it. 3624 // adaptor frame below it.
3625 const uint32_t kArgumentsLimit = 1 * KB; 3625 const uint32_t kArgumentsLimit = 1 * KB;
3626 __ cmp(length, kArgumentsLimit); 3626 __ cmp(length, kArgumentsLimit);
3627 DeoptimizeIf(above, instr, "too many arguments"); 3627 DeoptimizeIf(above, instr, Deoptimizer::kTooManyArguments);
3628 3628
3629 __ push(receiver); 3629 __ push(receiver);
3630 __ mov(receiver, length); 3630 __ mov(receiver, length);
3631 3631
3632 // Loop through the arguments pushing them onto the execution 3632 // Loop through the arguments pushing them onto the execution
3633 // stack. 3633 // stack.
3634 Label invoke, loop; 3634 Label invoke, loop;
3635 // length is a small non-negative integer, due to the test above. 3635 // length is a small non-negative integer, due to the test above.
3636 __ test(length, Operand(length)); 3636 __ test(length, Operand(length));
3637 __ j(zero, &invoke, Label::kNear); 3637 __ j(zero, &invoke, Label::kNear);
(...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after
3842 } 3842 }
3843 3843
3844 RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT); 3844 RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT);
3845 } 3845 }
3846 3846
3847 3847
3848 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LMathAbs* instr) { 3848 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LMathAbs* instr) {
3849 Register input_reg = ToRegister(instr->value()); 3849 Register input_reg = ToRegister(instr->value());
3850 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), 3850 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset),
3851 factory()->heap_number_map()); 3851 factory()->heap_number_map());
3852 DeoptimizeIf(not_equal, instr, "not a heap number"); 3852 DeoptimizeIf(not_equal, instr, Deoptimizer::kNotAHeapNumber);
3853 3853
3854 Label slow, allocated, done; 3854 Label slow, allocated, done;
3855 Register tmp = input_reg.is(eax) ? ecx : eax; 3855 Register tmp = input_reg.is(eax) ? ecx : eax;
3856 Register tmp2 = tmp.is(ecx) ? edx : input_reg.is(ecx) ? edx : ecx; 3856 Register tmp2 = tmp.is(ecx) ? edx : input_reg.is(ecx) ? edx : ecx;
3857 3857
3858 // Preserve the value of all registers. 3858 // Preserve the value of all registers.
3859 PushSafepointRegistersScope scope(this); 3859 PushSafepointRegistersScope scope(this);
3860 3860
3861 __ mov(tmp, FieldOperand(input_reg, HeapNumber::kExponentOffset)); 3861 __ mov(tmp, FieldOperand(input_reg, HeapNumber::kExponentOffset));
3862 // Check the sign of the argument. If the argument is positive, just 3862 // Check the sign of the argument. If the argument is positive, just
(...skipping 26 matching lines...) Expand all
3889 __ bind(&done); 3889 __ bind(&done);
3890 } 3890 }
3891 3891
3892 3892
3893 void LCodeGen::EmitIntegerMathAbs(LMathAbs* instr) { 3893 void LCodeGen::EmitIntegerMathAbs(LMathAbs* instr) {
3894 Register input_reg = ToRegister(instr->value()); 3894 Register input_reg = ToRegister(instr->value());
3895 __ test(input_reg, Operand(input_reg)); 3895 __ test(input_reg, Operand(input_reg));
3896 Label is_positive; 3896 Label is_positive;
3897 __ j(not_sign, &is_positive, Label::kNear); 3897 __ j(not_sign, &is_positive, Label::kNear);
3898 __ neg(input_reg); // Sets flags. 3898 __ neg(input_reg); // Sets flags.
3899 DeoptimizeIf(negative, instr, "overflow"); 3899 DeoptimizeIf(negative, instr, Deoptimizer::kOverflow);
3900 __ bind(&is_positive); 3900 __ bind(&is_positive);
3901 } 3901 }
3902 3902
3903 3903
3904 void LCodeGen::DoMathAbs(LMathAbs* instr) { 3904 void LCodeGen::DoMathAbs(LMathAbs* instr) {
3905 // Class for deferred case. 3905 // Class for deferred case.
3906 class DeferredMathAbsTaggedHeapNumber FINAL : public LDeferredCode { 3906 class DeferredMathAbsTaggedHeapNumber FINAL : public LDeferredCode {
3907 public: 3907 public:
3908 DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen, 3908 DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen,
3909 LMathAbs* instr, 3909 LMathAbs* instr,
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
3942 void LCodeGen::DoMathFloor(LMathFloor* instr) { 3942 void LCodeGen::DoMathFloor(LMathFloor* instr) {
3943 Register output_reg = ToRegister(instr->result()); 3943 Register output_reg = ToRegister(instr->result());
3944 X87Register input_reg = ToX87Register(instr->value()); 3944 X87Register input_reg = ToX87Register(instr->value());
3945 X87Fxch(input_reg); 3945 X87Fxch(input_reg);
3946 3946
3947 Label not_minus_zero, done; 3947 Label not_minus_zero, done;
3948 // Deoptimize on unordered. 3948 // Deoptimize on unordered.
3949 __ fldz(); 3949 __ fldz();
3950 __ fld(1); 3950 __ fld(1);
3951 __ FCmp(); 3951 __ FCmp();
3952 DeoptimizeIf(parity_even, instr, "NaN"); 3952 DeoptimizeIf(parity_even, instr, Deoptimizer::kNaN);
3953 __ j(below, &not_minus_zero, Label::kNear); 3953 __ j(below, &not_minus_zero, Label::kNear);
3954 3954
3955 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 3955 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
3956 // Check for negative zero. 3956 // Check for negative zero.
3957 __ j(not_equal, &not_minus_zero, Label::kNear); 3957 __ j(not_equal, &not_minus_zero, Label::kNear);
3958 // +- 0.0. 3958 // +- 0.0.
3959 __ fld(0); 3959 __ fld(0);
3960 __ FXamSign(); 3960 __ FXamSign();
3961 DeoptimizeIf(not_zero, instr, "minus zero"); 3961 DeoptimizeIf(not_zero, instr, Deoptimizer::kMinusZero);
3962 __ Move(output_reg, Immediate(0)); 3962 __ Move(output_reg, Immediate(0));
3963 __ jmp(&done, Label::kFar); 3963 __ jmp(&done, Label::kFar);
3964 } 3964 }
3965 3965
3966 // Positive input. 3966 // Positive input.
3967 // rc=01B, round down. 3967 // rc=01B, round down.
3968 __ bind(&not_minus_zero); 3968 __ bind(&not_minus_zero);
3969 __ fnclex(); 3969 __ fnclex();
3970 __ X87SetRC(0x0400); 3970 __ X87SetRC(0x0400);
3971 __ sub(esp, Immediate(kPointerSize)); 3971 __ sub(esp, Immediate(kPointerSize));
3972 __ fist_s(Operand(esp, 0)); 3972 __ fist_s(Operand(esp, 0));
3973 __ pop(output_reg); 3973 __ pop(output_reg);
3974 __ X87CheckIA(); 3974 __ X87CheckIA();
3975 DeoptimizeIf(equal, instr, "overflow"); 3975 DeoptimizeIf(equal, instr, Deoptimizer::kOverflow);
3976 __ fnclex(); 3976 __ fnclex();
3977 __ X87SetRC(0x0000); 3977 __ X87SetRC(0x0000);
3978 __ bind(&done); 3978 __ bind(&done);
3979 } 3979 }
3980 3980
3981 3981
3982 void LCodeGen::DoMathRound(LMathRound* instr) { 3982 void LCodeGen::DoMathRound(LMathRound* instr) {
3983 X87Register input_reg = ToX87Register(instr->value()); 3983 X87Register input_reg = ToX87Register(instr->value());
3984 Register result = ToRegister(instr->result()); 3984 Register result = ToRegister(instr->result());
3985 X87Fxch(input_reg); 3985 X87Fxch(input_reg);
(...skipping 13 matching lines...) Expand all
3999 __ fadd_d(Operand::StaticVariable(one_half)); 3999 __ fadd_d(Operand::StaticVariable(one_half));
4000 // rc=11B, round toward zero. 4000 // rc=11B, round toward zero.
4001 __ X87SetRC(0x0c00); 4001 __ X87SetRC(0x0c00);
4002 __ sub(esp, Immediate(kPointerSize)); 4002 __ sub(esp, Immediate(kPointerSize));
4003 // Clear exception bits. 4003 // Clear exception bits.
4004 __ fnclex(); 4004 __ fnclex();
4005 __ fistp_s(MemOperand(esp, 0)); 4005 __ fistp_s(MemOperand(esp, 0));
4006 // Check overflow. 4006 // Check overflow.
4007 __ X87CheckIA(); 4007 __ X87CheckIA();
4008 __ pop(result); 4008 __ pop(result);
4009 DeoptimizeIf(equal, instr, "conversion overflow"); 4009 DeoptimizeIf(equal, instr, Deoptimizer::kConversionOverflow);
4010 __ fnclex(); 4010 __ fnclex();
4011 // Restore round mode. 4011 // Restore round mode.
4012 __ X87SetRC(0x0000); 4012 __ X87SetRC(0x0000);
4013 __ jmp(&done); 4013 __ jmp(&done);
4014 4014
4015 __ bind(&below_one_half); 4015 __ bind(&below_one_half);
4016 __ fld_d(Operand::StaticVariable(minus_one_half)); 4016 __ fld_d(Operand::StaticVariable(minus_one_half));
4017 __ fld(1); 4017 __ fld(1);
4018 __ FCmp(); 4018 __ FCmp();
4019 __ j(carry, &below_minus_one_half); 4019 __ j(carry, &below_minus_one_half);
4020 // We return 0 for the input range [+0, 0.5[, or [-0.5, 0.5[ if 4020 // We return 0 for the input range [+0, 0.5[, or [-0.5, 0.5[ if
4021 // we can ignore the difference between a result of -0 and +0. 4021 // we can ignore the difference between a result of -0 and +0.
4022 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 4022 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
4023 // If the sign is positive, we return +0. 4023 // If the sign is positive, we return +0.
4024 __ fld(0); 4024 __ fld(0);
4025 __ FXamSign(); 4025 __ FXamSign();
4026 DeoptimizeIf(not_zero, instr, "minus zero"); 4026 DeoptimizeIf(not_zero, instr, Deoptimizer::kMinusZero);
4027 } 4027 }
4028 __ Move(result, Immediate(0)); 4028 __ Move(result, Immediate(0));
4029 __ jmp(&done); 4029 __ jmp(&done);
4030 4030
4031 __ bind(&below_minus_one_half); 4031 __ bind(&below_minus_one_half);
4032 __ fld(0); 4032 __ fld(0);
4033 __ fadd_d(Operand::StaticVariable(one_half)); 4033 __ fadd_d(Operand::StaticVariable(one_half));
4034 // rc=01B, round down. 4034 // rc=01B, round down.
4035 __ X87SetRC(0x0400); 4035 __ X87SetRC(0x0400);
4036 __ sub(esp, Immediate(kPointerSize)); 4036 __ sub(esp, Immediate(kPointerSize));
4037 // Clear exception bits. 4037 // Clear exception bits.
4038 __ fnclex(); 4038 __ fnclex();
4039 __ fistp_s(MemOperand(esp, 0)); 4039 __ fistp_s(MemOperand(esp, 0));
4040 // Check overflow. 4040 // Check overflow.
4041 __ X87CheckIA(); 4041 __ X87CheckIA();
4042 __ pop(result); 4042 __ pop(result);
4043 DeoptimizeIf(equal, instr, "conversion overflow"); 4043 DeoptimizeIf(equal, instr, Deoptimizer::kConversionOverflow);
4044 __ fnclex(); 4044 __ fnclex();
4045 // Restore round mode. 4045 // Restore round mode.
4046 __ X87SetRC(0x0000); 4046 __ X87SetRC(0x0000);
4047 4047
4048 __ bind(&done); 4048 __ bind(&done);
4049 } 4049 }
4050 4050
4051 4051
4052 void LCodeGen::DoMathFround(LMathFround* instr) { 4052 void LCodeGen::DoMathFround(LMathFround* instr) {
4053 X87Register input_reg = ToX87Register(instr->value()); 4053 X87Register input_reg = ToX87Register(instr->value());
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
4165 __ push(exponent); 4165 __ push(exponent);
4166 __ fild_s(MemOperand(esp, 0)); 4166 __ fild_s(MemOperand(esp, 0));
4167 __ pop(exponent); 4167 __ pop(exponent);
4168 } else if (exponent_type.IsTagged()) { 4168 } else if (exponent_type.IsTagged()) {
4169 Register exponent = ToRegister(instr->right()); 4169 Register exponent = ToRegister(instr->right());
4170 Register temp = exponent.is(ecx) ? eax : ecx; 4170 Register temp = exponent.is(ecx) ? eax : ecx;
4171 Label no_deopt, done; 4171 Label no_deopt, done;
4172 X87LoadForUsage(base); 4172 X87LoadForUsage(base);
4173 __ JumpIfSmi(exponent, &no_deopt); 4173 __ JumpIfSmi(exponent, &no_deopt);
4174 __ CmpObjectType(exponent, HEAP_NUMBER_TYPE, temp); 4174 __ CmpObjectType(exponent, HEAP_NUMBER_TYPE, temp);
4175 DeoptimizeIf(not_equal, instr, "not a heap number"); 4175 DeoptimizeIf(not_equal, instr, Deoptimizer::kNotAHeapNumber);
4176 // Heap number(double) 4176 // Heap number(double)
4177 __ fld_d(FieldOperand(exponent, HeapNumber::kValueOffset)); 4177 __ fld_d(FieldOperand(exponent, HeapNumber::kValueOffset));
4178 __ jmp(&done); 4178 __ jmp(&done);
4179 // SMI 4179 // SMI
4180 __ bind(&no_deopt); 4180 __ bind(&no_deopt);
4181 __ SmiUntag(exponent); 4181 __ SmiUntag(exponent);
4182 __ push(exponent); 4182 __ push(exponent);
4183 __ fild_s(MemOperand(esp, 0)); 4183 __ fild_s(MemOperand(esp, 0));
4184 __ pop(exponent); 4184 __ pop(exponent);
4185 __ bind(&done); 4185 __ bind(&done);
(...skipping 381 matching lines...) Expand 10 before | Expand all | Expand 10 after
4567 instr->hydrogen()->index()->representation())); 4567 instr->hydrogen()->index()->representation()));
4568 } else { 4568 } else {
4569 __ cmp(ToRegister(instr->index()), ToOperand(instr->length())); 4569 __ cmp(ToRegister(instr->index()), ToOperand(instr->length()));
4570 } 4570 }
4571 if (FLAG_debug_code && instr->hydrogen()->skip_check()) { 4571 if (FLAG_debug_code && instr->hydrogen()->skip_check()) {
4572 Label done; 4572 Label done;
4573 __ j(NegateCondition(cc), &done, Label::kNear); 4573 __ j(NegateCondition(cc), &done, Label::kNear);
4574 __ int3(); 4574 __ int3();
4575 __ bind(&done); 4575 __ bind(&done);
4576 } else { 4576 } else {
4577 DeoptimizeIf(cc, instr, "out of bounds"); 4577 DeoptimizeIf(cc, instr, Deoptimizer::kOutOfBounds);
4578 } 4578 }
4579 } 4579 }
4580 4580
4581 4581
4582 void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) { 4582 void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) {
4583 ElementsKind elements_kind = instr->elements_kind(); 4583 ElementsKind elements_kind = instr->elements_kind();
4584 LOperand* key = instr->key(); 4584 LOperand* key = instr->key();
4585 if (!key->IsConstantOperand() && 4585 if (!key->IsConstantOperand() &&
4586 ExternalArrayOpRequiresTemp(instr->hydrogen()->key()->representation(), 4586 ExternalArrayOpRequiresTemp(instr->hydrogen()->key()->representation(),
4587 elements_kind)) { 4587 elements_kind)) {
(...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after
4758 CodeFactory::KeyedStoreIC(isolate(), instr->strict_mode()).code(); 4758 CodeFactory::KeyedStoreIC(isolate(), instr->strict_mode()).code();
4759 CallCode(ic, RelocInfo::CODE_TARGET, instr); 4759 CallCode(ic, RelocInfo::CODE_TARGET, instr);
4760 } 4760 }
4761 4761
4762 4762
4763 void LCodeGen::DoTrapAllocationMemento(LTrapAllocationMemento* instr) { 4763 void LCodeGen::DoTrapAllocationMemento(LTrapAllocationMemento* instr) {
4764 Register object = ToRegister(instr->object()); 4764 Register object = ToRegister(instr->object());
4765 Register temp = ToRegister(instr->temp()); 4765 Register temp = ToRegister(instr->temp());
4766 Label no_memento_found; 4766 Label no_memento_found;
4767 __ TestJSArrayForAllocationMemento(object, temp, &no_memento_found); 4767 __ TestJSArrayForAllocationMemento(object, temp, &no_memento_found);
4768 DeoptimizeIf(equal, instr, "memento found"); 4768 DeoptimizeIf(equal, instr, Deoptimizer::kMementoFound);
4769 __ bind(&no_memento_found); 4769 __ bind(&no_memento_found);
4770 } 4770 }
4771 4771
4772 4772
4773 void LCodeGen::DoTransitionElementsKind(LTransitionElementsKind* instr) { 4773 void LCodeGen::DoTransitionElementsKind(LTransitionElementsKind* instr) {
4774 Register object_reg = ToRegister(instr->object()); 4774 Register object_reg = ToRegister(instr->object());
4775 4775
4776 Handle<Map> from_map = instr->original_map(); 4776 Handle<Map> from_map = instr->original_map();
4777 Handle<Map> to_map = instr->transitioned_map(); 4777 Handle<Map> to_map = instr->transitioned_map();
4778 ElementsKind from_kind = instr->from_kind(); 4778 ElementsKind from_kind = instr->from_kind();
(...skipping 351 matching lines...) Expand 10 before | Expand all | Expand 10 after
5130 __ StoreToSafepointRegisterSlot(reg, eax); 5130 __ StoreToSafepointRegisterSlot(reg, eax);
5131 } 5131 }
5132 5132
5133 5133
5134 void LCodeGen::DoSmiTag(LSmiTag* instr) { 5134 void LCodeGen::DoSmiTag(LSmiTag* instr) {
5135 HChange* hchange = instr->hydrogen(); 5135 HChange* hchange = instr->hydrogen();
5136 Register input = ToRegister(instr->value()); 5136 Register input = ToRegister(instr->value());
5137 if (hchange->CheckFlag(HValue::kCanOverflow) && 5137 if (hchange->CheckFlag(HValue::kCanOverflow) &&
5138 hchange->value()->CheckFlag(HValue::kUint32)) { 5138 hchange->value()->CheckFlag(HValue::kUint32)) {
5139 __ test(input, Immediate(0xc0000000)); 5139 __ test(input, Immediate(0xc0000000));
5140 DeoptimizeIf(not_zero, instr, "overflow"); 5140 DeoptimizeIf(not_zero, instr, Deoptimizer::kOverflow);
5141 } 5141 }
5142 __ SmiTag(input); 5142 __ SmiTag(input);
5143 if (hchange->CheckFlag(HValue::kCanOverflow) && 5143 if (hchange->CheckFlag(HValue::kCanOverflow) &&
5144 !hchange->value()->CheckFlag(HValue::kUint32)) { 5144 !hchange->value()->CheckFlag(HValue::kUint32)) {
5145 DeoptimizeIf(overflow, instr, "overflow"); 5145 DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow);
5146 } 5146 }
5147 } 5147 }
5148 5148
5149 5149
5150 void LCodeGen::DoSmiUntag(LSmiUntag* instr) { 5150 void LCodeGen::DoSmiUntag(LSmiUntag* instr) {
5151 LOperand* input = instr->value(); 5151 LOperand* input = instr->value();
5152 Register result = ToRegister(input); 5152 Register result = ToRegister(input);
5153 DCHECK(input->IsRegister() && input->Equals(instr->result())); 5153 DCHECK(input->IsRegister() && input->Equals(instr->result()));
5154 if (instr->needs_check()) { 5154 if (instr->needs_check()) {
5155 __ test(result, Immediate(kSmiTagMask)); 5155 __ test(result, Immediate(kSmiTagMask));
5156 DeoptimizeIf(not_zero, instr, "not a Smi"); 5156 DeoptimizeIf(not_zero, instr, Deoptimizer::kNotASmi);
5157 } else { 5157 } else {
5158 __ AssertSmi(result); 5158 __ AssertSmi(result);
5159 } 5159 }
5160 __ SmiUntag(result); 5160 __ SmiUntag(result);
5161 } 5161 }
5162 5162
5163 5163
5164 void LCodeGen::EmitNumberUntagDNoSSE2(LNumberUntagD* instr, Register input_reg, 5164 void LCodeGen::EmitNumberUntagDNoSSE2(LNumberUntagD* instr, Register input_reg,
5165 Register temp_reg, X87Register res_reg, 5165 Register temp_reg, X87Register res_reg,
5166 NumberUntagDMode mode) { 5166 NumberUntagDMode mode) {
5167 bool can_convert_undefined_to_nan = 5167 bool can_convert_undefined_to_nan =
5168 instr->hydrogen()->can_convert_undefined_to_nan(); 5168 instr->hydrogen()->can_convert_undefined_to_nan();
5169 bool deoptimize_on_minus_zero = instr->hydrogen()->deoptimize_on_minus_zero(); 5169 bool deoptimize_on_minus_zero = instr->hydrogen()->deoptimize_on_minus_zero();
5170 5170
5171 Label load_smi, done; 5171 Label load_smi, done;
5172 5172
5173 X87PrepareToWrite(res_reg); 5173 X87PrepareToWrite(res_reg);
5174 if (mode == NUMBER_CANDIDATE_IS_ANY_TAGGED) { 5174 if (mode == NUMBER_CANDIDATE_IS_ANY_TAGGED) {
5175 // Smi check. 5175 // Smi check.
5176 __ JumpIfSmi(input_reg, &load_smi); 5176 __ JumpIfSmi(input_reg, &load_smi);
5177 5177
5178 // Heap number map check. 5178 // Heap number map check.
5179 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), 5179 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset),
5180 factory()->heap_number_map()); 5180 factory()->heap_number_map());
5181 if (!can_convert_undefined_to_nan) { 5181 if (!can_convert_undefined_to_nan) {
5182 DeoptimizeIf(not_equal, instr, "not a heap number"); 5182 DeoptimizeIf(not_equal, instr, Deoptimizer::kNotAHeapNumber);
5183 } else { 5183 } else {
5184 Label heap_number, convert; 5184 Label heap_number, convert;
5185 __ j(equal, &heap_number); 5185 __ j(equal, &heap_number);
5186 5186
5187 // Convert undefined (or hole) to NaN. 5187 // Convert undefined (or hole) to NaN.
5188 __ cmp(input_reg, factory()->undefined_value()); 5188 __ cmp(input_reg, factory()->undefined_value());
5189 DeoptimizeIf(not_equal, instr, "not a heap number/undefined"); 5189 DeoptimizeIf(not_equal, instr, Deoptimizer::kNotAHeapNumberUndefined);
5190 5190
5191 __ bind(&convert); 5191 __ bind(&convert);
5192 __ push(Immediate(0xffffffff)); 5192 __ push(Immediate(0xffffffff));
5193 __ push(Immediate(0x7fffffff)); 5193 __ push(Immediate(0x7fffffff));
5194 __ fld_d(MemOperand(esp, 0)); 5194 __ fld_d(MemOperand(esp, 0));
5195 __ lea(esp, Operand(esp, kDoubleSize)); 5195 __ lea(esp, Operand(esp, kDoubleSize));
5196 __ jmp(&done, Label::kNear); 5196 __ jmp(&done, Label::kNear);
5197 5197
5198 __ bind(&heap_number); 5198 __ bind(&heap_number);
5199 } 5199 }
5200 // Heap number to x87 conversion. 5200 // Heap number to x87 conversion.
5201 __ fld_d(FieldOperand(input_reg, HeapNumber::kValueOffset)); 5201 __ fld_d(FieldOperand(input_reg, HeapNumber::kValueOffset));
5202 if (deoptimize_on_minus_zero) { 5202 if (deoptimize_on_minus_zero) {
5203 __ fldz(); 5203 __ fldz();
5204 __ FCmp(); 5204 __ FCmp();
5205 __ fld_d(FieldOperand(input_reg, HeapNumber::kValueOffset)); 5205 __ fld_d(FieldOperand(input_reg, HeapNumber::kValueOffset));
5206 __ j(not_zero, &done, Label::kNear); 5206 __ j(not_zero, &done, Label::kNear);
5207 5207
5208 // Use general purpose registers to check if we have -0.0 5208 // Use general purpose registers to check if we have -0.0
5209 __ mov(temp_reg, FieldOperand(input_reg, HeapNumber::kExponentOffset)); 5209 __ mov(temp_reg, FieldOperand(input_reg, HeapNumber::kExponentOffset));
5210 __ test(temp_reg, Immediate(HeapNumber::kSignMask)); 5210 __ test(temp_reg, Immediate(HeapNumber::kSignMask));
5211 __ j(zero, &done, Label::kNear); 5211 __ j(zero, &done, Label::kNear);
5212 5212
5213 // Pop FPU stack before deoptimizing. 5213 // Pop FPU stack before deoptimizing.
5214 __ fstp(0); 5214 __ fstp(0);
5215 DeoptimizeIf(not_zero, instr, "minus zero"); 5215 DeoptimizeIf(not_zero, instr, Deoptimizer::kMinusZero);
5216 } 5216 }
5217 __ jmp(&done, Label::kNear); 5217 __ jmp(&done, Label::kNear);
5218 } else { 5218 } else {
5219 DCHECK(mode == NUMBER_CANDIDATE_IS_SMI); 5219 DCHECK(mode == NUMBER_CANDIDATE_IS_SMI);
5220 } 5220 }
5221 5221
5222 __ bind(&load_smi); 5222 __ bind(&load_smi);
5223 // Clobbering a temp is faster than re-tagging the 5223 // Clobbering a temp is faster than re-tagging the
5224 // input register since we avoid dependencies. 5224 // input register since we avoid dependencies.
5225 __ mov(temp_reg, input_reg); 5225 __ mov(temp_reg, input_reg);
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
5258 __ jmp(done); 5258 __ jmp(done);
5259 5259
5260 __ bind(&check_bools); 5260 __ bind(&check_bools);
5261 __ cmp(input_reg, factory()->true_value()); 5261 __ cmp(input_reg, factory()->true_value());
5262 __ j(not_equal, &check_false, Label::kNear); 5262 __ j(not_equal, &check_false, Label::kNear);
5263 __ Move(input_reg, Immediate(1)); 5263 __ Move(input_reg, Immediate(1));
5264 __ jmp(done); 5264 __ jmp(done);
5265 5265
5266 __ bind(&check_false); 5266 __ bind(&check_false);
5267 __ cmp(input_reg, factory()->false_value()); 5267 __ cmp(input_reg, factory()->false_value());
5268 DeoptimizeIf(not_equal, instr, "not a heap number/undefined/true/false"); 5268 DeoptimizeIf(not_equal, instr,
5269 Deoptimizer::kNotAHeapNumberUndefinedTrueFalse);
5269 __ Move(input_reg, Immediate(0)); 5270 __ Move(input_reg, Immediate(0));
5270 } else { 5271 } else {
5271 // TODO(olivf) Converting a number on the fpu is actually quite slow. We 5272 // TODO(olivf) Converting a number on the fpu is actually quite slow. We
5272 // should first try a fast conversion and then bailout to this slow case. 5273 // should first try a fast conversion and then bailout to this slow case.
5273 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), 5274 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset),
5274 isolate()->factory()->heap_number_map()); 5275 isolate()->factory()->heap_number_map());
5275 DeoptimizeIf(not_equal, instr, "not a heap number"); 5276 DeoptimizeIf(not_equal, instr, Deoptimizer::kNotAHeapNumber);
5276 5277
5277 __ sub(esp, Immediate(kPointerSize)); 5278 __ sub(esp, Immediate(kPointerSize));
5278 __ fld_d(FieldOperand(input_reg, HeapNumber::kValueOffset)); 5279 __ fld_d(FieldOperand(input_reg, HeapNumber::kValueOffset));
5279 5280
5280 if (instr->hydrogen()->GetMinusZeroMode() == FAIL_ON_MINUS_ZERO) { 5281 if (instr->hydrogen()->GetMinusZeroMode() == FAIL_ON_MINUS_ZERO) {
5281 Label no_precision_lost, not_nan, zero_check; 5282 Label no_precision_lost, not_nan, zero_check;
5282 __ fld(0); 5283 __ fld(0);
5283 5284
5284 __ fist_s(MemOperand(esp, 0)); 5285 __ fist_s(MemOperand(esp, 0));
5285 __ fild_s(MemOperand(esp, 0)); 5286 __ fild_s(MemOperand(esp, 0));
5286 __ FCmp(); 5287 __ FCmp();
5287 __ pop(input_reg); 5288 __ pop(input_reg);
5288 5289
5289 __ j(equal, &no_precision_lost, Label::kNear); 5290 __ j(equal, &no_precision_lost, Label::kNear);
5290 __ fstp(0); 5291 __ fstp(0);
5291 DeoptimizeIf(no_condition, instr, "lost precision"); 5292 DeoptimizeIf(no_condition, instr, Deoptimizer::kLostPrecision);
5292 __ bind(&no_precision_lost); 5293 __ bind(&no_precision_lost);
5293 5294
5294 __ j(parity_odd, &not_nan); 5295 __ j(parity_odd, &not_nan);
5295 __ fstp(0); 5296 __ fstp(0);
5296 DeoptimizeIf(no_condition, instr, "NaN"); 5297 DeoptimizeIf(no_condition, instr, Deoptimizer::kNaN);
5297 __ bind(&not_nan); 5298 __ bind(&not_nan);
5298 5299
5299 __ test(input_reg, Operand(input_reg)); 5300 __ test(input_reg, Operand(input_reg));
5300 __ j(zero, &zero_check, Label::kNear); 5301 __ j(zero, &zero_check, Label::kNear);
5301 __ fstp(0); 5302 __ fstp(0);
5302 __ jmp(done); 5303 __ jmp(done);
5303 5304
5304 __ bind(&zero_check); 5305 __ bind(&zero_check);
5305 // To check for minus zero, we load the value again as float, and check 5306 // To check for minus zero, we load the value again as float, and check
5306 // if that is still 0. 5307 // if that is still 0.
5307 __ sub(esp, Immediate(kPointerSize)); 5308 __ sub(esp, Immediate(kPointerSize));
5308 __ fstp_s(Operand(esp, 0)); 5309 __ fstp_s(Operand(esp, 0));
5309 __ pop(input_reg); 5310 __ pop(input_reg);
5310 __ test(input_reg, Operand(input_reg)); 5311 __ test(input_reg, Operand(input_reg));
5311 DeoptimizeIf(not_zero, instr, "minus zero"); 5312 DeoptimizeIf(not_zero, instr, Deoptimizer::kMinusZero);
5312 } else { 5313 } else {
5313 __ fist_s(MemOperand(esp, 0)); 5314 __ fist_s(MemOperand(esp, 0));
5314 __ fild_s(MemOperand(esp, 0)); 5315 __ fild_s(MemOperand(esp, 0));
5315 __ FCmp(); 5316 __ FCmp();
5316 __ pop(input_reg); 5317 __ pop(input_reg);
5317 DeoptimizeIf(not_equal, instr, "lost precision"); 5318 DeoptimizeIf(not_equal, instr, Deoptimizer::kLostPrecision);
5318 DeoptimizeIf(parity_even, instr, "NaN"); 5319 DeoptimizeIf(parity_even, instr, Deoptimizer::kNaN);
5319 } 5320 }
5320 } 5321 }
5321 } 5322 }
5322 5323
5323 5324
5324 void LCodeGen::DoTaggedToI(LTaggedToI* instr) { 5325 void LCodeGen::DoTaggedToI(LTaggedToI* instr) {
5325 class DeferredTaggedToI FINAL : public LDeferredCode { 5326 class DeferredTaggedToI FINAL : public LDeferredCode {
5326 public: 5327 public:
5327 DeferredTaggedToI(LCodeGen* codegen, 5328 DeferredTaggedToI(LCodeGen* codegen,
5328 LTaggedToI* instr, 5329 LTaggedToI* instr,
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
5389 X87Fxch(input_reg); 5390 X87Fxch(input_reg);
5390 __ TruncateX87TOSToI(result_reg); 5391 __ TruncateX87TOSToI(result_reg);
5391 } else { 5392 } else {
5392 Label lost_precision, is_nan, minus_zero, done; 5393 Label lost_precision, is_nan, minus_zero, done;
5393 X87Register input_reg = ToX87Register(input); 5394 X87Register input_reg = ToX87Register(input);
5394 X87Fxch(input_reg); 5395 X87Fxch(input_reg);
5395 __ X87TOSToI(result_reg, instr->hydrogen()->GetMinusZeroMode(), 5396 __ X87TOSToI(result_reg, instr->hydrogen()->GetMinusZeroMode(),
5396 &lost_precision, &is_nan, &minus_zero); 5397 &lost_precision, &is_nan, &minus_zero);
5397 __ jmp(&done); 5398 __ jmp(&done);
5398 __ bind(&lost_precision); 5399 __ bind(&lost_precision);
5399 DeoptimizeIf(no_condition, instr, "lost precision"); 5400 DeoptimizeIf(no_condition, instr, Deoptimizer::kLostPrecision);
5400 __ bind(&is_nan); 5401 __ bind(&is_nan);
5401 DeoptimizeIf(no_condition, instr, "NaN"); 5402 DeoptimizeIf(no_condition, instr, Deoptimizer::kNaN);
5402 __ bind(&minus_zero); 5403 __ bind(&minus_zero);
5403 DeoptimizeIf(no_condition, instr, "minus zero"); 5404 DeoptimizeIf(no_condition, instr, Deoptimizer::kMinusZero);
5404 __ bind(&done); 5405 __ bind(&done);
5405 } 5406 }
5406 } 5407 }
5407 5408
5408 5409
5409 void LCodeGen::DoDoubleToSmi(LDoubleToSmi* instr) { 5410 void LCodeGen::DoDoubleToSmi(LDoubleToSmi* instr) {
5410 LOperand* input = instr->value(); 5411 LOperand* input = instr->value();
5411 DCHECK(input->IsDoubleRegister()); 5412 DCHECK(input->IsDoubleRegister());
5412 LOperand* result = instr->result(); 5413 LOperand* result = instr->result();
5413 DCHECK(result->IsRegister()); 5414 DCHECK(result->IsRegister());
5414 Register result_reg = ToRegister(result); 5415 Register result_reg = ToRegister(result);
5415 5416
5416 Label lost_precision, is_nan, minus_zero, done; 5417 Label lost_precision, is_nan, minus_zero, done;
5417 X87Register input_reg = ToX87Register(input); 5418 X87Register input_reg = ToX87Register(input);
5418 X87Fxch(input_reg); 5419 X87Fxch(input_reg);
5419 __ X87TOSToI(result_reg, instr->hydrogen()->GetMinusZeroMode(), 5420 __ X87TOSToI(result_reg, instr->hydrogen()->GetMinusZeroMode(),
5420 &lost_precision, &is_nan, &minus_zero); 5421 &lost_precision, &is_nan, &minus_zero);
5421 __ jmp(&done); 5422 __ jmp(&done);
5422 __ bind(&lost_precision); 5423 __ bind(&lost_precision);
5423 DeoptimizeIf(no_condition, instr, "lost precision"); 5424 DeoptimizeIf(no_condition, instr, Deoptimizer::kLostPrecision);
5424 __ bind(&is_nan); 5425 __ bind(&is_nan);
5425 DeoptimizeIf(no_condition, instr, "NaN"); 5426 DeoptimizeIf(no_condition, instr, Deoptimizer::kNaN);
5426 __ bind(&minus_zero); 5427 __ bind(&minus_zero);
5427 DeoptimizeIf(no_condition, instr, "minus zero"); 5428 DeoptimizeIf(no_condition, instr, Deoptimizer::kMinusZero);
5428 __ bind(&done); 5429 __ bind(&done);
5429 __ SmiTag(result_reg); 5430 __ SmiTag(result_reg);
5430 DeoptimizeIf(overflow, instr, "overflow"); 5431 DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow);
5431 } 5432 }
5432 5433
5433 5434
5434 void LCodeGen::DoCheckSmi(LCheckSmi* instr) { 5435 void LCodeGen::DoCheckSmi(LCheckSmi* instr) {
5435 LOperand* input = instr->value(); 5436 LOperand* input = instr->value();
5436 __ test(ToOperand(input), Immediate(kSmiTagMask)); 5437 __ test(ToOperand(input), Immediate(kSmiTagMask));
5437 DeoptimizeIf(not_zero, instr, "not a Smi"); 5438 DeoptimizeIf(not_zero, instr, Deoptimizer::kNotASmi);
5438 } 5439 }
5439 5440
5440 5441
5441 void LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) { 5442 void LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) {
5442 if (!instr->hydrogen()->value()->type().IsHeapObject()) { 5443 if (!instr->hydrogen()->value()->type().IsHeapObject()) {
5443 LOperand* input = instr->value(); 5444 LOperand* input = instr->value();
5444 __ test(ToOperand(input), Immediate(kSmiTagMask)); 5445 __ test(ToOperand(input), Immediate(kSmiTagMask));
5445 DeoptimizeIf(zero, instr, "Smi"); 5446 DeoptimizeIf(zero, instr, Deoptimizer::kSmi);
5446 } 5447 }
5447 } 5448 }
5448 5449
5449 5450
5450 void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) { 5451 void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) {
5451 Register input = ToRegister(instr->value()); 5452 Register input = ToRegister(instr->value());
5452 Register temp = ToRegister(instr->temp()); 5453 Register temp = ToRegister(instr->temp());
5453 5454
5454 __ mov(temp, FieldOperand(input, HeapObject::kMapOffset)); 5455 __ mov(temp, FieldOperand(input, HeapObject::kMapOffset));
5455 5456
5456 if (instr->hydrogen()->is_interval_check()) { 5457 if (instr->hydrogen()->is_interval_check()) {
5457 InstanceType first; 5458 InstanceType first;
5458 InstanceType last; 5459 InstanceType last;
5459 instr->hydrogen()->GetCheckInterval(&first, &last); 5460 instr->hydrogen()->GetCheckInterval(&first, &last);
5460 5461
5461 __ cmpb(FieldOperand(temp, Map::kInstanceTypeOffset), 5462 __ cmpb(FieldOperand(temp, Map::kInstanceTypeOffset),
5462 static_cast<int8_t>(first)); 5463 static_cast<int8_t>(first));
5463 5464
5464 // If there is only one type in the interval check for equality. 5465 // If there is only one type in the interval check for equality.
5465 if (first == last) { 5466 if (first == last) {
5466 DeoptimizeIf(not_equal, instr, "wrong instance type"); 5467 DeoptimizeIf(not_equal, instr, Deoptimizer::kWrongInstanceType);
5467 } else { 5468 } else {
5468 DeoptimizeIf(below, instr, "wrong instance type"); 5469 DeoptimizeIf(below, instr, Deoptimizer::kWrongInstanceType);
5469 // Omit check for the last type. 5470 // Omit check for the last type.
5470 if (last != LAST_TYPE) { 5471 if (last != LAST_TYPE) {
5471 __ cmpb(FieldOperand(temp, Map::kInstanceTypeOffset), 5472 __ cmpb(FieldOperand(temp, Map::kInstanceTypeOffset),
5472 static_cast<int8_t>(last)); 5473 static_cast<int8_t>(last));
5473 DeoptimizeIf(above, instr, "wrong instance type"); 5474 DeoptimizeIf(above, instr, Deoptimizer::kWrongInstanceType);
5474 } 5475 }
5475 } 5476 }
5476 } else { 5477 } else {
5477 uint8_t mask; 5478 uint8_t mask;
5478 uint8_t tag; 5479 uint8_t tag;
5479 instr->hydrogen()->GetCheckMaskAndTag(&mask, &tag); 5480 instr->hydrogen()->GetCheckMaskAndTag(&mask, &tag);
5480 5481
5481 if (base::bits::IsPowerOfTwo32(mask)) { 5482 if (base::bits::IsPowerOfTwo32(mask)) {
5482 DCHECK(tag == 0 || base::bits::IsPowerOfTwo32(tag)); 5483 DCHECK(tag == 0 || base::bits::IsPowerOfTwo32(tag));
5483 __ test_b(FieldOperand(temp, Map::kInstanceTypeOffset), mask); 5484 __ test_b(FieldOperand(temp, Map::kInstanceTypeOffset), mask);
5484 DeoptimizeIf(tag == 0 ? not_zero : zero, instr, "wrong instance type"); 5485 DeoptimizeIf(tag == 0 ? not_zero : zero, instr,
5486 Deoptimizer::kWrongInstanceType);
5485 } else { 5487 } else {
5486 __ movzx_b(temp, FieldOperand(temp, Map::kInstanceTypeOffset)); 5488 __ movzx_b(temp, FieldOperand(temp, Map::kInstanceTypeOffset));
5487 __ and_(temp, mask); 5489 __ and_(temp, mask);
5488 __ cmp(temp, tag); 5490 __ cmp(temp, tag);
5489 DeoptimizeIf(not_equal, instr, "wrong instance type"); 5491 DeoptimizeIf(not_equal, instr, Deoptimizer::kWrongInstanceType);
5490 } 5492 }
5491 } 5493 }
5492 } 5494 }
5493 5495
5494 5496
5495 void LCodeGen::DoCheckValue(LCheckValue* instr) { 5497 void LCodeGen::DoCheckValue(LCheckValue* instr) {
5496 Handle<HeapObject> object = instr->hydrogen()->object().handle(); 5498 Handle<HeapObject> object = instr->hydrogen()->object().handle();
5497 if (instr->hydrogen()->object_in_new_space()) { 5499 if (instr->hydrogen()->object_in_new_space()) {
5498 Register reg = ToRegister(instr->value()); 5500 Register reg = ToRegister(instr->value());
5499 Handle<Cell> cell = isolate()->factory()->NewCell(object); 5501 Handle<Cell> cell = isolate()->factory()->NewCell(object);
5500 __ cmp(reg, Operand::ForCell(cell)); 5502 __ cmp(reg, Operand::ForCell(cell));
5501 } else { 5503 } else {
5502 Operand operand = ToOperand(instr->value()); 5504 Operand operand = ToOperand(instr->value());
5503 __ cmp(operand, object); 5505 __ cmp(operand, object);
5504 } 5506 }
5505 DeoptimizeIf(not_equal, instr, "value mismatch"); 5507 DeoptimizeIf(not_equal, instr, Deoptimizer::kValueMismatch);
5506 } 5508 }
5507 5509
5508 5510
5509 void LCodeGen::DoDeferredInstanceMigration(LCheckMaps* instr, Register object) { 5511 void LCodeGen::DoDeferredInstanceMigration(LCheckMaps* instr, Register object) {
5510 { 5512 {
5511 PushSafepointRegistersScope scope(this); 5513 PushSafepointRegistersScope scope(this);
5512 __ push(object); 5514 __ push(object);
5513 __ xor_(esi, esi); 5515 __ xor_(esi, esi);
5514 __ CallRuntimeSaveDoubles(Runtime::kTryMigrateInstance); 5516 __ CallRuntimeSaveDoubles(Runtime::kTryMigrateInstance);
5515 RecordSafepointWithRegisters( 5517 RecordSafepointWithRegisters(
5516 instr->pointer_map(), 1, Safepoint::kNoLazyDeopt); 5518 instr->pointer_map(), 1, Safepoint::kNoLazyDeopt);
5517 5519
5518 __ test(eax, Immediate(kSmiTagMask)); 5520 __ test(eax, Immediate(kSmiTagMask));
5519 } 5521 }
5520 DeoptimizeIf(zero, instr, "instance migration failed"); 5522 DeoptimizeIf(zero, instr, Deoptimizer::kInstanceMigrationFailed);
5521 } 5523 }
5522 5524
5523 5525
5524 void LCodeGen::DoCheckMaps(LCheckMaps* instr) { 5526 void LCodeGen::DoCheckMaps(LCheckMaps* instr) {
5525 class DeferredCheckMaps FINAL : public LDeferredCode { 5527 class DeferredCheckMaps FINAL : public LDeferredCode {
5526 public: 5528 public:
5527 DeferredCheckMaps(LCodeGen* codegen, 5529 DeferredCheckMaps(LCodeGen* codegen,
5528 LCheckMaps* instr, 5530 LCheckMaps* instr,
5529 Register object, 5531 Register object,
5530 const X87Stack& x87_stack) 5532 const X87Stack& x87_stack)
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
5567 Handle<Map> map = maps->at(i).handle(); 5569 Handle<Map> map = maps->at(i).handle();
5568 __ CompareMap(reg, map); 5570 __ CompareMap(reg, map);
5569 __ j(equal, &success, Label::kNear); 5571 __ j(equal, &success, Label::kNear);
5570 } 5572 }
5571 5573
5572 Handle<Map> map = maps->at(maps->size() - 1).handle(); 5574 Handle<Map> map = maps->at(maps->size() - 1).handle();
5573 __ CompareMap(reg, map); 5575 __ CompareMap(reg, map);
5574 if (instr->hydrogen()->HasMigrationTarget()) { 5576 if (instr->hydrogen()->HasMigrationTarget()) {
5575 __ j(not_equal, deferred->entry()); 5577 __ j(not_equal, deferred->entry());
5576 } else { 5578 } else {
5577 DeoptimizeIf(not_equal, instr, "wrong map"); 5579 DeoptimizeIf(not_equal, instr, Deoptimizer::kWrongMap);
5578 } 5580 }
5579 5581
5580 __ bind(&success); 5582 __ bind(&success);
5581 } 5583 }
5582 5584
5583 5585
5584 void LCodeGen::DoClampDToUint8(LClampDToUint8* instr) { 5586 void LCodeGen::DoClampDToUint8(LClampDToUint8* instr) {
5585 X87Register value_reg = ToX87Register(instr->unclamped()); 5587 X87Register value_reg = ToX87Register(instr->unclamped());
5586 Register result_reg = ToRegister(instr->result()); 5588 Register result_reg = ToRegister(instr->result());
5587 X87Fxch(value_reg); 5589 X87Fxch(value_reg);
(...skipping 20 matching lines...) Expand all
5608 __ JumpIfSmi(input_reg, &is_smi); 5610 __ JumpIfSmi(input_reg, &is_smi);
5609 5611
5610 // Check for heap number 5612 // Check for heap number
5611 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), 5613 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset),
5612 factory()->heap_number_map()); 5614 factory()->heap_number_map());
5613 __ j(equal, &heap_number, Label::kNear); 5615 __ j(equal, &heap_number, Label::kNear);
5614 5616
5615 // Check for undefined. Undefined is converted to zero for clamping 5617 // Check for undefined. Undefined is converted to zero for clamping
5616 // conversions. 5618 // conversions.
5617 __ cmp(input_reg, factory()->undefined_value()); 5619 __ cmp(input_reg, factory()->undefined_value());
5618 DeoptimizeIf(not_equal, instr, "not a heap number/undefined"); 5620 DeoptimizeIf(not_equal, instr, Deoptimizer::kNotAHeapNumberUndefined);
5619 __ jmp(&zero_result, Label::kNear); 5621 __ jmp(&zero_result, Label::kNear);
5620 5622
5621 // Heap number 5623 // Heap number
5622 __ bind(&heap_number); 5624 __ bind(&heap_number);
5623 5625
5624 // Surprisingly, all of the hand-crafted bit-manipulations below are much 5626 // Surprisingly, all of the hand-crafted bit-manipulations below are much
5625 // faster than the x86 FPU built-in instruction, especially since "banker's 5627 // faster than the x86 FPU built-in instruction, especially since "banker's
5626 // rounding" would be additionally very expensive 5628 // rounding" would be additionally very expensive
5627 5629
5628 // Get exponent word. 5630 // Get exponent word.
(...skipping 550 matching lines...) Expand 10 before | Expand all | Expand 10 after
6179 DCHECK(!environment->HasBeenRegistered()); 6181 DCHECK(!environment->HasBeenRegistered());
6180 RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt); 6182 RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt);
6181 6183
6182 GenerateOsrPrologue(); 6184 GenerateOsrPrologue();
6183 } 6185 }
6184 6186
6185 6187
6186 void LCodeGen::DoForInPrepareMap(LForInPrepareMap* instr) { 6188 void LCodeGen::DoForInPrepareMap(LForInPrepareMap* instr) {
6187 DCHECK(ToRegister(instr->context()).is(esi)); 6189 DCHECK(ToRegister(instr->context()).is(esi));
6188 __ cmp(eax, isolate()->factory()->undefined_value()); 6190 __ cmp(eax, isolate()->factory()->undefined_value());
6189 DeoptimizeIf(equal, instr, "undefined"); 6191 DeoptimizeIf(equal, instr, Deoptimizer::kUndefined);
6190 6192
6191 __ cmp(eax, isolate()->factory()->null_value()); 6193 __ cmp(eax, isolate()->factory()->null_value());
6192 DeoptimizeIf(equal, instr, "null"); 6194 DeoptimizeIf(equal, instr, Deoptimizer::kNull);
6193 6195
6194 __ test(eax, Immediate(kSmiTagMask)); 6196 __ test(eax, Immediate(kSmiTagMask));
6195 DeoptimizeIf(zero, instr, "Smi"); 6197 DeoptimizeIf(zero, instr, Deoptimizer::kSmi);
6196 6198
6197 STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE); 6199 STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE);
6198 __ CmpObjectType(eax, LAST_JS_PROXY_TYPE, ecx); 6200 __ CmpObjectType(eax, LAST_JS_PROXY_TYPE, ecx);
6199 DeoptimizeIf(below_equal, instr, "wrong instance type"); 6201 DeoptimizeIf(below_equal, instr, Deoptimizer::kWrongInstanceType);
6200 6202
6201 Label use_cache, call_runtime; 6203 Label use_cache, call_runtime;
6202 __ CheckEnumCache(&call_runtime); 6204 __ CheckEnumCache(&call_runtime);
6203 6205
6204 __ mov(eax, FieldOperand(eax, HeapObject::kMapOffset)); 6206 __ mov(eax, FieldOperand(eax, HeapObject::kMapOffset));
6205 __ jmp(&use_cache, Label::kNear); 6207 __ jmp(&use_cache, Label::kNear);
6206 6208
6207 // Get the set of properties to enumerate. 6209 // Get the set of properties to enumerate.
6208 __ bind(&call_runtime); 6210 __ bind(&call_runtime);
6209 __ push(eax); 6211 __ push(eax);
6210 CallRuntime(Runtime::kGetPropertyNamesFast, 1, instr); 6212 CallRuntime(Runtime::kGetPropertyNamesFast, 1, instr);
6211 6213
6212 __ cmp(FieldOperand(eax, HeapObject::kMapOffset), 6214 __ cmp(FieldOperand(eax, HeapObject::kMapOffset),
6213 isolate()->factory()->meta_map()); 6215 isolate()->factory()->meta_map());
6214 DeoptimizeIf(not_equal, instr, "wrong map"); 6216 DeoptimizeIf(not_equal, instr, Deoptimizer::kWrongMap);
6215 __ bind(&use_cache); 6217 __ bind(&use_cache);
6216 } 6218 }
6217 6219
6218 6220
6219 void LCodeGen::DoForInCacheArray(LForInCacheArray* instr) { 6221 void LCodeGen::DoForInCacheArray(LForInCacheArray* instr) {
6220 Register map = ToRegister(instr->map()); 6222 Register map = ToRegister(instr->map());
6221 Register result = ToRegister(instr->result()); 6223 Register result = ToRegister(instr->result());
6222 Label load_cache, done; 6224 Label load_cache, done;
6223 __ EnumLength(result, map); 6225 __ EnumLength(result, map);
6224 __ cmp(result, Immediate(Smi::FromInt(0))); 6226 __ cmp(result, Immediate(Smi::FromInt(0)));
6225 __ j(not_equal, &load_cache, Label::kNear); 6227 __ j(not_equal, &load_cache, Label::kNear);
6226 __ mov(result, isolate()->factory()->empty_fixed_array()); 6228 __ mov(result, isolate()->factory()->empty_fixed_array());
6227 __ jmp(&done, Label::kNear); 6229 __ jmp(&done, Label::kNear);
6228 6230
6229 __ bind(&load_cache); 6231 __ bind(&load_cache);
6230 __ LoadInstanceDescriptors(map, result); 6232 __ LoadInstanceDescriptors(map, result);
6231 __ mov(result, 6233 __ mov(result,
6232 FieldOperand(result, DescriptorArray::kEnumCacheOffset)); 6234 FieldOperand(result, DescriptorArray::kEnumCacheOffset));
6233 __ mov(result, 6235 __ mov(result,
6234 FieldOperand(result, FixedArray::SizeFor(instr->idx()))); 6236 FieldOperand(result, FixedArray::SizeFor(instr->idx())));
6235 __ bind(&done); 6237 __ bind(&done);
6236 __ test(result, result); 6238 __ test(result, result);
6237 DeoptimizeIf(equal, instr, "no cache"); 6239 DeoptimizeIf(equal, instr, Deoptimizer::kNoCache);
6238 } 6240 }
6239 6241
6240 6242
6241 void LCodeGen::DoCheckMapValue(LCheckMapValue* instr) { 6243 void LCodeGen::DoCheckMapValue(LCheckMapValue* instr) {
6242 Register object = ToRegister(instr->value()); 6244 Register object = ToRegister(instr->value());
6243 __ cmp(ToRegister(instr->map()), 6245 __ cmp(ToRegister(instr->map()),
6244 FieldOperand(object, HeapObject::kMapOffset)); 6246 FieldOperand(object, HeapObject::kMapOffset));
6245 DeoptimizeIf(not_equal, instr, "wrong map"); 6247 DeoptimizeIf(not_equal, instr, Deoptimizer::kWrongMap);
6246 } 6248 }
6247 6249
6248 6250
6249 void LCodeGen::DoDeferredLoadMutableDouble(LLoadFieldByIndex* instr, 6251 void LCodeGen::DoDeferredLoadMutableDouble(LLoadFieldByIndex* instr,
6250 Register object, 6252 Register object,
6251 Register index) { 6253 Register index) {
6252 PushSafepointRegistersScope scope(this); 6254 PushSafepointRegistersScope scope(this);
6253 __ push(object); 6255 __ push(object);
6254 __ push(index); 6256 __ push(index);
6255 __ xor_(esi, esi); 6257 __ xor_(esi, esi);
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
6331 CallRuntime(Runtime::kPushBlockContext, 2, instr); 6333 CallRuntime(Runtime::kPushBlockContext, 2, instr);
6332 RecordSafepoint(Safepoint::kNoLazyDeopt); 6334 RecordSafepoint(Safepoint::kNoLazyDeopt);
6333 } 6335 }
6334 6336
6335 6337
6336 #undef __ 6338 #undef __
6337 6339
6338 } } // namespace v8::internal 6340 } } // namespace v8::internal
6339 6341
6340 #endif // V8_TARGET_ARCH_X87 6342 #endif // V8_TARGET_ARCH_X87
OLDNEW
« no previous file with comments | « src/x64/lithium-codegen-x64.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698