Optimizes JS constructs like ('foo' != null) -> (true).
Patch by: mmastrac
Review by: me
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@5519 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/dev/core/src/com/google/gwt/dev/js/JsStaticEval.java b/dev/core/src/com/google/gwt/dev/js/JsStaticEval.java
index 12a1d2f..01bf4c2 100644
--- a/dev/core/src/com/google/gwt/dev/js/JsStaticEval.java
+++ b/dev/core/src/com/google/gwt/dev/js/JsStaticEval.java
@@ -159,6 +159,8 @@
trySimplifyComma(arg1, arg2, ctx);
} else if (op == JsBinaryOperator.EQ) {
trySimplifyEq(x, arg1, arg2, ctx);
+ } else if (op == JsBinaryOperator.NEQ) {
+ trySimplifyNe(x, arg1, arg2, ctx);
}
}
@@ -482,6 +484,22 @@
return original;
}
+ private JsExpression simplifyNe(JsExpression original, JsExpression arg1,
+ JsExpression arg2) {
+ assert (original != null);
+
+ if (arg1 instanceof JsNullLiteral) {
+ return simplifyNullNe(original, arg2);
+ }
+
+ if (arg2 instanceof JsNullLiteral) {
+ return simplifyNullNe(original, arg1);
+ }
+
+ // no simplification made
+ return original;
+ }
+
/**
* Simplify exp == null.
*/
@@ -499,6 +517,23 @@
return original;
}
+ /**
+ * Simplify exp != null.
+ */
+ private JsExpression simplifyNullNe(JsExpression original, JsExpression exp) {
+ assert (original != null);
+
+ if (exp instanceof JsValueLiteral) {
+ // "undefined" is not a JsValueLiteral, so the only way
+ // the result can be false is if exp is itself a JsNullLiteral
+ boolean result = !(exp instanceof JsNullLiteral);
+ return program.getBooleanLiteral(result);
+ }
+
+ // no simplification made
+ return original;
+ }
+
private void trySimplifyEq(JsExpression original, JsExpression arg1,
JsExpression arg2, JsContext<JsExpression> ctx) {
JsExpression updated = simplifyEq(original, arg1, arg2);
@@ -506,6 +541,14 @@
ctx.replaceMe(updated);
}
}
+
+ private void trySimplifyNe(JsExpression original, JsExpression arg1,
+ JsExpression arg2, JsContext<JsExpression> ctx) {
+ JsExpression updated = simplifyNe(original, arg1, arg2);
+ if (updated != original) {
+ ctx.replaceMe(updated);
+ }
+ }
}
public static boolean exec(JsProgram program) {
diff --git a/dev/core/test/com/google/gwt/dev/js/JsStaticEvalTest.java b/dev/core/test/com/google/gwt/dev/js/JsStaticEvalTest.java
new file mode 100644
index 0000000..3e9a97e
--- /dev/null
+++ b/dev/core/test/com/google/gwt/dev/js/JsStaticEvalTest.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2009 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.dev.js;
+
+import com.google.gwt.dev.jjs.SourceOrigin;
+import com.google.gwt.dev.js.ast.JsProgram;
+import com.google.gwt.dev.js.ast.JsStatement;
+import com.google.gwt.dev.js.ast.JsVisitor;
+import com.google.gwt.dev.util.DefaultTextOutput;
+import com.google.gwt.dev.util.TextOutput;
+
+import junit.framework.TestCase;
+
+import java.io.StringReader;
+import java.util.List;
+
+public class JsStaticEvalTest extends TestCase {
+
+ public void testLiteralEqNull() throws Exception {
+ assertTrue(optimize("alert('test' == null)").equals("alert(false);"));
+ }
+
+ public void testLiteralNeNull() throws Exception {
+ assertTrue(optimize("alert('test' != null)").equals("alert(true);"));
+ }
+
+ public void testNullEqNull() throws Exception {
+ assertTrue(optimize("alert(null == null)").equals("alert(true);"));
+ }
+
+ public void testNullNeNull() throws Exception {
+ assertTrue(optimize("alert(null != null)").equals("alert(false);"));
+ }
+
+ private String optimize(String js) throws Exception {
+ JsProgram program = new JsProgram();
+ List<JsStatement> expected = JsParser.parse(SourceOrigin.UNKNOWN,
+ program.getScope(), new StringReader(js));
+ program.getGlobalBlock().getStatements().addAll(expected);
+
+ // Run the static evaluation over this new program
+ JsStaticEval.exec(program);
+
+ TextOutput text = new DefaultTextOutput(true);
+ JsVisitor generator = new JsSourceGenerationVisitor(text);
+
+ generator.accept(program);
+ return text.toString();
+ }
+}