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 2653 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2664 for (int i = 0; i < nof_escapes; i++) { | 2664 for (int i = 0; i < nof_escapes; i++) { |
2665 shadows.Add(new ShadowTarget(node->escaping_targets()->at(i))); | 2665 shadows.Add(new ShadowTarget(node->escaping_targets()->at(i))); |
2666 } | 2666 } |
2667 | 2667 |
2668 // Generate code for the statements in the try block. | 2668 // Generate code for the statements in the try block. |
2669 VisitStatementsAndSpill(node->try_block()->statements()); | 2669 VisitStatementsAndSpill(node->try_block()->statements()); |
2670 | 2670 |
2671 // Stop the introduced shadowing and count the number of required unlinks. | 2671 // Stop the introduced shadowing and count the number of required unlinks. |
2672 // After shadowing stops, the original targets are unshadowed and the | 2672 // After shadowing stops, the original targets are unshadowed and the |
2673 // ShadowTargets represent the formerly shadowing targets. | 2673 // ShadowTargets represent the formerly shadowing targets. |
2674 int nof_unlinks = 0; | 2674 bool has_unlinks = false; |
2675 for (int i = 0; i <= nof_escapes; i++) { | 2675 for (int i = 0; i <= nof_escapes; i++) { |
2676 shadows[i]->StopShadowing(); | 2676 shadows[i]->StopShadowing(); |
2677 if (shadows[i]->is_linked()) nof_unlinks++; | 2677 has_unlinks = has_unlinks || shadows[i]->is_linked(); |
2678 } | 2678 } |
2679 function_return_is_shadowed_ = function_return_was_shadowed; | 2679 function_return_is_shadowed_ = function_return_was_shadowed; |
2680 | 2680 |
2681 // Get an external reference to the handler address. | 2681 // Get an external reference to the handler address. |
2682 ExternalReference handler_address(Top::k_handler_address); | 2682 ExternalReference handler_address(Top::k_handler_address); |
2683 | 2683 |
2684 // Make sure that there's nothing left on the stack above the | 2684 // Make sure that there's nothing left on the stack above the |
2685 // handler structure. | 2685 // handler structure. |
2686 if (FLAG_debug_code) { | 2686 if (FLAG_debug_code) { |
2687 __ mov(eax, Operand::StaticVariable(handler_address)); | 2687 __ mov(eax, Operand::StaticVariable(handler_address)); |
2688 __ lea(eax, Operand(eax, StackHandlerConstants::kAddressDisplacement)); | 2688 __ lea(eax, Operand(eax, StackHandlerConstants::kAddressDisplacement)); |
2689 __ cmp(esp, Operand(eax)); | 2689 __ cmp(esp, Operand(eax)); |
2690 __ Assert(equal, "stack pointer should point to top handler"); | 2690 __ Assert(equal, "stack pointer should point to top handler"); |
2691 } | 2691 } |
2692 | 2692 |
2693 // If we can fall off the end of the try block, unlink from try chain. | 2693 // If we can fall off the end of the try block, unlink from try chain. |
2694 if (has_valid_frame()) { | 2694 if (has_valid_frame()) { |
2695 // The TOS is the next handler address. | 2695 // The next handler address is on top of the frame. Unlink from |
2696 frame_->EmitPop(eax); | 2696 // the handler list and drop the rest of this handler from the |
2697 __ mov(Operand::StaticVariable(handler_address), eax); | 2697 // frame. |
| 2698 frame_->EmitPop(Operand::StaticVariable(handler_address)); |
2698 frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1); | 2699 frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1); |
2699 if (nof_unlinks > 0) { | 2700 if (has_unlinks) { |
2700 exit.Jump(); | 2701 exit.Jump(); |
2701 } | 2702 } |
2702 } | 2703 } |
2703 | 2704 |
2704 // Generate unlink code for the (formerly) shadowing targets that have been | 2705 // Generate unlink code for the (formerly) shadowing targets that have been |
2705 // jumped to. | 2706 // jumped to. |
2706 for (int i = 0; i <= nof_escapes; i++) { | 2707 for (int i = 0; i <= nof_escapes; i++) { |
2707 if (shadows[i]->is_linked()) { | 2708 if (shadows[i]->is_linked()) { |
2708 // Unlink from try chain; be careful not to destroy the TOS. | 2709 // Unlink from try chain; be careful not to destroy the TOS. |
2709 shadows[i]->Bind(); | 2710 shadows[i]->Bind(); |
(...skipping 28 matching lines...) Expand all Loading... |
2738 ASSERT(!in_spilled_code()); | 2739 ASSERT(!in_spilled_code()); |
2739 VirtualFrame::SpilledScope spilled_scope(this); | 2740 VirtualFrame::SpilledScope spilled_scope(this); |
2740 Comment cmnt(masm_, "[ TryFinally"); | 2741 Comment cmnt(masm_, "[ TryFinally"); |
2741 CodeForStatementPosition(node); | 2742 CodeForStatementPosition(node); |
2742 | 2743 |
2743 // State: Used to keep track of reason for entering the finally | 2744 // State: Used to keep track of reason for entering the finally |
2744 // block. Should probably be extended to hold information for | 2745 // block. Should probably be extended to hold information for |
2745 // break/continue from within the try block. | 2746 // break/continue from within the try block. |
2746 enum { FALLING, THROWING, JUMPING }; | 2747 enum { FALLING, THROWING, JUMPING }; |
2747 | 2748 |
2748 JumpTarget unlink(this); | |
2749 JumpTarget try_block(this); | 2749 JumpTarget try_block(this); |
2750 JumpTarget finally_block(this); | 2750 JumpTarget finally_block(this); |
2751 | 2751 |
2752 try_block.Call(); | 2752 try_block.Call(); |
2753 | 2753 |
2754 frame_->EmitPush(eax); | 2754 frame_->EmitPush(eax); |
2755 // In case of thrown exceptions, this is where we continue. | 2755 // In case of thrown exceptions, this is where we continue. |
2756 __ Set(ecx, Immediate(Smi::FromInt(THROWING))); | 2756 __ Set(ecx, Immediate(Smi::FromInt(THROWING))); |
2757 finally_block.Jump(); | 2757 finally_block.Jump(); |
2758 | 2758 |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2790 // Stop the introduced shadowing and count the number of required unlinks. | 2790 // Stop the introduced shadowing and count the number of required unlinks. |
2791 // After shadowing stops, the original targets are unshadowed and the | 2791 // After shadowing stops, the original targets are unshadowed and the |
2792 // ShadowTargets represent the formerly shadowing targets. | 2792 // ShadowTargets represent the formerly shadowing targets. |
2793 int nof_unlinks = 0; | 2793 int nof_unlinks = 0; |
2794 for (int i = 0; i <= nof_escapes; i++) { | 2794 for (int i = 0; i <= nof_escapes; i++) { |
2795 shadows[i]->StopShadowing(); | 2795 shadows[i]->StopShadowing(); |
2796 if (shadows[i]->is_linked()) nof_unlinks++; | 2796 if (shadows[i]->is_linked()) nof_unlinks++; |
2797 } | 2797 } |
2798 function_return_is_shadowed_ = function_return_was_shadowed; | 2798 function_return_is_shadowed_ = function_return_was_shadowed; |
2799 | 2799 |
2800 // If we can fall off the end of the try block, set the state on the stack | 2800 // Get an external reference to the handler address. |
2801 // to FALLING. | 2801 ExternalReference handler_address(Top::k_handler_address); |
| 2802 |
| 2803 // If we can fall off the end of the try block, unlink from the try |
| 2804 // chain and set the state on the frame to FALLING. |
2802 if (has_valid_frame()) { | 2805 if (has_valid_frame()) { |
2803 frame_->EmitPush(Immediate(Factory::undefined_value())); // fake TOS | 2806 // The next handler address is on top of the frame. |
| 2807 ASSERT(StackHandlerConstants::kNextOffset == 0); |
| 2808 frame_->EmitPop(eax); |
| 2809 __ mov(Operand::StaticVariable(handler_address), eax); |
| 2810 frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1); |
| 2811 |
| 2812 // Fake a top of stack value (unneeded when FALLING) and set the |
| 2813 // state in ecx, then jump around the unlink blocks if any. |
| 2814 frame_->EmitPush(Immediate(Factory::undefined_value())); |
2804 __ Set(ecx, Immediate(Smi::FromInt(FALLING))); | 2815 __ Set(ecx, Immediate(Smi::FromInt(FALLING))); |
2805 if (nof_unlinks > 0) { | 2816 if (nof_unlinks > 0) { |
2806 unlink.Jump(); | 2817 finally_block.Jump(); |
2807 } | 2818 } |
2808 } | 2819 } |
2809 | 2820 |
2810 // Generate code to set the state for the (formerly) shadowing targets that | 2821 // Generate code to unlink and set the state for the (formerly) |
2811 // have been jumped to. | 2822 // shadowing targets that have been jumped to. |
2812 for (int i = 0; i <= nof_escapes; i++) { | 2823 for (int i = 0; i <= nof_escapes; i++) { |
2813 if (shadows[i]->is_linked()) { | 2824 if (shadows[i]->is_linked()) { |
| 2825 // If we have come from the shadowed return, the return value is |
| 2826 // in (a non-refcounted reference to) eax. We must preserve it |
| 2827 // until it is pushed. |
| 2828 // |
2814 // Because we can be jumping here (to spilled code) from | 2829 // Because we can be jumping here (to spilled code) from |
2815 // unspilled code, we need to reestablish a spilled frame at | 2830 // unspilled code, we need to reestablish a spilled frame at |
2816 // this block. | 2831 // this block. |
2817 shadows[i]->Bind(); | 2832 shadows[i]->Bind(); |
2818 frame_->SpillAll(); | 2833 frame_->SpillAll(); |
| 2834 |
| 2835 // Reload sp from the top handler, because some statements that |
| 2836 // we break from (eg, for...in) may have left stuff on the |
| 2837 // stack. |
| 2838 __ mov(edx, Operand::StaticVariable(handler_address)); |
| 2839 const int kNextOffset = StackHandlerConstants::kNextOffset + |
| 2840 StackHandlerConstants::kAddressDisplacement; |
| 2841 __ lea(esp, Operand(edx, kNextOffset)); |
| 2842 frame_->Forget(frame_->height() - handler_height); |
| 2843 |
| 2844 // Unlink this handler and drop it from the frame. |
| 2845 frame_->EmitPop(Operand::StaticVariable(handler_address)); |
| 2846 frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1); |
| 2847 |
2819 if (i == kReturnShadowIndex) { | 2848 if (i == kReturnShadowIndex) { |
2820 // If this target shadowed the function return, materialize | 2849 // If this target shadowed the function return, materialize |
2821 // the return value on the stack. | 2850 // the return value on the stack. |
2822 frame_->EmitPush(eax); | 2851 frame_->EmitPush(eax); |
2823 } else { | 2852 } else { |
2824 // Fake TOS for targets that shadowed breaks and continues. | 2853 // Fake TOS for targets that shadowed breaks and continues. |
2825 frame_->EmitPush(Immediate(Factory::undefined_value())); | 2854 frame_->EmitPush(Immediate(Factory::undefined_value())); |
2826 } | 2855 } |
2827 __ Set(ecx, Immediate(Smi::FromInt(JUMPING + i))); | 2856 __ Set(ecx, Immediate(Smi::FromInt(JUMPING + i))); |
2828 unlink.Jump(); | 2857 if (--nof_unlinks > 0) { |
| 2858 // If this is not the last unlink block, jump around the next. |
| 2859 finally_block.Jump(); |
| 2860 } |
2829 } | 2861 } |
2830 } | 2862 } |
2831 | 2863 |
2832 // Unlink from try chain; be careful not to destroy the TOS. | |
2833 if (unlink.is_linked()) { | |
2834 unlink.Bind(); | |
2835 } | |
2836 | |
2837 // Control can reach here via a jump to unlink or by falling off the | |
2838 // end of the try block (with no unlinks). | |
2839 if (has_valid_frame()) { | |
2840 // Reload sp from the top handler, because some statements that we | |
2841 // break from (eg, for...in) may have left stuff on the stack. | |
2842 // Preserve the TOS in a register across stack manipulation. | |
2843 frame_->EmitPop(eax); | |
2844 ExternalReference handler_address(Top::k_handler_address); | |
2845 __ mov(edx, Operand::StaticVariable(handler_address)); | |
2846 const int kNextOffset = StackHandlerConstants::kNextOffset + | |
2847 StackHandlerConstants::kAddressDisplacement; | |
2848 __ lea(esp, Operand(edx, kNextOffset)); | |
2849 frame_->Forget(frame_->height() - handler_height); | |
2850 | |
2851 frame_->EmitPop(Operand::StaticVariable(handler_address)); | |
2852 frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1); | |
2853 // Next_sp popped. | |
2854 frame_->EmitPush(eax); | |
2855 } | |
2856 | |
2857 // --- Finally block --- | 2864 // --- Finally block --- |
2858 finally_block.Bind(); | 2865 finally_block.Bind(); |
2859 | 2866 |
2860 // Push the state on the stack. | 2867 // Push the state on the stack. |
2861 frame_->EmitPush(ecx); | 2868 frame_->EmitPush(ecx); |
2862 | 2869 |
2863 // We keep two elements on the stack - the (possibly faked) result | 2870 // We keep two elements on the stack - the (possibly faked) result |
2864 // and the state - while evaluating the finally block. Record it, so | 2871 // and the state - while evaluating the finally block. Record it, so |
2865 // that a break/continue crossing this statement can restore the | 2872 // that a break/continue crossing this statement can restore the |
2866 // stack. | 2873 // stack. |
(...skipping 3959 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6826 | 6833 |
6827 // Slow-case: Go through the JavaScript implementation. | 6834 // Slow-case: Go through the JavaScript implementation. |
6828 __ bind(&slow); | 6835 __ bind(&slow); |
6829 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); | 6836 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); |
6830 } | 6837 } |
6831 | 6838 |
6832 | 6839 |
6833 #undef __ | 6840 #undef __ |
6834 | 6841 |
6835 } } // namespace v8::internal | 6842 } } // namespace v8::internal |
OLD | NEW |