blob: be8de7518bbcfa5ea4f54f1b9c53a9443a25c319 [file] [log] [blame]
/*
* Copyright 2010 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.dev.jjs.ast.JMethod;
import com.google.gwt.dev.jjs.ast.JProgram;
import com.google.gwt.dev.jjs.ast.js.JsniMethodBody;
public class PrunerTest extends OptimizerTestBase {
@Override
protected void setUp() throws Exception {
super.setUp();
runDeadCodeElimination = true;
}
public void testSmoke() throws Exception {
addSnippetClassDecl("static int foo(int i) { return i; }");
addSnippetClassDecl("static void unusedMethod() { }");
addSnippetClassDecl("static void usedMethod() { }");
addSnippetClassDecl("static class UnusedClass { }");
addSnippetClassDecl("static class UninstantiatedClass { int field; void method() {} }");
addSnippetClassDecl("static UninstantiatedClass uninstantiatedField;");
addSnippetClassDecl("static int unusedField;");
addSnippetClassDecl("static int unreadField;");
addSnippetClassDecl("static int unassignedField;");
addSnippetClassDecl("static UninstantiatedClass returnUninstantiatedClass() { return null; }");
addSnippetClassDecl(
"interface UsedInterface {",
" int unusedConstant = 2;",
" int usedConstant = 3;",
" void method2();",
"}");
addSnippetClassDecl("static class UsedClass implements UsedInterface {",
" int field2;",
" public void method2() { field2 = usedConstant; }",
" UsedClass(UninstantiatedClass c) { }",
" UsedClass(UninstantiatedClass c1, UninstantiatedClass c2) { }",
"}");
addSnippetClassDecl(
"static native void usedNativeMethod(UninstantiatedClass c, UsedClass c2)",
"/*-{",
" c.@test.EntryPoint.UninstantiatedClass::field = 2;",
" c.@test.EntryPoint.UninstantiatedClass::method();",
" c2.@test.EntryPoint.UsedClass::field2++;",
" c2.@test.EntryPoint.UsedClass::method2();",
"}-*/;");
addSnippetClassDecl(
"static native void unusedNativeMethod()",
"/*-{",
"}-*/;");
addSnippetClassDecl("static void methodWithUninstantiatedParam(UninstantiatedClass c) { }");
addSnippetClassDecl("interface UnusedInterface { void foo(); }");
Result result;
(result = optimize("void",
"usedMethod();",
"unreadField = 1;", // should be pruned because it's not read.
"foo(unassignedField);",
"returnUninstantiatedClass();",
"usedNativeMethod(null, null);",
"foo(uninstantiatedField.field);",
"uninstantiatedField.method();",
"methodWithUninstantiatedParam(null);",
"new UsedClass(null);",
"new UsedClass(returnUninstantiatedClass(), returnUninstantiatedClass());",
"UninstantiatedClass localUninstantiated = null;"
)).intoString(
"EntryPoint.usedMethod();",
"EntryPoint.foo(EntryPoint.unassignedField);",
"EntryPoint.returnUninstantiatedClass();",
"EntryPoint.usedNativeMethod(null, null);",
"EntryPoint.foo(null.nullField);",
"null.nullMethod();",
"EntryPoint.methodWithUninstantiatedParam();",
"new EntryPoint$UsedClass();",
"new EntryPoint$UsedClass((EntryPoint.returnUninstantiatedClass(), EntryPoint.returnUninstantiatedClass()));"
);
assertNotNull(result.findMethod("usedMethod"));
// We do not assign to the field, but we use its default value.
// Shouldn't be pruned.
assertNotNull(result.findField("unassignedField"));
assertNotNull(result.findMethod("usedNativeMethod"));
assertNotNull(result.findMethod("returnUninstantiatedClass"));
assertNotNull(result.findMethod("methodWithUninstantiatedParam"));
assertNotNull(result.findClass("EntryPoint$UsedClass"));
assertNotNull(result.findClass("EntryPoint$UsedInterface"));
assertNull(result.findMethod("unusedMethod"));
assertNull(result.findField("unusedField"));
assertNull(result.findField("unreadField"));
assertNull(result.findClass("EntryPoint$UnusedClass"));
assertNull(result.findMethod("unusedNativeMethod"));
assertNull(result.findField("uninstantiatedField"));
assertNull(result.findClass("EntryPoint$UnusedInterface"));
// Class is never instantiated. Should be pruned.
assertNull(result.findClass("UninstantiatedClass"));
assertEquals(
"public static <null> returnUninstantiatedClass(){\n" +
" return null;\n" +
"}",
result.findMethod("returnUninstantiatedClass").toSource());
assertEquals(
"public static void methodWithUninstantiatedParam(){\n" +
"}",
result.findMethod("methodWithUninstantiatedParam").toSource());
assertEquals(
"[final <null> nullField, int field2]",
((JsniMethodBody) result.findMethod("usedNativeMethod").getBody()).
getJsniFieldRefs().toString());
assertEquals(
"[public final <null> nullMethod(), public void method2()]",
((JsniMethodBody) result.findMethod("usedNativeMethod").getBody()).
getJsniMethodRefs().toString());
assertEquals(
"interface EntryPoint$UsedInterface {\n" +
" private static final void $clinit(){\n" +
" Object.$clinit();\n" +
" }\n" +
"\n" +
"}",
result.findClass("EntryPoint$UsedInterface").toSource());
}
@Override
protected boolean optimizeMethod(JProgram program, JMethod method) {
program.addEntryMethod(findMainMethod(program));
return Pruner.exec(program, true).didChange();
}
}