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

[async-iteration] implement spec update for yield* in async generators

https://github.com/tc39/proposal-async-iteration/commit/e3246ad69cc6f83b34bdd3451c3c6abce37fd1f3
removed some redundancies in yield and yield*.

In particular:
- AsyncGeneratorRawYield becomes unnecessary, and is deleted in this CL
- Parser::RewriteYieldStar() is updated to perform the IteratorValue() algorithm as appropriate

BUG=v8:6187, v8:5855
R=rmcilroy@chromium.org, adamk@chromium.org, littledan@chromium.org, vogelheim@chromium.org

Change-Id: I05e8429b9cbd4531c330ee53a05656b90162064c
Reviewed-on: https://chromium-review.googlesource.com/471806Reviewed-by: 's avatarRoss McIlroy <rmcilroy@chromium.org>
Reviewed-by: 's avatarGeorg Neis <neis@chromium.org>
Reviewed-by: 's avatarDaniel Vogelheim <vogelheim@chromium.org>
Commit-Queue: Caitlin Potter <caitp@igalia.com>
Cr-Commit-Position: refs/heads/master@{#44649}
parent 38c3b71c
......@@ -1416,12 +1416,6 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
InstallWithIntrinsicDefaultProto(isolate, yield,
Context::ASYNC_GENERATOR_YIELD);
Handle<JSFunction> raw_yield =
SimpleCreateFunction(isolate, factory->empty_string(),
Builtins::kAsyncGeneratorRawYield, 2, false);
InstallWithIntrinsicDefaultProto(isolate, raw_yield,
Context::ASYNC_GENERATOR_RAW_YIELD);
Handle<Code> code =
isolate->builtins()->AsyncGeneratorAwaitResolveClosure();
Handle<SharedFunctionInfo> info =
......
......@@ -378,50 +378,6 @@ TF_BUILTIN(AsyncGeneratorYield, AsyncGeneratorBuiltinsAssembler) {
Return(UndefinedConstant());
}
TF_BUILTIN(AsyncGeneratorRawYield, AsyncGeneratorBuiltinsAssembler) {
Node* const generator = Parameter(Descriptor::kReceiver);
Node* const iter_result = Parameter(Descriptor::kValue);
Node* const context = Parameter(Descriptor::kContext);
CSA_ASSERT_JS_ARGC_EQ(this, 1);
CSA_SLOW_ASSERT(this,
HasInstanceType(generator, JS_ASYNC_GENERATOR_OBJECT_TYPE));
CSA_ASSERT(this, IsGeneratorNotSuspendedForAwait(generator));
VARIABLE(var_value, MachineRepresentation::kTagged);
VARIABLE(var_done, MachineRepresentation::kTagged);
// RawYield is used for yield*, and values sent to yield* are always
// iterator result objects.
Label if_slow(this), async_generator_resolve(this);
GotoIfNot(IsFastJSIterResult(context, iter_result), &if_slow);
var_value.Bind(LoadObjectField(iter_result, JSIteratorResult::kValueOffset));
var_done.Bind(LoadObjectField(iter_result, JSIteratorResult::kDoneOffset));
Goto(&async_generator_resolve);
BIND(&if_slow);
{
var_value.Bind(
GetProperty(context, iter_result, factory()->value_string()));
Node* const done =
GetProperty(context, iter_result, factory()->done_string());
var_done.Bind(Select(
IsBoolean(done), [=]() { return done; },
[=]() { return CallBuiltin(Builtins::kToBoolean, context, done); },
MachineRepresentation::kTagged));
Goto(&async_generator_resolve);
}
BIND(&async_generator_resolve);
Node* const value = var_value.value();
Node* const done = var_done.value();
CallBuiltin(Builtins::kAsyncGeneratorResolve, context, generator, value,
done);
Return(UndefinedConstant());
}
TF_BUILTIN(AsyncGeneratorAwaitResolveClosure, AsyncGeneratorBuiltinsAssembler) {
Node* value = Parameter(Descriptor::kValue);
Node* context = Parameter(Descriptor::kContext);
......
......@@ -956,7 +956,6 @@ namespace internal {
/* resume behaviour specific to Async Generators. Internal / not exposed */ \
/* to JS code. */ \
TFJ(AsyncGeneratorYield, 1, kValue) \
TFJ(AsyncGeneratorRawYield, 1, kValue) \
\
/* Async-from-Sync Iterator */ \
\
......
......@@ -34,64 +34,63 @@ enum ContextLookupFlags {
// must always be allocated via Heap::AllocateContext() or
// Factory::NewContext.
#define NATIVE_CONTEXT_INTRINSIC_FUNCTIONS(V) \
V(ASYNC_FUNCTION_AWAIT_CAUGHT_INDEX, JSFunction, \
async_function_await_caught) \
V(ASYNC_FUNCTION_AWAIT_UNCAUGHT_INDEX, JSFunction, \
async_function_await_uncaught) \
V(ASYNC_FUNCTION_PROMISE_CREATE_INDEX, JSFunction, \
async_function_promise_create) \
V(ASYNC_FUNCTION_PROMISE_RELEASE_INDEX, JSFunction, \
async_function_promise_release) \
V(IS_ARRAYLIKE, JSFunction, is_arraylike) \
V(GENERATOR_NEXT_INTERNAL, JSFunction, generator_next_internal) \
V(GET_TEMPLATE_CALL_SITE_INDEX, JSFunction, get_template_call_site) \
V(MAKE_ERROR_INDEX, JSFunction, make_error) \
V(MAKE_RANGE_ERROR_INDEX, JSFunction, make_range_error) \
V(MAKE_SYNTAX_ERROR_INDEX, JSFunction, make_syntax_error) \
V(MAKE_TYPE_ERROR_INDEX, JSFunction, make_type_error) \
V(MAKE_URI_ERROR_INDEX, JSFunction, make_uri_error) \
V(OBJECT_CREATE, JSFunction, object_create) \
V(OBJECT_DEFINE_PROPERTIES, JSFunction, object_define_properties) \
V(OBJECT_DEFINE_PROPERTY, JSFunction, object_define_property) \
V(OBJECT_FREEZE, JSFunction, object_freeze) \
V(OBJECT_GET_PROTOTYPE_OF, JSFunction, object_get_prototype_of) \
V(OBJECT_IS_EXTENSIBLE, JSFunction, object_is_extensible) \
V(OBJECT_IS_FROZEN, JSFunction, object_is_frozen) \
V(OBJECT_IS_SEALED, JSFunction, object_is_sealed) \
V(OBJECT_KEYS, JSFunction, object_keys) \
V(REGEXP_INTERNAL_MATCH, JSFunction, regexp_internal_match) \
V(REFLECT_APPLY_INDEX, JSFunction, reflect_apply) \
V(REFLECT_CONSTRUCT_INDEX, JSFunction, reflect_construct) \
V(REFLECT_DEFINE_PROPERTY_INDEX, JSFunction, reflect_define_property) \
V(REFLECT_DELETE_PROPERTY_INDEX, JSFunction, reflect_delete_property) \
V(SPREAD_ARGUMENTS_INDEX, JSFunction, spread_arguments) \
V(SPREAD_ITERABLE_INDEX, JSFunction, spread_iterable) \
V(TYPED_ARRAY_CONSTRUCT_BY_ARRAY_BUFFER_INDEX, JSFunction, \
typed_array_construct_by_array_buffer) \
V(TYPED_ARRAY_CONSTRUCT_BY_ARRAY_LIKE_INDEX, JSFunction, \
typed_array_construct_by_array_like) \
V(TYPED_ARRAY_CONSTRUCT_BY_LENGTH_INDEX, JSFunction, \
typed_array_construct_by_length) \
V(TYPED_ARRAY_INITIALIZE_INDEX, JSFunction, typed_array_initialize) \
V(TYPED_ARRAY_SET_FROM_ARRAY_LIKE, JSFunction, \
typed_array_set_from_array_like) \
V(MATH_FLOOR_INDEX, JSFunction, math_floor) \
V(MATH_POW_INDEX, JSFunction, math_pow) \
V(NEW_PROMISE_CAPABILITY_INDEX, JSFunction, new_promise_capability) \
V(PROMISE_INTERNAL_CONSTRUCTOR_INDEX, JSFunction, \
promise_internal_constructor) \
V(PROMISE_INTERNAL_REJECT_INDEX, JSFunction, promise_internal_reject) \
V(IS_PROMISE_INDEX, JSFunction, is_promise) \
V(PROMISE_RESOLVE_INDEX, JSFunction, promise_resolve) \
V(PROMISE_THEN_INDEX, JSFunction, promise_then) \
V(PROMISE_HANDLE_INDEX, JSFunction, promise_handle) \
V(PROMISE_HANDLE_REJECT_INDEX, JSFunction, promise_handle_reject) \
V(ASYNC_GENERATOR_AWAIT_CAUGHT, JSFunction, async_generator_await_caught) \
V(ASYNC_GENERATOR_AWAIT_UNCAUGHT, JSFunction, \
async_generator_await_uncaught) \
V(ASYNC_GENERATOR_YIELD, JSFunction, async_generator_yield) \
V(ASYNC_GENERATOR_RAW_YIELD, JSFunction, async_generator_raw_yield)
#define NATIVE_CONTEXT_INTRINSIC_FUNCTIONS(V) \
V(ASYNC_FUNCTION_AWAIT_CAUGHT_INDEX, JSFunction, \
async_function_await_caught) \
V(ASYNC_FUNCTION_AWAIT_UNCAUGHT_INDEX, JSFunction, \
async_function_await_uncaught) \
V(ASYNC_FUNCTION_PROMISE_CREATE_INDEX, JSFunction, \
async_function_promise_create) \
V(ASYNC_FUNCTION_PROMISE_RELEASE_INDEX, JSFunction, \
async_function_promise_release) \
V(IS_ARRAYLIKE, JSFunction, is_arraylike) \
V(GENERATOR_NEXT_INTERNAL, JSFunction, generator_next_internal) \
V(GET_TEMPLATE_CALL_SITE_INDEX, JSFunction, get_template_call_site) \
V(MAKE_ERROR_INDEX, JSFunction, make_error) \
V(MAKE_RANGE_ERROR_INDEX, JSFunction, make_range_error) \
V(MAKE_SYNTAX_ERROR_INDEX, JSFunction, make_syntax_error) \
V(MAKE_TYPE_ERROR_INDEX, JSFunction, make_type_error) \
V(MAKE_URI_ERROR_INDEX, JSFunction, make_uri_error) \
V(OBJECT_CREATE, JSFunction, object_create) \
V(OBJECT_DEFINE_PROPERTIES, JSFunction, object_define_properties) \
V(OBJECT_DEFINE_PROPERTY, JSFunction, object_define_property) \
V(OBJECT_FREEZE, JSFunction, object_freeze) \
V(OBJECT_GET_PROTOTYPE_OF, JSFunction, object_get_prototype_of) \
V(OBJECT_IS_EXTENSIBLE, JSFunction, object_is_extensible) \
V(OBJECT_IS_FROZEN, JSFunction, object_is_frozen) \
V(OBJECT_IS_SEALED, JSFunction, object_is_sealed) \
V(OBJECT_KEYS, JSFunction, object_keys) \
V(REGEXP_INTERNAL_MATCH, JSFunction, regexp_internal_match) \
V(REFLECT_APPLY_INDEX, JSFunction, reflect_apply) \
V(REFLECT_CONSTRUCT_INDEX, JSFunction, reflect_construct) \
V(REFLECT_DEFINE_PROPERTY_INDEX, JSFunction, reflect_define_property) \
V(REFLECT_DELETE_PROPERTY_INDEX, JSFunction, reflect_delete_property) \
V(SPREAD_ARGUMENTS_INDEX, JSFunction, spread_arguments) \
V(SPREAD_ITERABLE_INDEX, JSFunction, spread_iterable) \
V(TYPED_ARRAY_CONSTRUCT_BY_ARRAY_BUFFER_INDEX, JSFunction, \
typed_array_construct_by_array_buffer) \
V(TYPED_ARRAY_CONSTRUCT_BY_ARRAY_LIKE_INDEX, JSFunction, \
typed_array_construct_by_array_like) \
V(TYPED_ARRAY_CONSTRUCT_BY_LENGTH_INDEX, JSFunction, \
typed_array_construct_by_length) \
V(TYPED_ARRAY_INITIALIZE_INDEX, JSFunction, typed_array_initialize) \
V(TYPED_ARRAY_SET_FROM_ARRAY_LIKE, JSFunction, \
typed_array_set_from_array_like) \
V(MATH_FLOOR_INDEX, JSFunction, math_floor) \
V(MATH_POW_INDEX, JSFunction, math_pow) \
V(NEW_PROMISE_CAPABILITY_INDEX, JSFunction, new_promise_capability) \
V(PROMISE_INTERNAL_CONSTRUCTOR_INDEX, JSFunction, \
promise_internal_constructor) \
V(PROMISE_INTERNAL_REJECT_INDEX, JSFunction, promise_internal_reject) \
V(IS_PROMISE_INDEX, JSFunction, is_promise) \
V(PROMISE_RESOLVE_INDEX, JSFunction, promise_resolve) \
V(PROMISE_THEN_INDEX, JSFunction, promise_then) \
V(PROMISE_HANDLE_INDEX, JSFunction, promise_handle) \
V(PROMISE_HANDLE_REJECT_INDEX, JSFunction, promise_handle_reject) \
V(ASYNC_GENERATOR_AWAIT_CAUGHT, JSFunction, async_generator_await_caught) \
V(ASYNC_GENERATOR_AWAIT_UNCAUGHT, JSFunction, \
async_generator_await_uncaught) \
V(ASYNC_GENERATOR_YIELD, JSFunction, async_generator_yield)
#define NATIVE_CONTEXT_IMPORTED_FIELDS(V) \
V(ARRAY_CONCAT_INDEX, JSFunction, array_concat) \
......
......@@ -2396,16 +2396,12 @@ void BytecodeGenerator::VisitSuspend(Suspend* expr) {
// to AsyncGeneratorResolve(), implemented via the runtime call below.
RegisterList args = register_allocator()->NewRegisterList(2);
int context_index = expr->is_yield_star()
? Context::ASYNC_GENERATOR_RAW_YIELD
: Context::ASYNC_GENERATOR_YIELD;
// Async GeneratorYield:
// AsyncGeneratorYield:
// perform AsyncGeneratorResolve(<generator>, <value>, false).
builder()
->MoveRegister(generator, args[0])
.MoveRegister(value, args[1])
.CallJSRuntime(context_index, args);
.CallJSRuntime(Context::ASYNC_GENERATOR_YIELD, args);
} else {
builder()->LoadAccumulatorWithRegister(value);
}
......
......@@ -4704,10 +4704,26 @@ Expression* Parser::RewriteYieldStar(Expression* generator,
// while (true) { ... }
// Already defined earlier: WhileStatement* loop = ...
{
Block* loop_body = factory()->NewBlock(nullptr, 4, false, nopos);
Block* loop_body = factory()->NewBlock(nullptr, 5, false, nopos);
loop_body->statements()->Add(switch_mode, zone());
loop_body->statements()->Add(if_done, zone());
loop_body->statements()->Add(set_mode_return, zone());
if (is_async_generator()) {
// AsyncGeneratorYield does not yield the original iterator result,
// unlike sync generators. Do `output = output.value`
VariableProxy* output_proxy = factory()->NewVariableProxy(var_output);
Expression* literal = factory()->NewStringLiteral(
ast_value_factory()->value_string(), nopos);
Assignment* assign = factory()->NewAssignment(
Token::ASSIGN, output_proxy,
factory()->NewProperty(factory()->NewVariableProxy(var_output),
literal, nopos),
nopos);
loop_body->statements()->Add(
factory()->NewExpressionStatement(assign, nopos), zone());
}
loop_body->statements()->Add(try_finally, zone());
loop->Initialize(factory()->NewBooleanLiteral(true, nopos), loop_body);
......
......@@ -1658,3 +1658,73 @@ assertEqualsAsync({ value: undefined, done: true }, () => it.next("x"));
assertEqualsAsync({ value: "nores", done: true },
() => it.return("nores"));
assertThrowsAsync(() => it.throw(new MyError("nores")), MyError, "nores");
// ----------------------------------------------------------------------------
// Simple yield*:
log = [];
async function* asyncGeneratorYieldStar1() {
yield* {
get [Symbol.asyncIterator]() {
log.push({ name: "get @@asyncIterator" });
return (...args) => {
log.push({ name: "call @@asyncIterator", args });
return this;
};
},
get [Symbol.iterator]() {
log.push({ name: "get @@iterator" });
return (...args) => {
log.push({ name: "call @@iterator", args });
return this;
}
},
get next() {
log.push({ name: "get next" });
return (...args) => {
log.push({ name: "call next", args });
return {
get then() {
log.push({ name: "get then" });
return null;
},
get value() {
log.push({ name: "get value" });
throw (exception = new MyError("AbruptValue!"));
},
get done() {
log.push({ name: "get done" });
return false;
}
};
}
},
get return() {
log.push({ name: "get return" });
return (...args) => {
log.push({ name: "call return", args });
return { value: args[0], done: true };
}
},
get throw() {
log.push({ name: "get throw" });
return (...args) => {
log.push({ name: "call throw", args });
throw args[0];
};
},
};
}
it = asyncGeneratorYieldStar1();
assertThrowsAsync(() => it.next(), MyError);
assertEquals([
{ name: "get @@asyncIterator" },
{ name: "call @@asyncIterator", args: [] },
{ name: "get next" },
{ name: "call next", args: [undefined] },
{ name: "get then" },
{ name: "get done" },
{ name: "get value" },
], log);
assertEqualsAsync({ value: undefined, done: true }, () => it.next());
......@@ -421,36 +421,6 @@
# https://bugs.chromium.org/p/v8/issues/detail?id=5601
'intl402/PluralRules/*': [SKIP],
# https://bugs.chromium.org/p/v8/issues/detail?id=5855
'language/expressions/async-generators/*': ['--harmony-async-iteration'],
'language/statements/async-generator/*': ['--harmony-async-iteration'],
# https://bugs.chromium.org/p/v8/issues/detail?id=6226
'language/expressions/async-generator/named-yield-star-async-next': [FAIL],
'language/expressions/async-generator/named-yield-star-async-return': [FAIL],
'language/expressions/async-generator/named-yield-star-async-throw': [FAIL],
'language/expressions/async-generator/yield-star-async-next': [FAIL],
'language/expressions/async-generator/yield-star-async-return': [FAIL],
'language/expressions/async-generator/yield-star-async-throw': [FAIL],
'language/expressions/class/async-gen-method-static-yield-star-async-next': [FAIL],
'language/expressions/class/async-gen-method-static-yield-star-async-return': [FAIL],
'language/expressions/class/async-gen-method-static-yield-star-async-throw': [FAIL],
'language/expressions/class/async-gen-method-yield-star-async-next': [FAIL],
'language/expressions/class/async-gen-method-yield-star-async-return': [FAIL],
'language/expressions/class/async-gen-method-yield-star-async-throw': [FAIL],
'language/expressions/object/method-definition/async-gen-yield-star-async-next': [FAIL],
'language/expressions/object/method-definition/async-gen-yield-star-async-return': [FAIL],
'language/expressions/object/method-definition/async-gen-yield-star-async-throw': [FAIL],
'language/statements/async-generator/yield-star-async-next': [FAIL],
'language/statements/async-generator/yield-star-async-return': [FAIL],
'language/statements/async-generator/yield-star-async-throw': [FAIL],
'language/statements/class/async-gen-method-static-yield-star-async-next': [FAIL],
'language/statements/class/async-gen-method-static-yield-star-async-return': [FAIL],
'language/statements/class/async-gen-method-static-yield-star-async-throw': [FAIL],
'language/statements/class/async-gen-method-yield-star-async-next': [FAIL],
'language/statements/class/async-gen-method-yield-star-async-return': [FAIL],
'language/statements/class/async-gen-method-yield-star-async-throw': [FAIL],
# https://bugs.chromium.org/p/v8/issues/detail?id=6242
'language/expressions/async-generator/named-yield-star-sync-next': [FAIL],
'language/expressions/async-generator/named-yield-star-sync-return': [FAIL],
......
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