Author: [email protected]
Date: Wed Feb 18 04:28:30 2009
New Revision: 1297

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

Log:
Experimental: introduce a simple mechanism to allow jump targets with
backward control flows to indicate at their binding site that only the
topmost N elements need to be mergable.  Aliasing and constants lower
in the frame will be as expected based on the forward control flows.

Use the mechanism for deferred code snippets, which all fit the simple
mechanism.
Review URL: http://codereview.chromium.org/21447

Modified: branches/experimental/toiger/src/codegen-arm.cc
==============================================================================
--- branches/experimental/toiger/src/codegen-arm.cc     (original)
+++ branches/experimental/toiger/src/codegen-arm.cc     Wed Feb 18 04:28:30 2009
@@ -785,7 +785,7 @@
    Result arg1 = generator()->allocator()->Allocate(r1);
    ASSERT(arg1.is_valid());
    generator()->frame()->CallStub(&igostub, &arg0, &arg1, 0);
-  exit()->Jump();
+  exit_.Jump();
  }


@@ -816,7 +816,7 @@
        deferred->enter()->Branch(vs);
        __ tst(r0, Operand(kSmiTagMask));
        deferred->enter()->Branch(ne);
-      deferred->exit()->Bind();
+      deferred->BindExit();
        break;
      }

@@ -832,7 +832,7 @@
        deferred->enter()->Branch(vs);
        __ tst(r0, Operand(kSmiTagMask));
        deferred->enter()->Branch(ne);
-      deferred->exit()->Bind();
+      deferred->BindExit();
        break;
      }

@@ -849,7 +849,7 @@
          case Token::BIT_AND: __ and_(r0, r0, Operand(value)); break;
          default: UNREACHABLE();
        }
-      deferred->exit()->Bind();
+      deferred->BindExit();
        break;
      }

@@ -902,7 +902,7 @@
            default: UNREACHABLE();
          }
          __ mov(r0, Operand(r2, LSL, kSmiTagSize));
-        deferred->exit()->Bind();
+        deferred->BindExit();
        }
        break;
      }
@@ -2345,7 +2345,7 @@
        frame->CallRuntime(Runtime::kCreateObjectLiteralBoilerplate, 3);
    __ mov(r2, Operand(boilerplate.reg()));
    // Result is returned in r2.
-  exit()->Jump();
+  exit_.Jump();
  }


@@ -2372,7 +2372,7 @@
    // If so, jump to the deferred code.
    __ cmp(r2, Operand(Factory::undefined_value()));
    deferred->enter()->Branch(eq);
-  deferred->exit()->Bind();
+  deferred->BindExit();

    // Push the object literal boilerplate.
    frame_->EmitPush(r2);

Modified: branches/experimental/toiger/src/codegen-ia32.cc
==============================================================================
--- branches/experimental/toiger/src/codegen-ia32.cc    (original)
+++ branches/experimental/toiger/src/codegen-ia32.cc    Wed Feb 18 04:28:30  
2009
@@ -738,7 +738,7 @@
    generator()->frame()->Push(&left);
    generator()->frame()->Push(&right);
    Result answer = generator()->frame()->CallStub(&stub_, 2);
-  exit()->Jump(&answer);
+  exit_.Jump(&answer);
  }


@@ -786,7 +786,7 @@
      // Generate the inline part of the code.
      // The operands are on the frame.
      Result answer = deferred->GenerateInlineCode();
-    deferred->exit()->Bind(&answer);
+    deferred->BindExit(&answer);
      frame_->Push(&answer);
    } else {
      // Call the stub and push the result to the stack.
@@ -826,7 +826,7 @@
    generator()->frame()->Push(value_);
    GenericBinaryOpStub igostub(op_, overwrite_mode_, SMI_CODE_INLINED);
    Result answer = generator()->frame()->CallStub(&igostub, 2);
-  exit()->Jump(&answer);
+  exit_.Jump(&answer);
  }


@@ -859,7 +859,7 @@
    generator()->frame()->Push(&right);
    GenericBinaryOpStub igostub(op_, overwrite_mode_, SMI_CODE_INLINED);
    Result answer = generator()->frame()->CallStub(&igostub, 2);
