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

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

Issue 2561093002: [parsing] Fix context allocation for async functions. (Closed)
Patch Set: Turn conditional into DCHECK. Created 4 years 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 <memory> 7 #include <memory>
8 8
9 #include "src/api.h" 9 #include "src/api.h"
10 #include "src/ast/ast-expression-rewriter.h" 10 #include "src/ast/ast-expression-rewriter.h"
(...skipping 736 matching lines...) Expand 10 before | Expand all | Expand 10 after
747 // Declare the special module parameter. 747 // Declare the special module parameter.
748 auto name = ast_value_factory()->empty_string(); 748 auto name = ast_value_factory()->empty_string();
749 bool is_duplicate; 749 bool is_duplicate;
750 bool is_rest = false; 750 bool is_rest = false;
751 bool is_optional = false; 751 bool is_optional = false;
752 auto var = scope->DeclareParameter(name, VAR, is_optional, is_rest, 752 auto var = scope->DeclareParameter(name, VAR, is_optional, is_rest,
753 &is_duplicate, ast_value_factory()); 753 &is_duplicate, ast_value_factory());
754 DCHECK(!is_duplicate); 754 DCHECK(!is_duplicate);
755 var->AllocateTo(VariableLocation::PARAMETER, 0); 755 var->AllocateTo(VariableLocation::PARAMETER, 0);
756 756
757 PrepareGeneratorVariables(&function_state); 757 PrepareGeneratorVariables();
758 Expression* initial_yield = 758 Expression* initial_yield =
759 BuildInitialYield(kNoSourcePosition, kGeneratorFunction); 759 BuildInitialYield(kNoSourcePosition, kGeneratorFunction);
760 body->Add( 760 body->Add(
761 factory()->NewExpressionStatement(initial_yield, kNoSourcePosition), 761 factory()->NewExpressionStatement(initial_yield, kNoSourcePosition),
762 zone()); 762 zone());
763 763
764 ParseModuleItemList(body, &ok); 764 ParseModuleItemList(body, &ok);
765 ok = ok && 765 ok = ok &&
766 module()->Validate(this->scope()->AsModuleScope(), 766 module()->Validate(this->scope()->AsModuleScope(),
767 &pending_error_handler_, zone()); 767 &pending_error_handler_, zone());
(...skipping 1728 matching lines...) Expand 10 before | Expand all | Expand 10 after
2496 2496
2497 for (auto p : parameters.params) { 2497 for (auto p : parameters.params) {
2498 if (p->pattern != nullptr) reindexer.Reindex(p->pattern); 2498 if (p->pattern != nullptr) reindexer.Reindex(p->pattern);
2499 if (p->initializer != nullptr) reindexer.Reindex(p->initializer); 2499 if (p->initializer != nullptr) reindexer.Reindex(p->initializer);
2500 } 2500 }
2501 2501
2502 DCHECK(reindexer.count() <= function_state_->materialized_literal_count()); 2502 DCHECK(reindexer.count() <= function_state_->materialized_literal_count());
2503 } 2503 }
2504 } 2504 }
2505 2505
2506 void Parser::PrepareGeneratorVariables(FunctionState* function_state) { 2506 void Parser::PrepareGeneratorVariables() {
2507 // For generators, allocating variables in contexts is currently a win because 2507 // For generators, allocating variables in contexts is currently a win because
2508 // it minimizes the work needed to suspend and resume an activation. The 2508 // it minimizes the work needed to suspend and resume an activation. The
2509 // code produced for generators relies on this forced context allocation, but 2509 // code produced for generators relies on this forced context allocation (it
2510 // not in an essential way. 2510 // does not restore the frame's parameters upon resume).
2511 scope()->ForceContextAllocation(); 2511 function_state_->scope()->ForceContextAllocation();
2512 2512
2513 // Calling a generator returns a generator object. That object is stored 2513 // Calling a generator returns a generator object. That object is stored
2514 // in a temporary variable, a definition that is used by "yield" 2514 // in a temporary variable, a definition that is used by "yield"
2515 // expressions. 2515 // expressions.
2516 Variable* temp = 2516 Variable* temp =
2517 NewTemporary(ast_value_factory()->dot_generator_object_string()); 2517 NewTemporary(ast_value_factory()->dot_generator_object_string());
2518 function_state->set_generator_object_variable(temp); 2518 function_state_->set_generator_object_variable(temp);
2519 } 2519 }
2520 2520
2521 FunctionLiteral* Parser::ParseFunctionLiteral( 2521 FunctionLiteral* Parser::ParseFunctionLiteral(
2522 const AstRawString* function_name, Scanner::Location function_name_location, 2522 const AstRawString* function_name, Scanner::Location function_name_location,
2523 FunctionNameValidity function_name_validity, FunctionKind kind, 2523 FunctionNameValidity function_name_validity, FunctionKind kind,
2524 int function_token_pos, FunctionLiteral::FunctionType function_type, 2524 int function_token_pos, FunctionLiteral::FunctionType function_type,
2525 LanguageMode language_mode, bool* ok) { 2525 LanguageMode language_mode, bool* ok) {
2526 // Function :: 2526 // Function ::
2527 // '(' FormalParameterList? ')' '{' FunctionBody '}' 2527 // '(' FormalParameterList? ')' '{' FunctionBody '}'
2528 // 2528 //
(...skipping 537 matching lines...) Expand 10 before | Expand all | Expand 10 after
3066 finally_block->statements()->Add(promise_release, zone()); 3066 finally_block->statements()->Add(promise_release, zone());
3067 } 3067 }
3068 3068
3069 Statement* try_finally_statement = factory()->NewTryFinallyStatement( 3069 Statement* try_finally_statement = factory()->NewTryFinallyStatement(
3070 outer_try_block, finally_block, kNoSourcePosition); 3070 outer_try_block, finally_block, kNoSourcePosition);
3071 3071
3072 result->statements()->Add(try_finally_statement, zone()); 3072 result->statements()->Add(try_finally_statement, zone());
3073 return result; 3073 return result;
3074 } 3074 }
3075 3075
3076 Expression* Parser::BuildCreateJSGeneratorObject(int pos, FunctionKind kind) { 3076 Assignment* Parser::BuildCreateJSGeneratorObject(int pos, FunctionKind kind) {
3077 // .generator = %CreateJSGeneratorObject(...);
3077 DCHECK_NOT_NULL(function_state_->generator_object_variable()); 3078 DCHECK_NOT_NULL(function_state_->generator_object_variable());
3078 ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(2, zone()); 3079 ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(2, zone());
3079 args->Add(factory()->NewThisFunction(pos), zone()); 3080 args->Add(factory()->NewThisFunction(pos), zone());
3080 args->Add(IsArrowFunction(kind) ? GetLiteralUndefined(pos) 3081 args->Add(IsArrowFunction(kind) ? GetLiteralUndefined(pos)
3081 : ThisExpression(kNoSourcePosition), 3082 : ThisExpression(kNoSourcePosition),
3082 zone()); 3083 zone());
3083 return factory()->NewCallRuntime(Runtime::kCreateJSGeneratorObject, args, 3084 Expression* allocation =
3084 pos); 3085 factory()->NewCallRuntime(Runtime::kCreateJSGeneratorObject, args, pos);
3086 VariableProxy* proxy =
3087 factory()->NewVariableProxy(function_state_->generator_object_variable());
3088 return factory()->NewAssignment(Token::INIT, proxy, allocation,
3089 kNoSourcePosition);
3085 } 3090 }
3086 3091
3087 Expression* Parser::BuildResolvePromise(Expression* value, int pos) { 3092 Expression* Parser::BuildResolvePromise(Expression* value, int pos) {
3088 // %ResolvePromise(.promise, value), .promise 3093 // %ResolvePromise(.promise, value), .promise
3089 ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(2, zone()); 3094 ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(2, zone());
3090 args->Add(factory()->NewVariableProxy(PromiseVariable()), zone()); 3095 args->Add(factory()->NewVariableProxy(PromiseVariable()), zone());
3091 args->Add(value, zone()); 3096 args->Add(value, zone());
3092 Expression* call_runtime = 3097 Expression* call_runtime =
3093 factory()->NewCallRuntime(Context::PROMISE_RESOLVE_INDEX, args, pos); 3098 factory()->NewCallRuntime(Context::PROMISE_RESOLVE_INDEX, args, pos);
3094 return factory()->NewBinaryOperation( 3099 return factory()->NewBinaryOperation(
(...skipping 22 matching lines...) Expand all
3117 // comes first should create it and stash it in the FunctionState. 3122 // comes first should create it and stash it in the FunctionState.
3118 Variable* promise = function_state_->promise_variable(); 3123 Variable* promise = function_state_->promise_variable();
3119 if (function_state_->promise_variable() == nullptr) { 3124 if (function_state_->promise_variable() == nullptr) {
3120 promise = scope()->NewTemporary(ast_value_factory()->empty_string()); 3125 promise = scope()->NewTemporary(ast_value_factory()->empty_string());
3121 function_state_->set_promise_variable(promise); 3126 function_state_->set_promise_variable(promise);
3122 } 3127 }
3123 return promise; 3128 return promise;
3124 } 3129 }
3125 3130
3126 Expression* Parser::BuildInitialYield(int pos, FunctionKind kind) { 3131 Expression* Parser::BuildInitialYield(int pos, FunctionKind kind) {
3127 Expression* allocation = BuildCreateJSGeneratorObject(pos, kind); 3132 Assignment* assignment = BuildCreateJSGeneratorObject(pos, kind);
3128 VariableProxy* init_proxy = 3133 VariableProxy* generator =
3129 factory()->NewVariableProxy(function_state_->generator_object_variable());
3130 Assignment* assignment = factory()->NewAssignment(
3131 Token::INIT, init_proxy, allocation, kNoSourcePosition);
3132 VariableProxy* get_proxy =
3133 factory()->NewVariableProxy(function_state_->generator_object_variable()); 3134 factory()->NewVariableProxy(function_state_->generator_object_variable());
3134 // The position of the yield is important for reporting the exception 3135 // The position of the yield is important for reporting the exception
3135 // caused by calling the .throw method on a generator suspended at the 3136 // caused by calling the .throw method on a generator suspended at the
3136 // initial yield (i.e. right after generator instantiation). 3137 // initial yield (i.e. right after generator instantiation).
3137 return factory()->NewYield(get_proxy, assignment, scope()->start_position(), 3138 return factory()->NewYield(generator, assignment, scope()->start_position(),
3138 Yield::kOnExceptionThrow); 3139 Yield::kOnExceptionThrow);
3139 } 3140 }
3140 3141
3141 ZoneList<Statement*>* Parser::ParseFunction( 3142 ZoneList<Statement*>* Parser::ParseFunction(
3142 const AstRawString* function_name, int pos, FunctionKind kind, 3143 const AstRawString* function_name, int pos, FunctionKind kind,
3143 FunctionLiteral::FunctionType function_type, 3144 FunctionLiteral::FunctionType function_type,
3144 DeclarationScope* function_scope, int* num_parameters, int* function_length, 3145 DeclarationScope* function_scope, int* num_parameters, int* function_length,
3145 bool* has_duplicate_parameters, int* materialized_literal_count, 3146 bool* has_duplicate_parameters, int* materialized_literal_count,
3146 int* expected_property_count, bool* ok) { 3147 int* expected_property_count, bool* ok) {
3147 ParsingModeScope mode(this, allow_lazy_ ? PARSE_LAZILY : PARSE_EAGERLY); 3148 ParsingModeScope mode(this, allow_lazy_ ? PARSE_LAZILY : PARSE_EAGERLY);
3148 3149
3149 FunctionState function_state(&function_state_, &scope_state_, function_scope); 3150 FunctionState function_state(&function_state_, &scope_state_, function_scope);
3150 3151
3151 DuplicateFinder duplicate_finder; 3152 DuplicateFinder duplicate_finder;
3152 ExpressionClassifier formals_classifier(this, &duplicate_finder); 3153 ExpressionClassifier formals_classifier(this, &duplicate_finder);
3153 3154
3154 if (IsGeneratorFunction(kind)) PrepareGeneratorVariables(&function_state); 3155 if (IsResumableFunction(kind)) PrepareGeneratorVariables();
3155 3156
3156 ParserFormalParameters formals(function_scope); 3157 ParserFormalParameters formals(function_scope);
3157 ParseFormalParameterList(&formals, CHECK_OK); 3158 ParseFormalParameterList(&formals, CHECK_OK);
3158 Expect(Token::RPAREN, CHECK_OK); 3159 Expect(Token::RPAREN, CHECK_OK);
3159 int formals_end_position = scanner()->location().end_pos; 3160 int formals_end_position = scanner()->location().end_pos;
3160 *num_parameters = formals.num_parameters(); 3161 *num_parameters = formals.num_parameters();
3161 *function_length = formals.function_length; 3162 *function_length = formals.function_length;
3162 3163
3163 CheckArityRestrictions(formals.arity, kind, formals.has_rest, 3164 CheckArityRestrictions(formals.arity, kind, formals.has_rest,
3164 function_scope->start_position(), formals_end_position, 3165 function_scope->start_position(), formals_end_position,
(...skipping 994 matching lines...) Expand 10 before | Expand all | Expand 10 after
4159 expr = factory()->NewBinaryOperation(Token::COMMA, expr, args->at(i), 4160 expr = factory()->NewBinaryOperation(Token::COMMA, expr, args->at(i),
4160 expr->position()); 4161 expr->position());
4161 } 4162 }
4162 return expr; 4163 return expr;
4163 } 4164 }
4164 4165
4165 // This method intoduces the line initializing the generator object 4166 // This method intoduces the line initializing the generator object
4166 // when desugaring the body of async_function. 4167 // when desugaring the body of async_function.
4167 void Parser::PrepareAsyncFunctionBody(ZoneList<Statement*>* body, 4168 void Parser::PrepareAsyncFunctionBody(ZoneList<Statement*>* body,
4168 FunctionKind kind, int pos) { 4169 FunctionKind kind, int pos) {
4169 // function async_function() { 4170 if (function_state_->generator_object_variable() == nullptr) {
Dan Ehrenberg 2016/12/09 21:51:46 Could you put a comment here explaining why this i
4170 // .generator_object = %CreateGeneratorObject(); 4171 PrepareGeneratorVariables();
4171 // BuildRejectPromiseOnException({ 4172 }
4172 // ... block ... 4173 body->Add(factory()->NewExpressionStatement(
4173 // return %ResolvePromise(.promise, expr), .promise; 4174 BuildCreateJSGeneratorObject(pos, kind), kNoSourcePosition),
4174 // })
4175 // }
4176
4177 Variable* temp =
4178 NewTemporary(ast_value_factory()->dot_generator_object_string());
4179 function_state_->set_generator_object_variable(temp);
4180
4181 Expression* init_generator_variable = factory()->NewAssignment(
4182 Token::INIT, factory()->NewVariableProxy(temp),
4183 BuildCreateJSGeneratorObject(pos, kind), kNoSourcePosition);
4184 body->Add(factory()->NewExpressionStatement(init_generator_variable,
4185 kNoSourcePosition),
4186 zone()); 4175 zone());
4187 } 4176 }
4188 4177
4189 // This method completes the desugaring of the body of async_function. 4178 // This method completes the desugaring of the body of async_function.
4190 void Parser::RewriteAsyncFunctionBody(ZoneList<Statement*>* body, Block* block, 4179 void Parser::RewriteAsyncFunctionBody(ZoneList<Statement*>* body, Block* block,
4191 Expression* return_value, bool* ok) { 4180 Expression* return_value, bool* ok) {
4192 // function async_function() { 4181 // function async_function() {
4193 // .generator_object = %CreateGeneratorObject(); 4182 // .generator_object = %CreateJSGeneratorObject();
4194 // BuildRejectPromiseOnException({ 4183 // BuildRejectPromiseOnException({
4195 // ... block ... 4184 // ... block ...
4196 // return %ResolvePromise(.promise, expr), .promise; 4185 // return %ResolvePromise(.promise, expr), .promise;
4197 // }) 4186 // })
4198 // } 4187 // }
4199 4188
4200 return_value = BuildResolvePromise(return_value, return_value->position()); 4189 return_value = BuildResolvePromise(return_value, return_value->position());
4201 block->statements()->Add( 4190 block->statements()->Add(
4202 factory()->NewReturnStatement(return_value, return_value->position()), 4191 factory()->NewReturnStatement(return_value, return_value->position()),
4203 zone()); 4192 zone());
(...skipping 16 matching lines...) Expand all
4220 // This handler has nothing useful to do with the value, as the Promise is 4209 // This handler has nothing useful to do with the value, as the Promise is
4221 // ignored. If we yielded the value of the throwawayPromise that 4210 // ignored. If we yielded the value of the throwawayPromise that
4222 // AsyncFunctionAwait creates as an intermediate, it would create a memory 4211 // AsyncFunctionAwait creates as an intermediate, it would create a memory
4223 // leak; we must return .promise instead; 4212 // leak; we must return .promise instead;
4224 // The operand needs to be evaluated on a separate statement in order to get 4213 // The operand needs to be evaluated on a separate statement in order to get
4225 // a break location, and the .promise needs to be read earlier so that it 4214 // a break location, and the .promise needs to be read earlier so that it
4226 // doesn't insert a false location. 4215 // doesn't insert a false location.
4227 // TODO(littledan): investigate why this ordering is needed in more detail. 4216 // TODO(littledan): investigate why this ordering is needed in more detail.
4228 Variable* generator_object_variable = 4217 Variable* generator_object_variable =
4229 function_state_->generator_object_variable(); 4218 function_state_->generator_object_variable();
4230 4219 DCHECK_NOT_NULL(generator_object_variable);
4231 // If generator_object_variable is null,
4232 // TODO(littledan): Is this necessary?
4233 if (!generator_object_variable) return value;
4234 4220
4235 const int nopos = kNoSourcePosition; 4221 const int nopos = kNoSourcePosition;
4236 4222
4237 Block* do_block = factory()->NewBlock(nullptr, 2, false, nopos); 4223 Block* do_block = factory()->NewBlock(nullptr, 2, false, nopos);
4238 4224
4239 Variable* promise = PromiseVariable(); 4225 Variable* promise = PromiseVariable();
4240 4226
4241 // Wrap value evaluation to provide a break location. 4227 // Wrap value evaluation to provide a break location.
4242 Variable* temp_var = NewTemporary(ast_value_factory()->empty_string()); 4228 Variable* temp_var = NewTemporary(ast_value_factory()->empty_string());
4243 Expression* value_assignment = factory()->NewAssignment( 4229 Expression* value_assignment = factory()->NewAssignment(
(...skipping 1199 matching lines...) Expand 10 before | Expand all | Expand 10 after
5443 5429
5444 return final_loop; 5430 return final_loop;
5445 } 5431 }
5446 5432
5447 #undef CHECK_OK 5433 #undef CHECK_OK
5448 #undef CHECK_OK_VOID 5434 #undef CHECK_OK_VOID
5449 #undef CHECK_FAILED 5435 #undef CHECK_FAILED
5450 5436
5451 } // namespace internal 5437 } // namespace internal
5452 } // namespace v8 5438 } // 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