Prevents another type of inlining recursion sickness in the compiler.


git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@1650 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/MethodInliner.java b/dev/core/src/com/google/gwt/dev/jjs/impl/MethodInliner.java
index 941ac34..b09f80c 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/MethodInliner.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/MethodInliner.java
@@ -31,6 +31,7 @@
 import com.google.gwt.dev.jjs.ast.JReturnStatement;
 import com.google.gwt.dev.jjs.ast.JStatement;
 import com.google.gwt.dev.jjs.ast.JThisRef;
+import com.google.gwt.dev.jjs.ast.JVisitor;
 import com.google.gwt.dev.jjs.ast.js.JMultiExpression;
 
 import java.util.ArrayList;
@@ -72,30 +73,6 @@
   }
 
   /**
-   * Replace parameters inside an inlined expression with arguments to the
-   * inlined method.
-   */
-  private class ParameterReplacer extends JModVisitor {
-    private final JMethodCall methodCall;
-
-    public ParameterReplacer(JMethodCall methodCall) {
-      this.methodCall = methodCall;
-    }
-
-    @Override
-    public void endVisit(JParameterRef x, Context ctx) {
-      int paramIndex = methodCall.getTarget().params.indexOf(x.getParameter());
-      assert paramIndex != -1;
-
-      // Replace with a cloned call argument.
-      CloneExpressionVisitor cloner = new CloneExpressionVisitor(program);
-      JExpression arg = methodCall.getArgs().get(paramIndex);
-      JExpression clone = cloner.cloneExpression(arg);
-      ctx.replaceMe(clone);
-    }
-  }
-
-  /**
    * Method inlining visitor.
    */
   private class InliningVisitor extends JModVisitor {
@@ -313,6 +290,15 @@
         return false;
       }
 
+      // Make sure the expression we're about to inline doesn't include a call
+      // to the target method!
+      RecursionCheckVisitor recursionCheckVisitor = new RecursionCheckVisitor(
+          x.getTarget());
+      recursionCheckVisitor.accept(targetExpr);
+      if (recursionCheckVisitor.isRecursive()) {
+        return false;
+      }
+
       /*
        * After this point, it's possible that the method might be inlinable at
        * some call sites, depending on its arguments. From here on return 'true'
@@ -447,6 +433,49 @@
   }
 
   /**
+   * Replace parameters inside an inlined expression with arguments to the
+   * inlined method.
+   */
+  private class ParameterReplacer extends JModVisitor {
+    private final JMethodCall methodCall;
+
+    public ParameterReplacer(JMethodCall methodCall) {
+      this.methodCall = methodCall;
+    }
+
+    @Override
+    public void endVisit(JParameterRef x, Context ctx) {
+      int paramIndex = methodCall.getTarget().params.indexOf(x.getParameter());
+      assert paramIndex != -1;
+
+      // Replace with a cloned call argument.
+      CloneExpressionVisitor cloner = new CloneExpressionVisitor(program);
+      JExpression arg = methodCall.getArgs().get(paramIndex);
+      JExpression clone = cloner.cloneExpression(arg);
+      ctx.replaceMe(clone);
+    }
+  }
+
+  private static class RecursionCheckVisitor extends JVisitor {
+    private boolean isRecursive = false;
+    private JMethod method;
+
+    public RecursionCheckVisitor(JMethod method) {
+      this.method = method;
+    }
+
+    public void endVisit(JMethodCall x, Context ctx) {
+      if (x.getTarget() == method) {
+        isRecursive = true;
+      }
+    }
+
+    public boolean isRecursive() {
+      return isRecursive;
+    }
+  }
+
+  /**
    * Results of a side-effect and order check.
    */
   private enum SideEffectCheck {