OLD | NEW |
1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 1582 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1593 } else { | 1593 } else { |
1594 frame_->PushParameterAt(slot->index()); | 1594 frame_->PushParameterAt(slot->index()); |
1595 } | 1595 } |
1596 Result var = frame_->Pop(); | 1596 Result var = frame_->Pop(); |
1597 var.ToRegister(); | 1597 var.ToRegister(); |
1598 __ AbortIfNotSmi(var.reg()); | 1598 __ AbortIfNotSmi(var.reg()); |
1599 } | 1599 } |
1600 } | 1600 } |
1601 | 1601 |
1602 | 1602 |
| 1603 void CodeGenerator::GenerateFastSmiLoop(ForStatement* node) { |
| 1604 // A fast smi loop is a for loop with an initializer |
| 1605 // that is a simple assignment of a smi to a stack variable, |
| 1606 // a test that is a simple test of that variable against a smi constant, |
| 1607 // and a step that is a increment/decrement of the variable, and |
| 1608 // where the variable isn't modified in the loop body. |
| 1609 // This guarantees that the variable is always a smi. |
| 1610 |
| 1611 Variable* loop_var = node->loop_variable(); |
| 1612 Smi* initial_value = *Handle<Smi>::cast(node->init() |
| 1613 ->StatementAsSimpleAssignment()->value()->AsLiteral()->handle()); |
| 1614 Smi* limit_value = *Handle<Smi>::cast( |
| 1615 node->cond()->AsCompareOperation()->right()->AsLiteral()->handle()); |
| 1616 Token::Value compare_op = |
| 1617 node->cond()->AsCompareOperation()->op(); |
| 1618 bool increments = |
| 1619 node->next()->StatementAsCountOperation()->op() == Token::INC; |
| 1620 |
| 1621 // Check that the condition isn't initially false. |
| 1622 bool initially_false = false; |
| 1623 int initial_int_value = initial_value->value(); |
| 1624 int limit_int_value = limit_value->value(); |
| 1625 switch (compare_op) { |
| 1626 case Token::LT: |
| 1627 initially_false = initial_int_value >= limit_int_value; |
| 1628 break; |
| 1629 case Token::LTE: |
| 1630 initially_false = initial_int_value > limit_int_value; |
| 1631 break; |
| 1632 case Token::GT: |
| 1633 initially_false = initial_int_value <= limit_int_value; |
| 1634 break; |
| 1635 case Token::GTE: |
| 1636 initially_false = initial_int_value < limit_int_value; |
| 1637 break; |
| 1638 default: |
| 1639 UNREACHABLE(); |
| 1640 } |
| 1641 if (initially_false) return; |
| 1642 |
| 1643 // Only check loop condition at the end. |
| 1644 |
| 1645 Visit(node->init()); |
| 1646 |
| 1647 JumpTarget loop(JumpTarget::BIDIRECTIONAL); |
| 1648 |
| 1649 IncrementLoopNesting(); |
| 1650 loop.Bind(); |
| 1651 |
| 1652 // Set number type of the loop variable to smi. |
| 1653 CheckStack(); // TODO(1222600): ignore if body contains calls. |
| 1654 |
| 1655 SetTypeForStackSlot(loop_var->slot(), TypeInfo::Smi()); |
| 1656 Visit(node->body()); |
| 1657 |
| 1658 if (node->continue_target()->is_linked()) { |
| 1659 node->continue_target()->Bind(); |
| 1660 } |
| 1661 |
| 1662 if (has_valid_frame()) { |
| 1663 CodeForStatementPosition(node); |
| 1664 Slot* loop_var_slot = loop_var->slot(); |
| 1665 if (loop_var_slot->type() == Slot::LOCAL) { |
| 1666 frame_->PushLocalAt(loop_var_slot->index()); |
| 1667 } else { |
| 1668 ASSERT(loop_var_slot->type() == Slot::PARAMETER); |
| 1669 frame_->PushParameterAt(loop_var_slot->index()); |
| 1670 } |
| 1671 Result loop_var_result = frame_->Pop(); |
| 1672 if (!loop_var_result.is_register()) { |
| 1673 loop_var_result.ToRegister(); |
| 1674 } |
| 1675 |
| 1676 if (increments) { |
| 1677 __ SmiAddConstant(loop_var_result.reg(), |
| 1678 loop_var_result.reg(), |
| 1679 Smi::FromInt(1)); |
| 1680 } else { |
| 1681 __ SmiSubConstant(loop_var_result.reg(), |
| 1682 loop_var_result.reg(), |
| 1683 Smi::FromInt(1)); |
| 1684 } |
| 1685 |
| 1686 { |
| 1687 __ SmiCompare(loop_var_result.reg(), limit_value); |
| 1688 Condition condition; |
| 1689 switch (compare_op) { |
| 1690 case Token::LT: |
| 1691 condition = less; |
| 1692 break; |
| 1693 case Token::LTE: |
| 1694 condition = less_equal; |
| 1695 break; |
| 1696 case Token::GT: |
| 1697 condition = greater; |
| 1698 break; |
| 1699 case Token::GTE: |
| 1700 condition = greater_equal; |
| 1701 break; |
| 1702 default: |
| 1703 condition = never; |
| 1704 UNREACHABLE(); |
| 1705 } |
| 1706 loop.Branch(condition); |
| 1707 } |
| 1708 loop_var_result.Unuse(); |
| 1709 } |
| 1710 if (node->break_target()->is_linked()) { |
| 1711 node->break_target()->Bind(); |
| 1712 } |
| 1713 DecrementLoopNesting(); |
| 1714 } |
| 1715 |
| 1716 |
1603 void CodeGenerator::VisitForStatement(ForStatement* node) { | 1717 void CodeGenerator::VisitForStatement(ForStatement* node) { |
1604 ASSERT(!in_spilled_code()); | 1718 ASSERT(!in_spilled_code()); |
1605 Comment cmnt(masm_, "[ ForStatement"); | 1719 Comment cmnt(masm_, "[ ForStatement"); |
1606 CodeForStatementPosition(node); | 1720 CodeForStatementPosition(node); |
1607 | 1721 |
| 1722 if (node->is_fast_smi_loop()) { |
| 1723 GenerateFastSmiLoop(node); |
| 1724 return; |
| 1725 } |
| 1726 |
1608 // Compile the init expression if present. | 1727 // Compile the init expression if present. |
1609 if (node->init() != NULL) { | 1728 if (node->init() != NULL) { |
1610 Visit(node->init()); | 1729 Visit(node->init()); |
1611 } | 1730 } |
1612 | 1731 |
1613 // If the condition is always false and has no side effects, we do not | 1732 // If the condition is always false and has no side effects, we do not |
1614 // need to compile anything else. | 1733 // need to compile anything else. |
1615 ConditionAnalysis info = AnalyzeCondition(node->cond()); | 1734 ConditionAnalysis info = AnalyzeCondition(node->cond()); |
1616 if (info == ALWAYS_FALSE) return; | 1735 if (info == ALWAYS_FALSE) return; |
1617 | 1736 |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1687 } | 1806 } |
1688 break; | 1807 break; |
1689 } | 1808 } |
1690 case ALWAYS_FALSE: | 1809 case ALWAYS_FALSE: |
1691 UNREACHABLE(); | 1810 UNREACHABLE(); |
1692 break; | 1811 break; |
1693 } | 1812 } |
1694 | 1813 |
1695 CheckStack(); // TODO(1222600): ignore if body contains calls. | 1814 CheckStack(); // TODO(1222600): ignore if body contains calls. |
1696 | 1815 |
1697 // We know that the loop index is a smi if it is not modified in the | |
1698 // loop body and it is checked against a constant limit in the loop | |
1699 // condition. In this case, we reset the static type information of the | |
1700 // loop index to smi before compiling the body, the update expression, and | |
1701 // the bottom check of the loop condition. | |
1702 if (node->is_fast_smi_loop()) { | |
1703 // Set number type of the loop variable to smi. | |
1704 SetTypeForStackSlot(node->loop_variable()->slot(), TypeInfo::Smi()); | |
1705 } | |
1706 | |
1707 Visit(node->body()); | 1816 Visit(node->body()); |
1708 | 1817 |
1709 // If there is an update expression, compile it if necessary. | 1818 // If there is an update expression, compile it if necessary. |
1710 if (node->next() != NULL) { | 1819 if (node->next() != NULL) { |
1711 if (node->continue_target()->is_linked()) { | 1820 if (node->continue_target()->is_linked()) { |
1712 node->continue_target()->Bind(); | 1821 node->continue_target()->Bind(); |
1713 } | 1822 } |
1714 | 1823 |
1715 // Control can reach the update by falling out of the body or by a | 1824 // Control can reach the update by falling out of the body or by a |
1716 // continue. | 1825 // continue. |
1717 if (has_valid_frame()) { | 1826 if (has_valid_frame()) { |
1718 // Record the source position of the statement as this code which | 1827 // Record the source position of the statement as this code which |
1719 // is after the code for the body actually belongs to the loop | 1828 // is after the code for the body actually belongs to the loop |
1720 // statement and not the body. | 1829 // statement and not the body. |
1721 CodeForStatementPosition(node); | 1830 CodeForStatementPosition(node); |
1722 Visit(node->next()); | 1831 Visit(node->next()); |
1723 } | 1832 } |
1724 } | 1833 } |
1725 | 1834 |
1726 // Set the type of the loop variable to smi before compiling the test | |
1727 // expression if we are in a fast smi loop condition. | |
1728 if (node->is_fast_smi_loop() && has_valid_frame()) { | |
1729 // Set number type of the loop variable to smi. | |
1730 SetTypeForStackSlot(node->loop_variable()->slot(), TypeInfo::Smi()); | |
1731 } | |
1732 | |
1733 // Based on the condition analysis, compile the backward jump as | 1835 // Based on the condition analysis, compile the backward jump as |
1734 // necessary. | 1836 // necessary. |
1735 switch (info) { | 1837 switch (info) { |
1736 case ALWAYS_TRUE: | 1838 case ALWAYS_TRUE: |
1737 if (has_valid_frame()) { | 1839 if (has_valid_frame()) { |
1738 if (node->next() == NULL) { | 1840 if (node->next() == NULL) { |
1739 node->continue_target()->Jump(); | 1841 node->continue_target()->Jump(); |
1740 } else { | 1842 } else { |
1741 loop.Jump(); | 1843 loop.Jump(); |
1742 } | 1844 } |
(...skipping 10206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
11949 } | 12051 } |
11950 | 12052 |
11951 #endif | 12053 #endif |
11952 | 12054 |
11953 | 12055 |
11954 #undef __ | 12056 #undef __ |
11955 | 12057 |
11956 } } // namespace v8::internal | 12058 } } // namespace v8::internal |
11957 | 12059 |
11958 #endif // V8_TARGET_ARCH_X64 | 12060 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |