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> {
template <typename Node>
void ReserveFeedbackSlots(Node* node) {
node->AssignFeedbackSlots(properties_.get_spec(), language_mode_,
&slot_cache_);
function_kind_, &slot_cache_);
}
class LanguageModeScope {
......@@ -198,7 +198,12 @@ void AstNumberingVisitor::VisitSuspend(Suspend* node) {
void AstNumberingVisitor::VisitYield(Yield* node) { VisitSuspend(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);
}
......
......@@ -246,6 +246,7 @@ static void AssignVectorSlots(Expression* expr, FeedbackVectorSpec* spec,
void ForInStatement::AssignFeedbackSlots(FeedbackVectorSpec* spec,
LanguageMode language_mode,
FunctionKind kind,
FeedbackSlotCache* cache) {
AssignVectorSlots(each(), spec, language_mode, &each_slot_);
for_in_feedback_slot_ = spec->AddGeneralSlot();
......@@ -261,12 +262,14 @@ Assignment::Assignment(NodeType node_type, Token::Value op, Expression* target,
void Assignment::AssignFeedbackSlots(FeedbackVectorSpec* spec,
LanguageMode language_mode,
FunctionKind kind,
FeedbackSlotCache* cache) {
AssignVectorSlots(target(), spec, language_mode, &slot_);
}
void CountOperation::AssignFeedbackSlots(FeedbackVectorSpec* spec,
LanguageMode language_mode,
FunctionKind kind,
FeedbackSlotCache* cache) {
AssignVectorSlots(expression(), spec, language_mode, &slot_);
// Assign a slot to collect feedback about binary operations. Used only in
......@@ -375,6 +378,7 @@ ClassLiteralProperty::ClassLiteralProperty(Expression* key, Expression* value,
void ClassLiteral::AssignFeedbackSlots(FeedbackVectorSpec* spec,
LanguageMode language_mode,
FunctionKind kind,
FeedbackSlotCache* cache) {
// This logic that computes the number of slots needed for vector store
// ICs must mirror BytecodeGenerator::VisitClassLiteral.
......@@ -412,8 +416,9 @@ bool ObjectLiteral::Property::emit_store() const { return emit_store_; }
void ObjectLiteral::AssignFeedbackSlots(FeedbackVectorSpec* spec,
LanguageMode language_mode,
FunctionKind kind,
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
// ics must mirror FullCodeGenerator::VisitObjectLiteral.
......@@ -770,8 +775,9 @@ void ArrayLiteral::RewindSpreads() {
void ArrayLiteral::AssignFeedbackSlots(FeedbackVectorSpec* spec,
LanguageMode language_mode,
FunctionKind kind,
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
// ics must mirror FullCodeGenerator::VisitArrayLiteral.
......@@ -835,6 +841,7 @@ void MaterializedLiteral::BuildConstants(Isolate* isolate) {
void BinaryOperation::AssignFeedbackSlots(FeedbackVectorSpec* spec,
LanguageMode language_mode,
FunctionKind kind,
FeedbackSlotCache* cache) {
// Feedback vector slot is only used by interpreter for binary operations.
// Full-codegen uses AstId to record type feedback.
......@@ -881,6 +888,7 @@ static bool IsTypeof(Expression* expr) {
void CompareOperation::AssignFeedbackSlots(FeedbackVectorSpec* spec,
LanguageMode language_mode,
FunctionKind kind,
FeedbackSlotCache* cache_) {
// Feedback vector slot is only used by interpreter for binary operations.
// Full-codegen uses AstId to record type feedback.
......@@ -1022,7 +1030,7 @@ bool Expression::IsMonomorphic() const {
}
void Call::AssignFeedbackSlots(FeedbackVectorSpec* spec,
LanguageMode language_mode,
LanguageMode language_mode, FunctionKind kind,
FeedbackSlotCache* cache) {
ic_slot_ = spec->AddCallICSlot();
}
......@@ -1060,6 +1068,7 @@ CaseClause::CaseClause(Expression* label, ZoneList<Statement*>* statements,
void CaseClause::AssignFeedbackSlots(FeedbackVectorSpec* spec,
LanguageMode language_mode,
FunctionKind kind,
FeedbackSlotCache* cache) {
feedback_slot_ = spec->AddInterpreterCompareICSlot();
}
......
This diff is collapsed.
......@@ -2727,6 +2727,7 @@ void BytecodeGenerator::VisitYield(Yield* expr) {
// let iteratorReturn = iterator.return;
// if (!IS_NULL_OR_UNDEFINED(iteratorReturn)) {
// output = %_Call(iteratorReturn, iterator);
// if (IS_ASYNC_GENERATOR) output = await output;
// if (!IS_RECEIVER(output)) %ThrowIterResultNotAnObject(output);
// }
// throw MakeTypeError(kThrowMethodMissing);
......@@ -2734,11 +2735,18 @@ void BytecodeGenerator::VisitYield(Yield* expr) {
// output = %_Call(iteratorThrow, iterator, input);
// break;
// }
//
// if (IS_ASYNC_GENERATOR) output = await output;
// if (!IS_RECEIVER(output)) %ThrowIterResultNotAnObject(output);
// if (output.done) break;
//
// // From the generator to its user:
// // 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);
// resumeMode = %GeneratorGetResumeMode();
// }
......@@ -2749,11 +2757,11 @@ void BytecodeGenerator::VisitYield(Yield* expr) {
// output.value
// }
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 resume_mode = register_allocator()->NewRegister();
IteratorType iterator_type = IsAsyncGeneratorFunction(function_kind())
? IteratorType::kAsync
: IteratorType::kNormal;
{
RegisterAllocationScope register_scope(this);
......@@ -2761,10 +2769,12 @@ void BytecodeGenerator::VisitYieldStar(YieldStar* expr) {
RegisterList iterator_and_input = register_allocator()->NewRegisterList(2);
Register iterator = iterator_and_input[0];
BuildGetIterator(expr->expression(), IteratorType::kNormal,
BuildGetIterator(expr->expression(), iterator_type,
expr->load_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);
Register input = iterator_and_input[1];
builder()->LoadUndefined().StoreAccumulatorInRegister(input);
......@@ -2776,8 +2786,11 @@ void BytecodeGenerator::VisitYieldStar(YieldStar* expr) {
// This loop builder does not construct counters as the loop is not
// visible to the user, and we therefore neither pass the block coverage
// 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);
VisitIterationHeader(expr->suspend_id(), 1, &loop);
VisitIterationHeader(expr->suspend_id(), expr->suspend_count(), &loop);
{
BytecodeLabels after_switch(zone());
......@@ -2827,7 +2840,11 @@ void BytecodeGenerator::VisitYieldStar(YieldStar* expr) {
return_input.Bind(builder());
{
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) {
.JumpIfNull(throw_throw_method_missing.New())
.CallProperty(
iterator_return, RegisterList(iterator),
feedback_index(expr->call_iterator_return_slot2()))
.JumpIfJSReceiver(throw_throw_method_missing.New())
feedback_index(expr->call_iterator_return_slot2()));
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);
throw_throw_method_missing.Bind(builder());
......@@ -2882,6 +2907,11 @@ void BytecodeGenerator::VisitYieldStar(YieldStar* expr) {
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.
BytecodeLabel check_if_done;
builder()
......@@ -2898,7 +2928,27 @@ void BytecodeGenerator::VisitYieldStar(YieldStar* expr) {
loop.BreakIfTrue(ToBooleanMode::kConvertToBoolean);
// 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());
builder()->StoreAccumulatorInRegister(input);
builder()
......@@ -2923,7 +2973,11 @@ void BytecodeGenerator::VisitYieldStar(YieldStar* expr) {
.CompareOperation(Token::EQ_STRICT, resume_mode)
.JumpIfFalse(ToBooleanMode::kAlreadyBoolean, &completion_is_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);
BuildIncrementBlockCoverageCounterIfEnabled(expr,
......
......@@ -2952,7 +2952,9 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseYieldExpression(
}
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]().
......
This diff is collapsed.
......@@ -599,8 +599,6 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) {
Block* block,
Expression* return_value, bool* ok);
Expression* RewriteYieldStar(Expression* expression, int pos);
void AddArrowFunctionFormalParameters(ParserFormalParameters* parameters,
Expression* params, int end_pos,
bool* ok);
......
......@@ -653,6 +653,9 @@ class PreParserFactory {
PreParserExpression NewAwait(PreParserExpression expression, int pos) {
return PreParserExpression::Default();
}
PreParserExpression NewYieldStar(PreParserExpression iterable, int pos) {
return PreParserExpression::Default();
}
PreParserExpression NewConditional(PreParserExpression condition,
PreParserExpression then_expression,
PreParserExpression else_expression,
......@@ -1031,10 +1034,6 @@ class PreParser : public ParserBase<PreParser> {
PreParserStatement block,
PreParserExpression return_value,
bool* ok) {}
V8_INLINE PreParserExpression RewriteYieldStar(PreParserExpression expression,
int pos) {
return PreParserExpression::Default();
}
V8_INLINE void RewriteNonPattern(bool* ok) { ValidateExpression(ok); }
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