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
This commit is contained in:
kmillikin@chromium.org 2009-03-19 11:57:18 +00:00
parent 881e01b245
commit cd296924b6
5 changed files with 73 additions and 32 deletions

View File

@ -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,

View File

@ -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_;

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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 <type, shift, size>.
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_); }
@ -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<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();
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;
}