-  exit()->Jump(&answer);
+  exit_.Jump(&answer);
  }


@@ -893,7 +893,7 @@
    generator()->frame()->Push(value_);
    GenericBinaryOpStub igostub(Token::ADD, overwrite_mode_,  
SMI_CODE_INLINED);
    Result answer = generator()->frame()->CallStub(&igostub, 2);
-  exit()->Jump(&answer);
+  exit_.Jump(&answer);
  }


@@ -927,7 +927,7 @@
    generator()->frame()->Push(&right);
    GenericBinaryOpStub igostub(Token::ADD, overwrite_mode_,  
SMI_CODE_INLINED);
    Result answer = generator()->frame()->CallStub(&igostub, 2);
-  exit()->Jump(&answer);
+  exit_.Jump(&answer);
  }


@@ -961,7 +961,7 @@
    generator()->frame()->Push(value_);
    GenericBinaryOpStub igostub(Token::SUB, overwrite_mode_,  
SMI_CODE_INLINED);
    Result answer = generator()->frame()->CallStub(&igostub, 2);
-  exit()->Jump(&answer);
+  exit_.Jump(&answer);
  }


@@ -992,7 +992,7 @@
    generator()->frame()->Push(&right);
    GenericBinaryOpStub igostub(Token::SUB, overwrite_mode_,  
SMI_CODE_INLINED);
    Result answer = generator()->frame()->CallStub(&igostub, 2);
-  exit()->Jump(&answer);
+  exit_.Jump(&answer);
  }


@@ -1032,7 +1032,7 @@
        deferred->enter()->Branch(overflow, &operand, not_taken);
        __ test(Operand(operand.reg()), Immediate(kSmiTagMask));
        deferred->enter()->Branch(not_zero, &operand, not_taken);
-      deferred->exit()->Bind(&operand);
+      deferred->BindExit(&operand);
        frame_->Push(&operand);
        break;
      }
@@ -1067,7 +1067,7 @@
        __ test(answer.reg(), Immediate(kSmiTagMask));
        deferred->enter()->Branch(not_zero, &operand, not_taken);
        operand.Unuse();
-      deferred->exit()->Bind(&answer);
+      deferred->BindExit(&answer);
        frame_->Push(&answer);
        break;
      }
@@ -1092,7 +1092,7 @@
          frame_->Spill(result.reg());
          __ sar(result.reg(), shift_value);
          __ and_(result.reg(), ~kSmiTagMask);
-        deferred->exit()->Bind(&result);
+        deferred->BindExit(&result);
          frame_->Push(&result);
        }
        break;
@@ -1129,7 +1129,7 @@
          ASSERT(kSmiTagSize == times_2);  // Adjust the code if not true.
          __ lea(answer.reg(),
                 Operand(answer.reg(), answer.reg(), times_1, kSmiTag));
-        deferred->exit()->Bind(&answer);
+        deferred->BindExit(&answer);
          frame_->Push(&answer);
        }
        break;
@@ -1167,7 +1167,7 @@
          __ add(answer.reg(), Operand(answer.reg()));
          deferred->enter()->Branch(overflow, &operand, not_taken);
          operand.Unuse();
-        deferred->exit()->Bind(&answer);
+        deferred->BindExit(&answer);
          frame_->Push(&answer);
        }
        break;
@@ -1197,7 +1197,7 @@
          ASSERT(op == Token::BIT_OR);
          __ or_(Operand(operand.reg()), Immediate(value));
        }
-      deferred->exit()->Bind(&operand);
+      deferred->BindExit(&operand);
        frame_->Push(&operand);
        break;
      }
@@ -1470,13 +1470,10 @@

  void DeferredStackCheck::Generate() {
    enter()->Bind();
-  // The stack check can trigger the debugger.  Before calling it, all
-  // values including constants must be spilled to the frame.
-  generator()->frame()->SpillAll();
    StackCheckStub stub;
    Result ignored = generator()->frame()->CallStub(&stub, 0);
    ignored.Unuse();
-  exit()->Jump();
+  exit_.Jump();
  }


