Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(659)

Unified Diff: src/interpreter/bytecode-array-builder.cc

Issue 1392933002: [Interpreter] Reduce temporary register usage in generated bytecode. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Incorporate comments from mstarzinger. Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/interpreter/bytecode-array-builder.h ('k') | src/interpreter/bytecode-generator.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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
« no previous file with comments | « src/interpreter/bytecode-array-builder.h ('k') | src/interpreter/bytecode-generator.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698