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 |