Index: src/virtual-frame-ia32.cc |
=================================================================== |
--- src/virtual-frame-ia32.cc (revision 1574) |
+++ src/virtual-frame-ia32.cc (working copy) |
@@ -498,63 +498,57 @@ |
} |
-// Before changing an element which is copied, adjust so that the |
-// first copy becomes the new backing store and all the other copies |
-// are updated. If the original was in memory, the new backing store |
-// is allocated to a register. Return a copy of the new backing store |
-// or an invalid element if the original was not a copy. |
-FrameElement VirtualFrame::AdjustCopies(int index) { |
+int VirtualFrame::InvalidateFrameSlotAt(int index) { |
FrameElement original = elements_[index]; |
- ASSERT(original.is_memory() || original.is_register()); |
- // Go looking for a first copy above index. |
- int i = index + 1; |
- while (i < elements_.length()) { |
- FrameElement elt = elements_[i]; |
- if (elt.is_copy() && elt.index() == index) break; |
- i++; |
+ // Is this element the backing store of any copies? |
+ int new_backing_index = kIllegalIndex; |
+ if (original.is_copied()) { |
+ // Verify it is copied, and find first copy. |
+ for (int i = index + 1; i < elements_.length(); i++) { |
+ if (elements_[i].is_copy() && elements_[i].index() == index) { |
+ new_backing_index = i; |
+ break; |
+ } |
+ } |
} |
- if (i < elements_.length()) { |
- // There was a first copy. Make it the new backing element. |
- Register backing_reg; |
- if (original.is_memory()) { |
- Result fresh = cgen_->allocator()->Allocate(); |
- ASSERT(fresh.is_valid()); |
- backing_reg = fresh.reg(); |
- __ mov(backing_reg, Operand(ebp, fp_relative(index))); |
- } else { |
- // The original was in a register. |
- backing_reg = original.reg(); |
+ if (new_backing_index == kIllegalIndex) { |
+ // No copies found, return kIllegalIndex. |
+ if (original.is_register()) { |
+ Unuse(original.reg()); |
} |
- FrameElement new_backing_element = |
+ elements_[index] = FrameElement::InvalidElement(); |
+ return kIllegalIndex; |
+ } |
+ |
+ // This is the backing store of copies. |
+ Register backing_reg; |
+ if (original.is_memory()) { |
+ Result fresh = cgen_->allocator()->Allocate(); |
+ ASSERT(fresh.is_valid()); |
+ Use(fresh.reg()); |
+ backing_reg = fresh.reg(); |
+ __ mov(backing_reg, Operand(ebp, fp_relative(index))); |
+ } else { |
+ // The original was in a register. |
+ backing_reg = original.reg(); |
+ } |
+ if (elements_[new_backing_index].is_synced()) { |
+ elements_[new_backing_index] = |
+ FrameElement::RegisterElement(backing_reg, FrameElement::SYNCED); |
+ } else { |
+ elements_[new_backing_index] = |
FrameElement::RegisterElement(backing_reg, FrameElement::NOT_SYNCED); |
- if (elements_[i].is_synced()) { |
- new_backing_element.set_sync(); |
+ } |
+ // Update the other copies. |
+ for (int i = new_backing_index + 1; i < elements_.length(); i++) { |
+ if (elements_[i].is_copy() && elements_[i].index() == index) { |
+ elements_[i].set_index(new_backing_index); |
+ elements_[new_backing_index].set_copied(); |
} |
- Use(backing_reg); |
- elements_[i] = new_backing_element; |
- |
- // Update the other copies. |
- FrameElement copy = CopyElementAt(i); |
- for (int j = i; j < elements_.length(); j++) { |
- FrameElement elt = elements_[j]; |
- if (elt.is_copy() && elt.index() == index) { |
- if (elt.is_synced()) { |
- copy.set_sync(); |
- } else { |
- copy.clear_sync(); |
- } |
- elements_[j] = copy; |
- } |
- } |
- |
- copy.clear_sync(); |
- return copy; |
} |
- |
- elements_[index].clear_copied(); |
- return FrameElement::InvalidElement(); |
+ return new_backing_index; |
} |
@@ -562,73 +556,38 @@ |
ASSERT(index >= 0); |
ASSERT(index <= elements_.length()); |
FrameElement original = elements_[index]; |
+ int new_backing_store_index = InvalidateFrameSlotAt(index); |
+ if (new_backing_store_index != kIllegalIndex) { |
+ elements_.Add(CopyElementAt(new_backing_store_index)); |
+ return; |
+ } |
switch (original.type()) { |
- case FrameElement::INVALID: |
- UNREACHABLE(); |
- break; |
- |
case FrameElement::MEMORY: { |
- // Allocate the element to a register. If it is not copied, |
- // push that register on top of the frame. If it is copied, |
- // make the first copy the backing store and push a fresh copy |
- // on top of the frame. |
- FrameElement copy = original.is_copied() |
- ? AdjustCopies(index) |
- : FrameElement::InvalidElement(); |
- if (copy.is_valid()) { |
- // The original element was a copy. Push the copy of the new |
- // backing store. |
- elements_.Add(copy); |
- } else { |
- // The element was not a copy. Move it to a register and push |
- // that. |
- Result fresh = cgen_->allocator()->Allocate(); |
- ASSERT(fresh.is_valid()); |
- FrameElement new_element = |
- FrameElement::RegisterElement(fresh.reg(), |
- FrameElement::NOT_SYNCED); |
- Use(fresh.reg()); |
- elements_.Add(new_element); |
- __ mov(fresh.reg(), Operand(ebp, fp_relative(index))); |
- } |
+ // Emit code to load the original element's data into a register. |
+ // Push that register as a FrameElement on top of the frame. |
+ Result fresh = cgen_->allocator()->Allocate(); |
+ ASSERT(fresh.is_valid()); |
+ FrameElement new_element = |
+ FrameElement::RegisterElement(fresh.reg(), |
+ FrameElement::NOT_SYNCED); |
+ Use(fresh.reg()); |
+ elements_.Add(new_element); |
+ __ mov(fresh.reg(), Operand(ebp, fp_relative(index))); |
break; |
} |
- |
- case FrameElement::REGISTER: { |
- // If the element is not copied, push it on top of the frame. |
- // If it is copied, make the first copy be the new backing store |
- // and push a fresh copy on top of the frame. |
- FrameElement copy = original.is_copied() |
- ? AdjustCopies(index) |
- : FrameElement::InvalidElement(); |
- if (copy.is_valid()) { |
- // The original element was a copy. Push the copy of the new |
- // backing store. |
- elements_.Add(copy); |
- // This is the only case where we have to unuse the original |
- // register. The original is still counted and so is the new |
- // backing store of the copies. |
- Unuse(original.reg()); |
- } else { |
- // The element was not a copy. Push it. |
- original.clear_sync(); |
- elements_.Add(original); |
- } |
- break; |
- } |
- |
+ case FrameElement::REGISTER: |
+ Use(original.reg()); |
+ // Fall through. |
case FrameElement::CONSTANT: |
- original.clear_sync(); |
- elements_.Add(original); |
- break; |
- |
case FrameElement::COPY: |
original.clear_sync(); |
elements_.Add(original); |
break; |
+ case FrameElement::INVALID: |
+ UNREACHABLE(); |
+ break; |
} |
- elements_[index] = FrameElement::InvalidElement(); |
} |
@@ -639,23 +598,14 @@ |
ASSERT(index >= 0); |
ASSERT(index < elements_.length()); |
- FrameElement original = elements_[index]; |
- // If the stored-to slot may be copied, adjust to preserve the |
- // copy-on-write semantics of copied elements. |
- if (original.is_copied() && |
- (original.is_register() || original.is_memory())) { |
- FrameElement ignored = AdjustCopies(index); |
- } |
- |
- // If the stored-to slot is a register reference, deallocate it. |
- if (original.is_register()) { |
- Unuse(original.reg()); |
- } |
- |
int top_index = elements_.length() - 1; |
FrameElement top = elements_[top_index]; |
+ FrameElement original = elements_[index]; |
+ if (top.is_copy() && top.index() == index) return; |
ASSERT(top.is_valid()); |
+ InvalidateFrameSlotAt(index); |
+ |
if (top.is_copy()) { |
// There are two cases based on the relative positions of the |
// stored-to slot and the backing slot of the top element. |
@@ -707,16 +657,11 @@ |
// All the copies of the old backing element (including the top |
// element) become copies of the new backing element. |
for (int i = backing_index + 1; i < elements_.length(); i++) { |
- FrameElement current = elements_[i]; |
- if (current.is_copy() && current.index() == backing_index) { |
- elements_[i] = new_element; |
- if (current.is_synced()) { |
- elements_[i].set_sync(); |
- } |
+ if (elements_[i].is_copy() && elements_[i].index() == backing_index) { |
+ elements_[i].set_index(index); |
} |
} |
} |
- |
return; |
} |