Index: src/interpreter/bytecode-array-builder.cc |
diff --git a/src/interpreter/bytecode-array-builder.cc b/src/interpreter/bytecode-array-builder.cc |
index 164ef5031eb8cf9770984cf3427ef169feff7477..1e7f824a4a97e349a98fb8e43f5877456f66ba0f 100644 |
--- a/src/interpreter/bytecode-array-builder.cc |
+++ b/src/interpreter/bytecode-array-builder.cc |
@@ -22,13 +22,12 @@ BytecodeArrayBuilder::BytecodeArrayBuilder(Isolate* isolate, Zone* zone) |
local_register_count_(-1), |
context_register_count_(-1), |
temporary_register_count_(0), |
- temporary_register_next_(0) {} |
+ free_temporaries_(zone) {} |
void BytecodeArrayBuilder::set_locals_count(int number_of_locals) { |
local_register_count_ = number_of_locals; |
DCHECK_LE(context_register_count_, 0); |
- temporary_register_next_ = local_register_count_; |
} |
@@ -40,7 +39,6 @@ void BytecodeArrayBuilder::set_parameter_count(int number_of_parameters) { |
void BytecodeArrayBuilder::set_context_count(int number_of_contexts) { |
context_register_count_ = number_of_contexts; |
DCHECK_GE(local_register_count_, 0); |
- temporary_register_next_ = local_register_count_ + context_register_count_; |
} |
@@ -56,12 +54,35 @@ Register BytecodeArrayBuilder::last_context_register() const { |
} |
+Register BytecodeArrayBuilder::first_temporary_register() const { |
+ DCHECK_GT(temporary_register_count_, 0); |
+ return Register(fixed_register_count()); |
+} |
+ |
+ |
+Register BytecodeArrayBuilder::last_temporary_register() const { |
+ DCHECK_GT(temporary_register_count_, 0); |
+ return Register(fixed_register_count() + temporary_register_count_ - 1); |
+} |
+ |
+ |
Register BytecodeArrayBuilder::Parameter(int parameter_index) const { |
DCHECK_GE(parameter_index, 0); |
return Register::FromParameterIndex(parameter_index, parameter_count()); |
} |
+bool BytecodeArrayBuilder::RegisterIsParameterOrLocal(Register reg) const { |
+ return reg.is_parameter() || reg.index() < locals_count(); |
+} |
+ |
+ |
+bool BytecodeArrayBuilder::RegisterIsTemporary(Register reg) const { |
+ return temporary_register_count_ > 0 && first_temporary_register() <= reg && |
+ reg <= last_temporary_register(); |
+} |
+ |
+ |
Handle<BytecodeArray> BytecodeArrayBuilder::ToBytecodeArray() { |
DCHECK_EQ(bytecode_generated_, false); |
@@ -607,6 +628,7 @@ void BytecodeArrayBuilder::EnsureReturn() { |
} |
} |
+ |
BytecodeArrayBuilder& BytecodeArrayBuilder::Call(Register callable, |
Register receiver, |
size_t arg_count) { |
@@ -661,18 +683,74 @@ size_t BytecodeArrayBuilder::GetConstantPoolEntry(Handle<Object> object) { |
int BytecodeArrayBuilder::BorrowTemporaryRegister() { |
- int temporary_reg_index = temporary_register_next_++; |
- int count = temporary_register_next_ - fixed_register_count(); |
- if (count > temporary_register_count_) { |
- temporary_register_count_ = count; |
+ if (free_temporaries_.empty()) { |
+ temporary_register_count_ += 1; |
+ return last_temporary_register().index(); |
+ } else { |
+ auto pos = free_temporaries_.begin(); |
+ int retval = *pos; |
+ free_temporaries_.erase(pos); |
+ return retval; |
} |
- return temporary_reg_index; |
+} |
+ |
+ |
+void BytecodeArrayBuilder::BorrowConsecutiveTemporaryRegister(int reg_index) { |
+ DCHECK(free_temporaries_.find(reg_index) != free_temporaries_.end()); |
+ free_temporaries_.erase(reg_index); |
} |
void BytecodeArrayBuilder::ReturnTemporaryRegister(int reg_index) { |
- DCHECK_EQ(reg_index, temporary_register_next_ - 1); |
- temporary_register_next_ = reg_index; |
+ DCHECK(free_temporaries_.find(reg_index) == free_temporaries_.end()); |
+ free_temporaries_.insert(reg_index); |
+} |
+ |
+ |
+int BytecodeArrayBuilder::PrepareForConsecutiveTemporaryRegisters( |
+ size_t count) { |
+ if (count == 0) { |
+ return -1; |
+ } |
+ |
+ // Search within existing temporaries for a run. |
+ auto start = free_temporaries_.begin(); |
+ size_t run_length = 0; |
+ for (auto run_end = start; run_end != free_temporaries_.end(); run_end++) { |
+ if (*run_end != *start + static_cast<int>(run_length)) { |
+ start = run_end; |
+ run_length = 0; |
+ } |
+ if (++run_length == count) { |
+ return *start; |
+ } |
+ } |
+ |
+ // Continue run if possible across existing last temporary. |
+ if (temporary_register_count_ > 0 && |
+ (start == free_temporaries_.end() || |
+ *start + static_cast<int>(run_length) != |
+ last_temporary_register().index() + 1)) { |
+ run_length = 0; |
+ } |
+ |
+ // Ensure enough registers for run. |
+ while (run_length++ < count) { |
+ temporary_register_count_++; |
+ free_temporaries_.insert(last_temporary_register().index()); |
+ } |
+ return last_temporary_register().index() - static_cast<int>(count) + 1; |
+} |
+ |
+ |
+bool BytecodeArrayBuilder::TemporaryRegisterIsLive(Register reg) const { |
+ if (temporary_register_count_ > 0) { |
+ DCHECK(reg.index() >= first_temporary_register().index() && |
+ reg.index() <= last_temporary_register().index()); |
+ return free_temporaries_.find(reg.index()) == free_temporaries_.end(); |
+ } else { |
+ return false; |
+ } |
} |
@@ -693,10 +771,12 @@ bool BytecodeArrayBuilder::OperandIsValid(Bytecode bytecode, int operand_index, |
if (reg.is_function_context() || reg.is_function_closure()) { |
return true; |
} else if (reg.is_parameter()) { |
- int parameter_index = reg.ToParameterIndex(parameter_count()); |
- return parameter_index >= 0 && parameter_index < parameter_count(); |
+ int parameter_index = reg.ToParameterIndex(parameter_count_); |
+ return parameter_index >= 0 && parameter_index < parameter_count_; |
+ } else if (reg.index() < fixed_register_count()) { |
+ return true; |
} else { |
- return (reg.index() >= 0 && reg.index() < temporary_register_next_); |
+ return TemporaryRegisterIsLive(reg); |
} |
} |
} |
@@ -880,20 +960,43 @@ bool BytecodeArrayBuilder::FitsInIdx16Operand(int value) { |
TemporaryRegisterScope::TemporaryRegisterScope(BytecodeArrayBuilder* builder) |
- : builder_(builder), count_(0), last_register_index_(-1) {} |
+ : builder_(builder), |
+ allocated_(builder->zone()), |
+ next_consecutive_register_(-1), |
+ next_consecutive_count_(-1) {} |
TemporaryRegisterScope::~TemporaryRegisterScope() { |
- while (count_-- != 0) { |
- builder_->ReturnTemporaryRegister(last_register_index_--); |
+ for (auto i = allocated_.rbegin(); i != allocated_.rend(); i++) { |
+ builder_->ReturnTemporaryRegister(*i); |
} |
+ allocated_.clear(); |
} |
Register TemporaryRegisterScope::NewRegister() { |
- count_++; |
- last_register_index_ = builder_->BorrowTemporaryRegister(); |
- return Register(last_register_index_); |
+ int allocated = builder_->BorrowTemporaryRegister(); |
+ allocated_.push_back(allocated); |
+ return Register(allocated); |
+} |
+ |
+ |
+void TemporaryRegisterScope::PrepareForConsecutiveAllocations(size_t count) { |
+ if (static_cast<int>(count) > next_consecutive_count_) { |
+ next_consecutive_register_ = |
+ builder_->PrepareForConsecutiveTemporaryRegisters(count); |
+ next_consecutive_count_ = static_cast<int>(count); |
+ } |
+} |
+ |
+ |
+Register TemporaryRegisterScope::NextConsecutiveRegister() { |
+ DCHECK_GE(next_consecutive_register_, 0); |
+ DCHECK_GT(next_consecutive_count_, 0); |
+ builder_->BorrowConsecutiveTemporaryRegister(next_consecutive_register_); |
+ allocated_.push_back(next_consecutive_register_); |
+ next_consecutive_count_--; |
+ return Register(next_consecutive_register_++); |
} |
} // namespace interpreter |