| Index: src/codegen-ia32.cc
 | 
| ===================================================================
 | 
| --- src/codegen-ia32.cc	(revision 1450)
 | 
| +++ src/codegen-ia32.cc	(working copy)
 | 
| @@ -2174,15 +2174,16 @@
 | 
|        JumpTarget body(this, JumpTarget::BIDIRECTIONAL);
 | 
|        IncrementLoopNesting();
 | 
|  
 | 
| -      // 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.
 | 
| +      // Label the top of the loop for the backward jump if necessary.
 | 
|        if (info == ALWAYS_TRUE) {
 | 
| +        // Use the continue target.
 | 
|          node->continue_target()->Initialize(this, JumpTarget::BIDIRECTIONAL);
 | 
|          node->continue_target()->Bind();
 | 
|        } else if (info == ALWAYS_FALSE) {
 | 
| +        // No need to label it.
 | 
|          node->continue_target()->Initialize(this);
 | 
|        } else {
 | 
| +        // Continue is the test, so use the backward body target.
 | 
|          ASSERT(info == DONT_KNOW);
 | 
|          node->continue_target()->Initialize(this);
 | 
|          body.Bind();
 | 
| @@ -2193,8 +2194,8 @@
 | 
|  
 | 
|        // Compile the test.
 | 
|        if (info == ALWAYS_TRUE) {
 | 
| -        // If control flow can fall off the end of the body, jump back to
 | 
| -        // the top and bind the break target as the exit.
 | 
| +        // If control flow can fall off the end of the body, jump back
 | 
| +        // to the top and bind the break target at the exit.
 | 
|          if (has_valid_frame()) {
 | 
|            node->continue_target()->Jump();
 | 
|          }
 | 
| @@ -2230,15 +2231,19 @@
 | 
|      }
 | 
|  
 | 
|      case LoopStatement::WHILE_LOOP: {
 | 
| -      JumpTarget body(this, JumpTarget::BIDIRECTIONAL);
 | 
| +      // TODO(260): This flag controls whether to duplicate the test
 | 
| +      // at the bottom of the loop.  Replace it with a better
 | 
| +      // indication of when it is safe to do so.
 | 
| +      static const bool test_at_bottom = false;
 | 
| +
 | 
| +      JumpTarget body;  // Uninitialized.
 | 
|        IncrementLoopNesting();
 | 
|  
 | 
|        // If the condition is always false and has no side effects, we
 | 
|        // do not need to compile anything.
 | 
|        if (info == ALWAYS_FALSE) break;
 | 
|  
 | 
| -      // Based on the condition analysis, compile the test if
 | 
| -      // necessary and label the body if necessary.
 | 
| +      // Based on the condition analysis, compile the test as necessary.
 | 
|        if (info == ALWAYS_TRUE) {
 | 
|          // We will not compile the test expression.  Label the top of
 | 
|          // the loop with the continue target.
 | 
| @@ -2246,7 +2251,18 @@
 | 
|          node->continue_target()->Bind();
 | 
|        } else {
 | 
|          ASSERT(info == DONT_KNOW);  // ALWAYS_FALSE cannot reach here.
 | 
| -        node->continue_target()->Initialize(this);
 | 
| +        if (test_at_bottom) {
 | 
| +          // Continue is the test at the bottom, no need to label the
 | 
| +          // test at the top.  The body is a backward target.
 | 
| +          node->continue_target()->Initialize(this);
 | 
| +          body.Initialize(this, JumpTarget::BIDIRECTIONAL);
 | 
| +        } else {
 | 
| +          // Label the test at the top as the continue target.  The
 | 
| +          // body is a forward-only target.
 | 
| +          node->continue_target()->Initialize(this, JumpTarget::BIDIRECTIONAL);
 | 
| +          node->continue_target()->Bind();
 | 
| +          body.Initialize(this);
 | 
| +        }
 | 
|          // Compile the test with the body as the true target and
 | 
|          // preferred fall-through and with the break target as the
 | 
|          // false target.
 | 
| @@ -2254,9 +2270,9 @@
 | 
|          LoadCondition(node->cond(), NOT_INSIDE_TYPEOF, &dest, true);
 | 
|  
 | 
|          if (dest.false_was_fall_through()) {
 | 
| -          // If we don't have dangling jumps to the body, the test is
 | 
| -          // unconditionally false and we do not need to compile the
 | 
| -          // body.
 | 
| +          // If we got the break target as fall-through, the test may
 | 
| +          // have been unconditionally false (if there are no jumps to
 | 
| +          // the body).
 | 
|            if (!body.is_linked()) break;
 | 
|  
 | 
|            // Otherwise, jump around the body on the fall through and
 | 
| @@ -2267,31 +2283,37 @@
 | 
|          }
 | 
|        }
 | 
|  
 | 
| -      // The (stack check at the start of the) body was labeled.
 | 
| -      // Compile it.
 | 
|        CheckStack();  // TODO(1222600): ignore if body contains calls.
 | 
|        Visit(node->body());
 | 
|  
 | 
| -      // Compile the test if necessary and jump back.
 | 
| +      // Based on the condition analysis, compile the backward jump as
 | 
| +      // necessary.
 | 
|        if (info == ALWAYS_TRUE) {
 | 
| -        // The body has been labeled with the continue target.
 | 
| +        // The loop body has been labeled with the continue target.
 | 
|          if (has_valid_frame()) {
 | 
|            node->continue_target()->Jump();
 | 
|          }
 | 
|        } else {
 | 
|          ASSERT(info == DONT_KNOW);  // ALWAYS_FALSE cannot reach here.
 | 
| -        if (node->continue_target()->is_linked()) {
 | 
| -          node->continue_target()->Bind();
 | 
| +        if (test_at_bottom) {
 | 
| +          // If we have chosen to recompile the test at the bottom,
 | 
| +          // then it is the continue target.
 | 
| +          if (node->continue_target()->is_linked()) {
 | 
| +            node->continue_target()->Bind();
 | 
| +          }
 | 
| +          if (has_valid_frame()) {
 | 
| +            // The break target is the fall-through (body is a backward
 | 
| +            // jump from here and thus an invalid fall-through).
 | 
| +            ControlDestination dest(&body, node->break_target(), false);
 | 
| +            LoadCondition(node->cond(), NOT_INSIDE_TYPEOF, &dest, true);
 | 
| +          }
 | 
| +        } else {
 | 
| +          // If we have chosen not to recompile the test at the
 | 
| +          // bottom, jump back to the one at the top.
 | 
| +          if (has_valid_frame()) {
 | 
| +            node->continue_target()->Jump();
 | 
| +          }
 | 
|          }
 | 
| -
 | 
| -        // If control can reach the bottom by falling off the body or
 | 
| -        // a continue in the body, (re)compile the test at the bottom.
 | 
| -        if (has_valid_frame()) {
 | 
| -          // The break target is the fall-through (body is a backward
 | 
| -          // jump from here).
 | 
| -          ControlDestination dest(&body, node->break_target(), false);
 | 
| -          LoadCondition(node->cond(), NOT_INSIDE_TYPEOF, &dest, true);
 | 
| -        }
 | 
|        }
 | 
|  
 | 
|        // The break target may be already bound (by the condition), or
 | 
| @@ -2303,8 +2325,14 @@
 | 
|      }
 | 
|  
 | 
|      case LoopStatement::FOR_LOOP: {
 | 
| -      JumpTarget body(this, JumpTarget::BIDIRECTIONAL);
 | 
| +      // TODO(260): This flag controls whether to duplicate the test
 | 
| +      // at the bottom of the loop.  Replace it with a better
 | 
| +      // indication of when it is safe to do so.
 | 
| +      static const bool test_at_bottom = false;
 | 
|  
 | 
| +      JumpTarget loop(this, JumpTarget::BIDIRECTIONAL);
 | 
| +      JumpTarget body(this);
 | 
| +
 | 
|        // Compile the init expression if present.
 | 
|        if (node->init() != NULL) {
 | 
|          Visit(node->init());
 | 
| @@ -2316,22 +2344,37 @@
 | 
|        // do not need to compile anything else.
 | 
|        if (info == ALWAYS_FALSE) break;
 | 
|  
 | 
| -      // Based on the condition analysis, compile the test if
 | 
| -      // necessary and label the body if necessary.
 | 
| +      // Based on the condition analysis, compile the test as necessary.
 | 
|        if (info == ALWAYS_TRUE) {
 | 
|          // We will not compile the test expression.  Label the top of
 | 
| -        // the loop with the continue target if there is no update
 | 
| -        // expression, otherwise with the body target.
 | 
| +        // the loop.
 | 
|          if (node->next() == NULL) {
 | 
| +          // Use the continue target if there is no update expression.
 | 
|            node->continue_target()->Initialize(this, JumpTarget::BIDIRECTIONAL);
 | 
|            node->continue_target()->Bind();
 | 
|          } else {
 | 
| +          // Otherwise use the backward loop target.
 | 
|            node->continue_target()->Initialize(this);
 | 
| -          body.Bind();
 | 
| +          loop.Bind();
 | 
|          }
 | 
|        } else {
 | 
|          ASSERT(info == DONT_KNOW);
 | 
| -        node->continue_target()->Initialize(this);
 | 
| +        if (test_at_bottom) {
 | 
| +          // Continue is either the update expression or the test at
 | 
| +          // the bottom, no need to label the test at the top.
 | 
| +          node->continue_target()->Initialize(this);
 | 
| +        } else if (node->next() == NULL) {
 | 
| +          // We are not recompiling the test at the bottom and there
 | 
| +          // is no update expression.
 | 
| +          node->continue_target()->Initialize(this, JumpTarget::BIDIRECTIONAL);
 | 
| +          node->continue_target()->Bind();
 | 
| +        } else {
 | 
| +          // We are not recompiling the test at the bottom and there
 | 
| +          // is an update expression.
 | 
| +          node->continue_target()->Initialize(this);
 | 
| +          loop.Bind();
 | 
| +        }
 | 
| +
 | 
|          // Compile the test with the body as the true target and
 | 
|          // preferred fall-through and with the break target as the
 | 
|          // false target.
 | 
| @@ -2339,9 +2382,9 @@
 | 
|          LoadCondition(node->cond(), NOT_INSIDE_TYPEOF, &dest, true);
 | 
|  
 | 
|          if (dest.false_was_fall_through()) {
 | 
| -          // If we don't have dangling jumps to the body, the test is
 | 
| -          // unconditionally false and we do not need to compile the
 | 
| -          // body.
 | 
| +          // If we got the break target as fall-through, the test may
 | 
| +          // have been unconditionally false (if there are no jumps to
 | 
| +          // the body).
 | 
|            if (!body.is_linked()) break;
 | 
|  
 | 
|            // Otherwise, jump around the body on the fall through and
 | 
| @@ -2352,20 +2395,17 @@
 | 
|          }
 | 
|        }
 | 
|  
 | 
| -      // The (stack check at the start of the) body was labeled.
 | 
| -      // Compile it.
 | 
|        CheckStack();  // TODO(1222600): ignore if body contains calls.
 | 
|        Visit(node->body());
 | 
|  
 | 
|        // If there is an update expression, compile it if necessary.
 | 
|        if (node->next() != NULL) {
 | 
| -        // We did not use the continue target for the body.
 | 
|          if (node->continue_target()->is_linked()) {
 | 
|            node->continue_target()->Bind();
 | 
|          }
 | 
|  
 | 
|          // Control can reach the update by falling out of the body or
 | 
| -        // by a continue in the body.
 | 
| +        // by a continue.
 | 
|          if (has_valid_frame()) {
 | 
|            // Record the source position of the statement as this code
 | 
|            // which is after the code for the body actually belongs to
 | 
| @@ -2375,32 +2415,43 @@
 | 
|          }
 | 
|        }
 | 
|  
 | 
| -      // Compile the test if necessary and jump back.
 | 
| +      // Based on the condition analysis, compile the backward jump as
 | 
| +      // necessary.
 | 
|        if (info == ALWAYS_TRUE) {
 | 
|          if (has_valid_frame()) {
 | 
|            if (node->next() == NULL) {
 | 
|              node->continue_target()->Jump();
 | 
|            } else {
 | 
| -            body.Jump();
 | 
| +            loop.Jump();
 | 
|            }
 | 
|          }
 | 
|        } else {
 | 
|          ASSERT(info == DONT_KNOW);  // ALWAYS_FALSE cannot reach here.
 | 
| -        if (node->continue_target()->is_linked()) {
 | 
| -          // We can have dangling jumps to the continue target if
 | 
| -          // there was no update expression.
 | 
| -          node->continue_target()->Bind();
 | 
| +        if (test_at_bottom) {
 | 
| +          if (node->continue_target()->is_linked()) {
 | 
| +            // We can have dangling jumps to the continue target if
 | 
| +            // there was no update expression.
 | 
| +            node->continue_target()->Bind();
 | 
| +          }
 | 
| +          // Control can reach the test at the bottom by falling out
 | 
| +          // of the body, by a continue in the body, or from the
 | 
| +          // update expression.
 | 
| +          if (has_valid_frame()) {
 | 
| +            // The break target is the fall-through (body is a
 | 
| +            // backward jump from here).
 | 
| +            ControlDestination dest(&body, node->break_target(), false);
 | 
| +            LoadCondition(node->cond(), NOT_INSIDE_TYPEOF, &dest, true);
 | 
| +          }
 | 
| +        } else {
 | 
| +          // Otherwise, jump back to the test at the top.
 | 
| +          if (has_valid_frame()) {
 | 
| +            if (node->next() == NULL) {
 | 
| +              node->continue_target()->Jump();
 | 
| +            } else {
 | 
| +              loop.Jump();
 | 
| +            }
 | 
| +          }
 | 
|          }
 | 
| -
 | 
| -        // Control can reach the test at the bottom by falling out of
 | 
| -        // the body, by a continue in the body, or from the update
 | 
| -        // expression.
 | 
| -        if (has_valid_frame()) {
 | 
| -          // The break target is the fall-through (body is a backward
 | 
| -          // jump from here).
 | 
| -          ControlDestination dest(&body, node->break_target(), false);
 | 
| -          LoadCondition(node->cond(), NOT_INSIDE_TYPEOF, &dest, true);
 | 
| -        }
 | 
|        }
 | 
|  
 | 
|        // The break target may be already bound (by the condition), or
 | 
| 
 |