Author: [email protected]
Date: Tue Jan  6 04:11:09 2009
New Revision: 1027

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:
Experimental: begin using the register allocator across entering and
leaving with statements.

This requires more care with the use of the context (esi on IA32)
register and the frame slot allocated for saving it.
Review URL: http://codereview.chromium.org/16512

Modified: branches/experimental/toiger/src/codegen-ia32.cc
==============================================================================
--- branches/experimental/toiger/src/codegen-ia32.cc    (original)
+++ branches/experimental/toiger/src/codegen-ia32.cc    Tue Jan  6 04:11:09  
2009
@@ -194,7 +194,7 @@
          verified_true.Bind();
        }
        // Update context local.
-      __ mov(frame_->Context(), esi);
+      frame_->SaveContextRegister();
      }

      // TODO(1241774): Improve this code:
@@ -1351,7 +1351,7 @@
    frame_->CallStub(&call_function, arg_count + 1);

    // Restore context and pop function from the stack.
-  __ mov(esi, frame_->Context());
+  frame_->RestoreContextRegister();
    __ mov(frame_->Top(), eax);
  }

@@ -1660,39 +1660,41 @@

  void CodeGenerator::VisitWithEnterStatement(WithEnterStatement* node) {
    ASSERT(!in_spilled_code());
-  VirtualFrame::SpilledScope spilled_scope(this);
    Comment cmnt(masm_, "[ WithEnterStatement");
    CodeForStatement(node);
-  LoadAndSpill(node->expression());
+  Load(node->expression());
+  Result context(this);
    if (node->is_catch_block()) {
-    frame_->CallRuntime(Runtime::kPushCatchContext, 1);
+    context = frame_->CallRuntime(Runtime::kPushCatchContext, 1);
    } else {
-    frame_->CallRuntime(Runtime::kPushContext, 1);
+    context = frame_->CallRuntime(Runtime::kPushContext, 1);
    }

    if (kDebug) {
      JumpTarget verified_true(this);
-    // Verify eax and esi are the same in debug mode
-    __ cmp(eax, Operand(esi));
-    verified_true.Branch(equal);
+    // Verify that the result of the runtime call and the esi register are
+    // the same in debug mode.
+    __ cmp(context.reg(), Operand(esi));
+    verified_true.Branch(equal, &context);
+    frame_->SpillAll();
      __ int3();
-    verified_true.Bind();
+    verified_true.Bind(&context);
    }
+  context.Unuse();

    // Update context local.
-  __ mov(frame_->Context(), esi);
+  frame_->SaveContextRegister();
  }


  void CodeGenerator::VisitWithExitStatement(WithExitStatement* node) {
    ASSERT(!in_spilled_code());
-  VirtualFrame::SpilledScope spilled_scope(this);
    Comment cmnt(masm_, "[ WithExitStatement");
    CodeForStatement(node);
    // Pop context.
    __ mov(esi, ContextOperand(esi, Context::PREVIOUS_INDEX));
    // Update context local.
-  __ mov(frame_->Context(), esi);
+  frame_->SaveContextRegister();
  }


@@ -2640,7 +2642,7 @@

      // For now, just do a runtime call.
      VirtualFrame::SpilledScope spilled_scope(this);
-    frame_->EmitPush(frame_->Context());
+    frame_->EmitPush(esi);
      frame_->EmitPush(Immediate(slot->var()->name()));

      if (init_state == CONST_INIT) {
@@ -3122,7 +3124,7 @@
      CodeForSourcePosition(node->position());
      frame_->CallCodeObject(stub, RelocInfo::CODE_TARGET_CONTEXT,
                             arg_count + 1);
-    __ mov(esi, frame_->Context());
+    frame_->RestoreContextRegister();

      // Overwrite the function on the stack with the result.
      __ mov(frame_->Top(), eax);
@@ -3171,7 +3173,7 @@
          : ComputeCallInitialize(arg_count);
        CodeForSourcePosition(node->position());
        frame_->CallCodeObject(stub, RelocInfo::CODE_TARGET, arg_count + 1);
-      __ mov(esi, frame_->Context());
+      frame_->RestoreContextRegister();

        // Overwrite the function on the stack with the result.
        __ mov(frame_->Top(), eax);
@@ -3299,7 +3301,7 @@
    frame_->CallStub(&call_function, arg_count + 1);

    // Restore context and pop function from the stack.
-  __ mov(esi, frame_->Context());
+  frame_->RestoreContextRegister();
    __ mov(frame_->Top(), eax);
  }

