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) { |