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()) { |
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); |
} |
} |