Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |