Commit fbb46475 authored by Caitlin Potter's avatar Caitlin Potter Committed by Commit Bot

[ignition] desugar AsyncGenerator yield* in BytecodeGenerator

Move the desugaring into BytecodeGenerator per TODOs.

BUG=v8:6472
R=tebbi@chromium.org, rmcilroy@chromium.org, jgruber@chromium.org

Change-Id: Ic482bee18d6e6fe73de4c5f9abaf4feda7be2dd5
Reviewed-on: https://chromium-review.googlesource.com/550396Reviewed-by: 's avatarRoss McIlroy <rmcilroy@chromium.org>
Reviewed-by: 's avatarGeorg Neis <neis@chromium.org>
Reviewed-by: 's avatarTobias Tebbi <tebbi@chromium.org>
Commit-Queue: Caitlin Potter <caitp@igalia.com>
Cr-Commit-Position: refs/heads/master@{#47403}
parent 7707e12b
...@@ -62,7 +62,7 @@ class AstNumberingVisitor final : public AstVisitor<AstNumberingVisitor> { ...@@ -62,7 +62,7 @@ class AstNumberingVisitor final : public AstVisitor<AstNumberingVisitor> {
template <typename Node> template <typename Node>
void ReserveFeedbackSlots(Node* node) { void ReserveFeedbackSlots(Node* node) {
node->AssignFeedbackSlots(properties_.get_spec(), language_mode_, node->AssignFeedbackSlots(properties_.get_spec(), language_mode_,
&slot_cache_); function_kind_, &slot_cache_);
} }
class LanguageModeScope { class LanguageModeScope {
...@@ -198,7 +198,12 @@ void AstNumberingVisitor::VisitSuspend(Suspend* node) { ...@@ -198,7 +198,12 @@ void AstNumberingVisitor::VisitSuspend(Suspend* node) {
void AstNumberingVisitor::VisitYield(Yield* node) { VisitSuspend(node); } void AstNumberingVisitor::VisitYield(Yield* node) { VisitSuspend(node); }
void AstNumberingVisitor::VisitYieldStar(YieldStar* node) { void AstNumberingVisitor::VisitYieldStar(YieldStar* node) {
VisitSuspend(node); node->set_suspend_id(suspend_count_++);
if (IsAsyncGeneratorFunction(function_kind_)) {
node->set_await_iterator_close_suspend_id(suspend_count_++);
node->set_await_delegated_iterator_output_suspend_id(suspend_count_++);
}
Visit(node->expression());
ReserveFeedbackSlots(node); ReserveFeedbackSlots(node);
} }
......
...@@ -246,6 +246,7 @@ static void AssignVectorSlots(Expression* expr, FeedbackVectorSpec* spec, ...@@ -246,6 +246,7 @@ static void AssignVectorSlots(Expression* expr, FeedbackVectorSpec* spec,
void ForInStatement::AssignFeedbackSlots(FeedbackVectorSpec* spec, void ForInStatement::AssignFeedbackSlots(FeedbackVectorSpec* spec,
LanguageMode language_mode, LanguageMode language_mode,
FunctionKind kind,
FeedbackSlotCache* cache) { FeedbackSlotCache* cache) {
AssignVectorSlots(each(), spec, language_mode, &each_slot_); AssignVectorSlots(each(), spec, language_mode, &each_slot_);
for_in_feedback_slot_ = spec->AddGeneralSlot(); for_in_feedback_slot_ = spec->AddGeneralSlot();
...@@ -261,12 +262,14 @@ Assignment::Assignment(NodeType node_type, Token::Value op, Expression* target, ...@@ -261,12 +262,14 @@ Assignment::Assignment(NodeType node_type, Token::Value op, Expression* target,
void Assignment::AssignFeedbackSlots(FeedbackVectorSpec* spec, void Assignment::AssignFeedbackSlots(FeedbackVectorSpec* spec,
LanguageMode language_mode, LanguageMode language_mode,
FunctionKind kind,
FeedbackSlotCache* cache) { FeedbackSlotCache* cache) {
AssignVectorSlots(target(), spec, language_mode, &slot_); AssignVectorSlots(target(), spec, language_mode, &slot_);
} }
void CountOperation::AssignFeedbackSlots(FeedbackVectorSpec* spec, void CountOperation::AssignFeedbackSlots(FeedbackVectorSpec* spec,
LanguageMode language_mode, LanguageMode language_mode,
FunctionKind kind,
FeedbackSlotCache* cache) { FeedbackSlotCache* cache) {
AssignVectorSlots(expression(), spec, language_mode, &slot_); AssignVectorSlots(expression(), spec, language_mode, &slot_);
// Assign a slot to collect feedback about binary operations. Used only in // Assign a slot to collect feedback about binary operations. Used only in
...@@ -375,6 +378,7 @@ ClassLiteralProperty::ClassLiteralProperty(Expression* key, Expression* value, ...@@ -375,6 +378,7 @@ ClassLiteralProperty::ClassLiteralProperty(Expression* key, Expression* value,
void ClassLiteral::AssignFeedbackSlots(FeedbackVectorSpec* spec, void ClassLiteral::AssignFeedbackSlots(FeedbackVectorSpec* spec,
LanguageMode language_mode, LanguageMode language_mode,
FunctionKind kind,
FeedbackSlotCache* cache) { FeedbackSlotCache* cache) {
// This logic that computes the number of slots needed for vector store // This logic that computes the number of slots needed for vector store
// ICs must mirror BytecodeGenerator::VisitClassLiteral. // ICs must mirror BytecodeGenerator::VisitClassLiteral.
...@@ -412,8 +416,9 @@ bool ObjectLiteral::Property::emit_store() const { return emit_store_; } ...@@ -412,8 +416,9 @@ bool ObjectLiteral::Property::emit_store() const { return emit_store_; }
void ObjectLiteral::AssignFeedbackSlots(FeedbackVectorSpec* spec, void ObjectLiteral::AssignFeedbackSlots(FeedbackVectorSpec* spec,
LanguageMode language_mode, LanguageMode language_mode,
FunctionKind kind,
FeedbackSlotCache* cache) { FeedbackSlotCache* cache) {
MaterializedLiteral::AssignFeedbackSlots(spec, language_mode, cache); MaterializedLiteral::AssignFeedbackSlots(spec, language_mode, kind, cache);
// This logic that computes the number of slots needed for vector store // This logic that computes the number of slots needed for vector store
// ics must mirror FullCodeGenerator::VisitObjectLiteral. // ics must mirror FullCodeGenerator::VisitObjectLiteral.
...@@ -770,8 +775,9 @@ void ArrayLiteral::RewindSpreads() { ...@@ -770,8 +775,9 @@ void ArrayLiteral::RewindSpreads() {
void ArrayLiteral::AssignFeedbackSlots(FeedbackVectorSpec* spec, void ArrayLiteral::AssignFeedbackSlots(FeedbackVectorSpec* spec,
LanguageMode language_mode, LanguageMode language_mode,
FunctionKind kind,
FeedbackSlotCache* cache) { FeedbackSlotCache* cache) {
MaterializedLiteral::AssignFeedbackSlots(spec, language_mode, cache); MaterializedLiteral::AssignFeedbackSlots(spec, language_mode, kind, cache);
// This logic that computes the number of slots needed for vector store // This logic that computes the number of slots needed for vector store
// ics must mirror FullCodeGenerator::VisitArrayLiteral. // ics must mirror FullCodeGenerator::VisitArrayLiteral.
...@@ -835,6 +841,7 @@ void MaterializedLiteral::BuildConstants(Isolate* isolate) { ...@@ -835,6 +841,7 @@ void MaterializedLiteral::BuildConstants(Isolate* isolate) {
void BinaryOperation::AssignFeedbackSlots(FeedbackVectorSpec* spec, void BinaryOperation::AssignFeedbackSlots(FeedbackVectorSpec* spec,
LanguageMode language_mode, LanguageMode language_mode,
FunctionKind kind,
FeedbackSlotCache* cache) { FeedbackSlotCache* cache) {
// Feedback vector slot is only used by interpreter for binary operations. // Feedback vector slot is only used by interpreter for binary operations.
// Full-codegen uses AstId to record type feedback. // Full-codegen uses AstId to record type feedback.
...@@ -881,6 +888,7 @@ static bool IsTypeof(Expression* expr) { ...@@ -881,6 +888,7 @@ static bool IsTypeof(Expression* expr) {
void CompareOperation::AssignFeedbackSlots(FeedbackVectorSpec* spec, void CompareOperation::AssignFeedbackSlots(FeedbackVectorSpec* spec,
LanguageMode language_mode, LanguageMode language_mode,
FunctionKind kind,
FeedbackSlotCache* cache_) { FeedbackSlotCache* cache_) {
// Feedback vector slot is only used by interpreter for binary operations. // Feedback vector slot is only used by interpreter for binary operations.
// Full-codegen uses AstId to record type feedback. // Full-codegen uses AstId to record type feedback.
...@@ -1022,7 +1030,7 @@ bool Expression::IsMonomorphic() const { ...@@ -1022,7 +1030,7 @@ bool Expression::IsMonomorphic() const {
} }
void Call::AssignFeedbackSlots(FeedbackVectorSpec* spec, void Call::AssignFeedbackSlots(FeedbackVectorSpec* spec,
LanguageMode language_mode, LanguageMode language_mode, FunctionKind kind,
FeedbackSlotCache* cache) { FeedbackSlotCache* cache) {
ic_slot_ = spec->AddCallICSlot(); ic_slot_ = spec->AddCallICSlot();
} }
...@@ -1060,6 +1068,7 @@ CaseClause::CaseClause(Expression* label, ZoneList<Statement*>* statements, ...@@ -1060,6 +1068,7 @@ CaseClause::CaseClause(Expression* label, ZoneList<Statement*>* statements,
void CaseClause::AssignFeedbackSlots(FeedbackVectorSpec* spec, void CaseClause::AssignFeedbackSlots(FeedbackVectorSpec* spec,
LanguageMode language_mode, LanguageMode language_mode,
FunctionKind kind,
FeedbackSlotCache* cache) { FeedbackSlotCache* cache) {
feedback_slot_ = spec->AddInterpreterCompareICSlot(); feedback_slot_ = spec->AddInterpreterCompareICSlot();
} }
......
This diff is collapsed.
...@@ -2727,6 +2727,7 @@ void BytecodeGenerator::VisitYield(Yield* expr) { ...@@ -2727,6 +2727,7 @@ void BytecodeGenerator::VisitYield(Yield* expr) {
// let iteratorReturn = iterator.return; // let iteratorReturn = iterator.return;
// if (!IS_NULL_OR_UNDEFINED(iteratorReturn)) { // if (!IS_NULL_OR_UNDEFINED(iteratorReturn)) {
// output = %_Call(iteratorReturn, iterator); // output = %_Call(iteratorReturn, iterator);
// if (IS_ASYNC_GENERATOR) output = await output;
// if (!IS_RECEIVER(output)) %ThrowIterResultNotAnObject(output); // if (!IS_RECEIVER(output)) %ThrowIterResultNotAnObject(output);
// } // }
// throw MakeTypeError(kThrowMethodMissing); // throw MakeTypeError(kThrowMethodMissing);
...@@ -2734,11 +2735,18 @@ void BytecodeGenerator::VisitYield(Yield* expr) { ...@@ -2734,11 +2735,18 @@ void BytecodeGenerator::VisitYield(Yield* expr) {
// output = %_Call(iteratorThrow, iterator, input); // output = %_Call(iteratorThrow, iterator, input);
// break; // break;
// } // }
//
// if (IS_ASYNC_GENERATOR) output = await output;
// if (!IS_RECEIVER(output)) %ThrowIterResultNotAnObject(output); // if (!IS_RECEIVER(output)) %ThrowIterResultNotAnObject(output);
// if (output.done) break; // if (output.done) break;
// //
// // From the generator to its user: // // From the generator to its user:
// // Forward output, receive new input, and determine resume mode. // // Forward output, receive new input, and determine resume mode.
// if (IS_ASYNC_GENERATOR) {
// // AsyncGeneratorYield abstract operation awaits the operand before
// // resolving the promise for the current AsyncGeneratorRequest.
// %_AsyncGeneratorYield(output.value)
// }
// input = Suspend(output); // input = Suspend(output);
// resumeMode = %GeneratorGetResumeMode(); // resumeMode = %GeneratorGetResumeMode();
// } // }
...@@ -2749,11 +2757,11 @@ void BytecodeGenerator::VisitYield(Yield* expr) { ...@@ -2749,11 +2757,11 @@ void BytecodeGenerator::VisitYield(Yield* expr) {
// output.value // output.value
// } // }
void BytecodeGenerator::VisitYieldStar(YieldStar* expr) { void BytecodeGenerator::VisitYieldStar(YieldStar* expr) {
// TODO(tebbi): Also desugar async generator yield* in the BytecodeGenerator.
DCHECK(!IsAsyncGeneratorFunction(function_kind()));
Register output = register_allocator()->NewRegister(); Register output = register_allocator()->NewRegister();
Register resume_mode = register_allocator()->NewRegister(); Register resume_mode = register_allocator()->NewRegister();
IteratorType iterator_type = IsAsyncGeneratorFunction(function_kind())
? IteratorType::kAsync
: IteratorType::kNormal;
{ {
RegisterAllocationScope register_scope(this); RegisterAllocationScope register_scope(this);
...@@ -2761,10 +2769,12 @@ void BytecodeGenerator::VisitYieldStar(YieldStar* expr) { ...@@ -2761,10 +2769,12 @@ void BytecodeGenerator::VisitYieldStar(YieldStar* expr) {
RegisterList iterator_and_input = register_allocator()->NewRegisterList(2); RegisterList iterator_and_input = register_allocator()->NewRegisterList(2);
Register iterator = iterator_and_input[0]; Register iterator = iterator_and_input[0];
BuildGetIterator(expr->expression(), IteratorType::kNormal,
BuildGetIterator(expr->expression(), iterator_type,
expr->load_iterable_iterator_slot(), expr->load_iterable_iterator_slot(),
expr->call_iterable_iterator_slot(), expr->call_iterable_iterator_slot(),
FeedbackSlot::Invalid(), FeedbackSlot::Invalid()); expr->load_iterable_async_iterator_slot(),
expr->call_iterable_async_iterator_slot());
builder()->StoreAccumulatorInRegister(iterator); builder()->StoreAccumulatorInRegister(iterator);
Register input = iterator_and_input[1]; Register input = iterator_and_input[1];
builder()->LoadUndefined().StoreAccumulatorInRegister(input); builder()->LoadUndefined().StoreAccumulatorInRegister(input);
...@@ -2776,8 +2786,11 @@ void BytecodeGenerator::VisitYieldStar(YieldStar* expr) { ...@@ -2776,8 +2786,11 @@ void BytecodeGenerator::VisitYieldStar(YieldStar* expr) {
// This loop builder does not construct counters as the loop is not // This loop builder does not construct counters as the loop is not
// visible to the user, and we therefore neither pass the block coverage // visible to the user, and we therefore neither pass the block coverage
// builder nor the expression. // builder nor the expression.
//
// YieldStar in AsyncGenerator functions includes 3 suspend points, rather
// than 1. These are documented in the YieldStar AST node.
LoopBuilder loop(builder(), nullptr, nullptr); LoopBuilder loop(builder(), nullptr, nullptr);
VisitIterationHeader(expr->suspend_id(), 1, &loop); VisitIterationHeader(expr->suspend_id(), expr->suspend_count(), &loop);
{ {
BytecodeLabels after_switch(zone()); BytecodeLabels after_switch(zone());
...@@ -2827,7 +2840,11 @@ void BytecodeGenerator::VisitYieldStar(YieldStar* expr) { ...@@ -2827,7 +2840,11 @@ void BytecodeGenerator::VisitYieldStar(YieldStar* expr) {
return_input.Bind(builder()); return_input.Bind(builder());
{ {
builder()->LoadAccumulatorWithRegister(input); builder()->LoadAccumulatorWithRegister(input);
execution_control()->ReturnAccumulator(); if (iterator_type == IteratorType::kAsync) {
execution_control()->AsyncReturnAccumulator();
} else {
execution_control()->ReturnAccumulator();
}
} }
} }
...@@ -2870,8 +2887,16 @@ void BytecodeGenerator::VisitYieldStar(YieldStar* expr) { ...@@ -2870,8 +2887,16 @@ void BytecodeGenerator::VisitYieldStar(YieldStar* expr) {
.JumpIfNull(throw_throw_method_missing.New()) .JumpIfNull(throw_throw_method_missing.New())
.CallProperty( .CallProperty(
iterator_return, RegisterList(iterator), iterator_return, RegisterList(iterator),
feedback_index(expr->call_iterator_return_slot2())) feedback_index(expr->call_iterator_return_slot2()));
.JumpIfJSReceiver(throw_throw_method_missing.New())
if (iterator_type == IteratorType::kAsync) {
// For async generators, await the result of the .return() call.
BuildAwait(expr->await_iterator_close_suspend_id());
builder()->StoreAccumulatorInRegister(output);
}
builder()
->JumpIfJSReceiver(throw_throw_method_missing.New())
.CallRuntime(Runtime::kThrowIteratorResultNotAnObject, output); .CallRuntime(Runtime::kThrowIteratorResultNotAnObject, output);
throw_throw_method_missing.Bind(builder()); throw_throw_method_missing.Bind(builder());
...@@ -2882,6 +2907,11 @@ void BytecodeGenerator::VisitYieldStar(YieldStar* expr) { ...@@ -2882,6 +2907,11 @@ void BytecodeGenerator::VisitYieldStar(YieldStar* expr) {
after_switch.Bind(builder()); after_switch.Bind(builder());
} }
if (iterator_type == IteratorType::kAsync) {
// Await the result of the method invocation.
BuildAwait(expr->await_delegated_iterator_output_suspend_id());
}
// Check that output is an object. // Check that output is an object.
BytecodeLabel check_if_done; BytecodeLabel check_if_done;
builder() builder()
...@@ -2898,7 +2928,27 @@ void BytecodeGenerator::VisitYieldStar(YieldStar* expr) { ...@@ -2898,7 +2928,27 @@ void BytecodeGenerator::VisitYieldStar(YieldStar* expr) {
loop.BreakIfTrue(ToBooleanMode::kConvertToBoolean); loop.BreakIfTrue(ToBooleanMode::kConvertToBoolean);
// Suspend the current generator. // Suspend the current generator.
builder()->LoadAccumulatorWithRegister(output); if (iterator_type == IteratorType::kNormal) {
builder()->LoadAccumulatorWithRegister(output);
} else {
RegisterAllocationScope register_scope(this);
DCHECK(iterator_type == IteratorType::kAsync);
// If generatorKind is async, perform AsyncGeneratorYield(output.value),
// which will await `output.value` before resolving the current
// AsyncGeneratorRequest's promise.
builder()->LoadNamedProperty(
output, ast_string_constants()->value_string(),
feedback_index(expr->load_output_value_slot()));
RegisterList args = register_allocator()->NewRegisterList(3);
builder()
->MoveRegister(generator_object(), args[0]) // generator
.StoreAccumulatorInRegister(args[1]) // value
.LoadBoolean(catch_prediction() != HandlerTable::ASYNC_AWAIT)
.StoreAccumulatorInRegister(args[2]) // is_caught
.CallRuntime(Runtime::kInlineAsyncGeneratorYield, args);
}
BuildSuspendPoint(expr->suspend_id()); BuildSuspendPoint(expr->suspend_id());
builder()->StoreAccumulatorInRegister(input); builder()->StoreAccumulatorInRegister(input);
builder() builder()
...@@ -2923,7 +2973,11 @@ void BytecodeGenerator::VisitYieldStar(YieldStar* expr) { ...@@ -2923,7 +2973,11 @@ void BytecodeGenerator::VisitYieldStar(YieldStar* expr) {
.CompareOperation(Token::EQ_STRICT, resume_mode) .CompareOperation(Token::EQ_STRICT, resume_mode)
.JumpIfFalse(ToBooleanMode::kAlreadyBoolean, &completion_is_output_value) .JumpIfFalse(ToBooleanMode::kAlreadyBoolean, &completion_is_output_value)
.LoadAccumulatorWithRegister(output_value); .LoadAccumulatorWithRegister(output_value);
execution_control()->ReturnAccumulator(); if (iterator_type == IteratorType::kAsync) {
execution_control()->AsyncReturnAccumulator();
} else {
execution_control()->ReturnAccumulator();
}
builder()->Bind(&completion_is_output_value); builder()->Bind(&completion_is_output_value);
BuildIncrementBlockCoverageCounterIfEnabled(expr, BuildIncrementBlockCoverageCounterIfEnabled(expr,
......
...@@ -2952,7 +2952,9 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseYieldExpression( ...@@ -2952,7 +2952,9 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseYieldExpression(
} }
if (delegating) { if (delegating) {
return impl()->RewriteYieldStar(expression, pos); ExpressionT yieldstar = factory()->NewYieldStar(expression, pos);
impl()->RecordSuspendSourceRange(yieldstar, PositionAfterSemicolon());
return yieldstar;
} }
// Hackily disambiguate o from o.next and o [Symbol.iterator](). // Hackily disambiguate o from o.next and o [Symbol.iterator]().
......
This diff is collapsed.
...@@ -599,8 +599,6 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) { ...@@ -599,8 +599,6 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) {
Block* block, Block* block,
Expression* return_value, bool* ok); Expression* return_value, bool* ok);
Expression* RewriteYieldStar(Expression* expression, int pos);
void AddArrowFunctionFormalParameters(ParserFormalParameters* parameters, void AddArrowFunctionFormalParameters(ParserFormalParameters* parameters,
Expression* params, int end_pos, Expression* params, int end_pos,
bool* ok); bool* ok);
......
...@@ -653,6 +653,9 @@ class PreParserFactory { ...@@ -653,6 +653,9 @@ class PreParserFactory {
PreParserExpression NewAwait(PreParserExpression expression, int pos) { PreParserExpression NewAwait(PreParserExpression expression, int pos) {
return PreParserExpression::Default(); return PreParserExpression::Default();
} }
PreParserExpression NewYieldStar(PreParserExpression iterable, int pos) {
return PreParserExpression::Default();
}
PreParserExpression NewConditional(PreParserExpression condition, PreParserExpression NewConditional(PreParserExpression condition,
PreParserExpression then_expression, PreParserExpression then_expression,
PreParserExpression else_expression, PreParserExpression else_expression,
...@@ -1031,10 +1034,6 @@ class PreParser : public ParserBase<PreParser> { ...@@ -1031,10 +1034,6 @@ class PreParser : public ParserBase<PreParser> {
PreParserStatement block, PreParserStatement block,
PreParserExpression return_value, PreParserExpression return_value,
bool* ok) {} bool* ok) {}
V8_INLINE PreParserExpression RewriteYieldStar(PreParserExpression expression,
int pos) {
return PreParserExpression::Default();
}
V8_INLINE void RewriteNonPattern(bool* ok) { ValidateExpression(ok); } V8_INLINE void RewriteNonPattern(bool* ok) { ValidateExpression(ok); }
void DeclareAndInitializeVariables( void DeclareAndInitializeVariables(
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment