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
-~----------~----~----~----~------~----~------~--~---

Reply via email to