Commit bab0ebcc authored by ebruneton's avatar ebruneton
Browse files

merge with ANN_SUPPORT branch

parent 9bace9a6
......@@ -31,7 +31,7 @@
# Some information about the product
product.name asm
product.version 1.5.1
product.version 2.0_alpha
###############################################################################
# BUILD
......
......@@ -107,12 +107,23 @@
<!-- =================================== -->
<target name="compile" depends="init">
<mkdir dir="${out.build}"/>
<javac destdir="${out.build}" optimize="on">
<classpath refid="classpath"/>
<mkdir dir="${out.build}/tmp"/>
<javac destdir="${out.build}/tmp" optimize="on">
<classpath>
<pathelement location="${out.build}/tmp"/>
</classpath>
<src path="${src}"/>
<include name="**/*.java"/>
<exclude name="**/xml/*.java"/>
</javac>
<java classname="org.objectweb.asm.optimizer.Shrinker">
<classpath>
<pathelement location="${out.build}/tmp"/>
</classpath>
<arg value="${src}/org/objectweb/asm/optimizer/shrink.properties"/>
<arg value="${out.build}/tmp"/>
<arg value="${out.build}"/>
</java>
</target>
<!-- =================================== -->
......@@ -135,19 +146,11 @@
</target>
<target name="jar" depends="dist.init,compile">
<!--
<mkdir dir="${out.tmp}"/>
<copy toDir="${out.tmp}">
<fileset dir="${archive}">
<include name="*.mf"/>
</fileset>
<filterset>
<filter token="@product.version@" value="${product.version}"/>
</filterset>
</copy>
<replace dir="${out.tmp}" token="@product.version@" value="${product.version}"/>
-->
<multipleAnt dir="${archive}"/>
<java classname="org.objectweb.asm.optimizer.JarOptimizer">
<classpath refid="classpath"/>
<arg value="${out.dist.lib}"/>
</java>
</target>
<target name="jdoc" depends="init,dist.init">
......
......@@ -28,15 +28,15 @@
* THE POSSIBILITY OF SUCH DAMAGE.
*/
import org.objectweb.asm.FieldVisitor;
import org.objectweb.asm.ClassAdapter;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.CodeAdapter;
import org.objectweb.asm.CodeVisitor;
import org.objectweb.asm.Constants;
import org.objectweb.asm.MethodAdapter;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import org.objectweb.asm.Attribute;
import java.io.FileOutputStream;
import java.io.InputStream;
......@@ -102,7 +102,7 @@ public class Adapt extends ClassLoader {
}
}
class TraceFieldClassAdapter extends ClassAdapter implements Constants {
class TraceFieldClassAdapter extends ClassAdapter implements Opcodes {
private String owner;
......@@ -114,29 +114,30 @@ class TraceFieldClassAdapter extends ClassAdapter implements Constants {
final int version,
final int access,
final String name,
final String signature,
final String superName,
final String[] interfaces,
final String sourceFile)
final String[] interfaces)
{
owner = name;
super.visit(version, access, name, superName, interfaces, sourceFile);
super.visit(version, access, name, signature, superName, interfaces);
}
public void visitField (
public FieldVisitor visitField (
final int access,
final String name,
final String desc,
final Object value,
final Attribute attrs)
final String signature,
final Object value)
{
super.visitField(access, name, desc, value, attrs);
FieldVisitor fv =
super.visitField(access, name, desc, signature, value);
if ((access & ACC_STATIC) == 0) {
Type t = Type.getType(desc);
int size = t.getSize();
// generates getter method
String gDesc = "()" + desc;
CodeVisitor gv =
MethodVisitor gv =
cv.visitMethod(ACC_PRIVATE, "_get" + name, gDesc, null, null);
gv.visitFieldInsn(GETSTATIC,
"java/lang/System", "err", "Ljava/io/PrintStream;");
......@@ -147,10 +148,11 @@ class TraceFieldClassAdapter extends ClassAdapter implements Constants {
gv.visitFieldInsn(GETFIELD, owner, name, desc);
gv.visitInsn(t.getOpcode(IRETURN));
gv.visitMaxs(1 + size, 1);
gv.visitEnd();
// generates setter method
String sDesc = "(" + desc + ")V";
CodeVisitor sv =
MethodVisitor sv =
cv.visitMethod(ACC_PRIVATE, "_set" + name, sDesc, null, null);
sv.visitFieldInsn(GETSTATIC,
"java/lang/System", "err", "Ljava/io/PrintStream;");
......@@ -158,31 +160,33 @@ class TraceFieldClassAdapter extends ClassAdapter implements Constants {
sv.visitMethodInsn(INVOKEVIRTUAL,
"java/io/PrintStream", "println", "(Ljava/lang/String;)V");
sv.visitVarInsn(ALOAD, 0);
sv.visitIntInsn(t.getOpcode(ILOAD), 1);
sv.visitVarInsn(t.getOpcode(ILOAD), 1);
sv.visitFieldInsn(PUTFIELD, owner, name, desc);
sv.visitInsn(RETURN);
sv.visitMaxs(1 + size, 1 + size);
sv.visitEnd();
}
return fv;
}
public CodeVisitor visitMethod (
public MethodVisitor visitMethod (
final int access,
final String name,
final String desc,
final String[] exceptions,
final Attribute attrs)
final String signature,
final String[] exceptions)
{
CodeVisitor mv = cv.visitMethod(access, name, desc, exceptions, attrs);
MethodVisitor mv = cv.visitMethod(access, name, desc, signature, exceptions);
return mv == null ? null : new TraceFieldCodeAdapter(mv, owner);
}
}
class TraceFieldCodeAdapter extends CodeAdapter implements Constants {
class TraceFieldCodeAdapter extends MethodAdapter implements Opcodes {
private String owner;
public TraceFieldCodeAdapter (final CodeVisitor cv, final String owner) {
super(cv);
public TraceFieldCodeAdapter (final MethodVisitor mv, final String owner) {
super(mv);
this.owner = owner;
}
......
......@@ -34,53 +34,52 @@ import java.util.List;
import java.util.Set;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.Constants;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Label;
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.IincInsnNode;
import org.objectweb.asm.tree.MethodNode;
import org.objectweb.asm.tree.TreeClassAdapter;
import org.objectweb.asm.tree.VarInsnNode;
import org.objectweb.asm.tree.analysis.Analyzer;
import org.objectweb.asm.tree.analysis.BasicVerifier;
import org.objectweb.asm.tree.analysis.DataflowInterpreter;
import org.objectweb.asm.tree.analysis.DataflowValue;
import org.objectweb.asm.tree.analysis.Frame;
import org.objectweb.asm.util.TraceCodeVisitor;
import org.objectweb.asm.util.TraceMethodVisitor;
/**
* @author Eric Bruneton
*/
public class Analysis implements Constants {
public class Analysis implements Opcodes {
public static void main (String[] args) throws Exception {
ClassReader cr = new ClassReader("Analysis");
TreeClassAdapter ca = new TreeClassAdapter(null);
cr.accept(ca, true);
List methods = ca.classNode.methods;
ClassNode cn = new ClassNode();
cr.accept(cn, true);
List methods = cn.methods;
for (int i = 0; i < methods.size(); ++i) {
MethodNode method = (MethodNode)methods.get(i);
if (method.instructions.size() > 0) {
if (!analyze(ca.classNode, method)) {
if (!analyze(cn, method)) {
Analyzer a = new Analyzer(new BasicVerifier());
try {
a.analyze(ca.classNode, method);
a.analyze(cn, method);
} catch (Exception ignored) {
}
final Frame[] frames = a.getFrames();
TraceCodeVisitor cv = new TraceCodeVisitor(null) {
public void visitMaxs (int maxStack, int maxLocals) {
TraceMethodVisitor mv = new TraceMethodVisitor() {
public void visitMaxs (final int maxStack, final int maxLocals) {
for (int i = 0; i < text.size(); ++i) {
String s = frames[i] == null ? "null" : frames[i].toString();
while (s.length() < Math.max(20, maxStack+maxLocals+1)) {
s += " ";
}
System.err.print(
Integer.toString(i + 1000).substring(1) + " " + s + " : "
Integer.toString(i + 1000).substring(1) + " " + s + " : "
+ text.get(i));
}
System.err.println();
......@@ -89,28 +88,28 @@ public class Analysis implements Constants {
for (int j = 0; j < method.instructions.size(); ++j) {
Object insn = method.instructions.get(j);
if (insn instanceof AbstractInsnNode) {
((AbstractInsnNode)insn).accept(cv);
((AbstractInsnNode)insn).accept(mv);
} else {
cv.visitLabel((Label)insn);
mv.visitLabel((Label)insn);
}
}
cv.visitMaxs(0, 0);
mv.visitMaxs(0, 0);
}
}
}
}
/*
* Detects unused xSTORE instructions, i.e. xSTORE instructions without at
* Detects unused xSTORE instructions, i.e. xSTORE instructions without at
* least one xLOAD corresponding instruction in their successor instructions
* (in the control flow graph).
*/
public static boolean analyze (ClassNode c, MethodNode m) throws Exception {
Analyzer a = new Analyzer(new DataflowInterpreter());
Frame[] frames = a.analyze(c, m);
// for each xLOAD instruction, we find the xSTORE instructions that can
// for each xLOAD instruction, we find the xSTORE instructions that can
// produce the value loaded by this instruction, and we put them in 'stores'
Set stores = new HashSet();
for (int i = 0; i < m.instructions.size(); ++i) {
......@@ -144,7 +143,7 @@ public class Analysis implements Constants {
if (!stores.contains(insn)) {
ok = false;
System.err.println(
"method " + m.name + ", instruction " + i +
"method " + m.name + ", instruction " + i +
": useless store instruction");
}
}
......@@ -152,14 +151,14 @@ public class Analysis implements Constants {
}
return ok;
}
/*
* Test for the above method, with three useless xSTORE instructions.
*/
public int test (int i, int j) {
i = i + 1; // ok, because i can be read after this point
if (j == 0) {
j = 1; // useless
} else {
......@@ -174,7 +173,7 @@ public class Analysis implements Constants {
j = j + 1; // useless
}
}
return 0;
}
}
......@@ -29,12 +29,13 @@
*/
import org.objectweb.asm.Attribute;
import org.objectweb.asm.FieldVisitor;
import org.objectweb.asm.ClassAdapter;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.CodeVisitor;
import org.objectweb.asm.Constants;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Label;
import org.objectweb.asm.ByteVector;
import org.objectweb.asm.util.TraceClassVisitor;
......@@ -63,12 +64,12 @@ public class Attributes extends ClassLoader {
// "disassembles" the adapted class
cr = new ClassReader(b);
cv = new TraceClassVisitor(null, new PrintWriter(System.out));
cv = new TraceClassVisitor(new PrintWriter(System.out));
cr.accept(cv, new Attribute[] { new CommentAttribute("") }, false);
}
}
class AddCommentClassAdapter extends ClassAdapter implements Constants {
class AddCommentClassAdapter extends ClassAdapter implements Opcodes {
public AddCommentClassAdapter (final ClassVisitor cv) {
super(cv);
......@@ -78,44 +79,36 @@ class AddCommentClassAdapter extends ClassAdapter implements Constants {
final int version,
final int access,
final String name,
final String signature,
final String superName,
final String[] interfaces,
final String sourceFile)
final String[] interfaces)
{
super.visit(version, access, name, superName, interfaces, sourceFile);
super.visit(version, access, name, signature, superName, interfaces);
visitAttribute(new CommentAttribute("this is a class comment"));
}
public void visitField (
public FieldVisitor visitField (
final int access,
final String name,
final String desc,
final Object value,
final Attribute attrs)
final String signature,
final Object value)
{
super.visitField(
access,
name,
desc,
value,
new CommentAttribute("this is a field comment", attrs));
FieldVisitor fv = super.visitField(access, name, desc, signature, value);
fv.visitAttribute(new CommentAttribute("this is a field comment"));
return fv;
}
public CodeVisitor visitMethod (
public MethodVisitor visitMethod (
final int access,
final String name,
final String desc,
final String[] exceptions,
final Attribute attrs)
final String signature,
final String[] exceptions)
{
CodeVisitor mv = cv.visitMethod(
access,
name,
desc,
exceptions,
new CommentAttribute("this is a method comment", attrs));
MethodVisitor mv = cv.visitMethod(access, name, desc, signature, exceptions);
if (mv != null) {
mv.visitAttribute(new CommentAttribute("this is a code comment"));
mv.visitAttribute(new CommentAttribute("this is a method comment"));
}
return mv;
}
......@@ -130,16 +123,14 @@ class CommentAttribute extends Attribute {
this.comment = comment;
}
public CommentAttribute (final String comment, final Attribute next) {
super("Comment");
this.comment = comment;
this.next = next;
}
public String getComment () {
return comment;
}
public boolean isUnknown () {
return false;
}
protected Attribute read (
ClassReader cr,
int off,
......
......@@ -29,8 +29,8 @@
*/
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.CodeVisitor;
import org.objectweb.asm.Constants;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Label;
import java.io.FileOutputStream;
......@@ -69,7 +69,7 @@ public class Compile extends ClassLoader {
* @author Eric Bruneton
*/
abstract class Exp implements Constants {
abstract class Exp implements Opcodes {
/*
* Returns the byte code of an Expression class corresponding to this
......@@ -80,23 +80,25 @@ abstract class Exp implements Constants {
// class header
String[] itfs = {Expression.class.getName()};
ClassWriter cw = new ClassWriter(true);
cw.visit(V1_1, ACC_PUBLIC, name, "java/lang/Object", itfs, null);
cw.visit(V1_1, ACC_PUBLIC, name, null, "java/lang/Object", itfs);
// default public constructor
CodeVisitor mw = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
mw.visitVarInsn(ALOAD, 0);
mw.visitMethodInsn(
MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(
INVOKESPECIAL,
"java/lang/Object", "<init>", "()V");
mw.visitInsn(RETURN);
mw.visitMaxs(1, 1);
mv.visitInsn(RETURN);
mv.visitMaxs(1, 1);
mv.visitEnd();
// eval method
mw = cw.visitMethod(ACC_PUBLIC, "eval", "(II)I", null, null);
compile(mw);
mw.visitInsn(IRETURN);
mv = cw.visitMethod(ACC_PUBLIC, "eval", "(II)I", null, null);
compile(mv);
mv.visitInsn(IRETURN);
// max stack and max locals automatically computed
mw.visitMaxs(0, 0);
mv.visitMaxs(0, 0);
mv.visitEnd();
return cw.toByteArray();
}
......@@ -107,7 +109,7 @@ abstract class Exp implements Constants {
* value of this expression.
*/
abstract void compile (CodeVisitor mw);
abstract void compile (MethodVisitor mv);
}
/**
......@@ -122,9 +124,9 @@ class Cst extends Exp {
this.value = value;
}
void compile (CodeVisitor mw) {
void compile (MethodVisitor mv) {
// pushes the constant's value onto the stack
mw.visitLdcInsn(new Integer(value));
mv.visitLdcInsn(new Integer(value));
}
}
......@@ -140,9 +142,9 @@ class Var extends Exp {
this.index = index + 1;
}
void compile (CodeVisitor mb) {
void compile (MethodVisitor mv) {
// pushes the 'index' local variable onto the stack
mb.visitVarInsn(ILOAD, index);
mv.visitVarInsn(ILOAD, index);
}
}
......@@ -171,11 +173,11 @@ class Add extends BinaryExp {
super(e1, e2);
}
void compile (CodeVisitor mw) {
void compile (MethodVisitor mv) {
// compiles e1, e2, and adds an instruction to add the two values
e1.compile(mw);
e2.compile(mw);
mw.visitInsn(IADD);
e1.compile(mv);
e2.compile(mv);
mv.visitInsn(IADD);
}
}
......@@ -189,11 +191,11 @@ class Mul extends BinaryExp {
super(e1, e2);
}
void compile (CodeVisitor mb) {
void compile (MethodVisitor mv) {
// compiles e1, e2, and adds an instruction to multiply the two values
e1.compile(mb);
e2.compile(mb);
mb.visitInsn(IMUL);
e1.compile(mv);
e2.compile(mv);
mv.visitInsn(IMUL);
}
}
......@@ -207,20 +209,20 @@ class GT extends BinaryExp {
super(e1, e2);
}
void compile (CodeVisitor mw) {
void compile (MethodVisitor mv) {
// compiles e1, e2, and adds the instructions to compare the two values
e1.compile(mw);
e2.compile(mw);
e1.compile(mv);
e2.compile(mv);
Label iftrue = new Label();
Label end = new Label();
mw.visitJumpInsn(IF_ICMPGT, iftrue);
mv.visitJumpInsn(IF_ICMPGT, iftrue);
// case where e1 <= e2 : pushes false and jump to "end"
mw.visitInsn(ICONST_0);
mw.visitJumpInsn(GOTO, end);
mv.visitLdcInsn(new Integer(0));
mv.visitJumpInsn(GOTO, end);
// case where e1 > e2 : pushes true
mw.visitLabel(iftrue);
mw.visitInsn(ICONST_1);
mw.visitLabel(end);
mv.visitLabel(iftrue);
mv.visitLdcInsn(new Integer(1));
mv.visitLabel(end);
}
}
......@@ -234,19 +236,19 @@ class And extends BinaryExp {
super(e1, e2);
}
void compile (CodeVisitor mw) {
void compile (MethodVisitor mv) {
// compiles e1
e1.compile(mw);
e1.compile(mv);
// tests if e1 is false
mw.visitInsn(DUP);
mv.visitInsn(DUP);
Label end = new Label();
mw.visitJumpInsn(IFEQ, end);
mv.visitJumpInsn(IFEQ, end);
// case where e1 is true : e1 && e2 is equal to e2
mw.visitInsn(POP);
e2.compile(mw);
mv.visitInsn(POP);
e2.compile(mv);
// if e1 is false, e1 && e2 is equal to e1:
// we jump directly to this label, without evaluating e2
mw.visitLabel(end);
mv.visitLabel(end);
}
}
......@@ -260,19 +262,19 @@ class Or extends BinaryExp {
super(e1, e2);
}
void compile (CodeV