Author: [email protected]
Date: Wed Feb 25 06:09:48 2009
New Revision: 1361

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

Log:
Experimental: fix a bug in our handling of the short-circuit boolean
operators && and ||.

Correctly detect that the left subexpression of && is unconditionally
false and set the state of the inherited control destination; and if
it is not unconditionally false ensure that the right subexpression is
compiled.

Analogously for ||.

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

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 25 06:09:48  
2009
@@ -4621,18 +4621,35 @@
      LoadCondition(node->left(), NOT_INSIDE_TYPEOF, &dest, false);

      if (dest.false_was_fall_through()) {
-      // We have just bound the false target.  There may be dangling
-      // jumps to is_true.
+      // The current false target was used as the fall-through.  If
+      // there are no dangling jumps to is_true then the left
+      // subexpression was unconditionally false.  Otherwise we have
+      // paths where we do have to evaluate the right subexpression.
        if (is_true.is_linked()) {
-        destination()->false_target()->Unuse();
-        destination()->false_target()->Jump();
+        // We need to compile the right subexpression.  If the jump to
+        // the current false target was a forward jump then we have a
+        // valid frame, we have just bound the false target, and we
+        // have to jump around the code for the right subexpression.
+        if (has_valid_frame()) {
+          destination()->false_target()->Unuse();
+          destination()->false_target()->Jump();
+        }
          is_true.Bind();
-        destination()->Goto(true);
+        // The left subexpression compiled to control flow, so the
+        // right one is free to do so as well.
+        LoadCondition(node->right(), NOT_INSIDE_TYPEOF, destination(),  
false);
+      } else {
+        // We have actually just jumped to or bound the current false
+        // target but the current control destination is not marked as
+        // used.
+        destination()->Use(false);
        }
+
      } else if (dest.is_used()) {
-      // The first subexpression compiled to control flow (is_true was
-      // just bound), so the second is free to do so as well.
+      // The left subexpression compiled to control flow (and is_true
+      // was just bound), so the right is free to do so as well.
        LoadCondition(node->right(), NOT_INSIDE_TYPEOF, destination(),  
false);
+
      } else {
        // We have a materialized value on the frame, so we exit with
        // one on all paths.  There are possibly also jumps to is_true
@@ -4653,7 +4670,7 @@
        // Pop the result of evaluating the first part.
        frame_->Drop();

-      // Evaluate right side expression.
+      // Compile right side expression.
        is_true.Bind();
        Load(node->right());

@@ -4667,18 +4684,34 @@
      LoadCondition(node->left(), NOT_INSIDE_TYPEOF, &dest, false);

      if (dest.true_was_fall_through()) {
-      // We have just bound the true target.  There may be dangling
-      // jumps to is_false.
+      // The current true target was used as the fall-through.  If
+      // there are no dangling jumps to is_false then the left
+      // subexpression was unconditionally true.  Otherwise we have
+      // paths where we do have to evaluate the right subexpression.
        if (is_false.is_linked()) {
-        destination()->true_target()->Unuse();
-        destination()->true_target()->Jump();
+        // We need to compile the right subexpression.  If the jump to
+        // the current true target was a forward jump then we have a
+        // valid frame, we have just bound the true target, and we
+        // have to jump around the code for the right subexpression.
+        if (has_valid_frame()) {
+          destination()->true_target()->Unuse();
+          destination()->true_target()->Jump();
+        }
          is_false.Bind();
-        destination()->Goto(false);
+        // The left subexpression compiled to control flow, so the
+        // right one is free to do so as well.
+        LoadCondition(node->right(), NOT_INSIDE_TYPEOF, destination(),  
false);
+      } else {
+        // We have just jumped to or bound the current true target but
+        // the current control destination is not marked as used.
+        destination()->Use(true);
        }
+
      } else if (dest.is_used()) {
-      // The first subexpression compiled to control flow (is_false
-      // was just bound), so the second is free to do so as well.
+      // The left subexpression compiled to control flow (and is_false
+      // was just bound), so the right is free to do so as well.
        LoadCondition(node->right(), NOT_INSIDE_TYPEOF, destination(),  
false);
+
      } else {
        // We have a materialized value on the frame, so we exit with
        // one on all paths.  There are possibly also jumps to is_false
@@ -4699,7 +4732,7 @@
        // Pop the result of evaluating the first part.
        frame_->Drop();

-      // Evaluate right side expression.
+      // Compile right side expression.
        is_false.Bind();
        Load(node->right());


Modified: branches/experimental/toiger/src/codegen-ia32.h
==============================================================================
--- branches/experimental/toiger/src/codegen-ia32.h     (original)
+++ branches/experimental/toiger/src/codegen-ia32.h     Wed Feb 25 06:09:48 2009
@@ -191,6 +191,18 @@
      true_is_fall_through_ = where;
    }

+  // Mark this jump target as used as if Goto had been called, but
+  // without generating a jump or binding a label (the control effect
+  // should have already happened).  This is used when the left
+  // subexpression of the short-circuit boolean operators are
+  // compiled.
+  void Use(bool where) {
+    ASSERT(!is_used_);
+    ASSERT((where ? true_target_ : false_target_)->is_bound());
+    is_used_ = true;
+    true_is_fall_through_ = where;
+  }
+
    // Swap the true and false targets but keep the same actual label as
    // the fall through.  This is used when compiling negated
    // expressions, where we want to swap the targets but preserve the

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

Reply via email to