Chromium Code Reviews| 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 <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 Loading... | |
| 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 Loading... | |
| 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(); |
|
Dan Ehrenberg
2016/12/09 06:02:21
I take it this is the key fix and the rest is clea
neis
2016/12/09 10:54:52
Yes this is the main fix. But I think it was also
| |
| 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 Loading... | |
| 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 = %CreateGeneratorObject(...); | |
| 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 Loading... | |
| 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(); |
|
adamk
2016/12/09 03:12:31
Why wasn't this needed before?
Dan Ehrenberg
2016/12/09 06:02:21
I believe because the logic was (duplicated) in Pr
neis
2016/12/09 10:54:52
Yes.
| |
| 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 Loading... | |
| 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) { |
|
adamk
2016/12/09 03:12:31
How would this be already-initialized at this poin
Dan Ehrenberg
2016/12/09 06:02:21
Wondering the same
neis
2016/12/09 10:54:52
It is initialized by the PrepareGeneratorVariables
| |
| 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 = %CreateGeneratorObject(); |
| 4194 // BuildRejectPromiseOnException({ | 4183 // BuildRejectPromiseOnException({ |
| 4195 // ... block ... | 4184 // ... block ... |
| (...skipping 1247 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5443 | 5432 |
| 5444 return final_loop; | 5433 return final_loop; |
| 5445 } | 5434 } |
| 5446 | 5435 |
| 5447 #undef CHECK_OK | 5436 #undef CHECK_OK |
| 5448 #undef CHECK_OK_VOID | 5437 #undef CHECK_OK_VOID |
| 5449 #undef CHECK_FAILED | 5438 #undef CHECK_FAILED |
| 5450 | 5439 |
| 5451 } // namespace internal | 5440 } // namespace internal |
| 5452 } // namespace v8 | 5441 } // namespace v8 |
| OLD | NEW |