Mirror of the BLOAT repository
https://www.cs.purdue.edu/homes/hosking/bloat/
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
261 lines
6.8 KiB
261 lines
6.8 KiB
/**
|
|
* All files in the distribution of BLOAT (Bytecode Level Optimization and
|
|
* Analysis tool for Java(tm)) are Copyright 1997-2001 by the Purdue
|
|
* Research Foundation of Purdue University. All rights reserved.
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
|
|
package EDU.purdue.cs.bloat.context;
|
|
|
|
import java.io.*;
|
|
import java.util.*;
|
|
|
|
import EDU.purdue.cs.bloat.editor.*;
|
|
import EDU.purdue.cs.bloat.file.*;
|
|
import EDU.purdue.cs.bloat.inline.*;
|
|
import EDU.purdue.cs.bloat.reflect.*;
|
|
|
|
/**
|
|
* This abstract class is a central repository for all things that are necessary
|
|
* for a BLOATing sessions. Its subclasses implement certain schemes for
|
|
* managing BLOAT data structures such as editors and control flow graphs.
|
|
*/
|
|
public abstract class BloatContext implements InlineContext {
|
|
public static boolean DEBUG = Boolean.getBoolean("BloatContext.DEBUG");
|
|
|
|
protected InlineStats inlineStats;
|
|
|
|
// Ignore stuff for inlining
|
|
protected Set ignorePackages = new HashSet();
|
|
|
|
protected Set ignoreClasses = new HashSet();
|
|
|
|
protected Set ignoreMethods = new HashSet();
|
|
|
|
protected Set ignoreFields = new HashSet();
|
|
|
|
protected boolean ignoreSystem = false;
|
|
|
|
protected CallGraph callGraph;
|
|
|
|
protected Set roots; // Root methods of call graph
|
|
|
|
protected static void db(final String s) {
|
|
if (BloatContext.DEBUG) {
|
|
System.out.println(s);
|
|
}
|
|
}
|
|
|
|
protected ClassInfoLoader loader;
|
|
|
|
/**
|
|
* Constructor. Each <tt>BloatContext</tt> needs to know about a
|
|
* <tt>ClassInfoLoader</tt>.
|
|
*/
|
|
public BloatContext(final ClassInfoLoader loader) {
|
|
this.loader = loader;
|
|
}
|
|
|
|
private static ClassLoader systemCL;
|
|
static {
|
|
final String s = "";
|
|
BloatContext.systemCL = s.getClass().getClassLoader();
|
|
}
|
|
|
|
/**
|
|
* Returns <tt>true</tt> if the give type is a system class (that is, has
|
|
* the same class loader as java.lang.String).
|
|
*/
|
|
public static boolean isSystem(final Type type) {
|
|
Class c = null;
|
|
try {
|
|
c = Class.forName(type.className().replace('/', '.'));
|
|
|
|
} catch (final ClassNotFoundException ex) {
|
|
System.err.println("** Could not find class " + type.className());
|
|
ex.printStackTrace(System.err);
|
|
System.exit(1);
|
|
}
|
|
|
|
// Have to use == because class loader might be null
|
|
return (c.getClassLoader() == BloatContext.systemCL);
|
|
}
|
|
|
|
public void setRootMethods(final Set roots) {
|
|
if (this.callGraph != null) {
|
|
// Can't set the call graph roots after its been created
|
|
throw new IllegalStateException("Cannot set roots after "
|
|
+ "call graph has been created");
|
|
}
|
|
|
|
this.roots = roots;
|
|
}
|
|
|
|
public CallGraph getCallGraph() {
|
|
if (this.callGraph == null) {
|
|
// Create a new CallGraph
|
|
this.callGraph = new CallGraph(this, this.roots);
|
|
}
|
|
return (this.callGraph);
|
|
}
|
|
|
|
public InlineStats getInlineStats() {
|
|
if (inlineStats == null) {
|
|
inlineStats = new InlineStats();
|
|
}
|
|
return (inlineStats);
|
|
}
|
|
|
|
public void addIgnorePackage(String name) {
|
|
name = name.replace('.', '/');
|
|
ignorePackages.add(name);
|
|
}
|
|
|
|
public void addIgnoreClass(final Type type) {
|
|
ignoreClasses.add(type);
|
|
}
|
|
|
|
public void addIgnoreMethod(final MemberRef method) {
|
|
ignoreMethods.add(method);
|
|
}
|
|
|
|
public void addIgnoreField(final MemberRef field) {
|
|
ignoreFields.add(field);
|
|
}
|
|
|
|
public void setIgnoreSystem(final boolean ignore) {
|
|
this.ignoreSystem = ignore;
|
|
}
|
|
|
|
public boolean ignoreClass(final Type type) {
|
|
// First, check to see if we explicitly ignore it. If not, check
|
|
// to see if we ignore its package. The ladies always seem to
|
|
// ignore my package.
|
|
if (ignoreClasses.contains(type)) {
|
|
return (true);
|
|
|
|
} else if (type.isPrimitive()) {
|
|
addIgnoreClass(type);
|
|
return (true);
|
|
|
|
} else {
|
|
if (this.ignoreSystem) {
|
|
if (BloatContext.isSystem(type)) {
|
|
addIgnoreClass(type);
|
|
return (true);
|
|
}
|
|
}
|
|
|
|
String packageName = type.className();
|
|
final int lastSlash = packageName.lastIndexOf('/');
|
|
|
|
if (lastSlash == -1) {
|
|
return (false);
|
|
}
|
|
|
|
packageName = packageName.substring(0, lastSlash);
|
|
|
|
// If any ignore package is a prefix of the class's package,
|
|
// then ignore it. This makes our lives easier.
|
|
final Iterator packages = ignorePackages.iterator();
|
|
while (packages.hasNext()) {
|
|
final String s = (String) packages.next();
|
|
if (type.className().startsWith(s)) {
|
|
addIgnoreClass(type);
|
|
return (true);
|
|
}
|
|
}
|
|
|
|
return (false);
|
|
}
|
|
}
|
|
|
|
public boolean ignoreMethod(final MemberRef method) {
|
|
if (ignoreMethods.contains(method)) {
|
|
return (true);
|
|
|
|
} else if (ignoreClass(method.declaringClass())) {
|
|
addIgnoreMethod(method);
|
|
return (true);
|
|
}
|
|
return (false);
|
|
}
|
|
|
|
public boolean ignoreField(final MemberRef field) {
|
|
if (ignoreMethods.contains(field)) {
|
|
return (true);
|
|
|
|
} else if (ignoreClass(field.declaringClass())) {
|
|
addIgnoreField(field);
|
|
return (true);
|
|
}
|
|
return (false);
|
|
}
|
|
|
|
/**
|
|
* Commits all classes, methods, and fields, that have been modified.
|
|
*/
|
|
public abstract void commitDirty();
|
|
|
|
/**
|
|
* Test the ignore stuff.
|
|
*/
|
|
public static void main(final String[] args) {
|
|
final PrintWriter out = new PrintWriter(System.out, true);
|
|
final PrintWriter err = new PrintWriter(System.err, true);
|
|
|
|
final BloatContext context = new CachingBloatContext(
|
|
new ClassFileLoader(), new ArrayList(), false);
|
|
|
|
final List types = new ArrayList();
|
|
|
|
for (int i = 0; i < args.length; i++) {
|
|
if (args[i].equals("-ip")) {
|
|
if (++i >= args.length) {
|
|
err.println("** Missing package name");
|
|
System.exit(1);
|
|
}
|
|
|
|
out.println("Ignoring package " + args[i]);
|
|
context.addIgnorePackage(args[i]);
|
|
|
|
} else if (args[i].equals("-ic")) {
|
|
if (++i >= args.length) {
|
|
err.println("** Missing class name");
|
|
System.exit(1);
|
|
}
|
|
|
|
out.println("Ignoring class " + args[i]);
|
|
final String type = args[i].replace('.', '/');
|
|
context.addIgnoreClass(Type.getType("L" + type + ";"));
|
|
|
|
} else {
|
|
// A type
|
|
final String type = args[i].replace('.', '/');
|
|
types.add(Type.getType("L" + type + ";"));
|
|
}
|
|
}
|
|
|
|
out.println("");
|
|
|
|
final Iterator iter = types.iterator();
|
|
while (iter.hasNext()) {
|
|
final Type type = (Type) iter.next();
|
|
out.println("Ignore " + type + "? " + context.ignoreClass(type));
|
|
}
|
|
}
|
|
|
|
}
|
|
|