Adds a couple more dead code optimizations, and also cleans up creation of JExpressionStatements throughout the compiler.

Review by: mmendez (desk check), alex.tkachman


git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@1003 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/dev/core/src/com/google/gwt/dev/jjs/JavaToJavaScriptCompiler.java b/dev/core/src/com/google/gwt/dev/jjs/JavaToJavaScriptCompiler.java
index 476b023..ec419f2 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/JavaToJavaScriptCompiler.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/JavaToJavaScriptCompiler.java
@@ -25,7 +25,6 @@
 import com.google.gwt.dev.jjs.InternalCompilerException.NodeInfo;
 import com.google.gwt.dev.jjs.ast.JClassType;
 import com.google.gwt.dev.jjs.ast.JExpression;
-import com.google.gwt.dev.jjs.ast.JExpressionStatement;
 import com.google.gwt.dev.jjs.ast.JMethod;
 import com.google.gwt.dev.jjs.ast.JMethodCall;
 import com.google.gwt.dev.jjs.ast.JNewInstance;
@@ -166,8 +165,7 @@
       // qualifier will be null if onModuleLoad is static
       JMethodCall onModuleLoadCall = new JMethodCall(program, null, qualifier,
           mainMethod);
-      bootStrapMethod.body.statements.add(new JExpressionStatement(program,
-          null, onModuleLoadCall));
+      bootStrapMethod.body.statements.add(onModuleLoadCall.makeStatement());
     }
     program.addEntryMethod(bootStrapMethod);
   }
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JExpression.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JExpression.java
index ada9ff7..eee6c9a 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JExpression.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JExpression.java
@@ -28,4 +28,7 @@
 
   public abstract boolean hasSideEffects();
 
