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
parent 881e01b2
...@@ -99,7 +99,7 @@ static void DumpBuffer(FILE* f, char* buff) { ...@@ -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 const int kRelocInfoPosition = 57;
static int DecodeIt(FILE* f, static int DecodeIt(FILE* f,
......
...@@ -270,6 +270,16 @@ void JumpTarget::ComputeEntryFrame(int mergable_elements) { ...@@ -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. // Fill in the other fields of the entry frame.
entry_frame_->local_count_ = initial_frame->local_count_; entry_frame_->local_count_ = initial_frame->local_count_;
entry_frame_->frame_pointer_ = initial_frame->frame_pointer_; entry_frame_->frame_pointer_ = initial_frame->frame_pointer_;
......
...@@ -171,11 +171,10 @@ void VirtualFrame::MergeTo(VirtualFrame* expected) { ...@@ -171,11 +171,10 @@ void VirtualFrame::MergeTo(VirtualFrame* expected) {
MergeMoveRegistersToRegisters(expected); MergeMoveRegistersToRegisters(expected);
MergeMoveMemoryToRegisters(expected); MergeMoveMemoryToRegisters(expected);
// Fix any sync bit problems from the bottom-up, stopping when we // Fix any sync flag problems from the bottom-up and make the copied
// hit the stack pointer or the top of the frame if the stack // flags exact. This assumes that the backing store of copies is
// pointer is floating above the frame. // always lower in the frame.
int limit = Min(stack_pointer_, elements_.length() - 1); for (int i = 0; i < elements_.length(); i++) {
for (int i = 0; i <= limit; i++) {
FrameElement source = elements_[i]; FrameElement source = elements_[i];
FrameElement target = expected->elements_[i]; FrameElement target = expected->elements_[i];
if (source.is_synced() && !target.is_synced()) { if (source.is_synced() && !target.is_synced()) {
...@@ -183,6 +182,10 @@ void VirtualFrame::MergeTo(VirtualFrame* expected) { ...@@ -183,6 +182,10 @@ void VirtualFrame::MergeTo(VirtualFrame* expected) {
} else if (!source.is_synced() && target.is_synced()) { } else if (!source.is_synced() && target.is_synced()) {
SyncElementAt(i); SyncElementAt(i);
} }
elements_[i].clear_copied();
if (elements_[i].is_copy()) {
elements_[elements_[i].index()].set_copied();
}
} }
// Adjust the stack point downard if necessary. // Adjust the stack point downard if necessary.
...@@ -550,6 +553,7 @@ FrameElement VirtualFrame::AdjustCopies(int index) { ...@@ -550,6 +553,7 @@ FrameElement VirtualFrame::AdjustCopies(int index) {
return copy; return copy;
} }
elements_[index].clear_copied();
return FrameElement::InvalidElement(); return FrameElement::InvalidElement();
} }
...@@ -569,7 +573,9 @@ void VirtualFrame::TakeFrameSlotAt(int index) { ...@@ -569,7 +573,9 @@ void VirtualFrame::TakeFrameSlotAt(int index) {
// push that register on top of the frame. If it is 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 // make the first copy the backing store and push a fresh copy
// on top of the frame. // on top of the frame.
FrameElement copy = AdjustCopies(index); FrameElement copy = original.is_copied()
? AdjustCopies(index)
: FrameElement::InvalidElement();
if (copy.is_valid()) { if (copy.is_valid()) {
// The original element was a copy. Push the copy of the new // The original element was a copy. Push the copy of the new
// backing store. // backing store.
...@@ -593,7 +599,9 @@ void VirtualFrame::TakeFrameSlotAt(int index) { ...@@ -593,7 +599,9 @@ void VirtualFrame::TakeFrameSlotAt(int index) {
// If the element is not copied, push it on top of the frame. // 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 // If it is copied, make the first copy be the new backing store
// and push a fresh copy on top of the frame. // 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()) { if (copy.is_valid()) {
// The original element was a copy. Push the copy of the new // The original element was a copy. Push the copy of the new
// backing store. // backing store.
...@@ -634,7 +642,8 @@ void VirtualFrame::StoreToFrameSlotAt(int index) { ...@@ -634,7 +642,8 @@ void VirtualFrame::StoreToFrameSlotAt(int index) {
FrameElement original = elements_[index]; FrameElement original = elements_[index];
// If the stored-to slot may be copied, adjust to preserve the // If the stored-to slot may be copied, adjust to preserve the
// copy-on-write semantics of copied elements. // 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); FrameElement ignored = AdjustCopies(index);
} }
......
...@@ -93,9 +93,11 @@ FrameElement VirtualFrame::CopyElementAt(int index) { ...@@ -93,9 +93,11 @@ FrameElement VirtualFrame::CopyElementAt(int index) {
case FrameElement::REGISTER: case FrameElement::REGISTER:
// All copies are backed by memory or register locations. // All copies are backed by memory or register locations.
result.type_ = result.type_ =
FrameElement::TypeField::encode(FrameElement::COPY) | FrameElement::TypeField::encode(FrameElement::COPY)
FrameElement::SyncField::encode(FrameElement::NOT_SYNCED); | FrameElement::IsCopiedField::encode(false)
| FrameElement::SyncField::encode(FrameElement::NOT_SYNCED);
result.data_.index_ = index; result.data_.index_ = index;
elements_[index].set_copied();
break; break;
case FrameElement::INVALID: case FrameElement::INVALID:
...@@ -208,11 +210,15 @@ void VirtualFrame::SpillElementAt(int index) { ...@@ -208,11 +210,15 @@ void VirtualFrame::SpillElementAt(int index) {
if (!elements_[index].is_valid()) return; if (!elements_[index].is_valid()) return;
SyncElementAt(index); 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()) { if (elements_[index].is_register()) {
Unuse(elements_[index].reg()); Unuse(elements_[index].reg());
} }
// The element is now in memory. elements_[index] = new_element;
elements_[index] = FrameElement::MemoryElement();
} }
...@@ -276,6 +282,11 @@ void VirtualFrame::PrepareMergeTo(VirtualFrame* expected) { ...@@ -276,6 +282,11 @@ void VirtualFrame::PrepareMergeTo(VirtualFrame* expected) {
ASSERT(source.is_valid()); ASSERT(source.is_valid());
elements_[i].clear_sync(); 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) { ...@@ -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 // If the original may be a copy, adjust to preserve the copy-on-write
// semantics of copied elements. // 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); FrameElement ignored = AdjustCopies(frame_index);
} }
...@@ -523,8 +535,7 @@ void VirtualFrame::Nip(int num_dropped) { ...@@ -523,8 +535,7 @@ void VirtualFrame::Nip(int num_dropped) {
bool FrameElement::Equals(FrameElement other) { bool FrameElement::Equals(FrameElement other) {
if (type() != other.type()) return false; if (type_ != other.type_) return false;
if (is_synced() != other.is_synced()) return false;
if (is_register()) { if (is_register()) {
if (!reg().is(other.reg())) return false; if (!reg().is(other.reg())) return false;
...@@ -539,17 +550,13 @@ bool FrameElement::Equals(FrameElement other) { ...@@ -539,17 +550,13 @@ bool FrameElement::Equals(FrameElement other) {
bool VirtualFrame::Equals(VirtualFrame* 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 (cgen_ != other->cgen_) return false;
if (masm_ != other->masm_) 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 (parameter_count_ != other->parameter_count_) return false;
if (local_count_ != other->local_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; if (frame_pointer_ != other->frame_pointer_) return false;
for (int i = 0; i < kNumRegisters; i++) { for (int i = 0; i < kNumRegisters; i++) {
...@@ -557,6 +564,12 @@ bool VirtualFrame::Equals(VirtualFrame* other) { ...@@ -557,6 +564,12 @@ bool VirtualFrame::Equals(VirtualFrame* other) {
return false; 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; return true;
} }
......
...@@ -101,6 +101,16 @@ class FrameElement BASE_EMBEDDED { ...@@ -101,6 +101,16 @@ class FrameElement BASE_EMBEDDED {
bool is_constant() const { return type() == CONSTANT; } bool is_constant() const { return type() == CONSTANT; }
bool is_copy() const { return type() == COPY; } 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 { Register reg() const {
ASSERT(is_register()); ASSERT(is_register());
return data_.reg_; return data_.reg_;
...@@ -129,7 +139,8 @@ class FrameElement BASE_EMBEDDED { ...@@ -129,7 +139,8 @@ class FrameElement BASE_EMBEDDED {
// BitField is <type, shift, size>. // BitField is <type, shift, size>.
class SyncField : public BitField<SyncFlag, 0, 1> {}; class SyncField : public BitField<SyncFlag, 0, 1> {};
class TypeField : public BitField<Type, 1, 32 - 1> {}; class IsCopiedField : public BitField<bool, 1, 1> {};
class TypeField : public BitField<Type, 2, 32 - 2> {};
Type type() const { return TypeField::decode(type_); } Type type() const { return TypeField::decode(type_); }
...@@ -144,10 +155,6 @@ class FrameElement BASE_EMBEDDED { ...@@ -144,10 +155,6 @@ class FrameElement BASE_EMBEDDED {
int index_; int index_;
} data_; } 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. // Used to construct memory and register elements.
FrameElement(Type type, Register reg, SyncFlag is_synced) { FrameElement(Type type, Register reg, SyncFlag is_synced) {
Initialize(type, reg, is_synced); Initialize(type, reg, is_synced);
...@@ -175,16 +182,18 @@ class FrameElement BASE_EMBEDDED { ...@@ -175,16 +182,18 @@ class FrameElement BASE_EMBEDDED {
namespace v8 { namespace internal { namespace v8 { namespace internal {
FrameElement::FrameElement(Handle<Object> value, SyncFlag is_synced) { FrameElement::FrameElement(Handle<Object> 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(); data_.handle_ = value.location();
next_ = VirtualFrame::kIllegalIndex;
} }
void FrameElement::Initialize(Type type, Register reg, SyncFlag is_synced) { 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; data_.reg_ = reg;
next_ = VirtualFrame::kIllegalIndex;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment