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(); |
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 = %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 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(); |
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) { |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |