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