| 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 758 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 769 globals_builder_(new (zone()) GlobalDeclarationsBuilder(info->zone())), | 769 globals_builder_(new (zone()) GlobalDeclarationsBuilder(info->zone())), |
| 770 global_declarations_(0, info->zone()), | 770 global_declarations_(0, info->zone()), |
| 771 function_literals_(0, info->zone()), | 771 function_literals_(0, info->zone()), |
| 772 native_function_literals_(0, info->zone()), | 772 native_function_literals_(0, info->zone()), |
| 773 object_literals_(0, info->zone()), | 773 object_literals_(0, info->zone()), |
| 774 array_literals_(0, info->zone()), | 774 array_literals_(0, info->zone()), |
| 775 execution_control_(nullptr), | 775 execution_control_(nullptr), |
| 776 execution_context_(nullptr), | 776 execution_context_(nullptr), |
| 777 execution_result_(nullptr), | 777 execution_result_(nullptr), |
| 778 generator_jump_table_(nullptr), | 778 generator_jump_table_(nullptr), |
| 779 generator_object_(), |
| 779 generator_state_(), | 780 generator_state_(), |
| 780 loop_depth_(0) { | 781 loop_depth_(0) { |
| 781 DCHECK_EQ(closure_scope(), closure_scope()->GetClosureScope()); | 782 DCHECK_EQ(closure_scope(), closure_scope()->GetClosureScope()); |
| 782 } | 783 } |
| 783 | 784 |
| 784 Handle<BytecodeArray> BytecodeGenerator::FinalizeBytecode(Isolate* isolate) { | 785 Handle<BytecodeArray> BytecodeGenerator::FinalizeBytecode(Isolate* isolate) { |
| 785 AllocateDeferredConstants(isolate); | 786 AllocateDeferredConstants(isolate); |
| 786 if (HasStackOverflow()) return Handle<BytecodeArray>(); | 787 if (HasStackOverflow()) return Handle<BytecodeArray>(); |
| 787 return builder()->ToBytecodeArray(isolate); | 788 return builder()->ToBytecodeArray(isolate); |
| 788 } | 789 } |
| (...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 955 // Otherwise this is an error. | 956 // Otherwise this is an error. |
| 956 BuildAbort(BailoutReason::kInvalidJumpTableIndex); | 957 BuildAbort(BailoutReason::kInvalidJumpTableIndex); |
| 957 | 958 |
| 958 builder()->Bind(¬_resuming); | 959 builder()->Bind(¬_resuming); |
| 959 } | 960 } |
| 960 } | 961 } |
| 961 | 962 |
| 962 void BytecodeGenerator::BuildGeneratorPrologue() { | 963 void BytecodeGenerator::BuildGeneratorPrologue() { |
| 963 DCHECK_GT(info()->literal()->suspend_count(), 0); | 964 DCHECK_GT(info()->literal()->suspend_count(), 0); |
| 964 | 965 |
| 966 generator_object_ = register_allocator()->NewRegister(); |
| 965 generator_state_ = register_allocator()->NewRegister(); | 967 generator_state_ = register_allocator()->NewRegister(); |
| 966 generator_jump_table_ = | 968 generator_jump_table_ = |
| 967 builder()->AllocateJumpTable(info()->literal()->suspend_count(), 0); | 969 builder()->AllocateJumpTable(info()->literal()->suspend_count(), 0); |
| 968 | 970 |
| 969 // The generator resume trampoline abuses the new.target register both to | 971 // The generator resume trampoline abuses the new.target register both to |
| 970 // indicate that this is a resume call and to pass in the generator object. | 972 // indicate that this is a resume call and to pass in the generator object. |
| 971 // In ordinary calls, new.target is always undefined because generator | 973 // In ordinary calls, new.target is always undefined because generator |
| 972 // functions are non-constructable. | 974 // functions are non-constructable. |
| 973 Register generator_object = Register::new_target(); | 975 builder()->MoveRegister(Register::new_target(), generator_object_); |
| 976 |
| 974 BytecodeLabel regular_call; | 977 BytecodeLabel regular_call; |
| 975 builder() | 978 builder() |
| 976 ->LoadAccumulatorWithRegister(generator_object) | 979 ->LoadAccumulatorWithRegister(generator_object_) |
| 977 .JumpIfUndefined(®ular_call); | 980 .JumpIfUndefined(®ular_call); |
| 978 | 981 |
| 979 // This is a resume call. Restore the current context and the registers, | 982 // This is a resume call. Restore the current context and the registers, |
| 980 // then perform state dispatch. | 983 // then perform state dispatch. |
| 981 Register generator_context = register_allocator()->NewRegister(); | 984 Register generator_context = register_allocator()->NewRegister(); |
| 982 builder() | 985 builder() |
| 983 ->CallRuntime(Runtime::kInlineGeneratorGetContext, generator_object) | 986 ->CallRuntime(Runtime::kInlineGeneratorGetContext, generator_object_) |
| 984 .PushContext(generator_context) | 987 .PushContext(generator_context) |
| 985 .ResumeGenerator(generator_object) | 988 .RestoreGeneratorState(generator_object_) |
| 986 .StoreAccumulatorInRegister(generator_state_) | 989 .StoreAccumulatorInRegister(generator_state_) |
| 987 .SwitchOnSmiNoFeedback(generator_jump_table_); | 990 .SwitchOnSmiNoFeedback(generator_jump_table_); |
| 988 // We fall through when the generator state is not in the jump table. | 991 // We fall through when the generator state is not in the jump table. |
| 989 // TODO(leszeks): Only generate this for debug builds. | 992 // TODO(leszeks): Only generate this for debug builds. |
| 990 BuildAbort(BailoutReason::kInvalidJumpTableIndex); | 993 BuildAbort(BailoutReason::kInvalidJumpTableIndex); |
| 991 | 994 |
| 992 // This is a regular call. | 995 // This is a regular call. |
| 993 builder() | 996 builder() |
| 994 ->Bind(®ular_call) | 997 ->Bind(®ular_call) |
| 995 .LoadLiteral(Smi::FromInt(JSGeneratorObject::kGeneratorExecuting)) | 998 .LoadLiteral(Smi::FromInt(JSGeneratorObject::kGeneratorExecuting)) |
| (...skipping 1515 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2511 } | 2514 } |
| 2512 case KEYED_SUPER_PROPERTY: { | 2515 case KEYED_SUPER_PROPERTY: { |
| 2513 builder() | 2516 builder() |
| 2514 ->StoreAccumulatorInRegister(super_property_args[3]) | 2517 ->StoreAccumulatorInRegister(super_property_args[3]) |
| 2515 .CallRuntime(StoreKeyedToSuperRuntimeId(), super_property_args); | 2518 .CallRuntime(StoreKeyedToSuperRuntimeId(), super_property_args); |
| 2516 break; | 2519 break; |
| 2517 } | 2520 } |
| 2518 } | 2521 } |
| 2519 } | 2522 } |
| 2520 | 2523 |
| 2521 void BytecodeGenerator::BuildGeneratorSuspend(Suspend* expr, | 2524 void BytecodeGenerator::BuildGeneratorSuspend(Suspend* expr, Register generator, |
| 2522 Register generator) { | 2525 RegisterList registers_to_save) { |
| 2523 RegisterAllocationScope register_scope(this); | 2526 RegisterAllocationScope register_scope(this); |
| 2524 | 2527 |
| 2525 builder()->SetExpressionPosition(expr); | 2528 builder()->SetExpressionPosition(expr); |
| 2526 Register value = VisitForRegisterValue(expr->expression()); | 2529 Register value = VisitForRegisterValue(expr->expression()); |
| 2527 | 2530 |
| 2528 // Save context, registers, and state. Then return. | 2531 // Save context, registers, and state. Then return. |
| 2529 builder() | 2532 builder() |
| 2530 ->LoadLiteral(Smi::FromInt(expr->suspend_id())) | 2533 ->LoadLiteral(Smi::FromInt(expr->suspend_id())) |
| 2531 .SuspendGenerator(generator, expr->flags()); | 2534 .SuspendGenerator(generator, registers_to_save, expr->flags()); |
| 2532 | 2535 |
| 2533 if (expr->IsNonInitialAsyncGeneratorYield()) { | 2536 if (expr->IsNonInitialAsyncGeneratorYield()) { |
| 2534 // AsyncGenerator yields (with the exception of the initial yield) delegate | 2537 // AsyncGenerator yields (with the exception of the initial yield) delegate |
| 2535 // to AsyncGeneratorResolve(), implemented via the runtime call below. | 2538 // to AsyncGeneratorResolve(), implemented via the runtime call below. |
| 2536 RegisterList args = register_allocator()->NewRegisterList(3); | 2539 RegisterList args = register_allocator()->NewRegisterList(3); |
| 2537 | 2540 |
| 2538 // AsyncGeneratorYield: | 2541 // AsyncGeneratorYield: |
| 2539 // perform AsyncGeneratorResolve(<generator>, <value>, false). | 2542 // perform AsyncGeneratorResolve(<generator>, <value>, false). |
| 2540 builder() | 2543 builder() |
| 2541 ->MoveRegister(generator, args[0]) | 2544 ->MoveRegister(generator, args[0]) |
| 2542 .MoveRegister(value, args[1]) | 2545 .MoveRegister(value, args[1]) |
| 2543 .LoadFalse() | 2546 .LoadFalse() |
| 2544 .StoreAccumulatorInRegister(args[2]) | 2547 .StoreAccumulatorInRegister(args[2]) |
| 2545 .CallRuntime(Runtime::kInlineAsyncGeneratorResolve, args); | 2548 .CallRuntime(Runtime::kInlineAsyncGeneratorResolve, args); |
| 2546 } else { | 2549 } else { |
| 2547 builder()->LoadAccumulatorWithRegister(value); | 2550 builder()->LoadAccumulatorWithRegister(value); |
| 2548 } | 2551 } |
| 2549 builder()->Return(); // Hard return (ignore any finally blocks). | 2552 builder()->Return(); // Hard return (ignore any finally blocks). |
| 2550 } | 2553 } |
| 2551 | 2554 |
| 2552 void BytecodeGenerator::BuildGeneratorResume(Suspend* expr, | 2555 void BytecodeGenerator::BuildGeneratorResume( |
| 2553 Register generator) { | 2556 Suspend* expr, Register generator, RegisterList registers_to_restore) { |
| 2554 RegisterAllocationScope register_scope(this); | 2557 RegisterAllocationScope register_scope(this); |
| 2555 | 2558 |
| 2559 // Clobbers all registers. |
| 2560 builder()->RestoreGeneratorRegisters(generator_object_, registers_to_restore); |
| 2561 |
| 2556 // Update state to indicate that we have finished resuming. Loop headers | 2562 // Update state to indicate that we have finished resuming. Loop headers |
| 2557 // rely on this. | 2563 // rely on this. |
| 2558 builder() | 2564 builder() |
| 2559 ->LoadLiteral(Smi::FromInt(JSGeneratorObject::kGeneratorExecuting)) | 2565 ->LoadLiteral(Smi::FromInt(JSGeneratorObject::kGeneratorExecuting)) |
| 2560 .StoreAccumulatorInRegister(generator_state_); | 2566 .StoreAccumulatorInRegister(generator_state_); |
| 2561 | 2567 |
| 2562 Register input = register_allocator()->NewRegister(); | 2568 Register input = register_allocator()->NewRegister(); |
| 2563 | 2569 |
| 2564 // When resuming an Async Generator from an Await expression, the sent | 2570 // When resuming an Async Generator from an Await expression, the sent |
| 2565 // value is in the [[await_input_or_debug_pos]] slot. Otherwise, the sent | 2571 // value is in the [[await_input_or_debug_pos]] slot. Otherwise, the sent |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2616 builder()->Throw(); | 2622 builder()->Throw(); |
| 2617 } | 2623 } |
| 2618 | 2624 |
| 2619 builder()->Bind(&resume_with_next); | 2625 builder()->Bind(&resume_with_next); |
| 2620 builder()->LoadAccumulatorWithRegister(input); | 2626 builder()->LoadAccumulatorWithRegister(input); |
| 2621 } | 2627 } |
| 2622 } | 2628 } |
| 2623 | 2629 |
| 2624 void BytecodeGenerator::VisitSuspend(Suspend* expr) { | 2630 void BytecodeGenerator::VisitSuspend(Suspend* expr) { |
| 2625 Register generator = VisitForRegisterValue(expr->generator_object()); | 2631 Register generator = VisitForRegisterValue(expr->generator_object()); |
| 2626 BuildGeneratorSuspend(expr, generator); | 2632 RegisterList registers(0, register_allocator()->next_register_index()); |
| 2633 BuildGeneratorSuspend(expr, generator, registers); |
| 2627 builder()->Bind(generator_jump_table_, static_cast<int>(expr->suspend_id())); | 2634 builder()->Bind(generator_jump_table_, static_cast<int>(expr->suspend_id())); |
| 2628 // Upon resume, we continue here. | 2635 // Upon resume, we continue here. |
| 2629 BuildGeneratorResume(expr, generator); | 2636 BuildGeneratorResume(expr, generator, registers); |
| 2630 } | 2637 } |
| 2631 | 2638 |
| 2632 void BytecodeGenerator::VisitThrow(Throw* expr) { | 2639 void BytecodeGenerator::VisitThrow(Throw* expr) { |
| 2633 VisitForAccumulatorValue(expr->exception()); | 2640 VisitForAccumulatorValue(expr->exception()); |
| 2634 builder()->SetExpressionPosition(expr); | 2641 builder()->SetExpressionPosition(expr); |
| 2635 builder()->Throw(); | 2642 builder()->Throw(); |
| 2636 } | 2643 } |
| 2637 | 2644 |
| 2638 void BytecodeGenerator::VisitPropertyLoad(Register obj, Property* expr) { | 2645 void BytecodeGenerator::VisitPropertyLoad(Register obj, Property* expr) { |
| 2639 LhsKind property_kind = Property::GetAssignType(expr); | 2646 LhsKind property_kind = Property::GetAssignType(expr); |
| (...skipping 1081 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3721 | 3728 |
| 3722 void BytecodeGenerator::BuildGeneratorObjectVariableInitialization() { | 3729 void BytecodeGenerator::BuildGeneratorObjectVariableInitialization() { |
| 3723 DCHECK(IsResumableFunction(info()->literal()->kind())); | 3730 DCHECK(IsResumableFunction(info()->literal()->kind())); |
| 3724 DCHECK_NOT_NULL(closure_scope()->generator_object_var()); | 3731 DCHECK_NOT_NULL(closure_scope()->generator_object_var()); |
| 3725 | 3732 |
| 3726 RegisterAllocationScope register_scope(this); | 3733 RegisterAllocationScope register_scope(this); |
| 3727 RegisterList args = register_allocator()->NewRegisterList(2); | 3734 RegisterList args = register_allocator()->NewRegisterList(2); |
| 3728 builder() | 3735 builder() |
| 3729 ->MoveRegister(Register::function_closure(), args[0]) | 3736 ->MoveRegister(Register::function_closure(), args[0]) |
| 3730 .MoveRegister(builder()->Receiver(), args[1]) | 3737 .MoveRegister(builder()->Receiver(), args[1]) |
| 3731 .CallRuntime(Runtime::kInlineCreateJSGeneratorObject, args); | 3738 .CallRuntime(Runtime::kInlineCreateJSGeneratorObject, args) |
| 3739 .StoreAccumulatorInRegister(generator_object_); |
| 3732 BuildVariableAssignment(closure_scope()->generator_object_var(), Token::INIT, | 3740 BuildVariableAssignment(closure_scope()->generator_object_var(), Token::INIT, |
| 3733 FeedbackSlot::Invalid(), HoleCheckMode::kElided); | 3741 FeedbackSlot::Invalid(), HoleCheckMode::kElided); |
| 3734 } | 3742 } |
| 3735 | 3743 |
| 3736 void BytecodeGenerator::VisitFunctionClosureForContext() { | 3744 void BytecodeGenerator::VisitFunctionClosureForContext() { |
| 3737 ValueResultScope value_execution_result(this); | 3745 ValueResultScope value_execution_result(this); |
| 3738 if (closure_scope()->is_script_scope()) { | 3746 if (closure_scope()->is_script_scope()) { |
| 3739 // Contexts nested in the native context have a canonical empty function as | 3747 // Contexts nested in the native context have a canonical empty function as |
| 3740 // their closure, not the anonymous closure containing the global code. | 3748 // their closure, not the anonymous closure containing the global code. |
| 3741 Register native_context = register_allocator()->NewRegister(); | 3749 Register native_context = register_allocator()->NewRegister(); |
| (...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3905 } | 3913 } |
| 3906 | 3914 |
| 3907 Runtime::FunctionId BytecodeGenerator::StoreKeyedToSuperRuntimeId() { | 3915 Runtime::FunctionId BytecodeGenerator::StoreKeyedToSuperRuntimeId() { |
| 3908 return is_strict(language_mode()) ? Runtime::kStoreKeyedToSuper_Strict | 3916 return is_strict(language_mode()) ? Runtime::kStoreKeyedToSuper_Strict |
| 3909 : Runtime::kStoreKeyedToSuper_Sloppy; | 3917 : Runtime::kStoreKeyedToSuper_Sloppy; |
| 3910 } | 3918 } |
| 3911 | 3919 |
| 3912 } // namespace interpreter | 3920 } // namespace interpreter |
| 3913 } // namespace internal | 3921 } // namespace internal |
| 3914 } // namespace v8 | 3922 } // namespace v8 |
| OLD | NEW |