| 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/code-stubs.h" | 5 #include "src/code-stubs.h" |
| 6 | 6 |
| 7 #include <sstream> | 7 #include <sstream> |
| 8 | 8 |
| 9 #include "src/ast/ast.h" | 9 #include "src/ast/ast.h" |
| 10 #include "src/bootstrapper.h" | 10 #include "src/bootstrapper.h" |
| (...skipping 1494 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1505 var_result.Bind(assembler->CallStub(callable, context, dividend, divisor)); | 1505 var_result.Bind(assembler->CallStub(callable, context, dividend, divisor)); |
| 1506 assembler->Goto(&end); | 1506 assembler->Goto(&end); |
| 1507 } | 1507 } |
| 1508 | 1508 |
| 1509 assembler->Bind(&end); | 1509 assembler->Bind(&end); |
| 1510 assembler->UpdateFeedback(var_type_feedback.value(), type_feedback_vector, | 1510 assembler->UpdateFeedback(var_type_feedback.value(), type_feedback_vector, |
| 1511 slot_id); | 1511 slot_id); |
| 1512 return var_result.value(); | 1512 return var_result.value(); |
| 1513 } | 1513 } |
| 1514 | 1514 |
| 1515 #define UNARY_OP_STUB(Name) \ | |
| 1516 void Name::GenerateAssembly(compiler::CodeAssemblerState* state) const { \ | |
| 1517 CodeStubAssembler assembler(state); \ | |
| 1518 assembler.Return(Generate(&assembler, assembler.Parameter(0), \ | |
| 1519 assembler.Parameter(1), assembler.Parameter(2), \ | |
| 1520 assembler.Parameter(3))); \ | |
| 1521 } | |
| 1522 UNARY_OP_STUB(IncStub) | |
| 1523 UNARY_OP_STUB(DecStub) | |
| 1524 #undef UNARY_OP_STUB | |
| 1525 | |
| 1526 // static | |
| 1527 compiler::Node* IncStub::Generate(CodeStubAssembler* assembler, | |
| 1528 compiler::Node* value, | |
| 1529 compiler::Node* context, | |
| 1530 compiler::Node* type_feedback_vector, | |
| 1531 compiler::Node* slot_id) { | |
| 1532 typedef CodeStubAssembler::Label Label; | |
| 1533 typedef compiler::Node Node; | |
| 1534 typedef CodeStubAssembler::Variable Variable; | |
| 1535 | |
| 1536 // Shared entry for floating point increment. | |
| 1537 Label do_finc(assembler), end(assembler); | |
| 1538 Variable var_finc_value(assembler, MachineRepresentation::kFloat64); | |
| 1539 | |
| 1540 // We might need to try again due to ToNumber conversion. | |
| 1541 Variable value_var(assembler, MachineRepresentation::kTagged); | |
| 1542 Variable result_var(assembler, MachineRepresentation::kTagged); | |
| 1543 Variable var_type_feedback(assembler, MachineRepresentation::kWord32); | |
| 1544 Variable* loop_vars[] = {&value_var, &var_type_feedback}; | |
| 1545 Label start(assembler, 2, loop_vars); | |
| 1546 value_var.Bind(value); | |
| 1547 var_type_feedback.Bind( | |
| 1548 assembler->Int32Constant(BinaryOperationFeedback::kNone)); | |
| 1549 assembler->Goto(&start); | |
| 1550 assembler->Bind(&start); | |
| 1551 { | |
| 1552 value = value_var.value(); | |
| 1553 | |
| 1554 Label if_issmi(assembler), if_isnotsmi(assembler); | |
| 1555 assembler->Branch(assembler->TaggedIsSmi(value), &if_issmi, &if_isnotsmi); | |
| 1556 | |
| 1557 assembler->Bind(&if_issmi); | |
| 1558 { | |
| 1559 // Try fast Smi addition first. | |
| 1560 Node* one = assembler->SmiConstant(Smi::FromInt(1)); | |
| 1561 Node* pair = assembler->IntPtrAddWithOverflow( | |
| 1562 assembler->BitcastTaggedToWord(value), | |
| 1563 assembler->BitcastTaggedToWord(one)); | |
| 1564 Node* overflow = assembler->Projection(1, pair); | |
| 1565 | |
| 1566 // Check if the Smi addition overflowed. | |
| 1567 Label if_overflow(assembler), if_notoverflow(assembler); | |
| 1568 assembler->Branch(overflow, &if_overflow, &if_notoverflow); | |
| 1569 | |
| 1570 assembler->Bind(&if_notoverflow); | |
| 1571 var_type_feedback.Bind(assembler->Word32Or( | |
| 1572 var_type_feedback.value(), | |
| 1573 assembler->Int32Constant(BinaryOperationFeedback::kSignedSmall))); | |
| 1574 result_var.Bind( | |
| 1575 assembler->BitcastWordToTaggedSigned(assembler->Projection(0, pair))); | |
| 1576 assembler->Goto(&end); | |
| 1577 | |
| 1578 assembler->Bind(&if_overflow); | |
| 1579 { | |
| 1580 var_finc_value.Bind(assembler->SmiToFloat64(value)); | |
| 1581 assembler->Goto(&do_finc); | |
| 1582 } | |
| 1583 } | |
| 1584 | |
| 1585 assembler->Bind(&if_isnotsmi); | |
| 1586 { | |
| 1587 // Check if the value is a HeapNumber. | |
| 1588 Label if_valueisnumber(assembler), | |
| 1589 if_valuenotnumber(assembler, Label::kDeferred); | |
| 1590 Node* value_map = assembler->LoadMap(value); | |
| 1591 assembler->Branch(assembler->IsHeapNumberMap(value_map), | |
| 1592 &if_valueisnumber, &if_valuenotnumber); | |
| 1593 | |
| 1594 assembler->Bind(&if_valueisnumber); | |
| 1595 { | |
| 1596 // Load the HeapNumber value. | |
| 1597 var_finc_value.Bind(assembler->LoadHeapNumberValue(value)); | |
| 1598 assembler->Goto(&do_finc); | |
| 1599 } | |
| 1600 | |
| 1601 assembler->Bind(&if_valuenotnumber); | |
| 1602 { | |
| 1603 // We do not require an Or with earlier feedback here because once we | |
| 1604 // convert the value to a number, we cannot reach this path. We can | |
| 1605 // only reach this path on the first pass when the feedback is kNone. | |
| 1606 CSA_ASSERT(assembler, | |
| 1607 assembler->Word32Equal(var_type_feedback.value(), | |
| 1608 assembler->Int32Constant( | |
| 1609 BinaryOperationFeedback::kNone))); | |
| 1610 | |
| 1611 Label if_valueisoddball(assembler), if_valuenotoddball(assembler); | |
| 1612 Node* instance_type = assembler->LoadMapInstanceType(value_map); | |
| 1613 Node* is_oddball = assembler->Word32Equal( | |
| 1614 instance_type, assembler->Int32Constant(ODDBALL_TYPE)); | |
| 1615 assembler->Branch(is_oddball, &if_valueisoddball, &if_valuenotoddball); | |
| 1616 | |
| 1617 assembler->Bind(&if_valueisoddball); | |
| 1618 { | |
| 1619 // Convert Oddball to Number and check again. | |
| 1620 value_var.Bind( | |
| 1621 assembler->LoadObjectField(value, Oddball::kToNumberOffset)); | |
| 1622 var_type_feedback.Bind(assembler->Int32Constant( | |
| 1623 BinaryOperationFeedback::kNumberOrOddball)); | |
| 1624 assembler->Goto(&start); | |
| 1625 } | |
| 1626 | |
| 1627 assembler->Bind(&if_valuenotoddball); | |
| 1628 { | |
| 1629 // Convert to a Number first and try again. | |
| 1630 Callable callable = | |
| 1631 CodeFactory::NonNumberToNumber(assembler->isolate()); | |
| 1632 var_type_feedback.Bind( | |
| 1633 assembler->Int32Constant(BinaryOperationFeedback::kAny)); | |
| 1634 value_var.Bind(assembler->CallStub(callable, context, value)); | |
| 1635 assembler->Goto(&start); | |
| 1636 } | |
| 1637 } | |
| 1638 } | |
| 1639 } | |
| 1640 | |
| 1641 assembler->Bind(&do_finc); | |
| 1642 { | |
| 1643 Node* finc_value = var_finc_value.value(); | |
| 1644 Node* one = assembler->Float64Constant(1.0); | |
| 1645 Node* finc_result = assembler->Float64Add(finc_value, one); | |
| 1646 var_type_feedback.Bind(assembler->Word32Or( | |
| 1647 var_type_feedback.value(), | |
| 1648 assembler->Int32Constant(BinaryOperationFeedback::kNumber))); | |
| 1649 result_var.Bind(assembler->AllocateHeapNumberWithValue(finc_result)); | |
| 1650 assembler->Goto(&end); | |
| 1651 } | |
| 1652 | |
| 1653 assembler->Bind(&end); | |
| 1654 assembler->UpdateFeedback(var_type_feedback.value(), type_feedback_vector, | |
| 1655 slot_id); | |
| 1656 return result_var.value(); | |
| 1657 } | |
| 1658 | |
| 1659 void NumberToStringStub::GenerateAssembly( | 1515 void NumberToStringStub::GenerateAssembly( |
| 1660 compiler::CodeAssemblerState* state) const { | 1516 compiler::CodeAssemblerState* state) const { |
| 1661 typedef compiler::Node Node; | 1517 typedef compiler::Node Node; |
| 1662 CodeStubAssembler assembler(state); | 1518 CodeStubAssembler assembler(state); |
| 1663 Node* argument = assembler.Parameter(Descriptor::kArgument); | 1519 Node* argument = assembler.Parameter(Descriptor::kArgument); |
| 1664 Node* context = assembler.Parameter(Descriptor::kContext); | 1520 Node* context = assembler.Parameter(Descriptor::kContext); |
| 1665 assembler.Return(assembler.NumberToString(context, argument)); | 1521 assembler.Return(assembler.NumberToString(context, argument)); |
| 1666 } | 1522 } |
| 1667 | 1523 |
| 1668 // static | |
| 1669 compiler::Node* DecStub::Generate(CodeStubAssembler* assembler, | |
| 1670 compiler::Node* value, | |
| 1671 compiler::Node* context, | |
| 1672 compiler::Node* type_feedback_vector, | |
| 1673 compiler::Node* slot_id) { | |
| 1674 typedef CodeStubAssembler::Label Label; | |
| 1675 typedef compiler::Node Node; | |
| 1676 typedef CodeStubAssembler::Variable Variable; | |
| 1677 | |
| 1678 // Shared entry for floating point decrement. | |
| 1679 Label do_fdec(assembler), end(assembler); | |
| 1680 Variable var_fdec_value(assembler, MachineRepresentation::kFloat64); | |
| 1681 | |
| 1682 // We might need to try again due to ToNumber conversion. | |
| 1683 Variable value_var(assembler, MachineRepresentation::kTagged); | |
| 1684 Variable result_var(assembler, MachineRepresentation::kTagged); | |
| 1685 Variable var_type_feedback(assembler, MachineRepresentation::kWord32); | |
| 1686 Variable* loop_vars[] = {&value_var, &var_type_feedback}; | |
| 1687 Label start(assembler, 2, loop_vars); | |
| 1688 var_type_feedback.Bind( | |
| 1689 assembler->Int32Constant(BinaryOperationFeedback::kNone)); | |
| 1690 value_var.Bind(value); | |
| 1691 assembler->Goto(&start); | |
| 1692 assembler->Bind(&start); | |
| 1693 { | |
| 1694 value = value_var.value(); | |
| 1695 | |
| 1696 Label if_issmi(assembler), if_isnotsmi(assembler); | |
| 1697 assembler->Branch(assembler->TaggedIsSmi(value), &if_issmi, &if_isnotsmi); | |
| 1698 | |
| 1699 assembler->Bind(&if_issmi); | |
| 1700 { | |
| 1701 // Try fast Smi subtraction first. | |
| 1702 Node* one = assembler->SmiConstant(Smi::FromInt(1)); | |
| 1703 Node* pair = assembler->IntPtrSubWithOverflow( | |
| 1704 assembler->BitcastTaggedToWord(value), | |
| 1705 assembler->BitcastTaggedToWord(one)); | |
| 1706 Node* overflow = assembler->Projection(1, pair); | |
| 1707 | |
| 1708 // Check if the Smi subtraction overflowed. | |
| 1709 Label if_overflow(assembler), if_notoverflow(assembler); | |
| 1710 assembler->Branch(overflow, &if_overflow, &if_notoverflow); | |
| 1711 | |
| 1712 assembler->Bind(&if_notoverflow); | |
| 1713 var_type_feedback.Bind(assembler->Word32Or( | |
| 1714 var_type_feedback.value(), | |
| 1715 assembler->Int32Constant(BinaryOperationFeedback::kSignedSmall))); | |
| 1716 result_var.Bind( | |
| 1717 assembler->BitcastWordToTaggedSigned(assembler->Projection(0, pair))); | |
| 1718 assembler->Goto(&end); | |
| 1719 | |
| 1720 assembler->Bind(&if_overflow); | |
| 1721 { | |
| 1722 var_fdec_value.Bind(assembler->SmiToFloat64(value)); | |
| 1723 assembler->Goto(&do_fdec); | |
| 1724 } | |
| 1725 } | |
| 1726 | |
| 1727 assembler->Bind(&if_isnotsmi); | |
| 1728 { | |
| 1729 // Check if the value is a HeapNumber. | |
| 1730 Label if_valueisnumber(assembler), | |
| 1731 if_valuenotnumber(assembler, Label::kDeferred); | |
| 1732 Node* value_map = assembler->LoadMap(value); | |
| 1733 assembler->Branch(assembler->IsHeapNumberMap(value_map), | |
| 1734 &if_valueisnumber, &if_valuenotnumber); | |
| 1735 | |
| 1736 assembler->Bind(&if_valueisnumber); | |
| 1737 { | |
| 1738 // Load the HeapNumber value. | |
| 1739 var_fdec_value.Bind(assembler->LoadHeapNumberValue(value)); | |
| 1740 assembler->Goto(&do_fdec); | |
| 1741 } | |
| 1742 | |
| 1743 assembler->Bind(&if_valuenotnumber); | |
| 1744 { | |
| 1745 // We do not require an Or with earlier feedback here because once we | |
| 1746 // convert the value to a number, we cannot reach this path. We can | |
| 1747 // only reach this path on the first pass when the feedback is kNone. | |
| 1748 CSA_ASSERT(assembler, | |
| 1749 assembler->Word32Equal(var_type_feedback.value(), | |
| 1750 assembler->Int32Constant( | |
| 1751 BinaryOperationFeedback::kNone))); | |
| 1752 | |
| 1753 Label if_valueisoddball(assembler), if_valuenotoddball(assembler); | |
| 1754 Node* instance_type = assembler->LoadMapInstanceType(value_map); | |
| 1755 Node* is_oddball = assembler->Word32Equal( | |
| 1756 instance_type, assembler->Int32Constant(ODDBALL_TYPE)); | |
| 1757 assembler->Branch(is_oddball, &if_valueisoddball, &if_valuenotoddball); | |
| 1758 | |
| 1759 assembler->Bind(&if_valueisoddball); | |
| 1760 { | |
| 1761 // Convert Oddball to Number and check again. | |
| 1762 value_var.Bind( | |
| 1763 assembler->LoadObjectField(value, Oddball::kToNumberOffset)); | |
| 1764 var_type_feedback.Bind(assembler->Int32Constant( | |
| 1765 BinaryOperationFeedback::kNumberOrOddball)); | |
| 1766 assembler->Goto(&start); | |
| 1767 } | |
| 1768 | |
| 1769 assembler->Bind(&if_valuenotoddball); | |
| 1770 { | |
| 1771 // Convert to a Number first and try again. | |
| 1772 Callable callable = | |
| 1773 CodeFactory::NonNumberToNumber(assembler->isolate()); | |
| 1774 var_type_feedback.Bind( | |
| 1775 assembler->Int32Constant(BinaryOperationFeedback::kAny)); | |
| 1776 value_var.Bind(assembler->CallStub(callable, context, value)); | |
| 1777 assembler->Goto(&start); | |
| 1778 } | |
| 1779 } | |
| 1780 } | |
| 1781 } | |
| 1782 | |
| 1783 assembler->Bind(&do_fdec); | |
| 1784 { | |
| 1785 Node* fdec_value = var_fdec_value.value(); | |
| 1786 Node* one = assembler->Float64Constant(1.0); | |
| 1787 Node* fdec_result = assembler->Float64Sub(fdec_value, one); | |
| 1788 var_type_feedback.Bind(assembler->Word32Or( | |
| 1789 var_type_feedback.value(), | |
| 1790 assembler->Int32Constant(BinaryOperationFeedback::kNumber))); | |
| 1791 result_var.Bind(assembler->AllocateHeapNumberWithValue(fdec_result)); | |
| 1792 assembler->Goto(&end); | |
| 1793 } | |
| 1794 | |
| 1795 assembler->Bind(&end); | |
| 1796 assembler->UpdateFeedback(var_type_feedback.value(), type_feedback_vector, | |
| 1797 slot_id); | |
| 1798 return result_var.value(); | |
| 1799 } | |
| 1800 | |
| 1801 // ES6 section 21.1.3.19 String.prototype.substring ( start, end ) | 1524 // ES6 section 21.1.3.19 String.prototype.substring ( start, end ) |
| 1802 compiler::Node* SubStringStub::Generate(CodeStubAssembler* assembler, | 1525 compiler::Node* SubStringStub::Generate(CodeStubAssembler* assembler, |
| 1803 compiler::Node* string, | 1526 compiler::Node* string, |
| 1804 compiler::Node* from, | 1527 compiler::Node* from, |
| 1805 compiler::Node* to, | 1528 compiler::Node* to, |
| 1806 compiler::Node* context) { | 1529 compiler::Node* context) { |
| 1807 return assembler->SubString(context, string, from, to); | 1530 return assembler->SubString(context, string, from, to); |
| 1808 } | 1531 } |
| 1809 | 1532 |
| 1810 void SubStringStub::GenerateAssembly( | 1533 void SubStringStub::GenerateAssembly( |
| (...skipping 1152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2963 } | 2686 } |
| 2964 | 2687 |
| 2965 ArrayConstructorStub::ArrayConstructorStub(Isolate* isolate) | 2688 ArrayConstructorStub::ArrayConstructorStub(Isolate* isolate) |
| 2966 : PlatformCodeStub(isolate) {} | 2689 : PlatformCodeStub(isolate) {} |
| 2967 | 2690 |
| 2968 InternalArrayConstructorStub::InternalArrayConstructorStub(Isolate* isolate) | 2691 InternalArrayConstructorStub::InternalArrayConstructorStub(Isolate* isolate) |
| 2969 : PlatformCodeStub(isolate) {} | 2692 : PlatformCodeStub(isolate) {} |
| 2970 | 2693 |
| 2971 } // namespace internal | 2694 } // namespace internal |
| 2972 } // namespace v8 | 2695 } // namespace v8 |
| OLD | NEW |