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