@@ -1487,7 +1484,7 @@
          ExternalReference::address_of_stack_guard_limit();
      __ cmp(esp, Operand::StaticVariable(stack_guard_limit));
      deferred->enter()->Branch(below, not_taken);
-    deferred->exit()->Bind();
+    deferred->BindExit();
    }
  }

@@ -3102,7 +3099,7 @@
    frame->Push(node_->flags());
    Result boilerplate =
        frame->CallRuntime(Runtime::kMaterializeRegExpLiteral, 4);
-  exit()->Jump(&boilerplate);
+  exit_.Jump(&boilerplate);
  }


@@ -3136,7 +3133,7 @@

    literals.Unuse();
    // The deferred code returns the boilerplate object.
-  deferred->exit()->Bind(&boilerplate);
+  deferred->BindExit(&boilerplate);

    // Push the boilerplate object.
    frame_->Push(&boilerplate);
@@ -3177,7 +3174,7 @@
    frame->Push(node_->constant_properties());
    Result boilerplate =
        frame->CallRuntime(Runtime::kCreateObjectLiteralBoilerplate, 3);
-  exit()->Jump(&boilerplate);
+  exit_.Jump(&boilerplate);
  }


@@ -3211,7 +3208,7 @@

    literals.Unuse();
    // The deferred code returns the boilerplate object.
-  deferred->exit()->Bind(&boilerplate);
+  deferred->BindExit(&boilerplate);

    // Push the boilerplate object.
    frame_->Push(&boilerplate);
@@ -4285,7 +4282,7 @@

    CounterOpStub stub(result_offset_, is_postfix_, is_increment_);
    value = generator()->frame()->CallStub(&stub, &value, 0);
-  exit()->Jump(&value);
+  exit_.Jump(&value);
  }


@@ -4371,7 +4368,7 @@
      }

      // Store the new value in the target if not const.
-    deferred->exit()->Bind(&value);
+    deferred->BindExit(&value);
      frame_->Push(&value);
      if (!is_const) {
        target.SetValue(NOT_CONST_INIT);
@@ -4822,7 +4819,14 @@
    int delta_to_patch_site = __ SizeOfCodeGeneratedSince(patch_site());
    __ test(value.reg(), Immediate(-delta_to_patch_site));
    __ IncrementCounter(&Counters::keyed_load_inline_miss, 1);
-  exit()->Jump(&value);
+
+  // The receiver and key were spilled by the call, so their state as
+  // constants or copies has been changed.  Thus, they need to be
+  // "mergable" in the block at the exit label and are therefore
+  // passed as return results here.
+  key = cgen->frame()->Pop();
+  receiver = cgen->frame()->Pop();
+  exit_.Jump(&receiver, &key, &value);
  }


@@ -4965,9 +4969,9 @@

          // Restore the receiver and key to the frame and push the
          // result on top of it.
+        deferred->BindExit(&receiver, &key, &value);
          cgen_->frame()->Push(&receiver);
          cgen_->frame()->Push(&key);
