| 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 303 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 314 Comment cmnt(masm_, "[ function body"); | 314 Comment cmnt(masm_, "[ function body"); |
| 315 #ifdef DEBUG | 315 #ifdef DEBUG |
| 316 bool is_builtin = Bootstrapper::IsActive(); | 316 bool is_builtin = Bootstrapper::IsActive(); |
| 317 bool should_trace = | 317 bool should_trace = |
| 318 is_builtin ? FLAG_trace_builtin_calls : FLAG_trace_calls; | 318 is_builtin ? FLAG_trace_builtin_calls : FLAG_trace_calls; |
| 319 if (should_trace) { | 319 if (should_trace) { |
| 320 frame_->CallRuntime(Runtime::kDebugTrace, 0); | 320 frame_->CallRuntime(Runtime::kDebugTrace, 0); |
| 321 // Ignore the return value. | 321 // Ignore the return value. |
| 322 } | 322 } |
| 323 #endif | 323 #endif |
| 324 VisitStatementsAndSpill(info->function()->body()); | 324 VisitStatements(info->function()->body()); |
| 325 } | 325 } |
| 326 } | 326 } |
| 327 | 327 |
| 328 // Generate the return sequence if necessary. | 328 // Generate the return sequence if necessary. |
| 329 if (has_valid_frame() || function_return_.is_linked()) { | 329 if (has_valid_frame() || function_return_.is_linked()) { |
| 330 if (!function_return_.is_linked()) { | 330 if (!function_return_.is_linked()) { |
| 331 CodeForReturnPosition(info->function()); | 331 CodeForReturnPosition(info->function()); |
| 332 } | 332 } |
| 333 // exit | 333 // exit |
| 334 // r0: result | 334 // r0: result |
| (...skipping 1224 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1559 lo); | 1559 lo); |
| 1560 } | 1560 } |
| 1561 | 1561 |
| 1562 | 1562 |
| 1563 void CodeGenerator::VisitStatements(ZoneList<Statement*>* statements) { | 1563 void CodeGenerator::VisitStatements(ZoneList<Statement*>* statements) { |
| 1564 #ifdef DEBUG | 1564 #ifdef DEBUG |
| 1565 int original_height = frame_->height(); | 1565 int original_height = frame_->height(); |
| 1566 #endif | 1566 #endif |
| 1567 VirtualFrame::SpilledScope spilled_scope(frame_); | 1567 VirtualFrame::SpilledScope spilled_scope(frame_); |
| 1568 for (int i = 0; frame_ != NULL && i < statements->length(); i++) { | 1568 for (int i = 0; frame_ != NULL && i < statements->length(); i++) { |
| 1569 VisitAndSpill(statements->at(i)); | 1569 Visit(statements->at(i)); |
| 1570 } | 1570 } |
| 1571 ASSERT(!has_valid_frame() || frame_->height() == original_height); | 1571 ASSERT(!has_valid_frame() || frame_->height() == original_height); |
| 1572 } | 1572 } |
| 1573 | 1573 |
| 1574 | 1574 |
| 1575 void CodeGenerator::VisitBlock(Block* node) { | 1575 void CodeGenerator::VisitBlock(Block* node) { |
| 1576 #ifdef DEBUG | 1576 #ifdef DEBUG |
| 1577 int original_height = frame_->height(); | 1577 int original_height = frame_->height(); |
| 1578 #endif | 1578 #endif |
| 1579 VirtualFrame::SpilledScope spilled_scope(frame_); | 1579 VirtualFrame::SpilledScope spilled_scope(frame_); |
| 1580 Comment cmnt(masm_, "[ Block"); | 1580 Comment cmnt(masm_, "[ Block"); |
| 1581 CodeForStatementPosition(node); | 1581 CodeForStatementPosition(node); |
| 1582 node->break_target()->SetExpectedHeight(); | 1582 node->break_target()->SetExpectedHeight(); |
| 1583 VisitStatementsAndSpill(node->statements()); | 1583 VisitStatements(node->statements()); |
| 1584 if (node->break_target()->is_linked()) { | 1584 if (node->break_target()->is_linked()) { |
| 1585 node->break_target()->Bind(); | 1585 node->break_target()->Bind(); |
| 1586 } | 1586 } |
| 1587 node->break_target()->Unuse(); | 1587 node->break_target()->Unuse(); |
| 1588 ASSERT(!has_valid_frame() || frame_->height() == original_height); | 1588 ASSERT(!has_valid_frame() || frame_->height() == original_height); |
| 1589 } | 1589 } |
| 1590 | 1590 |
| 1591 | 1591 |
| 1592 void CodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { | 1592 void CodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { |
| 1593 frame_->EmitPush(cp); | 1593 frame_->EmitPush(cp); |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1688 CodeForStatementPosition(node); | 1688 CodeForStatementPosition(node); |
| 1689 // nothing to do | 1689 // nothing to do |
| 1690 ASSERT(frame_->height() == original_height); | 1690 ASSERT(frame_->height() == original_height); |
| 1691 } | 1691 } |
| 1692 | 1692 |
| 1693 | 1693 |
| 1694 void CodeGenerator::VisitIfStatement(IfStatement* node) { | 1694 void CodeGenerator::VisitIfStatement(IfStatement* node) { |
| 1695 #ifdef DEBUG | 1695 #ifdef DEBUG |
| 1696 int original_height = frame_->height(); | 1696 int original_height = frame_->height(); |
| 1697 #endif | 1697 #endif |
| 1698 VirtualFrame::SpilledScope spilled_scope(frame_); | |
| 1699 Comment cmnt(masm_, "[ IfStatement"); | 1698 Comment cmnt(masm_, "[ IfStatement"); |
| 1700 // Generate different code depending on which parts of the if statement | 1699 // Generate different code depending on which parts of the if statement |
| 1701 // are present or not. | 1700 // are present or not. |
| 1702 bool has_then_stm = node->HasThenStatement(); | 1701 bool has_then_stm = node->HasThenStatement(); |
| 1703 bool has_else_stm = node->HasElseStatement(); | 1702 bool has_else_stm = node->HasElseStatement(); |
| 1704 | 1703 |
| 1705 CodeForStatementPosition(node); | 1704 CodeForStatementPosition(node); |
| 1706 | 1705 |
| 1707 JumpTarget exit; | 1706 JumpTarget exit; |
| 1708 if (has_then_stm && has_else_stm) { | 1707 if (has_then_stm && has_else_stm) { |
| 1709 Comment cmnt(masm_, "[ IfThenElse"); | 1708 Comment cmnt(masm_, "[ IfThenElse"); |
| 1710 JumpTarget then; | 1709 JumpTarget then; |
| 1711 JumpTarget else_; | 1710 JumpTarget else_; |
| 1712 // if (cond) | 1711 // if (cond) |
| 1713 LoadConditionAndSpill(node->condition(), &then, &else_, true); | 1712 LoadCondition(node->condition(), &then, &else_, true); |
| 1714 if (frame_ != NULL) { | 1713 if (frame_ != NULL) { |
| 1715 Branch(false, &else_); | 1714 Branch(false, &else_); |
| 1716 } | 1715 } |
| 1717 // then | 1716 // then |
| 1718 if (frame_ != NULL || then.is_linked()) { | 1717 if (frame_ != NULL || then.is_linked()) { |
| 1719 then.Bind(); | 1718 then.Bind(); |
| 1720 VisitAndSpill(node->then_statement()); | 1719 Visit(node->then_statement()); |
| 1721 } | 1720 } |
| 1722 if (frame_ != NULL) { | 1721 if (frame_ != NULL) { |
| 1723 exit.Jump(); | 1722 exit.Jump(); |
| 1724 } | 1723 } |
| 1725 // else | 1724 // else |
| 1726 if (else_.is_linked()) { | 1725 if (else_.is_linked()) { |
| 1727 else_.Bind(); | 1726 else_.Bind(); |
| 1728 VisitAndSpill(node->else_statement()); | 1727 Visit(node->else_statement()); |
| 1729 } | 1728 } |
| 1730 | 1729 |
| 1731 } else if (has_then_stm) { | 1730 } else if (has_then_stm) { |
| 1732 Comment cmnt(masm_, "[ IfThen"); | 1731 Comment cmnt(masm_, "[ IfThen"); |
| 1733 ASSERT(!has_else_stm); | 1732 ASSERT(!has_else_stm); |
| 1734 JumpTarget then; | 1733 JumpTarget then; |
| 1735 // if (cond) | 1734 // if (cond) |
| 1736 LoadConditionAndSpill(node->condition(), &then, &exit, true); | 1735 LoadCondition(node->condition(), &then, &exit, true); |
| 1737 if (frame_ != NULL) { | 1736 if (frame_ != NULL) { |
| 1738 Branch(false, &exit); | 1737 Branch(false, &exit); |
| 1739 } | 1738 } |
| 1740 // then | 1739 // then |
| 1741 if (frame_ != NULL || then.is_linked()) { | 1740 if (frame_ != NULL || then.is_linked()) { |
| 1742 then.Bind(); | 1741 then.Bind(); |
| 1743 VisitAndSpill(node->then_statement()); | 1742 Visit(node->then_statement()); |
| 1744 } | 1743 } |
| 1745 | 1744 |
| 1746 } else if (has_else_stm) { | 1745 } else if (has_else_stm) { |
| 1747 Comment cmnt(masm_, "[ IfElse"); | 1746 Comment cmnt(masm_, "[ IfElse"); |
| 1748 ASSERT(!has_then_stm); | 1747 ASSERT(!has_then_stm); |
| 1749 JumpTarget else_; | 1748 JumpTarget else_; |
| 1750 // if (!cond) | 1749 // if (!cond) |
| 1751 LoadConditionAndSpill(node->condition(), &exit, &else_, true); | 1750 LoadCondition(node->condition(), &exit, &else_, true); |
| 1752 if (frame_ != NULL) { | 1751 if (frame_ != NULL) { |
| 1753 Branch(true, &exit); | 1752 Branch(true, &exit); |
| 1754 } | 1753 } |
| 1755 // else | 1754 // else |
| 1756 if (frame_ != NULL || else_.is_linked()) { | 1755 if (frame_ != NULL || else_.is_linked()) { |
| 1757 else_.Bind(); | 1756 else_.Bind(); |
| 1758 VisitAndSpill(node->else_statement()); | 1757 Visit(node->else_statement()); |
| 1759 } | 1758 } |
| 1760 | 1759 |
| 1761 } else { | 1760 } else { |
| 1762 Comment cmnt(masm_, "[ If"); | 1761 Comment cmnt(masm_, "[ If"); |
| 1763 ASSERT(!has_then_stm && !has_else_stm); | 1762 ASSERT(!has_then_stm && !has_else_stm); |
| 1764 // if (cond) | 1763 // if (cond) |
| 1765 LoadConditionAndSpill(node->condition(), &exit, &exit, false); | 1764 LoadCondition(node->condition(), &exit, &exit, false); |
| 1766 if (frame_ != NULL) { | 1765 if (frame_ != NULL) { |
| 1767 if (has_cc()) { | 1766 if (has_cc()) { |
| 1768 cc_reg_ = al; | 1767 cc_reg_ = al; |
| 1769 } else { | 1768 } else { |
| 1770 frame_->Drop(); | 1769 frame_->Drop(); |
| 1771 } | 1770 } |
| 1772 } | 1771 } |
| 1773 } | 1772 } |
| 1774 | 1773 |
| 1775 // end | 1774 // end |
| (...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1898 // the stack. | 1897 // the stack. |
| 1899 frame_->Drop(); | 1898 frame_->Drop(); |
| 1900 | 1899 |
| 1901 // Label the body so that fall through is enabled. | 1900 // Label the body so that fall through is enabled. |
| 1902 if (i > 0 && cases->at(i - 1)->is_default()) { | 1901 if (i > 0 && cases->at(i - 1)->is_default()) { |
| 1903 default_exit.Bind(); | 1902 default_exit.Bind(); |
| 1904 } else { | 1903 } else { |
| 1905 fall_through.Bind(); | 1904 fall_through.Bind(); |
| 1906 fall_through.Unuse(); | 1905 fall_through.Unuse(); |
| 1907 } | 1906 } |
| 1908 VisitStatementsAndSpill(clause->statements()); | 1907 VisitStatements(clause->statements()); |
| 1909 | 1908 |
| 1910 // If control flow can fall through from the body, jump to the next body | 1909 // If control flow can fall through from the body, jump to the next body |
| 1911 // or the end of the statement. | 1910 // or the end of the statement. |
| 1912 if (frame_ != NULL) { | 1911 if (frame_ != NULL) { |
| 1913 if (i < length - 1 && cases->at(i + 1)->is_default()) { | 1912 if (i < length - 1 && cases->at(i + 1)->is_default()) { |
| 1914 default_entry.Jump(); | 1913 default_entry.Jump(); |
| 1915 } else { | 1914 } else { |
| 1916 fall_through.Jump(); | 1915 fall_through.Jump(); |
| 1917 } | 1916 } |
| 1918 } | 1917 } |
| 1919 } | 1918 } |
| 1920 | 1919 |
| 1921 // The final "test" removes the switch value. | 1920 // The final "test" removes the switch value. |
| 1922 next_test.Bind(); | 1921 next_test.Bind(); |
| 1923 frame_->Drop(); | 1922 frame_->Drop(); |
| 1924 | 1923 |
| 1925 // If there is a default clause, compile it. | 1924 // If there is a default clause, compile it. |
| 1926 if (default_clause != NULL) { | 1925 if (default_clause != NULL) { |
| 1927 Comment cmnt(masm_, "[ Default clause"); | 1926 Comment cmnt(masm_, "[ Default clause"); |
| 1928 default_entry.Bind(); | 1927 default_entry.Bind(); |
| 1929 VisitStatementsAndSpill(default_clause->statements()); | 1928 VisitStatements(default_clause->statements()); |
| 1930 // If control flow can fall out of the default and there is a case after | 1929 // If control flow can fall out of the default and there is a case after |
| 1931 // it, jup to that case's body. | 1930 // it, jup to that case's body. |
| 1932 if (frame_ != NULL && default_exit.is_bound()) { | 1931 if (frame_ != NULL && default_exit.is_bound()) { |
| 1933 default_exit.Jump(); | 1932 default_exit.Jump(); |
| 1934 } | 1933 } |
| 1935 } | 1934 } |
| 1936 | 1935 |
| 1937 if (fall_through.is_linked()) { | 1936 if (fall_through.is_linked()) { |
| 1938 fall_through.Bind(); | 1937 fall_through.Bind(); |
| 1939 } | 1938 } |
| (...skipping 29 matching lines...) Expand all Loading... |
| 1969 case ALWAYS_FALSE: | 1968 case ALWAYS_FALSE: |
| 1970 node->continue_target()->SetExpectedHeight(); | 1969 node->continue_target()->SetExpectedHeight(); |
| 1971 break; | 1970 break; |
| 1972 case DONT_KNOW: | 1971 case DONT_KNOW: |
| 1973 node->continue_target()->SetExpectedHeight(); | 1972 node->continue_target()->SetExpectedHeight(); |
| 1974 body.Bind(); | 1973 body.Bind(); |
| 1975 break; | 1974 break; |
| 1976 } | 1975 } |
| 1977 | 1976 |
| 1978 CheckStack(); // TODO(1222600): ignore if body contains calls. | 1977 CheckStack(); // TODO(1222600): ignore if body contains calls. |
| 1979 VisitAndSpill(node->body()); | 1978 Visit(node->body()); |
| 1980 | 1979 |
| 1981 // Compile the test. | 1980 // Compile the test. |
| 1982 switch (info) { | 1981 switch (info) { |
| 1983 case ALWAYS_TRUE: | 1982 case ALWAYS_TRUE: |
| 1984 // If control can fall off the end of the body, jump back to the | 1983 // If control can fall off the end of the body, jump back to the |
| 1985 // top. | 1984 // top. |
| 1986 if (has_valid_frame()) { | 1985 if (has_valid_frame()) { |
| 1987 node->continue_target()->Jump(); | 1986 node->continue_target()->Jump(); |
| 1988 } | 1987 } |
| 1989 break; | 1988 break; |
| 1990 case ALWAYS_FALSE: | 1989 case ALWAYS_FALSE: |
| 1991 // If we have a continue in the body, we only have to bind its | 1990 // If we have a continue in the body, we only have to bind its |
| 1992 // jump target. | 1991 // jump target. |
| 1993 if (node->continue_target()->is_linked()) { | 1992 if (node->continue_target()->is_linked()) { |
| 1994 node->continue_target()->Bind(); | 1993 node->continue_target()->Bind(); |
| 1995 } | 1994 } |
| 1996 break; | 1995 break; |
| 1997 case DONT_KNOW: | 1996 case DONT_KNOW: |
| 1998 // We have to compile the test expression if it can be reached by | 1997 // We have to compile the test expression if it can be reached by |
| 1999 // control flow falling out of the body or via continue. | 1998 // control flow falling out of the body or via continue. |
| 2000 if (node->continue_target()->is_linked()) { | 1999 if (node->continue_target()->is_linked()) { |
| 2001 node->continue_target()->Bind(); | 2000 node->continue_target()->Bind(); |
| 2002 } | 2001 } |
| 2003 if (has_valid_frame()) { | 2002 if (has_valid_frame()) { |
| 2004 Comment cmnt(masm_, "[ DoWhileCondition"); | 2003 Comment cmnt(masm_, "[ DoWhileCondition"); |
| 2005 CodeForDoWhileConditionPosition(node); | 2004 CodeForDoWhileConditionPosition(node); |
| 2006 LoadConditionAndSpill(node->cond(), &body, node->break_target(), true); | 2005 LoadCondition(node->cond(), &body, node->break_target(), true); |
| 2007 if (has_valid_frame()) { | 2006 if (has_valid_frame()) { |
| 2008 // A invalid frame here indicates that control did not | 2007 // A invalid frame here indicates that control did not |
| 2009 // fall out of the test expression. | 2008 // fall out of the test expression. |
| 2010 Branch(true, &body); | 2009 Branch(true, &body); |
| 2011 } | 2010 } |
| 2012 } | 2011 } |
| 2013 break; | 2012 break; |
| 2014 } | 2013 } |
| 2015 | 2014 |
| 2016 if (node->break_target()->is_linked()) { | 2015 if (node->break_target()->is_linked()) { |
| (...skipping 20 matching lines...) Expand all Loading... |
| 2037 node->break_target()->SetExpectedHeight(); | 2036 node->break_target()->SetExpectedHeight(); |
| 2038 IncrementLoopNesting(); | 2037 IncrementLoopNesting(); |
| 2039 | 2038 |
| 2040 // Label the top of the loop with the continue target for the backward | 2039 // Label the top of the loop with the continue target for the backward |
| 2041 // CFG edge. | 2040 // CFG edge. |
| 2042 node->continue_target()->SetExpectedHeight(); | 2041 node->continue_target()->SetExpectedHeight(); |
| 2043 node->continue_target()->Bind(); | 2042 node->continue_target()->Bind(); |
| 2044 | 2043 |
| 2045 if (info == DONT_KNOW) { | 2044 if (info == DONT_KNOW) { |
| 2046 JumpTarget body; | 2045 JumpTarget body; |
| 2047 LoadConditionAndSpill(node->cond(), &body, node->break_target(), true); | 2046 LoadCondition(node->cond(), &body, node->break_target(), true); |
| 2048 if (has_valid_frame()) { | 2047 if (has_valid_frame()) { |
| 2049 // A NULL frame indicates that control did not fall out of the | 2048 // A NULL frame indicates that control did not fall out of the |
| 2050 // test expression. | 2049 // test expression. |
| 2051 Branch(false, node->break_target()); | 2050 Branch(false, node->break_target()); |
| 2052 } | 2051 } |
| 2053 if (has_valid_frame() || body.is_linked()) { | 2052 if (has_valid_frame() || body.is_linked()) { |
| 2054 body.Bind(); | 2053 body.Bind(); |
| 2055 } | 2054 } |
| 2056 } | 2055 } |
| 2057 | 2056 |
| 2058 if (has_valid_frame()) { | 2057 if (has_valid_frame()) { |
| 2059 CheckStack(); // TODO(1222600): ignore if body contains calls. | 2058 CheckStack(); // TODO(1222600): ignore if body contains calls. |
| 2060 VisitAndSpill(node->body()); | 2059 Visit(node->body()); |
| 2061 | 2060 |
| 2062 // If control flow can fall out of the body, jump back to the top. | 2061 // If control flow can fall out of the body, jump back to the top. |
| 2063 if (has_valid_frame()) { | 2062 if (has_valid_frame()) { |
| 2064 node->continue_target()->Jump(); | 2063 node->continue_target()->Jump(); |
| 2065 } | 2064 } |
| 2066 } | 2065 } |
| 2067 if (node->break_target()->is_linked()) { | 2066 if (node->break_target()->is_linked()) { |
| 2068 node->break_target()->Bind(); | 2067 node->break_target()->Bind(); |
| 2069 } | 2068 } |
| 2070 DecrementLoopNesting(); | 2069 DecrementLoopNesting(); |
| 2071 ASSERT(!has_valid_frame() || frame_->height() == original_height); | 2070 ASSERT(!has_valid_frame() || frame_->height() == original_height); |
| 2072 } | 2071 } |
| 2073 | 2072 |
| 2074 | 2073 |
| 2075 void CodeGenerator::VisitForStatement(ForStatement* node) { | 2074 void CodeGenerator::VisitForStatement(ForStatement* node) { |
| 2076 #ifdef DEBUG | 2075 #ifdef DEBUG |
| 2077 int original_height = frame_->height(); | 2076 int original_height = frame_->height(); |
| 2078 #endif | 2077 #endif |
| 2079 VirtualFrame::SpilledScope spilled_scope(frame_); | 2078 VirtualFrame::SpilledScope spilled_scope(frame_); |
| 2080 Comment cmnt(masm_, "[ ForStatement"); | 2079 Comment cmnt(masm_, "[ ForStatement"); |
| 2081 CodeForStatementPosition(node); | 2080 CodeForStatementPosition(node); |
| 2082 if (node->init() != NULL) { | 2081 if (node->init() != NULL) { |
| 2083 VisitAndSpill(node->init()); | 2082 Visit(node->init()); |
| 2084 } | 2083 } |
| 2085 | 2084 |
| 2086 // If the test is never true there is no need to compile the test or | 2085 // If the test is never true there is no need to compile the test or |
| 2087 // body. | 2086 // body. |
| 2088 ConditionAnalysis info = AnalyzeCondition(node->cond()); | 2087 ConditionAnalysis info = AnalyzeCondition(node->cond()); |
| 2089 if (info == ALWAYS_FALSE) return; | 2088 if (info == ALWAYS_FALSE) return; |
| 2090 | 2089 |
| 2091 node->break_target()->SetExpectedHeight(); | 2090 node->break_target()->SetExpectedHeight(); |
| 2092 IncrementLoopNesting(); | 2091 IncrementLoopNesting(); |
| 2093 | 2092 |
| 2094 // If there is no update statement, label the top of the loop with the | 2093 // If there is no update statement, label the top of the loop with the |
| 2095 // continue target, otherwise with the loop target. | 2094 // continue target, otherwise with the loop target. |
| 2096 JumpTarget loop(JumpTarget::BIDIRECTIONAL); | 2095 JumpTarget loop(JumpTarget::BIDIRECTIONAL); |
| 2097 if (node->next() == NULL) { | 2096 if (node->next() == NULL) { |
| 2098 node->continue_target()->SetExpectedHeight(); | 2097 node->continue_target()->SetExpectedHeight(); |
| 2099 node->continue_target()->Bind(); | 2098 node->continue_target()->Bind(); |
| 2100 } else { | 2099 } else { |
| 2101 node->continue_target()->SetExpectedHeight(); | 2100 node->continue_target()->SetExpectedHeight(); |
| 2102 loop.Bind(); | 2101 loop.Bind(); |
| 2103 } | 2102 } |
| 2104 | 2103 |
| 2105 // If the test is always true, there is no need to compile it. | 2104 // If the test is always true, there is no need to compile it. |
| 2106 if (info == DONT_KNOW) { | 2105 if (info == DONT_KNOW) { |
| 2107 JumpTarget body; | 2106 JumpTarget body; |
| 2108 LoadConditionAndSpill(node->cond(), &body, node->break_target(), true); | 2107 LoadCondition(node->cond(), &body, node->break_target(), true); |
| 2109 if (has_valid_frame()) { | 2108 if (has_valid_frame()) { |
| 2110 Branch(false, node->break_target()); | 2109 Branch(false, node->break_target()); |
| 2111 } | 2110 } |
| 2112 if (has_valid_frame() || body.is_linked()) { | 2111 if (has_valid_frame() || body.is_linked()) { |
| 2113 body.Bind(); | 2112 body.Bind(); |
| 2114 } | 2113 } |
| 2115 } | 2114 } |
| 2116 | 2115 |
| 2117 if (has_valid_frame()) { | 2116 if (has_valid_frame()) { |
| 2118 CheckStack(); // TODO(1222600): ignore if body contains calls. | 2117 CheckStack(); // TODO(1222600): ignore if body contains calls. |
| 2119 VisitAndSpill(node->body()); | 2118 Visit(node->body()); |
| 2120 | 2119 |
| 2121 if (node->next() == NULL) { | 2120 if (node->next() == NULL) { |
| 2122 // If there is no update statement and control flow can fall out | 2121 // If there is no update statement and control flow can fall out |
| 2123 // of the loop, jump directly to the continue label. | 2122 // of the loop, jump directly to the continue label. |
| 2124 if (has_valid_frame()) { | 2123 if (has_valid_frame()) { |
| 2125 node->continue_target()->Jump(); | 2124 node->continue_target()->Jump(); |
| 2126 } | 2125 } |
| 2127 } else { | 2126 } else { |
| 2128 // If there is an update statement and control flow can reach it | 2127 // If there is an update statement and control flow can reach it |
| 2129 // via falling out of the body of the loop or continuing, we | 2128 // via falling out of the body of the loop or continuing, we |
| 2130 // compile the update statement. | 2129 // compile the update statement. |
| 2131 if (node->continue_target()->is_linked()) { | 2130 if (node->continue_target()->is_linked()) { |
| 2132 node->continue_target()->Bind(); | 2131 node->continue_target()->Bind(); |
| 2133 } | 2132 } |
| 2134 if (has_valid_frame()) { | 2133 if (has_valid_frame()) { |
| 2135 // Record source position of the statement as this code which is | 2134 // Record source position of the statement as this code which is |
| 2136 // after the code for the body actually belongs to the loop | 2135 // after the code for the body actually belongs to the loop |
| 2137 // statement and not the body. | 2136 // statement and not the body. |
| 2138 CodeForStatementPosition(node); | 2137 CodeForStatementPosition(node); |
| 2139 VisitAndSpill(node->next()); | 2138 Visit(node->next()); |
| 2140 loop.Jump(); | 2139 loop.Jump(); |
| 2141 } | 2140 } |
| 2142 } | 2141 } |
| 2143 } | 2142 } |
| 2144 if (node->break_target()->is_linked()) { | 2143 if (node->break_target()->is_linked()) { |
| 2145 node->break_target()->Bind(); | 2144 node->break_target()->Bind(); |
| 2146 } | 2145 } |
| 2147 DecrementLoopNesting(); | 2146 DecrementLoopNesting(); |
| 2148 ASSERT(!has_valid_frame() || frame_->height() == original_height); | 2147 ASSERT(!has_valid_frame() || frame_->height() == original_height); |
| 2149 } | 2148 } |
| (...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2350 // If the reference was to a slot we rely on the convenient property | 2349 // If the reference was to a slot we rely on the convenient property |
| 2351 // that it doesn't matter whether a value (eg, r3 pushed above) is | 2350 // that it doesn't matter whether a value (eg, r3 pushed above) is |
| 2352 // right on top of or right underneath a zero-sized reference. | 2351 // right on top of or right underneath a zero-sized reference. |
| 2353 each.SetValue(NOT_CONST_INIT); | 2352 each.SetValue(NOT_CONST_INIT); |
| 2354 frame_->Drop(); | 2353 frame_->Drop(); |
| 2355 } | 2354 } |
| 2356 } | 2355 } |
| 2357 } | 2356 } |
| 2358 // Body. | 2357 // Body. |
| 2359 CheckStack(); // TODO(1222600): ignore if body contains calls. | 2358 CheckStack(); // TODO(1222600): ignore if body contains calls. |
| 2360 VisitAndSpill(node->body()); | 2359 Visit(node->body()); |
| 2361 | 2360 |
| 2362 // Next. Reestablish a spilled frame in case we are coming here via | 2361 // Next. Reestablish a spilled frame in case we are coming here via |
| 2363 // a continue in the body. | 2362 // a continue in the body. |
| 2364 node->continue_target()->Bind(); | 2363 node->continue_target()->Bind(); |
| 2365 frame_->SpillAll(); | 2364 frame_->SpillAll(); |
| 2366 frame_->EmitPop(r0); | 2365 frame_->EmitPop(r0); |
| 2367 __ add(r0, r0, Operand(Smi::FromInt(1))); | 2366 __ add(r0, r0, Operand(Smi::FromInt(1))); |
| 2368 frame_->EmitPush(r0); | 2367 frame_->EmitPush(r0); |
| 2369 entry.Jump(); | 2368 entry.Jump(); |
| 2370 | 2369 |
| (...skipping 26 matching lines...) Expand all Loading... |
| 2397 frame_->EmitPush(r0); | 2396 frame_->EmitPush(r0); |
| 2398 | 2397 |
| 2399 // Store the caught exception in the catch variable. | 2398 // Store the caught exception in the catch variable. |
| 2400 Variable* catch_var = node->catch_var()->var(); | 2399 Variable* catch_var = node->catch_var()->var(); |
| 2401 ASSERT(catch_var != NULL && catch_var->slot() != NULL); | 2400 ASSERT(catch_var != NULL && catch_var->slot() != NULL); |
| 2402 StoreToSlot(catch_var->slot(), NOT_CONST_INIT); | 2401 StoreToSlot(catch_var->slot(), NOT_CONST_INIT); |
| 2403 | 2402 |
| 2404 // Remove the exception from the stack. | 2403 // Remove the exception from the stack. |
| 2405 frame_->Drop(); | 2404 frame_->Drop(); |
| 2406 | 2405 |
| 2407 VisitStatementsAndSpill(node->catch_block()->statements()); | 2406 VisitStatements(node->catch_block()->statements()); |
| 2408 if (frame_ != NULL) { | 2407 if (frame_ != NULL) { |
| 2409 exit.Jump(); | 2408 exit.Jump(); |
| 2410 } | 2409 } |
| 2411 | 2410 |
| 2412 | 2411 |
| 2413 // --- Try block --- | 2412 // --- Try block --- |
| 2414 try_block.Bind(); | 2413 try_block.Bind(); |
| 2415 | 2414 |
| 2416 frame_->PushTryHandler(TRY_CATCH_HANDLER); | 2415 frame_->PushTryHandler(TRY_CATCH_HANDLER); |
| 2417 int handler_height = frame_->height(); | 2416 int handler_height = frame_->height(); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 2432 bool function_return_was_shadowed = function_return_is_shadowed_; | 2431 bool function_return_was_shadowed = function_return_is_shadowed_; |
| 2433 function_return_is_shadowed_ = true; | 2432 function_return_is_shadowed_ = true; |
| 2434 ASSERT(shadows[kReturnShadowIndex]->other_target() == &function_return_); | 2433 ASSERT(shadows[kReturnShadowIndex]->other_target() == &function_return_); |
| 2435 | 2434 |
| 2436 // Add the remaining shadow targets. | 2435 // Add the remaining shadow targets. |
| 2437 for (int i = 0; i < nof_escapes; i++) { | 2436 for (int i = 0; i < nof_escapes; i++) { |
| 2438 shadows.Add(new ShadowTarget(node->escaping_targets()->at(i))); | 2437 shadows.Add(new ShadowTarget(node->escaping_targets()->at(i))); |
| 2439 } | 2438 } |
| 2440 | 2439 |
| 2441 // Generate code for the statements in the try block. | 2440 // Generate code for the statements in the try block. |
| 2442 VisitStatementsAndSpill(node->try_block()->statements()); | 2441 VisitStatements(node->try_block()->statements()); |
| 2443 | 2442 |
| 2444 // Stop the introduced shadowing and count the number of required unlinks. | 2443 // Stop the introduced shadowing and count the number of required unlinks. |
| 2445 // After shadowing stops, the original labels are unshadowed and the | 2444 // After shadowing stops, the original labels are unshadowed and the |
| 2446 // LabelShadows represent the formerly shadowing labels. | 2445 // LabelShadows represent the formerly shadowing labels. |
| 2447 bool has_unlinks = false; | 2446 bool has_unlinks = false; |
| 2448 for (int i = 0; i < shadows.length(); i++) { | 2447 for (int i = 0; i < shadows.length(); i++) { |
| 2449 shadows[i]->StopShadowing(); | 2448 shadows[i]->StopShadowing(); |
| 2450 has_unlinks = has_unlinks || shadows[i]->is_linked(); | 2449 has_unlinks = has_unlinks || shadows[i]->is_linked(); |
| 2451 } | 2450 } |
| 2452 function_return_is_shadowed_ = function_return_was_shadowed; | 2451 function_return_is_shadowed_ = function_return_was_shadowed; |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2546 bool function_return_was_shadowed = function_return_is_shadowed_; | 2545 bool function_return_was_shadowed = function_return_is_shadowed_; |
| 2547 function_return_is_shadowed_ = true; | 2546 function_return_is_shadowed_ = true; |
| 2548 ASSERT(shadows[kReturnShadowIndex]->other_target() == &function_return_); | 2547 ASSERT(shadows[kReturnShadowIndex]->other_target() == &function_return_); |
| 2549 | 2548 |
| 2550 // Add the remaining shadow targets. | 2549 // Add the remaining shadow targets. |
| 2551 for (int i = 0; i < nof_escapes; i++) { | 2550 for (int i = 0; i < nof_escapes; i++) { |
| 2552 shadows.Add(new ShadowTarget(node->escaping_targets()->at(i))); | 2551 shadows.Add(new ShadowTarget(node->escaping_targets()->at(i))); |
| 2553 } | 2552 } |
| 2554 | 2553 |
| 2555 // Generate code for the statements in the try block. | 2554 // Generate code for the statements in the try block. |
| 2556 VisitStatementsAndSpill(node->try_block()->statements()); | 2555 VisitStatements(node->try_block()->statements()); |
| 2557 | 2556 |
| 2558 // Stop the introduced shadowing and count the number of required unlinks. | 2557 // Stop the introduced shadowing and count the number of required unlinks. |
| 2559 // After shadowing stops, the original labels are unshadowed and the | 2558 // After shadowing stops, the original labels are unshadowed and the |
| 2560 // LabelShadows represent the formerly shadowing labels. | 2559 // LabelShadows represent the formerly shadowing labels. |
| 2561 int nof_unlinks = 0; | 2560 int nof_unlinks = 0; |
| 2562 for (int i = 0; i < shadows.length(); i++) { | 2561 for (int i = 0; i < shadows.length(); i++) { |
| 2563 shadows[i]->StopShadowing(); | 2562 shadows[i]->StopShadowing(); |
| 2564 if (shadows[i]->is_linked()) nof_unlinks++; | 2563 if (shadows[i]->is_linked()) nof_unlinks++; |
| 2565 } | 2564 } |
| 2566 function_return_is_shadowed_ = function_return_was_shadowed; | 2565 function_return_is_shadowed_ = function_return_was_shadowed; |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2636 // --- Finally block --- | 2635 // --- Finally block --- |
| 2637 finally_block.Bind(); | 2636 finally_block.Bind(); |
| 2638 | 2637 |
| 2639 // Push the state on the stack. | 2638 // Push the state on the stack. |
| 2640 frame_->EmitPush(r2); | 2639 frame_->EmitPush(r2); |
| 2641 | 2640 |
| 2642 // We keep two elements on the stack - the (possibly faked) result | 2641 // We keep two elements on the stack - the (possibly faked) result |
| 2643 // and the state - while evaluating the finally block. | 2642 // and the state - while evaluating the finally block. |
| 2644 // | 2643 // |
| 2645 // Generate code for the statements in the finally block. | 2644 // Generate code for the statements in the finally block. |
| 2646 VisitStatementsAndSpill(node->finally_block()->statements()); | 2645 VisitStatements(node->finally_block()->statements()); |
| 2647 | 2646 |
| 2648 if (has_valid_frame()) { | 2647 if (has_valid_frame()) { |
| 2649 // Restore state and return value or faked TOS. | 2648 // Restore state and return value or faked TOS. |
| 2650 frame_->EmitPop(r2); | 2649 frame_->EmitPop(r2); |
| 2651 frame_->EmitPop(r0); | 2650 frame_->EmitPop(r0); |
| 2652 } | 2651 } |
| 2653 | 2652 |
| 2654 // Generate code to jump to the right destination for all used | 2653 // Generate code to jump to the right destination for all used |
| 2655 // formerly shadowing targets. Deallocate each shadow target. | 2654 // formerly shadowing targets. Deallocate each shadow target. |
| 2656 for (int i = 0; i < shadows.length(); i++) { | 2655 for (int i = 0; i < shadows.length(); i++) { |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2751 | 2750 |
| 2752 | 2751 |
| 2753 void CodeGenerator::VisitConditional(Conditional* node) { | 2752 void CodeGenerator::VisitConditional(Conditional* node) { |
| 2754 #ifdef DEBUG | 2753 #ifdef DEBUG |
| 2755 int original_height = frame_->height(); | 2754 int original_height = frame_->height(); |
| 2756 #endif | 2755 #endif |
| 2757 VirtualFrame::SpilledScope spilled_scope(frame_); | 2756 VirtualFrame::SpilledScope spilled_scope(frame_); |
| 2758 Comment cmnt(masm_, "[ Conditional"); | 2757 Comment cmnt(masm_, "[ Conditional"); |
| 2759 JumpTarget then; | 2758 JumpTarget then; |
| 2760 JumpTarget else_; | 2759 JumpTarget else_; |
| 2761 LoadConditionAndSpill(node->condition(), &then, &else_, true); | 2760 LoadCondition(node->condition(), &then, &else_, true); |
| 2762 if (has_valid_frame()) { | 2761 if (has_valid_frame()) { |
| 2763 Branch(false, &else_); | 2762 Branch(false, &else_); |
| 2764 } | 2763 } |
| 2765 if (has_valid_frame() || then.is_linked()) { | 2764 if (has_valid_frame() || then.is_linked()) { |
| 2766 then.Bind(); | 2765 then.Bind(); |
| 2767 Load(node->then_expression()); | 2766 Load(node->then_expression()); |
| 2768 } | 2767 } |
| 2769 if (else_.is_linked()) { | 2768 if (else_.is_linked()) { |
| 2770 JumpTarget exit; | 2769 JumpTarget exit; |
| 2771 if (has_valid_frame()) exit.Jump(); | 2770 if (has_valid_frame()) exit.Jump(); |
| (...skipping 1277 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4049 } | 4048 } |
| 4050 | 4049 |
| 4051 | 4050 |
| 4052 void CodeGenerator::GenerateLog(ZoneList<Expression*>* args) { | 4051 void CodeGenerator::GenerateLog(ZoneList<Expression*>* args) { |
| 4053 // See comment in CodeGenerator::GenerateLog in codegen-ia32.cc. | 4052 // See comment in CodeGenerator::GenerateLog in codegen-ia32.cc. |
| 4054 ASSERT_EQ(args->length(), 3); | 4053 ASSERT_EQ(args->length(), 3); |
| 4055 #ifdef ENABLE_LOGGING_AND_PROFILING | 4054 #ifdef ENABLE_LOGGING_AND_PROFILING |
| 4056 if (ShouldGenerateLog(args->at(0))) { | 4055 if (ShouldGenerateLog(args->at(0))) { |
| 4057 Load(args->at(1)); | 4056 Load(args->at(1)); |
| 4058 Load(args->at(2)); | 4057 Load(args->at(2)); |
| 4059 frame_->SpillAll(); | |
| 4060 frame_->CallRuntime(Runtime::kLog, 2); | 4058 frame_->CallRuntime(Runtime::kLog, 2); |
| 4061 } | 4059 } |
| 4062 #endif | 4060 #endif |
| 4063 frame_->EmitPushRoot(Heap::kUndefinedValueRootIndex); | 4061 frame_->EmitPushRoot(Heap::kUndefinedValueRootIndex); |
| 4064 } | 4062 } |
| 4065 | 4063 |
| 4066 | 4064 |
| 4067 void CodeGenerator::GenerateIsNonNegativeSmi(ZoneList<Expression*>* args) { | 4065 void CodeGenerator::GenerateIsNonNegativeSmi(ZoneList<Expression*>* args) { |
| 4068 ASSERT(args->length() == 1); | 4066 ASSERT(args->length() == 1); |
| 4069 Load(args->at(0)); | 4067 Load(args->at(0)); |
| (...skipping 877 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4947 void CodeGenerator::VisitUnaryOperation(UnaryOperation* node) { | 4945 void CodeGenerator::VisitUnaryOperation(UnaryOperation* node) { |
| 4948 #ifdef DEBUG | 4946 #ifdef DEBUG |
| 4949 int original_height = frame_->height(); | 4947 int original_height = frame_->height(); |
| 4950 #endif | 4948 #endif |
| 4951 VirtualFrame::SpilledScope spilled_scope(frame_); | 4949 VirtualFrame::SpilledScope spilled_scope(frame_); |
| 4952 Comment cmnt(masm_, "[ UnaryOperation"); | 4950 Comment cmnt(masm_, "[ UnaryOperation"); |
| 4953 | 4951 |
| 4954 Token::Value op = node->op(); | 4952 Token::Value op = node->op(); |
| 4955 | 4953 |
| 4956 if (op == Token::NOT) { | 4954 if (op == Token::NOT) { |
| 4957 LoadConditionAndSpill(node->expression(), | 4955 LoadCondition(node->expression(), false_target(), true_target(), true); |
| 4958 false_target(), | |
| 4959 true_target(), | |
| 4960 true); | |
| 4961 // LoadCondition may (and usually does) leave a test and branch to | 4956 // LoadCondition may (and usually does) leave a test and branch to |
| 4962 // be emitted by the caller. In that case, negate the condition. | 4957 // be emitted by the caller. In that case, negate the condition. |
| 4963 if (has_cc()) cc_reg_ = NegateCondition(cc_reg_); | 4958 if (has_cc()) cc_reg_ = NegateCondition(cc_reg_); |
| 4964 | 4959 |
| 4965 } else if (op == Token::DELETE) { | 4960 } else if (op == Token::DELETE) { |
| 4966 Property* property = node->expression()->AsProperty(); | 4961 Property* property = node->expression()->AsProperty(); |
| 4967 Variable* variable = node->expression()->AsVariableProxy()->AsVariable(); | 4962 Variable* variable = node->expression()->AsVariableProxy()->AsVariable(); |
| 4968 if (property != NULL) { | 4963 if (property != NULL) { |
| 4969 Load(property->obj()); | 4964 Load(property->obj()); |
| 4970 Load(property->key()); | 4965 Load(property->key()); |
| (...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5193 | 5188 |
| 5194 // NOTE: If the left hand side produces a materialized value (not in | 5189 // NOTE: If the left hand side produces a materialized value (not in |
| 5195 // the CC register), we force the right hand side to do the | 5190 // the CC register), we force the right hand side to do the |
| 5196 // same. This is necessary because we may have to branch to the exit | 5191 // same. This is necessary because we may have to branch to the exit |
| 5197 // after evaluating the left hand side (due to the shortcut | 5192 // after evaluating the left hand side (due to the shortcut |
| 5198 // semantics), but the compiler must (statically) know if the result | 5193 // semantics), but the compiler must (statically) know if the result |
| 5199 // of compiling the binary operation is materialized or not. | 5194 // of compiling the binary operation is materialized or not. |
| 5200 VirtualFrame::SpilledScope spilled_scope(frame_); | 5195 VirtualFrame::SpilledScope spilled_scope(frame_); |
| 5201 if (node->op() == Token::AND) { | 5196 if (node->op() == Token::AND) { |
| 5202 JumpTarget is_true; | 5197 JumpTarget is_true; |
| 5203 LoadConditionAndSpill(node->left(), | 5198 LoadCondition(node->left(), &is_true, false_target(), false); |
| 5204 &is_true, | |
| 5205 false_target(), | |
| 5206 false); | |
| 5207 if (has_valid_frame() && !has_cc()) { | 5199 if (has_valid_frame() && !has_cc()) { |
| 5208 // The left-hand side result is on top of the virtual frame. | 5200 // The left-hand side result is on top of the virtual frame. |
| 5209 JumpTarget pop_and_continue; | 5201 JumpTarget pop_and_continue; |
| 5210 JumpTarget exit; | 5202 JumpTarget exit; |
| 5211 | 5203 |
| 5212 frame_->Dup(); | 5204 frame_->Dup(); |
| 5213 // Avoid popping the result if it converts to 'false' using the | 5205 // Avoid popping the result if it converts to 'false' using the |
| 5214 // standard ToBoolean() conversion as described in ECMA-262, | 5206 // standard ToBoolean() conversion as described in ECMA-262, |
| 5215 // section 9.2, page 30. | 5207 // section 9.2, page 30. |
| 5216 ToBoolean(&pop_and_continue, &exit); | 5208 ToBoolean(&pop_and_continue, &exit); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 5227 // Exit (always with a materialized value). | 5219 // Exit (always with a materialized value). |
| 5228 exit.Bind(); | 5220 exit.Bind(); |
| 5229 } else if (has_cc() || is_true.is_linked()) { | 5221 } else if (has_cc() || is_true.is_linked()) { |
| 5230 // The left-hand side is either (a) partially compiled to | 5222 // The left-hand side is either (a) partially compiled to |
| 5231 // control flow with a final branch left to emit or (b) fully | 5223 // control flow with a final branch left to emit or (b) fully |
| 5232 // compiled to control flow and possibly true. | 5224 // compiled to control flow and possibly true. |
| 5233 if (has_cc()) { | 5225 if (has_cc()) { |
| 5234 Branch(false, false_target()); | 5226 Branch(false, false_target()); |
| 5235 } | 5227 } |
| 5236 is_true.Bind(); | 5228 is_true.Bind(); |
| 5237 LoadConditionAndSpill(node->right(), | 5229 LoadCondition(node->right(), true_target(), false_target(), false); |
| 5238 true_target(), | |
| 5239 false_target(), | |
| 5240 false); | |
| 5241 } else { | 5230 } else { |
| 5242 // Nothing to do. | 5231 // Nothing to do. |
| 5243 ASSERT(!has_valid_frame() && !has_cc() && !is_true.is_linked()); | 5232 ASSERT(!has_valid_frame() && !has_cc() && !is_true.is_linked()); |
| 5244 } | 5233 } |
| 5245 | 5234 |
| 5246 } else { | 5235 } else { |
| 5247 ASSERT(node->op() == Token::OR); | 5236 ASSERT(node->op() == Token::OR); |
| 5248 JumpTarget is_false; | 5237 JumpTarget is_false; |
| 5249 LoadConditionAndSpill(node->left(), | 5238 LoadCondition(node->left(), true_target(), &is_false, false); |
| 5250 true_target(), | |
| 5251 &is_false, | |
| 5252 false); | |
| 5253 if (has_valid_frame() && !has_cc()) { | 5239 if (has_valid_frame() && !has_cc()) { |
| 5254 // The left-hand side result is on top of the virtual frame. | 5240 // The left-hand side result is on top of the virtual frame. |
| 5255 JumpTarget pop_and_continue; | 5241 JumpTarget pop_and_continue; |
| 5256 JumpTarget exit; | 5242 JumpTarget exit; |
| 5257 | 5243 |
| 5258 frame_->Dup(); | 5244 frame_->Dup(); |
| 5259 // Avoid popping the result if it converts to 'true' using the | 5245 // Avoid popping the result if it converts to 'true' using the |
| 5260 // standard ToBoolean() conversion as described in ECMA-262, | 5246 // standard ToBoolean() conversion as described in ECMA-262, |
| 5261 // section 9.2, page 30. | 5247 // section 9.2, page 30. |
| 5262 ToBoolean(&exit, &pop_and_continue); | 5248 ToBoolean(&exit, &pop_and_continue); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 5273 // Exit (always with a materialized value). | 5259 // Exit (always with a materialized value). |
| 5274 exit.Bind(); | 5260 exit.Bind(); |
| 5275 } else if (has_cc() || is_false.is_linked()) { | 5261 } else if (has_cc() || is_false.is_linked()) { |
| 5276 // The left-hand side is either (a) partially compiled to | 5262 // The left-hand side is either (a) partially compiled to |
| 5277 // control flow with a final branch left to emit or (b) fully | 5263 // control flow with a final branch left to emit or (b) fully |
| 5278 // compiled to control flow and possibly false. | 5264 // compiled to control flow and possibly false. |
| 5279 if (has_cc()) { | 5265 if (has_cc()) { |
| 5280 Branch(true, true_target()); | 5266 Branch(true, true_target()); |
| 5281 } | 5267 } |
| 5282 is_false.Bind(); | 5268 is_false.Bind(); |
| 5283 LoadConditionAndSpill(node->right(), | 5269 LoadCondition(node->right(), true_target(), false_target(), false); |
| 5284 true_target(), | |
| 5285 false_target(), | |
| 5286 false); | |
| 5287 } else { | 5270 } else { |
| 5288 // Nothing to do. | 5271 // Nothing to do. |
| 5289 ASSERT(!has_valid_frame() && !has_cc() && !is_false.is_linked()); | 5272 ASSERT(!has_valid_frame() && !has_cc() && !is_false.is_linked()); |
| 5290 } | 5273 } |
| 5291 } | 5274 } |
| 5292 } | 5275 } |
| 5293 | 5276 |
| 5294 | 5277 |
| 5295 void CodeGenerator::VisitBinaryOperation(BinaryOperation* node) { | 5278 void CodeGenerator::VisitBinaryOperation(BinaryOperation* node) { |
| 5296 #ifdef DEBUG | 5279 #ifdef DEBUG |
| (...skipping 4986 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10283 __ bind(&string_add_runtime); | 10266 __ bind(&string_add_runtime); |
| 10284 __ TailCallRuntime(Runtime::kStringAdd, 2, 1); | 10267 __ TailCallRuntime(Runtime::kStringAdd, 2, 1); |
| 10285 } | 10268 } |
| 10286 | 10269 |
| 10287 | 10270 |
| 10288 #undef __ | 10271 #undef __ |
| 10289 | 10272 |
| 10290 } } // namespace v8::internal | 10273 } } // namespace v8::internal |
| 10291 | 10274 |
| 10292 #endif // V8_TARGET_ARCH_ARM | 10275 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |