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

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

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