Author: [EMAIL PROTECTED]
Date: Thu Nov 20 02:03:11 2008
New Revision: 803
Modified:
branches/experimental/toiger/src/checks.h
branches/experimental/toiger/src/virtual-frame-ia32.cc
branches/experimental/toiger/src/virtual-frame-ia32.h
Log:
Experimental: initial simple support for registers in the virtual
frame.
It's impossible to do anything interesting without a register file
abstraction to track live registers and merge code for frames
containing registers.
Review URL: http://codereview.chromium.org/11472
Modified: branches/experimental/toiger/src/checks.h
==============================================================================
--- branches/experimental/toiger/src/checks.h (original)
+++ branches/experimental/toiger/src/checks.h Thu Nov 20 02:03:11 2008
@@ -228,8 +228,8 @@
// actually causes each use to introduce a new defined type with a
// name depending on the source line.
template <int> class StaticAssertionHelper { };
-#define
STATIC_CHECK(test) \
-
typedef
\
+#define
STATIC_CHECK(test) \
+
typedef \
StaticAssertionHelper<sizeof(StaticAssertion<static_cast<bool>(test)>)> \
SEMI_STATIC_JOIN(__StaticAssertTypedef__, __LINE__)
Modified: branches/experimental/toiger/src/virtual-frame-ia32.cc
==============================================================================
--- branches/experimental/toiger/src/virtual-frame-ia32.cc (original)
+++ branches/experimental/toiger/src/virtual-frame-ia32.cc Thu Nov 20
02:03:11 2008
@@ -99,25 +99,53 @@
}
-void VirtualFrame::SpillAll() {
- int i = 0;
-
- // Spill dirty constants below the stack pointer.
- for (; i <= stack_pointer_; i++) {
- if (elements_[i].type() == FrameElement::CONSTANT &&
- elements_[i].is_dirty()) {
- __ mov(Operand(ebp, fp_relative(i)),
Immediate(elements_[i].handle()));
- elements_[i] = FrameElement(); // The element is now in memory.
+// 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 (index <= stack_pointer_) {
+ // Write elements below the stack pointer to their (already
allocated)
+ // actual frame location.
+ if (element.is_constant()) {
+ __ Set(Operand(ebp, fp_relative(index)),
Immediate(element.handle()));
+ } else {
+ ASSERT(element.is_register());
+ __ mov(Operand(ebp, fp_relative(index)), element.reg());
+ }
+ } else {
+ // Push elements above the stack pointer to allocate space and sync
+ // them. Space should have already been allocated in the actual
frame
+ // for all the elements below this one.
+ ASSERT(index == stack_pointer_ + 1);
+ stack_pointer_++;
+ if (element.is_constant()) {
+ __ push(Immediate(element.handle()));
+ } else {
+ ASSERT(element.is_register());
+ __ push(element.reg());
+ }
}
}
+}
+
+
+// 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.
+ elements_[index] = FrameElement();
+}
- // Spill all constants above the stack pointer.
- for (; i < elements_.length(); i++) {
- ASSERT(elements_[i].type() == FrameElement::CONSTANT);
- ASSERT(elements_[i].is_dirty());
- stack_pointer_++;
- __ push(Immediate(elements_[i].handle()));
- elements_[i] = FrameElement(); // The element is now in memory.
+
+// Make the type of all elements be MEMORY.
+void VirtualFrame::SpillAll() {
+ for (int i = 0; i < elements_.length(); i++) {
+ SpillElementAt(i);
}
}
@@ -125,25 +153,34 @@
void VirtualFrame::PrepareForCall(int frame_arg_count) {
ASSERT(height() >= frame_arg_count);
- // The only non-memory elements of the frame are constants. Push all of
- // them above the stack pointer to allocate space for them and to ensure
- // the arguments are flushed to memory.
+ // Below the stack pointer, spill all registers.
+ for (int i = 0; i <= stack_pointer_; i++) {
+ if (elements_[i].is_register()) {
+ SpillElementAt(i);
+ }
+ }
+
+ // Above the stack pointer, spill registers and sync everything else (ie,
+ // constants).
for (int i = stack_pointer_ + 1; i < elements_.length(); i++) {
- ASSERT(elements_[i].type() == FrameElement::CONSTANT);
- ASSERT(elements_[i].is_dirty());
- stack_pointer_++;
- elements_[i].clear_dirty();
- __ push(Immediate(elements_[i].handle()));
+ if (elements_[i].is_register()) {
+ SpillElementAt(i);
+ } else {
+ SyncElementAt(i);
+ }
}
- // Forget the ones that will be popped by the call.
+ // Forget the frame elements that will be popped by the call.
Forget(frame_arg_count);
}
void VirtualFrame::EnsureMergable() {
// We cannot merge to a frame that has constants as elements, because an
- // arbitrary frame may not have constants in those locations.
+ // arbitrary frame might not have constants in those locations.
+ //
+ // We cannot merge to a frame that has registers as elements because we
+ // haven't implemented merging for such frames yet.
SpillAll();
}
@@ -155,9 +192,11 @@
ASSERT(local_count_ == expected->local_count_);
ASSERT(frame_pointer_ == expected->frame_pointer_);
- // The expected frame is one we can merge to (ie, currently that means
- // that all elements are in memory). The only thing we need to do to
- // merge is make this one mergable too.
+ // Mergable frames do not have constants and they do not (currently) have
+ // registers. They are always fully spilled, so the only thing needed to
+ // make this frame match the expected one is to spill everything.
+ //
+ // TODO(): Implement a non-stupid way of merging frames.
SpillAll();
ASSERT(stack_pointer_ == expected->stack_pointer_);
@@ -172,11 +211,21 @@
__ mov(ebp, Operand(esp));
// Store the context and the function in the frame.
- EmitPush(esi);
- EmitPush(edi);
+ FrameElement context(esi);
+ context.clear_dirty();
+ elements_.Add(context);
+ stack_pointer_++;
+ __ push(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)));
}
}
Modified: branches/experimental/toiger/src/virtual-frame-ia32.h
==============================================================================
--- branches/experimental/toiger/src/virtual-frame-ia32.h (original)
+++ branches/experimental/toiger/src/virtual-frame-ia32.h Thu Nov 20
02:03:11 2008
@@ -41,28 +41,40 @@
class FrameElement BASE_EMBEDDED {
public:
- enum Type { MEMORY, CONSTANT, LAST_TYPE = CONSTANT };
+ FrameElement() {
+ type_ = TypeField::encode(MEMORY) | DirtyField::encode(false);
+ // Memory elements have no useful data.
+ data_.reg_ = no_reg;
+ }
- FrameElement() : type_(MEMORY) {}
+ explicit FrameElement(Register reg) {
+ type_ = TypeField::encode(REGISTER) | DirtyField::encode(true);
+ data_.reg_ = reg;
+ }
- explicit FrameElement(Handle<Object> value) : type_(CONSTANT |
kDirtyBit) {
+ explicit FrameElement(Handle<Object> value) {
+ type_ = TypeField::encode(CONSTANT) | DirtyField::encode(true);
data_.handle_ = value.location();
}
- Type type() const { return static_cast<Type>(type_ & kTypeMask); }
-
- bool is_dirty() const {
- return (type_ & kDirtyBit) != 0;
- }
+ bool is_dirty() const { return DirtyField::decode(type_); }
void set_dirty() {
ASSERT(type() != MEMORY);
- type_ = type_ | kDirtyBit;
+ type_ = type_ | DirtyField::encode(true);
}
void clear_dirty() {
ASSERT(type() != MEMORY);
- type_ = type_ & ~kDirtyBit;
+ type_ = type_ & ~DirtyField::mask();
+ }
+
+ bool is_register() const { return type() == REGISTER; }
+ bool is_constant() const { return type() == CONSTANT; }
+
+ Register reg() const {
+ ASSERT(type() == REGISTER);
+ return data_.reg_;
}
Handle<Object> handle() const {
@@ -71,10 +83,13 @@
}
private:
- static const int kDirtyBit = 1 << 8;
- static const int kTypeMask = kDirtyBit - 1;
+ enum Type { MEMORY, REGISTER, CONSTANT };
- STATIC_ASSERT((kDirtyBit > LAST_TYPE));
+ // BitField is <type, shift, size>.
+ class DirtyField : public BitField<bool, 0, 1> {};
+ class TypeField : public BitField<Type, 1, 32 - 1> {};
+
+ Type type() const { return TypeField::decode(type_); }
// The element's type and a dirty bit. The dirty bit can be cleared
// for non-memory elements to indicate that the element agrees with
@@ -82,6 +97,7 @@
int type_;
union {
+ Register reg_;
Object** handle_;
} data_;
};
@@ -257,6 +273,18 @@
int fp_relative(int index) const {
return (frame_pointer_ - index) * kPointerSize;
}
+
+ // Sync the element at a particular index---write it to memory if
+ // necessary, but do not free any associated register or forget its value
+ // if constant. Space should have already been allocated in the actual
+ // frame for all the elements below this one (at least).
+ void SyncElementAt(int index);
+
+ // Spill the element at a particular index---write it to memory if
+ // necessary, free any associated register, and forget its value if
+ // constant. Space should have already been allocated in the actual
frame
+ // for all the elements below this one (at least).
+ void SpillElementAt(int index);
// Spill the topmost elements of the frame to memory (eg, they are the
// arguments to a call) and all registers.
--~--~---------~--~----~------------~-------~--~----~
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
-~----------~----~----~----~------~----~------~--~---