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

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

Issue 21040: Experimental: handle single-entry basic blocks as a special case.... (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/toiger/
Patch Set: '' Created 11 years, 10 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 | Annotate | Revision Log
« no previous file with comments | « src/codegen-ia32.h ('k') | src/jump-target.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 2006-2008 the V8 project authors. All rights reserved. 1 // Copyright 2006-2008 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 1425 matching lines...) Expand 10 before | Expand all | Expand 10 after
1436 } 1436 }
1437 1437
1438 1438
1439 void CodeGenerator::VisitBlock(Block* node) { 1439 void CodeGenerator::VisitBlock(Block* node) {
1440 ASSERT(!in_spilled_code()); 1440 ASSERT(!in_spilled_code());
1441 Comment cmnt(masm_, "[ Block"); 1441 Comment cmnt(masm_, "[ Block");
1442 CodeForStatementPosition(node); 1442 CodeForStatementPosition(node);
1443 node->set_break_stack_height(break_stack_height_); 1443 node->set_break_stack_height(break_stack_height_);
1444 node->break_target()->Initialize(this); 1444 node->break_target()->Initialize(this);
1445 VisitStatements(node->statements()); 1445 VisitStatements(node->statements());
1446 if (node->break_target()->is_linked()) { 1446 node->break_target()->Bind();
1447 node->break_target()->Bind();
1448 }
1449 } 1447 }
1450 1448
1451 1449
1452 void CodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { 1450 void CodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
1453 VirtualFrame::SpilledScope spilled_scope(this); 1451 VirtualFrame::SpilledScope spilled_scope(this);
1454 frame_->EmitPush(Immediate(pairs)); 1452 frame_->EmitPush(Immediate(pairs));
1455 frame_->EmitPush(esi); 1453 frame_->EmitPush(esi);
1456 frame_->EmitPush(Immediate(Smi::FromInt(is_eval() ? 1 : 0))); 1454 frame_->EmitPush(Immediate(Smi::FromInt(is_eval() ? 1 : 0)));
1457 frame_->CallRuntime(Runtime::kDeclareGlobals, 3); 1455 frame_->CallRuntime(Runtime::kDeclareGlobals, 3);
1458 // Return value is ignored. 1456 // Return value is ignored.
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after
1595 // or control flow effect). LoadCondition is called without 1593 // or control flow effect). LoadCondition is called without
1596 // forcing control flow. 1594 // forcing control flow.
1597 LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &exit, &exit, false); 1595 LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &exit, &exit, false);
1598 if (has_valid_frame()) { 1596 if (has_valid_frame()) {
1599 // Control flow can fall off the end of the condition with a 1597 // Control flow can fall off the end of the condition with a
1600 // value on the frame. 1598 // value on the frame.
1601 frame_->Drop(); 1599 frame_->Drop();
1602 } 1600 }
1603 } 1601 }
1604 1602
1605 if (exit.is_linked()) { 1603 exit.Bind();
1606 exit.Bind();
1607 }
1608 } 1604 }
1609 1605
1610 1606
1611 void CodeGenerator::CleanStack(int num_bytes) { 1607 void CodeGenerator::CleanStack(int num_bytes) {
1612 ASSERT(num_bytes % kPointerSize == 0); 1608 ASSERT(num_bytes % kPointerSize == 0);
1613 frame_->Drop(num_bytes / kPointerSize); 1609 frame_->Drop(num_bytes / kPointerSize);
1614 } 1610 }
1615 1611
1616 1612
1617 void CodeGenerator::VisitContinueStatement(ContinueStatement* node) { 1613 void CodeGenerator::VisitContinueStatement(ContinueStatement* node) {
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after
1748 int CodeGenerator::FastCaseSwitchMinCaseCount() { 1744 int CodeGenerator::FastCaseSwitchMinCaseCount() {
1749 return kFastSwitchMinCaseCount; 1745 return kFastSwitchMinCaseCount;
1750 } 1746 }
1751 1747
1752 1748
1753 // Generate a computed jump to a switch case. 1749 // Generate a computed jump to a switch case.
1754 void CodeGenerator::GenerateFastCaseSwitchJumpTable( 1750 void CodeGenerator::GenerateFastCaseSwitchJumpTable(
1755 SwitchStatement* node, 1751 SwitchStatement* node,
1756 int min_index, 1752 int min_index,
1757 int range, 1753 int range,
1758 JumpTarget* fail_label, 1754 Label* default_label,
1759 Vector<JumpTarget*> case_targets, 1755 Vector<Label*> case_targets,
1760 Vector<JumpTarget> case_labels) { 1756 Vector<Label> case_labels) {
1761 // Notice: Internal references, used by both the jmp instruction and 1757 // Notice: Internal references, used by both the jmp instruction and
1762 // the table entries, need to be relocated if the buffer grows. This 1758 // the table entries, need to be relocated if the buffer grows. This
1763 // prevents the forward use of Labels, since a displacement cannot 1759 // prevents the forward use of Labels, since a displacement cannot
1764 // survive relocation, and it also cannot safely be distinguished 1760 // survive relocation, and it also cannot safely be distinguished
1765 // from a real address. Instead we put in zero-values as 1761 // from a real address. Instead we put in zero-values as
1766 // placeholders, and fill in the addresses after the labels have been 1762 // placeholders, and fill in the addresses after the labels have been
1767 // bound. 1763 // bound.
1768 1764
1769 Result switch_value = frame_->Pop(); // supposed Smi 1765 JumpTarget setup_default(this);
1770 // If value is not in range [0..length-1] then jump to the default/end label. 1766 JumpTarget is_smi(this);
1767
1768 // A non-null default label pointer indicates a default case among
1769 // the case labels. Otherwise we use the break target as a
1770 // "default".
1771 JumpTarget* default_target =
1772 (default_label == NULL) ? node->break_target() : &setup_default;
1773
1774 // Test whether input is a smi.
1771 ASSERT(kSmiTagSize == 1 && kSmiTag == 0); 1775 ASSERT(kSmiTagSize == 1 && kSmiTag == 0);
1772 1776 Result switch_value = frame_->Pop();
1773 // Test whether input is a HeapNumber that is really a Smi
1774 JumpTarget is_smi(this);
1775 switch_value.ToRegister(); 1777 switch_value.ToRegister();
1776 __ test(switch_value.reg(), Immediate(kSmiTagMask)); 1778 __ test(switch_value.reg(), Immediate(kSmiTagMask));
1777 is_smi.Branch(equal, &switch_value, taken); 1779 is_smi.Branch(equal, &switch_value, taken);
1778 // It's a heap object, not a Smi or a Failure 1780
1781 // It's a heap object, not a smi or a failure. Check if it is a
1782 // heap number.
1779 Result temp = allocator()->Allocate(); 1783 Result temp = allocator()->Allocate();
1780 ASSERT(temp.is_valid()); 1784 ASSERT(temp.is_valid());
1781 __ mov(temp.reg(), FieldOperand(switch_value.reg(), HeapObject::kMapOffset)); 1785 __ mov(temp.reg(), FieldOperand(switch_value.reg(), HeapObject::kMapOffset));
1782 __ movzx_b(temp.reg(), FieldOperand(temp.reg(), Map::kInstanceTypeOffset)); 1786 __ movzx_b(temp.reg(), FieldOperand(temp.reg(), Map::kInstanceTypeOffset));
1783 __ cmp(temp.reg(), HEAP_NUMBER_TYPE); 1787 __ cmp(temp.reg(), HEAP_NUMBER_TYPE);
1784 temp.Unuse(); 1788 temp.Unuse();
1785 fail_label->Branch(not_equal); 1789 default_target->Branch(not_equal);
1786 // Result switch_value is a heap number. 1790
1791 // The switch value is a heap number. Convert it to a smi.
1787 frame_->Push(&switch_value); 1792 frame_->Push(&switch_value);
1788 Result smi_value = frame_->CallRuntime(Runtime::kNumberToSmi, 1); 1793 Result smi_value = frame_->CallRuntime(Runtime::kNumberToSmi, 1);
1794
1789 is_smi.Bind(&smi_value); 1795 is_smi.Bind(&smi_value);
1790 smi_value.ToRegister(); 1796 smi_value.ToRegister();
1791 1797 // Convert the switch value to a 0-based table index.
1792 if (min_index != 0) { 1798 if (min_index != 0) {
1793 frame_->Spill(smi_value.reg()); 1799 frame_->Spill(smi_value.reg());
1794 __ sub(Operand(smi_value.reg()), Immediate(min_index << kSmiTagSize)); 1800 __ sub(Operand(smi_value.reg()), Immediate(min_index << kSmiTagSize));
1795 } 1801 }
1802 // Go to the default case if the table index is negative or not a smi.
1796 __ test(smi_value.reg(), Immediate(0x80000000 | kSmiTagMask)); 1803 __ test(smi_value.reg(), Immediate(0x80000000 | kSmiTagMask));
1797 // Go to slow case if adjusted index is negative or not a Smi. 1804 default_target->Branch(not_equal, not_taken);
1798 fail_label->Branch(not_equal, not_taken);
1799 __ cmp(smi_value.reg(), range << kSmiTagSize); 1805 __ cmp(smi_value.reg(), range << kSmiTagSize);
1800 fail_label->Branch(greater_equal, not_taken); 1806 default_target->Branch(greater_equal, not_taken);
1801 1807
1802 // 0 is placeholder. 1808 // 0 is placeholder.
1803 // Jump to the address at table_address + 2 * smi_value.reg(). 1809 // Jump to the address at table_address + 2 * smi_value.reg().
1804 // The target of the jump is read from table_address + 4 * switch_value. 1810 // The target of the jump is read from table_address + 4 * switch_value.
1805 // The Smi encoding of smi_value.reg() is 2 * switch_value. 1811 // The Smi encoding of smi_value.reg() is 2 * switch_value.
1806 __ jmp(Operand(smi_value.reg(), smi_value.reg(), 1812 __ jmp(Operand(smi_value.reg(), smi_value.reg(),
1807 times_1, 0x0, RelocInfo::INTERNAL_REFERENCE)); 1813 times_1, 0x0, RelocInfo::INTERNAL_REFERENCE));
1814 smi_value.Unuse();
1815
1816 // The expected frame at all the case labels is the (mergable
1817 // version of the) current one. Keep a copy to restore at the start
1818 // of every label.
1819 frame_->MakeMergable();
1820 VirtualFrame* start_frame = new VirtualFrame(frame_);
1821
1808 // Calculate address to overwrite later with actual address of table. 1822 // Calculate address to overwrite later with actual address of table.
1809 int32_t jump_table_ref = __ pc_offset() - sizeof(int32_t); 1823 int32_t jump_table_ref = __ pc_offset() - sizeof(int32_t);
1810
1811 __ Align(4); 1824 __ Align(4);
1812 JumpTarget table_start(this); 1825 Label table_start;
1813 smi_value.Unuse(); 1826 __ bind(&table_start);
1814 table_start.Bind(); 1827 __ WriteInternalReference(jump_table_ref, table_start);
1815 __ WriteInternalReference(jump_table_ref, *table_start.entry_label());
1816 1828
1817 for (int i = 0; i < range; i++) { 1829 for (int i = 0; i < range; i++) {
1818 // These are the table entries. 0x0 is the placeholder for case address. 1830 // These are the table entries. 0x0 is the placeholder for case address.
1819 __ dd(0x0, RelocInfo::INTERNAL_REFERENCE); 1831 __ dd(0x0, RelocInfo::INTERNAL_REFERENCE);
1820 } 1832 }
1821 1833
1822 GenerateFastCaseSwitchCases(node, case_labels, &table_start); 1834 GenerateFastCaseSwitchCases(node, case_labels, start_frame);
1823 1835
1824 for (int i = 0, entry_pos = table_start.entry_label()->pos(); 1836 // If there was a default case, we need to emit the code to match it.
1837 if (default_label != NULL) {
1838 node->break_target()->Jump();
1839 setup_default.Bind();
1840 frame_->MergeTo(start_frame);
1841 __ jmp(default_label);
1842 DeleteFrame();
1843 }
1844 node->break_target()->Bind();
1845
1846 for (int i = 0, entry_pos = table_start.pos();
1825 i < range; 1847 i < range;
1826 i++, entry_pos += sizeof(uint32_t)) { 1848 i++, entry_pos += sizeof(uint32_t)) {
1827 __ WriteInternalReference(entry_pos, *case_targets[i]->entry_label()); 1849 if (case_targets[i] == NULL) {
1850 __ WriteInternalReference(entry_pos,
1851 *node->break_target()->entry_label());
1852 } else {
1853 __ WriteInternalReference(entry_pos, *case_targets[i]);
1854 }
1828 } 1855 }
1856
1857 delete start_frame;
1829 } 1858 }
1830 1859
1831 1860
1832 void CodeGenerator::VisitSwitchStatement(SwitchStatement* node) { 1861 void CodeGenerator::VisitSwitchStatement(SwitchStatement* node) {
1833 ASSERT(!in_spilled_code()); 1862 ASSERT(!in_spilled_code());
1834 Comment cmnt(masm_, "[ SwitchStatement"); 1863 Comment cmnt(masm_, "[ SwitchStatement");
1835 CodeForStatementPosition(node); 1864 CodeForStatementPosition(node);
1836 node->set_break_stack_height(break_stack_height_); 1865 node->set_break_stack_height(break_stack_height_);
1837 node->break_target()->Initialize(this); 1866 node->break_target()->Initialize(this);
1838 1867
1839 Load(node->tag()); 1868 Load(node->tag());
1840
1841 if (TryGenerateFastCaseSwitchStatement(node)) { 1869 if (TryGenerateFastCaseSwitchStatement(node)) {
1842 return; 1870 return;
1843 } 1871 }
1844 1872
1845 JumpTarget next_test(this); 1873 JumpTarget next_test(this);
1846 JumpTarget fall_through(this); 1874 JumpTarget fall_through(this);
1847 JumpTarget default_entry(this); 1875 JumpTarget default_entry(this);
1848 JumpTarget default_exit(this, JumpTarget::BIDIRECTIONAL); 1876 JumpTarget default_exit(this, JumpTarget::BIDIRECTIONAL);
1849 ZoneList<CaseClause*>* cases = node->cases(); 1877 ZoneList<CaseClause*>* cases = node->cases();
1850 int length = cases->length(); 1878 int length = cases->length();
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
1911 Comment cmnt(masm_, "[ Default clause"); 1939 Comment cmnt(masm_, "[ Default clause");
1912 default_entry.Bind(); 1940 default_entry.Bind();
1913 VisitStatements(default_clause->statements()); 1941 VisitStatements(default_clause->statements());
1914 // If control flow can fall out of the default and there is a case after 1942 // If control flow can fall out of the default and there is a case after
1915 // it, jump to that case's body. 1943 // it, jump to that case's body.
1916 if (has_valid_frame() && default_exit.is_bound()) { 1944 if (has_valid_frame() && default_exit.is_bound()) {
1917 default_exit.Jump(); 1945 default_exit.Jump();
1918 } 1946 }
1919 } 1947 }
1920 1948
1921 if (fall_through.is_linked()) { 1949 fall_through.Bind();
1922 fall_through.Bind(); 1950 node->break_target()->Bind();
1923 }
1924
1925 if (node->break_target()->is_linked()) {
1926 node->break_target()->Bind();
1927 }
1928 } 1951 }
1929 1952
1930 1953
1931 void CodeGenerator::VisitLoopStatement(LoopStatement* node) { 1954 void CodeGenerator::VisitLoopStatement(LoopStatement* node) {
1932 ASSERT(!in_spilled_code()); 1955 ASSERT(!in_spilled_code());
1933 Comment cmnt(masm_, "[ LoopStatement"); 1956 Comment cmnt(masm_, "[ LoopStatement");
1934 CodeForStatementPosition(node); 1957 CodeForStatementPosition(node);
1935 node->set_break_stack_height(break_stack_height_); 1958 node->set_break_stack_height(break_stack_height_);
1936 node->break_target()->Initialize(this); 1959 node->break_target()->Initialize(this);
1937 1960
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
1977 2000
1978 // Compile the test. 2001 // Compile the test.
1979 if (info == ALWAYS_TRUE) { 2002 if (info == ALWAYS_TRUE) {
1980 // If control flow can fall off the end of the body, jump back to 2003 // If control flow can fall off the end of the body, jump back to
1981 // the top. 2004 // the top.
1982 if (has_valid_frame()) { 2005 if (has_valid_frame()) {
1983 node->continue_target()->Jump(); 2006 node->continue_target()->Jump();
1984 } 2007 }
1985 } else if (info == ALWAYS_FALSE) { 2008 } else if (info == ALWAYS_FALSE) {
1986 // If we had a continue in the body we have to bind its jump target. 2009 // If we had a continue in the body we have to bind its jump target.
1987 if (node->continue_target()->is_linked()) { 2010 node->continue_target()->Bind();
1988 node->continue_target()->Bind();
1989 }
1990 } else { 2011 } else {
1991 ASSERT(info == DONT_KNOW); 2012 ASSERT(info == DONT_KNOW);
1992 // We have to compile the test expression if it can be reached by 2013 // We have to compile the test expression if it can be reached by
1993 // control flow falling out of the body or via continue. 2014 // control flow falling out of the body or via continue.
1994 if (node->continue_target()->is_linked()) { 2015 node->continue_target()->Bind();
1995 node->continue_target()->Bind();
1996 }
1997 if (has_valid_frame()) { 2016 if (has_valid_frame()) {
1998 LoadCondition(node->cond(), NOT_INSIDE_TYPEOF, 2017 LoadCondition(node->cond(), NOT_INSIDE_TYPEOF,
1999 &body, node->break_target(), true); 2018 &body, node->break_target(), true);
2000 } 2019 }
2001 } 2020 }
2002 break; 2021 break;
2003 } 2022 }
2004 2023
2005 case LoopStatement::WHILE_LOOP: { 2024 case LoopStatement::WHILE_LOOP: {
2006 IncrementLoopNesting(); 2025 IncrementLoopNesting();
2007 2026
2008 // If the test is never true and has no side effects there is no need 2027 // If the test is never true and has no side effects there is no need
2009 // to compile the test or body. 2028 // to compile the test or body.
2010 if (info == ALWAYS_FALSE) break; 2029 if (info == ALWAYS_FALSE) break;
2011 2030
2012 // Label the top of the loop with the continue target for the backward 2031 // Label the top of the loop with the continue target for the backward
2013 // CFG edge. 2032 // CFG edge.
2014 node->continue_target()->Initialize(this, JumpTarget::BIDIRECTIONAL); 2033 node->continue_target()->Initialize(this, JumpTarget::BIDIRECTIONAL);
2015 node->continue_target()->Bind(); 2034 node->continue_target()->Bind();
2016 2035
2017 // If the test is always true and has no side effects there is no need 2036 // If the test is always true and has no side effects there is no need
2018 // to compile it. We only compile the test when we do not know its 2037 // to compile it. We only compile the test when we do not know its
2019 // outcome or it may have side effects. 2038 // outcome or it may have side effects.
2020 if (info == DONT_KNOW) { 2039 if (info == DONT_KNOW) {
2021 JumpTarget body(this); 2040 JumpTarget body(this);
2022 LoadCondition(node->cond(), NOT_INSIDE_TYPEOF, 2041 LoadCondition(node->cond(), NOT_INSIDE_TYPEOF,
2023 &body, node->break_target(), true); 2042 &body, node->break_target(), true);
2024 if (body.is_linked()) { 2043 body.Bind();
2025 body.Bind();
2026 }
2027 } 2044 }
2028 2045
2029 if (has_valid_frame()) { 2046 if (has_valid_frame()) {
2030 CheckStack(); // TODO(1222600): ignore if body contains calls. 2047 CheckStack(); // TODO(1222600): ignore if body contains calls.
2031 Visit(node->body()); 2048 Visit(node->body());
2032 2049
2033 // If control flow can fall out of the body, jump back to the top. 2050 // If control flow can fall out of the body, jump back to the top.
2034 if (has_valid_frame()) { 2051 if (has_valid_frame()) {
2035 node->continue_target()->Jump(); 2052 node->continue_target()->Jump();
2036 } 2053 }
(...skipping 22 matching lines...) Expand all
2059 loop.Bind(); 2076 loop.Bind();
2060 } 2077 }
2061 2078
2062 // If the test is always true and has no side effects there is no need 2079 // If the test is always true and has no side effects there is no need
2063 // to compile it. We only compile the test when we do not know its 2080 // to compile it. We only compile the test when we do not know its
2064 // outcome or it has side effects. 2081 // outcome or it has side effects.
2065 if (info == DONT_KNOW) { 2082 if (info == DONT_KNOW) {
2066 JumpTarget body(this); 2083 JumpTarget body(this);
2067 LoadCondition(node->cond(), NOT_INSIDE_TYPEOF, 2084 LoadCondition(node->cond(), NOT_INSIDE_TYPEOF,
2068 &body, node->break_target(), true); 2085 &body, node->break_target(), true);
2069 if (body.is_linked()) { 2086 body.Bind();
2070 body.Bind();
2071 }
2072 } 2087 }
2073 2088
2074 if (has_valid_frame()) { 2089 if (has_valid_frame()) {
2075 CheckStack(); // TODO(1222600): ignore if body contains calls. 2090 CheckStack(); // TODO(1222600): ignore if body contains calls.
2076 Visit(node->body()); 2091 Visit(node->body());
2077 2092
2078 if (node->next() == NULL) { 2093 if (node->next() == NULL) {
2079 // If there is no update statement and control flow can fall out 2094 // If there is no update statement and control flow can fall out
2080 // of the loop, jump to the continue label. 2095 // of the loop, jump to the continue label.
2081 if (has_valid_frame()) { 2096 if (has_valid_frame()) {
2082 node->continue_target()->Jump(); 2097 node->continue_target()->Jump();
2083 } 2098 }
2084 } else { 2099 } else {
2085 // If there is an update statement and control flow can reach it 2100 // If there is an update statement and control flow can reach it
2086 // via falling out of the body of the loop or continuing, we 2101 // via falling out of the body of the loop or continuing, we
2087 // compile the update statement. 2102 // compile the update statement.
2088 if (node->continue_target()->is_linked()) { 2103 node->continue_target()->Bind();
2089 node->continue_target()->Bind();
2090 }
2091 if (has_valid_frame()) { 2104 if (has_valid_frame()) {
2092 // Record source position of the statement as this code which is 2105 // Record source position of the statement as this code which is
2093 // after the code for the body actually belongs to the loop 2106 // after the code for the body actually belongs to the loop
2094 // statement and not the body. 2107 // statement and not the body.
2095 CodeForStatementPosition(node); 2108 CodeForStatementPosition(node);
2096 ASSERT(node->type() == LoopStatement::FOR_LOOP); 2109 ASSERT(node->type() == LoopStatement::FOR_LOOP);
2097 Visit(node->next()); 2110 Visit(node->next());
2098 loop.Jump(); 2111 loop.Jump();
2099 } 2112 }
2100 } 2113 }
2101 } 2114 }
2102 break; 2115 break;
2103 } 2116 }
2104 } 2117 }
2105 2118
2106 DecrementLoopNesting(); 2119 DecrementLoopNesting();
2107 if (node->break_target()->is_linked()) { 2120 node->break_target()->Bind();
2108 node->break_target()->Bind();
2109 }
2110 } 2121 }
2111 2122
2112 2123
2113 void CodeGenerator::VisitForInStatement(ForInStatement* node) { 2124 void CodeGenerator::VisitForInStatement(ForInStatement* node) {
2114 ASSERT(!in_spilled_code()); 2125 ASSERT(!in_spilled_code());
2115 VirtualFrame::SpilledScope spilled_scope(this); 2126 VirtualFrame::SpilledScope spilled_scope(this);
2116 Comment cmnt(masm_, "[ ForInStatement"); 2127 Comment cmnt(masm_, "[ ForInStatement");
2117 CodeForStatementPosition(node); 2128 CodeForStatementPosition(node);
2118 2129
2119 // We keep stuff on the stack while the body is executing. 2130 // We keep stuff on the stack while the body is executing.
2120 // Record it, so that a break/continue crossing this statement 2131 // Record it, so that a break/continue crossing this statement
2121 // can restore the stack. 2132 // can restore the stack.
2122 const int kForInStackSize = 5 * kPointerSize; 2133 const int kForInStackSize = 5 * kPointerSize;
2123 break_stack_height_ += kForInStackSize; 2134 break_stack_height_ += kForInStackSize;
2124 node->set_break_stack_height(break_stack_height_); 2135 node->set_break_stack_height(break_stack_height_);
2125 node->break_target()->Initialize(this); 2136 node->break_target()->Initialize(this);
2126 node->continue_target()->Initialize(this); 2137 node->continue_target()->Initialize(this);
2127 2138
2128 JumpTarget primitive(this); 2139 JumpTarget primitive(this);
2129 JumpTarget jsobject(this); 2140 JumpTarget jsobject(this);
2130 JumpTarget fixed_array(this); 2141 JumpTarget fixed_array(this);
2131 JumpTarget entry(this, JumpTarget::BIDIRECTIONAL); 2142 JumpTarget entry(this, JumpTarget::BIDIRECTIONAL);
2132 JumpTarget end_del_check(this); 2143 JumpTarget end_del_check(this);
2133 JumpTarget cleanup(this);
2134 JumpTarget exit(this); 2144 JumpTarget exit(this);
2135 2145
2136 // Get the object to enumerate over (converted to JSObject). 2146 // Get the object to enumerate over (converted to JSObject).
2137 LoadAndSpill(node->enumerable()); 2147 LoadAndSpill(node->enumerable());
2138 2148
2139 // Both SpiderMonkey and kjs ignore null and undefined in contrast 2149 // Both SpiderMonkey and kjs ignore null and undefined in contrast
2140 // to the specification. 12.6.4 mandates a call to ToObject. 2150 // to the specification. 12.6.4 mandates a call to ToObject.
2141 frame_->EmitPop(eax); 2151 frame_->EmitPop(eax);
2142 2152
2143 // eax: value to be iterated over 2153 // eax: value to be iterated over
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
2209 // Push the length of the array and the initial index onto the stack. 2219 // Push the length of the array and the initial index onto the stack.
2210 __ mov(eax, FieldOperand(eax, FixedArray::kLengthOffset)); 2220 __ mov(eax, FieldOperand(eax, FixedArray::kLengthOffset));
2211 __ shl(eax, kSmiTagSize); 2221 __ shl(eax, kSmiTagSize);
2212 frame_->EmitPush(eax); // <- slot 1 2222 frame_->EmitPush(eax); // <- slot 1
2213 frame_->EmitPush(Immediate(Smi::FromInt(0))); // <- slot 0 2223 frame_->EmitPush(Immediate(Smi::FromInt(0))); // <- slot 0
2214 2224
2215 // Condition. 2225 // Condition.
2216 entry.Bind(); 2226 entry.Bind();
2217 __ mov(eax, frame_->ElementAt(0)); // load the current count 2227 __ mov(eax, frame_->ElementAt(0)); // load the current count
2218 __ cmp(eax, frame_->ElementAt(1)); // compare to the array length 2228 __ cmp(eax, frame_->ElementAt(1)); // compare to the array length
2219 cleanup.Branch(above_equal); 2229 node->break_target()->Branch(above_equal);
2220 2230
2221 // Get the i'th entry of the array. 2231 // Get the i'th entry of the array.
2222 __ mov(edx, frame_->ElementAt(2)); 2232 __ mov(edx, frame_->ElementAt(2));
2223 __ mov(ebx, Operand(edx, eax, times_2, 2233 __ mov(ebx, Operand(edx, eax, times_2,
2224 FixedArray::kHeaderSize - kHeapObjectTag)); 2234 FixedArray::kHeaderSize - kHeapObjectTag));
2225 2235
2226 // Get the expected map from the stack or a zero map in the 2236 // Get the expected map from the stack or a zero map in the
2227 // permanent slow case eax: current iteration count ebx: i'th entry 2237 // permanent slow case eax: current iteration count ebx: i'th entry
2228 // of the enum cache 2238 // of the enum cache
2229 __ mov(edx, frame_->ElementAt(3)); 2239 __ mov(edx, frame_->ElementAt(3));
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
2284 VisitAndSpill(node->body()); 2294 VisitAndSpill(node->body());
2285 2295
2286 // Next. 2296 // Next.
2287 node->continue_target()->Bind(); 2297 node->continue_target()->Bind();
2288 frame_->EmitPop(eax); 2298 frame_->EmitPop(eax);
2289 __ add(Operand(eax), Immediate(Smi::FromInt(1))); 2299 __ add(Operand(eax), Immediate(Smi::FromInt(1)));
2290 frame_->EmitPush(eax); 2300 frame_->EmitPush(eax);
2291 entry.Jump(); 2301 entry.Jump();
2292 2302
2293 // Cleanup. 2303 // Cleanup.
2294 cleanup.Bind();
2295 node->break_target()->Bind(); 2304 node->break_target()->Bind();
2296 frame_->Drop(5); 2305 frame_->Drop(5);
2297 2306
2298 // Exit. 2307 // Exit.
2299 exit.Bind(); 2308 exit.Bind();
2300 2309
2301 break_stack_height_ -= kForInStackSize; 2310 break_stack_height_ -= kForInStackSize;
2302 } 2311 }
2303 2312
2304 2313
(...skipping 349 matching lines...) Expand 10 before | Expand all | Expand 10 after
2654 if (else_.is_linked()) { 2663 if (else_.is_linked()) {
2655 exit.Jump(); 2664 exit.Jump();
2656 } 2665 }
2657 } 2666 }
2658 2667
2659 if (else_.is_linked()) { 2668 if (else_.is_linked()) {
2660 else_.Bind(); 2669 else_.Bind();
2661 Load(node->else_expression(), typeof_state()); 2670 Load(node->else_expression(), typeof_state());
2662 } 2671 }
2663 2672
2664 if (exit.is_linked()) { 2673 exit.Bind();
2665 exit.Bind();
2666 }
2667 } 2674 }
2668 2675
2669 2676
2670 void CodeGenerator::LoadFromSlot(Slot* slot, TypeofState typeof_state) { 2677 void CodeGenerator::LoadFromSlot(Slot* slot, TypeofState typeof_state) {
2671 if (slot->type() == Slot::LOOKUP) { 2678 if (slot->type() == Slot::LOOKUP) {
2672 ASSERT(slot->var()->mode() == Variable::DYNAMIC); 2679 ASSERT(slot->var()->mode() == Variable::DYNAMIC);
2673 2680
2674 // For now, just do a runtime call. 2681 // For now, just do a runtime call.
2675 frame_->Push(esi); 2682 frame_->Push(esi);
2676 frame_->Push(slot->var()->name()); 2683 frame_->Push(slot->var()->name());
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
2794 // needed (probably the common case). 2801 // needed (probably the common case).
2795 frame_->Spill(value.reg()); 2802 frame_->Spill(value.reg());
2796 int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize; 2803 int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize;
2797 Result temp = allocator_->Allocate(); 2804 Result temp = allocator_->Allocate();
2798 ASSERT(temp.is_valid()); 2805 ASSERT(temp.is_valid());
2799 __ RecordWrite(start.reg(), offset, value.reg(), temp.reg()); 2806 __ RecordWrite(start.reg(), offset, value.reg(), temp.reg());
2800 // The results start, value, and temp are unused by going out of 2807 // The results start, value, and temp are unused by going out of
2801 // scope. 2808 // scope.
2802 } 2809 }
2803 2810
2804 // If we definitely did not jump over the assignment, we do not need 2811 exit.Bind();
2805 // to bind the exit label. Doing so can defeat peephole
2806 // optimization.
2807 if (exit.is_linked()) {
2808 exit.Bind();
2809 }
2810 } 2812 }
2811 } 2813 }
2812 2814
2813 2815
2814 void CodeGenerator::VisitSlot(Slot* node) { 2816 void CodeGenerator::VisitSlot(Slot* node) {
2815 Comment cmnt(masm_, "[ Slot"); 2817 Comment cmnt(masm_, "[ Slot");
2816 LoadFromSlot(node, typeof_state()); 2818 LoadFromSlot(node, typeof_state());
2817 } 2819 }
2818 2820
2819 2821
(...skipping 3468 matching lines...) Expand 10 before | Expand all | Expand 10 after
6288 6290
6289 // Slow-case: Go through the JavaScript implementation. 6291 // Slow-case: Go through the JavaScript implementation.
6290 __ bind(&slow); 6292 __ bind(&slow);
6291 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); 6293 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION);
6292 } 6294 }
6293 6295
6294 6296
6295 #undef __ 6297 #undef __
6296 6298
6297 } } // namespace v8::internal 6299 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/codegen-ia32.h ('k') | src/jump-target.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698