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

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

Issue 2233923003: Desugar async/await to create the resulting Promise upfront (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Changes from review Created 4 years, 4 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') | no next file » | 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 <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 2498 matching lines...) Expand 10 before | Expand all | Expand 10 after
2509 // ES6 14.6.1 Static Semantics: IsInTailPosition 2509 // ES6 14.6.1 Static Semantics: IsInTailPosition
2510 function_state_->AddImplicitTailCallExpression(return_value); 2510 function_state_->AddImplicitTailCallExpression(return_value);
2511 } 2511 }
2512 } 2512 }
2513 } 2513 }
2514 ExpectSemicolon(CHECK_OK); 2514 ExpectSemicolon(CHECK_OK);
2515 2515
2516 if (is_generator()) { 2516 if (is_generator()) {
2517 return_value = BuildIteratorResult(return_value, true); 2517 return_value = BuildIteratorResult(return_value, true);
2518 } else if (is_async_function()) { 2518 } else if (is_async_function()) {
2519 return_value = BuildPromiseResolve(return_value, return_value->position()); 2519 return_value = BuildResolvePromise(return_value, return_value->position());
2520 } 2520 }
2521 2521
2522 result = factory()->NewReturnStatement(return_value, loc.beg_pos); 2522 result = factory()->NewReturnStatement(return_value, loc.beg_pos);
2523 2523
2524 DeclarationScope* decl_scope = GetDeclarationScope(); 2524 DeclarationScope* decl_scope = GetDeclarationScope();
2525 if (decl_scope->is_script_scope() || decl_scope->is_eval_scope()) { 2525 if (decl_scope->is_script_scope() || decl_scope->is_eval_scope()) {
2526 ReportMessageAt(loc, MessageTemplate::kIllegalReturn); 2526 ReportMessageAt(loc, MessageTemplate::kIllegalReturn);
2527 *ok = false; 2527 *ok = false;
2528 return NULL; 2528 return NULL;
2529 } 2529 }
(...skipping 1309 matching lines...) Expand 10 before | Expand all | Expand 10 after
3839 AddFormalParameter(parameters, expr, initializer, end_pos, is_rest); 3839 AddFormalParameter(parameters, expr, initializer, end_pos, is_rest);
3840 } 3840 }
3841 3841
3842 void Parser::DesugarAsyncFunctionBody(const AstRawString* function_name, 3842 void Parser::DesugarAsyncFunctionBody(const AstRawString* function_name,
3843 Scope* scope, ZoneList<Statement*>* body, 3843 Scope* scope, ZoneList<Statement*>* body,
3844 ExpressionClassifier* classifier, 3844 ExpressionClassifier* classifier,
3845 FunctionKind kind, 3845 FunctionKind kind,
3846 FunctionBodyType body_type, 3846 FunctionBodyType body_type,
3847 bool accept_IN, int pos, bool* ok) { 3847 bool accept_IN, int pos, bool* ok) {
3848 // function async_function() { 3848 // function async_function() {
3849 // try { 3849 // .generator_object = %CreateGeneratorObject();
3850 // .generator_object = %CreateGeneratorObject(); 3850 // BuildRejectPromiseOnException({
3851 // ... function body ... 3851 // ... function body ...
3852 // } catch (e) { 3852 // return %ResolvePromise(.promise, expr), .promise;
3853 // return Promise.reject(e); 3853 // })
3854 // }
3855 // } 3854 // }
3856 scope->ForceContextAllocation(); 3855 scope->ForceContextAllocation();
3857 Variable* temp = 3856 Variable* temp =
3858 NewTemporary(ast_value_factory()->dot_generator_object_string()); 3857 NewTemporary(ast_value_factory()->dot_generator_object_string());
3859 function_state_->set_generator_object_variable(temp); 3858 function_state_->set_generator_object_variable(temp);
3860 3859
3861 Expression* init_generator_variable = factory()->NewAssignment( 3860 Expression* init_generator_variable = factory()->NewAssignment(
3862 Token::INIT, factory()->NewVariableProxy(temp), 3861 Token::INIT, factory()->NewVariableProxy(temp),
3863 BuildCreateJSGeneratorObject(pos, kind), kNoSourcePosition); 3862 BuildCreateJSGeneratorObject(pos, kind), kNoSourcePosition);
3864 body->Add(factory()->NewExpressionStatement(init_generator_variable, 3863 body->Add(factory()->NewExpressionStatement(init_generator_variable,
3865 kNoSourcePosition), 3864 kNoSourcePosition),
3866 zone()); 3865 zone());
3867 3866
3868 Block* try_block = factory()->NewBlock(NULL, 8, true, kNoSourcePosition); 3867 Block* block = factory()->NewBlock(NULL, 8, true, kNoSourcePosition);
3869
3870 ZoneList<Statement*>* inner_body = try_block->statements();
3871 3868
3872 Expression* return_value = nullptr; 3869 Expression* return_value = nullptr;
3873 if (body_type == FunctionBodyType::kNormal) { 3870 if (body_type == FunctionBodyType::kNormal) {
3874 ParseStatementList(inner_body, Token::RBRACE, CHECK_OK_VOID); 3871 ParseStatementList(block->statements(), Token::RBRACE, CHECK_OK_VOID);
3875 return_value = factory()->NewUndefinedLiteral(kNoSourcePosition); 3872 return_value = factory()->NewUndefinedLiteral(kNoSourcePosition);
3876 } else { 3873 } else {
3877 return_value = 3874 return_value =
3878 ParseAssignmentExpression(accept_IN, classifier, CHECK_OK_VOID); 3875 ParseAssignmentExpression(accept_IN, classifier, CHECK_OK_VOID);
3879 RewriteNonPattern(classifier, CHECK_OK_VOID); 3876 RewriteNonPattern(classifier, CHECK_OK_VOID);
3880 } 3877 }
3881 3878
3882 return_value = BuildPromiseResolve(return_value, return_value->position()); 3879 return_value = BuildResolvePromise(return_value, return_value->position());
3883 inner_body->Add( 3880 block->statements()->Add(
3884 factory()->NewReturnStatement(return_value, return_value->position()), 3881 factory()->NewReturnStatement(return_value, return_value->position()),
3885 zone()); 3882 zone());
3886 body->Add(BuildRejectPromiseOnException(try_block), zone()); 3883 block = BuildRejectPromiseOnException(block, CHECK_OK_VOID);
3884 body->Add(block, zone());
3887 scope->set_end_position(scanner()->location().end_pos); 3885 scope->set_end_position(scanner()->location().end_pos);
3888 } 3886 }
3889 3887
3890 DoExpression* Parser::ParseDoExpression(bool* ok) { 3888 DoExpression* Parser::ParseDoExpression(bool* ok) {
3891 // AssignmentExpression :: 3889 // AssignmentExpression ::
3892 // do '{' StatementList '}' 3890 // do '{' StatementList '}'
3893 int pos = peek_position(); 3891 int pos = peek_position();
3894 3892
3895 Expect(Token::DO, CHECK_OK); 3893 Expect(Token::DO, CHECK_OK);
3896 Variable* result = NewTemporary(ast_value_factory()->dot_result_string()); 3894 Variable* result = NewTemporary(ast_value_factory()->dot_result_string());
(...skipping 540 matching lines...) Expand 10 before | Expand all | Expand 10 after
4437 param_scope = block_state.FinalizedBlockScope(); 4435 param_scope = block_state.FinalizedBlockScope();
4438 if (param_scope != nullptr) { 4436 if (param_scope != nullptr) {
4439 CheckConflictingVarDeclarations(param_scope, CHECK_OK); 4437 CheckConflictingVarDeclarations(param_scope, CHECK_OK);
4440 } 4438 }
4441 init_block->statements()->Add(param_block, zone()); 4439 init_block->statements()->Add(param_block, zone());
4442 } 4440 }
4443 } 4441 }
4444 return init_block; 4442 return init_block;
4445 } 4443 }
4446 4444
4447 Block* Parser::BuildRejectPromiseOnException(Block* block) { 4445 Block* Parser::BuildRejectPromiseOnException(Block* inner_block, bool* ok) {
4448 // try { <block> } catch (error) { return Promise.reject(error); } 4446 // var .promise = %CreatePromise();
4449 Block* try_block = block; 4447 // var .debug_is_active = %_DebugIsActive();
4448 // if (.debug_is_active) %DebugPushPromise(.promise);
4449 // try {
4450 // <inner_block>
4451 // } catch (.catch) {
4452 // %RejectPromise(.promise, .catch);
4453 // return .promise;
4454 // } finally {
4455 // if (.debug_is_active) %DebugPopPromise();
4456 // }
4457 Block* result = factory()->NewBlock(nullptr, 4, true, kNoSourcePosition);
4458
4459 // var .promise = %CreatePromise();
4460 Statement* set_promise;
4461 {
4462 DeclareVariable(ast_value_factory()->dot_promise_string(), VAR,
neis 2016/08/25 08:15:22 Please declare this CONST, not VAR.
Dan Ehrenberg 2016/08/25 14:23:34 I use VAR rather than CONST here so that if there
4463 kNoSourcePosition, CHECK_OK);
4464 Expression* create_promise = factory()->NewCallRuntime(
4465 Context::PROMISE_CREATE_INDEX,
4466 new (zone()) ZoneList<Expression*>(0, zone()), kNoSourcePosition);
4467 Assignment* assign_promise = factory()->NewAssignment(
4468 Token::INIT, BuildDotPromise(), create_promise, kNoSourcePosition);
4469 set_promise =
4470 factory()->NewExpressionStatement(assign_promise, kNoSourcePosition);
4471 }
4472 result->statements()->Add(set_promise, zone());
4473
4474 // var .debug_is_active = %_DebugIsActive();
4475 Statement* set_debug_is_active;
4476 {
4477 DeclareVariable(ast_value_factory()->dot_debug_is_active_string(), VAR,
4478 kNoSourcePosition, CHECK_OK);
4479 Expression* debug_is_active = factory()->NewCallRuntime(
4480 Runtime::kInlineDebugIsActive,
4481 new (zone()) ZoneList<Expression*>(0, zone()), kNoSourcePosition);
4482 Assignment* assign_debug_is_active = factory()->NewAssignment(
4483 Token::INIT, BuildDotDebugIsActive(), debug_is_active, kNoSourcePosition );
4484 set_debug_is_active = factory()->NewExpressionStatement(
4485 assign_debug_is_active, kNoSourcePosition);
4486 }
4487 result->statements()->Add(set_debug_is_active, zone());
4488
4489 // if (.debug_is_active) %DebugPushPromise(.promise);
4490 Statement* conditionally_debug_push_promise;
4491 {
4492 ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(1, zone());
4493 args->Add(BuildDotPromise(), zone());
4494 Expression* call_push_promise = factory()->NewCallRuntime(
4495 Runtime::kDebugPushPromise, args, kNoSourcePosition);
4496 Statement* debug_push_promise =
4497 factory()->NewExpressionStatement(call_push_promise, kNoSourcePosition);
4498 conditionally_debug_push_promise = factory()->NewIfStatement(
4499 BuildDotDebugIsActive(), debug_push_promise,
4500 factory()->NewEmptyStatement(kNoSourcePosition), kNoSourcePosition);
4501 }
4502 result->statements()->Add(conditionally_debug_push_promise, zone());
4503
4504 // catch (.catch) { return %RejectPromise(.promise, .catch), .promise }
4450 Scope* catch_scope = NewScope(CATCH_SCOPE); 4505 Scope* catch_scope = NewScope(CATCH_SCOPE);
4451 catch_scope->set_is_hidden(); 4506 catch_scope->set_is_hidden();
4452 Variable* catch_variable = 4507 Variable* catch_variable =
4453 catch_scope->DeclareLocal(ast_value_factory()->dot_catch_string(), VAR, 4508 catch_scope->DeclareLocal(ast_value_factory()->dot_catch_string(), VAR,
4454 kCreatedInitialized, Variable::NORMAL); 4509 kCreatedInitialized, Variable::NORMAL);
4455 Block* catch_block = factory()->NewBlock(nullptr, 1, true, kNoSourcePosition); 4510 Block* catch_block = factory()->NewBlock(nullptr, 1, true, kNoSourcePosition);
4456 4511
4457 Expression* promise_reject = BuildPromiseReject( 4512 Expression* promise_reject = BuildRejectPromise(
4458 factory()->NewVariableProxy(catch_variable), kNoSourcePosition); 4513 factory()->NewVariableProxy(catch_variable), kNoSourcePosition);
4459
4460 ReturnStatement* return_promise_reject = 4514 ReturnStatement* return_promise_reject =
4461 factory()->NewReturnStatement(promise_reject, kNoSourcePosition); 4515 factory()->NewReturnStatement(promise_reject, kNoSourcePosition);
4462 catch_block->statements()->Add(return_promise_reject, zone()); 4516 catch_block->statements()->Add(return_promise_reject, zone());
4517
4463 TryStatement* try_catch_statement = factory()->NewTryCatchStatement( 4518 TryStatement* try_catch_statement = factory()->NewTryCatchStatement(
4464 try_block, catch_scope, catch_variable, catch_block, kNoSourcePosition); 4519 inner_block, catch_scope, catch_variable, catch_block, kNoSourcePosition);
4465 4520
4466 block = factory()->NewBlock(nullptr, 1, true, kNoSourcePosition); 4521 // There is no TryCatchFinally node, so wrap it in an outer try/finally
4467 block->statements()->Add(try_catch_statement, zone()); 4522 Block* outer_try_block =
4468 return block; 4523 factory()->NewBlock(nullptr, 1, true, kNoSourcePosition);
4524 outer_try_block->statements()->Add(try_catch_statement, zone());
4525
4526 // finally { if (.debug_is_active) %DebugPopPromise(); }
4527 Block* finally_block =
4528 factory()->NewBlock(nullptr, 1, true, kNoSourcePosition);
4529 {
4530 ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(0, zone());
4531 Expression* call_pop_promise = factory()->NewCallRuntime(
4532 Runtime::kDebugPopPromise, args, kNoSourcePosition);
4533 Statement* debug_pop_promise =
4534 factory()->NewExpressionStatement(call_pop_promise, kNoSourcePosition);
4535 Statement* conditionally_debug_pop_promise = factory()->NewIfStatement(
4536 BuildDotDebugIsActive(), debug_pop_promise,
4537 factory()->NewEmptyStatement(kNoSourcePosition), kNoSourcePosition);
4538 finally_block->statements()->Add(conditionally_debug_pop_promise, zone());
4539 }
4540
4541 Statement* try_finally_statement = factory()->NewTryFinallyStatement(
4542 outer_try_block, finally_block, kNoSourcePosition);
4543
4544 result->statements()->Add(try_finally_statement, zone());
4545 return result;
4469 } 4546 }
4470 4547
4471 Expression* Parser::BuildCreateJSGeneratorObject(int pos, FunctionKind kind) { 4548 Expression* Parser::BuildCreateJSGeneratorObject(int pos, FunctionKind kind) {
4472 DCHECK_NOT_NULL(function_state_->generator_object_variable()); 4549 DCHECK_NOT_NULL(function_state_->generator_object_variable());
4473 ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(2, zone()); 4550 ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(2, zone());
4474 args->Add(factory()->NewThisFunction(pos), zone()); 4551 args->Add(factory()->NewThisFunction(pos), zone());
4475 args->Add(IsArrowFunction(kind) ? GetLiteralUndefined(pos) 4552 args->Add(IsArrowFunction(kind) ? GetLiteralUndefined(pos)
4476 : ThisExpression(kNoSourcePosition), 4553 : ThisExpression(kNoSourcePosition),
4477 zone()); 4554 zone());
4478 return factory()->NewCallRuntime(Runtime::kCreateJSGeneratorObject, args, 4555 return factory()->NewCallRuntime(Runtime::kCreateJSGeneratorObject, args,
4479 pos); 4556 pos);
4480 } 4557 }
4481 4558
4482 Expression* Parser::BuildPromiseResolve(Expression* value, int pos) { 4559 Expression* Parser::BuildResolvePromise(Expression* value, int pos) {
4483 ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(1, zone()); 4560 // %ResolvePromise(.promise, value), .promise
4561 ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(2, zone());
4562 args->Add(BuildDotPromise(), zone());
4484 args->Add(value, zone()); 4563 args->Add(value, zone());
4485 return factory()->NewCallRuntime(Context::PROMISE_CREATE_RESOLVED_INDEX, args, 4564 Expression* call_runtime =
4486 pos); 4565 factory()->NewCallRuntime(Context::PROMISE_RESOLVE_INDEX, args, pos);
4566 return factory()->NewBinaryOperation(Token::COMMA, call_runtime,
4567 BuildDotPromise(), pos);
4487 } 4568 }
4488 4569
4489 Expression* Parser::BuildPromiseReject(Expression* value, int pos) { 4570 Expression* Parser::BuildRejectPromise(Expression* value, int pos) {
4490 ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(1, zone()); 4571 // %RejectPromiseNoDebugEvent(.promise, value, true), .promise
4572 // The NoDebugEvent variant disables the additional debug event for the
4573 // rejection since a debug event already happened for the exception that got
4574 // us here.
4575 ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(2, zone());
4576 args->Add(BuildDotPromise(), zone());
4491 args->Add(value, zone()); 4577 args->Add(value, zone());
4492 return factory()->NewCallRuntime(Context::PROMISE_CREATE_REJECTED_INDEX, args, 4578 Expression* call_runtime = factory()->NewCallRuntime(
4493 pos); 4579 Context::REJECT_PROMISE_NO_DEBUG_EVENT_INDEX, args, pos);
4580 return factory()->NewBinaryOperation(Token::COMMA, call_runtime,
4581 BuildDotPromise(), pos);
4582 }
4583
4584 VariableProxy* Parser::BuildDotPromise() {
4585 return NewUnresolved(ast_value_factory()->dot_promise_string(), VAR);
4586 }
4587
4588 VariableProxy* Parser::BuildDotDebugIsActive() {
4589 return NewUnresolved(ast_value_factory()->dot_debug_is_active_string(), VAR);
4494 } 4590 }
4495 4591
4496 ZoneList<Statement*>* Parser::ParseEagerFunctionBody( 4592 ZoneList<Statement*>* Parser::ParseEagerFunctionBody(
4497 const AstRawString* function_name, int pos, 4593 const AstRawString* function_name, int pos,
4498 const ParserFormalParameters& parameters, FunctionKind kind, 4594 const ParserFormalParameters& parameters, FunctionKind kind,
4499 FunctionLiteral::FunctionType function_type, bool* ok) { 4595 FunctionLiteral::FunctionType function_type, bool* ok) {
4500 // Everything inside an eagerly parsed function will be parsed eagerly 4596 // Everything inside an eagerly parsed function will be parsed eagerly
4501 // (see comment above). 4597 // (see comment above).
4502 ParsingModeScope parsing_mode(this, PARSE_EAGERLY); 4598 ParsingModeScope parsing_mode(this, PARSE_EAGERLY);
4503 ZoneList<Statement*>* result = new(zone()) ZoneList<Statement*>(8, zone()); 4599 ZoneList<Statement*>* result = new(zone()) ZoneList<Statement*>(8, zone());
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
4609 DCHECK_EQ(function_scope, inner_scope->outer_scope()); 4705 DCHECK_EQ(function_scope, inner_scope->outer_scope());
4610 DCHECK_EQ(body, inner_block->statements()); 4706 DCHECK_EQ(body, inner_block->statements());
4611 SetLanguageMode(function_scope, inner_scope->language_mode()); 4707 SetLanguageMode(function_scope, inner_scope->language_mode());
4612 Block* init_block = BuildParameterInitializationBlock(parameters, CHECK_OK); 4708 Block* init_block = BuildParameterInitializationBlock(parameters, CHECK_OK);
4613 4709
4614 if (is_sloppy(inner_scope->language_mode())) { 4710 if (is_sloppy(inner_scope->language_mode())) {
4615 InsertSloppyBlockFunctionVarBindings(inner_scope, function_scope, 4711 InsertSloppyBlockFunctionVarBindings(inner_scope, function_scope,
4616 CHECK_OK); 4712 CHECK_OK);
4617 } 4713 }
4618 4714
4715 // TODO(littledan): Merge the two rejection blocks into one
4619 if (IsAsyncFunction(kind)) { 4716 if (IsAsyncFunction(kind)) {
4620 init_block = BuildRejectPromiseOnException(init_block); 4717 init_block = BuildRejectPromiseOnException(init_block, CHECK_OK);
4621 } 4718 }
4622 4719
4623 DCHECK_NOT_NULL(init_block); 4720 DCHECK_NOT_NULL(init_block);
4624 4721
4625 inner_scope->set_end_position(scanner()->location().end_pos); 4722 inner_scope->set_end_position(scanner()->location().end_pos);
4626 if (inner_scope->FinalizeBlockScope() != nullptr) { 4723 if (inner_scope->FinalizeBlockScope() != nullptr) {
4627 CheckConflictingVarDeclarations(inner_scope, CHECK_OK); 4724 CheckConflictingVarDeclarations(inner_scope, CHECK_OK);
4628 InsertShadowingVarBindingInitializers(inner_block); 4725 InsertShadowingVarBindingInitializers(inner_block);
4629 } 4726 }
4630 inner_scope = nullptr; 4727 inner_scope = nullptr;
(...skipping 2092 matching lines...) Expand 10 before | Expand all | Expand 10 after
6723 node->Print(Isolate::Current()); 6820 node->Print(Isolate::Current());
6724 } 6821 }
6725 #endif // DEBUG 6822 #endif // DEBUG
6726 6823
6727 #undef CHECK_OK 6824 #undef CHECK_OK
6728 #undef CHECK_OK_VOID 6825 #undef CHECK_OK_VOID
6729 #undef CHECK_FAILED 6826 #undef CHECK_FAILED
6730 6827
6731 } // namespace internal 6828 } // namespace internal
6732 } // namespace v8 6829 } // namespace v8
OLDNEW
« no previous file with comments | « src/parsing/parser.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698