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

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

Issue 269049: Split the AST LoopStatement type into separate types for do/while,... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: Created 11 years, 2 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
OLDNEW
1 // Copyright 2006-2009 the V8 project authors. All rights reserved. 1 // Copyright 2006-2009 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 2680 matching lines...) Expand 10 before | Expand all | Expand 10 after
2691 2691
2692 // We may not have a valid frame here so bind the break target only 2692 // We may not have a valid frame here so bind the break target only
2693 // if needed. 2693 // if needed.
2694 if (node->break_target()->is_linked()) { 2694 if (node->break_target()->is_linked()) {
2695 node->break_target()->Bind(); 2695 node->break_target()->Bind();
2696 } 2696 }
2697 node->break_target()->Unuse(); 2697 node->break_target()->Unuse();
2698 } 2698 }
2699 2699
2700 2700
2701 void CodeGenerator::VisitLoopStatement(LoopStatement* node) { 2701 void CodeGenerator::VisitDoWhileStatement(DoWhileStatement* node) {
2702 ASSERT(!in_spilled_code()); 2702 ASSERT(!in_spilled_code());
2703 Comment cmnt(masm_, "[ LoopStatement"); 2703 Comment cmnt(masm_, "[ DoWhileStatement");
2704 CodeForStatementPosition(node); 2704 CodeForStatementPosition(node);
2705 node->break_target()->set_direction(JumpTarget::FORWARD_ONLY); 2705 node->break_target()->set_direction(JumpTarget::FORWARD_ONLY);
2706 2706 JumpTarget body(JumpTarget::BIDIRECTIONAL);
2707 // Simple condition analysis. ALWAYS_TRUE and ALWAYS_FALSE represent a 2707 IncrementLoopNesting();
2708 // known result for the test expression, with no side effects. 2708
2709 enum { ALWAYS_TRUE, ALWAYS_FALSE, DONT_KNOW } info = DONT_KNOW; 2709 ConditionAnalysis info = AnalyzeCondition(node->cond());
2710 if (node->cond() == NULL) { 2710 // Label the top of the loop for the backward jump if necessary.
2711 ASSERT(node->type() == LoopStatement::FOR_LOOP); 2711 switch (info) {
2712 info = ALWAYS_TRUE; 2712 case ALWAYS_TRUE:
2713 } else { 2713 // Use the continue target.
2714 Literal* lit = node->cond()->AsLiteral(); 2714 node->continue_target()->set_direction(JumpTarget::BIDIRECTIONAL);
2715 if (lit != NULL) { 2715 node->continue_target()->Bind();
2716 if (lit->IsTrue()) { 2716 break;
2717 info = ALWAYS_TRUE; 2717 case ALWAYS_FALSE:
2718 } else if (lit->IsFalse()) { 2718 // No need to label it.
2719 info = ALWAYS_FALSE; 2719 node->continue_target()->set_direction(JumpTarget::FORWARD_ONLY);
2720 } 2720 break;
2721 case DONT_KNOW:
2722 // Continue is the test, so use the backward body target.
2723 node->continue_target()->set_direction(JumpTarget::FORWARD_ONLY);
2724 body.Bind();
2725 break;
2726 }
2727
2728 CheckStack(); // TODO(1222600): ignore if body contains calls.
2729 Visit(node->body());
2730
2731 // Compile the test.
2732 switch (info) {
2733 case ALWAYS_TRUE:
2734 // If control flow can fall off the end of the body, jump back to
2735 // the top and bind the break target at the exit.
2736 if (has_valid_frame()) {
2737 node->continue_target()->Jump();
2738 }
2739 if (node->break_target()->is_linked()) {
2740 node->break_target()->Bind();
2741 }
2742 break;
2743 case ALWAYS_FALSE:
2744 // We may have had continues or breaks in the body.
2745 if (node->continue_target()->is_linked()) {
2746 node->continue_target()->Bind();
2747 }
2748 if (node->break_target()->is_linked()) {
2749 node->break_target()->Bind();
2750 }
2751 break;
2752 case DONT_KNOW:
2753 // We have to compile the test expression if it can be reached by
2754 // control flow falling out of the body or via continue.
2755 if (node->continue_target()->is_linked()) {
2756 node->continue_target()->Bind();
2757 }
2758 if (has_valid_frame()) {
2759 ControlDestination dest(&body, node->break_target(), false);
2760 LoadCondition(node->cond(), NOT_INSIDE_TYPEOF, &dest, true);
2761 }
2762 if (node->break_target()->is_linked()) {
2763 node->break_target()->Bind();
2764 }
2765 break;
2766 }
2767
2768 DecrementLoopNesting();
2769 }
2770
2771
2772 void CodeGenerator::VisitWhileStatement(WhileStatement* node) {
2773 ASSERT(!in_spilled_code());
2774 Comment cmnt(masm_, "[ WhileStatement");
2775 CodeForStatementPosition(node);
2776
2777 // If the condition is always false and has no side effects, we do not
2778 // need to compile anything.
2779 ConditionAnalysis info = AnalyzeCondition(node->cond());
2780 if (info == ALWAYS_FALSE) return;
2781
2782 // Do not duplicate conditions that may have function literal
2783 // subexpressions. This can cause us to compile the function literal
2784 // twice.
2785 bool test_at_bottom = !node->may_have_function_literal();
2786 node->break_target()->set_direction(JumpTarget::FORWARD_ONLY);
2787 IncrementLoopNesting();
2788 JumpTarget body;
2789 if (test_at_bottom) {
2790 body.set_direction(JumpTarget::BIDIRECTIONAL);
2791 }
2792
2793 // Based on the condition analysis, compile the test as necessary.
2794 switch (info) {
2795 case ALWAYS_TRUE:
2796 // We will not compile the test expression. Label the top of the
2797 // loop with the continue target.
2798 node->continue_target()->set_direction(JumpTarget::BIDIRECTIONAL);
2799 node->continue_target()->Bind();
2800 break;
2801 case DONT_KNOW: {
2802 if (test_at_bottom) {
2803 // Continue is the test at the bottom, no need to label the test
2804 // at the top. The body is a backward target.
2805 node->continue_target()->set_direction(JumpTarget::FORWARD_ONLY);
2806 } else {
2807 // Label the test at the top as the continue target. The body
2808 // is a forward-only target.
2809 node->continue_target()->set_direction(JumpTarget::BIDIRECTIONAL);
2810 node->continue_target()->Bind();
2811 }
2812 // Compile the test with the body as the true target and preferred
2813 // fall-through and with the break target as the false target.
2814 ControlDestination dest(&body, node->break_target(), true);
2815 LoadCondition(node->cond(), NOT_INSIDE_TYPEOF, &dest, true);
2816
2817 if (dest.false_was_fall_through()) {
2818 // If we got the break target as fall-through, the test may have
2819 // been unconditionally false (if there are no jumps to the
2820 // body).
2821 if (!body.is_linked()) {
2822 DecrementLoopNesting();
2823 return;
2824 }
2825
2826 // Otherwise, jump around the body on the fall through and then
2827 // bind the body target.
2828 node->break_target()->Unuse();
2829 node->break_target()->Jump();
2830 body.Bind();
2831 }
2832 break;
2721 } 2833 }
2722 } 2834 case ALWAYS_FALSE:
2723 2835 UNREACHABLE();
2724 switch (node->type()) { 2836 break;
2725 case LoopStatement::DO_LOOP: { 2837 }
2726 JumpTarget body(JumpTarget::BIDIRECTIONAL); 2838
2727 IncrementLoopNesting(); 2839 CheckStack(); // TODO(1222600): ignore if body contains calls.
2728 2840 Visit(node->body());
2729 // Label the top of the loop for the backward jump if necessary. 2841
2730 if (info == ALWAYS_TRUE) { 2842 // Based on the condition analysis, compile the backward jump as
2731 // Use the continue target. 2843 // necessary.
2732 node->continue_target()->set_direction(JumpTarget::BIDIRECTIONAL); 2844 switch (info) {
2733 node->continue_target()->Bind(); 2845 case ALWAYS_TRUE:
2734 } else if (info == ALWAYS_FALSE) { 2846 // The loop body has been labeled with the continue target.
2735 // No need to label it. 2847 if (has_valid_frame()) {
2736 node->continue_target()->set_direction(JumpTarget::FORWARD_ONLY); 2848 node->continue_target()->Jump();
2737 } else { 2849 }
2738 // Continue is the test, so use the backward body target. 2850 break;
2739 ASSERT(info == DONT_KNOW); 2851 case DONT_KNOW:
2740 node->continue_target()->set_direction(JumpTarget::FORWARD_ONLY); 2852 if (test_at_bottom) {
2741 body.Bind(); 2853 // If we have chosen to recompile the test at the bottom, then
2742 } 2854 // it is the continue target.
2743 2855 if (node->continue_target()->is_linked()) {
2744 CheckStack(); // TODO(1222600): ignore if body contains calls. 2856 node->continue_target()->Bind();
2745 Visit(node->body()); 2857 }
2746 2858 if (has_valid_frame()) {
2747 // Compile the test. 2859 // The break target is the fall-through (body is a backward
2748 if (info == ALWAYS_TRUE) { 2860 // jump from here and thus an invalid fall-through).
2749 // If control flow can fall off the end of the body, jump back 2861 ControlDestination dest(&body, node->break_target(), false);
2750 // to the top and bind the break target at the exit. 2862 LoadCondition(node->cond(), NOT_INSIDE_TYPEOF, &dest, true);
2863 }
2864 } else {
2865 // If we have chosen not to recompile the test at the bottom,
2866 // jump back to the one at the top.
2751 if (has_valid_frame()) { 2867 if (has_valid_frame()) {
2752 node->continue_target()->Jump(); 2868 node->continue_target()->Jump();
2753 } 2869 }
2754 if (node->break_target()->is_linked()) { 2870 }
2755 node->break_target()->Bind(); 2871 break;
2756 } 2872 case ALWAYS_FALSE:
2757 2873 UNREACHABLE();
2758 } else if (info == ALWAYS_FALSE) { 2874 break;
2759 // We may have had continues or breaks in the body. 2875 }
2876
2877 // The break target may be already bound (by the condition), or there
2878 // may not be a valid frame. Bind it only if needed.
2879 if (node->break_target()->is_linked()) {
2880 node->break_target()->Bind();
2881 }
2882 DecrementLoopNesting();
2883 }
2884
2885
2886 void CodeGenerator::VisitForStatement(ForStatement* node) {
2887 ASSERT(!in_spilled_code());
2888 Comment cmnt(masm_, "[ ForStatement");
2889 CodeForStatementPosition(node);
2890
2891 // Compile the init expression if present.
2892 if (node->init() != NULL) {
2893 Visit(node->init());
2894 }
2895
2896 // If the condition is always false and has no side effects, we do not
2897 // need to compile anything else.
2898 ConditionAnalysis info = AnalyzeCondition(node->cond());
2899 if (info == ALWAYS_FALSE) return;
2900
2901 // Do not duplicate conditions that may have function literal
2902 // subexpressions. This can cause us to compile the function literal
2903 // twice.
2904 bool test_at_bottom = !node->may_have_function_literal();
2905 node->break_target()->set_direction(JumpTarget::FORWARD_ONLY);
2906 IncrementLoopNesting();
2907
2908 // Target for backward edge if no test at the bottom, otherwise
2909 // unused.
2910 JumpTarget loop(JumpTarget::BIDIRECTIONAL);
2911
2912 // Target for backward edge if there is a test at the bottom,
2913 // otherwise used as target for test at the top.
2914 JumpTarget body;
2915 if (test_at_bottom) {
2916 body.set_direction(JumpTarget::BIDIRECTIONAL);
2917 }
2918
2919 // Based on the condition analysis, compile the test as necessary.
2920 switch (info) {
2921 case ALWAYS_TRUE:
2922 // We will not compile the test expression. Label the top of the
2923 // loop.
2924 if (node->next() == NULL) {
2925 // Use the continue target if there is no update expression.
2926 node->continue_target()->set_direction(JumpTarget::BIDIRECTIONAL);
2927 node->continue_target()->Bind();
2928 } else {
2929 // Otherwise use the backward loop target.
2930 node->continue_target()->set_direction(JumpTarget::FORWARD_ONLY);
2931 loop.Bind();
2932 }
2933 break;
2934 case DONT_KNOW: {
2935 if (test_at_bottom) {
2936 // Continue is either the update expression or the test at the
2937 // bottom, no need to label the test at the top.
2938 node->continue_target()->set_direction(JumpTarget::FORWARD_ONLY);
2939 } else if (node->next() == NULL) {
2940 // We are not recompiling the test at the bottom and there is no
2941 // update expression.
2942 node->continue_target()->set_direction(JumpTarget::BIDIRECTIONAL);
2943 node->continue_target()->Bind();
2944 } else {
2945 // We are not recompiling the test at the bottom and there is an
2946 // update expression.
2947 node->continue_target()->set_direction(JumpTarget::FORWARD_ONLY);
2948 loop.Bind();
2949 }
2950 // Compile the test with the body as the true target and preferred
2951 // fall-through and with the break target as the false target.
2952 ControlDestination dest(&body, node->break_target(), true);
2953 LoadCondition(node->cond(), NOT_INSIDE_TYPEOF, &dest, true);
2954
2955 if (dest.false_was_fall_through()) {
2956 // If we got the break target as fall-through, the test may have
2957 // been unconditionally false (if there are no jumps to the
2958 // body).
2959 if (!body.is_linked()) {
2960 DecrementLoopNesting();
2961 return;
2962 }
2963
2964 // Otherwise, jump around the body on the fall through and then
2965 // bind the body target.
2966 node->break_target()->Unuse();
2967 node->break_target()->Jump();
2968 body.Bind();
2969 }
2970 break;
2971 }
2972 case ALWAYS_FALSE:
2973 UNREACHABLE();
2974 break;
2975 }
2976
2977 CheckStack(); // TODO(1222600): ignore if body contains calls.
2978 Visit(node->body());
2979
2980 // If there is an update expression, compile it if necessary.
2981 if (node->next() != NULL) {
2982 if (node->continue_target()->is_linked()) {
2983 node->continue_target()->Bind();
2984 }
2985
2986 // Control can reach the update by falling out of the body or by a
2987 // continue.
2988 if (has_valid_frame()) {
2989 // Record the source position of the statement as this code which
2990 // is after the code for the body actually belongs to the loop
2991 // statement and not the body.
2992 CodeForStatementPosition(node);
2993 Visit(node->next());
2994 }
2995 }
2996
2997 // Based on the condition analysis, compile the backward jump as
2998 // necessary.
2999 switch (info) {
3000 case ALWAYS_TRUE:
3001 if (has_valid_frame()) {
3002 if (node->next() == NULL) {
3003 node->continue_target()->Jump();
3004 } else {
3005 loop.Jump();
3006 }
3007 }
3008 case DONT_KNOW:
3009 if (test_at_bottom) {
2760 if (node->continue_target()->is_linked()) { 3010 if (node->continue_target()->is_linked()) {
3011 // We can have dangling jumps to the continue target if there
3012 // was no update expression.
2761 node->continue_target()->Bind(); 3013 node->continue_target()->Bind();
2762 } 3014 }
2763 if (node->break_target()->is_linked()) { 3015 // Control can reach the test at the bottom by falling out of
2764 node->break_target()->Bind(); 3016 // the body, by a continue in the body, or from the update
2765 } 3017 // expression.
2766
2767 } else {
2768 ASSERT(info == DONT_KNOW);
2769 // We have to compile the test expression if it can be reached by
2770 // control flow falling out of the body or via continue.
2771 if (node->continue_target()->is_linked()) {
2772 node->continue_target()->Bind();
2773 }
2774 if (has_valid_frame()) { 3018 if (has_valid_frame()) {
3019 // The break target is the fall-through (body is a backward
3020 // jump from here).
2775 ControlDestination dest(&body, node->break_target(), false); 3021 ControlDestination dest(&body, node->break_target(), false);
2776 LoadCondition(node->cond(), NOT_INSIDE_TYPEOF, &dest, true); 3022 LoadCondition(node->cond(), NOT_INSIDE_TYPEOF, &dest, true);
2777 } 3023 }
2778 if (node->break_target()->is_linked()) { 3024 } else {
2779 node->break_target()->Bind(); 3025 // Otherwise, jump back to the test at the top.
2780 }
2781 }
2782 break;
2783 }
2784
2785 case LoopStatement::WHILE_LOOP: {
2786 // Do not duplicate conditions that may have function literal
2787 // subexpressions. This can cause us to compile the function
2788 // literal twice.
2789 bool test_at_bottom = !node->may_have_function_literal();
2790
2791 IncrementLoopNesting();
2792
2793 // If the condition is always false and has no side effects, we
2794 // do not need to compile anything.
2795 if (info == ALWAYS_FALSE) break;
2796
2797 JumpTarget body;
2798 if (test_at_bottom) {
2799 body.set_direction(JumpTarget::BIDIRECTIONAL);
2800 }
2801
2802 // Based on the condition analysis, compile the test as necessary.
2803 if (info == ALWAYS_TRUE) {
2804 // We will not compile the test expression. Label the top of
2805 // the loop with the continue target.
2806 node->continue_target()->set_direction(JumpTarget::BIDIRECTIONAL);
2807 node->continue_target()->Bind();
2808 } else {
2809 ASSERT(info == DONT_KNOW); // ALWAYS_FALSE cannot reach here.
2810 if (test_at_bottom) {
2811 // Continue is the test at the bottom, no need to label the
2812 // test at the top. The body is a backward target.
2813 node->continue_target()->set_direction(JumpTarget::FORWARD_ONLY);
2814 } else {
2815 // Label the test at the top as the continue target. The
2816 // body is a forward-only target.
2817 node->continue_target()->set_direction(JumpTarget::BIDIRECTIONAL);
2818 node->continue_target()->Bind();
2819 }
2820 // Compile the test with the body as the true target and
2821 // preferred fall-through and with the break target as the
2822 // false target.
2823 ControlDestination dest(&body, node->break_target(), true);
2824 LoadCondition(node->cond(), NOT_INSIDE_TYPEOF, &dest, true);
2825
2826 if (dest.false_was_fall_through()) {
2827 // If we got the break target as fall-through, the test may
2828 // have been unconditionally false (if there are no jumps to
2829 // the body).
2830 if (!body.is_linked()) break;
2831
2832 // Otherwise, jump around the body on the fall through and
2833 // then bind the body target.
2834 node->break_target()->Unuse();
2835 node->break_target()->Jump();
2836 body.Bind();
2837 }
2838 }
2839
2840 CheckStack(); // TODO(1222600): ignore if body contains calls.
2841 Visit(node->body());
2842
2843 // Based on the condition analysis, compile the backward jump as
2844 // necessary.
2845 if (info == ALWAYS_TRUE) {
2846 // The loop body has been labeled with the continue target.
2847 if (has_valid_frame()) {
2848 node->continue_target()->Jump();
2849 }
2850 } else {
2851 ASSERT(info == DONT_KNOW); // ALWAYS_FALSE cannot reach here.
2852 if (test_at_bottom) {
2853 // If we have chosen to recompile the test at the bottom,
2854 // then it is the continue target.
2855 if (node->continue_target()->is_linked()) {
2856 node->continue_target()->Bind();
2857 }
2858 if (has_valid_frame()) {
2859 // The break target is the fall-through (body is a backward
2860 // jump from here and thus an invalid fall-through).
2861 ControlDestination dest(&body, node->break_target(), false);
2862 LoadCondition(node->cond(), NOT_INSIDE_TYPEOF, &dest, true);
2863 }
2864 } else {
2865 // If we have chosen not to recompile the test at the
2866 // bottom, jump back to the one at the top.
2867 if (has_valid_frame()) {
2868 node->continue_target()->Jump();
2869 }
2870 }
2871 }
2872
2873 // The break target may be already bound (by the condition), or
2874 // there may not be a valid frame. Bind it only if needed.
2875 if (node->break_target()->is_linked()) {
2876 node->break_target()->Bind();
2877 }
2878 break;
2879 }
2880
2881 case LoopStatement::FOR_LOOP: {
2882 // Do not duplicate conditions that may have function literal
2883 // subexpressions. This can cause us to compile the function
2884 // literal twice.
2885 bool test_at_bottom = !node->may_have_function_literal();
2886
2887 // Compile the init expression if present.
2888 if (node->init() != NULL) {
2889 Visit(node->init());
2890 }
2891
2892 IncrementLoopNesting();
2893
2894 // If the condition is always false and has no side effects, we
2895 // do not need to compile anything else.
2896 if (info == ALWAYS_FALSE) break;
2897
2898 // Target for backward edge if no test at the bottom, otherwise
2899 // unused.
2900 JumpTarget loop(JumpTarget::BIDIRECTIONAL);
2901
2902 // Target for backward edge if there is a test at the bottom,
2903 // otherwise used as target for test at the top.
2904 JumpTarget body;
2905 if (test_at_bottom) {
2906 body.set_direction(JumpTarget::BIDIRECTIONAL);
2907 }
2908
2909 // Based on the condition analysis, compile the test as necessary.
2910 if (info == ALWAYS_TRUE) {
2911 // We will not compile the test expression. Label the top of
2912 // the loop.
2913 if (node->next() == NULL) {
2914 // Use the continue target if there is no update expression.
2915 node->continue_target()->set_direction(JumpTarget::BIDIRECTIONAL);
2916 node->continue_target()->Bind();
2917 } else {
2918 // Otherwise use the backward loop target.
2919 node->continue_target()->set_direction(JumpTarget::FORWARD_ONLY);
2920 loop.Bind();
2921 }
2922 } else {
2923 ASSERT(info == DONT_KNOW);
2924 if (test_at_bottom) {
2925 // Continue is either the update expression or the test at
2926 // the bottom, no need to label the test at the top.
2927 node->continue_target()->set_direction(JumpTarget::FORWARD_ONLY);
2928 } else if (node->next() == NULL) {
2929 // We are not recompiling the test at the bottom and there
2930 // is no update expression.
2931 node->continue_target()->set_direction(JumpTarget::BIDIRECTIONAL);
2932 node->continue_target()->Bind();
2933 } else {
2934 // We are not recompiling the test at the bottom and there
2935 // is an update expression.
2936 node->continue_target()->set_direction(JumpTarget::FORWARD_ONLY);
2937 loop.Bind();
2938 }
2939
2940 // Compile the test with the body as the true target and
2941 // preferred fall-through and with the break target as the
2942 // false target.
2943 ControlDestination dest(&body, node->break_target(), true);
2944 LoadCondition(node->cond(), NOT_INSIDE_TYPEOF, &dest, true);
2945
2946 if (dest.false_was_fall_through()) {
2947 // If we got the break target as fall-through, the test may
2948 // have been unconditionally false (if there are no jumps to
2949 // the body).
2950 if (!body.is_linked()) break;
2951
2952 // Otherwise, jump around the body on the fall through and
2953 // then bind the body target.
2954 node->break_target()->Unuse();
2955 node->break_target()->Jump();
2956 body.Bind();
2957 }
2958 }
2959
2960 CheckStack(); // TODO(1222600): ignore if body contains calls.
2961 Visit(node->body());
2962
2963 // If there is an update expression, compile it if necessary.
2964 if (node->next() != NULL) {
2965 if (node->continue_target()->is_linked()) {
2966 node->continue_target()->Bind();
2967 }
2968
2969 // Control can reach the update by falling out of the body or
2970 // by a continue.
2971 if (has_valid_frame()) {
2972 // Record the source position of the statement as this code
2973 // which is after the code for the body actually belongs to
2974 // the loop statement and not the body.
2975 CodeForStatementPosition(node);
2976 Visit(node->next());
2977 }
2978 }
2979
2980 // Based on the condition analysis, compile the backward jump as
2981 // necessary.
2982 if (info == ALWAYS_TRUE) {
2983 if (has_valid_frame()) { 3026 if (has_valid_frame()) {
2984 if (node->next() == NULL) { 3027 if (node->next() == NULL) {
2985 node->continue_target()->Jump(); 3028 node->continue_target()->Jump();
2986 } else { 3029 } else {
2987 loop.Jump(); 3030 loop.Jump();
2988 } 3031 }
2989 } 3032 }
2990 } else {
2991 ASSERT(info == DONT_KNOW); // ALWAYS_FALSE cannot reach here.
2992 if (test_at_bottom) {
2993 if (node->continue_target()->is_linked()) {
2994 // We can have dangling jumps to the continue target if
2995 // there was no update expression.
2996 node->continue_target()->Bind();
2997 }
2998 // Control can reach the test at the bottom by falling out
2999 // of the body, by a continue in the body, or from the
3000 // update expression.
3001 if (has_valid_frame()) {
3002 // The break target is the fall-through (body is a
3003 // backward jump from here).
3004 ControlDestination dest(&body, node->break_target(), false);
3005 LoadCondition(node->cond(), NOT_INSIDE_TYPEOF, &dest, true);
3006 }
3007 } else {
3008 // Otherwise, jump back to the test at the top.
3009 if (has_valid_frame()) {
3010 if (node->next() == NULL) {
3011 node->continue_target()->Jump();
3012 } else {
3013 loop.Jump();
3014 }
3015 }
3016 }
3017 } 3033 }
3018 3034 case ALWAYS_FALSE:
3019 // The break target may be already bound (by the condition), or 3035 UNREACHABLE();
3020 // there may not be a valid frame. Bind it only if needed.
3021 if (node->break_target()->is_linked()) {
3022 node->break_target()->Bind();
3023 }
3024 break; 3036 break;
3025 }
3026 } 3037 }
3027 3038
3039 // The break target may be already bound (by the condition), or
3040 // there may not be a valid frame. Bind it only if needed.
3041 if (node->break_target()->is_linked()) {
3042 node->break_target()->Bind();
3043 }
3028 DecrementLoopNesting(); 3044 DecrementLoopNesting();
3029 node->continue_target()->Unuse();
3030 node->break_target()->Unuse();
3031 } 3045 }
3032 3046
3033 3047
3034 void CodeGenerator::VisitForInStatement(ForInStatement* node) { 3048 void CodeGenerator::VisitForInStatement(ForInStatement* node) {
3035 ASSERT(!in_spilled_code()); 3049 ASSERT(!in_spilled_code());
3036 VirtualFrame::SpilledScope spilled_scope; 3050 VirtualFrame::SpilledScope spilled_scope;
3037 Comment cmnt(masm_, "[ ForInStatement"); 3051 Comment cmnt(masm_, "[ ForInStatement");
3038 CodeForStatementPosition(node); 3052 CodeForStatementPosition(node);
3039 3053
3040 JumpTarget primitive; 3054 JumpTarget primitive;
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after
3214 frame_->Drop(5); 3228 frame_->Drop(5);
3215 3229
3216 // Exit. 3230 // Exit.
3217 exit.Bind(); 3231 exit.Bind();
3218 3232
3219 node->continue_target()->Unuse(); 3233 node->continue_target()->Unuse();
3220 node->break_target()->Unuse(); 3234 node->break_target()->Unuse();
3221 } 3235 }
3222 3236
3223 3237
3224 void CodeGenerator::VisitTryCatch(TryCatch* node) { 3238 void CodeGenerator::VisitTryCatchStatement(TryCatchStatement* node) {
3225 ASSERT(!in_spilled_code()); 3239 ASSERT(!in_spilled_code());
3226 VirtualFrame::SpilledScope spilled_scope; 3240 VirtualFrame::SpilledScope spilled_scope;
3227 Comment cmnt(masm_, "[ TryCatch"); 3241 Comment cmnt(masm_, "[ TryCatchStatement");
3228 CodeForStatementPosition(node); 3242 CodeForStatementPosition(node);
3229 3243
3230 JumpTarget try_block; 3244 JumpTarget try_block;
3231 JumpTarget exit; 3245 JumpTarget exit;
3232 3246
3233 try_block.Call(); 3247 try_block.Call();
3234 // --- Catch block --- 3248 // --- Catch block ---
3235 frame_->EmitPush(eax); 3249 frame_->EmitPush(eax);
3236 3250
3237 // Store the caught exception in the catch variable. 3251 // Store the caught exception in the catch variable.
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
3350 } else { 3364 } else {
3351 shadows[i]->other_target()->Jump(); 3365 shadows[i]->other_target()->Jump();
3352 } 3366 }
3353 } 3367 }
3354 } 3368 }
3355 3369
3356 exit.Bind(); 3370 exit.Bind();
3357 } 3371 }
3358 3372
3359 3373
3360 void CodeGenerator::VisitTryFinally(TryFinally* node) { 3374 void CodeGenerator::VisitTryFinallyStatement(TryFinallyStatement* node) {
3361 ASSERT(!in_spilled_code()); 3375 ASSERT(!in_spilled_code());
3362 VirtualFrame::SpilledScope spilled_scope; 3376 VirtualFrame::SpilledScope spilled_scope;
3363 Comment cmnt(masm_, "[ TryFinally"); 3377 Comment cmnt(masm_, "[ TryFinallyStatement");
3364 CodeForStatementPosition(node); 3378 CodeForStatementPosition(node);
3365 3379
3366 // State: Used to keep track of reason for entering the finally 3380 // State: Used to keep track of reason for entering the finally
3367 // block. Should probably be extended to hold information for 3381 // block. Should probably be extended to hold information for
3368 // break/continue from within the try block. 3382 // break/continue from within the try block.
3369 enum { FALLING, THROWING, JUMPING }; 3383 enum { FALLING, THROWING, JUMPING };
3370 3384
3371 JumpTarget try_block; 3385 JumpTarget try_block;
3372 JumpTarget finally_block; 3386 JumpTarget finally_block;
3373 3387
(...skipping 4736 matching lines...) Expand 10 before | Expand all | Expand 10 after
8110 8124
8111 int CompareStub::MinorKey() { 8125 int CompareStub::MinorKey() {
8112 // Encode the two parameters in a unique 16 bit value. 8126 // Encode the two parameters in a unique 16 bit value.
8113 ASSERT(static_cast<unsigned>(cc_) < (1 << 15)); 8127 ASSERT(static_cast<unsigned>(cc_) < (1 << 15));
8114 return (static_cast<unsigned>(cc_) << 1) | (strict_ ? 1 : 0); 8128 return (static_cast<unsigned>(cc_) << 1) | (strict_ ? 1 : 0);
8115 } 8129 }
8116 8130
8117 #undef __ 8131 #undef __
8118 8132
8119 } } // namespace v8::internal 8133 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/ia32/codegen-ia32.h ('k') | src/parser.cc » ('j') | src/parser.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698