Chromium Code Reviews| 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 |
| 11 class BytecodeArrayBuilder::PreviousBytecodeHelper { | 11 class BytecodeArrayBuilder::PreviousBytecodeHelper BASE_EMBEDDED { |
| 12 public: | 12 public: |
| 13 explicit PreviousBytecodeHelper(const BytecodeArrayBuilder& array_builder) | 13 explicit PreviousBytecodeHelper(const BytecodeArrayBuilder& array_builder) |
| 14 : array_builder_(array_builder), | 14 : array_builder_(array_builder), |
| 15 previous_bytecode_start_(array_builder_.last_bytecode_start_) { | 15 previous_bytecode_start_(array_builder_.last_bytecode_start_) { |
| 16 // This helper is expected to be instantiated only when the last bytecode is | 16 // This helper is expected to be instantiated only when the last bytecode is |
| 17 // in the same basic block. | 17 // in the same basic block. |
| 18 DCHECK(array_builder_.LastBytecodeInSameBlock()); | 18 DCHECK(array_builder_.LastBytecodeInSameBlock()); |
| 19 } | 19 } |
| 20 | 20 |
| 21 // Returns the previous bytecode in the same basic block. | 21 // Returns the previous bytecode in the same basic block. |
| 22 MUST_USE_RESULT Bytecode GetBytecode() const { | 22 MUST_USE_RESULT Bytecode GetBytecode() const { |
| 23 DCHECK_EQ(array_builder_.last_bytecode_start_, previous_bytecode_start_); | 23 DCHECK_EQ(array_builder_.last_bytecode_start_, previous_bytecode_start_); |
| 24 return Bytecodes::FromByte( | 24 return Bytecodes::FromByte( |
| 25 array_builder_.bytecodes()->at(previous_bytecode_start_)); | 25 array_builder_.bytecodes()->at(previous_bytecode_start_)); |
| 26 } | 26 } |
| 27 | 27 |
| 28 // Returns the operand at operand_index for the previous bytecode in the | 28 // Returns the operand at operand_index for the previous bytecode in the |
| 29 // same basic block. | 29 // same basic block. |
| 30 MUST_USE_RESULT uint32_t GetOperand(int operand_index) const { | 30 MUST_USE_RESULT uint32_t GetOperand(int operand_index) const { |
| 31 DCHECK_EQ(array_builder_.last_bytecode_start_, previous_bytecode_start_); | 31 DCHECK_EQ(array_builder_.last_bytecode_start_, previous_bytecode_start_); |
| 32 Bytecode bytecode = GetBytecode(); | 32 Bytecode bytecode = GetBytecode(); |
| 33 DCHECK_GE(operand_index, 0); | 33 DCHECK_GE(operand_index, 0); |
| 34 DCHECK_LT(operand_index, Bytecodes::NumberOfOperands(bytecode)); | 34 DCHECK_LT(operand_index, Bytecodes::NumberOfOperands(bytecode)); |
| 35 size_t operand_offset = | 35 size_t operand_offset = |
| 36 previous_bytecode_start_ + | 36 previous_bytecode_start_ + |
| 37 Bytecodes::GetOperandOffset(bytecode, operand_index); | 37 Bytecodes::GetOperandOffset(bytecode, operand_index); |
| 38 OperandSize size = Bytecodes::GetOperandSize(bytecode, operand_index); | 38 OperandSize size = Bytecodes::GetOperandSize(bytecode, operand_index); |
| 39 switch (size) { | 39 switch (size) { |
| 40 default: | |
| 41 case OperandSize::kNone: | 40 case OperandSize::kNone: |
| 42 UNREACHABLE(); | 41 UNREACHABLE(); |
| 42 break; | |
| 43 case OperandSize::kByte: | 43 case OperandSize::kByte: |
| 44 return static_cast<uint32_t>( | 44 return static_cast<uint32_t>( |
| 45 array_builder_.bytecodes()->at(operand_offset)); | 45 array_builder_.bytecodes()->at(operand_offset)); |
| 46 case OperandSize::kShort: | 46 case OperandSize::kShort: |
| 47 uint16_t operand = | 47 uint16_t operand = |
| 48 (array_builder_.bytecodes()->at(operand_offset) << 8) + | 48 (array_builder_.bytecodes()->at(operand_offset) << 8) + |
| 49 array_builder_.bytecodes()->at(operand_offset + 1); | 49 array_builder_.bytecodes()->at(operand_offset + 1); |
| 50 return static_cast<uint32_t>(operand); | 50 return static_cast<uint32_t>(operand); |
| 51 } | 51 } |
| 52 return 0; | |
| 52 } | 53 } |
| 53 | 54 |
| 54 Handle<Object> GetConstantForIndexOperand(int operand_index) const { | 55 Handle<Object> GetConstantForIndexOperand(int operand_index) const { |
| 55 return array_builder_.constant_array_builder()->At( | 56 return array_builder_.constant_array_builder()->At( |
| 56 GetOperand(operand_index)); | 57 GetOperand(operand_index)); |
| 57 } | 58 } |
| 58 | 59 |
| 59 private: | 60 private: |
| 60 const BytecodeArrayBuilder& array_builder_; | 61 const BytecodeArrayBuilder& array_builder_; |
| 61 size_t previous_bytecode_start_; | 62 size_t previous_bytecode_start_; |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 72 constant_array_builder_(isolate, zone), | 73 constant_array_builder_(isolate, zone), |
| 73 handler_table_builder_(isolate, zone), | 74 handler_table_builder_(isolate, zone), |
| 74 last_block_end_(0), | 75 last_block_end_(0), |
| 75 last_bytecode_start_(~0), | 76 last_bytecode_start_(~0), |
| 76 exit_seen_in_block_(false), | 77 exit_seen_in_block_(false), |
| 77 unbound_jumps_(0), | 78 unbound_jumps_(0), |
| 78 parameter_count_(-1), | 79 parameter_count_(-1), |
| 79 local_register_count_(-1), | 80 local_register_count_(-1), |
| 80 context_register_count_(-1), | 81 context_register_count_(-1), |
| 81 temporary_register_count_(0), | 82 temporary_register_count_(0), |
| 82 free_temporaries_(zone) {} | 83 free_temporaries_(zone), |
| 84 register_translator_(this) {} | |
| 83 | 85 |
| 84 | 86 |
| 85 BytecodeArrayBuilder::~BytecodeArrayBuilder() { DCHECK_EQ(0, unbound_jumps_); } | 87 BytecodeArrayBuilder::~BytecodeArrayBuilder() { DCHECK_EQ(0, unbound_jumps_); } |
| 86 | 88 |
| 87 | 89 |
| 88 void BytecodeArrayBuilder::set_locals_count(int number_of_locals) { | 90 void BytecodeArrayBuilder::set_locals_count(int number_of_locals) { |
| 89 local_register_count_ = number_of_locals; | 91 local_register_count_ = number_of_locals; |
| 90 DCHECK_LE(context_register_count_, 0); | 92 DCHECK_LE(context_register_count_, 0); |
| 91 } | 93 } |
| 92 | 94 |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 141 return temporary_register_count_ > 0 && first_temporary_register() <= reg && | 143 return temporary_register_count_ > 0 && first_temporary_register() <= reg && |
| 142 reg <= last_temporary_register(); | 144 reg <= last_temporary_register(); |
| 143 } | 145 } |
| 144 | 146 |
| 145 | 147 |
| 146 Handle<BytecodeArray> BytecodeArrayBuilder::ToBytecodeArray() { | 148 Handle<BytecodeArray> BytecodeArrayBuilder::ToBytecodeArray() { |
| 147 DCHECK_EQ(bytecode_generated_, false); | 149 DCHECK_EQ(bytecode_generated_, false); |
| 148 EnsureReturn(); | 150 EnsureReturn(); |
| 149 | 151 |
| 150 int bytecode_size = static_cast<int>(bytecodes_.size()); | 152 int bytecode_size = static_cast<int>(bytecodes_.size()); |
| 151 int register_count = fixed_register_count() + temporary_register_count_; | 153 int register_count = |
| 154 fixed_and_temporary_register_count() + translation_register_count(); | |
| 152 int frame_size = register_count * kPointerSize; | 155 int frame_size = register_count * kPointerSize; |
| 153 Handle<FixedArray> constant_pool = constant_array_builder()->ToFixedArray(); | 156 Handle<FixedArray> constant_pool = constant_array_builder()->ToFixedArray(); |
| 154 Handle<FixedArray> handler_table = handler_table_builder()->ToHandlerTable(); | 157 Handle<FixedArray> handler_table = handler_table_builder()->ToHandlerTable(); |
| 155 Handle<BytecodeArray> output = isolate_->factory()->NewBytecodeArray( | 158 Handle<BytecodeArray> output = isolate_->factory()->NewBytecodeArray( |
| 156 bytecode_size, &bytecodes_.front(), frame_size, parameter_count(), | 159 bytecode_size, &bytecodes_.front(), frame_size, parameter_count(), |
| 157 constant_pool); | 160 constant_pool); |
| 158 output->set_handler_table(*handler_table); | 161 output->set_handler_table(*handler_table); |
| 159 bytecode_generated_ = true; | 162 bytecode_generated_ = true; |
| 160 return output; | 163 return output; |
| 161 } | 164 } |
| 162 | 165 |
| 163 | 166 |
| 164 template <size_t N> | 167 template <size_t N> |
| 165 void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t(&operands)[N]) { | 168 void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t(&operands)[N]) { |
| 166 // Don't output dead code. | 169 // Don't output dead code. |
| 167 if (exit_seen_in_block_) return; | 170 if (exit_seen_in_block_) return; |
| 168 | 171 |
| 169 DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), static_cast<int>(N)); | 172 int operand_count = static_cast<int>(N); |
| 173 DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), operand_count); | |
| 174 | |
| 175 int register_operand_count = Bytecodes::NumberOfRegisterOperands(bytecode); | |
| 176 if (register_operand_count > 0) { | |
| 177 register_translator()->TranslateRegisters(bytecode, operands, | |
| 178 operand_count); | |
| 179 } | |
| 180 | |
| 170 last_bytecode_start_ = bytecodes()->size(); | 181 last_bytecode_start_ = bytecodes()->size(); |
| 171 bytecodes()->push_back(Bytecodes::ToByte(bytecode)); | 182 bytecodes()->push_back(Bytecodes::ToByte(bytecode)); |
| 172 for (int i = 0; i < static_cast<int>(N); i++) { | 183 for (int i = 0; i < operand_count; i++) { |
| 173 DCHECK(OperandIsValid(bytecode, i, operands[i])); | 184 DCHECK(OperandIsValid(bytecode, i, operands[i])); |
| 174 switch (Bytecodes::GetOperandSize(bytecode, i)) { | 185 switch (Bytecodes::GetOperandSize(bytecode, i)) { |
| 175 case OperandSize::kNone: | 186 case OperandSize::kNone: |
| 176 UNREACHABLE(); | 187 UNREACHABLE(); |
| 188 break; | |
| 177 case OperandSize::kByte: | 189 case OperandSize::kByte: |
| 178 bytecodes()->push_back(static_cast<uint8_t>(operands[i])); | 190 bytecodes()->push_back(static_cast<uint8_t>(operands[i])); |
| 179 break; | 191 break; |
| 180 case OperandSize::kShort: { | 192 case OperandSize::kShort: { |
| 181 uint8_t operand_bytes[2]; | 193 uint8_t operand_bytes[2]; |
| 182 WriteUnalignedUInt16(operand_bytes, operands[i]); | 194 WriteUnalignedUInt16(operand_bytes, operands[i]); |
| 183 bytecodes()->insert(bytecodes()->end(), operand_bytes, | 195 bytecodes()->insert(bytecodes()->end(), operand_bytes, |
| 184 operand_bytes + 2); | 196 operand_bytes + 2); |
| 185 break; | 197 break; |
| 186 } | 198 } |
| 187 } | 199 } |
| 188 } | 200 } |
| 201 | |
| 202 if (register_operand_count > 0) { | |
| 203 register_translator()->UntranslateRegisters(); | |
|
rmcilroy
2016/01/25 12:12:05
Not sure about the naming of UntranslateRegisters.
oth
2016/01/25 16:51:56
Done as discussed TranslateInputRegisters/Translat
| |
| 204 } | |
| 189 } | 205 } |
| 190 | 206 |
| 191 | 207 |
| 192 void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t operand0, | 208 void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t operand0, |
| 193 uint32_t operand1, uint32_t operand2, | 209 uint32_t operand1, uint32_t operand2, |
| 194 uint32_t operand3) { | 210 uint32_t operand3) { |
| 195 uint32_t operands[] = {operand0, operand1, operand2, operand3}; | 211 uint32_t operands[] = {operand0, operand1, operand2, operand3}; |
| 196 Output(bytecode, operands); | 212 Output(bytecode, operands); |
| 197 } | 213 } |
| 198 | 214 |
| (...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 354 if (!IsRegisterInAccumulator(reg)) { | 370 if (!IsRegisterInAccumulator(reg)) { |
| 355 Output(Bytecode::kStar, reg.ToRawOperand()); | 371 Output(Bytecode::kStar, reg.ToRawOperand()); |
| 356 } | 372 } |
| 357 return *this; | 373 return *this; |
| 358 } | 374 } |
| 359 | 375 |
| 360 | 376 |
| 361 BytecodeArrayBuilder& BytecodeArrayBuilder::MoveRegister(Register from, | 377 BytecodeArrayBuilder& BytecodeArrayBuilder::MoveRegister(Register from, |
| 362 Register to) { | 378 Register to) { |
| 363 DCHECK(from != to); | 379 DCHECK(from != to); |
| 364 if (FitsInReg8Operand(to) && FitsInReg8Operand(from)) { | 380 // Move bytecodes modify the stack. Chacking validity is essential. |
|
rmcilroy
2016/01/25 12:12:05
I'm not sure what this comment means? I'm guessing
oth
2016/01/25 16:51:56
Have changed this to a DCHECK for the purpose of t
| |
| 381 if (FitsInReg8Operand(from) && FitsInReg8Operand(to)) { | |
| 382 CHECK(RegisterIsValid(from, OperandType::kReg8) && | |
| 383 RegisterIsValid(to, OperandType::kReg8)); | |
| 365 Output(Bytecode::kMov, from.ToRawOperand(), to.ToRawOperand()); | 384 Output(Bytecode::kMov, from.ToRawOperand(), to.ToRawOperand()); |
| 366 } else if (FitsInReg16Operand(to) && FitsInReg16Operand(from)) { | 385 } else if (FitsInReg16Operand(from) && FitsInReg16Operand(to)) { |
| 386 CHECK(RegisterIsValid(from, OperandType::kReg16) && | |
| 387 RegisterIsValid(to, OperandType::kReg16)); | |
| 367 Output(Bytecode::kMovWide, from.ToRawOperand(), to.ToRawOperand()); | 388 Output(Bytecode::kMovWide, from.ToRawOperand(), to.ToRawOperand()); |
| 368 } else { | 389 } else { |
| 369 UNIMPLEMENTED(); | 390 UNIMPLEMENTED(); |
| 370 } | 391 } |
| 371 return *this; | 392 return *this; |
| 372 } | 393 } |
| 373 | 394 |
| 374 | 395 |
| 396 void BytecodeArrayBuilder::MoveRegisterUntranslated(Register from, | |
| 397 Register to) { | |
| 398 // Move bytecodes modify the stack. Chacking validity is essential. | |
| 399 if (FitsInReg8OperandUntranslated(from)) { | |
| 400 CHECK(RegisterIsValid(from, OperandType::kReg8) && | |
| 401 RegisterIsValid(to, OperandType::kReg16)); | |
| 402 } else if (FitsInReg8OperandUntranslated(to)) { | |
| 403 CHECK(RegisterIsValid(from, OperandType::kReg16) && | |
| 404 RegisterIsValid(to, OperandType::kReg8)); | |
| 405 } else { | |
| 406 UNIMPLEMENTED(); | |
| 407 } | |
| 408 Output(Bytecode::kMovWide, from.ToRawOperand(), to.ToRawOperand()); | |
| 409 } | |
| 410 | |
| 411 | |
| 375 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadGlobal( | 412 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadGlobal( |
| 376 const Handle<String> name, int feedback_slot, LanguageMode language_mode, | 413 const Handle<String> name, int feedback_slot, LanguageMode language_mode, |
| 377 TypeofMode typeof_mode) { | 414 TypeofMode typeof_mode) { |
| 378 // TODO(rmcilroy): Potentially store language and typeof information in an | 415 // TODO(rmcilroy): Potentially store language and typeof information in an |
| 379 // operand rather than having extra bytecodes. | 416 // operand rather than having extra bytecodes. |
| 380 Bytecode bytecode = BytecodeForLoadGlobal(language_mode, typeof_mode); | 417 Bytecode bytecode = BytecodeForLoadGlobal(language_mode, typeof_mode); |
| 381 size_t name_index = GetConstantPoolEntry(name); | 418 size_t name_index = GetConstantPoolEntry(name); |
| 382 if (FitsInIdx8Operand(name_index) && FitsInIdx8Operand(feedback_slot)) { | 419 if (FitsInIdx8Operand(name_index) && FitsInIdx8Operand(feedback_slot)) { |
| 383 Output(bytecode, static_cast<uint8_t>(name_index), | 420 Output(bytecode, static_cast<uint8_t>(name_index), |
| 384 static_cast<uint8_t>(feedback_slot)); | 421 static_cast<uint8_t>(feedback_slot)); |
| (...skipping 691 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1076 } | 1113 } |
| 1077 | 1114 |
| 1078 | 1115 |
| 1079 BytecodeArrayBuilder& BytecodeArrayBuilder::New(Register constructor, | 1116 BytecodeArrayBuilder& BytecodeArrayBuilder::New(Register constructor, |
| 1080 Register first_arg, | 1117 Register first_arg, |
| 1081 size_t arg_count) { | 1118 size_t arg_count) { |
| 1082 if (!first_arg.is_valid()) { | 1119 if (!first_arg.is_valid()) { |
| 1083 DCHECK_EQ(0u, arg_count); | 1120 DCHECK_EQ(0u, arg_count); |
| 1084 first_arg = Register(0); | 1121 first_arg = Register(0); |
| 1085 } | 1122 } |
| 1086 | |
| 1087 if (FitsInReg8Operand(constructor) && FitsInReg8Operand(first_arg) && | 1123 if (FitsInReg8Operand(constructor) && FitsInReg8Operand(first_arg) && |
| 1088 FitsInIdx8Operand(arg_count)) { | 1124 FitsInIdx8Operand(arg_count)) { |
| 1089 Output(Bytecode::kNew, constructor.ToRawOperand(), first_arg.ToRawOperand(), | 1125 Output(Bytecode::kNew, constructor.ToRawOperand(), first_arg.ToRawOperand(), |
| 1090 static_cast<uint8_t>(arg_count)); | 1126 static_cast<uint8_t>(arg_count)); |
| 1091 } else if (FitsInReg16Operand(constructor) && FitsInReg16Operand(first_arg) && | 1127 } else if (FitsInReg16Operand(constructor) && FitsInReg16Operand(first_arg) && |
| 1092 FitsInIdx16Operand(arg_count)) { | 1128 FitsInIdx16Operand(arg_count)) { |
| 1093 Output(Bytecode::kNewWide, constructor.ToRawOperand(), | 1129 Output(Bytecode::kNewWide, constructor.ToRawOperand(), |
| 1094 first_arg.ToRawOperand(), static_cast<uint16_t>(arg_count)); | 1130 first_arg.ToRawOperand(), static_cast<uint16_t>(arg_count)); |
| 1095 } else { | 1131 } else { |
| 1096 UNIMPLEMENTED(); | 1132 UNIMPLEMENTED(); |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1174 Output(Bytecode::kDeleteLookupSlot); | 1210 Output(Bytecode::kDeleteLookupSlot); |
| 1175 return *this; | 1211 return *this; |
| 1176 } | 1212 } |
| 1177 | 1213 |
| 1178 | 1214 |
| 1179 size_t BytecodeArrayBuilder::GetConstantPoolEntry(Handle<Object> object) { | 1215 size_t BytecodeArrayBuilder::GetConstantPoolEntry(Handle<Object> object) { |
| 1180 return constant_array_builder()->Insert(object); | 1216 return constant_array_builder()->Insert(object); |
| 1181 } | 1217 } |
| 1182 | 1218 |
| 1183 | 1219 |
| 1220 void BytecodeArrayBuilder::ForgeTemporaryRegister() { | |
| 1221 temporary_register_count_++; | |
| 1222 } | |
| 1223 | |
| 1224 | |
| 1184 int BytecodeArrayBuilder::BorrowTemporaryRegister() { | 1225 int BytecodeArrayBuilder::BorrowTemporaryRegister() { |
| 1185 if (free_temporaries_.empty()) { | 1226 if (free_temporaries_.empty()) { |
| 1186 temporary_register_count_ += 1; | 1227 ForgeTemporaryRegister(); |
| 1187 return last_temporary_register().index(); | 1228 return last_temporary_register().index(); |
| 1188 } else { | 1229 } else { |
| 1189 auto pos = free_temporaries_.begin(); | 1230 auto pos = free_temporaries_.begin(); |
| 1190 int retval = *pos; | 1231 int retval = *pos; |
| 1191 free_temporaries_.erase(pos); | 1232 free_temporaries_.erase(pos); |
| 1192 return retval; | 1233 return retval; |
| 1193 } | 1234 } |
| 1194 } | 1235 } |
| 1195 | 1236 |
| 1196 | 1237 |
| 1197 int BytecodeArrayBuilder::BorrowTemporaryRegisterNotInRange(int start_index, | 1238 int BytecodeArrayBuilder::BorrowTemporaryRegisterNotInRange(int start_index, |
| 1198 int end_index) { | 1239 int end_index) { |
| 1199 auto index = free_temporaries_.lower_bound(start_index); | 1240 auto index = free_temporaries_.lower_bound(start_index); |
| 1200 if (index == free_temporaries_.begin()) { | 1241 if (index == free_temporaries_.begin()) { |
| 1201 // If start_index is the first free register, check for a register | 1242 // If start_index is the first free register, check for a register |
| 1202 // greater than end_index. | 1243 // greater than end_index. |
| 1203 index = free_temporaries_.upper_bound(end_index); | 1244 index = free_temporaries_.upper_bound(end_index); |
| 1204 if (index == free_temporaries_.end()) { | 1245 if (index == free_temporaries_.end()) { |
| 1205 temporary_register_count_ += 1; | 1246 ForgeTemporaryRegister(); |
| 1206 return last_temporary_register().index(); | 1247 return last_temporary_register().index(); |
| 1207 } | 1248 } |
| 1208 } else { | 1249 } else { |
| 1209 // If there is a free register < start_index | 1250 // If there is a free register < start_index |
| 1210 index--; | 1251 index--; |
| 1211 } | 1252 } |
| 1212 | 1253 |
| 1213 int retval = *index; | 1254 int retval = *index; |
| 1214 free_temporaries_.erase(index); | 1255 free_temporaries_.erase(index); |
| 1215 return retval; | 1256 return retval; |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 1227 free_temporaries_.insert(reg_index); | 1268 free_temporaries_.insert(reg_index); |
| 1228 } | 1269 } |
| 1229 | 1270 |
| 1230 | 1271 |
| 1231 int BytecodeArrayBuilder::PrepareForConsecutiveTemporaryRegisters( | 1272 int BytecodeArrayBuilder::PrepareForConsecutiveTemporaryRegisters( |
| 1232 size_t count) { | 1273 size_t count) { |
| 1233 if (count == 0) { | 1274 if (count == 0) { |
| 1234 return -1; | 1275 return -1; |
| 1235 } | 1276 } |
| 1236 | 1277 |
| 1278 // TODO(oth): replace use of set<> here for free_temporaries with a | |
| 1279 // more efficient structure. And/or partition into two searches - | |
| 1280 // one before the translation window and one after. | |
| 1281 | |
| 1282 // A run will require at least |count| free temporaries. | |
| 1283 while (free_temporaries_.size() < count) { | |
| 1284 ForgeTemporaryRegister(); | |
| 1285 free_temporaries_.insert(last_temporary_register().index()); | |
| 1286 } | |
| 1287 | |
| 1237 // Search within existing temporaries for a run. | 1288 // Search within existing temporaries for a run. |
| 1238 auto start = free_temporaries_.begin(); | 1289 auto start = free_temporaries_.begin(); |
| 1239 size_t run_length = 0; | 1290 size_t run_length = 0; |
| 1240 for (auto run_end = start; run_end != free_temporaries_.end(); run_end++) { | 1291 for (auto run_end = start; run_end != free_temporaries_.end(); run_end++) { |
| 1241 if (*run_end != *start + static_cast<int>(run_length)) { | 1292 int expected = *start + static_cast<int>(run_length); |
| 1293 if (*run_end != expected) { | |
| 1242 start = run_end; | 1294 start = run_end; |
| 1243 run_length = 0; | 1295 run_length = 0; |
| 1244 } | 1296 } |
| 1297 Register reg_start(*start); | |
| 1298 Register reg_expected(expected); | |
| 1299 if (RegisterTranslator::DistanceToTranslationWindow(reg_start) > 0 && | |
| 1300 RegisterTranslator::DistanceToTranslationWindow(reg_expected) <= 0) { | |
| 1301 // Run straddles the lower edge of the translation window. Registers | |
| 1302 // after the start of this boundary are displaced by the register | |
| 1303 // translator to provide a hole for translation. Runs either side | |
| 1304 // of the boundary are fine. | |
| 1305 start = run_end; | |
| 1306 run_length = 0; | |
| 1307 } | |
| 1245 if (++run_length == count) { | 1308 if (++run_length == count) { |
| 1246 return *start; | 1309 return *start; |
| 1247 } | 1310 } |
| 1248 } | 1311 } |
| 1249 | 1312 |
| 1250 // Continue run if possible across existing last temporary. | 1313 // Continue run if possible across existing last temporary. |
| 1251 if (temporary_register_count_ > 0 && | 1314 if (temporary_register_count_ > 0 && |
| 1252 (start == free_temporaries_.end() || | 1315 (start == free_temporaries_.end() || |
| 1253 *start + static_cast<int>(run_length) != | 1316 *start + static_cast<int>(run_length) != |
| 1254 last_temporary_register().index() + 1)) { | 1317 last_temporary_register().index() + 1)) { |
| 1255 run_length = 0; | 1318 run_length = 0; |
| 1256 } | 1319 } |
| 1257 | 1320 |
| 1321 // Pad temporaries if extended run would cross translation boundary. | |
| 1322 Register reg_first(*start); | |
| 1323 Register reg_last(*start + static_cast<int>(count) - 1); | |
| 1324 DCHECK_GT(RegisterTranslator::DistanceToTranslationWindow(reg_first), | |
| 1325 RegisterTranslator::DistanceToTranslationWindow(reg_last)); | |
| 1326 while (RegisterTranslator::DistanceToTranslationWindow(reg_first) > 0 && | |
| 1327 RegisterTranslator::DistanceToTranslationWindow(reg_last) <= 0) { | |
| 1328 ForgeTemporaryRegister(); | |
| 1329 free_temporaries_.insert(last_temporary_register().index()); | |
| 1330 start = --free_temporaries_.end(); | |
| 1331 reg_first = Register(*start); | |
| 1332 reg_last = Register(*start + static_cast<int>(count) - 1); | |
| 1333 run_length = 0; | |
| 1334 } | |
| 1335 | |
| 1258 // Ensure enough registers for run. | 1336 // Ensure enough registers for run. |
| 1259 while (run_length++ < count) { | 1337 while (run_length++ < count) { |
| 1260 temporary_register_count_++; | 1338 ForgeTemporaryRegister(); |
| 1261 free_temporaries_.insert(last_temporary_register().index()); | 1339 free_temporaries_.insert(last_temporary_register().index()); |
| 1262 } | 1340 } |
| 1263 return last_temporary_register().index() - static_cast<int>(count) + 1; | 1341 |
| 1342 int run_start = | |
| 1343 last_temporary_register().index() - static_cast<int>(count) + 1; | |
| 1344 DCHECK(RegisterTranslator::DistanceToTranslationWindow(Register(run_start)) <= | |
| 1345 0 || | |
| 1346 RegisterTranslator::DistanceToTranslationWindow( | |
| 1347 Register(run_start + static_cast<int>(count) - 1)) > 0); | |
| 1348 return run_start; | |
| 1264 } | 1349 } |
| 1265 | 1350 |
| 1266 | 1351 |
| 1267 bool BytecodeArrayBuilder::TemporaryRegisterIsLive(Register reg) const { | 1352 bool BytecodeArrayBuilder::TemporaryRegisterIsLive(Register reg) const { |
| 1268 if (temporary_register_count_ > 0) { | 1353 if (temporary_register_count_ > 0) { |
| 1269 DCHECK(reg.index() >= first_temporary_register().index() && | 1354 DCHECK(reg.index() >= first_temporary_register().index() && |
| 1270 reg.index() <= last_temporary_register().index()); | 1355 reg.index() <= last_temporary_register().index()); |
| 1271 return free_temporaries_.find(reg.index()) == free_temporaries_.end(); | 1356 return free_temporaries_.find(reg.index()) == free_temporaries_.end(); |
| 1272 } else { | 1357 } else { |
| 1273 return false; | 1358 return false; |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1324 } | 1409 } |
| 1325 UNREACHABLE(); | 1410 UNREACHABLE(); |
| 1326 return false; | 1411 return false; |
| 1327 } | 1412 } |
| 1328 | 1413 |
| 1329 | 1414 |
| 1330 bool BytecodeArrayBuilder::RegisterIsValid(Register reg, | 1415 bool BytecodeArrayBuilder::RegisterIsValid(Register reg, |
| 1331 OperandType reg_type) const { | 1416 OperandType reg_type) const { |
| 1332 switch (Bytecodes::SizeOfOperand(reg_type)) { | 1417 switch (Bytecodes::SizeOfOperand(reg_type)) { |
| 1333 case OperandSize::kByte: | 1418 case OperandSize::kByte: |
| 1334 if (!FitsInReg8Operand(reg)) { return false; } | 1419 if (!FitsInReg8OperandUntranslated(reg)) { |
| 1420 return false; | |
| 1421 } | |
| 1335 break; | 1422 break; |
| 1336 case OperandSize::kShort: | 1423 case OperandSize::kShort: |
| 1337 if (!FitsInReg16Operand(reg)) { return false; } | 1424 if (!FitsInReg16OperandUntranslated(reg)) { |
| 1425 return false; | |
| 1426 } | |
| 1338 break; | 1427 break; |
| 1339 case OperandSize::kNone: | 1428 case OperandSize::kNone: |
| 1340 UNREACHABLE(); | 1429 UNREACHABLE(); |
| 1341 return false; | 1430 return false; |
| 1342 } | 1431 } |
| 1343 | 1432 |
| 1344 if (reg.is_current_context() || reg.is_function_closure() || | 1433 if (reg.is_current_context() || reg.is_function_closure() || |
| 1345 reg.is_new_target()) { | 1434 reg.is_new_target()) { |
| 1346 return true; | 1435 return true; |
| 1347 } else if (reg.is_parameter()) { | 1436 } else if (reg.is_parameter()) { |
| 1348 int parameter_index = reg.ToParameterIndex(parameter_count_); | 1437 int parameter_index = reg.ToParameterIndex(parameter_count()); |
| 1349 return parameter_index >= 0 && parameter_index < parameter_count_; | 1438 return parameter_index >= 0 && parameter_index < parameter_count(); |
| 1350 } else if (reg.index() < fixed_register_count()) { | |
| 1351 return true; | |
| 1352 } else { | 1439 } else { |
| 1353 return TemporaryRegisterIsLive(reg); | 1440 int register_limit = |
| 1441 (fixed_and_temporary_register_count() + translation_register_count()); | |
| 1442 return reg.index() < register_limit; | |
|
rmcilroy
2016/01/25 12:12:05
Same comment as last time on this line - looks lik
oth
2016/01/25 16:51:56
No, brain melt. Fixed.
| |
| 1354 } | 1443 } |
| 1355 } | 1444 } |
| 1356 | 1445 |
| 1357 | 1446 |
| 1358 bool BytecodeArrayBuilder::LastBytecodeInSameBlock() const { | 1447 bool BytecodeArrayBuilder::LastBytecodeInSameBlock() const { |
| 1359 return last_bytecode_start_ < bytecodes()->size() && | 1448 return last_bytecode_start_ < bytecodes()->size() && |
| 1360 last_bytecode_start_ >= last_block_end_; | 1449 last_bytecode_start_ >= last_block_end_; |
| 1361 } | 1450 } |
| 1362 | 1451 |
| 1363 | 1452 |
| 1364 bool BytecodeArrayBuilder::IsRegisterInAccumulator(Register reg) { | 1453 bool BytecodeArrayBuilder::IsRegisterInAccumulator(Register reg) { |
| 1365 if (LastBytecodeInSameBlock()) { | 1454 if (LastBytecodeInSameBlock()) { |
| 1366 PreviousBytecodeHelper previous_bytecode(*this); | 1455 PreviousBytecodeHelper previous_bytecode(*this); |
| 1367 Bytecode bytecode = previous_bytecode.GetBytecode(); | 1456 Bytecode bytecode = previous_bytecode.GetBytecode(); |
| 1368 if ((bytecode == Bytecode::kLdar || bytecode == Bytecode::kStar) && | 1457 if (bytecode == Bytecode::kLdar || bytecode == Bytecode::kStar) { |
| 1369 (reg == Register::FromOperand(previous_bytecode.GetOperand(0)))) { | 1458 Register previous_reg = |
| 1370 return true; | 1459 Register::FromOperand(previous_bytecode.GetOperand(0)); |
| 1460 return previous_reg == reg; | |
| 1371 } | 1461 } |
| 1372 } | 1462 } |
| 1373 return false; | 1463 return false; |
| 1374 } | 1464 } |
| 1375 | 1465 |
| 1376 | 1466 |
| 1377 // static | 1467 // static |
| 1378 Bytecode BytecodeArrayBuilder::BytecodeForBinaryOperation(Token::Value op) { | 1468 Bytecode BytecodeArrayBuilder::BytecodeForBinaryOperation(Token::Value op) { |
| 1379 switch (op) { | 1469 switch (op) { |
| 1380 case Token::Value::ADD: | 1470 case Token::Value::ADD: |
| (...skipping 292 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1673 | 1763 |
| 1674 | 1764 |
| 1675 // static | 1765 // static |
| 1676 bool BytecodeArrayBuilder::FitsInIdx16Operand(size_t value) { | 1766 bool BytecodeArrayBuilder::FitsInIdx16Operand(size_t value) { |
| 1677 return value <= static_cast<size_t>(kMaxUInt16); | 1767 return value <= static_cast<size_t>(kMaxUInt16); |
| 1678 } | 1768 } |
| 1679 | 1769 |
| 1680 | 1770 |
| 1681 // static | 1771 // static |
| 1682 bool BytecodeArrayBuilder::FitsInReg8Operand(Register value) { | 1772 bool BytecodeArrayBuilder::FitsInReg8Operand(Register value) { |
| 1683 return kMinInt8 <= value.index() && value.index() <= kMaxInt8; | 1773 return RegisterTranslator::FitsInReg8Operand(value); |
| 1774 } | |
| 1775 | |
| 1776 | |
| 1777 // static | |
| 1778 bool BytecodeArrayBuilder::FitsInReg8OperandUntranslated(Register value) { | |
| 1779 return value.is_byte_operand(); | |
| 1684 } | 1780 } |
| 1685 | 1781 |
| 1686 | 1782 |
| 1687 // static | 1783 // static |
| 1688 bool BytecodeArrayBuilder::FitsInReg16Operand(Register value) { | 1784 bool BytecodeArrayBuilder::FitsInReg16Operand(Register value) { |
| 1689 return kMinInt16 <= value.index() && value.index() <= kMaxInt16; | 1785 return RegisterTranslator::FitsInReg16Operand(value); |
| 1786 } | |
| 1787 | |
| 1788 | |
| 1789 // static | |
| 1790 bool BytecodeArrayBuilder::FitsInReg16OperandUntranslated(Register value) { | |
| 1791 return value.is_short_operand(); | |
| 1690 } | 1792 } |
| 1691 | 1793 |
| 1692 } // namespace interpreter | 1794 } // namespace interpreter |
| 1693 } // namespace internal | 1795 } // namespace internal |
| 1694 } // namespace v8 | 1796 } // namespace v8 |
| OLD | NEW |