From cd296924b60e5998fdd2bb09c450a86cefe5fd86 Mon Sep 17 00:00:00 2001 From: "kmillikin@chromium.org" Date: Thu, 19 Mar 2009 11:57:18 +0000 Subject: [PATCH] Add a copied flag to virtual frame elements that tells if a copy has been made of the element. Set it when copying an element, clear it when writing to an element marked copied and discovering that it is not copied. The copied flags on entry frames are exact. Preparing a frame for merging set the copied flags to be exact (to increase the likelihood of matching the entry frame or another frame). Review URL: http://codereview.chromium.org/50005 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@1546 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/disassembler.cc | 2 +- src/jump-target.cc | 10 ++++++++++ src/virtual-frame-ia32.cc | 25 ++++++++++++++++-------- src/virtual-frame.cc | 41 ++++++++++++++++++++++++++------------- src/virtual-frame.h | 27 +++++++++++++++++--------- 5 files changed, 73 insertions(+), 32 deletions(-) diff --git a/src/disassembler.cc b/src/disassembler.cc index 9178aedbe9..24765b3fd1 100644 --- a/src/disassembler.cc +++ b/src/disassembler.cc @@ -99,7 +99,7 @@ static void DumpBuffer(FILE* f, char* buff) { } } -static const int kOutBufferSize = 1024 + String::kMaxShortPrintLength; +static const int kOutBufferSize = 2048 + String::kMaxShortPrintLength; static const int kRelocInfoPosition = 57; static int DecodeIt(FILE* f, diff --git a/src/jump-target.cc b/src/jump-target.cc index 48b05b579f..6cee05760d 100644 --- a/src/jump-target.cc +++ b/src/jump-target.cc @@ -270,6 +270,16 @@ void JumpTarget::ComputeEntryFrame(int mergable_elements) { } } + // Set the copied flags in the frame to be exact. This assumes that + // the backing store of copies is always lower in the frame. + for (int i = 0; i < length; i++) { + entry_frame_->elements_[i].clear_copied(); + if (entry_frame_->elements_[i].is_copy()) { + int index = entry_frame_->elements_[i].index(); + entry_frame_->elements_[index].set_copied(); + } + } + // Fill in the other fields of the entry frame. entry_frame_->local_count_ = initial_frame->local_count_; entry_frame_->frame_pointer_ = initial_frame->frame_pointer_; diff --git a/src/virtual-frame-ia32.cc b/src/virtual-frame-ia32.cc index b31c394c90..2a5c416c1c 100644 --- a/src/virtual-frame-ia32.cc +++ b/src/virtual-frame-ia32.cc @@ -171,11 +171,10 @@ void VirtualFrame::MergeTo(VirtualFrame* expected) { MergeMoveRegistersToRegisters(expected); MergeMoveMemoryToRegisters(expected); - // Fix any sync bit problems from the bottom-up, stopping when we - // hit the stack pointer or the top of the frame if the stack - // pointer is floating above the frame. - int limit = Min(stack_pointer_, elements_.length() - 1); - for (int i = 0; i <= limit; i++) { + // Fix any sync flag problems from the bottom-up and make the copied + // flags exact. This assumes that the backing store of copies is + // always lower in the frame. + for (int i = 0; i < elements_.length(); i++) { FrameElement source = elements_[i]; FrameElement target = expected->elements_[i]; if (source.is_synced() && !target.is_synced()) { @@ -183,6 +182,10 @@ void VirtualFrame::MergeTo(VirtualFrame* expected) { } else if (!source.is_synced() && target.is_synced()) { SyncElementAt(i); } + elements_[i].clear_copied(); + if (elements_[i].is_copy()) { + elements_[elements_[i].index()].set_copied(); + } } // Adjust the stack point downard if necessary. @@ -550,6 +553,7 @@ FrameElement VirtualFrame::AdjustCopies(int index) { return copy; } + elements_[index].clear_copied(); return FrameElement::InvalidElement(); } @@ -569,7 +573,9 @@ void VirtualFrame::TakeFrameSlotAt(int index) { // 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 = AdjustCopies(index); + 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. @@ -593,7 +599,9 @@ void VirtualFrame::TakeFrameSlotAt(int index) { // 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 = AdjustCopies(index); + 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. @@ -634,7 +642,8 @@ void VirtualFrame::StoreToFrameSlotAt(int index) { 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_register() || original.is_memory()) { + if (original.is_copied() && + (original.is_register() || original.is_memory())) { FrameElement ignored = AdjustCopies(index); } diff --git a/src/virtual-frame.cc b/src/virtual-frame.cc index 60fa699c9a..531f986e26 100644 --- a/src/virtual-frame.cc +++ b/src/virtual-frame.cc @@ -93,9 +93,11 @@ FrameElement VirtualFrame::CopyElementAt(int index) { case FrameElement::REGISTER: // All copies are backed by memory or register locations. result.type_ = - FrameElement::TypeField::encode(FrameElement::COPY) | - FrameElement::SyncField::encode(FrameElement::NOT_SYNCED); + FrameElement::TypeField::encode(FrameElement::COPY) + | FrameElement::IsCopiedField::encode(false) + | FrameElement::SyncField::encode(FrameElement::NOT_SYNCED); result.data_.index_ = index; + elements_[index].set_copied(); break; case FrameElement::INVALID: @@ -208,11 +210,15 @@ void VirtualFrame::SpillElementAt(int index) { if (!elements_[index].is_valid()) return; SyncElementAt(index); + // The element is now in memory. Its copied flag is preserved. + FrameElement new_element = FrameElement::MemoryElement(); + if (elements_[index].is_copied()) { + new_element.set_copied(); + } if (elements_[index].is_register()) { Unuse(elements_[index].reg()); } - // The element is now in memory. - elements_[index] = FrameElement::MemoryElement(); + elements_[index] = new_element; } @@ -276,6 +282,11 @@ void VirtualFrame::PrepareMergeTo(VirtualFrame* expected) { ASSERT(source.is_valid()); elements_[i].clear_sync(); } + + elements_[i].clear_copied(); + if (elements_[i].is_copy()) { + elements_[elements_[i].index()].set_copied(); + } } } @@ -367,7 +378,8 @@ void VirtualFrame::SetElementAt(int index, Result* value) { // If the original may be a copy, adjust to preserve the copy-on-write // semantics of copied elements. - if (original.is_register() || original.is_memory()) { + if (original.is_copied() && + (original.is_register() || original.is_memory())) { FrameElement ignored = AdjustCopies(frame_index); } @@ -523,8 +535,7 @@ void VirtualFrame::Nip(int num_dropped) { bool FrameElement::Equals(FrameElement other) { - if (type() != other.type()) return false; - if (is_synced() != other.is_synced()) return false; + if (type_ != other.type_) return false; if (is_register()) { if (!reg().is(other.reg())) return false; @@ -539,17 +550,13 @@ bool FrameElement::Equals(FrameElement other) { bool VirtualFrame::Equals(VirtualFrame* other) { +#ifdef DEBUG + // These are sanity checks in debug builds, but we do not need to + // use them to distinguish frames at merge points. if (cgen_ != other->cgen_) return false; if (masm_ != other->masm_) return false; - if (elements_.length() != other->elements_.length()) return false; - - for (int i = 0; i < elements_.length(); i++) { - if (!elements_[i].Equals(other->elements_[i])) return false; - } - if (parameter_count_ != other->parameter_count_) return false; if (local_count_ != other->local_count_) return false; - if (stack_pointer_ != other->stack_pointer_) return false; if (frame_pointer_ != other->frame_pointer_) return false; for (int i = 0; i < kNumRegisters; i++) { @@ -557,6 +564,12 @@ bool VirtualFrame::Equals(VirtualFrame* other) { return false; } } + if (elements_.length() != other->elements_.length()) return false; +#endif + if (stack_pointer_ != other->stack_pointer_) return false; + for (int i = 0; i < elements_.length(); i++) { + if (!elements_[i].Equals(other->elements_[i])) return false; + } return true; } diff --git a/src/virtual-frame.h b/src/virtual-frame.h index f28744d14e..71f21c3050 100644 --- a/src/virtual-frame.h +++ b/src/virtual-frame.h @@ -101,6 +101,16 @@ class FrameElement BASE_EMBEDDED { bool is_constant() const { return type() == CONSTANT; } bool is_copy() const { return type() == COPY; } + bool is_copied() const { return IsCopiedField::decode(type_); } + + void set_copied() { + type_ = (type_ & ~IsCopiedField::mask()) | IsCopiedField::encode(true); + } + + void clear_copied() { + type_ = (type_ & ~IsCopiedField::mask()) | IsCopiedField::encode(false); + } + Register reg() const { ASSERT(is_register()); return data_.reg_; @@ -129,7 +139,8 @@ class FrameElement BASE_EMBEDDED { // BitField is . class SyncField : public BitField {}; - class TypeField : public BitField {}; + class IsCopiedField : public BitField {}; + class TypeField : public BitField {}; Type type() const { return TypeField::decode(type_); } @@ -144,10 +155,6 @@ class FrameElement BASE_EMBEDDED { int index_; } data_; - // The index of the next element in a list of copies, or the frame's - // illegal index if there is no next element. - int next_; - // Used to construct memory and register elements. FrameElement(Type type, Register reg, SyncFlag is_synced) { Initialize(type, reg, is_synced); @@ -175,16 +182,18 @@ class FrameElement BASE_EMBEDDED { namespace v8 { namespace internal { FrameElement::FrameElement(Handle value, SyncFlag is_synced) { - type_ = TypeField::encode(CONSTANT) | SyncField::encode(is_synced); + type_ = TypeField::encode(CONSTANT) + | IsCopiedField::encode(false) + | SyncField::encode(is_synced); data_.handle_ = value.location(); - next_ = VirtualFrame::kIllegalIndex; } void FrameElement::Initialize(Type type, Register reg, SyncFlag is_synced) { - type_ = TypeField::encode(type) | SyncField::encode(is_synced); + type_ = TypeField::encode(type) + | IsCopiedField::encode(false) + | SyncField::encode(is_synced); data_.reg_ = reg; - next_ = VirtualFrame::kIllegalIndex; }