| 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 |