OLD | NEW |
1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2008 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
141 TemporaryScope* temp_scope_; | 141 TemporaryScope* temp_scope_; |
142 Mode mode_; | 142 Mode mode_; |
143 | 143 |
144 Target* target_stack_; // for break, continue statements | 144 Target* target_stack_; // for break, continue statements |
145 bool allow_natives_syntax_; | 145 bool allow_natives_syntax_; |
146 v8::Extension* extension_; | 146 v8::Extension* extension_; |
147 ParserFactory* factory_; | 147 ParserFactory* factory_; |
148 ParserLog* log_; | 148 ParserLog* log_; |
149 bool is_pre_parsing_; | 149 bool is_pre_parsing_; |
150 ScriptDataImpl* pre_data_; | 150 ScriptDataImpl* pre_data_; |
| 151 bool seen_loop_stmt_; // Used for inner loop detection. |
151 | 152 |
152 bool inside_with() const { return with_nesting_level_ > 0; } | 153 bool inside_with() const { return with_nesting_level_ > 0; } |
153 ParserFactory* factory() const { return factory_; } | 154 ParserFactory* factory() const { return factory_; } |
154 ParserLog* log() const { return log_; } | 155 ParserLog* log() const { return log_; } |
155 Scanner& scanner() { return scanner_; } | 156 Scanner& scanner() { return scanner_; } |
156 Mode mode() const { return mode_; } | 157 Mode mode() const { return mode_; } |
157 ScriptDataImpl* pre_data() const { return pre_data_; } | 158 ScriptDataImpl* pre_data() const { return pre_data_; } |
158 | 159 |
159 // All ParseXXX functions take as the last argument an *ok parameter | 160 // All ParseXXX functions take as the last argument an *ok parameter |
160 // which is set to false if parsing failed; it is unchanged otherwise. | 161 // which is set to false if parsing failed; it is unchanged otherwise. |
(...skipping 1037 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1198 scanner_(is_pre_parsing), | 1199 scanner_(is_pre_parsing), |
1199 top_scope_(NULL), | 1200 top_scope_(NULL), |
1200 with_nesting_level_(0), | 1201 with_nesting_level_(0), |
1201 temp_scope_(NULL), | 1202 temp_scope_(NULL), |
1202 target_stack_(NULL), | 1203 target_stack_(NULL), |
1203 allow_natives_syntax_(allow_natives_syntax), | 1204 allow_natives_syntax_(allow_natives_syntax), |
1204 extension_(extension), | 1205 extension_(extension), |
1205 factory_(factory), | 1206 factory_(factory), |
1206 log_(log), | 1207 log_(log), |
1207 is_pre_parsing_(is_pre_parsing == PREPARSE), | 1208 is_pre_parsing_(is_pre_parsing == PREPARSE), |
1208 pre_data_(pre_data) { | 1209 pre_data_(pre_data), |
| 1210 seen_loop_stmt_(false) { |
1209 } | 1211 } |
1210 | 1212 |
1211 | 1213 |
1212 bool Parser::PreParseProgram(Handle<String> source, | 1214 bool Parser::PreParseProgram(Handle<String> source, |
1213 unibrow::CharacterStream* stream) { | 1215 unibrow::CharacterStream* stream) { |
1214 HistogramTimerScope timer(&Counters::pre_parse); | 1216 HistogramTimerScope timer(&Counters::pre_parse); |
1215 AssertNoZoneAllocation assert_no_zone_allocation; | 1217 AssertNoZoneAllocation assert_no_zone_allocation; |
1216 AssertNoAllocation assert_no_allocation; | 1218 AssertNoAllocation assert_no_allocation; |
1217 NoHandleAllocation no_handle_allocation; | 1219 NoHandleAllocation no_handle_allocation; |
1218 scanner_.Initialize(source, stream, JAVASCRIPT); | 1220 scanner_.Initialize(source, stream, JAVASCRIPT); |
(...skipping 1425 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2644 Expression* cond = ParseExpression(true, CHECK_OK); | 2646 Expression* cond = ParseExpression(true, CHECK_OK); |
2645 Expect(Token::RPAREN, CHECK_OK); | 2647 Expect(Token::RPAREN, CHECK_OK); |
2646 | 2648 |
2647 // Allow do-statements to be terminated with and without | 2649 // Allow do-statements to be terminated with and without |
2648 // semi-colons. This allows code such as 'do;while(0)return' to | 2650 // semi-colons. This allows code such as 'do;while(0)return' to |
2649 // parse, which would not be the case if we had used the | 2651 // parse, which would not be the case if we had used the |
2650 // ExpectSemicolon() functionality here. | 2652 // ExpectSemicolon() functionality here. |
2651 if (peek() == Token::SEMICOLON) Consume(Token::SEMICOLON); | 2653 if (peek() == Token::SEMICOLON) Consume(Token::SEMICOLON); |
2652 | 2654 |
2653 if (loop != NULL) loop->Initialize(cond, body); | 2655 if (loop != NULL) loop->Initialize(cond, body); |
| 2656 |
| 2657 seen_loop_stmt_ = true; |
| 2658 |
2654 return loop; | 2659 return loop; |
2655 } | 2660 } |
2656 | 2661 |
2657 | 2662 |
2658 WhileStatement* Parser::ParseWhileStatement(ZoneStringList* labels, bool* ok) { | 2663 WhileStatement* Parser::ParseWhileStatement(ZoneStringList* labels, bool* ok) { |
2659 // WhileStatement :: | 2664 // WhileStatement :: |
2660 // 'while' '(' Expression ')' Statement | 2665 // 'while' '(' Expression ')' Statement |
2661 | 2666 |
2662 WhileStatement* loop = NEW(WhileStatement(labels)); | 2667 WhileStatement* loop = NEW(WhileStatement(labels)); |
2663 Target target(this, loop); | 2668 Target target(this, loop); |
2664 | 2669 |
2665 Expect(Token::WHILE, CHECK_OK); | 2670 Expect(Token::WHILE, CHECK_OK); |
2666 Expect(Token::LPAREN, CHECK_OK); | 2671 Expect(Token::LPAREN, CHECK_OK); |
2667 Expression* cond = ParseExpression(true, CHECK_OK); | 2672 Expression* cond = ParseExpression(true, CHECK_OK); |
2668 Expect(Token::RPAREN, CHECK_OK); | 2673 Expect(Token::RPAREN, CHECK_OK); |
2669 Statement* body = ParseStatement(NULL, CHECK_OK); | 2674 Statement* body = ParseStatement(NULL, CHECK_OK); |
2670 | 2675 |
2671 if (loop != NULL) loop->Initialize(cond, body); | 2676 if (loop != NULL) loop->Initialize(cond, body); |
| 2677 |
| 2678 seen_loop_stmt_ = true; |
| 2679 |
2672 return loop; | 2680 return loop; |
2673 } | 2681 } |
2674 | 2682 |
2675 | 2683 |
2676 Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) { | 2684 Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) { |
2677 // ForStatement :: | 2685 // ForStatement :: |
2678 // 'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement | 2686 // 'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement |
2679 | 2687 |
2680 Statement* init = NULL; | 2688 Statement* init = NULL; |
2681 | 2689 |
(...skipping 13 matching lines...) Expand all Loading... |
2695 Expect(Token::RPAREN, CHECK_OK); | 2703 Expect(Token::RPAREN, CHECK_OK); |
2696 | 2704 |
2697 Statement* body = ParseStatement(NULL, CHECK_OK); | 2705 Statement* body = ParseStatement(NULL, CHECK_OK); |
2698 if (is_pre_parsing_) { | 2706 if (is_pre_parsing_) { |
2699 return NULL; | 2707 return NULL; |
2700 } else { | 2708 } else { |
2701 loop->Initialize(each, enumerable, body); | 2709 loop->Initialize(each, enumerable, body); |
2702 Block* result = NEW(Block(NULL, 2, false)); | 2710 Block* result = NEW(Block(NULL, 2, false)); |
2703 result->AddStatement(variable_statement); | 2711 result->AddStatement(variable_statement); |
2704 result->AddStatement(loop); | 2712 result->AddStatement(loop); |
| 2713 |
| 2714 seen_loop_stmt_ = true; |
| 2715 |
2705 // Parsed for-in loop w/ variable/const declaration. | 2716 // Parsed for-in loop w/ variable/const declaration. |
2706 return result; | 2717 return result; |
2707 } | 2718 } |
2708 | 2719 |
2709 } else { | 2720 } else { |
2710 init = variable_statement; | 2721 init = variable_statement; |
2711 } | 2722 } |
2712 | 2723 |
2713 } else { | 2724 } else { |
2714 Expression* expression = ParseExpression(false, CHECK_OK); | 2725 Expression* expression = ParseExpression(false, CHECK_OK); |
2715 if (peek() == Token::IN) { | 2726 if (peek() == Token::IN) { |
2716 // Signal a reference error if the expression is an invalid | 2727 // Signal a reference error if the expression is an invalid |
2717 // left-hand side expression. We could report this as a syntax | 2728 // left-hand side expression. We could report this as a syntax |
2718 // error here but for compatibility with JSC we choose to report | 2729 // error here but for compatibility with JSC we choose to report |
2719 // the error at runtime. | 2730 // the error at runtime. |
2720 if (expression == NULL || !expression->IsValidLeftHandSide()) { | 2731 if (expression == NULL || !expression->IsValidLeftHandSide()) { |
2721 Handle<String> type = Factory::invalid_lhs_in_for_in_symbol(); | 2732 Handle<String> type = Factory::invalid_lhs_in_for_in_symbol(); |
2722 expression = NewThrowReferenceError(type); | 2733 expression = NewThrowReferenceError(type); |
2723 } | 2734 } |
2724 ForInStatement* loop = NEW(ForInStatement(labels)); | 2735 ForInStatement* loop = NEW(ForInStatement(labels)); |
2725 Target target(this, loop); | 2736 Target target(this, loop); |
2726 | 2737 |
2727 Expect(Token::IN, CHECK_OK); | 2738 Expect(Token::IN, CHECK_OK); |
2728 Expression* enumerable = ParseExpression(true, CHECK_OK); | 2739 Expression* enumerable = ParseExpression(true, CHECK_OK); |
2729 Expect(Token::RPAREN, CHECK_OK); | 2740 Expect(Token::RPAREN, CHECK_OK); |
2730 | 2741 |
2731 Statement* body = ParseStatement(NULL, CHECK_OK); | 2742 Statement* body = ParseStatement(NULL, CHECK_OK); |
2732 if (loop) loop->Initialize(expression, enumerable, body); | 2743 if (loop) loop->Initialize(expression, enumerable, body); |
2733 | 2744 |
| 2745 seen_loop_stmt_ = true; |
| 2746 |
2734 // Parsed for-in loop. | 2747 // Parsed for-in loop. |
2735 return loop; | 2748 return loop; |
2736 | 2749 |
2737 } else { | 2750 } else { |
2738 init = NEW(ExpressionStatement(expression)); | 2751 init = NEW(ExpressionStatement(expression)); |
2739 } | 2752 } |
2740 } | 2753 } |
2741 } | 2754 } |
2742 | 2755 |
2743 // Standard 'for' loop | 2756 // Standard 'for' loop |
(...skipping 12 matching lines...) Expand all Loading... |
2756 } | 2769 } |
2757 Expect(Token::SEMICOLON, CHECK_OK); | 2770 Expect(Token::SEMICOLON, CHECK_OK); |
2758 | 2771 |
2759 Statement* next = NULL; | 2772 Statement* next = NULL; |
2760 if (peek() != Token::RPAREN) { | 2773 if (peek() != Token::RPAREN) { |
2761 Expression* exp = ParseExpression(true, CHECK_OK); | 2774 Expression* exp = ParseExpression(true, CHECK_OK); |
2762 next = NEW(ExpressionStatement(exp)); | 2775 next = NEW(ExpressionStatement(exp)); |
2763 } | 2776 } |
2764 Expect(Token::RPAREN, CHECK_OK); | 2777 Expect(Token::RPAREN, CHECK_OK); |
2765 | 2778 |
| 2779 seen_loop_stmt_ = false; |
| 2780 |
2766 Statement* body = ParseStatement(NULL, CHECK_OK); | 2781 Statement* body = ParseStatement(NULL, CHECK_OK); |
2767 | 2782 |
| 2783 // Mark this loop if it is an inner loop. |
| 2784 if (loop && !seen_loop_stmt_) loop->set_peel_this_loop(true); |
| 2785 |
2768 if (loop) loop->Initialize(init, cond, next, body); | 2786 if (loop) loop->Initialize(init, cond, next, body); |
| 2787 |
| 2788 seen_loop_stmt_ = true; |
| 2789 |
2769 return loop; | 2790 return loop; |
2770 } | 2791 } |
2771 | 2792 |
2772 | 2793 |
2773 // Precedence = 1 | 2794 // Precedence = 1 |
2774 Expression* Parser::ParseExpression(bool accept_IN, bool* ok) { | 2795 Expression* Parser::ParseExpression(bool accept_IN, bool* ok) { |
2775 // Expression :: | 2796 // Expression :: |
2776 // AssignmentExpression | 2797 // AssignmentExpression |
2777 // Expression ',' AssignmentExpression | 2798 // Expression ',' AssignmentExpression |
2778 | 2799 |
(...skipping 924 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3703 } | 3724 } |
3704 | 3725 |
3705 | 3726 |
3706 FunctionLiteral* Parser::ParseFunctionLiteral(Handle<String> var_name, | 3727 FunctionLiteral* Parser::ParseFunctionLiteral(Handle<String> var_name, |
3707 int function_token_position, | 3728 int function_token_position, |
3708 FunctionLiteralType type, | 3729 FunctionLiteralType type, |
3709 bool* ok) { | 3730 bool* ok) { |
3710 // Function :: | 3731 // Function :: |
3711 // '(' FormalParameterList? ')' '{' FunctionBody '}' | 3732 // '(' FormalParameterList? ')' '{' FunctionBody '}' |
3712 | 3733 |
| 3734 // Reset flag used for inner loop detection. |
| 3735 seen_loop_stmt_ = false; |
| 3736 |
3713 bool is_named = !var_name.is_null(); | 3737 bool is_named = !var_name.is_null(); |
3714 | 3738 |
3715 // The name associated with this function. If it's a function expression, | 3739 // The name associated with this function. If it's a function expression, |
3716 // this is the actual function name, otherwise this is the name of the | 3740 // this is the actual function name, otherwise this is the name of the |
3717 // variable declared and initialized with the function (expression). In | 3741 // variable declared and initialized with the function (expression). In |
3718 // that case, we don't have a function name (it's empty). | 3742 // that case, we don't have a function name (it's empty). |
3719 Handle<String> name = is_named ? var_name : factory()->EmptySymbol(); | 3743 Handle<String> name = is_named ? var_name : factory()->EmptySymbol(); |
3720 // The function name, if any. | 3744 // The function name, if any. |
3721 Handle<String> function_name = factory()->EmptySymbol(); | 3745 Handle<String> function_name = factory()->EmptySymbol(); |
3722 if (is_named && (type == EXPRESSION || type == NESTED)) { | 3746 if (is_named && (type == EXPRESSION || type == NESTED)) { |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3813 expected_property_count, | 3837 expected_property_count, |
3814 only_simple_this_property_assignments, | 3838 only_simple_this_property_assignments, |
3815 this_property_assignments, | 3839 this_property_assignments, |
3816 num_parameters, | 3840 num_parameters, |
3817 start_pos, | 3841 start_pos, |
3818 end_pos, | 3842 end_pos, |
3819 function_name->length() > 0)); | 3843 function_name->length() > 0)); |
3820 if (!is_pre_parsing_) { | 3844 if (!is_pre_parsing_) { |
3821 function_literal->set_function_token_position(function_token_position); | 3845 function_literal->set_function_token_position(function_token_position); |
3822 } | 3846 } |
| 3847 |
| 3848 // Set flag for inner loop detection. We treat loops that contain a function |
| 3849 // literal not as inner loops because we avoid duplicating function literals |
| 3850 // when peeling or unrolling such a loop. |
| 3851 seen_loop_stmt_ = true; |
| 3852 |
3823 return function_literal; | 3853 return function_literal; |
3824 } | 3854 } |
3825 } | 3855 } |
3826 | 3856 |
3827 | 3857 |
3828 Expression* Parser::ParseV8Intrinsic(bool* ok) { | 3858 Expression* Parser::ParseV8Intrinsic(bool* ok) { |
3829 // CallRuntime :: | 3859 // CallRuntime :: |
3830 // '%' Identifier Arguments | 3860 // '%' Identifier Arguments |
3831 | 3861 |
3832 Expect(Token::MOD, CHECK_OK); | 3862 Expect(Token::MOD, CHECK_OK); |
(...skipping 1309 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5142 parser.ParseLazy(script_source, name, | 5172 parser.ParseLazy(script_source, name, |
5143 start_position, end_position, is_expression); | 5173 start_position, end_position, is_expression); |
5144 return result; | 5174 return result; |
5145 } | 5175 } |
5146 | 5176 |
5147 | 5177 |
5148 #undef NEW | 5178 #undef NEW |
5149 | 5179 |
5150 | 5180 |
5151 } } // namespace v8::internal | 5181 } } // namespace v8::internal |
OLD | NEW |