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

Unified 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: Partially fix `throw` completions (resumption works, but no resumption doesn't) Created 4 years, 8 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 side-by-side diff with in-line comments
Download patch
Index: src/parsing/parser.cc
diff --git a/src/parsing/parser.cc b/src/parsing/parser.cc
index ed63b543b46cae98d24debebc9334fcfa1f6f6ec..856f2c3614a0313980a704c3718c229288c87496 100644
--- a/src/parsing/parser.cc
+++ b/src/parsing/parser.cc
@@ -2681,7 +2681,7 @@ Statement* Parser::ParseReturnStatement(bool* ok) {
}
ExpectSemicolon(CHECK_OK);
- if (is_generator()) {
+ if (is_generator() || is_async_function()) {
return_value = BuildIteratorResult(return_value, true);
}
@@ -4026,6 +4026,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
? peek_position() : function_token_pos;
bool is_generator = IsGeneratorFunction(kind);
+ bool is_async = IsAsyncFunction(kind);
// Anonymous functions were passed either the empty symbol or a null
// handle as the function name. Remember if we were passed a non-empty
@@ -4057,7 +4058,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
scope_->SetScopeName(function_name);
ExpressionClassifier formals_classifier(this, &duplicate_finder);
- if (is_generator) {
+ if (is_generator || is_async) {
// For generators, allocating variables in contexts is currently a win
// because it minimizes the work needed to suspend and resume an
// activation. The machine code produced for generators (by full-codegen)
@@ -4541,27 +4542,28 @@ ZoneList<Statement*>* Parser::ParseEagerFunctionBody(
Block* try_block =
factory()->NewBlock(nullptr, 3, false, RelocInfo::kNoPosition);
- {
- ZoneList<Expression*>* arguments =
- new (zone()) ZoneList<Expression*>(2, zone());
- arguments->Add(factory()->NewThisFunction(pos), zone());
- arguments->Add(
- ThisExpression(scope_, factory(), RelocInfo::kNoPosition), zone());
- CallRuntime* allocation = factory()->NewCallRuntime(
- Runtime::kCreateJSGeneratorObject, arguments, pos);
-
- VariableProxy* init_proxy = factory()->NewVariableProxy(
- function_state_->generator_object_variable());
- Assignment* assignment = factory()->NewAssignment(
- Token::INIT, init_proxy, allocation, RelocInfo::kNoPosition);
- VariableProxy* get_proxy = factory()->NewVariableProxy(
- function_state_->generator_object_variable());
- Yield* yield =
- factory()->NewYield(get_proxy, assignment, RelocInfo::kNoPosition);
- try_block->statements()->Add(
- factory()->NewExpressionStatement(yield, RelocInfo::kNoPosition),
- zone());
- }
+ ZoneList<Expression*>* arguments =
caitp (gmail) 2016/04/16 18:33:03 Bunch of phantom edits to clean up, since the asyn
+ new (zone()) ZoneList<Expression*>(2, zone());
+ arguments->Add(factory()->NewThisFunction(pos), zone());
+ arguments->Add(ThisExpression(scope_, factory(), RelocInfo::kNoPosition),
+ zone());
+ CallRuntime* allocation = factory()->NewCallRuntime(
+ Runtime::kCreateJSGeneratorObject, arguments, pos);
+
+ VariableProxy* init_proxy = factory()->NewVariableProxy(
+ function_state_->generator_object_variable());
+ Assignment* assignment = factory()->NewAssignment(
+ Token::INIT, init_proxy, allocation, RelocInfo::kNoPosition);
+
+ VariableProxy* get_proxy = factory()->NewVariableProxy(
+ function_state_->generator_object_variable());
+
+ Yield* yield =
+ factory()->NewYield(get_proxy, assignment, RelocInfo::kNoPosition);
+
+ try_block->statements()->Add(
+ factory()->NewExpressionStatement(yield, RelocInfo::kNoPosition),
+ zone());
ParseStatementList(try_block->statements(), Token::RBRACE, CHECK_OK);
@@ -4578,6 +4580,7 @@ ZoneList<Statement*>* Parser::ParseEagerFunctionBody(
args->Add(call_proxy, zone());
Expression* call = factory()->NewCallRuntime(
Runtime::kGeneratorClose, args, RelocInfo::kNoPosition);
+
finally_block->statements()->Add(
factory()->NewExpressionStatement(call, RelocInfo::kNoPosition),
zone());
@@ -4585,6 +4588,41 @@ ZoneList<Statement*>* Parser::ParseEagerFunctionBody(
body->Add(factory()->NewTryFinallyStatement(try_block, finally_block,
RelocInfo::kNoPosition),
zone());
+ } else if (IsAsyncFunction(kind)) {
+ ZoneList<Expression*>* arguments =
+ new (zone()) ZoneList<Expression*>(2, zone());
+ arguments->Add(factory()->NewThisFunction(pos), zone());
+ arguments->Add(ThisExpression(scope_, factory(), RelocInfo::kNoPosition),
+ zone());
+ CallRuntime* allocation = factory()->NewCallRuntime(
+ Runtime::kCreateJSGeneratorObject, arguments, pos);
+
+ VariableProxy* init_proxy = factory()->NewVariableProxy(
+ function_state_->generator_object_variable());
+ Assignment* assignment = factory()->NewAssignment(
+ Token::INIT, init_proxy, allocation, RelocInfo::kNoPosition);
+
+ VariableProxy* get_proxy = factory()->NewVariableProxy(
+ function_state_->generator_object_variable());
+
+ ZoneList<Expression*>* async_function_start_args =
+ new (zone()) ZoneList<Expression*>(1, zone());
+ async_function_start_args->Add(get_proxy, zone());
+ CallRuntime* async_function_start = factory()->NewCallRuntime(
+ Context::ASYNC_FUNCTION_START_INDEX, async_function_start_args,
+ RelocInfo::kNoPosition);
+ Yield* yield = factory()->NewAsyncFunctionStart(
+ assignment, async_function_start, RelocInfo::kNoPosition);
+
+ body->Add(
+ factory()->NewExpressionStatement(yield, RelocInfo::kNoPosition),
+ zone());
+
+ ParseStatementList(body, Token::RBRACE, CHECK_OK);
+
+ Statement* final_return = factory()->NewReturnStatement(
+ BuildIteratorResult(nullptr, true), RelocInfo::kNoPosition);
+ body->Add(final_return, zone());
} else {
ParseStatementList(body, Token::RBRACE, CHECK_OK);
}
@@ -4606,6 +4644,39 @@ ZoneList<Statement*>* Parser::ParseEagerFunctionBody(
DCHECK_EQ(body, inner_block->statements());
SetLanguageMode(scope_, inner_scope->language_mode());
Block* init_block = BuildParameterInitializationBlock(parameters, CHECK_OK);
+
+ if (IsAsyncFunction(kind)) {
+ // If an exception occurs during parameter initialization, return a
+ // rejected promise.
+ //
+ // try { <init_block> } catch (error) { return Promise.reject(error); }
+ Block* try_block = init_block;
+ Scope* catch_scope = NewScope(scope_, CATCH_SCOPE);
+ Variable* catch_variable =
+ catch_scope->DeclareLocal(ast_value_factory()->dot_catch_string(),
+ VAR, kCreatedInitialized, Variable::NORMAL);
+ Block* catch_block =
+ factory()->NewBlock(nullptr, 1, true, RelocInfo::kNoPosition);
+
+ ZoneList<Expression*>* promise_reject_arguments =
+ new (zone()) ZoneList<Expression*>(1, zone());
+ promise_reject_arguments->Add(factory()->NewVariableProxy(catch_variable),
+ zone());
+ CallRuntime* promise_reject = factory()->NewCallRuntime(
+ Context::PROMISE_CREATE_REJECTED_INDEX, promise_reject_arguments,
+ RelocInfo::kNoPosition);
+ ReturnStatement* return_promise_reject =
+ factory()->NewReturnStatement(promise_reject, RelocInfo::kNoPosition);
+ catch_block->statements()->Add(return_promise_reject, zone());
+ TryStatement* try_catch_statement = factory()->NewTryCatchStatement(
+ try_block, catch_scope, catch_variable, catch_block,
+ RelocInfo::kNoPosition);
+
+ init_block =
+ factory()->NewBlock(nullptr, 1, true, RelocInfo::kNoPosition);
+ init_block->statements()->Add(try_catch_statement, zone());
+ }
+
DCHECK_NOT_NULL(init_block);
inner_scope->set_end_position(scanner()->location().end_pos);
@@ -5396,7 +5467,10 @@ void ParserTraits::RewriteNonPattern(Type::ExpressionClassifier* classifier,
Expression* ParserTraits::RewriteAwaitExpression(Expression* value, int pos) {
// TODO(caitp): Implement AsyncFunctionAwait()
// per tc39.github.io/ecmascript-asyncawait/#abstract-ops-async-function-await
- return value;
+ Expression* generator_object = parser_->factory()->NewVariableProxy(
+ parser_->function_state_->generator_object_variable());
+ value = BuildIteratorResult(value, false);
+ return parser_->factory()->NewYield(generator_object, value, pos);
}
Zone* ParserTraits::zone() const {
« src/js/promise.js ('K') | « src/objects-inl.h ('k') | src/parsing/parser-base.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698