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

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

Issue 2685683002: [async-await] (simpler) fix for Return in try/finally in async functions (Closed)
Patch Set: Created 3 years, 10 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
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 1597 matching lines...) Expand 10 before | Expand all | Expand 10 after
1608 Expression* is_undefined = factory()->NewCompareOperation( 1608 Expression* is_undefined = factory()->NewCompareOperation(
1609 Token::EQ_STRICT, assign, 1609 Token::EQ_STRICT, assign,
1610 factory()->NewUndefinedLiteral(kNoSourcePosition), pos); 1610 factory()->NewUndefinedLiteral(kNoSourcePosition), pos);
1611 1611
1612 // is_undefined ? this : is_object_conditional 1612 // is_undefined ? this : is_object_conditional
1613 return_value = factory()->NewConditional(is_undefined, ThisExpression(pos), 1613 return_value = factory()->NewConditional(is_undefined, ThisExpression(pos),
1614 is_object_conditional, pos); 1614 is_object_conditional, pos);
1615 } 1615 }
1616 if (is_generator()) { 1616 if (is_generator()) {
1617 return_value = BuildIteratorResult(return_value, true); 1617 return_value = BuildIteratorResult(return_value, true);
1618 } else if (is_async_function()) {
1619 return_value = BuildResolvePromise(return_value, return_value->position());
1620 } 1618 }
1621 return return_value; 1619 return return_value;
1622 } 1620 }
1623 1621
1624 Expression* Parser::RewriteDoExpression(Block* body, int pos, bool* ok) { 1622 Expression* Parser::RewriteDoExpression(Block* body, int pos, bool* ok) {
1625 Variable* result = NewTemporary(ast_value_factory()->dot_result_string()); 1623 Variable* result = NewTemporary(ast_value_factory()->dot_result_string());
1626 DoExpression* expr = factory()->NewDoExpression(body, result, pos); 1624 DoExpression* expr = factory()->NewDoExpression(body, result, pos);
1627 if (!Rewriter::Rewrite(this, GetClosureScope(), expr, ast_value_factory())) { 1625 if (!Rewriter::Rewrite(this, GetClosureScope(), expr, ast_value_factory())) {
1628 *ok = false; 1626 *ok = false;
1629 return nullptr; 1627 return nullptr;
(...skipping 842 matching lines...) Expand 10 before | Expand all | Expand 10 after
2472 void Parser::PrepareGeneratorVariables() { 2470 void Parser::PrepareGeneratorVariables() {
2473 // For generators, allocating variables in contexts is currently a win because 2471 // For generators, allocating variables in contexts is currently a win because
2474 // it minimizes the work needed to suspend and resume an activation. The 2472 // it minimizes the work needed to suspend and resume an activation. The
2475 // code produced for generators relies on this forced context allocation (it 2473 // code produced for generators relies on this forced context allocation (it
2476 // does not restore the frame's parameters upon resume). 2474 // does not restore the frame's parameters upon resume).
2477 function_state_->scope()->ForceContextAllocation(); 2475 function_state_->scope()->ForceContextAllocation();
2478 2476
2479 // Calling a generator returns a generator object. That object is stored 2477 // Calling a generator returns a generator object. That object is stored
2480 // in a temporary variable, a definition that is used by "yield" 2478 // in a temporary variable, a definition that is used by "yield"
2481 // expressions. 2479 // expressions.
2482 Variable* temp = 2480 Variable* temp = function_state_->scope()->DeclareGeneratorObjectVar(
2483 NewTemporary(ast_value_factory()->dot_generator_object_string()); 2481 ast_value_factory()->dot_generator_object_string());
2484 function_state_->set_generator_object_variable(temp); 2482 temp->set_is_used();
2485 } 2483 }
2486 2484
2487 FunctionLiteral* Parser::ParseFunctionLiteral( 2485 FunctionLiteral* Parser::ParseFunctionLiteral(
2488 const AstRawString* function_name, Scanner::Location function_name_location, 2486 const AstRawString* function_name, Scanner::Location function_name_location,
2489 FunctionNameValidity function_name_validity, FunctionKind kind, 2487 FunctionNameValidity function_name_validity, FunctionKind kind,
2490 int function_token_pos, FunctionLiteral::FunctionType function_type, 2488 int function_token_pos, FunctionLiteral::FunctionType function_type,
2491 LanguageMode language_mode, bool* ok) { 2489 LanguageMode language_mode, bool* ok) {
2492 // Function :: 2490 // Function ::
2493 // '(' FormalParameterList? ')' '{' FunctionBody '}' 2491 // '(' FormalParameterList? ')' '{' FunctionBody '}'
2494 // 2492 //
(...skipping 511 matching lines...) Expand 10 before | Expand all | Expand 10 after
3006 // catch (.catch) { return %RejectPromise(.promise, .catch), .promise } 3004 // catch (.catch) { return %RejectPromise(.promise, .catch), .promise }
3007 Scope* catch_scope = NewScope(CATCH_SCOPE); 3005 Scope* catch_scope = NewScope(CATCH_SCOPE);
3008 catch_scope->set_is_hidden(); 3006 catch_scope->set_is_hidden();
3009 Variable* catch_variable = 3007 Variable* catch_variable =
3010 catch_scope->DeclareLocal(ast_value_factory()->dot_catch_string(), VAR); 3008 catch_scope->DeclareLocal(ast_value_factory()->dot_catch_string(), VAR);
3011 Block* catch_block = factory()->NewBlock(nullptr, 1, true, kNoSourcePosition); 3009 Block* catch_block = factory()->NewBlock(nullptr, 1, true, kNoSourcePosition);
3012 3010
3013 Expression* promise_reject = BuildRejectPromise( 3011 Expression* promise_reject = BuildRejectPromise(
3014 factory()->NewVariableProxy(catch_variable), kNoSourcePosition); 3012 factory()->NewVariableProxy(catch_variable), kNoSourcePosition);
3015 ReturnStatement* return_promise_reject = 3013 ReturnStatement* return_promise_reject =
3016 factory()->NewReturnStatement(promise_reject, kNoSourcePosition); 3014 factory()->NewHardReturnStatement(promise_reject, kNoSourcePosition);
3017 catch_block->statements()->Add(return_promise_reject, zone()); 3015 catch_block->statements()->Add(return_promise_reject, zone());
3018 3016
3019 TryStatement* try_catch_statement = 3017 TryStatement* try_catch_statement =
3020 factory()->NewTryCatchStatementForAsyncAwait(inner_block, catch_scope, 3018 factory()->NewTryCatchStatementForAsyncAwait(inner_block, catch_scope,
3021 catch_variable, catch_block, 3019 catch_variable, catch_block,
3022 kNoSourcePosition); 3020 kNoSourcePosition);
3023 3021
3024 // There is no TryCatchFinally node, so wrap it in an outer try/finally 3022 // There is no TryCatchFinally node, so wrap it in an outer try/finally
3025 Block* outer_try_block = 3023 Block* outer_try_block =
3026 factory()->NewBlock(nullptr, 1, true, kNoSourcePosition); 3024 factory()->NewBlock(nullptr, 1, true, kNoSourcePosition);
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
3088 Token::COMMA, call_runtime, 3086 Token::COMMA, call_runtime,
3089 factory()->NewVariableProxy(PromiseVariable()), pos); 3087 factory()->NewVariableProxy(PromiseVariable()), pos);
3090 } 3088 }
3091 3089
3092 Variable* Parser::PromiseVariable() { 3090 Variable* Parser::PromiseVariable() {
3093 // Based on the various compilation paths, there are many different code 3091 // Based on the various compilation paths, there are many different code
3094 // paths which may be the first to access the Promise temporary. Whichever 3092 // paths which may be the first to access the Promise temporary. Whichever
3095 // comes first should create it and stash it in the FunctionState. 3093 // comes first should create it and stash it in the FunctionState.
3096 Variable* promise = function_state_->promise_variable(); 3094 Variable* promise = function_state_->promise_variable();
3097 if (function_state_->promise_variable() == nullptr) { 3095 if (function_state_->promise_variable() == nullptr) {
3098 promise = scope()->NewTemporary(ast_value_factory()->empty_string()); 3096 promise = function_state_->scope()->DeclarePromiseVar(
3099 function_state_->set_promise_variable(promise); 3097 ast_value_factory()->empty_string());
3098 promise->set_is_used();
3100 } 3099 }
3101 return promise; 3100 return promise;
3102 } 3101 }
3103 3102
3104 Expression* Parser::BuildInitialYield(int pos, FunctionKind kind) { 3103 Expression* Parser::BuildInitialYield(int pos, FunctionKind kind) {
3105 Assignment* assignment = BuildCreateJSGeneratorObject(pos, kind); 3104 Assignment* assignment = BuildCreateJSGeneratorObject(pos, kind);
3106 VariableProxy* generator = 3105 VariableProxy* generator =
3107 factory()->NewVariableProxy(function_state_->generator_object_variable()); 3106 factory()->NewVariableProxy(function_state_->generator_object_variable());
3108 // The position of the yield is important for reporting the exception 3107 // The position of the yield is important for reporting the exception
3109 // caused by calling the .throw method on a generator suspended at the 3108 // caused by calling the .throw method on a generator suspended at the
(...skipping 671 matching lines...) Expand 10 before | Expand all | Expand 10 after
3781 // function async_function() { 3780 // function async_function() {
3782 // .generator_object = %CreateJSGeneratorObject(); 3781 // .generator_object = %CreateJSGeneratorObject();
3783 // BuildRejectPromiseOnException({ 3782 // BuildRejectPromiseOnException({
3784 // ... block ... 3783 // ... block ...
3785 // return %ResolvePromise(.promise, expr), .promise; 3784 // return %ResolvePromise(.promise, expr), .promise;
3786 // }) 3785 // })
3787 // } 3786 // }
3788 3787
3789 return_value = BuildResolvePromise(return_value, return_value->position()); 3788 return_value = BuildResolvePromise(return_value, return_value->position());
3790 block->statements()->Add( 3789 block->statements()->Add(
3791 factory()->NewReturnStatement(return_value, return_value->position()), 3790 factory()->NewHardReturnStatement(return_value, return_value->position()),
3792 zone()); 3791 zone());
3793 block = BuildRejectPromiseOnException(block); 3792 block = BuildRejectPromiseOnException(block);
3794 body->Add(block, zone()); 3793 body->Add(block, zone());
3795 } 3794 }
3796 3795
3797 Expression* Parser::RewriteAwaitExpression(Expression* value, int await_pos) { 3796 Expression* Parser::RewriteAwaitExpression(Expression* value, int await_pos) {
3798 // yield do { 3797 // yield do {
3799 // tmp = <operand>; 3798 // tmp = <operand>;
3800 // %AsyncFunctionAwait(.generator_object, tmp, .promise); 3799 // %AsyncFunctionAwait(.generator_object, tmp, .promise);
3801 // .promise 3800 // .promise
(...skipping 1224 matching lines...) Expand 10 before | Expand all | Expand 10 after
5026 5025
5027 return final_loop; 5026 return final_loop;
5028 } 5027 }
5029 5028
5030 #undef CHECK_OK 5029 #undef CHECK_OK
5031 #undef CHECK_OK_VOID 5030 #undef CHECK_OK_VOID
5032 #undef CHECK_FAILED 5031 #undef CHECK_FAILED
5033 5032
5034 } // namespace internal 5033 } // namespace internal
5035 } // namespace v8 5034 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698