OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/parsing/parser.h" | 5 #include "src/parsing/parser.h" |
6 | 6 |
7 #include "src/api.h" | 7 #include "src/api.h" |
8 #include "src/ast/ast.h" | 8 #include "src/ast/ast.h" |
9 #include "src/ast/ast-expression-rewriter.h" | 9 #include "src/ast/ast-expression-rewriter.h" |
10 #include "src/ast/ast-expression-visitor.h" | 10 #include "src/ast/ast-expression-visitor.h" |
(...skipping 2774 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2785 // temp === undefined | 2785 // temp === undefined |
2786 Expression* is_undefined = factory()->NewCompareOperation( | 2786 Expression* is_undefined = factory()->NewCompareOperation( |
2787 Token::EQ_STRICT, assign, | 2787 Token::EQ_STRICT, assign, |
2788 factory()->NewUndefinedLiteral(RelocInfo::kNoPosition), pos); | 2788 factory()->NewUndefinedLiteral(RelocInfo::kNoPosition), pos); |
2789 | 2789 |
2790 // is_undefined ? this : is_object_conditional | 2790 // is_undefined ? this : is_object_conditional |
2791 return_value = factory()->NewConditional( | 2791 return_value = factory()->NewConditional( |
2792 is_undefined, ThisExpression(scope_, factory(), pos), | 2792 is_undefined, ThisExpression(scope_, factory(), pos), |
2793 is_object_conditional, pos); | 2793 is_object_conditional, pos); |
2794 } | 2794 } |
| 2795 |
| 2796 // ES6 14.6.1 Static Semantics: IsInTailPosition |
| 2797 if (FLAG_harmony_tailcalls && !is_sloppy(language_mode())) { |
| 2798 function_state_->AddExpressionInTailPosition(return_value); |
| 2799 } |
2795 } | 2800 } |
2796 ExpectSemicolon(CHECK_OK); | 2801 ExpectSemicolon(CHECK_OK); |
2797 | 2802 |
2798 if (is_generator()) { | 2803 if (is_generator()) { |
2799 Expression* generator = factory()->NewVariableProxy( | 2804 Expression* generator = factory()->NewVariableProxy( |
2800 function_state_->generator_object_variable()); | 2805 function_state_->generator_object_variable()); |
2801 Expression* yield = factory()->NewYield( | 2806 Expression* yield = factory()->NewYield( |
2802 generator, return_value, Yield::kFinal, loc.beg_pos); | 2807 generator, return_value, Yield::kFinal, loc.beg_pos); |
2803 result = factory()->NewExpressionStatement(yield, loc.beg_pos); | 2808 result = factory()->NewExpressionStatement(yield, loc.beg_pos); |
2804 } else { | 2809 } else { |
(...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2990 *ok = false; | 2995 *ok = false; |
2991 return NULL; | 2996 return NULL; |
2992 } | 2997 } |
2993 Expression* exception = ParseExpression(true, CHECK_OK); | 2998 Expression* exception = ParseExpression(true, CHECK_OK); |
2994 ExpectSemicolon(CHECK_OK); | 2999 ExpectSemicolon(CHECK_OK); |
2995 | 3000 |
2996 return factory()->NewExpressionStatement( | 3001 return factory()->NewExpressionStatement( |
2997 factory()->NewThrow(exception, pos), pos); | 3002 factory()->NewThrow(exception, pos), pos); |
2998 } | 3003 } |
2999 | 3004 |
| 3005 class Parser::DontCollectExpressionsInTailPositionScope { |
| 3006 public: |
| 3007 DontCollectExpressionsInTailPositionScope( |
| 3008 Parser::FunctionState* function_state) |
| 3009 : function_state_(function_state), |
| 3010 old_value_(function_state->collect_expressions_in_tail_position()) { |
| 3011 function_state->set_collect_expressions_in_tail_position(false); |
| 3012 } |
| 3013 ~DontCollectExpressionsInTailPositionScope() { |
| 3014 function_state_->set_collect_expressions_in_tail_position(old_value_); |
| 3015 } |
| 3016 |
| 3017 private: |
| 3018 Parser::FunctionState* function_state_; |
| 3019 bool old_value_; |
| 3020 }; |
| 3021 |
| 3022 // Collects all return expressions at tail call position in this scope |
| 3023 // to a separate list. |
| 3024 class Parser::CollectExpressionsInTailPositionToListScope { |
| 3025 public: |
| 3026 CollectExpressionsInTailPositionToListScope( |
| 3027 Parser::FunctionState* function_state, List<Expression*>* list) |
| 3028 : function_state_(function_state), list_(list) { |
| 3029 function_state->expressions_in_tail_position().Swap(list_); |
| 3030 } |
| 3031 ~CollectExpressionsInTailPositionToListScope() { |
| 3032 function_state_->expressions_in_tail_position().Swap(list_); |
| 3033 } |
| 3034 |
| 3035 private: |
| 3036 Parser::FunctionState* function_state_; |
| 3037 List<Expression*>* list_; |
| 3038 }; |
3000 | 3039 |
3001 TryStatement* Parser::ParseTryStatement(bool* ok) { | 3040 TryStatement* Parser::ParseTryStatement(bool* ok) { |
3002 // TryStatement :: | 3041 // TryStatement :: |
3003 // 'try' Block Catch | 3042 // 'try' Block Catch |
3004 // 'try' Block Finally | 3043 // 'try' Block Finally |
3005 // 'try' Block Catch Finally | 3044 // 'try' Block Catch Finally |
3006 // | 3045 // |
3007 // Catch :: | 3046 // Catch :: |
3008 // 'catch' '(' Identifier ')' Block | 3047 // 'catch' '(' Identifier ')' Block |
3009 // | 3048 // |
3010 // Finally :: | 3049 // Finally :: |
3011 // 'finally' Block | 3050 // 'finally' Block |
3012 | 3051 |
3013 Expect(Token::TRY, CHECK_OK); | 3052 Expect(Token::TRY, CHECK_OK); |
3014 int pos = position(); | 3053 int pos = position(); |
3015 | 3054 |
3016 Block* try_block = ParseBlock(NULL, CHECK_OK); | 3055 Block* try_block; |
| 3056 { |
| 3057 DontCollectExpressionsInTailPositionScope no_tail_calls(function_state_); |
| 3058 try_block = ParseBlock(NULL, CHECK_OK); |
| 3059 } |
3017 | 3060 |
3018 Token::Value tok = peek(); | 3061 Token::Value tok = peek(); |
3019 if (tok != Token::CATCH && tok != Token::FINALLY) { | 3062 if (tok != Token::CATCH && tok != Token::FINALLY) { |
3020 ReportMessage(MessageTemplate::kNoCatchOrFinally); | 3063 ReportMessage(MessageTemplate::kNoCatchOrFinally); |
3021 *ok = false; | 3064 *ok = false; |
3022 return NULL; | 3065 return NULL; |
3023 } | 3066 } |
3024 | 3067 |
3025 Scope* catch_scope = NULL; | 3068 Scope* catch_scope = NULL; |
3026 Variable* catch_variable = NULL; | 3069 Variable* catch_variable = NULL; |
3027 Block* catch_block = NULL; | 3070 Block* catch_block = NULL; |
| 3071 List<Expression*> expressions_in_tail_position_in_catch_block; |
3028 if (tok == Token::CATCH) { | 3072 if (tok == Token::CATCH) { |
3029 Consume(Token::CATCH); | 3073 Consume(Token::CATCH); |
3030 | 3074 |
3031 Expect(Token::LPAREN, CHECK_OK); | 3075 Expect(Token::LPAREN, CHECK_OK); |
3032 catch_scope = NewScope(scope_, CATCH_SCOPE); | 3076 catch_scope = NewScope(scope_, CATCH_SCOPE); |
3033 catch_scope->set_start_position(scanner()->location().beg_pos); | 3077 catch_scope->set_start_position(scanner()->location().beg_pos); |
3034 | 3078 |
3035 ExpressionClassifier pattern_classifier; | 3079 ExpressionClassifier pattern_classifier; |
3036 Expression* pattern = ParsePrimaryExpression(&pattern_classifier, CHECK_OK); | 3080 Expression* pattern = ParsePrimaryExpression(&pattern_classifier, CHECK_OK); |
3037 ValidateBindingPattern(&pattern_classifier, CHECK_OK); | 3081 ValidateBindingPattern(&pattern_classifier, CHECK_OK); |
3038 | 3082 |
3039 const AstRawString* name = ast_value_factory()->dot_catch_string(); | 3083 const AstRawString* name = ast_value_factory()->dot_catch_string(); |
3040 bool is_simple = pattern->IsVariableProxy(); | 3084 bool is_simple = pattern->IsVariableProxy(); |
3041 if (is_simple) { | 3085 if (is_simple) { |
3042 auto proxy = pattern->AsVariableProxy(); | 3086 auto proxy = pattern->AsVariableProxy(); |
3043 scope_->RemoveUnresolved(proxy); | 3087 scope_->RemoveUnresolved(proxy); |
3044 name = proxy->raw_name(); | 3088 name = proxy->raw_name(); |
3045 } | 3089 } |
3046 | 3090 |
3047 catch_variable = catch_scope->DeclareLocal(name, VAR, kCreatedInitialized, | 3091 catch_variable = catch_scope->DeclareLocal(name, VAR, kCreatedInitialized, |
3048 Variable::NORMAL); | 3092 Variable::NORMAL); |
3049 | 3093 |
3050 Expect(Token::RPAREN, CHECK_OK); | 3094 Expect(Token::RPAREN, CHECK_OK); |
3051 | 3095 |
3052 { | 3096 { |
| 3097 CollectExpressionsInTailPositionToListScope |
| 3098 collect_expressions_in_tail_position_scope( |
| 3099 function_state_, &expressions_in_tail_position_in_catch_block); |
3053 BlockState block_state(&scope_, catch_scope); | 3100 BlockState block_state(&scope_, catch_scope); |
3054 | 3101 |
3055 // TODO(adamk): Make a version of ParseBlock that takes a scope and | 3102 // TODO(adamk): Make a version of ParseBlock that takes a scope and |
3056 // a block. | 3103 // a block. |
3057 catch_block = | 3104 catch_block = |
3058 factory()->NewBlock(nullptr, 16, false, RelocInfo::kNoPosition); | 3105 factory()->NewBlock(nullptr, 16, false, RelocInfo::kNoPosition); |
3059 Scope* block_scope = NewScope(scope_, BLOCK_SCOPE); | 3106 Scope* block_scope = NewScope(scope_, BLOCK_SCOPE); |
3060 | 3107 |
3061 block_scope->set_start_position(scanner()->location().beg_pos); | 3108 block_scope->set_start_position(scanner()->location().beg_pos); |
3062 { | 3109 { |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3117 TryCatchStatement* statement = | 3164 TryCatchStatement* statement = |
3118 factory()->NewTryCatchStatement(try_block, catch_scope, catch_variable, | 3165 factory()->NewTryCatchStatement(try_block, catch_scope, catch_variable, |
3119 catch_block, RelocInfo::kNoPosition); | 3166 catch_block, RelocInfo::kNoPosition); |
3120 try_block = factory()->NewBlock(NULL, 1, false, RelocInfo::kNoPosition); | 3167 try_block = factory()->NewBlock(NULL, 1, false, RelocInfo::kNoPosition); |
3121 try_block->statements()->Add(statement, zone()); | 3168 try_block->statements()->Add(statement, zone()); |
3122 catch_block = NULL; // Clear to indicate it's been handled. | 3169 catch_block = NULL; // Clear to indicate it's been handled. |
3123 } | 3170 } |
3124 | 3171 |
3125 TryStatement* result = NULL; | 3172 TryStatement* result = NULL; |
3126 if (catch_block != NULL) { | 3173 if (catch_block != NULL) { |
| 3174 // For a try-catch construct append return expressions from the catch block |
| 3175 // to the list of return expressions. |
| 3176 function_state_->expressions_in_tail_position().AddAll( |
| 3177 expressions_in_tail_position_in_catch_block); |
| 3178 |
3127 DCHECK(finally_block == NULL); | 3179 DCHECK(finally_block == NULL); |
3128 DCHECK(catch_scope != NULL && catch_variable != NULL); | 3180 DCHECK(catch_scope != NULL && catch_variable != NULL); |
3129 result = factory()->NewTryCatchStatement(try_block, catch_scope, | 3181 result = factory()->NewTryCatchStatement(try_block, catch_scope, |
3130 catch_variable, catch_block, pos); | 3182 catch_variable, catch_block, pos); |
3131 } else { | 3183 } else { |
3132 DCHECK(finally_block != NULL); | 3184 DCHECK(finally_block != NULL); |
3133 result = factory()->NewTryFinallyStatement(try_block, finally_block, pos); | 3185 result = factory()->NewTryFinallyStatement(try_block, finally_block, pos); |
3134 } | 3186 } |
3135 | 3187 |
3136 return result; | 3188 return result; |
(...skipping 1607 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4744 VariableProxy* fproxy = factory()->NewVariableProxy(fvar); | 4796 VariableProxy* fproxy = factory()->NewVariableProxy(fvar); |
4745 result->Set(kFunctionNameAssignmentIndex, | 4797 result->Set(kFunctionNameAssignmentIndex, |
4746 factory()->NewExpressionStatement( | 4798 factory()->NewExpressionStatement( |
4747 factory()->NewAssignment(Token::INIT, fproxy, | 4799 factory()->NewAssignment(Token::INIT, fproxy, |
4748 factory()->NewThisFunction(pos), | 4800 factory()->NewThisFunction(pos), |
4749 RelocInfo::kNoPosition), | 4801 RelocInfo::kNoPosition), |
4750 RelocInfo::kNoPosition)); | 4802 RelocInfo::kNoPosition)); |
4751 } | 4803 } |
4752 | 4804 |
4753 // ES6 14.6.1 Static Semantics: IsInTailPosition | 4805 // ES6 14.6.1 Static Semantics: IsInTailPosition |
4754 if (FLAG_harmony_tailcalls && !is_sloppy(language_mode())) { | 4806 // Mark collected return expressions that are in tail call position. |
4755 for (int i = 0; i < body->length(); i++) { | 4807 const List<Expression*>& expressions_in_tail_position = |
4756 Statement* stmt = body->at(i); | 4808 function_state_->expressions_in_tail_position(); |
4757 stmt->MarkTail(); | 4809 for (int i = 0; i < expressions_in_tail_position.length(); ++i) { |
4758 } | 4810 expressions_in_tail_position[i]->MarkTail(); |
4759 } | 4811 } |
4760 return result; | 4812 return result; |
4761 } | 4813 } |
4762 | 4814 |
4763 | 4815 |
4764 PreParser::PreParseResult Parser::ParseLazyFunctionBodyWithPreParser( | 4816 PreParser::PreParseResult Parser::ParseLazyFunctionBodyWithPreParser( |
4765 SingletonLogger* logger, Scanner::BookmarkScope* bookmark) { | 4817 SingletonLogger* logger, Scanner::BookmarkScope* bookmark) { |
4766 // This function may be called on a background thread too; record only the | 4818 // This function may be called on a background thread too; record only the |
4767 // main thread preparse times. | 4819 // main thread preparse times. |
4768 if (pre_parse_timer_ != NULL) { | 4820 if (pre_parse_timer_ != NULL) { |
(...skipping 1561 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6330 | 6382 |
6331 statements->Add(get_return, zone); | 6383 statements->Add(get_return, zone); |
6332 statements->Add(check_return, zone); | 6384 statements->Add(check_return, zone); |
6333 statements->Add(call_return, zone); | 6385 statements->Add(call_return, zone); |
6334 statements->Add(validate_output, zone); | 6386 statements->Add(validate_output, zone); |
6335 } | 6387 } |
6336 | 6388 |
6337 | 6389 |
6338 } // namespace internal | 6390 } // namespace internal |
6339 } // namespace v8 | 6391 } // namespace v8 |
OLD | NEW |