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-array-builder.h" | 5 #include "src/interpreter/bytecode-array-builder.h" |
6 | 6 |
7 #include "src/globals.h" | 7 #include "src/globals.h" |
8 #include "src/interpreter/bytecode-array-writer.h" | 8 #include "src/interpreter/bytecode-array-writer.h" |
9 #include "src/interpreter/bytecode-dead-code-optimizer.h" | 9 #include "src/interpreter/bytecode-dead-code-optimizer.h" |
10 #include "src/interpreter/bytecode-label.h" | 10 #include "src/interpreter/bytecode-label.h" |
(...skipping 10 matching lines...) Expand all Loading... |
21 int locals_count, FunctionLiteral* literal, | 21 int locals_count, FunctionLiteral* literal, |
22 SourcePositionTableBuilder::RecordingMode source_position_mode) | 22 SourcePositionTableBuilder::RecordingMode source_position_mode) |
23 : zone_(zone), | 23 : zone_(zone), |
24 bytecode_generated_(false), | 24 bytecode_generated_(false), |
25 constant_array_builder_(zone, isolate->factory()->the_hole_value()), | 25 constant_array_builder_(zone, isolate->factory()->the_hole_value()), |
26 handler_table_builder_(zone), | 26 handler_table_builder_(zone), |
27 return_seen_in_block_(false), | 27 return_seen_in_block_(false), |
28 parameter_count_(parameter_count), | 28 parameter_count_(parameter_count), |
29 local_register_count_(locals_count), | 29 local_register_count_(locals_count), |
30 context_register_count_(context_count), | 30 context_register_count_(context_count), |
31 temporary_allocator_(zone, fixed_register_count()), | 31 register_allocator_(fixed_register_count()), |
32 bytecode_array_writer_(zone, &constant_array_builder_, | 32 bytecode_array_writer_(zone, &constant_array_builder_, |
33 source_position_mode), | 33 source_position_mode), |
34 pipeline_(&bytecode_array_writer_) { | 34 pipeline_(&bytecode_array_writer_) { |
35 DCHECK_GE(parameter_count_, 0); | 35 DCHECK_GE(parameter_count_, 0); |
36 DCHECK_GE(context_register_count_, 0); | 36 DCHECK_GE(context_register_count_, 0); |
37 DCHECK_GE(local_register_count_, 0); | 37 DCHECK_GE(local_register_count_, 0); |
38 | 38 |
39 if (FLAG_ignition_deadcode) { | 39 if (FLAG_ignition_deadcode) { |
40 pipeline_ = new (zone) BytecodeDeadCodeOptimizer(pipeline_); | 40 pipeline_ = new (zone) BytecodeDeadCodeOptimizer(pipeline_); |
41 } | 41 } |
42 | 42 |
43 if (FLAG_ignition_peephole) { | 43 if (FLAG_ignition_peephole) { |
44 pipeline_ = new (zone) BytecodePeepholeOptimizer(pipeline_); | 44 pipeline_ = new (zone) BytecodePeepholeOptimizer(pipeline_); |
45 } | 45 } |
46 | 46 |
47 if (FLAG_ignition_reo) { | 47 if (FLAG_ignition_reo) { |
48 pipeline_ = new (zone) BytecodeRegisterOptimizer( | 48 pipeline_ = new (zone) BytecodeRegisterOptimizer( |
49 zone, &temporary_allocator_, parameter_count, pipeline_); | 49 zone, ®ister_allocator_, fixed_register_count(), parameter_count, |
| 50 pipeline_); |
50 } | 51 } |
51 | 52 |
52 return_position_ = | 53 return_position_ = |
53 literal ? std::max(literal->start_position(), literal->end_position() - 1) | 54 literal ? std::max(literal->start_position(), literal->end_position() - 1) |
54 : kNoSourcePosition; | 55 : kNoSourcePosition; |
55 } | 56 } |
56 | 57 |
57 Register BytecodeArrayBuilder::first_context_register() const { | 58 Register BytecodeArrayBuilder::first_context_register() const { |
58 DCHECK_GT(context_register_count_, 0); | 59 DCHECK_GT(context_register_count_, 0); |
59 return Register(local_register_count_); | 60 return Register(local_register_count_); |
60 } | 61 } |
61 | 62 |
62 Register BytecodeArrayBuilder::last_context_register() const { | 63 Register BytecodeArrayBuilder::last_context_register() const { |
63 DCHECK_GT(context_register_count_, 0); | 64 DCHECK_GT(context_register_count_, 0); |
64 return Register(local_register_count_ + context_register_count_ - 1); | 65 return Register(local_register_count_ + context_register_count_ - 1); |
65 } | 66 } |
66 | 67 |
67 Register BytecodeArrayBuilder::Parameter(int parameter_index) const { | 68 Register BytecodeArrayBuilder::Parameter(int parameter_index) const { |
68 DCHECK_GE(parameter_index, 0); | 69 DCHECK_GE(parameter_index, 0); |
69 return Register::FromParameterIndex(parameter_index, parameter_count()); | 70 return Register::FromParameterIndex(parameter_index, parameter_count()); |
70 } | 71 } |
71 | 72 |
72 bool BytecodeArrayBuilder::RegisterIsParameterOrLocal(Register reg) const { | |
73 return reg.is_parameter() || reg.index() < locals_count(); | |
74 } | |
75 | |
76 Handle<BytecodeArray> BytecodeArrayBuilder::ToBytecodeArray(Isolate* isolate) { | 73 Handle<BytecodeArray> BytecodeArrayBuilder::ToBytecodeArray(Isolate* isolate) { |
77 DCHECK(return_seen_in_block_); | 74 DCHECK(return_seen_in_block_); |
78 DCHECK(!bytecode_generated_); | 75 DCHECK(!bytecode_generated_); |
79 bytecode_generated_ = true; | 76 bytecode_generated_ = true; |
80 | 77 |
81 Handle<FixedArray> handler_table = | 78 Handle<FixedArray> handler_table = |
82 handler_table_builder()->ToHandlerTable(isolate); | 79 handler_table_builder()->ToHandlerTable(isolate); |
83 return pipeline_->ToBytecodeArray(isolate, | 80 return pipeline_->ToBytecodeArray(isolate, total_register_count(), |
84 fixed_and_temporary_register_count(), | |
85 parameter_count(), handler_table); | 81 parameter_count(), handler_table); |
86 } | 82 } |
87 | 83 |
88 void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t operand0, | 84 void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t operand0, |
89 uint32_t operand1, uint32_t operand2, | 85 uint32_t operand1, uint32_t operand2, |
90 uint32_t operand3) { | 86 uint32_t operand3) { |
91 DCHECK(OperandsAreValid(bytecode, 4, operand0, operand1, operand2, operand3)); | 87 DCHECK(OperandsAreValid(bytecode, 4, operand0, operand1, operand2, operand3)); |
92 BytecodeNode node(bytecode, operand0, operand1, operand2, operand3, | 88 BytecodeNode node(bytecode, operand0, operand1, operand2, operand3, |
93 &latest_source_info_); | 89 &latest_source_info_); |
94 pipeline()->Write(&node); | 90 pipeline()->Write(&node); |
(...skipping 627 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
722 | 718 |
723 void BytecodeArrayBuilder::EnsureReturn() { | 719 void BytecodeArrayBuilder::EnsureReturn() { |
724 if (!return_seen_in_block_) { | 720 if (!return_seen_in_block_) { |
725 LoadUndefined(); | 721 LoadUndefined(); |
726 Return(); | 722 Return(); |
727 } | 723 } |
728 DCHECK(return_seen_in_block_); | 724 DCHECK(return_seen_in_block_); |
729 } | 725 } |
730 | 726 |
731 BytecodeArrayBuilder& BytecodeArrayBuilder::Call(Register callable, | 727 BytecodeArrayBuilder& BytecodeArrayBuilder::Call(Register callable, |
732 Register receiver_args, | 728 RegisterList args, |
733 size_t receiver_args_count, | |
734 int feedback_slot, | 729 int feedback_slot, |
735 TailCallMode tail_call_mode) { | 730 TailCallMode tail_call_mode) { |
736 if (tail_call_mode == TailCallMode::kDisallow) { | 731 if (tail_call_mode == TailCallMode::kDisallow) { |
737 Output(Bytecode::kCall, RegisterOperand(callable), | 732 Output(Bytecode::kCall, RegisterOperand(callable), |
738 RegisterOperand(receiver_args), UnsignedOperand(receiver_args_count), | 733 RegisterOperand(args.first_register()), |
| 734 UnsignedOperand(args.register_count()), |
739 UnsignedOperand(feedback_slot)); | 735 UnsignedOperand(feedback_slot)); |
740 } else { | 736 } else { |
741 DCHECK(tail_call_mode == TailCallMode::kAllow); | 737 DCHECK(tail_call_mode == TailCallMode::kAllow); |
742 Output(Bytecode::kTailCall, RegisterOperand(callable), | 738 Output(Bytecode::kTailCall, RegisterOperand(callable), |
743 RegisterOperand(receiver_args), UnsignedOperand(receiver_args_count), | 739 RegisterOperand(args.first_register()), |
| 740 UnsignedOperand(args.register_count()), |
744 UnsignedOperand(feedback_slot)); | 741 UnsignedOperand(feedback_slot)); |
745 } | 742 } |
746 return *this; | 743 return *this; |
747 } | 744 } |
748 | 745 |
749 BytecodeArrayBuilder& BytecodeArrayBuilder::New(Register constructor, | 746 BytecodeArrayBuilder& BytecodeArrayBuilder::New(Register constructor, |
750 Register first_arg, | 747 RegisterList args, |
751 size_t arg_count, | |
752 int feedback_slot_id) { | 748 int feedback_slot_id) { |
753 if (!first_arg.is_valid()) { | |
754 DCHECK_EQ(0u, arg_count); | |
755 first_arg = Register(0); | |
756 } | |
757 Output(Bytecode::kNew, RegisterOperand(constructor), | 749 Output(Bytecode::kNew, RegisterOperand(constructor), |
758 RegisterOperand(first_arg), UnsignedOperand(arg_count), | 750 RegisterOperand(args.first_register()), |
| 751 UnsignedOperand(args.register_count()), |
759 UnsignedOperand(feedback_slot_id)); | 752 UnsignedOperand(feedback_slot_id)); |
760 return *this; | 753 return *this; |
761 } | 754 } |
762 | 755 |
763 BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntime( | 756 BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntime( |
764 Runtime::FunctionId function_id, Register first_arg, size_t arg_count) { | 757 Runtime::FunctionId function_id, RegisterList args) { |
765 DCHECK_EQ(1, Runtime::FunctionForId(function_id)->result_size); | 758 DCHECK_EQ(1, Runtime::FunctionForId(function_id)->result_size); |
766 DCHECK(Bytecodes::SizeForUnsignedOperand(function_id) <= OperandSize::kShort); | 759 DCHECK(Bytecodes::SizeForUnsignedOperand(function_id) <= OperandSize::kShort); |
767 if (!first_arg.is_valid()) { | |
768 DCHECK_EQ(0u, arg_count); | |
769 first_arg = Register(0); | |
770 } | |
771 Bytecode bytecode; | 760 Bytecode bytecode; |
772 uint32_t id; | 761 uint32_t id; |
773 if (IntrinsicsHelper::IsSupported(function_id)) { | 762 if (IntrinsicsHelper::IsSupported(function_id)) { |
774 bytecode = Bytecode::kInvokeIntrinsic; | 763 bytecode = Bytecode::kInvokeIntrinsic; |
775 id = static_cast<uint32_t>(IntrinsicsHelper::FromRuntimeId(function_id)); | 764 id = static_cast<uint32_t>(IntrinsicsHelper::FromRuntimeId(function_id)); |
776 } else { | 765 } else { |
777 bytecode = Bytecode::kCallRuntime; | 766 bytecode = Bytecode::kCallRuntime; |
778 id = static_cast<uint32_t>(function_id); | 767 id = static_cast<uint32_t>(function_id); |
779 } | 768 } |
780 Output(bytecode, id, RegisterOperand(first_arg), UnsignedOperand(arg_count)); | 769 Output(bytecode, id, RegisterOperand(args.first_register()), |
| 770 UnsignedOperand(args.register_count())); |
| 771 return *this; |
| 772 } |
| 773 |
| 774 BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntime( |
| 775 Runtime::FunctionId function_id, Register arg) { |
| 776 return CallRuntime(function_id, RegisterList(arg.index(), 1)); |
| 777 } |
| 778 |
| 779 BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntime( |
| 780 Runtime::FunctionId function_id) { |
| 781 return CallRuntime(function_id, RegisterList()); |
| 782 } |
| 783 |
| 784 BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntimeForPair( |
| 785 Runtime::FunctionId function_id, RegisterList args, Register first_return) { |
| 786 DCHECK_EQ(2, Runtime::FunctionForId(function_id)->result_size); |
| 787 DCHECK(Bytecodes::SizeForUnsignedOperand(function_id) <= OperandSize::kShort); |
| 788 Output(Bytecode::kCallRuntimeForPair, static_cast<uint16_t>(function_id), |
| 789 RegisterOperand(args.first_register()), |
| 790 UnsignedOperand(args.register_count()), RegisterOperand(first_return)); |
781 return *this; | 791 return *this; |
782 } | 792 } |
783 | 793 |
784 BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntimeForPair( | 794 BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntimeForPair( |
785 Runtime::FunctionId function_id, Register first_arg, size_t arg_count, | 795 Runtime::FunctionId function_id, Register arg, Register first_return) { |
786 Register first_return) { | 796 return CallRuntimeForPair(function_id, RegisterList(arg.index(), 1), |
787 DCHECK_EQ(2, Runtime::FunctionForId(function_id)->result_size); | 797 first_return); |
788 DCHECK(Bytecodes::SizeForUnsignedOperand(function_id) <= OperandSize::kShort); | 798 } |
789 if (!first_arg.is_valid()) { | 799 |
790 DCHECK_EQ(0u, arg_count); | 800 BytecodeArrayBuilder& BytecodeArrayBuilder::CallJSRuntime(int context_index, |
791 first_arg = Register(0); | 801 RegisterList args) { |
792 } | 802 Output(Bytecode::kCallJSRuntime, UnsignedOperand(context_index), |
793 Output(Bytecode::kCallRuntimeForPair, static_cast<uint16_t>(function_id), | 803 RegisterOperand(args.first_register()), |
794 RegisterOperand(first_arg), UnsignedOperand(arg_count), | 804 UnsignedOperand(args.register_count())); |
795 RegisterOperand(first_return)); | |
796 return *this; | 805 return *this; |
797 } | 806 } |
798 | 807 |
799 BytecodeArrayBuilder& BytecodeArrayBuilder::CallJSRuntime( | |
800 int context_index, Register receiver_args, size_t receiver_args_count) { | |
801 Output(Bytecode::kCallJSRuntime, UnsignedOperand(context_index), | |
802 RegisterOperand(receiver_args), UnsignedOperand(receiver_args_count)); | |
803 return *this; | |
804 } | |
805 | |
806 BytecodeArrayBuilder& BytecodeArrayBuilder::Delete(Register object, | 808 BytecodeArrayBuilder& BytecodeArrayBuilder::Delete(Register object, |
807 LanguageMode language_mode) { | 809 LanguageMode language_mode) { |
808 if (language_mode == SLOPPY) { | 810 if (language_mode == SLOPPY) { |
809 Output(Bytecode::kDeletePropertySloppy, RegisterOperand(object)); | 811 Output(Bytecode::kDeletePropertySloppy, RegisterOperand(object)); |
810 } else { | 812 } else { |
811 DCHECK_EQ(language_mode, STRICT); | 813 DCHECK_EQ(language_mode, STRICT); |
812 Output(Bytecode::kDeletePropertyStrict, RegisterOperand(object)); | 814 Output(Bytecode::kDeletePropertyStrict, RegisterOperand(object)); |
813 } | 815 } |
814 return *this; | 816 return *this; |
815 } | 817 } |
816 | 818 |
817 size_t BytecodeArrayBuilder::GetConstantPoolEntry(Handle<Object> object) { | 819 size_t BytecodeArrayBuilder::GetConstantPoolEntry(Handle<Object> object) { |
818 return constant_array_builder()->Insert(object); | 820 return constant_array_builder()->Insert(object); |
819 } | 821 } |
820 | 822 |
821 size_t BytecodeArrayBuilder::AllocateConstantPoolEntry() { | 823 size_t BytecodeArrayBuilder::AllocateConstantPoolEntry() { |
822 return constant_array_builder()->AllocateEntry(); | 824 return constant_array_builder()->AllocateEntry(); |
823 } | 825 } |
824 | 826 |
825 void BytecodeArrayBuilder::InsertConstantPoolEntryAt(size_t entry, | 827 void BytecodeArrayBuilder::InsertConstantPoolEntryAt(size_t entry, |
826 Handle<Object> object) { | 828 Handle<Object> object) { |
827 constant_array_builder()->InsertAllocatedEntry(entry, object); | 829 constant_array_builder()->InsertAllocatedEntry(entry, object); |
828 } | 830 } |
829 | 831 |
830 void BytecodeArrayBuilder::SetReturnPosition() { | 832 void BytecodeArrayBuilder::SetReturnPosition() { |
831 if (return_position_ == kNoSourcePosition) return; | 833 if (return_position_ == kNoSourcePosition) return; |
832 latest_source_info_.MakeStatementPosition(return_position_); | 834 latest_source_info_.MakeStatementPosition(return_position_); |
833 } | 835 } |
834 | 836 |
835 bool BytecodeArrayBuilder::TemporaryRegisterIsLive(Register reg) const { | |
836 return temporary_register_allocator()->RegisterIsLive(reg); | |
837 } | |
838 | |
839 bool BytecodeArrayBuilder::RegisterIsValid(Register reg) const { | 837 bool BytecodeArrayBuilder::RegisterIsValid(Register reg) const { |
840 if (!reg.is_valid()) { | 838 if (!reg.is_valid()) { |
841 return false; | 839 return false; |
842 } | 840 } |
843 | 841 |
844 if (reg.is_current_context() || reg.is_function_closure() || | 842 if (reg.is_current_context() || reg.is_function_closure() || |
845 reg.is_new_target()) { | 843 reg.is_new_target()) { |
846 return true; | 844 return true; |
847 } else if (reg.is_parameter()) { | 845 } else if (reg.is_parameter()) { |
848 int parameter_index = reg.ToParameterIndex(parameter_count()); | 846 int parameter_index = reg.ToParameterIndex(parameter_count()); |
849 return parameter_index >= 0 && parameter_index < parameter_count(); | 847 return parameter_index >= 0 && parameter_index < parameter_count(); |
850 } else if (reg.index() < fixed_register_count()) { | 848 } else if (reg.index() < fixed_register_count()) { |
851 return true; | 849 return true; |
852 } else { | 850 } else { |
853 return TemporaryRegisterIsLive(reg); | 851 return register_allocator()->RegisterIsLive(reg); |
854 } | 852 } |
855 } | 853 } |
856 | 854 |
857 bool BytecodeArrayBuilder::OperandsAreValid( | 855 bool BytecodeArrayBuilder::OperandsAreValid( |
858 Bytecode bytecode, int operand_count, uint32_t operand0, uint32_t operand1, | 856 Bytecode bytecode, int operand_count, uint32_t operand0, uint32_t operand1, |
859 uint32_t operand2, uint32_t operand3) const { | 857 uint32_t operand2, uint32_t operand3) const { |
860 if (Bytecodes::NumberOfOperands(bytecode) != operand_count) { | 858 if (Bytecodes::NumberOfOperands(bytecode) != operand_count) { |
861 return false; | 859 return false; |
862 } | 860 } |
863 | 861 |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
934 } | 932 } |
935 } | 933 } |
936 } | 934 } |
937 | 935 |
938 return true; | 936 return true; |
939 } | 937 } |
940 | 938 |
941 } // namespace interpreter | 939 } // namespace interpreter |
942 } // namespace internal | 940 } // namespace internal |
943 } // namespace v8 | 941 } // namespace v8 |
OLD | NEW |