Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1)

Side by Side Diff: src/interpreter/bytecode-generator.cc

Issue 2894293003: Save/restore only live registers in the generator suspend/resume. (Closed)
Patch Set: Tweak Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/interpreter/bytecode-generator.h ('k') | src/interpreter/bytecode-operands.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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(&not_resuming); 959 builder()->Bind(&not_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(&regular_call); 980 .JumpIfUndefined(&regular_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(&regular_call) 997 ->Bind(&regular_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
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
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
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
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
OLDNEW
« no previous file with comments | « src/interpreter/bytecode-generator.h ('k') | src/interpreter/bytecode-operands.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698