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

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

Issue 1895603002: [esnext] prototype runtime implementation for async functions (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@AsyncFunction
Patch Set: fix some nits Created 4 years, 7 months 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 "src/api.h" 7 #include "src/api.h"
8 #include "src/ast/ast.h" 8 #include "src/ast/ast.h"
9 #include "src/ast/ast-expression-rewriter.h" 9 #include "src/ast/ast-expression-rewriter.h"
10 #include "src/ast/ast-expression-visitor.h" 10 #include "src/ast/ast-expression-visitor.h"
(...skipping 2734 matching lines...) Expand 10 before | Expand all | Expand 10 after
2745 if (allow_tailcalls() && !is_sloppy(language_mode())) { 2745 if (allow_tailcalls() && !is_sloppy(language_mode())) {
2746 // ES6 14.6.1 Static Semantics: IsInTailPosition 2746 // ES6 14.6.1 Static Semantics: IsInTailPosition
2747 function_state_->AddImplicitTailCallExpression(return_value); 2747 function_state_->AddImplicitTailCallExpression(return_value);
2748 } 2748 }
2749 } 2749 }
2750 } 2750 }
2751 ExpectSemicolon(CHECK_OK); 2751 ExpectSemicolon(CHECK_OK);
2752 2752
2753 if (is_generator()) { 2753 if (is_generator()) {
2754 return_value = BuildIteratorResult(return_value, true); 2754 return_value = BuildIteratorResult(return_value, true);
2755 } else if (is_async_function()) {
2756 return_value = BuildPromiseResolve(return_value, return_value->position());
2755 } 2757 }
2756 2758
2757 result = factory()->NewReturnStatement(return_value, loc.beg_pos); 2759 result = factory()->NewReturnStatement(return_value, loc.beg_pos);
2758 2760
2759 Scope* decl_scope = scope_->DeclarationScope(); 2761 Scope* decl_scope = scope_->DeclarationScope();
2760 if (decl_scope->is_script_scope() || decl_scope->is_eval_scope()) { 2762 if (decl_scope->is_script_scope() || decl_scope->is_eval_scope()) {
2761 ReportMessageAt(loc, MessageTemplate::kIllegalReturn); 2763 ReportMessageAt(loc, MessageTemplate::kIllegalReturn);
2762 *ok = false; 2764 *ok = false;
2763 return NULL; 2765 return NULL;
2764 } 2766 }
(...skipping 1220 matching lines...) Expand 10 before | Expand all | Expand 10 after
3985 expr = assignment->target(); 3987 expr = assignment->target();
3986 3988
3987 // TODO(adamk): Only call this if necessary. 3989 // TODO(adamk): Only call this if necessary.
3988 RewriteParameterInitializerScope(parser_->stack_limit(), initializer, 3990 RewriteParameterInitializerScope(parser_->stack_limit(), initializer,
3989 parser_->scope_, parameters->scope); 3991 parser_->scope_, parameters->scope);
3990 } 3992 }
3991 3993
3992 AddFormalParameter(parameters, expr, initializer, end_pos, is_rest); 3994 AddFormalParameter(parameters, expr, initializer, end_pos, is_rest);
3993 } 3995 }
3994 3996
3997 void ParserTraits::ParseAsyncArrowSingleExpressionBody(
3998 ZoneList<Statement*>* body, bool accept_IN,
3999 Type::ExpressionClassifier* classifier, int pos, bool* ok) {
4000 parser_->DesugarAsyncFunctionBody(
4001 parser_->ast_value_factory()->empty_string(), parser_->scope_, body,
4002 classifier, kAsyncArrowFunction, FunctionBody::SingleExpression,
4003 accept_IN, pos, ok);
4004 }
4005
4006 void Parser::DesugarAsyncFunctionBody(const AstRawString* function_name,
4007 Scope* scope, ZoneList<Statement*>* body,
4008 ExpressionClassifier* classifier,
4009 FunctionKind kind, FunctionBody body_type,
4010 bool accept_IN, int pos, bool* ok) {
4011 // function async_function() {
4012 // try {
4013 // .generator_object = %CreateGeneratorObject();
4014 // ... function body ...
4015 // } catch (e) {
4016 // return Promise.reject(e);
4017 // }
4018 // }
4019 scope->ForceContextAllocation();
4020 Variable* temp =
4021 scope_->NewTemporary(ast_value_factory()->dot_generator_object_string());
4022 function_state_->set_generator_object_variable(temp);
4023
4024 Expression* init_generator_variable = factory()->NewAssignment(
4025 Token::INIT, factory()->NewVariableProxy(temp),
4026 BuildCreateJSGeneratorObject(pos), RelocInfo::kNoPosition);
4027 body->Add(factory()->NewExpressionStatement(init_generator_variable,
4028 RelocInfo::kNoPosition),
4029 zone());
4030
4031 Block* try_block = factory()->NewBlock(NULL, 8, true, RelocInfo::kNoPosition);
4032
4033 ZoneList<Statement*>* inner_body = try_block->statements();
4034
4035 Expression* return_value = nullptr;
4036 if (body_type == FunctionBody::Normal) {
4037 ParseStatementList(inner_body, Token::RBRACE, ok);
4038 if (!*ok) return;
4039 return_value = factory()->NewUndefinedLiteral(RelocInfo::kNoPosition);
4040 } else {
4041 return_value = ParseAssignmentExpression(accept_IN, classifier, ok);
4042 if (!*ok) return;
4043 ParserTraits::RewriteNonPattern(classifier, ok);
4044 if (!*ok) return;
4045 }
4046
4047 return_value = BuildPromiseResolve(return_value, return_value->position());
4048 inner_body->Add(
4049 factory()->NewReturnStatement(return_value, return_value->position()),
4050 zone());
4051 body->Add(BuildRejectPromiseOnException(try_block), zone());
4052 scope->set_end_position(scanner()->location().end_pos);
4053 }
3995 4054
3996 DoExpression* Parser::ParseDoExpression(bool* ok) { 4055 DoExpression* Parser::ParseDoExpression(bool* ok) {
3997 // AssignmentExpression :: 4056 // AssignmentExpression ::
3998 // do '{' StatementList '}' 4057 // do '{' StatementList '}'
3999 int pos = peek_position(); 4058 int pos = peek_position();
4000 4059
4001 Expect(Token::DO, CHECK_OK); 4060 Expect(Token::DO, CHECK_OK);
4002 Variable* result = 4061 Variable* result =
4003 scope_->NewTemporary(ast_value_factory()->dot_result_string()); 4062 scope_->NewTemporary(ast_value_factory()->dot_result_string());
4004 Block* block = ParseBlock(nullptr, false, CHECK_OK); 4063 Block* block = ParseBlock(nullptr, false, CHECK_OK);
(...skipping 526 matching lines...) Expand 10 before | Expand all | Expand 10 after
4531 param_scope = param_scope->FinalizeBlockScope(); 4590 param_scope = param_scope->FinalizeBlockScope();
4532 if (param_scope != nullptr) { 4591 if (param_scope != nullptr) {
4533 CheckConflictingVarDeclarations(param_scope, CHECK_OK); 4592 CheckConflictingVarDeclarations(param_scope, CHECK_OK);
4534 } 4593 }
4535 init_block->statements()->Add(param_block, zone()); 4594 init_block->statements()->Add(param_block, zone());
4536 } 4595 }
4537 } 4596 }
4538 return init_block; 4597 return init_block;
4539 } 4598 }
4540 4599
4600 Block* Parser::BuildRejectPromiseOnException(Block* block) {
4601 // try { <block> } catch (error) { return Promise.reject(error); }
4602 Block* try_block = block;
4603 Scope* catch_scope = NewScope(scope_, CATCH_SCOPE);
4604 catch_scope->set_is_hidden();
4605 Variable* catch_variable =
4606 catch_scope->DeclareLocal(ast_value_factory()->dot_catch_string(), VAR,
4607 kCreatedInitialized, Variable::NORMAL);
4608 Block* catch_block =
4609 factory()->NewBlock(nullptr, 1, true, RelocInfo::kNoPosition);
4610
4611 Expression* promise_reject = BuildPromiseReject(
4612 factory()->NewVariableProxy(catch_variable), RelocInfo::kNoPosition);
4613
4614 ReturnStatement* return_promise_reject =
4615 factory()->NewReturnStatement(promise_reject, RelocInfo::kNoPosition);
4616 catch_block->statements()->Add(return_promise_reject, zone());
4617 TryStatement* try_catch_statement =
4618 factory()->NewTryCatchStatement(try_block, catch_scope, catch_variable,
4619 catch_block, RelocInfo::kNoPosition);
4620
4621 block = factory()->NewBlock(nullptr, 1, true, RelocInfo::kNoPosition);
4622 block->statements()->Add(try_catch_statement, zone());
4623 return block;
4624 }
4625
4626 Expression* Parser::BuildCreateJSGeneratorObject(int pos) {
4627 DCHECK_NOT_NULL(function_state_->generator_object_variable());
4628 ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(2, zone());
4629 args->Add(factory()->NewThisFunction(pos), zone());
4630 args->Add(ThisExpression(scope_, factory(), RelocInfo::kNoPosition), zone());
4631 return factory()->NewCallRuntime(Runtime::kCreateJSGeneratorObject, args,
4632 pos);
4633 }
4634
4635 Expression* Parser::BuildPromiseResolve(Expression* value, int pos) {
4636 ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(1, zone());
4637 args->Add(value, zone());
4638 return factory()->NewCallRuntime(Context::PROMISE_CREATE_RESOLVED_INDEX, args,
4639 pos);
4640 }
4641
4642 Expression* Parser::BuildPromiseReject(Expression* value, int pos) {
4643 ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(1, zone());
4644 args->Add(value, zone());
4645 return factory()->NewCallRuntime(Context::PROMISE_CREATE_REJECTED_INDEX, args,
4646 pos);
4647 }
4541 4648
4542 ZoneList<Statement*>* Parser::ParseEagerFunctionBody( 4649 ZoneList<Statement*>* Parser::ParseEagerFunctionBody(
4543 const AstRawString* function_name, int pos, 4650 const AstRawString* function_name, int pos,
4544 const ParserFormalParameters& parameters, FunctionKind kind, 4651 const ParserFormalParameters& parameters, FunctionKind kind,
4545 FunctionLiteral::FunctionType function_type, bool* ok) { 4652 FunctionLiteral::FunctionType function_type, bool* ok) {
4546 // Everything inside an eagerly parsed function will be parsed eagerly 4653 // Everything inside an eagerly parsed function will be parsed eagerly
4547 // (see comment above). 4654 // (see comment above).
4548 ParsingModeScope parsing_mode(this, PARSE_EAGERLY); 4655 ParsingModeScope parsing_mode(this, PARSE_EAGERLY);
4549 ZoneList<Statement*>* result = new(zone()) ZoneList<Statement*>(8, zone()); 4656 ZoneList<Statement*>* result = new(zone()) ZoneList<Statement*>(8, zone());
4550 4657
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
4584 // - InitialYield yields the actual generator object. 4691 // - InitialYield yields the actual generator object.
4585 // - Any return statement inside the body will have its argument wrapped 4692 // - Any return statement inside the body will have its argument wrapped
4586 // in a "done" iterator result object. 4693 // in a "done" iterator result object.
4587 // - If the generator terminates for whatever reason, we must close it. 4694 // - If the generator terminates for whatever reason, we must close it.
4588 // Hence the finally clause. 4695 // Hence the finally clause.
4589 4696
4590 Block* try_block = 4697 Block* try_block =
4591 factory()->NewBlock(nullptr, 3, false, RelocInfo::kNoPosition); 4698 factory()->NewBlock(nullptr, 3, false, RelocInfo::kNoPosition);
4592 4699
4593 { 4700 {
4594 ZoneList<Expression*>* arguments = 4701 Expression* allocation = BuildCreateJSGeneratorObject(pos);
4595 new (zone()) ZoneList<Expression*>(2, zone());
4596 arguments->Add(factory()->NewThisFunction(pos), zone());
4597 arguments->Add(
4598 ThisExpression(scope_, factory(), RelocInfo::kNoPosition), zone());
4599 CallRuntime* allocation = factory()->NewCallRuntime(
4600 Runtime::kCreateJSGeneratorObject, arguments, pos);
4601
4602 VariableProxy* init_proxy = factory()->NewVariableProxy( 4702 VariableProxy* init_proxy = factory()->NewVariableProxy(
4603 function_state_->generator_object_variable()); 4703 function_state_->generator_object_variable());
4604 Assignment* assignment = factory()->NewAssignment( 4704 Assignment* assignment = factory()->NewAssignment(
4605 Token::INIT, init_proxy, allocation, RelocInfo::kNoPosition); 4705 Token::INIT, init_proxy, allocation, RelocInfo::kNoPosition);
4606 VariableProxy* get_proxy = factory()->NewVariableProxy( 4706 VariableProxy* get_proxy = factory()->NewVariableProxy(
4607 function_state_->generator_object_variable()); 4707 function_state_->generator_object_variable());
4608 Yield* yield = 4708 Yield* yield =
4609 factory()->NewYield(get_proxy, assignment, RelocInfo::kNoPosition); 4709 factory()->NewYield(get_proxy, assignment, RelocInfo::kNoPosition);
4610 try_block->statements()->Add( 4710 try_block->statements()->Add(
4611 factory()->NewExpressionStatement(yield, RelocInfo::kNoPosition), 4711 factory()->NewExpressionStatement(yield, RelocInfo::kNoPosition),
(...skipping 15 matching lines...) Expand all
4627 args->Add(call_proxy, zone()); 4727 args->Add(call_proxy, zone());
4628 Expression* call = factory()->NewCallRuntime( 4728 Expression* call = factory()->NewCallRuntime(
4629 Runtime::kGeneratorClose, args, RelocInfo::kNoPosition); 4729 Runtime::kGeneratorClose, args, RelocInfo::kNoPosition);
4630 finally_block->statements()->Add( 4730 finally_block->statements()->Add(
4631 factory()->NewExpressionStatement(call, RelocInfo::kNoPosition), 4731 factory()->NewExpressionStatement(call, RelocInfo::kNoPosition),
4632 zone()); 4732 zone());
4633 4733
4634 body->Add(factory()->NewTryFinallyStatement(try_block, finally_block, 4734 body->Add(factory()->NewTryFinallyStatement(try_block, finally_block,
4635 RelocInfo::kNoPosition), 4735 RelocInfo::kNoPosition),
4636 zone()); 4736 zone());
4737 } else if (IsAsyncFunction(kind)) {
4738 const bool accept_IN = true;
4739 DesugarAsyncFunctionBody(function_name, inner_scope, body, nullptr, kind,
4740 FunctionBody::Normal, accept_IN, pos, CHECK_OK);
4637 } else { 4741 } else {
4638 ParseStatementList(body, Token::RBRACE, CHECK_OK); 4742 ParseStatementList(body, Token::RBRACE, CHECK_OK);
4639 } 4743 }
4640 4744
4641 if (IsSubclassConstructor(kind)) { 4745 if (IsSubclassConstructor(kind)) {
4642 body->Add( 4746 body->Add(
4643 factory()->NewReturnStatement( 4747 factory()->NewReturnStatement(
4644 this->ThisExpression(scope_, factory(), RelocInfo::kNoPosition), 4748 this->ThisExpression(scope_, factory(), RelocInfo::kNoPosition),
4645 RelocInfo::kNoPosition), 4749 RelocInfo::kNoPosition),
4646 zone()); 4750 zone());
4647 } 4751 }
4648 } 4752 }
4649 4753
4650 Expect(Token::RBRACE, CHECK_OK); 4754 Expect(Token::RBRACE, CHECK_OK);
4651 scope_->set_end_position(scanner()->location().end_pos); 4755 scope_->set_end_position(scanner()->location().end_pos);
4652 4756
4653 if (!parameters.is_simple) { 4757 if (!parameters.is_simple) {
4654 DCHECK_NOT_NULL(inner_scope); 4758 DCHECK_NOT_NULL(inner_scope);
4655 DCHECK_EQ(body, inner_block->statements()); 4759 DCHECK_EQ(body, inner_block->statements());
4656 SetLanguageMode(scope_, inner_scope->language_mode()); 4760 SetLanguageMode(scope_, inner_scope->language_mode());
4657 Block* init_block = BuildParameterInitializationBlock(parameters, CHECK_OK); 4761 Block* init_block = BuildParameterInitializationBlock(parameters, CHECK_OK);
4762
4763 if (IsAsyncFunction(kind)) {
4764 init_block = BuildRejectPromiseOnException(init_block);
4765 }
4766
4658 DCHECK_NOT_NULL(init_block); 4767 DCHECK_NOT_NULL(init_block);
4659 4768
4660 inner_scope->set_end_position(scanner()->location().end_pos); 4769 inner_scope->set_end_position(scanner()->location().end_pos);
4661 inner_scope = inner_scope->FinalizeBlockScope(); 4770 inner_scope = inner_scope->FinalizeBlockScope();
4662 if (inner_scope != nullptr) { 4771 if (inner_scope != nullptr) {
4663 CheckConflictingVarDeclarations(inner_scope, CHECK_OK); 4772 CheckConflictingVarDeclarations(inner_scope, CHECK_OK);
4664 InsertShadowingVarBindingInitializers(inner_block); 4773 InsertShadowingVarBindingInitializers(inner_block);
4665 } 4774 }
4666 4775
4667 result->Add(init_block, zone()); 4776 result->Add(init_block, zone());
(...skipping 784 matching lines...) Expand 10 before | Expand all | Expand 10 after
5452 int pos) { 5561 int pos) {
5453 return parser_->RewriteAssignExponentiation(left, right, pos); 5562 return parser_->RewriteAssignExponentiation(left, right, pos);
5454 } 5563 }
5455 5564
5456 void ParserTraits::RewriteNonPattern(Type::ExpressionClassifier* classifier, 5565 void ParserTraits::RewriteNonPattern(Type::ExpressionClassifier* classifier,
5457 bool* ok) { 5566 bool* ok) {
5458 parser_->RewriteNonPattern(classifier, ok); 5567 parser_->RewriteNonPattern(classifier, ok);
5459 } 5568 }
5460 5569
5461 Expression* ParserTraits::RewriteAwaitExpression(Expression* value, int pos) { 5570 Expression* ParserTraits::RewriteAwaitExpression(Expression* value, int pos) {
5462 // TODO(caitp): Implement AsyncFunctionAwait() 5571 // yield %AsyncFunctionAwait(.generator_object, <operand>)
5463 // per tc39.github.io/ecmascript-asyncawait/#abstract-ops-async-function-await 5572 Variable* generator_object_variable =
5464 return value; 5573 parser_->function_state_->generator_object_variable();
5574
5575 // If generator_object_variable is null,
5576 if (!generator_object_variable) return value;
5577
5578 Expression* generator_object =
5579 parser_->factory()->NewVariableProxy(generator_object_variable);
5580
5581 ZoneList<Expression*>* async_function_await_args =
5582 new (zone()) ZoneList<Expression*>(2, zone());
5583 async_function_await_args->Add(generator_object, zone());
5584 async_function_await_args->Add(value, zone());
5585 Expression* async_function_await = parser_->factory()->NewCallRuntime(
5586 Context::ASYNC_FUNCTION_AWAIT_INDEX, async_function_await_args,
5587 RelocInfo::kNoPosition);
5588
5589 generator_object =
5590 parser_->factory()->NewVariableProxy(generator_object_variable);
5591 return parser_->factory()->NewYield(generator_object, async_function_await,
5592 pos);
5465 } 5593 }
5466 5594
5467 Zone* ParserTraits::zone() const { 5595 Zone* ParserTraits::zone() const {
5468 return parser_->function_state_->scope()->zone(); 5596 return parser_->function_state_->scope()->zone();
5469 } 5597 }
5470 5598
5471 5599
5472 ZoneList<Expression*>* ParserTraits::GetNonPatternList() const { 5600 ZoneList<Expression*>* ParserTraits::GetNonPatternList() const {
5473 return parser_->function_state_->non_patterns_to_rewrite(); 5601 return parser_->function_state_->non_patterns_to_rewrite();
5474 } 5602 }
(...skipping 1473 matching lines...) Expand 10 before | Expand all | Expand 10 after
6948 try_block, target); 7076 try_block, target);
6949 final_loop = target; 7077 final_loop = target;
6950 } 7078 }
6951 7079
6952 return final_loop; 7080 return final_loop;
6953 } 7081 }
6954 7082
6955 7083
6956 } // namespace internal 7084 } // namespace internal
6957 } // namespace v8 7085 } // 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