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 |