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