This is a patch to remove catch blocks for globally uninstantiable exception types. It does not do any control flow analysis to determine what exceptions could be thrown from a particular try block (that would be a good idea for the future). My first try at implementing this was to simply use the typeOracle.isInstantiatedType() test; this did not work. The reason is that the catch arg had already been tightened to the nullType by global pruning. What's really weird is that during CaseNormalizer, we were actually generating code for "x instanceof nullType" which is totally bogus. I added in assertions into CastNormalizer to ensure that instanceof and casts to the nullType don't reach there. Had those assertions been in before, it would have forced the catch block optimization. Review by: mmendez git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@391 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/CastNormalizer.java b/dev/core/src/com/google/gwt/dev/jjs/impl/CastNormalizer.java index 70d4589..7368151 100644 --- a/dev/core/src/com/google/gwt/dev/jjs/impl/CastNormalizer.java +++ b/dev/core/src/com/google/gwt/dev/jjs/impl/CastNormalizer.java
@@ -155,11 +155,13 @@ // @Override public void endVisit(JCastOperation x, Context ctx) { + assert (x.getCastType() != program.getTypeNull()); recordCast(x.getCastType(), x.getExpr()); } // @Override public void endVisit(JInstanceOf x, Context ctx) { + assert (x.getTestType() != program.getTypeNull()); recordCast(x.getTestType(), x.getExpr()); }
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 7b5311a..6c6176d 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
@@ -26,15 +26,20 @@ import com.google.gwt.dev.jjs.ast.JExpression; import com.google.gwt.dev.jjs.ast.JForStatement; import com.google.gwt.dev.jjs.ast.JIfStatement; +import com.google.gwt.dev.jjs.ast.JLocalRef; import com.google.gwt.dev.jjs.ast.JModVisitor; import com.google.gwt.dev.jjs.ast.JPrefixOperation; import com.google.gwt.dev.jjs.ast.JProgram; +import com.google.gwt.dev.jjs.ast.JReferenceType; import com.google.gwt.dev.jjs.ast.JStatement; import com.google.gwt.dev.jjs.ast.JTryStatement; import com.google.gwt.dev.jjs.ast.JUnaryOperator; import com.google.gwt.dev.jjs.ast.JVisitor; import com.google.gwt.dev.jjs.ast.JWhileStatement; +import java.util.Iterator; +import java.util.List; + /** * Attempts to remove dead code. */ @@ -173,20 +178,37 @@ } /** - * Prune try statements with no body. Hoist up try statements with no - * catches and an empty finally. + * 1) Remove catch blocks whose exception type is not instantiable. 2) Prune + * try statements with no body. 3) Hoist up try statements with no catches + * and an empty finally. */ public void endVisit(JTryStatement x, Context ctx) { + // 1) Remove catch blocks whose exception type is not instantiable. + List catchArgs = x.getCatchArgs(); + List catchBlocks = x.getCatchBlocks(); + for (Iterator itA = catchArgs.iterator(), itB = catchBlocks.iterator(); itA.hasNext();) { + JLocalRef localRef = (JLocalRef) itA.next(); + itB.next(); + JReferenceType type = (JReferenceType) localRef.getType(); + if (!program.typeOracle.isInstantiatedType(type) + || type == program.getTypeNull()) { + itA.remove(); + itB.remove(); + } + } + + // 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 noCatch = x.getCatchArgs().size() == 0; + boolean noCatch = catchArgs.size() == 0; if (noTry) { - // If the try block is empty, just remove it + // 2) Prune try statements with no body. removeMe(x, ctx); } else if (noCatch && noFinally) { + // 3) Hoist up try statements with no catches and an empty finally. // If there's no catch or finally, there's no point in this even being // a try statement, replace myself with the try block ctx.replaceMe(x.getTryBlock());