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;
}
}