| 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 | 
|---|