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, expr->yield_type()) |
| 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 builder() |
| 2272 ->LoadLiteral(Smi::FromInt(expr->yield_id())) |
| 2273 .SuspendGenerator(generator, expr->yield_type()) |
| 2274 .LoadAccumulatorWithRegister(value) |
| 2275 .Return(); // Hard return (ignore any finally blocks). |
| 2276 } |
2253 | 2277 |
2254 builder()->Bind(&(generator_resume_points_[expr->yield_id()])); | 2278 builder()->Bind(&(generator_resume_points_[expr->yield_id()])); |
2255 // Upon resume, we continue here. | 2279 // Upon resume, we continue here. |
2256 | 2280 |
2257 { | 2281 { |
2258 RegisterAllocationScope register_scope(this); | 2282 RegisterAllocationScope register_scope(this); |
2259 | 2283 |
2260 // Update state to indicate that we have finished resuming. Loop headers | 2284 // Update state to indicate that we have finished resuming. Loop headers |
2261 // rely on this. | 2285 // rely on this. |
2262 builder() | 2286 builder() |
2263 ->LoadLiteral(Smi::FromInt(JSGeneratorObject::kGeneratorExecuting)) | 2287 ->LoadLiteral(Smi::FromInt(JSGeneratorObject::kGeneratorExecuting)) |
2264 .StoreAccumulatorInRegister(generator_state_); | 2288 .StoreAccumulatorInRegister(generator_state_); |
2265 | 2289 |
2266 Register input = register_allocator()->NewRegister(); | 2290 Register input = register_allocator()->NewRegister(); |
2267 builder() | 2291 if (!kIsAsyncGenerator || expr->yield_type() != Yield::kAwait) { |
2268 ->CallRuntime(Runtime::kInlineGeneratorGetInputOrDebugPos, generator) | 2292 builder() |
2269 .StoreAccumulatorInRegister(input); | 2293 ->CallRuntime(Runtime::kInlineGeneratorGetInputOrDebugPos, generator) |
| 2294 .StoreAccumulatorInRegister(input); |
| 2295 } else { |
| 2296 // When resuming from an Await expression, the sent value is in the |
| 2297 // await input slot. |
| 2298 builder() |
| 2299 ->CallRuntime(Runtime::kInlineAsyncGeneratorGetAwaitInput, generator) |
| 2300 .StoreAccumulatorInRegister(input); |
| 2301 } |
2270 | 2302 |
2271 Register resume_mode = register_allocator()->NewRegister(); | 2303 Register resume_mode = register_allocator()->NewRegister(); |
2272 builder() | 2304 builder() |
2273 ->CallRuntime(Runtime::kInlineGeneratorGetResumeMode, generator) | 2305 ->CallRuntime(Runtime::kInlineGeneratorGetResumeMode, generator) |
2274 .StoreAccumulatorInRegister(resume_mode); | 2306 .StoreAccumulatorInRegister(resume_mode); |
2275 | 2307 |
2276 // Now dispatch on resume mode. | 2308 // Now dispatch on resume mode. |
2277 | 2309 |
2278 BytecodeLabel resume_with_next; | 2310 BytecodeLabel resume_with_next; |
2279 BytecodeLabel resume_with_return; | 2311 BytecodeLabel resume_with_return; |
(...skipping 601 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2881 void BytecodeGenerator::VisitGetIterator(GetIterator* expr) { | 2913 void BytecodeGenerator::VisitGetIterator(GetIterator* expr) { |
2882 FeedbackVectorSlot load_slot = expr->IteratorPropertyFeedbackSlot(); | 2914 FeedbackVectorSlot load_slot = expr->IteratorPropertyFeedbackSlot(); |
2883 FeedbackVectorSlot call_slot = expr->IteratorCallFeedbackSlot(); | 2915 FeedbackVectorSlot call_slot = expr->IteratorCallFeedbackSlot(); |
2884 | 2916 |
2885 RegisterList args = register_allocator()->NewRegisterList(1); | 2917 RegisterList args = register_allocator()->NewRegisterList(1); |
2886 Register method = register_allocator()->NewRegister(); | 2918 Register method = register_allocator()->NewRegister(); |
2887 Register obj = args[0]; | 2919 Register obj = args[0]; |
2888 | 2920 |
2889 VisitForAccumulatorValue(expr->iterable()); | 2921 VisitForAccumulatorValue(expr->iterable()); |
2890 | 2922 |
2891 // Let method be GetMethod(obj, @@iterator). | 2923 if (expr->hint() == GetIterator::kAsync) { |
2892 builder() | 2924 FeedbackVectorSlot load_slot2 = expr->AsyncIteratorPropertyFeedbackSlot(); |
2893 ->StoreAccumulatorInRegister(obj) | 2925 FeedbackVectorSlot call_slot2 = expr->AsyncIteratorCallFeedbackSlot(); |
2894 .LoadNamedProperty(obj, iterator_symbol(), feedback_index(load_slot)) | 2926 Register tmp = register_allocator()->NewRegister(); |
2895 .StoreAccumulatorInRegister(method); | 2927 // Set method to GetMethod(obj, @@asyncIterator) |
| 2928 builder()->StoreAccumulatorInRegister(obj).LoadNamedProperty( |
| 2929 obj, async_iterator_symbol(), feedback_index(load_slot2)); |
2896 | 2930 |
2897 // Let iterator be Call(method, obj). | 2931 BytecodeLabel async_iterator_undefined, async_iterator_null, done; |
2898 builder()->Call(method, args, feedback_index(call_slot), | 2932 builder()->JumpIfUndefined(&async_iterator_undefined); |
2899 Call::NAMED_PROPERTY_CALL); | 2933 builder()->JumpIfNull(&async_iterator_null); |
2900 | 2934 |
2901 // If Type(iterator) is not Object, throw a TypeError exception. | 2935 // Let iterator be Call(method, obj) |
2902 BytecodeLabel no_type_error; | 2936 builder()->StoreAccumulatorInRegister(method).Call( |
2903 builder()->JumpIfJSReceiver(&no_type_error); | 2937 method, args, feedback_index(call_slot), Call::NAMED_PROPERTY_CALL); |
2904 builder()->CallRuntime(Runtime::kThrowSymbolIteratorInvalid); | 2938 |
2905 builder()->Bind(&no_type_error); | 2939 // If Type(iterator) is not Object, throw a TypeError exception. |
| 2940 builder()->JumpIfJSReceiver(&done); |
| 2941 builder()->CallRuntime(Runtime::kThrowSymbolAsyncIteratorInvalid); |
| 2942 |
| 2943 builder()->Bind(&async_iterator_undefined); |
| 2944 builder()->Bind(&async_iterator_null); |
| 2945 // If method is undefined, |
| 2946 // Let syncMethod be GetMethod(obj, @@iterator) |
| 2947 builder() |
| 2948 ->LoadNamedProperty(obj, iterator_symbol(), feedback_index(load_slot)) |
| 2949 .StoreAccumulatorInRegister(method); |
| 2950 |
| 2951 // Let syncIterator be Call(syncMethod, obj) |
| 2952 builder()->Call(method, args, feedback_index(call_slot2), |
| 2953 Call::NAMED_PROPERTY_CALL); |
| 2954 |
| 2955 // Return CreateAsyncFromSyncIterator(syncIterator) |
| 2956 RegisterList args = register_allocator()->NewRegisterList(1); |
| 2957 Register sync_iterator = args[0]; |
| 2958 builder() |
| 2959 ->StoreAccumulatorInRegister(sync_iterator) |
| 2960 .CallRuntime(Runtime::kInlineCreateAsyncFromSyncIterator, args); |
| 2961 |
| 2962 builder()->Bind(&done); |
| 2963 } else { |
| 2964 // Let method be GetMethod(obj, @@iterator). |
| 2965 builder() |
| 2966 ->StoreAccumulatorInRegister(obj) |
| 2967 .LoadNamedProperty(obj, iterator_symbol(), feedback_index(load_slot)) |
| 2968 .StoreAccumulatorInRegister(method); |
| 2969 |
| 2970 // Let iterator be Call(method, obj). |
| 2971 builder()->Call(method, args, feedback_index(call_slot), |
| 2972 Call::NAMED_PROPERTY_CALL); |
| 2973 |
| 2974 // If Type(iterator) is not Object, throw a TypeError exception. |
| 2975 BytecodeLabel no_type_error; |
| 2976 builder()->JumpIfJSReceiver(&no_type_error); |
| 2977 builder()->CallRuntime(Runtime::kThrowSymbolIteratorInvalid); |
| 2978 builder()->Bind(&no_type_error); |
| 2979 } |
2906 } | 2980 } |
2907 | 2981 |
2908 void BytecodeGenerator::VisitThisFunction(ThisFunction* expr) { | 2982 void BytecodeGenerator::VisitThisFunction(ThisFunction* expr) { |
2909 builder()->LoadAccumulatorWithRegister(Register::function_closure()); | 2983 builder()->LoadAccumulatorWithRegister(Register::function_closure()); |
2910 } | 2984 } |
2911 | 2985 |
2912 void BytecodeGenerator::VisitSuperCallReference(SuperCallReference* expr) { | 2986 void BytecodeGenerator::VisitSuperCallReference(SuperCallReference* expr) { |
2913 // Handled by VisitCall(). | 2987 // Handled by VisitCall(). |
2914 UNREACHABLE(); | 2988 UNREACHABLE(); |
2915 } | 2989 } |
(...skipping 405 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3321 } | 3395 } |
3322 | 3396 |
3323 Runtime::FunctionId BytecodeGenerator::StoreKeyedToSuperRuntimeId() { | 3397 Runtime::FunctionId BytecodeGenerator::StoreKeyedToSuperRuntimeId() { |
3324 return is_strict(language_mode()) ? Runtime::kStoreKeyedToSuper_Strict | 3398 return is_strict(language_mode()) ? Runtime::kStoreKeyedToSuper_Strict |
3325 : Runtime::kStoreKeyedToSuper_Sloppy; | 3399 : Runtime::kStoreKeyedToSuper_Sloppy; |
3326 } | 3400 } |
3327 | 3401 |
3328 } // namespace interpreter | 3402 } // namespace interpreter |
3329 } // namespace internal | 3403 } // namespace internal |
3330 } // namespace v8 | 3404 } // namespace v8 |
OLD | NEW |