Index: src/interpreter/bytecode-generator.cc |
diff --git a/src/interpreter/bytecode-generator.cc b/src/interpreter/bytecode-generator.cc |
index d0c35acae48ee430bde5ce2c7773c561fc2618a2..c029a132ff36a9737806ccc17a3f4feeddc746b8 100644 |
--- a/src/interpreter/bytecode-generator.cc |
+++ b/src/interpreter/bytecode-generator.cc |
@@ -603,6 +603,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()), |
prototype_string_(info->isolate()->factory()->prototype_string()), |
empty_fixed_array_(info->isolate()->factory()->empty_fixed_array()), |
undefined_string_( |
@@ -2933,8 +2935,8 @@ void BytecodeGenerator::VisitEmptyParentheses(EmptyParentheses* expr) { |
} |
void BytecodeGenerator::VisitGetIterator(GetIterator* expr) { |
- FeedbackVectorSlot load_slot = expr->IteratorPropertyFeedbackSlot(); |
- FeedbackVectorSlot call_slot = expr->IteratorCallFeedbackSlot(); |
+ FeedbackVectorSlot load_iter_slot = expr->IteratorPropertyFeedbackSlot(); |
+ FeedbackVectorSlot call_iter_slot = expr->IteratorCallFeedbackSlot(); |
RegisterList args = register_allocator()->NewRegisterList(1); |
Register method = register_allocator()->NewRegister(); |
@@ -2942,21 +2944,68 @@ 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() == IteratorType::kAsync) { |
+ FeedbackVectorSlot load_async_iter_slot = |
+ expr->AsyncIteratorPropertyFeedbackSlot(); |
+ FeedbackVectorSlot call_async_iter_slot = |
+ expr->AsyncIteratorCallFeedbackSlot(); |
+ |
+ // Set method to GetMethod(obj, @@asyncIterator) |
+ builder()->StoreAccumulatorInRegister(obj).LoadNamedProperty( |
+ obj, async_iterator_symbol(), feedback_index(load_async_iter_slot)); |
+ |
+ BytecodeLabel async_iterator_undefined, async_iterator_null, done; |
+ // TODO(ignition): Add a single opcode for JumpIfNullOrUndefined |
+ 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_async_iter_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_iter_slot)) |
+ .StoreAccumulatorInRegister(method); |
+ |
+ // Let syncIterator be Call(syncMethod, obj) |
+ builder()->Call(method, args, feedback_index(call_iter_slot), |
+ Call::NAMED_PROPERTY_CALL); |
+ |
+ // Return CreateAsyncFromSyncIterator(syncIterator) |
+ // alias `method` register as it's no longer used |
+ Register sync_iter = method; |
+ builder()->StoreAccumulatorInRegister(sync_iter).CallRuntime( |
+ Runtime::kInlineCreateAsyncFromSyncIterator, sync_iter); |
+ |
+ builder()->Bind(&done); |
+ } else { |
+ // Let method be GetMethod(obj, @@iterator). |
+ builder() |
+ ->StoreAccumulatorInRegister(obj) |
+ .LoadNamedProperty(obj, iterator_symbol(), |
+ feedback_index(load_iter_slot)) |
+ .StoreAccumulatorInRegister(method); |
+ |
+ // Let iterator be Call(method, obj). |
+ builder()->Call(method, args, feedback_index(call_iter_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) { |