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

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

Issue 39331: Fix issue 263:... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 11 years, 9 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-arm.cc ('k') | test/mjsunit/regress/regress-263.js » ('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 2653 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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
OLDNEW
« no previous file with comments | « src/codegen-arm.cc ('k') | test/mjsunit/regress/regress-263.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698