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

Unified Diff: src/interpreter/bytecode-register-allocator.cc

Issue 1651133002: [interpreter] Move temporary register allocator into own file. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Incorporate review comments from rmcilroy. Created 4 years, 11 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-register-allocator.h ('k') | src/interpreter/bytecodes.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/interpreter/bytecode-register-allocator.cc
diff --git a/src/interpreter/bytecode-register-allocator.cc b/src/interpreter/bytecode-register-allocator.cc
index 4efb612db52b7566464d58a199f15e397b820350..0a617c048acb17176df0f5693dead235dc42e271 100644
--- a/src/interpreter/bytecode-register-allocator.cc
+++ b/src/interpreter/bytecode-register-allocator.cc
@@ -10,17 +10,173 @@ namespace v8 {
namespace internal {
namespace interpreter {
+TemporaryRegisterAllocator::TemporaryRegisterAllocator(Zone* zone,
+ int allocation_base)
+ : free_temporaries_(zone),
+ allocation_base_(allocation_base),
+ allocation_count_(0) {}
+
+Register TemporaryRegisterAllocator::first_temporary_register() const {
+ DCHECK(allocation_count() > 0);
+ return Register(allocation_base());
+}
+
+Register TemporaryRegisterAllocator::last_temporary_register() const {
+ DCHECK(allocation_count() > 0);
+ return Register(allocation_base() + allocation_count() - 1);
+}
+
+int TemporaryRegisterAllocator::AllocateTemporaryRegister() {
+ allocation_count_ += 1;
+ return allocation_base() + allocation_count() - 1;
+}
+
+int TemporaryRegisterAllocator::BorrowTemporaryRegister() {
+ if (free_temporaries_.empty()) {
+ return AllocateTemporaryRegister();
+ } else {
+ auto pos = free_temporaries_.begin();
+ int retval = *pos;
+ free_temporaries_.erase(pos);
+ return retval;
+ }
+}
+
+int TemporaryRegisterAllocator::BorrowTemporaryRegisterNotInRange(
+ int start_index, int end_index) {
+ if (free_temporaries_.empty()) {
+ int next_allocation = allocation_base() + allocation_count();
+ while (next_allocation >= start_index && next_allocation <= end_index) {
+ free_temporaries_.insert(AllocateTemporaryRegister());
+ next_allocation += 1;
+ }
+ return AllocateTemporaryRegister();
+ }
+
+ ZoneSet<int>::iterator index = free_temporaries_.lower_bound(start_index);
+ if (index == free_temporaries_.begin()) {
+ // If start_index is the first free register, check for a register
+ // greater than end_index.
+ index = free_temporaries_.upper_bound(end_index);
+ if (index == free_temporaries_.end()) {
+ return AllocateTemporaryRegister();
+ }
+ } else {
+ // If there is a free register < start_index
+ index--;
+ }
+
+ int retval = *index;
+ free_temporaries_.erase(index);
+ return retval;
+}
+
+int TemporaryRegisterAllocator::PrepareForConsecutiveTemporaryRegisters(
+ size_t count) {
+ if (count == 0) {
+ return -1;
+ }
+
+ // TODO(oth): replace use of set<> here for free_temporaries with a
+ // more efficient structure. And/or partition into two searches -
+ // one before the translation window and one after.
+
+ // A run will require at least |count| free temporaries.
+ while (free_temporaries_.size() < count) {
+ free_temporaries_.insert(AllocateTemporaryRegister());
+ }
+
+ // 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++) {
+ int expected = *start + static_cast<int>(run_length);
+ if (*run_end != expected) {
+ start = run_end;
+ run_length = 0;
+ }
+ Register reg_start(*start);
+ Register reg_expected(expected);
+ if (RegisterTranslator::DistanceToTranslationWindow(reg_start) > 0 &&
+ RegisterTranslator::DistanceToTranslationWindow(reg_expected) <= 0) {
+ // Run straddles the lower edge of the translation window. Registers
+ // after the start of this boundary are displaced by the register
+ // translator to provide a hole for translation. Runs either side
+ // of the boundary are fine.
+ start = run_end;
+ run_length = 0;
+ }
+ if (++run_length == count) {
+ return *start;
+ }
+ }
+
+ // Continue run if possible across existing last temporary.
+ if (allocation_count_ > 0 && (start == free_temporaries_.end() ||
+ *start + static_cast<int>(run_length) !=
+ last_temporary_register().index() + 1)) {
+ run_length = 0;
+ }
+
+ // Pad temporaries if extended run would cross translation boundary.
+ Register reg_first(*start);
+ Register reg_last(*start + static_cast<int>(count) - 1);
+ DCHECK_GT(RegisterTranslator::DistanceToTranslationWindow(reg_first),
+ RegisterTranslator::DistanceToTranslationWindow(reg_last));
+ while (RegisterTranslator::DistanceToTranslationWindow(reg_first) > 0 &&
+ RegisterTranslator::DistanceToTranslationWindow(reg_last) <= 0) {
+ auto pos_insert_pair =
+ free_temporaries_.insert(AllocateTemporaryRegister());
+ reg_first = Register(*pos_insert_pair.first);
+ reg_last = Register(reg_first.index() + static_cast<int>(count) - 1);
+ run_length = 0;
+ }
+
+ // Ensure enough registers for run.
+ while (run_length++ < count) {
+ free_temporaries_.insert(AllocateTemporaryRegister());
+ }
+
+ int run_start =
+ last_temporary_register().index() - static_cast<int>(count) + 1;
+ DCHECK(RegisterTranslator::DistanceToTranslationWindow(Register(run_start)) <=
+ 0 ||
+ RegisterTranslator::DistanceToTranslationWindow(
+ Register(run_start + static_cast<int>(count) - 1)) > 0);
+ return run_start;
+}
+
+bool TemporaryRegisterAllocator::RegisterIsLive(Register reg) const {
+ if (allocation_count_ > 0) {
+ DCHECK(reg >= first_temporary_register() &&
+ reg <= last_temporary_register());
+ return free_temporaries_.find(reg.index()) == free_temporaries_.end();
+ } else {
+ return false;
+ }
+}
+
+void TemporaryRegisterAllocator::BorrowConsecutiveTemporaryRegister(
+ int reg_index) {
+ DCHECK(free_temporaries_.find(reg_index) != free_temporaries_.end());
+ free_temporaries_.erase(reg_index);
+}
+
+void TemporaryRegisterAllocator::ReturnTemporaryRegister(int reg_index) {
+ DCHECK(free_temporaries_.find(reg_index) == free_temporaries_.end());
+ free_temporaries_.insert(reg_index);
+}
+
BytecodeRegisterAllocator::BytecodeRegisterAllocator(
- BytecodeArrayBuilder* builder)
- : builder_(builder),
- allocated_(builder->zone()),
+ Zone* zone, TemporaryRegisterAllocator* allocator)
+ : base_allocator_(allocator),
+ allocated_(zone),
next_consecutive_register_(-1),
next_consecutive_count_(-1) {}
-
BytecodeRegisterAllocator::~BytecodeRegisterAllocator() {
for (auto i = allocated_.rbegin(); i != allocated_.rend(); i++) {
- builder_->ReturnTemporaryRegister(*i);
+ base_allocator()->ReturnTemporaryRegister(*i);
}
allocated_.clear();
}
@@ -29,9 +185,9 @@ BytecodeRegisterAllocator::~BytecodeRegisterAllocator() {
Register BytecodeRegisterAllocator::NewRegister() {
int allocated = -1;
if (next_consecutive_count_ <= 0) {
- allocated = builder_->BorrowTemporaryRegister();
+ allocated = base_allocator()->BorrowTemporaryRegister();
} else {
- allocated = builder_->BorrowTemporaryRegisterNotInRange(
+ allocated = base_allocator()->BorrowTemporaryRegisterNotInRange(
next_consecutive_register_,
next_consecutive_register_ + next_consecutive_count_ - 1);
}
@@ -52,7 +208,7 @@ bool BytecodeRegisterAllocator::RegisterIsAllocatedInThisScope(
void BytecodeRegisterAllocator::PrepareForConsecutiveAllocations(size_t count) {
if (static_cast<int>(count) > next_consecutive_count_) {
next_consecutive_register_ =
- builder_->PrepareForConsecutiveTemporaryRegisters(count);
+ base_allocator()->PrepareForConsecutiveTemporaryRegisters(count);
next_consecutive_count_ = static_cast<int>(count);
}
}
@@ -61,7 +217,8 @@ void BytecodeRegisterAllocator::PrepareForConsecutiveAllocations(size_t count) {
Register BytecodeRegisterAllocator::NextConsecutiveRegister() {
DCHECK_GE(next_consecutive_register_, 0);
DCHECK_GT(next_consecutive_count_, 0);
- builder_->BorrowConsecutiveTemporaryRegister(next_consecutive_register_);
+ base_allocator()->BorrowConsecutiveTemporaryRegister(
+ next_consecutive_register_);
allocated_.push_back(next_consecutive_register_);
next_consecutive_count_--;
return Register(next_consecutive_register_++);
« no previous file with comments | « src/interpreter/bytecode-register-allocator.h ('k') | src/interpreter/bytecodes.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698