@@ -3582,7 +3584,7 @@
      Handle<Code> stub = ComputeCallInitialize(arg_count);
      __ Set(eax, Immediate(args->length()));
      frame_->CallCodeObject(stub, RelocInfo::CODE_TARGET, arg_count + 1);
-    __ mov(esi, frame_->Context());
+    frame_->RestoreContextRegister();
      __ mov(frame_->Top(), eax);
    } else {
      // Call the C runtime function.

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      Tue Jan  6  
04:11:09 2009
@@ -590,11 +590,10 @@
    frame_pointer_ = stack_pointer_;
    __ mov(ebp, Operand(esp));

-  // Store the context in the frame.  The context is kept in esi, so the
-  // register reference is not owned by the frame (ie, the frame is not  
free
-  // to spill it).  This is implemented by making the in-frame value be
-  // memory.
-  EmitPush(esi);
+  // Store the context in the frame.  The context is kept in esi and a
+  // copy is stored in the frame.  The external reference to esi
+  // remains in addition to the cached copy in the frame.
+  Push(esi);

    // Store the function in the frame.  The frame owns the register  
reference
    // now (ie, it can keep it in edi or spill it later).
@@ -681,6 +680,38 @@
  }


+void VirtualFrame::SaveContextRegister() {
+  FrameElement current = elements_[context_index()];
+  ASSERT(current.is_register() || current.is_memory());
+  if (!current.is_register() || !current.reg().is(esi)) {
+    if (current.is_register()) {
+      Unuse(current.reg());
+    }
+    Use(esi);
+    elements_[context_index()] =
+        FrameElement::RegisterElement(esi, FrameElement::NOT_SYNCED);
+  }
+}
+
+
+void VirtualFrame::RestoreContextRegister() {
+  FrameElement current = elements_[context_index()];
+  ASSERT(current.is_register() || current.is_memory());
+  if (current.is_register() && !current.reg().is(esi)) {
+    Unuse(current.reg());
+    Use(esi);
+    __ mov(esi, current.reg());
+    elements_[context_index()] =
+        FrameElement::RegisterElement(esi, FrameElement::NOT_SYNCED);
+  } else if (current.is_memory()) {
+    Use(esi);
+    __ mov(esi, Operand(ebp, fp_relative(context_index())));
+    elements_[context_index()] =
+        FrameElement::RegisterElement(esi, FrameElement::SYNCED);
+  }
+}
+
+
  void VirtualFrame::LoadFrameSlotAt(int index) {
    ASSERT(index >= 0);
    ASSERT(index < elements_.length());
@@ -806,17 +837,25 @@
  }


-void VirtualFrame::CallRuntime(Runtime::Function* f, int frame_arg_count) {
+Result VirtualFrame::CallRuntime(Runtime::Function* f,
+                                 int frame_arg_count) {
    ASSERT(cgen_->HasValidEntryRegisters());
    PrepareForCall(frame_arg_count);
    __ CallRuntime(f, frame_arg_count);
+  Result result = cgen_->allocator()->Allocate(eax);
+  ASSERT(result.is_valid());
+  return result;
  }


-void VirtualFrame::CallRuntime(Runtime::FunctionId id, int  
frame_arg_count) {
+Result VirtualFrame::CallRuntime(Runtime::FunctionId id,
+                                 int frame_arg_count) {
    ASSERT(cgen_->HasValidEntryRegisters());
    PrepareForCall(frame_arg_count);
    __ CallRuntime(id, frame_arg_count);
+  Result result = cgen_->allocator()->Allocate(eax);
+  ASSERT(result.is_valid());
+  return result;
  }



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       Tue Jan  6  
04:11:09 2009
@@ -281,8 +281,12 @@
    // The function frame slot.
    Operand Function() const { return Operand(ebp, kFunctionOffset); }

-  // The context frame slot.
-  Operand Context() const { return Operand(ebp, kContextOffset); }
+  // Lazily save the value of the esi register to the context frame slot.
+  void SaveContextRegister();
+
+  // Eagerly restore the esi register from the value of the frame context
+  // slot.
+  void RestoreContextRegister();

    // A parameter as an assembly operand.
    Operand ParameterAt(int index) const {
@@ -326,8 +330,8 @@

    // Call the runtime, given the number of arguments expected on (and
    // removed from) the top of the physical frame.
-  void CallRuntime(Runtime::Function* f, int frame_arg_count);
-  void CallRuntime(Runtime::FunctionId id, int frame_arg_count);
+  Result CallRuntime(Runtime::Function* f, int frame_arg_count);
+  Result CallRuntime(Runtime::FunctionId id, int frame_arg_count);

    // Invoke a builtin, given the number of arguments it expects on (and
    // removes from) the top of the physical frame.

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

Reply via email to