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

Unified Diff: src/virtual-frame-ia32.cc

Issue 11396: Begin counting references to registers, both in the frame and out.... (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/toiger/
Patch Set: '' Created 12 years, 1 month 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/virtual-frame-ia32.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/virtual-frame-ia32.cc
===================================================================
--- src/virtual-frame-ia32.cc (revision 814)
+++ src/virtual-frame-ia32.cc (working copy)
@@ -41,26 +41,30 @@
// On entry to a function, the virtual frame already contains the receiver,
// the parameters, and a return address. All frame elements are in memory.
VirtualFrame::VirtualFrame(CodeGenerator* cgen)
- : masm_(cgen->masm()),
+ : cgen_(cgen),
+ masm_(cgen->masm()),
elements_(0),
parameter_count_(cgen->scope()->num_parameters()),
local_count_(0),
stack_pointer_(parameter_count_ + 1), // 0-based index of TOS.
frame_pointer_(kIllegalIndex) {
+ FrameElement memory_element;
for (int i = 0; i < parameter_count_ + 2; i++) {
- elements_.Add(FrameElement());
+ elements_.Add(memory_element);
}
}
// When cloned, a frame is a deep copy of the original.
VirtualFrame::VirtualFrame(VirtualFrame* original)
- : masm_(original->masm_),
+ : cgen_(original->cgen_),
+ masm_(original->masm_),
elements_(original->elements_.length()),
parameter_count_(original->parameter_count_),
local_count_(original->local_count_),
stack_pointer_(original->stack_pointer_),
- frame_pointer_(original->frame_pointer_) {
+ frame_pointer_(original->frame_pointer_),
+ frame_registers_(original->frame_registers_) {
// Copy all the elements from the original.
for (int i = 0; i < original->elements_.length(); i++) {
elements_.Add(original->elements_[i]);
@@ -94,18 +98,33 @@
stack_pointer_ -= count;
for (int i = 0; i < count; i++) {
- elements_.RemoveLast();
+ FrameElement last = elements_.RemoveLast();
+ if (last.is_register()) {
+ Unuse(last.reg());
+ }
}
}
+void VirtualFrame::Use(Register reg) {
+ frame_registers_.Use(reg);
+ cgen_->allocator()->Use(reg);
+}
+
+
+void VirtualFrame::Unuse(Register reg) {
+ frame_registers_.Unuse(reg);
+ cgen_->allocator()->Unuse(reg);
+}
+
+
// Clear the dirty bit for the element at a given index. We can only
// allocate space in the actual frame for the virtual element immediately
// above the stack pointer.
void VirtualFrame::SyncElementAt(int index) {
FrameElement element = elements_[index];
- if (element.is_dirty()) {
+ if (!element.is_synced()) {
if (index <= stack_pointer_) {
// Write elements below the stack pointer to their (already allocated)
// actual frame location.
@@ -128,20 +147,79 @@
__ push(element.reg());
}
}
+
+ elements_[index].set_sync();
}
}
+// Spill any register if possible, making its reference count zero.
+Register VirtualFrame::SpillAnyRegister() {
+ // Find the leftmost (ordered by register code), least
+ // internally-referenced register whose internal reference count matches
+ // its external reference count (so that spilling it from the frame frees
+ // it for use).
+ int min_count = kMaxInt;
+ int best_register_code = no_reg.code();
+
+ for (int i = 0; i < RegisterFile::kNumRegisters; i++) {
+ int count = frame_registers_.count(i);
+ if (count < min_count && count == cgen_->allocator()->count(i)) {
+ min_count = count;
+ best_register_code = i;
+ }
+ }
+
+ if (best_register_code != no_reg.code()) {
+ // Spill all occurrences of the register. There are min_count
+ // occurrences, stop when we've spilled them all to avoid syncing
+ // elements unnecessarily.
+ int i = 0;
+ while (min_count > 0) {
+ ASSERT(i < elements_.length());
+ if (elements_[i].is_register() &&
+ elements_[i].reg().code() == best_register_code) {
+ // Found an instance of the best_register being used in the frame.
+ // Spill it.
+ SpillElementAt(i);
+ min_count--;
+ } else {
+ if (i > stack_pointer_) {
+ // Make sure to materialize elements on the virtual frame in
+ // memory. We rely on this to spill occurrences of the register
+ // lying above the current virtual stack pointer.
+ SyncElementAt(i);
+ }
+ }
+ }
+ }
+
+ Register result = { best_register_code };
+ return result;
+}
+
+
// Make the type of the element at a given index be MEMORY. We can only
// allocate space in the actual frame for the virtual element immediately
// above the stack pointer.
void VirtualFrame::SpillElementAt(int index) {
SyncElementAt(index);
// The element is now in memory.
+ if (elements_[index].is_register()) {
+ Unuse(elements_[index].reg());
+ }
elements_[index] = FrameElement();
}
+// Clear the dirty bits for all elements.
+void VirtualFrame::SyncAll() {
+ for (int i = 0; i < elements_.length(); i++) {
+ SyncElementAt(i);
+ }
+}
+
+
// Make the type of all elements be MEMORY.
void VirtualFrame::SpillAll() {
for (int i = 0; i < elements_.length(); i++) {
@@ -186,6 +264,7 @@
void VirtualFrame::MergeTo(VirtualFrame* expected) {
+ ASSERT(cgen_ == expected->cgen_);
ASSERT(masm_ == expected->masm_);
ASSERT(elements_.length() == expected->elements_.length());
ASSERT(parameter_count_ == expected->parameter_count_);
@@ -204,6 +283,7 @@
void VirtualFrame::Enter() {
+ // Registers live on entry: esp, ebp, esi, edi.
Comment cmnt(masm_, "[ Enter JS frame");
EmitPush(ebp);
@@ -211,23 +291,12 @@
__ mov(ebp, Operand(esp));
// Store the context and the function in the frame.
- FrameElement context(esi);
- context.clear_dirty();
- elements_.Add(context);
- stack_pointer_++;
- __ push(esi);
+ Push(esi);
+ // The frame owns the register reference now.
+ cgen_->allocator()->Unuse(esi);
- FrameElement function(edi);
- function.clear_dirty();
- elements_.Add(function);
- stack_pointer_++;
- __ push(edi);
-
- // Clear the function slot when generating debug code.
- if (FLAG_debug_code) {
- SpillElementAt(stack_pointer_);
- __ Set(edi, Immediate(reinterpret_cast<int>(kZapValue)));
- }
+ Push(edi);
+ cgen_->allocator()->Unuse(edi);
}
@@ -244,7 +313,10 @@
__ mov(esp, Operand(ebp));
stack_pointer_ = frame_pointer_;
for (int i = elements_.length() - 1; i > stack_pointer_; i--) {
- elements_.RemoveLast();
+ FrameElement last = elements_.RemoveLast();
+ if (last.is_register()) {
+ Unuse(last.reg());
+ }
}
frame_pointer_ = kIllegalIndex;
@@ -260,14 +332,17 @@
Comment cmnt(masm_, "[ Allocate space for locals");
// The locals are constants (the undefined value), but we sync them with
// the actual frame to allocate space for spilling them.
- FrameElement initial_value(Factory::undefined_value());
- initial_value.clear_dirty();
- __ Set(eax, Immediate(Factory::undefined_value()));
+ SyncAll();
+ Handle<Object> undefined = Factory::undefined_value();
+ FrameElement initial_value(undefined, FrameElement::SYNCED);
+ Register tmp = cgen_->allocator()->Allocate();
+ __ Set(tmp, Immediate(undefined));
for (int i = 0; i < count; i++) {
elements_.Add(initial_value);
stack_pointer_++;
- __ push(eax);
+ __ push(tmp);
}
+ cgen_->allocator()->Unuse(tmp);
}
}
@@ -323,7 +398,10 @@
// Discard elements above the stack pointer.
while (count > 0 && stack_pointer_ < elements_.length() - 1) {
- elements_.RemoveLast();
+ FrameElement last = elements_.RemoveLast();
+ if (last.is_register()) {
+ Unuse(last.reg());
+ }
}
// Discard the rest of the elements and lower the stack pointer.
@@ -371,12 +449,26 @@
void VirtualFrame::EmitPush(Immediate immediate) {
ASSERT(stack_pointer_ == elements_.length() - 1);
- elements_.Add(FrameElement());
+ FrameElement memory_element;
+ elements_.Add(memory_element);
stack_pointer_++;
__ push(immediate);
}
+void VirtualFrame::Push(Register reg) {
+ FrameElement register_element(reg, FrameElement::NOT_SYNCED);
+ Use(reg);
+ elements_.Add(register_element);
+}
+
+
+void VirtualFrame::Push(Handle<Object> value) {
+ FrameElement constant_element(value, FrameElement::NOT_SYNCED);
+ elements_.Add(constant_element);
+}
+
+
#undef __
} } // namespace v8::internal
« no previous file with comments | « src/virtual-frame-ia32.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698