/* * Copyright 2014 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.jjs.impl; import com.google.gwt.core.ext.TreeLogger; import com.google.gwt.core.ext.UnableToCompleteException; import com.google.gwt.dev.jjs.ast.Context; import com.google.gwt.dev.jjs.ast.JDeclaredType; import com.google.gwt.dev.jjs.ast.JFieldRef; import com.google.gwt.dev.jjs.ast.JMethod; import com.google.gwt.dev.jjs.ast.JProgram; import com.google.gwt.dev.jjs.ast.JVisitor; /** * Tests for class {@link CompileTimeConstantsReplacer}. */ public class CompileTimeConstantsReplacerTest extends OptimizerTestBase { @Override protected void setUp() throws Exception { super.setUp(); runDeadCodeElimination = false; } public void testReplacement_basic() throws Exception { addSnippetClassDecl( "static class A { ", " final static int f1 = 1;", " static int f2 = 2;", " final static int f3;", " static { f3 = 3; }", "}"); optimizeInto("int i = A.f1;", "int i = 1;"); optimizeInto("int i = A.f2;", "int i = A.f2;"); optimizeInto("int i = A.f3;", "int i = A.f3;"); } public void testReplacement_inLValue() throws Exception { addSnippetClassDecl("static class B {" + " final static int f1 = 1;" + " int m() { " + " if (f1 == 1) " + " return 1; " + " else " + " return 2;" + " } " + "}"); Result result = optimize("void", "int i = B.f1; int[] a = new int[] {1, 2, 3}; a[B.f1] = 1;"); result.into("int i = 1; int[] a = new int[] {1, 2, 3}; a[1] = 1;"); JDeclaredType bType = result.findClass("test.EntryPoint.B"); assertTrue("f1 not found as l-value of declaration statement", findMethod(bType, "$clinit").getBody().toString().contains("final static int f1 = 1")); assertTrue("f1 in condition was not replaced", findMethod(bType, "m").getBody().toString().contains("1 == 1")); assertEquals("incorrect modifiers for f1", "final static int f1", findField(bType, "f1").toString()); assertNoCompileTimeConstants(result.getOptimizedProgram()); } public void testReplacement_withAddition() throws Exception { addSnippetClassDecl( "static class A { ", " final static int f1 = 1 + 1;", " static int f2 = 2;", " final static int f3;", " static { f3 = 3; }", "}", "static class B { ", " final static int f1 = 1 + A.f1;", " static int f2 = 2;", " final static int f3;", " static { f3 = 3; }", "}"); optimizeInto("int i = A.f1;", "int i = 1 + 1;"); optimizeInto("int i = B.f1;", "int i = 1 + 1 + 1;"); } public void testReplacement_withCoercion() throws Exception { addSnippetClassDecl( "static class A { ", " final static double f1 = 1 + 1;", " static int f2 = 2;", " final static int f3;", " static { f3 = 3; }", "}", "static class B { ", " final static double f1 = 1 + A.f1;", " static int f2 = 2;", " final static int f3;", " static { f3 = 3; }", "}"); optimizeInto("double i = A.f1;", "double i = (double) (1 + 1);"); optimizeInto("double i = B.f1;", "double i = 1 + (double) (1 + 1);"); } @Override protected boolean doOptimizeMethod(TreeLogger logger, JProgram program, JMethod method) { CompileTimeConstantsReplacer.exec(program); return true; } private void assertNoCompileTimeConstants(JProgram program) { new JVisitor() { @Override public void endVisit(JFieldRef x, Context ctx) { assertTrue(x.getField() + " was not replaced everywhere", ctx.isLvalue() || !x.getField().isCompileTimeConstant()); } }.accept(program); } private void optimizeInto(String original, String into) throws UnableToCompleteException { Result result = optimize("void", original); assertNoCompileTimeConstants(result.getOptimizedProgram()); result.into(into); } }