-        deferred->exit()->Bind(&value);
          cgen_->frame()->Push(&value);

        } else {

Modified: branches/experimental/toiger/src/codegen.cc
==============================================================================
--- branches/experimental/toiger/src/codegen.cc (original)
+++ branches/experimental/toiger/src/codegen.cc Wed Feb 18 04:28:30 2009
@@ -38,8 +38,8 @@
  namespace v8 { namespace internal {

  DeferredCode::DeferredCode(CodeGenerator* generator)
-  : masm_(generator->masm()),
-    generator_(generator),
+  : generator_(generator),
+    masm_(generator->masm()),
      enter_(generator),
      exit_(generator, JumpTarget::BIDIRECTIONAL),
      statement_position_(masm_->current_statement_position()),

Modified: branches/experimental/toiger/src/codegen.h
==============================================================================
--- branches/experimental/toiger/src/codegen.h  (original)
+++ branches/experimental/toiger/src/codegen.h  Wed Feb 18 04:28:30 2009
@@ -96,7 +96,11 @@
    CodeGenerator* generator() const { return generator_; }

    JumpTarget* enter() { return &enter_; }
-  JumpTarget* exit() { return &exit_; }
+  void BindExit() { exit_.Bind(0); }
+  void BindExit(Result* result) { exit_.Bind(result, 1); }
+  void BindExit(Result* result0, Result* result1, Result* result2) {
+    exit_.Bind(result0, result1, result2, 3);
+  }

    int statement_position() const { return statement_position_; }
    int position() const { return position_; }
@@ -110,15 +114,12 @@
  #endif

   protected:
-  // The masm_ field is manipulated when compiling stubs with the
-  // BEGIN_STUB and END_STUB macros. For that reason, it cannot be
-  // constant.
-  MacroAssembler* masm_;
-
- private:
    CodeGenerator* const generator_;
+  MacroAssembler* const masm_;
    JumpTarget enter_;
    JumpTarget exit_;
+
+ private:
    int statement_position_;
    int position_;
  #ifdef DEBUG

Modified: branches/experimental/toiger/src/jump-target-arm.cc
==============================================================================
--- branches/experimental/toiger/src/jump-target-arm.cc (original)
+++ branches/experimental/toiger/src/jump-target-arm.cc Wed Feb 18 04:28:30  
2009
@@ -130,7 +130,7 @@
  }


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

@@ -139,7 +139,7 @@
    ASSERT(!cgen_->has_valid_frame() || cgen_->HasValidEntryRegisters());

    // Compute the frame to use for entry to the block.
-  ComputeEntryFrame();
+  ComputeEntryFrame(mergable_elements);

    if (is_linked()) {
      // There were forward jumps.  All the reaching frames, beginning

Modified: branches/experimental/toiger/src/jump-target-ia32.cc
==============================================================================
--- branches/experimental/toiger/src/jump-target-ia32.cc        (original)
+++ branches/experimental/toiger/src/jump-target-ia32.cc        Wed Feb 18  
04:28:30 2009
@@ -130,7 +130,7 @@
  }


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

@@ -139,7 +139,7 @@
    ASSERT(!cgen_->has_valid_frame() || cgen_->HasValidEntryRegisters());

    // Compute the frame to use for entry to the block.
-  ComputeEntryFrame();
+  ComputeEntryFrame(mergable_elements);

    if (is_linked()) {
      // There were forward jumps.  All the reaching frames, beginning

Modified: branches/experimental/toiger/src/jump-target.cc
==============================================================================
--- branches/experimental/toiger/src/jump-target.cc     (original)
+++ branches/experimental/toiger/src/jump-target.cc     Wed Feb 18 04:28:30 2009
@@ -139,7 +139,7 @@
  }


-void JumpTarget::ComputeEntryFrame() {
+void JumpTarget::ComputeEntryFrame(int mergable_elements) {
    // Given: a collection of frames reaching by forward CFG edges
    // (including the code generator's current frame) and the
    // directionality of the block.  Compute: an entry frame for the
@@ -159,12 +159,21 @@
    int length = initial_frame->elements_.length();
    List<FrameElement*> elements(length);

+  // Convert the number of mergable elements (counted from the top
+  // down) to a frame high-water mark (counted from the bottom up).
+  // Elements strictly above the high-water index will be mergable in
+  // entry frames for bidirectional jump targets.
+  int high_water_mark = (mergable_elements == kAllElements)
+      ? VirtualFrame::kIllegalIndex  // All frame indices are above this.
+      : length - mergable_elements - 1;  // Top index if m_e == 0.
+
    // Initially populate the list of elements based on the initial
    // frame.
    for (int i = 0; i < length; i++) {
      FrameElement element = initial_frame->elements_[i];
      // We do not allow copies or constants in bidirectional frames.
      if (direction_ == BIDIRECTIONAL &&
+        i > high_water_mark &&
          (element.is_constant() || element.is_copy())) {
        elements.Add(NULL);
      } else {
@@ -440,31 +449,34 @@
  #undef ASSERT_ARGCHECK


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

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


-void JumpTarget::Bind(Result* arg0, Result* arg1) {
+void JumpTarget::Bind(Result* arg0, Result* arg1, int mergable_elements) {
    ASSERT(cgen_ != NULL);

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


-void JumpTarget::Bind(Result* arg0, Result* arg1, Result* arg2) {
+void JumpTarget::Bind(Result* arg0,
+                      Result* arg1,
+                      Result* arg2,
+                      int mergable_elements) {
    ASSERT(cgen_ != NULL);

    if (cgen_->has_valid_frame()) {
@@ -472,14 +484,18 @@
      cgen_->frame()->Push(arg1);
      cgen_->frame()->Push(arg2);
    }
-  Bind();
+  Bind(mergable_elements);
    *arg2 = cgen_->frame()->Pop();
    *arg1 = cgen_->frame()->Pop();
    *arg0 = cgen_->frame()->Pop();
  }


-void JumpTarget::Bind(Result* arg0, Result* arg1, Result* arg2, Result*  
arg3) {
+void JumpTarget::Bind(Result* arg0,
+                      Result* arg1,
+                      Result* arg2,
+                      Result* arg3,
+                      int mergable_elements) {
    ASSERT(cgen_ != NULL);

    if (cgen_->has_valid_frame()) {
@@ -488,7 +504,7 @@
      cgen_->frame()->Push(arg2);
      cgen_->frame()->Push(arg3);
    }
-  Bind();
+  Bind(mergable_elements);
    *arg3 = cgen_->frame()->Pop();
    *arg2 = cgen_->frame()->Pop();
    *arg1 = cgen_->frame()->Pop();

Modified: branches/experimental/toiger/src/jump-target.h
==============================================================================
--- branches/experimental/toiger/src/jump-target.h      (original)
+++ branches/experimental/toiger/src/jump-target.h      Wed Feb 18 04:28:30 2009
@@ -131,13 +131,29 @@

    // Bind a jump target.  If there is no current frame at the binding
    // site, there must be at least one frame reaching via a forward
-  // jump.  This frame will be used to establish an expected frame for
-  // the block, which will be the current frame after the bind.
-  void Bind();
-  void Bind(Result* arg);
-  void Bind(Result* arg0, Result* arg1);
-  void Bind(Result* arg0, Result* arg1, Result* arg2);
-  void Bind(Result* arg0, Result* arg1, Result* arg2, Result* arg3);
+  // jump.
+  //
+  // The number of mergable elements is a number of frame elements
+  // counting from the top down which must be "mergable" (not
+  // constants or copies) in the entry frame at the jump target.
+  // Backward jumps to the target must contain the same constants and
+  // sharing as the entry frame, except for the mergable elements.
+  //
+  // A mergable elements argument of kAllElements indicates that all
+  // frame elements must be mergable.  Mergable elements are ignored
+  // completely for forward-only jump targets.
+  void Bind(int mergable_elements = kAllElements);
+  void Bind(Result* arg, int mergable_elements = kAllElements);
+  void Bind(Result* arg0, Result* arg1, int mergable_elements =  
kAllElements);
+  void Bind(Result* arg0,
+            Result* arg1,
+            Result* arg2,
+            int mergable_elements = kAllElements);
+  void Bind(Result* arg0,
+            Result* arg1,
+            Result* arg2,
+            Result* arg3,
+            int mergable_elements = kAllElements);

    // Emit a call to a jump target.  There must be a current frame at
    // the call.  The frame at the target is the same as the current
@@ -145,6 +161,8 @@
    // after the call is the same as the frame before the call.
    void Call();

+  static const int kAllElements = -1;  // Not a valid number of elements.
+
   protected:
    // The code generator gives access to its current frame.
    CodeGenerator* cgen_;
@@ -184,8 +202,9 @@
    // expected frame.  Return null if they are incompatible.
    FrameElement* Combine(FrameElement* left, FrameElement* right);

-  // Compute a frame to use for entry to this block.
-  void ComputeEntryFrame();
+  // Compute a frame to use for entry to this block.  Mergable
+  // elements is as described for the Bind function.
+  void ComputeEntryFrame(int mergable_elements);

    DISALLOW_COPY_AND_ASSIGN(JumpTarget);
  };

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

Reply via email to