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