Author: whessev8
Date: Wed Jan  7 08:35:15 2009
New Revision: 1041

Modified:
    branches/experimental/toiger/src/codegen-ia32.cc
    branches/experimental/toiger/src/virtual-frame-ia32.cc
    branches/experimental/toiger/src/virtual-frame-ia32.h

Log:
Adds Nip() function, makes UnloadReference() work without spilling
frames.
Review URL: http://codereview.chromium.org/16572

Modified: branches/experimental/toiger/src/codegen-ia32.cc
==============================================================================
--- branches/experimental/toiger/src/codegen-ia32.cc    (original)
+++ branches/experimental/toiger/src/codegen-ia32.cc    Wed Jan  7 08:35:15  
2009
@@ -549,17 +549,7 @@
  void CodeGenerator::UnloadReference(Reference* ref) {
    // Pop a reference from the stack while preserving TOS.
    Comment cmnt(masm_, "[ UnloadReference");
-  int size = ref->size();
-  if (size == 1) {
-    VirtualFrame::SpilledScope spilled_scope(this);
-    frame_->EmitPop(eax);
-    __ mov(frame_->Top(), eax);
-  } else if (size > 1) {
-    VirtualFrame::SpilledScope spilled_scope(this);
-    frame_->EmitPop(eax);
-    frame_->Drop(size);
-    frame_->EmitPush(eax);
-  }
+  frame_->Nip(ref->size());
  }


@@ -3114,7 +3104,7 @@
          var->mode() == Variable::CONST &&
          node->op() != Token::INIT_VAR && node->op() != Token::INIT_CONST) {
        // Assignment ignored - leave the value on the stack.
-  } else {
+    } else {
        CodeForSourcePosition(node->position());
        if (node->op() == Token::INIT_CONST) {
          // Dynamic constant initializations must use the function context

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      Wed Jan  7  
08:35:15 2009
@@ -410,6 +410,24 @@
    MergeMoveRegistersToRegisters(expected);
    MergeMoveMemoryToRegisters(expected);

+  int height_difference = stack_pointer_ - expected->stack_pointer_;
+  if (stack_pointer_ > expected->stack_pointer_) {
+#ifdef DEBUG
+    for (int i = stack_pointer_; i > expected->stack_pointer_; i--) {
+      ASSERT(!elements_[i].is_memory());
+      ASSERT(!elements_[i].is_synced());
+    }
+#endif
+    __ add(Operand(esp), Immediate(height_difference * kPointerSize));
+    stack_pointer_ = expected->stack_pointer_;
+  } else if (stack_pointer_ < expected->stack_pointer_) {
+    // Put valid data on the stack, that will only be accessed by GC.
+    while (stack_pointer_ < expected->stack_pointer_) {
+      __ push(Immediate(Smi::FromInt(0)));
+      stack_pointer_++;
+    }
+  }
+
    // At this point, the frames should be identical.
    // TODO(): Consider an "equals" method for frames.
    ASSERT(stack_pointer_ == expected->stack_pointer_);
@@ -674,25 +692,33 @@
    ASSERT(frame_index >= 0);
    ASSERT(frame_index < elements_.length());
    ASSERT(value->is_valid());
+  FrameElement target = elements_[frame_index];

-  // TODO(): if the element is backed by the same register or the same
-  // constant, consider preserving the sync bit.
-  if (elements_[frame_index].is_register()) {
-    Unuse(elements_[frame_index].reg());
+  if (target.is_register()) {
+    Unuse(target.reg());
    }

    if (value->is_register()) {
      Use(value->reg());
-    elements_[frame_index] =
-        FrameElement::RegisterElement(value->reg(),
-                                      FrameElement::NOT_SYNCED);
+    // Write the new value to the frame, if it is changed.
+    // Otherwise, if target equals value, keep its current sync state.
+    if (!target.is_register() ||
+        !value->reg().is(target.reg())) {
+      elements_[frame_index] =
+          FrameElement::RegisterElement(value->reg(),
+                                        FrameElement::NOT_SYNCED);
+    }
    } else {
      ASSERT(value->is_constant());
-    elements_[frame_index] =
-        FrameElement::ConstantElement(value->handle(),
-                                      FrameElement::NOT_SYNCED);
+    // Write the new value to the frame element, if it is a change.
+    // Otherwise, do nothing, and keep the current sync state.
+    if (!target.is_constant() ||
+        !value->handle().is_identical_to(target.handle())) {
+      elements_[frame_index] =
+          FrameElement::ConstantElement(value->handle(),
+                                        FrameElement::NOT_SYNCED);
+    }
    }
-
    value->Unuse();
  }

@@ -1004,6 +1030,17 @@
      Push(result->handle());
    }
    result->Unuse();
+}
+
+
+void VirtualFrame::Nip(int num_dropped) {
+  ASSERT(num_dropped >= 0);
+  if (num_dropped == 0) return;
+  Result tos = Pop();
+  if (num_dropped > 1) {
+    Drop(num_dropped - 1);
+  }
+  SetElementAt(0, &tos);
  }



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       Wed Jan  7  
08:35:15 2009
@@ -385,6 +385,11 @@
    // frame).
    void Push(Result* result);

+  // Nip removes zero or more elements from immediately below the top
+  // of the frame, leaving the previous top-of-frame value on top of
+  // the frame.  Nip(k) is equivalent to x = Pop(), Drop(k), Push(x).
+  void Nip(int num_dropped);
+
  #ifdef DEBUG
    bool IsSpilled();
  #endif

--~--~---------~--~----~------------~-------~--~----~
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
-~----------~----~----~----~------~----~------~--~---

Reply via email to