Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2)

Side by Side Diff: src/x64/codegen-x64.cc

Issue 2835030: X64: Made simpler version of fast-smi-loop code. (Closed)
Patch Set: Addressed review comments Created 10 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/x64/codegen-x64.h ('k') | src/x64/virtual-frame-x64.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
OLDNEW
« no previous file with comments | « src/x64/codegen-x64.h ('k') | src/x64/virtual-frame-x64.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698