| OLD | NEW |
| 1 // Copyright 2016 the V8 project authors. All rights reserved. | 1 // Copyright 2016 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-register-optimizer.h" | 5 #include "src/interpreter/bytecode-register-optimizer.h" |
| 6 | 6 |
| 7 namespace v8 { | 7 namespace v8 { |
| 8 namespace internal { | 8 namespace internal { |
| 9 namespace interpreter { | 9 namespace interpreter { |
| 10 | 10 |
| 11 const uint32_t BytecodeRegisterOptimizer::kInvalidEquivalenceId; | 11 const uint32_t BytecodeRegisterOptimizer::kInvalidEquivalenceId; |
| 12 | 12 |
| 13 // A class for tracking the state of a register. This class tracks | 13 // A class for tracking the state of a register. This class tracks |
| 14 // which equivalence set a register is a member of and also whether a | 14 // which equivalence set a register is a member of and also whether a |
| 15 // register is materialized in the bytecode stream. | 15 // register is materialized in the bytecode stream. |
| 16 class BytecodeRegisterOptimizer::RegisterInfo final : public ZoneObject { | 16 class BytecodeRegisterOptimizer::RegisterInfo final : public ZoneObject { |
| 17 public: | 17 public: |
| 18 RegisterInfo(Register reg, uint32_t equivalence_id, bool materialized) | 18 RegisterInfo(Register reg, uint32_t equivalence_id, bool materialized, |
| 19 bool allocated) |
| 19 : register_(reg), | 20 : register_(reg), |
| 20 equivalence_id_(equivalence_id), | 21 equivalence_id_(equivalence_id), |
| 21 materialized_(materialized), | 22 materialized_(materialized), |
| 23 allocated_(allocated), |
| 22 next_(this), | 24 next_(this), |
| 23 prev_(this) {} | 25 prev_(this) {} |
| 24 | 26 |
| 25 void AddToEquivalenceSetOf(RegisterInfo* info); | 27 void AddToEquivalenceSetOf(RegisterInfo* info); |
| 26 void MoveToNewEquivalenceSet(uint32_t equivalence_id, bool materialized); | 28 void MoveToNewEquivalenceSet(uint32_t equivalence_id, bool materialized); |
| 27 bool IsOnlyMemberOfEquivalenceSet() const; | 29 bool IsOnlyMemberOfEquivalenceSet() const; |
| 28 bool IsOnlyMaterializedMemberOfEquivalenceSet() const; | 30 bool IsOnlyMaterializedMemberOfEquivalenceSet() const; |
| 29 bool IsInSameEquivalenceSet(RegisterInfo* info) const; | 31 bool IsInSameEquivalenceSet(RegisterInfo* info) const; |
| 30 | 32 |
| 31 // Get a member of this register's equivalence set that is | 33 // Get a member of this register's equivalence set that is |
| 32 // materialized. The materialized equivalent will be this register | 34 // materialized. The materialized equivalent will be this register |
| 33 // if it is materialized. Returns nullptr if no materialized | 35 // if it is materialized. Returns nullptr if no materialized |
| 34 // equivalent exists. | 36 // equivalent exists. |
| 35 RegisterInfo* GetMaterializedEquivalent(); | 37 RegisterInfo* GetMaterializedEquivalent(); |
| 36 | 38 |
| 37 // Get a member of this register's equivalence set that is | 39 // Get a member of this register's equivalence set that is |
| 38 // materialized and not register |reg|. The materialized equivalent | 40 // materialized and not register |reg|. The materialized equivalent |
| 39 // will be this register if it is materialized. Returns nullptr if | 41 // will be this register if it is materialized. Returns nullptr if |
| 40 // no materialized equivalent exists. | 42 // no materialized equivalent exists. |
| 41 RegisterInfo* GetMaterializedEquivalentOtherThan(Register reg); | 43 RegisterInfo* GetMaterializedEquivalentOtherThan(Register reg); |
| 42 | 44 |
| 43 // Get a member of this register's equivalence set that is intended | 45 // Get a member of this register's equivalence set that is intended |
| 44 // to be materialized in place of this register (which is currently | 46 // to be materialized in place of this register (which is currently |
| 45 // materialized). The best candidate is deemed to be the register | 47 // materialized). The best candidate is deemed to be the register |
| 46 // with the lowest index as this permits temporary registers to be | 48 // with the lowest index as this permits temporary registers to be |
| 47 // removed from the bytecode stream. Returns nullptr if no candidate | 49 // removed from the bytecode stream. Returns nullptr if no candidate |
| 48 // exists. | 50 // exists. |
| 49 RegisterInfo* GetEquivalentToMaterialize(); | 51 RegisterInfo* GetEquivalentToMaterialize(); |
| 50 | 52 |
| 53 // Marks all temporary registers of the equivalence set as unmaterialized. |
| 54 void MarkTemporariesAsUnmaterialized(Register temporary_base); |
| 55 |
| 51 // Get an equivalent register. Returns this if none exists. | 56 // Get an equivalent register. Returns this if none exists. |
| 52 RegisterInfo* GetEquivalent(); | 57 RegisterInfo* GetEquivalent(); |
| 53 | 58 |
| 54 Register register_value() const { return register_; } | 59 Register register_value() const { return register_; } |
| 55 bool materialized() const { return materialized_; } | 60 bool materialized() const { return materialized_; } |
| 56 void set_materialized(bool materialized) { materialized_ = materialized; } | 61 void set_materialized(bool materialized) { materialized_ = materialized; } |
| 62 bool allocated() const { return allocated_; } |
| 63 void set_allocated(bool allocated) { allocated_ = allocated; } |
| 57 void set_equivalence_id(uint32_t equivalence_id) { | 64 void set_equivalence_id(uint32_t equivalence_id) { |
| 58 equivalence_id_ = equivalence_id; | 65 equivalence_id_ = equivalence_id; |
| 59 } | 66 } |
| 60 uint32_t equivalence_id() const { return equivalence_id_; } | 67 uint32_t equivalence_id() const { return equivalence_id_; } |
| 61 | 68 |
| 62 private: | 69 private: |
| 63 Register register_; | 70 Register register_; |
| 64 uint32_t equivalence_id_; | 71 uint32_t equivalence_id_; |
| 65 bool materialized_; | 72 bool materialized_; |
| 73 bool allocated_; |
| 66 | 74 |
| 67 // Equivalence set pointers. | 75 // Equivalence set pointers. |
| 68 RegisterInfo* next_; | 76 RegisterInfo* next_; |
| 69 RegisterInfo* prev_; | 77 RegisterInfo* prev_; |
| 70 | 78 |
| 71 DISALLOW_COPY_AND_ASSIGN(RegisterInfo); | 79 DISALLOW_COPY_AND_ASSIGN(RegisterInfo); |
| 72 }; | 80 }; |
| 73 | 81 |
| 74 void BytecodeRegisterOptimizer::RegisterInfo::AddToEquivalenceSetOf( | 82 void BytecodeRegisterOptimizer::RegisterInfo::AddToEquivalenceSetOf( |
| 75 RegisterInfo* info) { | 83 RegisterInfo* info) { |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 148 | 156 |
| 149 BytecodeRegisterOptimizer::RegisterInfo* | 157 BytecodeRegisterOptimizer::RegisterInfo* |
| 150 BytecodeRegisterOptimizer::RegisterInfo::GetEquivalentToMaterialize() { | 158 BytecodeRegisterOptimizer::RegisterInfo::GetEquivalentToMaterialize() { |
| 151 DCHECK(this->materialized()); | 159 DCHECK(this->materialized()); |
| 152 RegisterInfo* visitor = this->next_; | 160 RegisterInfo* visitor = this->next_; |
| 153 RegisterInfo* best_info = nullptr; | 161 RegisterInfo* best_info = nullptr; |
| 154 while (visitor != this) { | 162 while (visitor != this) { |
| 155 if (visitor->materialized()) { | 163 if (visitor->materialized()) { |
| 156 return nullptr; | 164 return nullptr; |
| 157 } | 165 } |
| 158 if (best_info == nullptr || | 166 if (visitor->allocated() && |
| 159 visitor->register_value() < best_info->register_value()) { | 167 (best_info == nullptr || |
| 168 visitor->register_value() < best_info->register_value())) { |
| 160 best_info = visitor; | 169 best_info = visitor; |
| 161 } | 170 } |
| 162 visitor = visitor->next_; | 171 visitor = visitor->next_; |
| 163 } | 172 } |
| 164 return best_info; | 173 return best_info; |
| 165 } | 174 } |
| 166 | 175 |
| 176 void BytecodeRegisterOptimizer::RegisterInfo::MarkTemporariesAsUnmaterialized( |
| 177 Register temporary_base) { |
| 178 DCHECK(this->register_value() < temporary_base); |
| 179 DCHECK(this->materialized()); |
| 180 RegisterInfo* visitor = this->next_; |
| 181 while (visitor != this) { |
| 182 if (visitor->register_value() >= temporary_base) { |
| 183 visitor->set_materialized(false); |
| 184 } |
| 185 visitor = visitor->next_; |
| 186 } |
| 187 } |
| 188 |
| 167 BytecodeRegisterOptimizer::RegisterInfo* | 189 BytecodeRegisterOptimizer::RegisterInfo* |
| 168 BytecodeRegisterOptimizer::RegisterInfo::GetEquivalent() { | 190 BytecodeRegisterOptimizer::RegisterInfo::GetEquivalent() { |
| 169 return next_; | 191 return next_; |
| 170 } | 192 } |
| 171 | 193 |
| 172 BytecodeRegisterOptimizer::BytecodeRegisterOptimizer( | 194 BytecodeRegisterOptimizer::BytecodeRegisterOptimizer( |
| 173 Zone* zone, TemporaryRegisterAllocator* register_allocator, | 195 Zone* zone, BytecodeRegisterAllocator* register_allocator, |
| 174 int parameter_count, BytecodePipelineStage* next_stage) | 196 int fixed_registers_count, int parameter_count, |
| 197 BytecodePipelineStage* next_stage) |
| 175 : accumulator_(Register::virtual_accumulator()), | 198 : accumulator_(Register::virtual_accumulator()), |
| 176 temporary_base_(register_allocator->allocation_base()), | 199 temporary_base_(fixed_registers_count), |
| 177 max_register_index_(register_allocator->allocation_base() - 1), | 200 max_register_index_(fixed_registers_count - 1), |
| 178 register_info_table_(zone), | 201 register_info_table_(zone), |
| 179 equivalence_id_(0), | 202 equivalence_id_(0), |
| 180 next_stage_(next_stage), | 203 next_stage_(next_stage), |
| 181 flush_required_(false), | 204 flush_required_(false), |
| 182 zone_(zone) { | 205 zone_(zone) { |
| 183 register_allocator->set_observer(this); | 206 register_allocator->set_observer(this); |
| 184 | 207 |
| 185 // Calculate offset so register index values can be mapped into | 208 // Calculate offset so register index values can be mapped into |
| 186 // a vector of register metadata. | 209 // a vector of register metadata. |
| 187 if (parameter_count != 0) { | 210 if (parameter_count != 0) { |
| 188 register_info_table_offset_ = | 211 register_info_table_offset_ = |
| 189 -Register::FromParameterIndex(0, parameter_count).index(); | 212 -Register::FromParameterIndex(0, parameter_count).index(); |
| 190 } else { | 213 } else { |
| 191 // TODO(oth): This path shouldn't be necessary in bytecode generated | 214 // TODO(oth): This path shouldn't be necessary in bytecode generated |
| 192 // from Javascript, but a set of tests do not include the JS receiver. | 215 // from Javascript, but a set of tests do not include the JS receiver. |
| 193 register_info_table_offset_ = -accumulator_.index(); | 216 register_info_table_offset_ = -accumulator_.index(); |
| 194 } | 217 } |
| 195 | 218 |
| 196 // Initialize register map for parameters, locals, and the | 219 // Initialize register map for parameters, locals, and the |
| 197 // accumulator. | 220 // accumulator. |
| 198 register_info_table_.resize(register_info_table_offset_ + | 221 register_info_table_.resize(register_info_table_offset_ + |
| 199 static_cast<size_t>(temporary_base_.index())); | 222 static_cast<size_t>(temporary_base_.index())); |
| 200 for (size_t i = 0; i < register_info_table_.size(); ++i) { | 223 for (size_t i = 0; i < register_info_table_.size(); ++i) { |
| 201 register_info_table_[i] = new (zone) RegisterInfo( | 224 register_info_table_[i] = new (zone) RegisterInfo( |
| 202 RegisterFromRegisterInfoTableIndex(i), NextEquivalenceId(), true); | 225 RegisterFromRegisterInfoTableIndex(i), NextEquivalenceId(), true, true); |
| 203 DCHECK_EQ(register_info_table_[i]->register_value().index(), | 226 DCHECK_EQ(register_info_table_[i]->register_value().index(), |
| 204 RegisterFromRegisterInfoTableIndex(i).index()); | 227 RegisterFromRegisterInfoTableIndex(i).index()); |
| 205 } | 228 } |
| 206 accumulator_info_ = GetRegisterInfo(accumulator_); | 229 accumulator_info_ = GetRegisterInfo(accumulator_); |
| 207 DCHECK(accumulator_info_->register_value() == accumulator_); | 230 DCHECK(accumulator_info_->register_value() == accumulator_); |
| 208 } | 231 } |
| 209 | 232 |
| 210 // override | 233 // override |
| 211 Handle<BytecodeArray> BytecodeRegisterOptimizer::ToBytecodeArray( | 234 Handle<BytecodeArray> BytecodeRegisterOptimizer::ToBytecodeArray( |
| 212 Isolate* isolate, int register_count, int parameter_count, | 235 Isolate* isolate, int register_count, int parameter_count, |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 289 // Materialize all live registers and break equivalences. | 312 // Materialize all live registers and break equivalences. |
| 290 size_t count = register_info_table_.size(); | 313 size_t count = register_info_table_.size(); |
| 291 for (size_t i = 0; i < count; ++i) { | 314 for (size_t i = 0; i < count; ++i) { |
| 292 RegisterInfo* reg_info = register_info_table_[i]; | 315 RegisterInfo* reg_info = register_info_table_[i]; |
| 293 if (reg_info->materialized()) { | 316 if (reg_info->materialized()) { |
| 294 // Walk equivalents of materialized registers, materializing | 317 // Walk equivalents of materialized registers, materializing |
| 295 // each equivalent register as necessary and placing in their | 318 // each equivalent register as necessary and placing in their |
| 296 // own equivalence set. | 319 // own equivalence set. |
| 297 RegisterInfo* equivalent; | 320 RegisterInfo* equivalent; |
| 298 while ((equivalent = reg_info->GetEquivalent()) != reg_info) { | 321 while ((equivalent = reg_info->GetEquivalent()) != reg_info) { |
| 299 if (!equivalent->materialized()) { | 322 if (equivalent->allocated() && !equivalent->materialized()) { |
| 300 OutputRegisterTransfer(reg_info, equivalent); | 323 OutputRegisterTransfer(reg_info, equivalent); |
| 301 } | 324 } |
| 302 equivalent->MoveToNewEquivalenceSet(NextEquivalenceId(), true); | 325 equivalent->MoveToNewEquivalenceSet(NextEquivalenceId(), true); |
| 303 } | 326 } |
| 304 } | 327 } |
| 305 } | 328 } |
| 306 | 329 |
| 307 flush_required_ = false; | 330 flush_required_ = false; |
| 308 } | 331 } |
| 309 | 332 |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 397 RegisterIsObservable(output_info->register_value()); | 420 RegisterIsObservable(output_info->register_value()); |
| 398 if (output_is_observable) { | 421 if (output_is_observable) { |
| 399 // Force store to be emitted when register is observable. | 422 // Force store to be emitted when register is observable. |
| 400 output_info->set_materialized(false); | 423 output_info->set_materialized(false); |
| 401 RegisterInfo* materialized_info = input_info->GetMaterializedEquivalent(); | 424 RegisterInfo* materialized_info = input_info->GetMaterializedEquivalent(); |
| 402 OutputRegisterTransfer(materialized_info, output_info, source_info); | 425 OutputRegisterTransfer(materialized_info, output_info, source_info); |
| 403 } else if (source_info->is_valid()) { | 426 } else if (source_info->is_valid()) { |
| 404 // Emit a placeholder nop to maintain source position info. | 427 // Emit a placeholder nop to maintain source position info. |
| 405 EmitNopForSourceInfo(source_info); | 428 EmitNopForSourceInfo(source_info); |
| 406 } | 429 } |
| 430 |
| 431 bool input_is_observable = RegisterIsObservable(input_info->register_value()); |
| 432 if (input_is_observable) { |
| 433 // If input is observable by the debugger, mark all other temporaries |
| 434 // registers as unmaterialized so that this register is used in preference. |
| 435 input_info->MarkTemporariesAsUnmaterialized(temporary_base_); |
| 436 } |
| 407 } | 437 } |
| 408 | 438 |
| 409 void BytecodeRegisterOptimizer::EmitNopForSourceInfo( | 439 void BytecodeRegisterOptimizer::EmitNopForSourceInfo( |
| 410 BytecodeSourceInfo* source_info) const { | 440 BytecodeSourceInfo* source_info) const { |
| 411 DCHECK(source_info->is_valid()); | 441 DCHECK(source_info->is_valid()); |
| 412 BytecodeNode nop(Bytecode::kNop, source_info); | 442 BytecodeNode nop(Bytecode::kNop, source_info); |
| 413 next_stage_->Write(&nop); | 443 next_stage_->Write(&nop); |
| 414 } | 444 } |
| 415 | 445 |
| 416 void BytecodeRegisterOptimizer::DoLdar(BytecodeNode* node) { | 446 void BytecodeRegisterOptimizer::DoLdar(BytecodeNode* node) { |
| 417 Register input = GetRegisterInputOperand( | 447 Register input = GetRegisterInputOperand( |
| 418 0, node->bytecode(), node->operands(), node->operand_count()); | 448 0, node->bytecode(), node->operands(), node->operand_count()); |
| 419 RegisterInfo* input_info = GetRegisterInfo(input); | 449 RegisterInfo* input_info = GetRegisterInfo(input); |
| 420 RegisterTransfer(input_info, accumulator_info_, node->source_info_ptr()); | 450 RegisterTransfer(input_info, accumulator_info_, node->source_info_ptr()); |
| 421 } | 451 } |
| 422 | 452 |
| 423 void BytecodeRegisterOptimizer::DoMov(BytecodeNode* node) { | 453 void BytecodeRegisterOptimizer::DoMov(BytecodeNode* node) { |
| 424 Register input = GetRegisterInputOperand( | 454 Register input = GetRegisterInputOperand( |
| 425 0, node->bytecode(), node->operands(), node->operand_count()); | 455 0, node->bytecode(), node->operands(), node->operand_count()); |
| 426 RegisterInfo* input_info = GetRegisterInfo(input); | 456 RegisterInfo* input_info = GetRegisterInfo(input); |
| 427 Register output = GetRegisterOutputOperand( | 457 Register output = GetRegisterOutputOperand( |
| 428 1, node->bytecode(), node->operands(), node->operand_count()); | 458 1, node->bytecode(), node->operands(), node->operand_count()); |
| 429 RegisterInfo* output_info = GetOrCreateRegisterInfo(output); | 459 RegisterInfo* output_info = GetRegisterInfo(output); |
| 430 RegisterTransfer(input_info, output_info, node->source_info_ptr()); | 460 RegisterTransfer(input_info, output_info, node->source_info_ptr()); |
| 431 } | 461 } |
| 432 | 462 |
| 433 void BytecodeRegisterOptimizer::DoStar(BytecodeNode* node) { | 463 void BytecodeRegisterOptimizer::DoStar(BytecodeNode* node) { |
| 434 Register output = GetRegisterOutputOperand( | 464 Register output = GetRegisterOutputOperand( |
| 435 0, node->bytecode(), node->operands(), node->operand_count()); | 465 0, node->bytecode(), node->operands(), node->operand_count()); |
| 436 RegisterInfo* output_info = GetOrCreateRegisterInfo(output); | 466 RegisterInfo* output_info = GetRegisterInfo(output); |
| 437 RegisterTransfer(accumulator_info_, output_info, node->source_info_ptr()); | 467 RegisterTransfer(accumulator_info_, output_info, node->source_info_ptr()); |
| 438 } | 468 } |
| 439 | 469 |
| 440 void BytecodeRegisterOptimizer::PrepareRegisterOutputOperand( | 470 void BytecodeRegisterOptimizer::PrepareRegisterOutputOperand( |
| 441 RegisterInfo* reg_info) { | 471 RegisterInfo* reg_info) { |
| 442 if (reg_info->materialized()) { | 472 if (reg_info->materialized()) { |
| 443 CreateMaterializedEquivalent(reg_info); | 473 CreateMaterializedEquivalent(reg_info); |
| 444 } | 474 } |
| 445 max_register_index_ = | 475 max_register_index_ = |
| 446 std::max(max_register_index_, reg_info->register_value().index()); | 476 std::max(max_register_index_, reg_info->register_value().index()); |
| 447 reg_info->MoveToNewEquivalenceSet(NextEquivalenceId(), true); | 477 reg_info->MoveToNewEquivalenceSet(NextEquivalenceId(), true); |
| 448 } | 478 } |
| 449 | 479 |
| 450 void BytecodeRegisterOptimizer::PrepareRegisterRangeOutputOperand( | 480 void BytecodeRegisterOptimizer::PrepareRegisterRangeOutputOperand( |
| 451 Register start, int count) { | 481 Register start, int count) { |
| 452 for (int i = 0; i < count; ++i) { | 482 for (int i = 0; i < count; ++i) { |
| 453 Register reg(start.index() + i); | 483 Register reg(start.index() + i); |
| 454 RegisterInfo* reg_info = GetOrCreateRegisterInfo(reg); | 484 RegisterInfo* reg_info = GetRegisterInfo(reg); |
| 455 PrepareRegisterOutputOperand(reg_info); | 485 PrepareRegisterOutputOperand(reg_info); |
| 456 } | 486 } |
| 457 } | 487 } |
| 458 | 488 |
| 459 Register BytecodeRegisterOptimizer::GetEquivalentRegisterForInputOperand( | 489 Register BytecodeRegisterOptimizer::GetEquivalentRegisterForInputOperand( |
| 460 Register reg) { | 490 Register reg) { |
| 461 // For a temporary register, RegInfo state may need be created. For | 491 // For a temporary register, RegInfo state may need be created. For |
| 462 // locals and parameters, the RegInfo state is created in the | 492 // locals and parameters, the RegInfo state is created in the |
| 463 // BytecodeRegisterOptimizer constructor. | 493 // BytecodeRegisterOptimizer constructor. |
| 464 RegisterInfo* reg_info = GetOrCreateRegisterInfo(reg); | 494 RegisterInfo* reg_info = GetRegisterInfo(reg); |
| 465 if (reg_info->materialized()) { | 495 if (reg_info->materialized()) { |
| 466 return reg; | 496 return reg; |
| 467 } else { | 497 } else { |
| 468 RegisterInfo* equivalent_info = | 498 RegisterInfo* equivalent_info = |
| 469 GetMaterializedEquivalentNotAccumulator(reg_info); | 499 GetMaterializedEquivalentNotAccumulator(reg_info); |
| 470 return equivalent_info->register_value(); | 500 return equivalent_info->register_value(); |
| 471 } | 501 } |
| 472 } | 502 } |
| 473 | 503 |
| 474 void BytecodeRegisterOptimizer::PrepareRegisterInputOperand( | 504 void BytecodeRegisterOptimizer::PrepareRegisterInputOperand( |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 563 int index, Bytecode bytecode, const uint32_t* operands, int operand_count) { | 593 int index, Bytecode bytecode, const uint32_t* operands, int operand_count) { |
| 564 DCHECK_LT(index, operand_count); | 594 DCHECK_LT(index, operand_count); |
| 565 DCHECK(Bytecodes::IsRegisterOutputOperandType( | 595 DCHECK(Bytecodes::IsRegisterOutputOperandType( |
| 566 Bytecodes::GetOperandType(bytecode, index))); | 596 Bytecodes::GetOperandType(bytecode, index))); |
| 567 return OperandToRegister(operands[index]); | 597 return OperandToRegister(operands[index]); |
| 568 } | 598 } |
| 569 | 599 |
| 570 BytecodeRegisterOptimizer::RegisterInfo* | 600 BytecodeRegisterOptimizer::RegisterInfo* |
| 571 BytecodeRegisterOptimizer::GetRegisterInfo(Register reg) { | 601 BytecodeRegisterOptimizer::GetRegisterInfo(Register reg) { |
| 572 size_t index = GetRegisterInfoTableIndex(reg); | 602 size_t index = GetRegisterInfoTableIndex(reg); |
| 573 return (index < register_info_table_.size()) ? register_info_table_[index] | 603 DCHECK_LT(index, register_info_table_.size()); |
| 574 : nullptr; | 604 return register_info_table_[index]; |
| 575 } | 605 } |
| 576 | 606 |
| 577 BytecodeRegisterOptimizer::RegisterInfo* | 607 BytecodeRegisterOptimizer::RegisterInfo* |
| 578 BytecodeRegisterOptimizer::GetOrCreateRegisterInfo(Register reg) { | 608 BytecodeRegisterOptimizer::GetOrCreateRegisterInfo(Register reg) { |
| 579 size_t index = GetRegisterInfoTableIndex(reg); | 609 size_t index = GetRegisterInfoTableIndex(reg); |
| 580 return index < register_info_table_.size() ? register_info_table_[index] | 610 return index < register_info_table_.size() ? register_info_table_[index] |
| 581 : NewRegisterInfo(reg); | 611 : NewRegisterInfo(reg); |
| 582 } | 612 } |
| 583 | 613 |
| 584 BytecodeRegisterOptimizer::RegisterInfo* | 614 BytecodeRegisterOptimizer::RegisterInfo* |
| 585 BytecodeRegisterOptimizer::NewRegisterInfo(Register reg) { | 615 BytecodeRegisterOptimizer::NewRegisterInfo(Register reg) { |
| 586 size_t index = GetRegisterInfoTableIndex(reg); | 616 size_t index = GetRegisterInfoTableIndex(reg); |
| 587 DCHECK_GE(index, register_info_table_.size()); | 617 DCHECK_GE(index, register_info_table_.size()); |
| 588 GrowRegisterMap(reg); | 618 GrowRegisterMap(reg); |
| 589 return register_info_table_[index]; | 619 return register_info_table_[index]; |
| 590 } | 620 } |
| 591 | 621 |
| 592 void BytecodeRegisterOptimizer::GrowRegisterMap(Register reg) { | 622 void BytecodeRegisterOptimizer::GrowRegisterMap(Register reg) { |
| 593 DCHECK(RegisterIsTemporary(reg)); | 623 DCHECK(RegisterIsTemporary(reg)); |
| 594 size_t index = GetRegisterInfoTableIndex(reg); | 624 size_t index = GetRegisterInfoTableIndex(reg); |
| 595 DCHECK_GE(index, register_info_table_.size()); | 625 if (index >= register_info_table_.size()) { |
| 596 size_t new_size = index + 1; | 626 size_t new_size = index + 1; |
| 597 size_t old_size = register_info_table_.size(); | 627 size_t old_size = register_info_table_.size(); |
| 598 register_info_table_.resize(new_size); | 628 register_info_table_.resize(new_size); |
| 599 for (size_t i = old_size; i < new_size; ++i) { | 629 for (size_t i = old_size; i < new_size; ++i) { |
| 600 register_info_table_[i] = new (zone()) RegisterInfo( | 630 register_info_table_[i] = |
| 601 RegisterFromRegisterInfoTableIndex(i), NextEquivalenceId(), false); | 631 new (zone()) RegisterInfo(RegisterFromRegisterInfoTableIndex(i), |
| 632 NextEquivalenceId(), false, false); |
| 633 } |
| 602 } | 634 } |
| 603 } | 635 } |
| 604 | 636 |
| 605 void BytecodeRegisterOptimizer::TemporaryRegisterFreeEvent(Register reg) { | 637 void BytecodeRegisterOptimizer::RegisterAllocateEvent(Register reg) { |
| 606 RegisterInfo* info = GetRegisterInfo(reg); | 638 GetOrCreateRegisterInfo(reg)->set_allocated(true); |
| 607 if (info != nullptr) { | 639 } |
| 608 // If register is materialized and part of equivalence set, make | 640 |
| 609 // sure another member of the set holds the value before the | 641 void BytecodeRegisterOptimizer::RegisterListAllocateEvent( |
| 610 // temporary register is removed. | 642 RegisterList reg_list) { |
| 611 if (info->materialized()) { | 643 if (reg_list.register_count() != 0) { |
| 612 CreateMaterializedEquivalent(info); | 644 int first_index = reg_list.first_register().index(); |
| 645 GrowRegisterMap(Register(first_index + reg_list.register_count() - 1)); |
| 646 for (int i = 0; i < reg_list.register_count(); i++) { |
| 647 GetRegisterInfo(Register(first_index + i))->set_allocated(true); |
| 613 } | 648 } |
| 614 info->MoveToNewEquivalenceSet(kInvalidEquivalenceId, false); | |
| 615 } | 649 } |
| 616 } | 650 } |
| 617 | 651 |
| 652 void BytecodeRegisterOptimizer::RegisterListFreeEvent(RegisterList reg_list) { |
| 653 int first_index = reg_list.first_register().index(); |
| 654 for (int i = 0; i < reg_list.register_count(); i++) { |
| 655 GetRegisterInfo(Register(first_index + i))->set_allocated(false); |
| 656 } |
| 657 } |
| 658 |
| 618 } // namespace interpreter | 659 } // namespace interpreter |
| 619 } // namespace internal | 660 } // namespace internal |
| 620 } // namespace v8 | 661 } // namespace v8 |
| OLD | NEW |