OLD | NEW |
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 Loading... |
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, ÷nd_is_not_negative, Label::kNear); | 1410 __ j(not_sign, ÷nd_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(÷nd_is_not_negative); | 1421 __ bind(÷nd_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, ÷nd_not_zero, Label::kNear); | 1598 __ j(not_zero, ÷nd_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(÷nd_not_zero); | 1601 __ bind(÷nd_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, ÷nd_not_min_int, Label::kNear); | 1608 __ j(not_zero, ÷nd_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(÷nd_not_min_int); | 1611 __ bind(÷nd_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, ¬_kmin_int, Label::kNear); | 1661 __ j(no_overflow, ¬_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(¬_kmin_int); | 1664 __ bind(¬_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 Loading... |
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, ÷nd_not_zero, Label::kNear); | 1738 __ j(not_zero, ÷nd_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(÷nd_not_zero); | 1741 __ bind(÷nd_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, ÷nd_not_min_int, Label::kNear); | 1748 __ j(not_zero, ÷nd_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(÷nd_not_min_int); | 1751 __ bind(÷nd_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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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(¬_heap_number); | 2473 __ bind(¬_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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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, ¬_minus_zero, Label::kNear); | 3953 __ j(below, ¬_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, ¬_minus_zero, Label::kNear); | 3957 __ j(not_equal, ¬_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(¬_minus_zero); | 3968 __ bind(¬_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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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, ¬_nan); | 5295 __ j(parity_odd, ¬_nan); |
5295 __ fstp(0); | 5296 __ fstp(0); |
5296 DeoptimizeIf(no_condition, instr, "NaN"); | 5297 DeoptimizeIf(no_condition, instr, Deoptimizer::kNaN); |
5297 __ bind(¬_nan); | 5298 __ bind(¬_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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |