Author: [email protected]
Date: Thu Apr  2 01:58:18 2009
New Revision: 1669

Modified:
    branches/bleeding_edge/src/codegen-arm.h
    branches/bleeding_edge/src/codegen-ia32.cc
    branches/bleeding_edge/src/codegen-ia32.h
    branches/bleeding_edge/src/codegen.cc
    branches/bleeding_edge/src/codegen.h
    branches/bleeding_edge/src/jump-target-arm.cc
    branches/bleeding_edge/src/jump-target-ia32.cc
    branches/bleeding_edge/src/jump-target.cc
    branches/bleeding_edge/src/jump-target.h

Log:
Clean up return statements in the code generator by explicitly
counting the reference to the return value and passing it to the
return label.  This requires threading it through try/catch and
try/finally.  The return value is loaded into eax more lazily than
before.

Also, perform some related refactoring of jump targets.
Review URL: http://codereview.chromium.org/56172

Modified: branches/bleeding_edge/src/codegen-arm.h
==============================================================================
--- branches/bleeding_edge/src/codegen-arm.h    (original)
+++ branches/bleeding_edge/src/codegen-arm.h    Thu Apr  2 01:58:18 2009
@@ -394,6 +394,7 @@
    // positions are collected by the assembler and emitted with the  
relocation
    // information.
    void CodeForFunctionPosition(FunctionLiteral* fun);
+  void CodeForReturnPosition(FunctionLiteral* fun);
    void CodeForStatementPosition(Node* node);
    void CodeForSourcePosition(int pos);


Modified: branches/bleeding_edge/src/codegen-ia32.cc
==============================================================================
--- branches/bleeding_edge/src/codegen-ia32.cc  (original)
+++ branches/bleeding_edge/src/codegen-ia32.cc  Thu Apr  2 01:58:18 2009
@@ -274,25 +274,29 @@
        if (has_valid_frame()) {
          // If there is a valid frame, control flow can fall off the end of
          // the body.  In that case there is an implicit return statement.
-        // Compiling a return statement will jump to the return sequence if
-        // it is already generated or generate it if not.
          ASSERT(!function_return_is_shadowed_);
-        Literal undefined(Factory::undefined_value());
-        ReturnStatement statement(&undefined);
-        statement.set_statement_pos(fun->end_position());
-        VisitReturnStatement(&statement);
+        CodeForReturnPosition(fun);
+        frame_->PrepareForReturn();
+        Result undefined(Factory::undefined_value(), this);
+        if (function_return_.is_bound()) {
+          function_return_.Jump(&undefined);
+        } else {
+          // Though this is a (possibly) backward block, the frames
+          // can only differ on their top element.
+          function_return_.Bind(&undefined, 1);
+          GenerateReturnSequence(&undefined);
+        }
        } else if (function_return_.is_linked()) {
          // If the return target has dangling jumps to it, then we have not
          // yet generated the return sequence.  This can happen when (a)
          // control does not flow off the end of the body so we did not
          // compile an artificial return statement just above, and (b) there
          // are return statements in the body but (c) they are all shadowed.
-        //
-        // There is no valid frame here but it is safe (also necessary) to
-        // load the return value into eax.
-        __ mov(eax, Immediate(Factory::undefined_value()));
-        function_return_.Bind();
-        GenerateReturnSequence();
+        Result return_value(this);
+        // Though this is a (possibly) backward block, the frames can
+        // only differ on their top element.
+        function_return_.Bind(&return_value, 1);
+        GenerateReturnSequence(&return_value);
        }
      }
    }
@@ -1943,52 +1947,37 @@
    ASSERT(!in_spilled_code());
    Comment cmnt(masm_, "[ ReturnStatement");

+  CodeForStatementPosition(node);
+  Load(node->expression());
+  Result return_value = frame_->Pop();
    if (function_return_is_shadowed_) {
-    // If the function return is shadowed, we spill all information
-    // and just jump to the label.
-    VirtualFrame::SpilledScope spilled_scope(this);
-    CodeForStatementPosition(node);
-    LoadAndSpill(node->expression());
-    frame_->EmitPop(eax);
-    function_return_.Jump();
+    function_return_.Jump(&return_value);
    } else {
-    // Load the returned value.
-    CodeForStatementPosition(node);
-    Load(node->expression());
-
-    // Pop the result from the frame and prepare the frame for
-    // returning thus making it easier to merge.
-    Result result = frame_->Pop();
      frame_->PrepareForReturn();
-
-    // Move the result into register eax where it belongs.
-    result.ToRegister(eax);
-    // TODO(203): Instead of explictly calling Unuse on the result, it
-    // might be better to pass the result to Jump and Bind below.
-    result.Unuse();
-
-    // If the function return label is already bound, we reuse the
-    // code by jumping to the return site.
      if (function_return_.is_bound()) {
-      function_return_.Jump();
+      // If the function return label is already bound we reuse the
+      // code by jumping to the return site.
+      function_return_.Jump(&return_value);
      } else {
-      function_return_.Bind();
-      GenerateReturnSequence();
+      // Though this is a (possibly) backward block, the frames can
+      // only differ on their top element.
+      function_return_.Bind(&return_value, 1);
+      GenerateReturnSequence(&return_value);
      }
    }
  }


-void CodeGenerator::GenerateReturnSequence() {
+void CodeGenerator::GenerateReturnSequence(Result* return_value) {
    // The return value is a live (but not currently reference counted)
    // reference to eax.  This is safe because the current frame does not
    // contain a reference to eax (it is prepared for the return by spilling
    // all registers).
-  ASSERT(has_valid_frame());
    if (FLAG_trace) {
-    frame_->Push(eax);  // Materialize result on the stack.
-    frame_->CallRuntime(Runtime::kTraceExit, 1);
+    frame_->Push(return_value);
+    *return_value = frame_->CallRuntime(Runtime::kTraceExit, 1);
    }
+  return_value->ToRegister(eax);

    // Add a label for checking the size of the code used for returning.
    Label check_exit_codesize;
@@ -2921,14 +2910,22 @@
      }
    }

-  // Generate unlink code for the (formerly) shadowing targets that have  
been
-  // jumped to.  Deallocate each shadow target.
+  // Generate unlink code for the (formerly) shadowing targets that
+  // have been jumped to.  Deallocate each shadow target.
+  Result return_value(this);
    for (int i = 0; i < shadows.length(); i++) {
      if (shadows[i]->is_linked()) {
-      // Unlink from try chain; be careful not to destroy the TOS.
-      shadows[i]->Bind();
-      // Because we can be jumping here (to spilled code) from unspilled
-      // code, we need to reestablish a spilled frame at this block.
+      // Unlink from try chain; be careful not to destroy the TOS if
+      // there is one.
+      if (i == kReturnShadowIndex) {
+        shadows[i]->Bind(&return_value);
+        return_value.ToRegister(eax);
+      } else {
+        shadows[i]->Bind();
+      }
+      // Because we can be jumping here (to spilled code) from
+      // unspilled code, we need to reestablish a spilled frame at
+      // this block.
        frame_->SpillAll();

        // Reload sp from the top handler, because some statements that we
@@ -2943,10 +2940,12 @@
        frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1);
        // next_sp popped.

-      if (!function_return_is_shadowed_ && i == kReturnShadowIndex) {
-        frame_->PrepareForReturn();
+      if (i == kReturnShadowIndex) {
+        if (!function_return_is_shadowed_) frame_->PrepareForReturn();
+        shadows[i]->other_target()->Jump(&return_value);
+      } else {
+        shadows[i]->other_target()->Jump();
        }
-      shadows[i]->other_target()->Jump();
      }
      delete shadows[i];
    }
@@ -3043,13 +3042,18 @@
    for (int i = 0; i < shadows.length(); i++) {
      if (shadows[i]->is_linked()) {
        // If we have come from the shadowed return, the return value is
-      // in (a non-refcounted reference to) eax.  We must preserve it
-      // until it is pushed.
-      //
+      // on the virtual frame.  We must preserve it until it is
+      // pushed.
+      if (i == kReturnShadowIndex) {
+        Result return_value(this);
+        shadows[i]->Bind(&return_value);
+        return_value.ToRegister(eax);
+      } else {
+        shadows[i]->Bind();
+      }
        // Because we can be jumping here (to spilled code) from
        // unspilled code, we need to reestablish a spilled frame at
        // this block.
-      shadows[i]->Bind();
        frame_->SpillAll();

        // Reload sp from the top handler, because some statements that
@@ -3103,14 +3107,23 @@
    // formerly shadowing targets.  Deallocate each shadow target.
    for (int i = 0; i < shadows.length(); i++) {
      if (has_valid_frame() && shadows[i]->is_bound()) {
-      JumpTarget* original = shadows[i]->other_target();
+      BreakTarget* original = shadows[i]->other_target();
        __ cmp(Operand(ecx), Immediate(Smi::FromInt(JUMPING + i)));
-      if (!function_return_is_shadowed_ && i == kReturnShadowIndex) {
-        JumpTarget skip(this);
-        skip.Branch(not_equal);
-        frame_->PrepareForReturn();
-        original->Jump();
-        skip.Bind();
+      if (i == kReturnShadowIndex) {
+        // The return value is (already) in eax.
+        Result return_value = allocator_->Allocate(eax);
+        ASSERT(return_value.is_valid());
+        if (function_return_is_shadowed_) {
+          original->Branch(equal, &return_value);
+        } else {
+          // Branch around the preparation for return which may emit
+          // code.
+          JumpTarget skip(this);
+          skip.Branch(not_equal);
+          frame_->PrepareForReturn();
+          original->Jump(&return_value);
+          skip.Bind();
+        }
        } else {
          original->Branch(equal);
        }

Modified: branches/bleeding_edge/src/codegen-ia32.h
==============================================================================
--- branches/bleeding_edge/src/codegen-ia32.h   (original)
+++ branches/bleeding_edge/src/codegen-ia32.h   Thu Apr  2 01:58:18 2009
@@ -371,11 +371,10 @@
    // Main code generation function
    void GenCode(FunctionLiteral* fun);

-  // Generate the return sequence code.  Should be called no more than once
-  // per compiled function (it binds the return target, which can not be
-  // done more than once).  The return value is assumed to be in eax by the
-  // code generated.
-  void GenerateReturnSequence();
+  // Generate the return sequence code.  Should be called no more than
+  // once per compiled function, immediately after binding the return
+  // target (which can not be done more than once).
+  void GenerateReturnSequence(Result* return_value);

    // The following are used by class Reference.
    void LoadReference(Reference* ref);
@@ -567,6 +566,7 @@
    // positions are collected by the assembler and emitted with the  
relocation
    // information.
    void CodeForFunctionPosition(FunctionLiteral* fun);
+  void CodeForReturnPosition(FunctionLiteral* fun);
    void CodeForStatementPosition(Node* node);
    void CodeForSourcePosition(int pos);


Modified: branches/bleeding_edge/src/codegen.cc
==============================================================================
--- branches/bleeding_edge/src/codegen.cc       (original)
+++ branches/bleeding_edge/src/codegen.cc       Thu Apr  2 01:58:18 2009
@@ -566,12 +566,23 @@
  }


+void CodeGenerator::CodeForReturnPosition(FunctionLiteral* fun) {
+  if (FLAG_debug_info) {
+    int pos = fun->start_position();
+    if (pos != RelocInfo::kNoPosition) {
+      masm()->RecordStatementPosition(pos);
+      masm()->RecordPosition(pos);
+    }
+  }
+}
+
+
  void CodeGenerator::CodeForStatementPosition(Node* node) {
    if (FLAG_debug_info) {
      int pos = node->statement_pos();
      if (pos != RelocInfo::kNoPosition) {
        masm()->RecordStatementPosition(pos);
-      CodeForSourcePosition(pos);
+      masm()->RecordPosition(pos);
      }
    }
  }

Modified: branches/bleeding_edge/src/codegen.h
==============================================================================
--- branches/bleeding_edge/src/codegen.h        (original)
+++ branches/bleeding_edge/src/codegen.h        Thu Apr  2 01:58:18 2009
@@ -35,37 +35,41 @@
  // Include the declaration of the architecture defined class CodeGenerator.
  // The contract  to the shared code is that the the CodeGenerator is a  
subclass
  // of Visitor and that the following methods are available publicly:
-// CodeGenerator::MakeCode
-// CodeGenerator::SetFunctionInfo
-// CodeGenerator::masm
-// CodeGenerator::frame
-// CodeGenerator::has_valid_frame
-// CodeGenerator::SetFrame
-// CodeGenerator::DeleteFrame
-// CodeGenerator::allocator
-// CodeGenerator::AddDeferred
-// CodeGenerator::in_spilled_code
-// CodeGenerator::set_in_spilled_code
+//   MakeCode
+//   SetFunctionInfo
+//   masm
+//   frame
+//   has_valid_frame
+//   SetFrame
+//   DeleteFrame
+//   allocator
+//   AddDeferred
+//   in_spilled_code
+//   set_in_spilled_code
  //
  // These methods are either used privately by the shared code or  
implemented as
  // shared code:
-// CodeGenerator::CodeGenerator
-// CodeGenerator::~CodeGenerator
-// CodeGenerator::ProcessDeferred
-// CodeGenerator::ClearDeferred
-// CodeGenerator::GenCode
-// CodeGenerator::BuildBoilerplate
-// CodeGenerator::ComputeCallInitialize
-// CodeGenerator::ComputeCallInitializeInLoop
-// CodeGenerator::ProcessDeclarations
-// CodeGenerator::DeclareGlobals
-// CodeGenerator::CheckForInlineRuntimeCall
-// CodeGenerator::GenerateFastCaseSwitchStatement
-// CodeGenerator::GenerateFastCaseSwitchCases
-// CodeGenerator::TryGenerateFastCaseSwitchStatement
-// CodeGenerator::GenerateFastCaseSwitchJumpTable
-// CodeGenerator::FastCaseSwitchMinCaseCount
-// CodeGenerator::FastCaseSwitchMaxOverheadFactor
+//   CodeGenerator
+//   ~CodeGenerator
+//   ProcessDeferred
+//   ClearDeferred
+//   GenCode
+//   BuildBoilerplate
+//   ComputeCallInitialize
+//   ComputeCallInitializeInLoop
+//   ProcessDeclarations
+//   DeclareGlobals
+//   CheckForInlineRuntimeCall
+//   GenerateFastCaseSwitchStatement
+//   GenerateFastCaseSwitchCases
+//   TryGenerateFastCaseSwitchStatement
+//   GenerateFastCaseSwitchJumpTable
+//   FastCaseSwitchMinCaseCount
+//   FastCaseSwitchMaxOverheadFactor
+//   CodeForFunctionPosition
+//   CodeForReturnPosition
+//   CodeForStatementPosition
+//   CodeForSourcePosition

  #ifdef ARM
  #include "codegen-arm.h"

Modified: branches/bleeding_edge/src/jump-target-arm.cc
==============================================================================
--- branches/bleeding_edge/src/jump-target-arm.cc       (original)
+++ branches/bleeding_edge/src/jump-target-arm.cc       Thu Apr  2 01:58:18 2009
@@ -37,7 +37,7 @@

  #define __ masm_->

-void JumpTarget::Jump() {
+void JumpTarget::DoJump() {
    ASSERT(cgen_ != NULL);
    ASSERT(cgen_->has_valid_frame());
    // Live non-frame registers are not allowed at unconditional jumps
@@ -65,7 +65,7 @@
  }


-void JumpTarget::Branch(Condition cc, Hint ignored) {
+void JumpTarget::DoBranch(Condition cc, Hint ignored) {
    ASSERT(cgen_ != NULL);
    ASSERT(cgen_->has_valid_frame());

@@ -148,7 +148,7 @@
  }


-void JumpTarget::Bind(int mergable_elements) {
+void JumpTarget::DoBind(int mergable_elements) {
    ASSERT(cgen_ != NULL);
    ASSERT(!is_bound());


Modified: branches/bleeding_edge/src/jump-target-ia32.cc
==============================================================================
--- branches/bleeding_edge/src/jump-target-ia32.cc      (original)
+++ branches/bleeding_edge/src/jump-target-ia32.cc      Thu Apr  2 01:58:18 2009
@@ -37,7 +37,7 @@

  #define __ masm_->

-void JumpTarget::Jump() {
+void JumpTarget::DoJump() {
    ASSERT(cgen_ != NULL);
    ASSERT(cgen_->has_valid_frame());
    // Live non-frame registers are not allowed at unconditional jumps
@@ -65,7 +65,7 @@
  }


-void JumpTarget::Branch(Condition cc, Hint hint) {
+void JumpTarget::DoBranch(Condition cc, Hint hint) {
    ASSERT(cgen_ != NULL);
    ASSERT(cgen_->has_valid_frame());

@@ -148,7 +148,7 @@
  }


-void JumpTarget::Bind(int mergable_elements) {
+void JumpTarget::DoBind(int mergable_elements) {
    ASSERT(cgen_ != NULL);
    ASSERT(!is_bound());


Modified: branches/bleeding_edge/src/jump-target.cc
==============================================================================
--- branches/bleeding_edge/src/jump-target.cc   (original)
+++ branches/bleeding_edge/src/jump-target.cc   Thu Apr  2 01:58:18 2009
@@ -298,12 +298,17 @@
  }


+void JumpTarget::Jump() {
+  DoJump();
+}
+
+
  void JumpTarget::Jump(Result* arg) {
    ASSERT(cgen_ != NULL);
    ASSERT(cgen_->has_valid_frame());

    cgen_->frame()->Push(arg);
-  Jump();
+  DoJump();
  }


@@ -313,7 +318,7 @@

    cgen_->frame()->Push(arg0);
    cgen_->frame()->Push(arg1);
-  Jump();
+  DoJump();
  }


@@ -324,7 +329,12 @@
    cgen_->frame()->Push(arg0);
    cgen_->frame()->Push(arg1);
    cgen_->frame()->Push(arg2);
-  Jump();
+  DoJump();
+}
+
+
+void JumpTarget::Branch(Condition cc, Hint hint) {
+  DoBranch(cc, hint);
  }


@@ -352,7 +362,7 @@
    DECLARE_ARGCHECK_VARS(arg);

    cgen_->frame()->Push(arg);
-  Branch(cc, hint);
+  DoBranch(cc, hint);
    *arg = cgen_->frame()->Pop();

    ASSERT_ARGCHECK(arg);
@@ -370,7 +380,7 @@

    cgen_->frame()->Push(arg0);
    cgen_->frame()->Push(arg1);
-  Branch(cc, hint);
+  DoBranch(cc, hint);
    *arg1 = cgen_->frame()->Pop();
    *arg0 = cgen_->frame()->Pop();

@@ -396,7 +406,7 @@
    cgen_->frame()->Push(arg0);
    cgen_->frame()->Push(arg1);
    cgen_->frame()->Push(arg2);
-  Branch(cc, hint);
+  DoBranch(cc, hint);
    *arg2 = cgen_->frame()->Pop();
    *arg1 = cgen_->frame()->Pop();
    *arg0 = cgen_->frame()->Pop();
@@ -427,7 +437,7 @@
    cgen_->frame()->Push(arg1);
    cgen_->frame()->Push(arg2);
    cgen_->frame()->Push(arg3);
-  Branch(cc, hint);
+  DoBranch(cc, hint);
    *arg3 = cgen_->frame()->Pop();
    *arg2 = cgen_->frame()->Pop();
    *arg1 = cgen_->frame()->Pop();
@@ -439,17 +449,47 @@
    ASSERT_ARGCHECK(arg3);
  }

+
+void BreakTarget::Branch(Condition cc, Result* arg, Hint hint) {
+  ASSERT(cgen_ != NULL);
+  ASSERT(cgen_->has_valid_frame());
+
+  int count = cgen_->frame()->height() - expected_height_;
+  if (count > 0) {
+    // We negate and branch here rather than using DoBranch's negate
+    // and branch.  This gives us a hook to remove statement state
+    // from the frame.
+    JumpTarget fall_through(cgen_);
+    // Branch to fall through will not negate, because it is a
+    // forward-only target.
+    fall_through.Branch(NegateCondition(cc), NegateHint(hint));
+    Jump(arg);  // May emit merge code here.
+    fall_through.Bind();
+  } else {
+    DECLARE_ARGCHECK_VARS(arg);
+    cgen_->frame()->Push(arg);
+    DoBranch(cc, hint);
+    *arg = cgen_->frame()->Pop();
+    ASSERT_ARGCHECK(arg);
+  }
+}
+
  #undef DECLARE_ARGCHECK_VARS
  #undef ASSERT_ARGCHECK


+void JumpTarget::Bind(int mergable_elements) {
+  DoBind(mergable_elements);
+}
+
+
  void JumpTarget::Bind(Result* arg, int mergable_elements) {
    ASSERT(cgen_ != NULL);

    if (cgen_->has_valid_frame()) {
      cgen_->frame()->Push(arg);
    }
-  Bind(mergable_elements);
+  DoBind(mergable_elements);
    *arg = cgen_->frame()->Pop();
  }

@@ -461,7 +501,7 @@
      cgen_->frame()->Push(arg0);
      cgen_->frame()->Push(arg1);
    }
-  Bind(mergable_elements);
+  DoBind(mergable_elements);
    *arg1 = cgen_->frame()->Pop();
    *arg0 = cgen_->frame()->Pop();
  }
@@ -478,7 +518,7 @@
      cgen_->frame()->Push(arg1);
      cgen_->frame()->Push(arg2);
    }
-  Bind(mergable_elements);
+  DoBind(mergable_elements);
    *arg2 = cgen_->frame()->Pop();
    *arg1 = cgen_->frame()->Pop();
    *arg0 = cgen_->frame()->Pop();
@@ -498,7 +538,7 @@
      cgen_->frame()->Push(arg2);
      cgen_->frame()->Push(arg3);
    }
-  Bind(mergable_elements);
+  DoBind(mergable_elements);
    *arg3 = cgen_->frame()->Pop();
    *arg2 = cgen_->frame()->Pop();
    *arg1 = cgen_->frame()->Pop();
@@ -548,10 +588,20 @@
    ASSERT(cgen_ != NULL);
    ASSERT(cgen_->has_valid_frame());

-  // This is a break target so drop leftover statement state from the
-  // frame before merging.
+  // Drop leftover statement state from the frame before merging.
    cgen_->frame()->ForgetElements(cgen_->frame()->height() -  
expected_height_);
-  JumpTarget::Jump();
+  DoJump();
+}
+
+
+void BreakTarget::Jump(Result* arg) {
+  ASSERT(cgen_ != NULL);
+  ASSERT(cgen_->has_valid_frame());
+
+  // Drop leftover statement state from the frame before merging.
+  cgen_->frame()->ForgetElements(cgen_->frame()->height() -  
expected_height_);
+  cgen_->frame()->Push(arg);
+  DoJump();
  }


@@ -561,9 +611,9 @@

    int count = cgen_->frame()->height() - expected_height_;
    if (count > 0) {
-    // We negate and branch here rather than using
-    // JumpTarget::Branch's negate and branch.  This gives us a hook
-    // to remove statement state from the frame.
+    // We negate and branch here rather than using DoBranch's negate
+    // and branch.  This gives us a hook to remove statement state
+    // from the frame.
      JumpTarget fall_through(cgen_);
      // Branch to fall through will not negate, because it is a
      // forward-only target.
@@ -571,14 +621,13 @@
      Jump();  // May emit merge code here.
      fall_through.Bind();
    } else {
-    JumpTarget::Branch(cc, hint);
+    DoBranch(cc, hint);
    }
  }


  void BreakTarget::Bind(int mergable_elements) {
  #ifdef DEBUG
-  ASSERT(mergable_elements == kAllElements);
    ASSERT(cgen_ != NULL);
    // All the forward-reaching frames should have been adjusted at the
    // jumps to this target.
@@ -587,13 +636,35 @@
             reaching_frames_[i]->height() == expected_height_);
    }
  #endif
-  // This is a break target so we drop leftover statement state from
-  // the frame before merging, even on the fall through.  This is
-  // because we can bind the return target with state on the frame.
+  // Drop leftover statement state from the frame before merging, even
+  // on the fall through.  This is so we can bind the return target
+  // with state on the frame.
+  if (cgen_->has_valid_frame()) {
+    cgen_->frame()->ForgetElements(cgen_->frame()->height() -  
expected_height_);
+  }
+  DoBind(mergable_elements);
+}
+
+
+void BreakTarget::Bind(Result* arg, int mergable_elements) {
+#ifdef DEBUG
+  ASSERT(cgen_ != NULL);
+  // All the forward-reaching frames should have been adjusted at the
+  // jumps to this target.
+  for (int i = 0; i < reaching_frames_.length(); i++) {
+    ASSERT(reaching_frames_[i] == NULL ||
+           reaching_frames_[i]->height() == expected_height_ + 1);
+  }
+#endif
+  // Drop leftover statement state from the frame before merging, even
+  // on the fall through.  This is so we can bind the return target
+  // with state on the frame.
    if (cgen_->has_valid_frame()) {
      cgen_->frame()->ForgetElements(cgen_->frame()->height() -  
expected_height_);
+    cgen_->frame()->Push(arg);
    }
-  JumpTarget::Bind(mergable_elements);
+  DoBind(mergable_elements);
+  *arg = cgen_->frame()->Pop();
  }



Modified: branches/bleeding_edge/src/jump-target.h
==============================================================================
--- branches/bleeding_edge/src/jump-target.h    (original)
+++ branches/bleeding_edge/src/jump-target.h    Thu Apr  2 01:58:18 2009
@@ -105,7 +105,7 @@
    // Emit a jump to the target.  There must be a current frame at the
    // jump and there will be no current frame after the jump.
    virtual void Jump();
-  void Jump(Result* arg);
+  virtual void Jump(Result* arg);
    void Jump(Result* arg0, Result* arg1);
    void Jump(Result* arg0, Result* arg1, Result* arg2);

@@ -113,7 +113,7 @@
    // frame at the branch.  The current frame will fall through to the
    // code after the branch.
    virtual void Branch(Condition cc, Hint hint = no_hint);
-  void Branch(Condition cc, Result* arg, Hint hint = no_hint);
+  virtual void Branch(Condition cc, Result* arg, Hint hint = no_hint);
    void Branch(Condition cc, Result* arg0, Result* arg1, Hint hint =  
no_hint);
    void Branch(Condition cc,
                Result* arg0,
@@ -141,7 +141,7 @@
    // frame elements must be mergable.  Mergable elements are ignored
    // completely for forward-only jump targets.
    virtual void Bind(int mergable_elements = kAllElements);
-  void Bind(Result* arg, int mergable_elements = kAllElements);
+  virtual void Bind(Result* arg, int mergable_elements = kAllElements);
    void Bind(Result* arg0, Result* arg1, int mergable_elements =  
kAllElements);
    void Bind(Result* arg0,
              Result* arg1,
@@ -191,6 +191,12 @@
    bool is_bound_;
    bool is_linked_;

+  // Implementations of Jump, Branch, and Bind with all arguments and
+  // return values using the virtual frame.
+  void DoJump();
+  void DoBranch(Condition cc, Hint hint);
+  void DoBind(int mergable_elements);
+
   private:
    // Add a virtual frame reaching this labeled block via a forward
    // jump, and a fresh label for its merge code.
@@ -243,16 +249,19 @@
    // Emit a jump to the target.  There must be a current frame at the
    // jump and there will be no current frame after the jump.
    virtual void Jump();
+  virtual void Jump(Result* arg);

    // Emit a conditional branch to the target.  There must be a current
    // frame at the branch.  The current frame will fall through to the
    // code after the branch.
    virtual void Branch(Condition cc, Hint hint = no_hint);
+  virtual void Branch(Condition cc, Result* arg, Hint hint = no_hint);

    // Bind a break target.  If there is no current frame at the binding
    // site, there must be at least one frame reaching via a forward
    // jump.
    virtual void Bind(int mergable_elements = kAllElements);
+  virtual void Bind(Result* arg, int mergable_elements = kAllElements);

    // Setter for expected height.
    void set_expected_height(int expected) { expected_height_ = expected; }

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

Reply via email to