| 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 1730 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |