Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(382)

Side by Side Diff: src/parsing/parser.cc

Issue 1693523002: [es6] More efficient way of marking AST call expressions in tail positions. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Removed MarkTail() from Statement Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/parsing/parser.h ('k') | src/parsing/parser-base.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/parsing/parser.h ('k') | src/parsing/parser-base.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698