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 namespace v8 { | 7 namespace v8 { |
8 namespace internal { | 8 namespace internal { |
9 namespace interpreter { | 9 namespace interpreter { |
10 | 10 |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
102 | 102 |
103 Handle<BytecodeArray> output = | 103 Handle<BytecodeArray> output = |
104 factory->NewBytecodeArray(bytecode_size, &bytecodes_.front(), frame_size, | 104 factory->NewBytecodeArray(bytecode_size, &bytecodes_.front(), frame_size, |
105 parameter_count(), constant_pool); | 105 parameter_count(), constant_pool); |
106 bytecode_generated_ = true; | 106 bytecode_generated_ = true; |
107 return output; | 107 return output; |
108 } | 108 } |
109 | 109 |
110 | 110 |
111 template <size_t N> | 111 template <size_t N> |
112 void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t(&operands)[N]) { | 112 void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t(&operands)[N], |
| 113 RegisterValidityCheck reg_check) { |
113 DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), static_cast<int>(N)); | 114 DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), static_cast<int>(N)); |
114 last_bytecode_start_ = bytecodes()->size(); | 115 last_bytecode_start_ = bytecodes()->size(); |
115 bytecodes()->push_back(Bytecodes::ToByte(bytecode)); | 116 bytecodes()->push_back(Bytecodes::ToByte(bytecode)); |
116 for (int i = 0; i < static_cast<int>(N); i++) { | 117 for (int i = 0; i < static_cast<int>(N); i++) { |
117 DCHECK(OperandIsValid(bytecode, i, operands[i])); | 118 DCHECK(OperandIsValid(bytecode, i, operands[i], reg_check)); |
118 switch (Bytecodes::GetOperandSize(bytecode, i)) { | 119 switch (Bytecodes::GetOperandSize(bytecode, i)) { |
119 case OperandSize::kNone: | 120 case OperandSize::kNone: |
120 UNREACHABLE(); | 121 UNREACHABLE(); |
121 case OperandSize::kByte: | 122 case OperandSize::kByte: |
122 bytecodes()->push_back(static_cast<uint8_t>(operands[i])); | 123 bytecodes()->push_back(static_cast<uint8_t>(operands[i])); |
123 break; | 124 break; |
124 case OperandSize::kShort: { | 125 case OperandSize::kShort: { |
125 uint8_t operand_bytes[2]; | 126 uint8_t operand_bytes[2]; |
126 Bytecodes::ShortOperandToBytes(operands[i], operand_bytes); | 127 Bytecodes::ShortOperandToBytes(operands[i], operand_bytes); |
127 bytecodes()->insert(bytecodes()->end(), operand_bytes, | 128 bytecodes()->insert(bytecodes()->end(), operand_bytes, |
128 operand_bytes + 2); | 129 operand_bytes + 2); |
129 break; | 130 break; |
130 } | 131 } |
131 } | 132 } |
132 } | 133 } |
133 } | 134 } |
134 | 135 |
135 | 136 |
136 void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t operand0, | 137 void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t operand0, |
137 uint32_t operand1, uint32_t operand2) { | 138 uint32_t operand1, uint32_t operand2, |
| 139 RegisterValidityCheck reg_check) { |
138 uint32_t operands[] = {operand0, operand1, operand2}; | 140 uint32_t operands[] = {operand0, operand1, operand2}; |
139 Output(bytecode, operands); | 141 Output(bytecode, operands, reg_check); |
140 } | 142 } |
141 | 143 |
142 | 144 |
143 void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t operand0, | 145 void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t operand0, |
144 uint32_t operand1) { | 146 uint32_t operand1, |
| 147 RegisterValidityCheck reg_check) { |
145 uint32_t operands[] = {operand0, operand1}; | 148 uint32_t operands[] = {operand0, operand1}; |
146 Output(bytecode, operands); | 149 Output(bytecode, operands, reg_check); |
147 } | 150 } |
148 | 151 |
149 | 152 |
150 void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t operand0) { | 153 void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t operand0, |
| 154 RegisterValidityCheck reg_check) { |
151 uint32_t operands[] = {operand0}; | 155 uint32_t operands[] = {operand0}; |
152 Output(bytecode, operands); | 156 Output(bytecode, operands, reg_check); |
153 } | 157 } |
154 | 158 |
155 | 159 |
156 void BytecodeArrayBuilder::Output(Bytecode bytecode) { | 160 void BytecodeArrayBuilder::Output(Bytecode bytecode) { |
157 DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), 0); | 161 DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), 0); |
158 last_bytecode_start_ = bytecodes()->size(); | 162 last_bytecode_start_ = bytecodes()->size(); |
159 bytecodes()->push_back(Bytecodes::ToByte(bytecode)); | 163 bytecodes()->push_back(Bytecodes::ToByte(bytecode)); |
160 } | 164 } |
161 | 165 |
162 | 166 |
(...skipping 601 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
764 } else { | 768 } else { |
765 UNIMPLEMENTED(); | 769 UNIMPLEMENTED(); |
766 } | 770 } |
767 return *this; | 771 return *this; |
768 } | 772 } |
769 | 773 |
770 | 774 |
771 BytecodeArrayBuilder& BytecodeArrayBuilder::New(Register constructor, | 775 BytecodeArrayBuilder& BytecodeArrayBuilder::New(Register constructor, |
772 Register first_arg, | 776 Register first_arg, |
773 size_t arg_count) { | 777 size_t arg_count) { |
| 778 RegisterValidityCheck reg_check = RegisterValidityCheck::kCheckRegisters; |
| 779 if (arg_count == 0) { |
| 780 first_arg = Register(0); |
| 781 reg_check = RegisterValidityCheck::kDontCheckRegisters; |
| 782 } |
774 DCHECK(FitsInIdx8Operand(arg_count)); | 783 DCHECK(FitsInIdx8Operand(arg_count)); |
775 Output(Bytecode::kNew, constructor.ToOperand(), first_arg.ToOperand(), | 784 Output(Bytecode::kNew, constructor.ToOperand(), first_arg.ToOperand(), |
776 static_cast<uint8_t>(arg_count)); | 785 static_cast<uint8_t>(arg_count), reg_check); |
777 return *this; | 786 return *this; |
778 } | 787 } |
779 | 788 |
780 | 789 |
781 BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntime( | 790 BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntime( |
782 Runtime::FunctionId function_id, Register first_arg, size_t arg_count) { | 791 Runtime::FunctionId function_id, Register first_arg, size_t arg_count) { |
783 DCHECK(FitsInIdx16Operand(function_id)); | 792 DCHECK(FitsInIdx16Operand(function_id)); |
784 DCHECK(FitsInIdx8Operand(arg_count)); | 793 DCHECK(FitsInIdx8Operand(arg_count)); |
| 794 RegisterValidityCheck reg_check = RegisterValidityCheck::kCheckRegisters; |
| 795 if (arg_count == 0) { |
| 796 first_arg = Register(0); |
| 797 reg_check = RegisterValidityCheck::kDontCheckRegisters; |
| 798 } |
785 Output(Bytecode::kCallRuntime, static_cast<uint16_t>(function_id), | 799 Output(Bytecode::kCallRuntime, static_cast<uint16_t>(function_id), |
786 first_arg.ToOperand(), static_cast<uint8_t>(arg_count)); | 800 first_arg.ToOperand(), static_cast<uint8_t>(arg_count), reg_check); |
787 return *this; | 801 return *this; |
788 } | 802 } |
789 | 803 |
| 804 |
| 805 BytecodeArrayBuilder& BytecodeArrayBuilder::CallJSRuntime(int context_index, |
| 806 Register receiver, |
| 807 size_t arg_count) { |
| 808 DCHECK(FitsInIdx16Operand(context_index)); |
| 809 DCHECK(FitsInIdx8Operand(arg_count)); |
| 810 Output(Bytecode::kCallJSRuntime, static_cast<uint16_t>(context_index), |
| 811 receiver.ToOperand(), static_cast<uint8_t>(arg_count)); |
| 812 return *this; |
| 813 } |
| 814 |
790 | 815 |
791 BytecodeArrayBuilder& BytecodeArrayBuilder::Delete(Register object, | 816 BytecodeArrayBuilder& BytecodeArrayBuilder::Delete(Register object, |
792 LanguageMode language_mode) { | 817 LanguageMode language_mode) { |
793 Output(BytecodeForDelete(language_mode), object.ToOperand()); | 818 Output(BytecodeForDelete(language_mode), object.ToOperand()); |
794 return *this; | 819 return *this; |
795 } | 820 } |
796 | 821 |
797 | 822 |
798 size_t BytecodeArrayBuilder::GetConstantPoolEntry(Handle<Object> object) { | 823 size_t BytecodeArrayBuilder::GetConstantPoolEntry(Handle<Object> object) { |
799 // These constants shouldn't be added to the constant pool, the should use | 824 // These constants shouldn't be added to the constant pool, the should use |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
880 if (temporary_register_count_ > 0) { | 905 if (temporary_register_count_ > 0) { |
881 DCHECK(reg.index() >= first_temporary_register().index() && | 906 DCHECK(reg.index() >= first_temporary_register().index() && |
882 reg.index() <= last_temporary_register().index()); | 907 reg.index() <= last_temporary_register().index()); |
883 return free_temporaries_.find(reg.index()) == free_temporaries_.end(); | 908 return free_temporaries_.find(reg.index()) == free_temporaries_.end(); |
884 } else { | 909 } else { |
885 return false; | 910 return false; |
886 } | 911 } |
887 } | 912 } |
888 | 913 |
889 | 914 |
890 bool BytecodeArrayBuilder::OperandIsValid(Bytecode bytecode, int operand_index, | 915 bool BytecodeArrayBuilder::OperandIsValid( |
891 uint32_t operand_value) const { | 916 Bytecode bytecode, int operand_index, uint32_t operand_value, |
| 917 RegisterValidityCheck reg_check) const { |
892 OperandType operand_type = Bytecodes::GetOperandType(bytecode, operand_index); | 918 OperandType operand_type = Bytecodes::GetOperandType(bytecode, operand_index); |
893 switch (operand_type) { | 919 switch (operand_type) { |
894 case OperandType::kNone: | 920 case OperandType::kNone: |
895 return false; | 921 return false; |
896 case OperandType::kIdx16: | 922 case OperandType::kIdx16: |
897 return static_cast<uint16_t>(operand_value) == operand_value; | 923 return static_cast<uint16_t>(operand_value) == operand_value; |
898 case OperandType::kCount8: | 924 case OperandType::kCount8: |
899 case OperandType::kImm8: | 925 case OperandType::kImm8: |
900 case OperandType::kIdx8: | 926 case OperandType::kIdx8: |
901 return static_cast<uint8_t>(operand_value) == operand_value; | 927 return static_cast<uint8_t>(operand_value) == operand_value; |
902 case OperandType::kReg8: { | 928 case OperandType::kReg8: { |
903 Register reg = Register::FromOperand(static_cast<uint8_t>(operand_value)); | 929 Register reg = Register::FromOperand(static_cast<uint8_t>(operand_value)); |
904 if (reg.is_function_context() || reg.is_function_closure()) { | 930 if (reg_check == RegisterValidityCheck::kDontCheckRegisters) { |
| 931 return true; |
| 932 } else if (reg.is_function_context() || reg.is_function_closure()) { |
905 return true; | 933 return true; |
906 } else if (reg.is_parameter()) { | 934 } else if (reg.is_parameter()) { |
907 int parameter_index = reg.ToParameterIndex(parameter_count_); | 935 int parameter_index = reg.ToParameterIndex(parameter_count_); |
908 return parameter_index >= 0 && parameter_index < parameter_count_; | 936 return parameter_index >= 0 && parameter_index < parameter_count_; |
909 } else if (reg.index() < fixed_register_count()) { | 937 } else if (reg.index() < fixed_register_count()) { |
910 return true; | 938 return true; |
911 } else { | 939 } else { |
912 return TemporaryRegisterIsLive(reg); | 940 return TemporaryRegisterIsLive(reg); |
913 } | 941 } |
914 } | 942 } |
(...skipping 324 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1239 DCHECK_GT(next_consecutive_count_, 0); | 1267 DCHECK_GT(next_consecutive_count_, 0); |
1240 builder_->BorrowConsecutiveTemporaryRegister(next_consecutive_register_); | 1268 builder_->BorrowConsecutiveTemporaryRegister(next_consecutive_register_); |
1241 allocated_.push_back(next_consecutive_register_); | 1269 allocated_.push_back(next_consecutive_register_); |
1242 next_consecutive_count_--; | 1270 next_consecutive_count_--; |
1243 return Register(next_consecutive_register_++); | 1271 return Register(next_consecutive_register_++); |
1244 } | 1272 } |
1245 | 1273 |
1246 } // namespace interpreter | 1274 } // namespace interpreter |
1247 } // namespace internal | 1275 } // namespace internal |
1248 } // namespace v8 | 1276 } // namespace v8 |
OLD | NEW |