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 1746 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1757 // label. | 1757 // label. |
1758 int nof_escapes = node->escaping_labels()->length(); | 1758 int nof_escapes = node->escaping_labels()->length(); |
1759 List<LabelShadow*> shadows(1 + nof_escapes); | 1759 List<LabelShadow*> shadows(1 + nof_escapes); |
1760 shadows.Add(new LabelShadow(&function_return_)); | 1760 shadows.Add(new LabelShadow(&function_return_)); |
1761 for (int i = 0; i < nof_escapes; i++) { | 1761 for (int i = 0; i < nof_escapes; i++) { |
1762 shadows.Add(new LabelShadow(node->escaping_labels()->at(i))); | 1762 shadows.Add(new LabelShadow(node->escaping_labels()->at(i))); |
1763 } | 1763 } |
1764 | 1764 |
1765 // Generate code for the statements in the try block. | 1765 // Generate code for the statements in the try block. |
1766 VisitStatements(node->try_block()->statements()); | 1766 VisitStatements(node->try_block()->statements()); |
1767 frame_->Pop(); // Discard the result. | 1767 // Discard the code slot from the handler. |
| 1768 frame_->Pop(); |
1768 | 1769 |
1769 // Stop the introduced shadowing and count the number of required unlinks. | 1770 // Stop the introduced shadowing and count the number of required unlinks. |
1770 // After shadowing stops, the original labels are unshadowed and the | 1771 // After shadowing stops, the original labels are unshadowed and the |
1771 // LabelShadows represent the formerly shadowing labels. | 1772 // LabelShadows represent the formerly shadowing labels. |
1772 int nof_unlinks = 0; | 1773 int nof_unlinks = 0; |
1773 for (int i = 0; i <= nof_escapes; i++) { | 1774 for (int i = 0; i <= nof_escapes; i++) { |
1774 shadows[i]->StopShadowing(); | 1775 shadows[i]->StopShadowing(); |
1775 if (shadows[i]->is_linked()) nof_unlinks++; | 1776 if (shadows[i]->is_linked()) nof_unlinks++; |
1776 } | 1777 } |
1777 | 1778 |
1778 // Unlink from try chain. | 1779 // Unlink from try chain. |
1779 // TOS contains code slot | 1780 // The code slot has already been discarded, so the next index is |
1780 const int kNextIndex = (StackHandlerConstants::kNextOffset | 1781 // adjusted by 1. |
1781 + StackHandlerConstants::kAddressDisplacement) | 1782 const int kNextIndex = |
1782 / kPointerSize; | 1783 (StackHandlerConstants::kNextOffset / kPointerSize) - 1; |
1783 __ ldr(r1, frame_->Element(kNextIndex)); // read next_sp | 1784 __ ldr(r1, frame_->Element(kNextIndex)); // read next_sp |
1784 __ mov(r3, Operand(ExternalReference(Top::k_handler_address))); | 1785 __ mov(r3, Operand(ExternalReference(Top::k_handler_address))); |
1785 __ str(r1, MemOperand(r3)); | 1786 __ str(r1, MemOperand(r3)); |
1786 ASSERT(StackHandlerConstants::kCodeOffset == 0); // first field is code | 1787 // The code slot has already been dropped from the handler. |
1787 frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1); | 1788 frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1); |
1788 // Code slot popped. | |
1789 if (nof_unlinks > 0) __ b(&exit); | 1789 if (nof_unlinks > 0) __ b(&exit); |
1790 | 1790 |
1791 // Generate unlink code for the (formerly) shadowing labels that have been | 1791 // Generate unlink code for the (formerly) shadowing labels that have been |
1792 // jumped to. | 1792 // jumped to. |
1793 for (int i = 0; i <= nof_escapes; i++) { | 1793 for (int i = 0; i <= nof_escapes; i++) { |
1794 if (shadows[i]->is_linked()) { | 1794 if (shadows[i]->is_linked()) { |
1795 // Unlink from try chain; | 1795 // Unlink from try chain; |
1796 __ bind(shadows[i]); | 1796 __ bind(shadows[i]); |
1797 | 1797 |
1798 // Reload sp from the top handler, because some statements that we | 1798 // Reload sp from the top handler, because some statements that we |
1799 // break from (eg, for...in) may have left stuff on the stack. | 1799 // break from (eg, for...in) may have left stuff on the stack. |
1800 __ mov(r3, Operand(ExternalReference(Top::k_handler_address))); | 1800 __ mov(r3, Operand(ExternalReference(Top::k_handler_address))); |
1801 __ ldr(sp, MemOperand(r3)); | 1801 __ ldr(sp, MemOperand(r3)); |
1802 | 1802 |
1803 __ ldr(r1, frame_->Element(kNextIndex)); | 1803 __ ldr(r1, frame_->Element(kNextIndex)); |
1804 __ str(r1, MemOperand(r3)); | 1804 __ str(r1, MemOperand(r3)); |
1805 ASSERT(StackHandlerConstants::kCodeOffset == 0); // first field is code | 1805 // The code slot has already been dropped from the handler. |
1806 frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1); | 1806 frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1); |
1807 // Code slot popped. | |
1808 | 1807 |
1809 __ b(shadows[i]->original_label()); | 1808 __ b(shadows[i]->original_label()); |
1810 } | 1809 } |
1811 } | 1810 } |
1812 | 1811 |
1813 __ bind(&exit); | 1812 __ bind(&exit); |
1814 } | 1813 } |
1815 | 1814 |
1816 | 1815 |
1817 void CodeGenerator::VisitTryFinally(TryFinally* node) { | 1816 void CodeGenerator::VisitTryFinally(TryFinally* node) { |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1884 frame_->Push(r0); | 1883 frame_->Push(r0); |
1885 } | 1884 } |
1886 __ mov(r2, Operand(Smi::FromInt(JUMPING + i))); | 1885 __ mov(r2, Operand(Smi::FromInt(JUMPING + i))); |
1887 __ b(&unlink); | 1886 __ b(&unlink); |
1888 } | 1887 } |
1889 } | 1888 } |
1890 | 1889 |
1891 // Unlink from try chain; | 1890 // Unlink from try chain; |
1892 __ bind(&unlink); | 1891 __ bind(&unlink); |
1893 | 1892 |
1894 frame_->Pop(r0); // Store TOS in r0 across stack manipulation | 1893 frame_->Pop(r0); // Preserve TOS result in r0 across stack manipulation. |
1895 // Reload sp from the top handler, because some statements that we | 1894 // Reload sp from the top handler, because some statements that we |
1896 // break from (eg, for...in) may have left stuff on the stack. | 1895 // break from (eg, for...in) may have left stuff on the stack. |
1897 __ mov(r3, Operand(ExternalReference(Top::k_handler_address))); | 1896 __ mov(r3, Operand(ExternalReference(Top::k_handler_address))); |
1898 __ ldr(sp, MemOperand(r3)); | 1897 __ ldr(sp, MemOperand(r3)); |
1899 const int kNextIndex = (StackHandlerConstants::kNextOffset | 1898 const int kNextIndex = (StackHandlerConstants::kNextOffset |
1900 + StackHandlerConstants::kAddressDisplacement) | 1899 + StackHandlerConstants::kAddressDisplacement) |
1901 / kPointerSize; | 1900 / kPointerSize; |
1902 __ ldr(r1, frame_->Element(kNextIndex)); | 1901 __ ldr(r1, frame_->Element(kNextIndex)); |
1903 __ str(r1, MemOperand(r3)); | 1902 __ str(r1, MemOperand(r3)); |
1904 ASSERT(StackHandlerConstants::kCodeOffset == 0); // first field is code | 1903 ASSERT(StackHandlerConstants::kCodeOffset == 0); // first field is code |
| 1904 // The stack pointer was restored to just below the code slot (the |
| 1905 // topmost slot) of the handler, so all but the code slot need to be |
| 1906 // dropped. |
1905 frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1); | 1907 frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1); |
1906 // Code slot popped. | 1908 // Restore result to TOS. |
1907 frame_->Push(r0); | 1909 frame_->Push(r0); |
1908 | 1910 |
1909 // --- Finally block --- | 1911 // --- Finally block --- |
1910 __ bind(&finally_block); | 1912 __ bind(&finally_block); |
1911 | 1913 |
1912 // Push the state on the stack. | 1914 // Push the state on the stack. |
1913 frame_->Push(r2); | 1915 frame_->Push(r2); |
1914 | 1916 |
1915 // We keep two elements on the stack - the (possibly faked) result | 1917 // We keep two elements on the stack - the (possibly faked) result |
1916 // and the state - while evaluating the finally block. Record it, so | 1918 // and the state - while evaluating the finally block. Record it, so |
1917 // that a break/continue crossing this statement can restore the | 1919 // that a break/continue crossing this statement can restore the |
1918 // stack. | 1920 // stack. |
1919 const int kFinallyStackSize = 2 * kPointerSize; | 1921 const int kFinallyStackSize = 2 * kPointerSize; |
1920 break_stack_height_ += kFinallyStackSize; | 1922 break_stack_height_ += kFinallyStackSize; |
1921 | 1923 |
1922 // Generate code for the statements in the finally block. | 1924 // Generate code for the statements in the finally block. |
1923 VisitStatements(node->finally_block()->statements()); | 1925 VisitStatements(node->finally_block()->statements()); |
1924 | 1926 |
1925 // Restore state and return value or faked TOS. | 1927 // Restore state and return value or faked TOS. |
1926 frame_->Pop(r2); | 1928 frame_->Pop(r2); |
1927 frame_->Pop(r0); | 1929 frame_->Pop(r0); |
1928 break_stack_height_ -= kFinallyStackSize; | 1930 break_stack_height_ -= kFinallyStackSize; |
1929 | 1931 |
1930 // Generate code to jump to the right destination for all used (formerly) | 1932 // Generate code to jump to the right destination for all used (formerly) |
1931 // shadowing labels. | 1933 // shadowing labels. |
1932 for (int i = 0; i <= nof_escapes; i++) { | 1934 for (int i = 0; i <= nof_escapes; i++) { |
1933 if (shadows[i]->is_bound()) { | 1935 if (shadows[i]->is_bound()) { |
1934 __ cmp(r2, Operand(Smi::FromInt(JUMPING + i))); | 1936 __ cmp(r2, Operand(Smi::FromInt(JUMPING + i))); |
1935 if (shadows[i]->original_label() != &function_return_) { | 1937 __ b(eq, shadows[i]->original_label()); |
1936 Label next; | |
1937 __ b(ne, &next); | |
1938 __ b(shadows[i]->original_label()); | |
1939 __ bind(&next); | |
1940 } else { | |
1941 __ b(eq, shadows[i]->original_label()); | |
1942 } | |
1943 } | 1938 } |
1944 } | 1939 } |
1945 | 1940 |
1946 // Check if we need to rethrow the exception. | 1941 // Check if we need to rethrow the exception. |
1947 __ cmp(r2, Operand(Smi::FromInt(THROWING))); | 1942 __ cmp(r2, Operand(Smi::FromInt(THROWING))); |
1948 __ b(ne, &exit); | 1943 __ b(ne, &exit); |
1949 | 1944 |
1950 // Rethrow exception. | 1945 // Rethrow exception. |
1951 frame_->Push(r0); | 1946 frame_->Push(r0); |
1952 __ CallRuntime(Runtime::kReThrow, 1); | 1947 __ CallRuntime(Runtime::kReThrow, 1); |
(...skipping 2505 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4458 __ mov(r2, Operand(0)); | 4453 __ mov(r2, Operand(0)); |
4459 __ GetBuiltinEntry(r3, Builtins::CALL_NON_FUNCTION); | 4454 __ GetBuiltinEntry(r3, Builtins::CALL_NON_FUNCTION); |
4460 __ Jump(Handle<Code>(Builtins::builtin(Builtins::ArgumentsAdaptorTrampoline)), | 4455 __ Jump(Handle<Code>(Builtins::builtin(Builtins::ArgumentsAdaptorTrampoline)), |
4461 RelocInfo::CODE_TARGET); | 4456 RelocInfo::CODE_TARGET); |
4462 } | 4457 } |
4463 | 4458 |
4464 | 4459 |
4465 #undef __ | 4460 #undef __ |
4466 | 4461 |
4467 } } // namespace v8::internal | 4462 } } // namespace v8::internal |
OLD | NEW |