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

Unified Diff: src/interpreter/bytecode-generator.cc

Issue 2622833002: WIP [esnext] implement async iteration proposal (Closed)
Patch Set: simplify AsyncIteratorValueUnwrap Created 3 years, 11 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
« no previous file with comments | « src/interpreter/bytecode-generator.h ('k') | src/interpreter/bytecodes.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/interpreter/bytecode-generator.cc
diff --git a/src/interpreter/bytecode-generator.cc b/src/interpreter/bytecode-generator.cc
index 7279f69d8a01c554e1b0b627f423c994331568f8..3bbe8da3067b3f6283e437eb19a99ce24fa02aca 100644
--- a/src/interpreter/bytecode-generator.cc
+++ b/src/interpreter/bytecode-generator.cc
@@ -585,6 +585,8 @@ BytecodeGenerator::BytecodeGenerator(CompilationInfo* info)
loop_depth_(0),
home_object_symbol_(info->isolate()->factory()->home_object_symbol()),
iterator_symbol_(info->isolate()->factory()->iterator_symbol()),
+ async_iterator_symbol_(
+ info->isolate()->factory()->async_iterator_symbol()),
empty_fixed_array_(info->isolate()->factory()->empty_fixed_array()) {
AstValueFactory* ast_value_factory = info->parse_info()->ast_value_factory();
const AstRawString* prototype_string = ast_value_factory->prototype_string();
@@ -2244,12 +2246,34 @@ void BytecodeGenerator::VisitYield(Yield* expr) {
Register generator = VisitForRegisterValue(expr->generator_object());
- // Save context, registers, and state. Then return.
- builder()
- ->LoadLiteral(Smi::FromInt(expr->yield_id()))
- .SuspendGenerator(generator)
- .LoadAccumulatorWithRegister(value)
- .Return(); // Hard return (ignore any finally blocks).
+ const bool kIsAsyncGenerator =
+ IsAsyncGeneratorFunction(scope()->function_kind());
+
+ if (kIsAsyncGenerator && expr->yield_id() > 0 &&
+ expr->yield_type() != Yield::kAwait) {
+ RegisterList args = register_allocator()->NewRegisterList(2);
+
+ int context_index = Context::ASYNC_GENERATOR_YIELD;
+ if (expr->yield_type() == Yield::kDelegate) {
+ // Avoid wrapping in iterator result for yield* yields
+ context_index = Context::ASYNC_GENERATOR_RAW_YIELD;
+ }
+
+ builder()
+ ->LoadLiteral(Smi::FromInt(expr->yield_id()))
+ .SuspendGenerator(generator, expr->yield_type())
+ .MoveRegister(generator, args[0])
+ .MoveRegister(value, args[1])
+ .CallJSRuntime(context_index, args)
+ .Return(); // Hard return (ignore any finally blocks).
+ } else {
+ // Save context, registers, and state. Then return.
+ builder()
+ ->LoadLiteral(Smi::FromInt(expr->yield_id()))
+ .SuspendGenerator(generator, expr->yield_type())
+ .LoadAccumulatorWithRegister(value)
+ .Return(); // Hard return (ignore any finally blocks).
+ }
builder()->Bind(&(generator_resume_points_[expr->yield_id()]));
// Upon resume, we continue here.
@@ -2264,9 +2288,17 @@ void BytecodeGenerator::VisitYield(Yield* expr) {
.StoreAccumulatorInRegister(generator_state_);
Register input = register_allocator()->NewRegister();
- builder()
- ->CallRuntime(Runtime::kInlineGeneratorGetInputOrDebugPos, generator)
- .StoreAccumulatorInRegister(input);
+ if (!kIsAsyncGenerator || expr->yield_type() != Yield::kAwait) {
+ builder()
+ ->CallRuntime(Runtime::kInlineGeneratorGetInputOrDebugPos, generator)
+ .StoreAccumulatorInRegister(input);
+ } else {
+ // When resuming from an Await expression, the sent value is in the
+ // await input slot.
+ builder()
+ ->CallRuntime(Runtime::kInlineAsyncGeneratorGetAwaitInput, generator)
+ .StoreAccumulatorInRegister(input);
+ }
Register resume_mode = register_allocator()->NewRegister();
builder()
@@ -2888,21 +2920,63 @@ void BytecodeGenerator::VisitGetIterator(GetIterator* expr) {
VisitForAccumulatorValue(expr->iterable());
- // Let method be GetMethod(obj, @@iterator).
- builder()
- ->StoreAccumulatorInRegister(obj)
- .LoadNamedProperty(obj, iterator_symbol(), feedback_index(load_slot))
- .StoreAccumulatorInRegister(method);
-
- // Let iterator be Call(method, obj).
- builder()->Call(method, args, feedback_index(call_slot),
- Call::NAMED_PROPERTY_CALL);
-
- // If Type(iterator) is not Object, throw a TypeError exception.
- BytecodeLabel no_type_error;
- builder()->JumpIfJSReceiver(&no_type_error);
- builder()->CallRuntime(Runtime::kThrowSymbolIteratorInvalid);
- builder()->Bind(&no_type_error);
+ if (expr->hint() == GetIterator::kAsync) {
+ FeedbackVectorSlot load_slot2 = expr->AsyncIteratorPropertyFeedbackSlot();
+ FeedbackVectorSlot call_slot2 = expr->AsyncIteratorCallFeedbackSlot();
+ Register tmp = register_allocator()->NewRegister();
+ // Set method to GetMethod(obj, @@asyncIterator)
+ builder()->StoreAccumulatorInRegister(obj).LoadNamedProperty(
+ obj, async_iterator_symbol(), feedback_index(load_slot2));
+
+ BytecodeLabel async_iterator_undefined, async_iterator_null, done;
+ builder()->JumpIfUndefined(&async_iterator_undefined);
+ builder()->JumpIfNull(&async_iterator_null);
+
+ // Let iterator be Call(method, obj)
+ builder()->StoreAccumulatorInRegister(method).Call(
+ method, args, feedback_index(call_slot), Call::NAMED_PROPERTY_CALL);
+
+ // If Type(iterator) is not Object, throw a TypeError exception.
+ builder()->JumpIfJSReceiver(&done);
+ builder()->CallRuntime(Runtime::kThrowSymbolAsyncIteratorInvalid);
+
+ builder()->Bind(&async_iterator_undefined);
+ builder()->Bind(&async_iterator_null);
+ // If method is undefined,
+ // Let syncMethod be GetMethod(obj, @@iterator)
+ builder()
+ ->LoadNamedProperty(obj, iterator_symbol(), feedback_index(load_slot))
+ .StoreAccumulatorInRegister(method);
+
+ // Let syncIterator be Call(syncMethod, obj)
+ builder()->Call(method, args, feedback_index(call_slot2),
+ Call::NAMED_PROPERTY_CALL);
+
+ // Return CreateAsyncFromSyncIterator(syncIterator)
+ RegisterList args = register_allocator()->NewRegisterList(1);
+ Register sync_iterator = args[0];
+ builder()
+ ->StoreAccumulatorInRegister(sync_iterator)
+ .CallRuntime(Runtime::kInlineCreateAsyncFromSyncIterator, args);
+
+ builder()->Bind(&done);
+ } else {
+ // Let method be GetMethod(obj, @@iterator).
+ builder()
+ ->StoreAccumulatorInRegister(obj)
+ .LoadNamedProperty(obj, iterator_symbol(), feedback_index(load_slot))
+ .StoreAccumulatorInRegister(method);
+
+ // Let iterator be Call(method, obj).
+ builder()->Call(method, args, feedback_index(call_slot),
+ Call::NAMED_PROPERTY_CALL);
+
+ // If Type(iterator) is not Object, throw a TypeError exception.
+ BytecodeLabel no_type_error;
+ builder()->JumpIfJSReceiver(&no_type_error);
+ builder()->CallRuntime(Runtime::kThrowSymbolIteratorInvalid);
+ builder()->Bind(&no_type_error);
+ }
}
void BytecodeGenerator::VisitThisFunction(ThisFunction* expr) {
« no previous file with comments | « src/interpreter/bytecode-generator.h ('k') | src/interpreter/bytecodes.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698