Author: [email protected]
Date: Tue Jan  6 02:46:16 2009
New Revision: 1026

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

Log:
Experimental: begin using the register allocator for do and while
loops, as well as continue and break statements.

This required fixing branches to blocks that have an expected frame.
The expected frame needs to be split (cloned), with one copy being
merged to the expected frame and the other flowing to the fall
through.

It also requires reestablishing a spilled frame when a break or
continue jumps into spilled code.
Review URL: http://codereview.chromium.org/17044

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 02:46:16  
2009
@@ -1601,7 +1601,6 @@

  void CodeGenerator::VisitContinueStatement(ContinueStatement* node) {
    ASSERT(!in_spilled_code());
-  VirtualFrame::SpilledScope spilled_scope(this);
    Comment cmnt(masm_, "[ ContinueStatement");
    CodeForStatement(node);
    CleanStack(break_stack_height_ - node->target()->break_stack_height());
@@ -1611,7 +1610,6 @@

  void CodeGenerator::VisitBreakStatement(BreakStatement* node) {
    ASSERT(!in_spilled_code());
-  VirtualFrame::SpilledScope spilled_scope(this);
    Comment cmnt(masm_, "[ BreakStatement");
    CodeForStatement(node);
    CleanStack(break_stack_height_ - node->target()->break_stack_height());
@@ -1893,11 +1891,12 @@

    switch (node->type()) {
      case LoopStatement::DO_LOOP: {
-      // The new code generator does not yet compile do loops.
-      VirtualFrame::SpilledScope spilled_scope(this);
        JumpTarget body(this);
        IncrementLoopNesting();
-      // Label the body.
+
+      // Label the top of the loop for the backward CFG edge.  If the test
+      // is always true we can use the continue target, and if the test is
+      // always false there is no need.
        if (info == ALWAYS_TRUE) {
          node->continue_target()->Bind();
        } else if (info == ALWAYS_FALSE) {
@@ -1906,19 +1905,19 @@
          ASSERT(info == DONT_KNOW);
          body.Bind();
        }
+
        CheckStack();  // TODO(1222600): ignore if body contains calls.
-      VisitAndSpill(node->body());
+      Visit(node->body());

-      // Compile the "test".
+      // Compile the test.
        if (info == ALWAYS_TRUE) {
+        // If control flow can fall off the end of the body, jump back to
+        // the top.
          if (has_valid_frame()) {
-          // If control flow can fall off the end of the body, jump back to
-          // the top.
            node->continue_target()->Jump();
          }
        } else if (info == ALWAYS_FALSE) {
-        // If we have a continue in the body, we only have to bind its jump
-        // target.
+        // If we had a continue in the body we have to bind its jump  
target.
          if (node->continue_target()->is_linked()) {
            node->continue_target()->Bind();
          }
@@ -1926,10 +1925,12 @@
          ASSERT(info == DONT_KNOW);
          // We have to compile the test expression if it can be reached by
          // control flow falling out of the body or via continue.
-        if (has_valid_frame() || node->continue_target()->is_linked()) {
+        if (node->continue_target()->is_linked()) {
            node->continue_target()->Bind();
-          LoadConditionAndSpill(node->cond(), NOT_INSIDE_TYPEOF,
-                                &body, node->break_target(), true);
+        }
+        if (has_valid_frame()) {
+          LoadCondition(node->cond(), NOT_INSIDE_TYPEOF,
+                        &body, node->break_target(), true);
            // An invalid frame here indicates that control flow did not fall
            // out of the test expression.
            if (has_valid_frame()) {
@@ -1941,36 +1942,36 @@
      }

      case LoopStatement::WHILE_LOOP: {
-      // The new code generator does not yet compile while loops.
-      VirtualFrame::SpilledScope spilled_scope(this);
-      JumpTarget body(this);
        IncrementLoopNesting();
-      // Generate the loop header.
-      if (info == ALWAYS_TRUE) {
-        // Merely label the body with the continue target.
-        node->continue_target()->Bind();
-      } else if (info == ALWAYS_FALSE) {
-        // There is no need to even compile the test or body.
-        break;
-      } else {
-        // Compile the test labeled with the continue target and label the
-        // body with the body target.
-        ASSERT(info == DONT_KNOW);
-        node->continue_target()->Bind();
-        LoadConditionAndSpill(node->cond(), NOT_INSIDE_TYPEOF,
-                              &body, node->break_target(), true);
+
+      // If the test is never true and has no side effects there is no need
+      // to compile the test or body.
+      if (info == ALWAYS_FALSE) break;
+
+      // Label the top of the loop with the continue target for the  
backward
+      // CFG edge.
+      node->continue_target()->Bind();
+
+      // If the test is always true and has no side effects there is no  
need
+      // to compile it.  We only compile the test when we do not know its
+      // outcome or it may have side effects.
+      if (info == DONT_KNOW) {
+        JumpTarget body(this);
+        LoadCondition(node->cond(), NOT_INSIDE_TYPEOF,
+                      &body, node->break_target(), true);
          // An invalid frame indicates that control did not fall out of the
          // test expression.
          if (has_valid_frame()) {
            Branch(false, node->break_target());
          }
-        if (has_valid_frame() || body.is_linked()) {
+        if (body.is_linked()) {
            body.Bind();
          }
        }
+
        if (has_valid_frame()) {
          CheckStack();  // TODO(1222600): ignore if body contains calls.
-        VisitAndSpill(node->body());
+        Visit(node->body());

          // If control flow can fall out of the body, jump back to the top.
          if (has_valid_frame()) {
@@ -1982,32 +1983,34 @@

      case LoopStatement::FOR_LOOP: {
        JumpTarget loop(this);
-      JumpTarget body(this);
        if (node->init() != NULL) {
          Visit(node->init());
        }

        IncrementLoopNesting();
-      // There is no need to compile the test or body.
+      // If the test is never true and has no side effects there is no need
+      // to compile the test or body.
        if (info == ALWAYS_FALSE) break;

        // Label the top of the loop for the backward CFG edge.  If there is
-      // no update expression label it with the continue target, otherwise
-      // with the loop target.
+      // no update expression we can use the continue target.
        if (node->next() == NULL) {
          node->continue_target()->Bind();
        } else {
          loop.Bind();
        }

-      // If the test is always true, there is no need to compile it.
+      // If the test is always true and has no side effects there is no  
need
+      // to compile it.  We only compile the test when we do not know its
+      // outcome or it has side effects.
        if (info == DONT_KNOW) {
+        JumpTarget body(this);
          LoadCondition(node->cond(), NOT_INSIDE_TYPEOF,
                        &body, node->break_target(), true);
          if (has_valid_frame()) {
            Branch(false, node->break_target());
          }
-        if (has_valid_frame() || body.is_linked()) {
+        if (body.is_linked()) {
            body.Bind();
          }
        }
@@ -2026,8 +2029,10 @@
            // If there is an update statement and control flow can reach it
            // via falling out of the body of the loop or continuing, we
            // compile the update statement.
-          if (has_valid_frame() || node->continue_target()->is_linked()) {
+          if (node->continue_target()->is_linked()) {
              node->continue_target()->Bind();
+          }
+          if (has_valid_frame()) {
              // Record source position of the statement as this code which  
is
              // after the code for the body actually belongs to the loop
              // statement and not the body.
@@ -2332,7 +2337,11 @@
    for (int i = 0; i <= nof_escapes; i++) {
      if (shadows[i]->is_linked()) {
        // Unlink from try chain; be careful not to destroy the TOS.
+      //
+      // 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 we
        // break from (eg, for...in) may have left stuff on the stack.
@@ -2427,7 +2436,10 @@
    // have been jumped to.
    for (int i = 0; i <= nof_escapes; i++) {
      if (shadows[i]->is_linked()) {
+      // 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();
        if (shadows[i]->original_target() == &function_return_) {
          // If this target shadowed the function return, materialize the
          // return value on the stack.

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        Tue Jan  6  
02:46:16 2009
@@ -137,11 +137,27 @@
    } else {
      // No code needs to be emitted to merge to the expected frame at the
      // actual function return.
-    if (!cgen_->IsActualFunctionReturn(this)) {
-      current_frame->MergeTo(expected_frame_);
-    }
-    ASSERT(cgen_->HasValidEntryRegisters());
+    if (cgen_->IsActualFunctionReturn(this)) {
+      ASSERT(cgen_->HasValidEntryRegisters());
        __ j(cc, &label_, hint);
+    } else {
+      // We negate the condition and emit the code to merge to the expected
+      // frame immediately.
+      //
+      // TODO(): This should be replaced with a solution that emits the
+      // merge code for forward CFG edges at the appropriate entry to the
+      // target block.
+      Label original_fall_through;
+      __ j(NegateCondition(cc), &original_fall_through, NegateHint(hint));
+      VirtualFrame* working_frame = new VirtualFrame(current_frame);
+      cgen_->SetFrame(working_frame);
+      working_frame->MergeTo(expected_frame_);
+      ASSERT(cgen_->HasValidEntryRegisters());
+      __ jmp(&label_);
+      cgen_->SetFrame(current_frame);
+      delete working_frame;
+      __ bind(&original_fall_through);
+    }
    }
    // Postcondition: there is both a current frame and an expected frame at
    // the label and they match.

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

Reply via email to