OLD | NEW |
1 // Copyright 2006-2009 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2009 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 1521 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1532 } | 1532 } |
1533 | 1533 |
1534 if (node->break_target()->is_linked()) { | 1534 if (node->break_target()->is_linked()) { |
1535 node->break_target()->Bind(); | 1535 node->break_target()->Bind(); |
1536 } | 1536 } |
1537 node->break_target()->Unuse(); | 1537 node->break_target()->Unuse(); |
1538 ASSERT(!has_valid_frame() || frame_->height() == original_height); | 1538 ASSERT(!has_valid_frame() || frame_->height() == original_height); |
1539 } | 1539 } |
1540 | 1540 |
1541 | 1541 |
1542 void CodeGenerator::VisitLoopStatement(LoopStatement* node) { | 1542 void CodeGenerator::VisitDoWhileStatement(DoWhileStatement* node) { |
1543 #ifdef DEBUG | 1543 #ifdef DEBUG |
1544 int original_height = frame_->height(); | 1544 int original_height = frame_->height(); |
1545 #endif | 1545 #endif |
1546 VirtualFrame::SpilledScope spilled_scope; | 1546 VirtualFrame::SpilledScope spilled_scope; |
1547 Comment cmnt(masm_, "[ LoopStatement"); | 1547 Comment cmnt(masm_, "[ DoWhileStatement"); |
1548 CodeForStatementPosition(node); | 1548 CodeForStatementPosition(node); |
1549 node->break_target()->set_direction(JumpTarget::FORWARD_ONLY); | 1549 node->break_target()->set_direction(JumpTarget::FORWARD_ONLY); |
1550 | 1550 JumpTarget body(JumpTarget::BIDIRECTIONAL); |
1551 // Simple condition analysis. ALWAYS_TRUE and ALWAYS_FALSE represent a | 1551 |
1552 // known result for the test expression, with no side effects. | 1552 // Label the top of the loop for the backward CFG edge. If the test |
1553 enum { ALWAYS_TRUE, ALWAYS_FALSE, DONT_KNOW } info = DONT_KNOW; | 1553 // is always true we can use the continue target, and if the test is |
1554 if (node->cond() == NULL) { | 1554 // always false there is no need. |
1555 ASSERT(node->type() == LoopStatement::FOR_LOOP); | 1555 ConditionAnalysis info = AnalyzeCondition(node->cond()); |
1556 info = ALWAYS_TRUE; | 1556 switch (info) { |
1557 } else { | 1557 case ALWAYS_TRUE: |
1558 Literal* lit = node->cond()->AsLiteral(); | |
1559 if (lit != NULL) { | |
1560 if (lit->IsTrue()) { | |
1561 info = ALWAYS_TRUE; | |
1562 } else if (lit->IsFalse()) { | |
1563 info = ALWAYS_FALSE; | |
1564 } | |
1565 } | |
1566 } | |
1567 | |
1568 switch (node->type()) { | |
1569 case LoopStatement::DO_LOOP: { | |
1570 JumpTarget body(JumpTarget::BIDIRECTIONAL); | |
1571 | |
1572 // Label the top of the loop for the backward CFG edge. If the test | |
1573 // is always true we can use the continue target, and if the test is | |
1574 // always false there is no need. | |
1575 if (info == ALWAYS_TRUE) { | |
1576 node->continue_target()->set_direction(JumpTarget::BIDIRECTIONAL); | |
1577 node->continue_target()->Bind(); | |
1578 } else if (info == ALWAYS_FALSE) { | |
1579 node->continue_target()->set_direction(JumpTarget::FORWARD_ONLY); | |
1580 } else { | |
1581 ASSERT(info == DONT_KNOW); | |
1582 node->continue_target()->set_direction(JumpTarget::FORWARD_ONLY); | |
1583 body.Bind(); | |
1584 } | |
1585 | |
1586 CheckStack(); // TODO(1222600): ignore if body contains calls. | |
1587 VisitAndSpill(node->body()); | |
1588 | |
1589 // Compile the test. | |
1590 if (info == ALWAYS_TRUE) { | |
1591 if (has_valid_frame()) { | |
1592 // If control can fall off the end of the body, jump back to the | |
1593 // top. | |
1594 node->continue_target()->Jump(); | |
1595 } | |
1596 } else if (info == ALWAYS_FALSE) { | |
1597 // If we have a continue in the body, we only have to bind its jump | |
1598 // target. | |
1599 if (node->continue_target()->is_linked()) { | |
1600 node->continue_target()->Bind(); | |
1601 } | |
1602 } else { | |
1603 ASSERT(info == DONT_KNOW); | |
1604 // We have to compile the test expression if it can be reached by | |
1605 // control flow falling out of the body or via continue. | |
1606 if (node->continue_target()->is_linked()) { | |
1607 node->continue_target()->Bind(); | |
1608 } | |
1609 if (has_valid_frame()) { | |
1610 LoadConditionAndSpill(node->cond(), NOT_INSIDE_TYPEOF, | |
1611 &body, node->break_target(), true); | |
1612 if (has_valid_frame()) { | |
1613 // A invalid frame here indicates that control did not | |
1614 // fall out of the test expression. | |
1615 Branch(true, &body); | |
1616 } | |
1617 } | |
1618 } | |
1619 break; | |
1620 } | |
1621 | |
1622 case LoopStatement::WHILE_LOOP: { | |
1623 // If the test is never true and has no side effects there is no need | |
1624 // to compile the test or body. | |
1625 if (info == ALWAYS_FALSE) break; | |
1626 | |
1627 // Label the top of the loop with the continue target for the backward | |
1628 // CFG edge. | |
1629 node->continue_target()->set_direction(JumpTarget::BIDIRECTIONAL); | 1558 node->continue_target()->set_direction(JumpTarget::BIDIRECTIONAL); |
1630 node->continue_target()->Bind(); | 1559 node->continue_target()->Bind(); |
1631 | 1560 break; |
1632 if (info == DONT_KNOW) { | 1561 case ALWAYS_FALSE: |
1633 JumpTarget body; | 1562 node->continue_target()->set_direction(JumpTarget::FORWARD_ONLY); |
| 1563 break; |
| 1564 case DONT_KNOW: |
| 1565 node->continue_target()->set_direction(JumpTarget::FORWARD_ONLY); |
| 1566 body.Bind(); |
| 1567 break; |
| 1568 } |
| 1569 |
| 1570 CheckStack(); // TODO(1222600): ignore if body contains calls. |
| 1571 VisitAndSpill(node->body()); |
| 1572 |
| 1573 // Compile the test. |
| 1574 switch (info) { |
| 1575 case ALWAYS_TRUE: |
| 1576 // If control can fall off the end of the body, jump back to the |
| 1577 // top. |
| 1578 if (has_valid_frame()) { |
| 1579 node->continue_target()->Jump(); |
| 1580 } |
| 1581 break; |
| 1582 case ALWAYS_FALSE: |
| 1583 // If we have a continue in the body, we only have to bind its |
| 1584 // jump target. |
| 1585 if (node->continue_target()->is_linked()) { |
| 1586 node->continue_target()->Bind(); |
| 1587 } |
| 1588 break; |
| 1589 case DONT_KNOW: |
| 1590 // We have to compile the test expression if it can be reached by |
| 1591 // control flow falling out of the body or via continue. |
| 1592 if (node->continue_target()->is_linked()) { |
| 1593 node->continue_target()->Bind(); |
| 1594 } |
| 1595 if (has_valid_frame()) { |
1634 LoadConditionAndSpill(node->cond(), NOT_INSIDE_TYPEOF, | 1596 LoadConditionAndSpill(node->cond(), NOT_INSIDE_TYPEOF, |
1635 &body, node->break_target(), true); | 1597 &body, node->break_target(), true); |
1636 if (has_valid_frame()) { | 1598 if (has_valid_frame()) { |
1637 // A NULL frame indicates that control did not fall out of the | 1599 // A invalid frame here indicates that control did not |
1638 // test expression. | 1600 // fall out of the test expression. |
1639 Branch(false, node->break_target()); | 1601 Branch(true, &body); |
1640 } | 1602 } |
1641 if (has_valid_frame() || body.is_linked()) { | 1603 } |
1642 body.Bind(); | 1604 break; |
1643 } | |
1644 } | |
1645 | |
1646 if (has_valid_frame()) { | |
1647 CheckStack(); // TODO(1222600): ignore if body contains calls. | |
1648 VisitAndSpill(node->body()); | |
1649 | |
1650 // If control flow can fall out of the body, jump back to the top. | |
1651 if (has_valid_frame()) { | |
1652 node->continue_target()->Jump(); | |
1653 } | |
1654 } | |
1655 break; | |
1656 } | |
1657 | |
1658 case LoopStatement::FOR_LOOP: { | |
1659 JumpTarget loop(JumpTarget::BIDIRECTIONAL); | |
1660 | |
1661 if (node->init() != NULL) { | |
1662 VisitAndSpill(node->init()); | |
1663 } | |
1664 | |
1665 // There is no need to compile the test or body. | |
1666 if (info == ALWAYS_FALSE) break; | |
1667 | |
1668 // If there is no update statement, label the top of the loop with the | |
1669 // continue target, otherwise with the loop target. | |
1670 if (node->next() == NULL) { | |
1671 node->continue_target()->set_direction(JumpTarget::BIDIRECTIONAL); | |
1672 node->continue_target()->Bind(); | |
1673 } else { | |
1674 node->continue_target()->set_direction(JumpTarget::FORWARD_ONLY); | |
1675 loop.Bind(); | |
1676 } | |
1677 | |
1678 // If the test is always true, there is no need to compile it. | |
1679 if (info == DONT_KNOW) { | |
1680 JumpTarget body; | |
1681 LoadConditionAndSpill(node->cond(), NOT_INSIDE_TYPEOF, | |
1682 &body, node->break_target(), true); | |
1683 if (has_valid_frame()) { | |
1684 Branch(false, node->break_target()); | |
1685 } | |
1686 if (has_valid_frame() || body.is_linked()) { | |
1687 body.Bind(); | |
1688 } | |
1689 } | |
1690 | |
1691 if (has_valid_frame()) { | |
1692 CheckStack(); // TODO(1222600): ignore if body contains calls. | |
1693 VisitAndSpill(node->body()); | |
1694 | |
1695 if (node->next() == NULL) { | |
1696 // If there is no update statement and control flow can fall out | |
1697 // of the loop, jump directly to the continue label. | |
1698 if (has_valid_frame()) { | |
1699 node->continue_target()->Jump(); | |
1700 } | |
1701 } else { | |
1702 // If there is an update statement and control flow can reach it | |
1703 // via falling out of the body of the loop or continuing, we | |
1704 // compile the update statement. | |
1705 if (node->continue_target()->is_linked()) { | |
1706 node->continue_target()->Bind(); | |
1707 } | |
1708 if (has_valid_frame()) { | |
1709 // Record source position of the statement as this code which is | |
1710 // after the code for the body actually belongs to the loop | |
1711 // statement and not the body. | |
1712 CodeForStatementPosition(node); | |
1713 VisitAndSpill(node->next()); | |
1714 loop.Jump(); | |
1715 } | |
1716 } | |
1717 } | |
1718 break; | |
1719 } | |
1720 } | 1605 } |
1721 | 1606 |
1722 if (node->break_target()->is_linked()) { | 1607 if (node->break_target()->is_linked()) { |
1723 node->break_target()->Bind(); | 1608 node->break_target()->Bind(); |
1724 } | 1609 } |
1725 node->continue_target()->Unuse(); | |
1726 node->break_target()->Unuse(); | |
1727 ASSERT(!has_valid_frame() || frame_->height() == original_height); | 1610 ASSERT(!has_valid_frame() || frame_->height() == original_height); |
1728 } | 1611 } |
1729 | 1612 |
| 1613 |
| 1614 void CodeGenerator::VisitWhileStatement(WhileStatement* node) { |
| 1615 #ifdef DEBUG |
| 1616 int original_height = frame_->height(); |
| 1617 #endif |
| 1618 VirtualFrame::SpilledScope spilled_scope; |
| 1619 Comment cmnt(masm_, "[ WhileStatement"); |
| 1620 CodeForStatementPosition(node); |
| 1621 |
| 1622 // If the test is never true and has no side effects there is no need |
| 1623 // to compile the test or body. |
| 1624 ConditionAnalysis info = AnalyzeCondition(node->cond()); |
| 1625 if (info == ALWAYS_FALSE) return; |
| 1626 |
| 1627 node->break_target()->set_direction(JumpTarget::FORWARD_ONLY); |
| 1628 |
| 1629 // Label the top of the loop with the continue target for the backward |
| 1630 // CFG edge. |
| 1631 node->continue_target()->set_direction(JumpTarget::BIDIRECTIONAL); |
| 1632 node->continue_target()->Bind(); |
| 1633 |
| 1634 if (info == DONT_KNOW) { |
| 1635 JumpTarget body; |
| 1636 LoadConditionAndSpill(node->cond(), NOT_INSIDE_TYPEOF, |
| 1637 &body, node->break_target(), true); |
| 1638 if (has_valid_frame()) { |
| 1639 // A NULL frame indicates that control did not fall out of the |
| 1640 // test expression. |
| 1641 Branch(false, node->break_target()); |
| 1642 } |
| 1643 if (has_valid_frame() || body.is_linked()) { |
| 1644 body.Bind(); |
| 1645 } |
| 1646 } |
| 1647 |
| 1648 if (has_valid_frame()) { |
| 1649 CheckStack(); // TODO(1222600): ignore if body contains calls. |
| 1650 VisitAndSpill(node->body()); |
| 1651 |
| 1652 // If control flow can fall out of the body, jump back to the top. |
| 1653 if (has_valid_frame()) { |
| 1654 node->continue_target()->Jump(); |
| 1655 } |
| 1656 } |
| 1657 if (node->break_target()->is_linked()) { |
| 1658 node->break_target()->Bind(); |
| 1659 } |
| 1660 ASSERT(!has_valid_frame() || frame_->height() == original_height); |
| 1661 } |
| 1662 |
| 1663 |
| 1664 void CodeGenerator::VisitForStatement(ForStatement* node) { |
| 1665 #ifdef DEBUG |
| 1666 int original_height = frame_->height(); |
| 1667 #endif |
| 1668 VirtualFrame::SpilledScope spilled_scope; |
| 1669 Comment cmnt(masm_, "[ ForStatement"); |
| 1670 CodeForStatementPosition(node); |
| 1671 if (node->init() != NULL) { |
| 1672 VisitAndSpill(node->init()); |
| 1673 } |
| 1674 |
| 1675 // If the test is never true there is no need to compile the test or |
| 1676 // body. |
| 1677 ConditionAnalysis info = AnalyzeCondition(node->cond()); |
| 1678 if (info == ALWAYS_FALSE) return; |
| 1679 |
| 1680 node->break_target()->set_direction(JumpTarget::FORWARD_ONLY); |
| 1681 |
| 1682 // If there is no update statement, label the top of the loop with the |
| 1683 // continue target, otherwise with the loop target. |
| 1684 JumpTarget loop(JumpTarget::BIDIRECTIONAL); |
| 1685 if (node->next() == NULL) { |
| 1686 node->continue_target()->set_direction(JumpTarget::BIDIRECTIONAL); |
| 1687 node->continue_target()->Bind(); |
| 1688 } else { |
| 1689 node->continue_target()->set_direction(JumpTarget::FORWARD_ONLY); |
| 1690 loop.Bind(); |
| 1691 } |
| 1692 |
| 1693 // If the test is always true, there is no need to compile it. |
| 1694 if (info == DONT_KNOW) { |
| 1695 JumpTarget body; |
| 1696 LoadConditionAndSpill(node->cond(), NOT_INSIDE_TYPEOF, |
| 1697 &body, node->break_target(), true); |
| 1698 if (has_valid_frame()) { |
| 1699 Branch(false, node->break_target()); |
| 1700 } |
| 1701 if (has_valid_frame() || body.is_linked()) { |
| 1702 body.Bind(); |
| 1703 } |
| 1704 } |
| 1705 |
| 1706 if (has_valid_frame()) { |
| 1707 CheckStack(); // TODO(1222600): ignore if body contains calls. |
| 1708 VisitAndSpill(node->body()); |
| 1709 |
| 1710 if (node->next() == NULL) { |
| 1711 // If there is no update statement and control flow can fall out |
| 1712 // of the loop, jump directly to the continue label. |
| 1713 if (has_valid_frame()) { |
| 1714 node->continue_target()->Jump(); |
| 1715 } |
| 1716 } else { |
| 1717 // If there is an update statement and control flow can reach it |
| 1718 // via falling out of the body of the loop or continuing, we |
| 1719 // compile the update statement. |
| 1720 if (node->continue_target()->is_linked()) { |
| 1721 node->continue_target()->Bind(); |
| 1722 } |
| 1723 if (has_valid_frame()) { |
| 1724 // Record source position of the statement as this code which is |
| 1725 // after the code for the body actually belongs to the loop |
| 1726 // statement and not the body. |
| 1727 CodeForStatementPosition(node); |
| 1728 VisitAndSpill(node->next()); |
| 1729 loop.Jump(); |
| 1730 } |
| 1731 } |
| 1732 } |
| 1733 if (node->break_target()->is_linked()) { |
| 1734 node->break_target()->Bind(); |
| 1735 } |
| 1736 ASSERT(!has_valid_frame() || frame_->height() == original_height); |
| 1737 } |
| 1738 |
1730 | 1739 |
1731 void CodeGenerator::VisitForInStatement(ForInStatement* node) { | 1740 void CodeGenerator::VisitForInStatement(ForInStatement* node) { |
1732 #ifdef DEBUG | 1741 #ifdef DEBUG |
1733 int original_height = frame_->height(); | 1742 int original_height = frame_->height(); |
1734 #endif | 1743 #endif |
1735 VirtualFrame::SpilledScope spilled_scope; | 1744 VirtualFrame::SpilledScope spilled_scope; |
1736 Comment cmnt(masm_, "[ ForInStatement"); | 1745 Comment cmnt(masm_, "[ ForInStatement"); |
1737 CodeForStatementPosition(node); | 1746 CodeForStatementPosition(node); |
1738 | 1747 |
1739 JumpTarget primitive; | 1748 JumpTarget primitive; |
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1911 frame_->Drop(5); | 1920 frame_->Drop(5); |
1912 | 1921 |
1913 // Exit. | 1922 // Exit. |
1914 exit.Bind(); | 1923 exit.Bind(); |
1915 node->continue_target()->Unuse(); | 1924 node->continue_target()->Unuse(); |
1916 node->break_target()->Unuse(); | 1925 node->break_target()->Unuse(); |
1917 ASSERT(frame_->height() == original_height); | 1926 ASSERT(frame_->height() == original_height); |
1918 } | 1927 } |
1919 | 1928 |
1920 | 1929 |
1921 void CodeGenerator::VisitTryCatch(TryCatch* node) { | 1930 void CodeGenerator::VisitTryCatchStatement(TryCatchStatement* node) { |
1922 #ifdef DEBUG | 1931 #ifdef DEBUG |
1923 int original_height = frame_->height(); | 1932 int original_height = frame_->height(); |
1924 #endif | 1933 #endif |
1925 VirtualFrame::SpilledScope spilled_scope; | 1934 VirtualFrame::SpilledScope spilled_scope; |
1926 Comment cmnt(masm_, "[ TryCatch"); | 1935 Comment cmnt(masm_, "[ TryCatchStatement"); |
1927 CodeForStatementPosition(node); | 1936 CodeForStatementPosition(node); |
1928 | 1937 |
1929 JumpTarget try_block; | 1938 JumpTarget try_block; |
1930 JumpTarget exit; | 1939 JumpTarget exit; |
1931 | 1940 |
1932 try_block.Call(); | 1941 try_block.Call(); |
1933 // --- Catch block --- | 1942 // --- Catch block --- |
1934 frame_->EmitPush(r0); | 1943 frame_->EmitPush(r0); |
1935 | 1944 |
1936 // Store the caught exception in the catch variable. | 1945 // Store the caught exception in the catch variable. |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2036 } | 2045 } |
2037 shadows[i]->other_target()->Jump(); | 2046 shadows[i]->other_target()->Jump(); |
2038 } | 2047 } |
2039 } | 2048 } |
2040 | 2049 |
2041 exit.Bind(); | 2050 exit.Bind(); |
2042 ASSERT(!has_valid_frame() || frame_->height() == original_height); | 2051 ASSERT(!has_valid_frame() || frame_->height() == original_height); |
2043 } | 2052 } |
2044 | 2053 |
2045 | 2054 |
2046 void CodeGenerator::VisitTryFinally(TryFinally* node) { | 2055 void CodeGenerator::VisitTryFinallyStatement(TryFinallyStatement* node) { |
2047 #ifdef DEBUG | 2056 #ifdef DEBUG |
2048 int original_height = frame_->height(); | 2057 int original_height = frame_->height(); |
2049 #endif | 2058 #endif |
2050 VirtualFrame::SpilledScope spilled_scope; | 2059 VirtualFrame::SpilledScope spilled_scope; |
2051 Comment cmnt(masm_, "[ TryFinally"); | 2060 Comment cmnt(masm_, "[ TryFinallyStatement"); |
2052 CodeForStatementPosition(node); | 2061 CodeForStatementPosition(node); |
2053 | 2062 |
2054 // State: Used to keep track of reason for entering the finally | 2063 // State: Used to keep track of reason for entering the finally |
2055 // block. Should probably be extended to hold information for | 2064 // block. Should probably be extended to hold information for |
2056 // break/continue from within the try block. | 2065 // break/continue from within the try block. |
2057 enum { FALLING, THROWING, JUMPING }; | 2066 enum { FALLING, THROWING, JUMPING }; |
2058 | 2067 |
2059 JumpTarget try_block; | 2068 JumpTarget try_block; |
2060 JumpTarget finally_block; | 2069 JumpTarget finally_block; |
2061 | 2070 |
(...skipping 4194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6256 int CompareStub::MinorKey() { | 6265 int CompareStub::MinorKey() { |
6257 // Encode the two parameters in a unique 16 bit value. | 6266 // Encode the two parameters in a unique 16 bit value. |
6258 ASSERT(static_cast<unsigned>(cc_) >> 28 < (1 << 15)); | 6267 ASSERT(static_cast<unsigned>(cc_) >> 28 < (1 << 15)); |
6259 return (static_cast<unsigned>(cc_) >> 27) | (strict_ ? 1 : 0); | 6268 return (static_cast<unsigned>(cc_) >> 27) | (strict_ ? 1 : 0); |
6260 } | 6269 } |
6261 | 6270 |
6262 | 6271 |
6263 #undef __ | 6272 #undef __ |
6264 | 6273 |
6265 } } // namespace v8::internal | 6274 } } // namespace v8::internal |
OLD | NEW |