+  public JExpressionStatement makeStatement() {
+    return new JExpressionStatement(program, getSourceInfo(), this);
+  }
 }
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JExpressionStatement.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JExpressionStatement.java
index 2379c91..6aa909c 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JExpressionStatement.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JExpressionStatement.java
@@ -18,13 +18,16 @@
 import com.google.gwt.dev.jjs.SourceInfo;
 
 /**
- * Repesents a statement that is an expression.
+ * Represents a statement that is an expression.
  */
 public class JExpressionStatement extends JStatement {
 
   private JExpression expr;
 
-  public JExpressionStatement(JProgram program, SourceInfo info,
+  /**
+   * Constructed via {@link JExpression#makeStatement()}.
+   */
+  JExpressionStatement(JProgram program, SourceInfo info,
       JExpression expr) {
     super(program, info);
     this.expr = expr;
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JProgram.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JProgram.java
index 67785c4..991aad6 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JProgram.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JProgram.java
@@ -227,7 +227,7 @@
       JExpression lhs, JExpression rhs) {
     JBinaryOperation assign = new JBinaryOperation(this, info, lhs.getType(),
         JBinaryOperator.ASG, lhs, rhs);
-    return new JExpressionStatement(this, info, assign);
+    return assign.makeStatement();
   }
 
   public JClassType createClass(SourceInfo info, char[][] name,
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/DeadCodeElimination.java b/dev/core/src/com/google/gwt/dev/jjs/impl/DeadCodeElimination.java
index e2cd025..7863f74 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/DeadCodeElimination.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/DeadCodeElimination.java
@@ -236,23 +236,27 @@
     }
 
     /**
-     * Prune "if (false)" statements.
+     * Simplify if statements.
      */
     public void endVisit(JIfStatement x, Context ctx) {
-      JExpression expression = x.getIfExpr();
-      if (expression instanceof JBooleanLiteral) {
-        JBooleanLiteral booleanLiteral = (JBooleanLiteral) expression;
-
-        if (booleanLiteral.getValue()) {
+      JExpression expr = x.getIfExpr();
+      JStatement thenStmt = x.getThenStmt();
+      JStatement elseStmt = x.getElseStmt();
+      if (expr instanceof JBooleanLiteral) {
+        JBooleanLiteral booleanLiteral = (JBooleanLiteral) expr;
+        boolean boolVal = booleanLiteral.getValue();
+        if (boolVal && !isEmpty(thenStmt)) {
           // If true, replace myself with then statement
-          ctx.replaceMe(x.getThenStmt());
-        } else if (x.getElseStmt() != null) {
+          ctx.replaceMe(thenStmt);
+        } else if (!boolVal && !isEmpty(elseStmt)) {
           // If false, replace myself with else statement
-          ctx.replaceMe(x.getElseStmt());
+          ctx.replaceMe(elseStmt);
         } else {
           // just prune me
           removeMe(x, ctx);
         }
+      } else if (isEmpty(thenStmt) && isEmpty(elseStmt)) {
+        ctx.replaceMe(expr.makeStatement());
       }
     }
 
@@ -341,8 +345,7 @@
       // Compute properties regarding the state of this try statement
       boolean noTry = x.getTryBlock().statements.isEmpty();
       // TODO: normalize finally block handling
-      boolean noFinally = (x.getFinallyBlock() == null)
-          || x.getFinallyBlock().statements.isEmpty();
+      boolean noFinally = isEmpty(x.getFinallyBlock());
       boolean noCatch = catchArgs.size() == 0;
 
       if (noTry) {
@@ -371,6 +374,16 @@
       }
     }
 
+    /**
+     * TODO: if the AST were normalized, we wouldn't need this.
+     */
+    private boolean isEmpty(JStatement stmt) {
+      if (stmt == null) {
+        return true;
+      }
+      return (stmt instanceof JBlock && ((JBlock) stmt).statements.isEmpty());
+    }
+
     private Class mapType(JType type) {
       return (Class) typeClassMap.get(type);
     }
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaAST.java b/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaAST.java
index f0bc1f5..3ad0ec8 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaAST.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaAST.java
@@ -37,7 +37,6 @@
 import com.google.gwt.dev.jjs.ast.JDoStatement;
 import com.google.gwt.dev.jjs.ast.JDoubleLiteral;
 import com.google.gwt.dev.jjs.ast.JExpression;
-import com.google.gwt.dev.jjs.ast.JExpressionStatement;
 import com.google.gwt.dev.jjs.ast.JField;
 import com.google.gwt.dev.jjs.ast.JFieldRef;
 import com.google.gwt.dev.jjs.ast.JFloatLiteral;
@@ -364,7 +363,7 @@
         if (expr == null) {
           return null;
         }
-        stmt = new JExpressionStatement(program, makeSourceInfo(x), expr);
+        stmt = expr.makeStatement();
       } else {
         stmt = (JStatement) dispatch("processStatement", x);
       }
@@ -441,10 +440,11 @@
         currentMethod = ctor;
         currentMethodScope = x.scope;
 
-        JMethodCall call = null;
+        JMethodCall superOrThisCall = null;
         ExplicitConstructorCall ctorCall = x.constructorCall;
         if (ctorCall != null) {
-          call = (JMethodCall) dispatch("processExpression", ctorCall);
+          superOrThisCall = (JMethodCall) dispatch("processExpression",
+              ctorCall);
         }
 
         /*
@@ -463,8 +463,7 @@
         JMethod clinitMethod = (JMethod) enclosingType.methods.get(0);
         JMethodCall clinitCall = new JMethodCall(program, info, null,
             clinitMethod);
-        ctor.body.statements.add(new JExpressionStatement(program, info,
-            clinitCall));
+        ctor.body.statements.add(clinitCall.makeStatement());
 
         /*
          * All synthetic fields must be assigned, unless we have an explicit
@@ -503,9 +502,8 @@
         }
 
         // optional this or super constructor call
-        if (call != null) {
-          ctor.body.statements.add(new JExpressionStatement(program,
-              makeSourceInfo(ctorCall), call));
+        if (superOrThisCall != null) {
+          ctor.body.statements.add(superOrThisCall.makeStatement());
         }
 
         JExpression thisRef = createThisRef(info, enclosingType);
@@ -519,8 +517,7 @@
           JMethod initMethod = (JMethod) enclosingType.methods.get(1);
           JMethodCall initCall = new JMethodCall(program, info, thisRef,
               initMethod);
-          ctor.body.statements.add(new JExpressionStatement(program, info,
-              initCall));
+          ctor.body.statements.add(initCall.makeStatement());
         }
 
         // user code (finally!)
@@ -1000,14 +997,15 @@
       JExpression qualifier = dispProcessExpression(x.enclosingInstance);
       List qualList = new ArrayList();
       qualList.add(qualifier);
-      
+
       /*
        * Really weird: Sometimes an allocation expression needs both its
        * explicit qualifier AND its implicit enclosing class! We add this second
        * because the explicit qualifier takes precedence.
        */
       if (!currentMethod.isStatic()) {
-        JExpression implicitOuter = program.getExprThisRef(info, (JClassType) currentClass);
+        JExpression implicitOuter = program.getExprThisRef(info,
+            (JClassType) currentClass);
         qualList.add(implicitOuter);
       }
 
@@ -1393,8 +1391,10 @@
 
       SourceInfo info = makeSourceInfo(x);
       JExpression expr = dispProcessExpression(x.condition);
-      JStatement thenStmt = removeThen ? null : dispProcessStatement(x.thenStatement);
-      JStatement elseStmt = removeElse ? null : dispProcessStatement(x.elseStatement);
+      JStatement thenStmt = removeThen ? null
+          : dispProcessStatement(x.thenStatement);
+      JStatement elseStmt = removeElse ? null
+          : dispProcessStatement(x.elseStatement);
       JIfStatement ifStmt = new JIfStatement(program, info, expr, thenStmt,
           elseStmt);
       return ifStmt;
@@ -1449,7 +1449,7 @@
       SourceInfo info = makeSourceInfo(x);
       JBlock block = (JBlock) dispProcessStatement(x.block);
       JExpression expr = dispProcessExpression(x.expression);
-      block.statements.add(0, new JExpressionStatement(program, info, expr));
+      block.statements.add(0, expr.makeStatement());
       return block;
     }
 
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/MakeCallsStatic.java b/dev/core/src/com/google/gwt/dev/jjs/impl/MakeCallsStatic.java
index 7603f1d..afeca7a 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/MakeCallsStatic.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/MakeCallsStatic.java
@@ -18,7 +18,6 @@
 import com.google.gwt.dev.jjs.SourceInfo;
 import com.google.gwt.dev.jjs.ast.Context;
 import com.google.gwt.dev.jjs.ast.JClassType;
-import com.google.gwt.dev.jjs.ast.JExpressionStatement;
 import com.google.gwt.dev.jjs.ast.JLocal;
 import com.google.gwt.dev.jjs.ast.JLocalRef;
 import com.google.gwt.dev.jjs.ast.JMethod;
@@ -126,7 +125,7 @@
       }
       JStatement statement;
       if (oldReturnType == program.getTypeVoid()) {
-        statement = new JExpressionStatement(program, bodyInfo, newCall);
+        statement = newCall.makeStatement();
       } else {
         statement = new JReturnStatement(program, bodyInfo, newCall);
       }