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

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

Issue 16513: Experimental: begin using the register allocator for switch statements... (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/toiger/
Patch Set: '' Created 11 years, 11 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.cc ('k') | src/virtual-frame-ia32.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 1706 matching lines...) Expand 10 before | Expand all | Expand 10 after
1717 Vector<JumpTarget*> case_targets, 1717 Vector<JumpTarget*> case_targets,
1718 Vector<JumpTarget> case_labels) { 1718 Vector<JumpTarget> case_labels) {
1719 // Notice: Internal references, used by both the jmp instruction and 1719 // Notice: Internal references, used by both the jmp instruction and
1720 // the table entries, need to be relocated if the buffer grows. This 1720 // the table entries, need to be relocated if the buffer grows. This
1721 // prevents the forward use of Labels, since a displacement cannot 1721 // prevents the forward use of Labels, since a displacement cannot
1722 // survive relocation, and it also cannot safely be distinguished 1722 // survive relocation, and it also cannot safely be distinguished
1723 // from a real address. Instead we put in zero-values as 1723 // from a real address. Instead we put in zero-values as
1724 // placeholders, and fill in the addresses after the labels have been 1724 // placeholders, and fill in the addresses after the labels have been
1725 // bound. 1725 // bound.
1726 1726
1727 VirtualFrame::SpilledScope spilled_scope(this);
1727 frame_->EmitPop(eax); // supposed Smi 1728 frame_->EmitPop(eax); // supposed Smi
1728 // check range of value, if outside [0..length-1] jump to default/end label. 1729 // check range of value, if outside [0..length-1] jump to default/end label.
1729 ASSERT(kSmiTagSize == 1 && kSmiTag == 0); 1730 ASSERT(kSmiTagSize == 1 && kSmiTag == 0);
1730 1731
1731 // Test whether input is a HeapNumber that is really a Smi 1732 // Test whether input is a HeapNumber that is really a Smi
1732 JumpTarget is_smi(this); 1733 JumpTarget is_smi(this);
1733 __ test(eax, Immediate(kSmiTagMask)); 1734 __ test(eax, Immediate(kSmiTagMask));
1734 is_smi.Branch(equal); 1735 is_smi.Branch(equal);
1735 // It's a heap object, not a Smi or a Failure 1736 // It's a heap object, not a Smi or a Failure
1736 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); 1737 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
1737 __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset)); 1738 __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset));
1738 __ cmp(ebx, HEAP_NUMBER_TYPE); 1739 __ cmp(ebx, HEAP_NUMBER_TYPE);
1739 fail_label->Branch(not_equal); 1740 fail_label->Branch(not_equal);
1740 // eax points to a heap number. 1741 // eax points to a heap number.
1741 __ push(eax); 1742 frame_->EmitPush(eax);
1742 __ CallRuntime(Runtime::kNumberToSmi, 1); 1743 frame_->CallRuntime(Runtime::kNumberToSmi, 1);
1743 is_smi.Bind(); 1744 is_smi.Bind();
1744 1745
1745 if (min_index != 0) { 1746 if (min_index != 0) {
1746 __ sub(Operand(eax), Immediate(min_index << kSmiTagSize)); 1747 __ sub(Operand(eax), Immediate(min_index << kSmiTagSize));
1747 } 1748 }
1748 __ test(eax, Immediate(0x80000000 | kSmiTagMask)); // negative or not Smi 1749 __ test(eax, Immediate(0x80000000 | kSmiTagMask)); // negative or not Smi
1749 fail_label->Branch(not_equal, not_taken); 1750 fail_label->Branch(not_equal, not_taken);
1750 __ cmp(eax, range << kSmiTagSize); 1751 __ cmp(eax, range << kSmiTagSize);
1751 fail_label->Branch(greater_equal, not_taken); 1752 fail_label->Branch(greater_equal, not_taken);
1752 1753
(...skipping 17 matching lines...) Expand all
1770 for (int i = 0, entry_pos = table_start.label()->pos(); 1771 for (int i = 0, entry_pos = table_start.label()->pos();
1771 i < range; 1772 i < range;
1772 i++, entry_pos += sizeof(uint32_t)) { 1773 i++, entry_pos += sizeof(uint32_t)) {
1773 __ WriteInternalReference(entry_pos, *case_targets[i]->label()); 1774 __ WriteInternalReference(entry_pos, *case_targets[i]->label());
1774 } 1775 }
1775 } 1776 }
1776 1777
1777 1778
1778 void CodeGenerator::VisitSwitchStatement(SwitchStatement* node) { 1779 void CodeGenerator::VisitSwitchStatement(SwitchStatement* node) {
1779 ASSERT(!in_spilled_code()); 1780 ASSERT(!in_spilled_code());
1780 VirtualFrame::SpilledScope spilled_scope(this);
1781 Comment cmnt(masm_, "[ SwitchStatement"); 1781 Comment cmnt(masm_, "[ SwitchStatement");
1782 CodeForStatement(node); 1782 CodeForStatement(node);
1783 node->set_break_stack_height(break_stack_height_); 1783 node->set_break_stack_height(break_stack_height_);
1784 node->break_target()->set_code_generator(this); 1784 node->break_target()->set_code_generator(this);
1785 1785
1786 LoadAndSpill(node->tag()); 1786 Load(node->tag());
1787 1787
1788 if (TryGenerateFastCaseSwitchStatement(node)) { 1788 if (TryGenerateFastCaseSwitchStatement(node)) {
1789 return; 1789 return;
1790 } 1790 }
1791 1791
1792 JumpTarget next_test(this); 1792 JumpTarget next_test(this);
1793 JumpTarget fall_through(this); 1793 JumpTarget fall_through(this);
1794 JumpTarget default_entry(this); 1794 JumpTarget default_entry(this);
1795 JumpTarget default_exit(this); 1795 JumpTarget default_exit(this);
1796 ZoneList<CaseClause*>* cases = node->cases(); 1796 ZoneList<CaseClause*>* cases = node->cases();
1797 int length = cases->length(); 1797 int length = cases->length();
1798 CaseClause* default_clause = NULL; 1798 CaseClause* default_clause = NULL;
1799 1799
1800 for (int i = 0; i < length; i++) { 1800 for (int i = 0; i < length; i++) {
1801 CaseClause* clause = cases->at(i); 1801 CaseClause* clause = cases->at(i);
1802 if (clause->is_default()) { 1802 if (clause->is_default()) {
1803 // Remember the default clause and compile it at the end. 1803 // Remember the default clause and compile it at the end.
1804 default_clause = clause; 1804 default_clause = clause;
1805 continue; 1805 continue;
1806 } 1806 }
1807 1807
1808 // Compile each non-default clause.
1808 Comment cmnt(masm_, "[ Case clause"); 1809 Comment cmnt(masm_, "[ Case clause");
1809 // Compile the test. 1810 // Label and compile the test.
1810 next_test.Bind(); 1811 if (next_test.is_linked()) {
1811 next_test.Unuse(); 1812 // Recycle the same label for each test.
1812 // Duplicate TOS. 1813 next_test.Bind();
1813 __ mov(eax, frame_->Top()); 1814 next_test.Unuse();
1814 frame_->EmitPush(eax); 1815 }
1815 LoadAndSpill(clause->label()); 1816 // Duplicate the switch value.
1817 frame_->Dup();
1818 Load(clause->label());
1816 Comparison(equal, true); 1819 Comparison(equal, true);
1817 Branch(false, &next_test); 1820 Branch(false, &next_test);
1818 1821
1819 // Before entering the body from the test, remove the switch value from 1822 // Before entering the body from the test remove the switch value from
1820 // the stack. 1823 // the frame.
William Hesse 2009/01/06 13:37:02 How about // Drop the switch value from the frame
Kevin Millikin (Chromium) 2009/01/06 14:18:47 I want the comment to indicate that it only happen
1821 frame_->Drop(); 1824 frame_->Drop();
1822 1825
1823 // Label the body so that fall through is enabled. 1826 // Label the body so that fall through is enabled.
1824 if (i > 0 && cases->at(i - 1)->is_default()) { 1827 if (i > 0 && cases->at(i - 1)->is_default()) {
1828 // The previous case was the default. This will be the target of a
1829 // possible backward edge.
1825 default_exit.Bind(); 1830 default_exit.Bind();
1826 } else { 1831 } else if (fall_through.is_linked()) {
1832 // Recycle the same label for each fall through except for the default
1833 // case.
1827 fall_through.Bind(); 1834 fall_through.Bind();
1828 fall_through.Unuse(); 1835 fall_through.Unuse();
1829 } 1836 }
1830 VisitStatementsAndSpill(clause->statements()); 1837 VisitStatements(clause->statements());
1831 1838
1832 // If control flow can fall through from the body, jump to the next body 1839 // If control flow can fall through from the body jump to the next body
1833 // or the end of the statement. 1840 // or the end of the statement.
1834 if (has_valid_frame()) { 1841 if (has_valid_frame()) {
1835 if (i < length - 1 && cases->at(i + 1)->is_default()) { 1842 if (i < length - 1 && cases->at(i + 1)->is_default()) {
1843 // The next case is the default.
1836 default_entry.Jump(); 1844 default_entry.Jump();
1837 } else { 1845 } else {
1838 fall_through.Jump(); 1846 fall_through.Jump();
1839 } 1847 }
1840 } 1848 }
1841 } 1849 }
1842 1850
1843 // The final "test" removes the switch value. 1851 // The block at the final "test" label removes the switch value.
1844 next_test.Bind(); 1852 next_test.Bind();
1845 frame_->Drop(); 1853 frame_->Drop();
1846 1854
1847 // If there is a default clause, compile it. 1855 // If there is a default clause, compile it now.
1848 if (default_clause != NULL) { 1856 if (default_clause != NULL) {
1849 Comment cmnt(masm_, "[ Default clause"); 1857 Comment cmnt(masm_, "[ Default clause");
1850 default_entry.Bind(); 1858 default_entry.Bind();
1851 VisitStatementsAndSpill(default_clause->statements()); 1859 VisitStatements(default_clause->statements());
1852 // If control flow can fall out of the default and there is a case after 1860 // If control flow can fall out of the default and there is a case after
1853 // it, jump to that case's body. 1861 // it, jump to that case's body.
1854 if (has_valid_frame() && default_exit.is_bound()) { 1862 if (has_valid_frame() && default_exit.is_bound()) {
1855 default_exit.Jump(); 1863 default_exit.Jump();
1856 } 1864 }
1857 } 1865 }
1858 1866
1859 if (fall_through.is_linked()) { 1867 if (fall_through.is_linked()) {
1860 fall_through.Bind(); 1868 fall_through.Bind();
1861 } 1869 }
(...skipping 3937 matching lines...) Expand 10 before | Expand all | Expand 10 after
5799 5807
5800 // Slow-case: Go through the JavaScript implementation. 5808 // Slow-case: Go through the JavaScript implementation.
5801 __ bind(&slow); 5809 __ bind(&slow);
5802 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); 5810 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION);
5803 } 5811 }
5804 5812
5805 5813
5806 #undef __ 5814 #undef __
5807 5815
5808 } } // namespace v8::internal 5816 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/codegen.cc ('k') | src/virtual-frame-ia32.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698