Don't allow DataflowOptimizer to perform constant transformation on expressions with side-effects. Review at http://gwt-code-reviews.appspot.com/1467801 git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@10360 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/gflow/constants/ConstantsTransformationFunction.java b/dev/core/src/com/google/gwt/dev/jjs/impl/gflow/constants/ConstantsTransformationFunction.java index 812c143..8fb4616 100644 --- a/dev/core/src/com/google/gwt/dev/jjs/impl/gflow/constants/ConstantsTransformationFunction.java +++ b/dev/core/src/com/google/gwt/dev/jjs/impl/gflow/constants/ConstantsTransformationFunction.java
@@ -56,6 +56,11 @@ Preconditions.checkNotNull(condition, "Null condition in %s: %s", node, node.getJNode()); + + if (condition.hasSideEffects()) { + return; + } + JValueLiteral evaluatedCondition = ExpressionEvaluator.evaluate(condition, assumption);
diff --git a/dev/core/test/com/google/gwt/dev/jjs/impl/gflow/DataflowOptimizerTest.java b/dev/core/test/com/google/gwt/dev/jjs/impl/gflow/DataflowOptimizerTest.java index 060bc4e..60a1a00 100644 --- a/dev/core/test/com/google/gwt/dev/jjs/impl/gflow/DataflowOptimizerTest.java +++ b/dev/core/test/com/google/gwt/dev/jjs/impl/gflow/DataflowOptimizerTest.java
@@ -2,6 +2,8 @@ import com.google.gwt.dev.jjs.ast.JMethod; import com.google.gwt.dev.jjs.ast.JProgram; +import com.google.gwt.dev.jjs.impl.DeadCodeElimination; +import com.google.gwt.dev.jjs.impl.MethodInliner; import com.google.gwt.dev.jjs.impl.OptimizerTestBase; public class DataflowOptimizerTest extends OptimizerTestBase { @@ -9,6 +11,10 @@ protected void setUp() throws Exception { super.setUp(); + /* + * TODO: Each of these snippets shouldn't be setup for every test, and thus should be moved + * to the individual test cases they are needed for (or to shared methods if needed). + */ addSnippetClassDecl("static void foo(int i) { }"); addSnippetClassDecl("static boolean bar() { return true; }"); addSnippetClassDecl("static void baz(boolean b) { }"); @@ -29,6 +35,9 @@ addSnippetClassDecl("static class Foo { int i; int j; int k; }"); addSnippetClassDecl("static Foo createFoo() {return null;}"); addSnippetClassDecl("static Foo staticFooInstance;"); + + runMethodInliner = false; + runDCE = false; } public void testLinearStatements1() throws Exception { @@ -305,9 +314,60 @@ " long lng8 = lng << 8;", " return lng8;"); } + + /* + * This test is a regression for an issue where inlined multiexpressions were getting removed + * by the ConstantsTransformationFunction, based on the constant value of the multi-expression, + * despite there being side-effects of the multi-expression. So, we want to test that inlining + * proceeds, but not further constant transformation. + * + * TODO: This test may need to evolve over time, as the specifics of the optimizers change. One + * obvious todo is to allow some form of constant transformation to occur with inlined + * multi-expressions (see comment below). + */ + public void testInlinedConstantExpressionWithSideEffects() throws Exception { + + runDCE = true; + runMethodInliner = true; + + addSnippetClassDecl("static void fail() {" + + " throw new RuntimeException();" + + "}"); + addSnippetClassDecl("static Integer x;"); + addSnippetClassDecl("static boolean copy(Number n) {" + + " x = (Integer) n;" + + " return true;" + + "}"); + + optimize("int", + "Integer n = new Integer(1);", + "if (!copy(n)) {", + " fail();", + "}", + "return x;") + // TODO: Allow the second line below to be transformed to just: "EntryPoint.x = n;" + .intoString("Integer n = new Integer(1);", + "((EntryPoint.x = n, true)) || EntryPoint.fail();", + "return EntryPoint.x.intValue();"); + + } + + private boolean runDCE; + private boolean runMethodInliner; @Override protected boolean optimizeMethod(JProgram program, JMethod method) { - return DataflowOptimizer.exec(program, method).didChange(); + boolean didChange = false; + + if (runDCE) { + didChange = DeadCodeElimination.exec(program).didChange() || didChange; + } + + if (runMethodInliner) { + didChange = MethodInliner.exec(program).didChange() || didChange; + } + + didChange = DataflowOptimizer.exec(program, method).didChange() || didChange; + return didChange; } }