| 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 |