 Chromium Code Reviews
 Chromium Code Reviews Issue 2622833002:
  WIP [esnext] implement async iteration proposal  (Closed)
    
  
    Issue 2622833002:
  WIP [esnext] implement async iteration proposal  (Closed) 
  | OLD | NEW | 
|---|---|
| 1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 the V8 project authors. All rights reserved. | 
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be | 
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. | 
| 4 | 4 | 
| 5 #include "src/interpreter/bytecode-generator.h" | 5 #include "src/interpreter/bytecode-generator.h" | 
| 6 | 6 | 
| 7 #include "src/ast/compile-time-value.h" | 7 #include "src/ast/compile-time-value.h" | 
| 8 #include "src/ast/scopes.h" | 8 #include "src/ast/scopes.h" | 
| 9 #include "src/builtins/builtins-constructor.h" | 9 #include "src/builtins/builtins-constructor.h" | 
| 10 #include "src/code-stubs.h" | 10 #include "src/code-stubs.h" | 
| (...skipping 567 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 578 function_literals_(0, info->zone()), | 578 function_literals_(0, info->zone()), | 
| 579 native_function_literals_(0, info->zone()), | 579 native_function_literals_(0, info->zone()), | 
| 580 execution_control_(nullptr), | 580 execution_control_(nullptr), | 
| 581 execution_context_(nullptr), | 581 execution_context_(nullptr), | 
| 582 execution_result_(nullptr), | 582 execution_result_(nullptr), | 
| 583 generator_resume_points_(info->literal()->yield_count(), info->zone()), | 583 generator_resume_points_(info->literal()->yield_count(), info->zone()), | 
| 584 generator_state_(), | 584 generator_state_(), | 
| 585 loop_depth_(0), | 585 loop_depth_(0), | 
| 586 home_object_symbol_(info->isolate()->factory()->home_object_symbol()), | 586 home_object_symbol_(info->isolate()->factory()->home_object_symbol()), | 
| 587 iterator_symbol_(info->isolate()->factory()->iterator_symbol()), | 587 iterator_symbol_(info->isolate()->factory()->iterator_symbol()), | 
| 588 async_iterator_symbol_( | |
| 589 info->isolate()->factory()->async_iterator_symbol()), | |
| 588 empty_fixed_array_(info->isolate()->factory()->empty_fixed_array()) { | 590 empty_fixed_array_(info->isolate()->factory()->empty_fixed_array()) { | 
| 589 AstValueFactory* ast_value_factory = info->parse_info()->ast_value_factory(); | 591 AstValueFactory* ast_value_factory = info->parse_info()->ast_value_factory(); | 
| 590 const AstRawString* prototype_string = ast_value_factory->prototype_string(); | 592 const AstRawString* prototype_string = ast_value_factory->prototype_string(); | 
| 591 ast_value_factory->Internalize(info->isolate()); | 593 ast_value_factory->Internalize(info->isolate()); | 
| 592 prototype_string_ = prototype_string->string(); | 594 prototype_string_ = prototype_string->string(); | 
| 593 undefined_string_ = ast_value_factory->undefined_string(); | 595 undefined_string_ = ast_value_factory->undefined_string(); | 
| 594 } | 596 } | 
| 595 | 597 | 
| 596 Handle<BytecodeArray> BytecodeGenerator::FinalizeBytecode(Isolate* isolate) { | 598 Handle<BytecodeArray> BytecodeGenerator::FinalizeBytecode(Isolate* isolate) { | 
| 597 AllocateDeferredConstants(); | 599 AllocateDeferredConstants(); | 
| (...skipping 1639 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2237 } | 2239 } | 
| 2238 } | 2240 } | 
| 2239 } | 2241 } | 
| 2240 | 2242 | 
| 2241 void BytecodeGenerator::VisitYield(Yield* expr) { | 2243 void BytecodeGenerator::VisitYield(Yield* expr) { | 
| 2242 builder()->SetExpressionPosition(expr); | 2244 builder()->SetExpressionPosition(expr); | 
| 2243 Register value = VisitForRegisterValue(expr->expression()); | 2245 Register value = VisitForRegisterValue(expr->expression()); | 
| 2244 | 2246 | 
| 2245 Register generator = VisitForRegisterValue(expr->generator_object()); | 2247 Register generator = VisitForRegisterValue(expr->generator_object()); | 
| 2246 | 2248 | 
| 2247 // Save context, registers, and state. Then return. | 2249 const bool kIsAsyncGenerator = | 
| 2248 builder() | 2250 IsAsyncGeneratorFunction(scope()->function_kind()); | 
| 2249 ->LoadLiteral(Smi::FromInt(expr->yield_id())) | 2251 | 
| 2250 .SuspendGenerator(generator) | 2252 if (kIsAsyncGenerator && expr->yield_id() > 0 && | 
| 2251 .LoadAccumulatorWithRegister(value) | 2253 expr->yield_type() != Yield::kAwait) { | 
| 2252 .Return(); // Hard return (ignore any finally blocks). | 2254 RegisterList args = register_allocator()->NewRegisterList(2); | 
| 2255 | |
| 2256 int context_index = Context::ASYNC_GENERATOR_YIELD; | |
| 2257 if (expr->yield_type() == Yield::kDelegate) { | |
| 2258 // Avoid wrapping in iterator result for yield* yields | |
| 2259 context_index = Context::ASYNC_GENERATOR_RAW_YIELD; | |
| 2260 } | |
| 2261 | |
| 2262 builder() | |
| 2263 ->LoadLiteral(Smi::FromInt(expr->yield_id())) | |
| 2264 .SuspendGenerator(generator) | |
| 2265 .MoveRegister(generator, args[0]) | |
| 2266 .MoveRegister(value, args[1]) | |
| 2267 .CallJSRuntime(context_index, args) | |
| 2268 .Return(); // Hard return (ignore any finally blocks). | |
| 2269 } else { | |
| 2270 // Save context, registers, and state. Then return. | |
| 2271 if (IsAsyncGeneratorFunction(scope()->function_kind()) && | |
| 2272 expr->yield_type() == Yield::kAwait) { | |
| 2273 // For Await expressions in async generators, store the original | |
| 2274 // generator input in the await input position, so it can be restored | |
| 2275 // later. The first Yield can never be an Await. | |
| 2276 DCHECK_GE(expr->yield_id(), 1); | |
| 2277 builder()->CallRuntime(Runtime::kInlineGeneratorSaveInputForAwait, | |
| 2278 generator); | |
| 2279 } | |
| 2280 | |
| 2281 builder() | |
| 2282 ->LoadLiteral(Smi::FromInt(expr->yield_id())) | |
| 2283 .SuspendGenerator(generator) | |
| 2284 .LoadAccumulatorWithRegister(value) | |
| 2285 .Return(); // Hard return (ignore any finally blocks). | |
| 2286 } | |
| 2253 | 2287 | 
| 2254 builder()->Bind(&(generator_resume_points_[expr->yield_id()])); | 2288 builder()->Bind(&(generator_resume_points_[expr->yield_id()])); | 
| 2255 // Upon resume, we continue here. | 2289 // Upon resume, we continue here. | 
| 2256 | 2290 | 
| 2257 { | 2291 { | 
| 2258 RegisterAllocationScope register_scope(this); | 2292 RegisterAllocationScope register_scope(this); | 
| 2259 | 2293 | 
| 2260 // Update state to indicate that we have finished resuming. Loop headers | 2294 // Update state to indicate that we have finished resuming. Loop headers | 
| 2261 // rely on this. | 2295 // rely on this. | 
| 2262 builder() | 2296 builder() | 
| 2263 ->LoadLiteral(Smi::FromInt(JSGeneratorObject::kGeneratorExecuting)) | 2297 ->LoadLiteral(Smi::FromInt(JSGeneratorObject::kGeneratorExecuting)) | 
| 2264 .StoreAccumulatorInRegister(generator_state_); | 2298 .StoreAccumulatorInRegister(generator_state_); | 
| 2265 | 2299 | 
| 2266 Register input = register_allocator()->NewRegister(); | 2300 Register input = register_allocator()->NewRegister(); | 
| 2267 builder() | 2301 if (!kIsAsyncGenerator || expr->yield_type() != Yield::kAwait) { | 
| 2268 ->CallRuntime(Runtime::kInlineGeneratorGetInputOrDebugPos, generator) | 2302 builder() | 
| 2269 .StoreAccumulatorInRegister(input); | 2303 ->CallRuntime(Runtime::kInlineGeneratorGetInputOrDebugPos, generator) | 
| 2304 .StoreAccumulatorInRegister(input); | |
| 2305 } else { | |
| 2306 // When resuming from an Await expression, the sent value is in the | |
| 2307 // await input slot. | |
| 2308 builder() | |
| 2309 ->CallRuntime(Runtime::kInlineGeneratorGetAwaitInput, generator) | |
| 
Dan Ehrenberg
2017/01/14 00:48:38
Nit: 'GeneratorGetAwaitInput' is a sort of funny n
 | |
| 2310 .StoreAccumulatorInRegister(input); | |
| 2311 } | |
| 2270 | 2312 | 
| 2271 Register resume_mode = register_allocator()->NewRegister(); | 2313 Register resume_mode = register_allocator()->NewRegister(); | 
| 2272 builder() | 2314 builder() | 
| 2273 ->CallRuntime(Runtime::kInlineGeneratorGetResumeMode, generator) | 2315 ->CallRuntime(Runtime::kInlineGeneratorGetResumeMode, generator) | 
| 2274 .StoreAccumulatorInRegister(resume_mode); | 2316 .StoreAccumulatorInRegister(resume_mode); | 
| 2275 | 2317 | 
| 2276 // Now dispatch on resume mode. | 2318 // Now dispatch on resume mode. | 
| 2277 | 2319 | 
| 2278 BytecodeLabel resume_with_next; | 2320 BytecodeLabel resume_with_next; | 
| 2279 BytecodeLabel resume_with_return; | 2321 BytecodeLabel resume_with_return; | 
| (...skipping 601 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2881 void BytecodeGenerator::VisitGetIterator(GetIterator* expr) { | 2923 void BytecodeGenerator::VisitGetIterator(GetIterator* expr) { | 
| 2882 FeedbackVectorSlot load_slot = expr->IteratorPropertyFeedbackSlot(); | 2924 FeedbackVectorSlot load_slot = expr->IteratorPropertyFeedbackSlot(); | 
| 2883 FeedbackVectorSlot call_slot = expr->IteratorCallFeedbackSlot(); | 2925 FeedbackVectorSlot call_slot = expr->IteratorCallFeedbackSlot(); | 
| 2884 | 2926 | 
| 2885 RegisterList args = register_allocator()->NewRegisterList(1); | 2927 RegisterList args = register_allocator()->NewRegisterList(1); | 
| 2886 Register method = register_allocator()->NewRegister(); | 2928 Register method = register_allocator()->NewRegister(); | 
| 2887 Register obj = args[0]; | 2929 Register obj = args[0]; | 
| 2888 | 2930 | 
| 2889 VisitForAccumulatorValue(expr->iterable()); | 2931 VisitForAccumulatorValue(expr->iterable()); | 
| 2890 | 2932 | 
| 2891 // Let method be GetMethod(obj, @@iterator). | 2933 if (expr->hint() == GetIterator::kAsync) { | 
| 2892 builder() | 2934 FeedbackVectorSlot load_slot2 = expr->AsyncIteratorPropertyFeedbackSlot(); | 
| 2893 ->StoreAccumulatorInRegister(obj) | 2935 FeedbackVectorSlot call_slot2 = expr->AsyncIteratorCallFeedbackSlot(); | 
| 2894 .LoadNamedProperty(obj, iterator_symbol(), feedback_index(load_slot)) | |
| 2895 .StoreAccumulatorInRegister(method); | |
| 2896 | 2936 | 
| 2897 // Let iterator be Call(method, obj). | 2937 // Set method to GetMethod(obj, @@asyncIterator) | 
| 2898 builder()->Call(method, args, feedback_index(call_slot), | 2938 builder()->StoreAccumulatorInRegister(obj).LoadNamedProperty( | 
| 2899 Call::NAMED_PROPERTY_CALL); | 2939 obj, async_iterator_symbol(), feedback_index(load_slot2)); | 
| 2900 | 2940 | 
| 2901 // If Type(iterator) is not Object, throw a TypeError exception. | 2941 BytecodeLabel create_async_from_sync, done; | 
| 2902 BytecodeLabel no_type_error; | 2942 builder()->JumpIfUndefined(&create_async_from_sync); | 
| 2903 builder()->JumpIfJSReceiver(&no_type_error); | 2943 | 
| 2904 builder()->CallRuntime(Runtime::kThrowSymbolIteratorInvalid); | 2944 // Let iterator be Call(method, obj) | 
| 2905 builder()->Bind(&no_type_error); | 2945 builder()->StoreAccumulatorInRegister(method).Call( | 
| 2946 method, args, feedback_index(call_slot), Call::NAMED_PROPERTY_CALL); | |
| 2947 | |
| 2948 // If Type(iterator) is not Object, throw a TypeError exception. | |
| 2949 builder()->JumpIfJSReceiver(&done); | |
| 2950 builder()->CallRuntime(Runtime::kThrowSymbolAsyncIteratorInvalid); | |
| 2951 | |
| 2952 builder()->Bind(&create_async_from_sync); | |
| 2953 // If method is undefined, | |
| 2954 // Let syncMethod be GetMethod(obj, @@iterator) | |
| 2955 builder() | |
| 2956 ->LoadNamedProperty(obj, iterator_symbol(), feedback_index(load_slot)) | |
| 2957 .StoreAccumulatorInRegister(method); | |
| 2958 | |
| 2959 // Let syncIterator be Call(syncMethod, obj) | |
| 2960 builder()->Call(method, args, feedback_index(call_slot2), | |
| 2961 Call::NAMED_PROPERTY_CALL); | |
| 2962 | |
| 2963 // Return CreateAsyncFromSyncIterator(syncIterator) | |
| 2964 RegisterList args = register_allocator()->NewRegisterList(1); | |
| 2965 Register sync_iterator = args[0]; | |
| 2966 builder() | |
| 2967 ->StoreAccumulatorInRegister(sync_iterator) | |
| 2968 .CallRuntime(Runtime::kInlineCreateAsyncFromSyncIterator, args); | |
| 2969 | |
| 2970 builder()->Bind(&done); | |
| 2971 } else { | |
| 2972 // Let method be GetMethod(obj, @@iterator). | |
| 2973 builder() | |
| 2974 ->StoreAccumulatorInRegister(obj) | |
| 2975 .LoadNamedProperty(obj, iterator_symbol(), feedback_index(load_slot)) | |
| 2976 .StoreAccumulatorInRegister(method); | |
| 2977 | |
| 2978 // Let iterator be Call(method, obj). | |
| 2979 builder()->Call(method, args, feedback_index(call_slot), | |
| 2980 Call::NAMED_PROPERTY_CALL); | |
| 2981 | |
| 2982 // If Type(iterator) is not Object, throw a TypeError exception. | |
| 2983 BytecodeLabel no_type_error; | |
| 2984 builder()->JumpIfJSReceiver(&no_type_error); | |
| 2985 builder()->CallRuntime(Runtime::kThrowSymbolIteratorInvalid); | |
| 2986 builder()->Bind(&no_type_error); | |
| 2987 } | |
| 2906 } | 2988 } | 
| 2907 | 2989 | 
| 2908 void BytecodeGenerator::VisitThisFunction(ThisFunction* expr) { | 2990 void BytecodeGenerator::VisitThisFunction(ThisFunction* expr) { | 
| 2909 builder()->LoadAccumulatorWithRegister(Register::function_closure()); | 2991 builder()->LoadAccumulatorWithRegister(Register::function_closure()); | 
| 2910 } | 2992 } | 
| 2911 | 2993 | 
| 2912 void BytecodeGenerator::VisitSuperCallReference(SuperCallReference* expr) { | 2994 void BytecodeGenerator::VisitSuperCallReference(SuperCallReference* expr) { | 
| 2913 // Handled by VisitCall(). | 2995 // Handled by VisitCall(). | 
| 2914 UNREACHABLE(); | 2996 UNREACHABLE(); | 
| 2915 } | 2997 } | 
| (...skipping 405 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3321 } | 3403 } | 
| 3322 | 3404 | 
| 3323 Runtime::FunctionId BytecodeGenerator::StoreKeyedToSuperRuntimeId() { | 3405 Runtime::FunctionId BytecodeGenerator::StoreKeyedToSuperRuntimeId() { | 
| 3324 return is_strict(language_mode()) ? Runtime::kStoreKeyedToSuper_Strict | 3406 return is_strict(language_mode()) ? Runtime::kStoreKeyedToSuper_Strict | 
| 3325 : Runtime::kStoreKeyedToSuper_Sloppy; | 3407 : Runtime::kStoreKeyedToSuper_Sloppy; | 
| 3326 } | 3408 } | 
| 3327 | 3409 | 
| 3328 } // namespace interpreter | 3410 } // namespace interpreter | 
| 3329 } // namespace internal | 3411 } // namespace internal | 
| 3330 } // namespace v8 | 3412 } // namespace v8 | 
| OLD | NEW |