Chromium Code Reviews| Index: src/interpreter/bytecode-register-optimizer.cc |
| diff --git a/src/interpreter/bytecode-register-optimizer.cc b/src/interpreter/bytecode-register-optimizer.cc |
| index 12be57b48c2964d53bf8b9127d5c4ea562e2361f..9ee80749bb1b915b699f859405cfcfc8ca62f5f6 100644 |
| --- a/src/interpreter/bytecode-register-optimizer.cc |
| +++ b/src/interpreter/bytecode-register-optimizer.cc |
| @@ -15,10 +15,12 @@ const uint32_t BytecodeRegisterOptimizer::kInvalidEquivalenceId; |
| // register is materialized in the bytecode stream. |
| class BytecodeRegisterOptimizer::RegisterInfo final : public ZoneObject { |
| public: |
| - RegisterInfo(Register reg, uint32_t equivalence_id, bool materialized) |
| + RegisterInfo(Register reg, uint32_t equivalence_id, bool materialized, |
| + bool allocated) |
| : register_(reg), |
| equivalence_id_(equivalence_id), |
| materialized_(materialized), |
| + allocated_(allocated), |
| next_(this), |
| prev_(this) {} |
| @@ -48,12 +50,17 @@ class BytecodeRegisterOptimizer::RegisterInfo final : public ZoneObject { |
| // exists. |
| RegisterInfo* GetEquivalentToMaterialize(); |
| + // Marks all temporary registers of the equivalence set as unmaterialized. |
| + void MarkTemporariesAsUnmaterialized(Register temporary_base); |
| + |
| // Get an equivalent register. Returns this if none exists. |
| RegisterInfo* GetEquivalent(); |
| Register register_value() const { return register_; } |
| bool materialized() const { return materialized_; } |
| void set_materialized(bool materialized) { materialized_ = materialized; } |
| + bool allocated() const { return allocated_; } |
| + void set_allocated(bool allocated) { allocated_ = allocated; } |
| void set_equivalence_id(uint32_t equivalence_id) { |
| equivalence_id_ = equivalence_id; |
| } |
| @@ -63,6 +70,7 @@ class BytecodeRegisterOptimizer::RegisterInfo final : public ZoneObject { |
| Register register_; |
| uint32_t equivalence_id_; |
| bool materialized_; |
| + bool allocated_; |
| // Equivalence set pointers. |
| RegisterInfo* next_; |
| @@ -155,8 +163,9 @@ BytecodeRegisterOptimizer::RegisterInfo::GetEquivalentToMaterialize() { |
| if (visitor->materialized()) { |
|
mythria
2016/09/28 11:45:29
I am not sure I understand it fully, but what woul
rmcilroy
2016/09/30 08:37:54
As discussed offline, yes we can reuse it even if
|
| return nullptr; |
| } |
| - if (best_info == nullptr || |
| - visitor->register_value() < best_info->register_value()) { |
| + if (visitor->allocated() && |
| + (best_info == nullptr || |
| + visitor->register_value() < best_info->register_value())) { |
| best_info = visitor; |
| } |
| visitor = visitor->next_; |
| @@ -164,17 +173,31 @@ BytecodeRegisterOptimizer::RegisterInfo::GetEquivalentToMaterialize() { |
| return best_info; |
| } |
| +void BytecodeRegisterOptimizer::RegisterInfo::MarkTemporariesAsUnmaterialized( |
| + Register temporary_base) { |
| + DCHECK(this->register_value() < temporary_base); |
| + DCHECK(this->materialized()); |
| + RegisterInfo* visitor = this->next_; |
| + while (visitor != this) { |
| + if (visitor->register_value() >= temporary_base) { |
| + visitor->set_materialized(false); |
| + } |
| + visitor = visitor->next_; |
| + } |
| +} |
| + |
| BytecodeRegisterOptimizer::RegisterInfo* |
| BytecodeRegisterOptimizer::RegisterInfo::GetEquivalent() { |
| return next_; |
| } |
| BytecodeRegisterOptimizer::BytecodeRegisterOptimizer( |
| - Zone* zone, TemporaryRegisterAllocator* register_allocator, |
| - int parameter_count, BytecodePipelineStage* next_stage) |
| + Zone* zone, BytecodeRegisterAllocator* register_allocator, |
| + int fixed_registers_count, int parameter_count, |
| + BytecodePipelineStage* next_stage) |
| : accumulator_(Register::virtual_accumulator()), |
| - temporary_base_(register_allocator->allocation_base()), |
| - max_register_index_(register_allocator->allocation_base() - 1), |
| + temporary_base_(fixed_registers_count), |
| + max_register_index_(fixed_registers_count - 1), |
| register_info_table_(zone), |
| equivalence_id_(0), |
| next_stage_(next_stage), |
| @@ -199,7 +222,7 @@ BytecodeRegisterOptimizer::BytecodeRegisterOptimizer( |
| static_cast<size_t>(temporary_base_.index())); |
| for (size_t i = 0; i < register_info_table_.size(); ++i) { |
| register_info_table_[i] = new (zone) RegisterInfo( |
| - RegisterFromRegisterInfoTableIndex(i), NextEquivalenceId(), true); |
| + RegisterFromRegisterInfoTableIndex(i), NextEquivalenceId(), true, true); |
| DCHECK_EQ(register_info_table_[i]->register_value().index(), |
| RegisterFromRegisterInfoTableIndex(i).index()); |
| } |
| @@ -296,7 +319,7 @@ void BytecodeRegisterOptimizer::FlushState() { |
| // own equivalence set. |
| RegisterInfo* equivalent; |
| while ((equivalent = reg_info->GetEquivalent()) != reg_info) { |
| - if (!equivalent->materialized()) { |
| + if (equivalent->allocated() && !equivalent->materialized()) { |
| OutputRegisterTransfer(reg_info, equivalent); |
| } |
| equivalent->MoveToNewEquivalenceSet(NextEquivalenceId(), true); |
| @@ -404,6 +427,13 @@ void BytecodeRegisterOptimizer::RegisterTransfer( |
| // Emit a placeholder nop to maintain source position info. |
| EmitNopForSourceInfo(source_info); |
| } |
| + |
| + bool input_is_observable = RegisterIsObservable(input_info->register_value()); |
| + if (input_is_observable) { |
| + // If input is observable by the debugger, mark all other temporaries |
| + // registers as unmaterialized so that this register is used in preference. |
| + input_info->MarkTemporariesAsUnmaterialized(temporary_base_); |
| + } |
| } |
| void BytecodeRegisterOptimizer::EmitNopForSourceInfo( |
| @@ -426,14 +456,14 @@ void BytecodeRegisterOptimizer::DoMov(BytecodeNode* node) { |
| RegisterInfo* input_info = GetRegisterInfo(input); |
| Register output = GetRegisterOutputOperand( |
| 1, node->bytecode(), node->operands(), node->operand_count()); |
| - RegisterInfo* output_info = GetOrCreateRegisterInfo(output); |
| + RegisterInfo* output_info = GetRegisterInfo(output); |
| RegisterTransfer(input_info, output_info, node->source_info_ptr()); |
| } |
| void BytecodeRegisterOptimizer::DoStar(BytecodeNode* node) { |
| Register output = GetRegisterOutputOperand( |
| 0, node->bytecode(), node->operands(), node->operand_count()); |
| - RegisterInfo* output_info = GetOrCreateRegisterInfo(output); |
| + RegisterInfo* output_info = GetRegisterInfo(output); |
| RegisterTransfer(accumulator_info_, output_info, node->source_info_ptr()); |
| } |
| @@ -451,7 +481,7 @@ void BytecodeRegisterOptimizer::PrepareRegisterRangeOutputOperand( |
| Register start, int count) { |
| for (int i = 0; i < count; ++i) { |
| Register reg(start.index() + i); |
| - RegisterInfo* reg_info = GetOrCreateRegisterInfo(reg); |
| + RegisterInfo* reg_info = GetRegisterInfo(reg); |
| PrepareRegisterOutputOperand(reg_info); |
| } |
| } |
| @@ -461,7 +491,7 @@ Register BytecodeRegisterOptimizer::GetEquivalentRegisterForInputOperand( |
| // For a temporary register, RegInfo state may need be created. For |
| // locals and parameters, the RegInfo state is created in the |
| // BytecodeRegisterOptimizer constructor. |
| - RegisterInfo* reg_info = GetOrCreateRegisterInfo(reg); |
| + RegisterInfo* reg_info = GetRegisterInfo(reg); |
| if (reg_info->materialized()) { |
| return reg; |
| } else { |
| @@ -570,8 +600,8 @@ Register BytecodeRegisterOptimizer::GetRegisterOutputOperand( |
| BytecodeRegisterOptimizer::RegisterInfo* |
| BytecodeRegisterOptimizer::GetRegisterInfo(Register reg) { |
| size_t index = GetRegisterInfoTableIndex(reg); |
| - return (index < register_info_table_.size()) ? register_info_table_[index] |
| - : nullptr; |
| + DCHECK_LT(index, register_info_table_.size()); |
| + return register_info_table_[index]; |
| } |
| BytecodeRegisterOptimizer::RegisterInfo* |
| @@ -592,26 +622,37 @@ BytecodeRegisterOptimizer::NewRegisterInfo(Register reg) { |
| void BytecodeRegisterOptimizer::GrowRegisterMap(Register reg) { |
| DCHECK(RegisterIsTemporary(reg)); |
| size_t index = GetRegisterInfoTableIndex(reg); |
| - DCHECK_GE(index, register_info_table_.size()); |
| - size_t new_size = index + 1; |
| - size_t old_size = register_info_table_.size(); |
| - register_info_table_.resize(new_size); |
| - for (size_t i = old_size; i < new_size; ++i) { |
| - register_info_table_[i] = new (zone()) RegisterInfo( |
| - RegisterFromRegisterInfoTableIndex(i), NextEquivalenceId(), false); |
| + if (index >= register_info_table_.size()) { |
| + size_t new_size = index + 1; |
| + size_t old_size = register_info_table_.size(); |
| + register_info_table_.resize(new_size); |
| + for (size_t i = old_size; i < new_size; ++i) { |
| + register_info_table_[i] = |
| + new (zone()) RegisterInfo(RegisterFromRegisterInfoTableIndex(i), |
| + NextEquivalenceId(), false, false); |
| + } |
| } |
| } |
| -void BytecodeRegisterOptimizer::TemporaryRegisterFreeEvent(Register reg) { |
| - RegisterInfo* info = GetRegisterInfo(reg); |
| - if (info != nullptr) { |
| - // If register is materialized and part of equivalence set, make |
| - // sure another member of the set holds the value before the |
| - // temporary register is removed. |
| - if (info->materialized()) { |
| - CreateMaterializedEquivalent(info); |
| +void BytecodeRegisterOptimizer::RegisterAllocateEvent(Register reg) { |
| + GetOrCreateRegisterInfo(reg)->set_allocated(true); |
| +} |
| + |
| +void BytecodeRegisterOptimizer::RegisterListAllocateEvent( |
| + RegisterList reg_list) { |
| + if (reg_list.register_count() != 0) { |
| + int first_index = reg_list.first_register().index(); |
| + GrowRegisterMap(Register(first_index + reg_list.register_count() - 1)); |
| + for (int i = 0; i < reg_list.register_count(); i++) { |
| + GetRegisterInfo(Register(first_index + i))->set_allocated(true); |
| } |
| - info->MoveToNewEquivalenceSet(kInvalidEquivalenceId, false); |
| + } |
| +} |
| + |
| +void BytecodeRegisterOptimizer::RegisterListFreeEvent(RegisterList reg_list) { |
| + int first_index = reg_list.first_register().index(); |
| + for (int i = 0; i < reg_list.register_count(); i++) { |
| + GetRegisterInfo(Register(first_index + i))->set_allocated(false); |
| } |
|
mythria
2016/09/28 11:45:29
If I understand correctly, the idea here is that,
rmcilroy
2016/09/30 08:37:54
As discussed offline, we don't need to materialize
|
| } |