Author: [email protected]
Date: Tue Feb 24 04:28:43 2009
New Revision: 1346

Modified:
    branches/experimental/toiger/src/codegen-arm.cc
    branches/experimental/toiger/src/codegen-ia32.cc
    branches/experimental/toiger/src/codegen.cc
    branches/experimental/toiger/test/mjsunit/compare-constants.js

Log:
Experimental: fix two issues with ARM fast (jump table) switches.
(1) do not emit the jump table twice, (2) do bind the break target.

Review URL: http://codereview.chromium.org/28066

Modified: branches/experimental/toiger/src/codegen-arm.cc
==============================================================================
--- branches/experimental/toiger/src/codegen-arm.cc     (original)
+++ branches/experimental/toiger/src/codegen-arm.cc     Tue Feb 24 04:28:43 2009
@@ -1448,18 +1448,25 @@
      Vector<Label*> case_targets,
      Vector<Label> case_labels) {
    VirtualFrame::SpilledScope spilled_scope(this);
-  ASSERT(kSmiTag == 0 && kSmiTagSize <= 2);
+  JumpTarget setup_default(this);
+  JumpTarget is_smi(this);

+  // A non-null default label pointer indicates a default case among
+  // the case labels.  Otherwise we use the break target as a
+  // "default" for failure to hit the jump table.
+  JumpTarget* default_target =
+      (default_label == NULL) ? node->break_target() : &setup_default;
+
+  ASSERT(kSmiTag == 0 && kSmiTagSize <= 2);
    frame_->EmitPop(r0);

    // Test for a Smi value in a HeapNumber.
-  JumpTarget is_smi(this);
    __ tst(r0, Operand(kSmiTagMask));
    is_smi.Branch(eq);
    __ ldr(r1, MemOperand(r0, HeapObject::kMapOffset - kHeapObjectTag));
    __ ldrb(r1, MemOperand(r1, Map::kInstanceTypeOffset - kHeapObjectTag));
    __ cmp(r1, Operand(HEAP_NUMBER_TYPE));
-  __ b(ne, default_label);
+  default_target->Branch(ne);
    frame_->EmitPush(r0);
    frame_->CallRuntime(Runtime::kNumberToSmi, 1);
    is_smi.Bind();
@@ -1479,17 +1486,30 @@
      }
    }
    __ tst(r0, Operand(0x80000000 | kSmiTagMask));
-  __ b(ne, default_label);
+  default_target->Branch(ne);
    __ cmp(r0, Operand(Smi::FromInt(range)));
-  __ b(ge, default_label);
+  default_target->Branch(ge);
+  VirtualFrame* start_frame = new VirtualFrame(frame_);
    __ SmiJumpTable(r0, case_targets);

-  VirtualFrame* start_frame = new VirtualFrame(frame_);
-  // Table containing branch operations.
-  for (int i = 0; i < range; i++) {
-    __ jmp(case_targets[i]);
-  }
    GenerateFastCaseSwitchCases(node, case_labels, start_frame);
+
+  // If there was a default case among the case labels, we need to
+  // emit code to jump to it from the default target used for failure
+  // to hit the jump table.
+  if (default_label != NULL) {
+    if (has_valid_frame()) {
+      node->break_target()->Jump();
+    }
+    setup_default.Bind();
+    frame_->MergeTo(start_frame);
+    __ b(default_label);
+    DeleteFrame();
+  }
+  if (node->break_target()->is_linked()) {
+    node->break_target()->Bind();
+  }
+
    delete start_frame;
  }

@@ -1513,7 +1533,7 @@
    JumpTarget next_test(this);
    JumpTarget fall_through(this);
    JumpTarget default_entry(this);
-  JumpTarget default_exit(this);
+  JumpTarget default_exit(this, JumpTarget::BIDIRECTIONAL);
    ZoneList<CaseClause*>* cases = node->cases();
    int length = cases->length();
    CaseClause* default_clause = NULL;

Modified: branches/experimental/toiger/src/codegen-ia32.cc
==============================================================================
--- branches/experimental/toiger/src/codegen-ia32.cc    (original)
+++ branches/experimental/toiger/src/codegen-ia32.cc    Tue Feb 24 04:28:43  
2009
@@ -2000,13 +2000,17 @@

    // If there was a default case, we need to emit the code to match it.
    if (default_label != NULL) {
-    node->break_target()->Jump();
+    if (has_valid_frame()) {
+      node->break_target()->Jump();
+    }
      setup_default.Bind();
      frame_->MergeTo(start_frame);
      __ jmp(default_label);
      DeleteFrame();
    }
-  node->break_target()->Bind();
+  if (node->break_target()->is_linked()) {
+    node->break_target()->Bind();
+  }

    for (int i = 0, entry_pos = table_start.pos();
         i < range;

Modified: branches/experimental/toiger/src/codegen.cc
==============================================================================
--- branches/experimental/toiger/src/codegen.cc (original)
+++ branches/experimental/toiger/src/codegen.cc Tue Feb 24 04:28:43 2009
@@ -453,19 +453,19 @@

    for (int i = 0; i < length; i++) {
      Comment cmnt(masm(), "[ Case clause");
-    masm()->bind(&case_labels[i]);
-    VisitStatements(cases->at(i)->statements());

-    // If control flow did not fall off the end of the case statement,
-    // we restore the expected frame for the next iteration (or exit
-    // of the loop).  Otherwise we have to generate merge code to
-    // expectation at the next case.
+    // We may not have a virtual frame if control flow did not fall
+    // off the end of the previous case.  In that case, use the start
+    // frame.  Otherwise, we have to merge the existing one to the
+    // start frame as part of the previous case.
      if (!has_valid_frame()) {
        RegisterFile non_frame_registers = RegisterAllocator::Reserved();
        SetFrame(new VirtualFrame(start_frame), &non_frame_registers);
      } else {
        frame_->MergeTo(start_frame);
      }
+    masm()->bind(&case_labels[i]);
+    VisitStatements(cases->at(i)->statements());
    }
  }


Modified: branches/experimental/toiger/test/mjsunit/compare-constants.js
==============================================================================
--- branches/experimental/toiger/test/mjsunit/compare-constants.js       
(original)
+++ branches/experimental/toiger/test/mjsunit/compare-constants.js      Tue Feb 
 
24 04:28:43 2009
@@ -25,13 +25,12 @@
  // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

-// Test comparison operations that involve one or two constant Smis.
+// Test comparison operations that involve one or two constant smis.

-
-function foo() {
+function test() {
    var i = 5;
    var j = 3;
-
+
    assertTrue( j < i );
    i = 5; j = 3;
    assertTrue( j <= i );
@@ -61,8 +60,7 @@
      ++i;
    }
    j = 21;
-
-
+
    assertTrue( j < i );
    j = 21;
    assertTrue( j <= i );
@@ -116,8 +114,8 @@
        assertUnreachable();
        break;
    }
-  assertEquals(17, j, "switch with constant value");
+  assertEquals(17, j, "switch with constant value");
  }

-foo();
+test();


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

Reply via email to