From: aclement Date: Mon, 5 Oct 2009 17:35:36 +0000 (+0000) Subject: optimization X-Git-Tag: V1_6_7~252 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=9b9952cc696d268e9458b1e998b2b167da973f90;p=aspectj.git optimization --- diff --git a/bcel-builder/src/org/aspectj/apache/bcel/classfile/Code.java b/bcel-builder/src/org/aspectj/apache/bcel/classfile/Code.java index fb96fbe5f..b714e6cab 100644 --- a/bcel-builder/src/org/aspectj/apache/bcel/classfile/Code.java +++ b/bcel-builder/src/org/aspectj/apache/bcel/classfile/Code.java @@ -68,7 +68,7 @@ import org.aspectj.apache.bcel.Constants; * This attribute has attributes itself, namely LineNumberTable which is used for debugging purposes and * LocalVariableTable which contains information about the local variables. * - * @version $Id: Code.java,v 1.8 2009/09/15 19:40:12 aclement Exp $ + * @version $Id: Code.java,v 1.9 2009/10/05 17:35:36 aclement Exp $ * @author M. Dahm * @see Attribute * @see CodeException @@ -109,8 +109,9 @@ public final class Code extends Attribute { exceptionTable = NO_EXCEPTIONS; } else { exceptionTable = new CodeException[len]; - for (int i = 0; i < len; i++) + for (int i = 0; i < len; i++) { exceptionTable[i] = new CodeException(file); + } } // Read all attributes, eg: LineNumberTable, LocalVariableTable @@ -172,12 +173,14 @@ public final class Code extends Attribute { file.write(code, 0, code.length); file.writeShort(exceptionTable.length); - for (int i = 0; i < exceptionTable.length; i++) + for (int i = 0; i < exceptionTable.length; i++) { exceptionTable[i].dump(file); + } file.writeShort(attributes.length); - for (int i = 0; i < attributes.length; i++) + for (int i = 0; i < attributes.length; i++) { attributes[i].dump(file); + } } /** @@ -192,9 +195,11 @@ public final class Code extends Attribute { * @return LineNumberTable of Code, if it has one */ public LineNumberTable getLineNumberTable() { - for (int i = 0; i < attributes.length; i++) - if (attributes[i].tag == Constants.ATTR_LINE_NUMBER_TABLE) + for (int i = 0; i < attributes.length; i++) { + if (attributes[i].tag == Constants.ATTR_LINE_NUMBER_TABLE) { return (LineNumberTable) attributes[i]; + } + } return null; } @@ -202,9 +207,11 @@ public final class Code extends Attribute { * @return LocalVariableTable of Code, if it has one */ public LocalVariableTable getLocalVariableTable() { - for (int i = 0; i < attributes.length; i++) - if (attributes[i].tag == Constants.ATTR_LOCAL_VARIABLE_TABLE) + for (int i = 0; i < attributes.length; i++) { + if (attributes[i].tag == Constants.ATTR_LOCAL_VARIABLE_TABLE) { return (LocalVariableTable) attributes[i]; + } + } return null; } @@ -255,8 +262,9 @@ public final class Code extends Attribute { private final int calculateLength() { int len = 0; if (attributes != null) { - for (int i = 0; i < attributes.length; i++) + for (int i = 0; i < attributes.length; i++) { len += attributes[i].length + 6 /* attribute header size */; + } } return len + getInternalLength(); } @@ -309,15 +317,17 @@ public final class Code extends Attribute { if (exceptionTable.length > 0) { buf.append("\nException handler(s) = \n" + "From\tTo\tHandler\tType\n"); - for (int i = 0; i < exceptionTable.length; i++) + for (int i = 0; i < exceptionTable.length; i++) { buf.append(exceptionTable[i].toString(cpool, verbose) + "\n"); + } } if (attributes.length > 0) { buf.append("\nAttribute(s) = \n"); - for (int i = 0; i < attributes.length; i++) + for (int i = 0; i < attributes.length; i++) { buf.append(attributes[i].toString() + "\n"); + } } return buf.toString(); @@ -366,8 +376,9 @@ public final class Code extends Attribute { CodeException exc = exceptionTable[i]; int type = exc.getCatchType(); String name = "finally"; - if (type != 0) + if (type != 0) { name = this.cpool.getConstantString(type, Constants.CONSTANT_Class); + } codeString.append(name).append("["); codeString.append(exc.getStartPC()).append(">").append(exc.getEndPC()).append("]\n"); } diff --git a/bcel-builder/src/org/aspectj/apache/bcel/generic/BranchHandle.java b/bcel-builder/src/org/aspectj/apache/bcel/generic/BranchHandle.java index c735075a4..35d9528b8 100644 --- a/bcel-builder/src/org/aspectj/apache/bcel/generic/BranchHandle.java +++ b/bcel-builder/src/org/aspectj/apache/bcel/generic/BranchHandle.java @@ -55,77 +55,80 @@ package org.aspectj.apache.bcel.generic; */ /** - * BranchHandle is returned by specialized InstructionList.append() whenever a - * BranchInstruction is appended. This is useful when the target of this - * instruction is not known at time of creation and must be set later - * via setTarget(). - * + * BranchHandle is returned by specialized InstructionList.append() whenever a BranchInstruction is appended. This is useful when + * the target of this instruction is not known at time of creation and must be set later via setTarget(). + * * @see InstructionHandle * @see Instruction * @see InstructionList - * @version $Id: BranchHandle.java,v 1.4 2008/05/28 23:52:55 aclement Exp $ - * @author M. Dahm + * @version $Id: BranchHandle.java,v 1.5 2009/10/05 17:35:36 aclement Exp $ + * @author M. Dahm */ public final class BranchHandle extends InstructionHandle { - private InstructionBranch bi; // An alias in fact, but saves lots of casts - - private BranchHandle(InstructionBranch i) { - super(i); - bi = i; - } + private InstructionBranch bi; // An alias in fact, but saves lots of casts - static final BranchHandle getBranchHandle(InstructionBranch i) { - return new BranchHandle(i); - } + private BranchHandle(InstructionBranch i) { + super(i); + bi = i; + } - /* Override InstructionHandle methods: delegate to branch instruction. - * Through this overriding all access to the private i_position field should - * be prevented. - */ - public int getPosition() { return bi.positionOfThisInstruction; } + static final BranchHandle getBranchHandle(InstructionBranch i) { + return new BranchHandle(i); + } - void setPosition(int pos) { - i_position = bi.positionOfThisInstruction = pos; - } + /* + * Override InstructionHandle methods: delegate to branch instruction. Through this overriding all access to the private + * i_position field should be prevented. + */ + public int getPosition() { + return bi.positionOfThisInstruction; + } - protected int updatePosition(int offset, int max_offset) { - int x = bi.updatePosition(offset, max_offset); - i_position = bi.positionOfThisInstruction; - return x; - } + void setPosition(int pos) { + this.pos = bi.positionOfThisInstruction = pos; + } - /** - * Pass new target to instruction. - */ - public void setTarget(InstructionHandle ih) { - bi.setTarget(ih); - } + /** + * Called by InstructionList.setPositions when setting the position for every instruction. In the presence of variable length + * instructions 'setPositions()' performs multiple passes over the instruction list to calculate the correct (byte) positions + * and offsets by calling this function. + * + * @param offset additional offset caused by preceding (variable length) instructions + * @param max_offset the maximum offset that may be caused by these instructions + * @return additional offset caused by possible change of this instruction's length + */ + protected int updatePosition(int offset, int max_offset) { + int x = bi.updatePosition(offset, max_offset); + pos = bi.positionOfThisInstruction; + return x; + } - /** - * Update target of instruction. - */ - public void updateTarget(InstructionHandle old_ih, InstructionHandle new_ih) { - bi.updateTarget(old_ih, new_ih); - } + /** + * Pass new target to instruction. + */ + public void setTarget(InstructionHandle ih) { + bi.setTarget(ih); + } - /** - * @return target of instruction. - */ - public InstructionHandle getTarget() { - return bi.getTarget(); - } + /** + * Update target of instruction. + */ + public void updateTarget(InstructionHandle old_ih, InstructionHandle new_ih) { + bi.updateTarget(old_ih, new_ih); + } - /** - * Set new contents. Old instruction is disposed and may not be used anymore. - */ - public void setInstruction(Instruction i) { - super.setInstruction(i); + /** + * @return target of instruction. + */ + public InstructionHandle getTarget() { + return bi.getTarget(); + } - if(!(i instanceof InstructionBranch)) - throw new ClassGenException("Assigning " + i + - " to branch handle which is not a branch instruction"); - - bi = (InstructionBranch)i; - } + /** + * Set new contents. Old instruction is disposed and may not be used anymore. + */ + public void setInstruction(Instruction i) { + super.setInstruction(i); + bi = (InstructionBranch) i; + } } - diff --git a/bcel-builder/src/org/aspectj/apache/bcel/generic/FieldInstruction.java b/bcel-builder/src/org/aspectj/apache/bcel/generic/FieldInstruction.java index e7c67d2ef..54983e7c9 100644 --- a/bcel-builder/src/org/aspectj/apache/bcel/generic/FieldInstruction.java +++ b/bcel-builder/src/org/aspectj/apache/bcel/generic/FieldInstruction.java @@ -58,50 +58,55 @@ import org.aspectj.apache.bcel.classfile.ConstantPool; /** * Super class for the GET/PUTxxx family of instructions. - * - * @version $Id: FieldInstruction.java,v 1.6 2008/05/28 23:52:56 aclement Exp $ - * @author M. Dahm + * + * @version $Id: FieldInstruction.java,v 1.7 2009/10/05 17:35:36 aclement Exp $ + * @author M. Dahm */ public class FieldInstruction extends FieldOrMethod { - public FieldInstruction(short opcode, int index) { - super(opcode, index); - } + public FieldInstruction(short opcode, int index) { + super(opcode, index); + } - public String toString(ConstantPool cp) { - return org.aspectj.apache.bcel.Constants.OPCODE_NAMES[opcode] + " " + - cp.constantToString(index, org.aspectj.apache.bcel.Constants.CONSTANT_Fieldref); - } - - /** @return size of field (1 or 2) - */ - protected int getFieldSize(ConstantPool cpg) { - return Type.getTypeSize(getSignature(cpg)); - } + public String toString(ConstantPool cp) { + return org.aspectj.apache.bcel.Constants.OPCODE_NAMES[opcode] + " " + + cp.constantToString(index, org.aspectj.apache.bcel.Constants.CONSTANT_Fieldref); + } - public Type getType(ConstantPool cpg) { - return getFieldType(cpg); - } + /** + * @return size of field (1 or 2) + */ + protected int getFieldSize(ConstantPool cpg) { + return Type.getTypeSize(getSignature(cpg)); + } - public Type getFieldType(ConstantPool cpg) { - return Type.getType(getSignature(cpg)); - } + public Type getType(ConstantPool cpg) { + return getFieldType(cpg); + } + public Type getFieldType(ConstantPool cpg) { + return Type.getType(getSignature(cpg)); + } - public String getFieldName(ConstantPool cpg) { - return getName(cpg); - } - - public int produceStack(ConstantPool cpg) { - if (!isStackProducer()) return 0; - - return getFieldSize(cpg); // SAME FOR GETFIELD/GETSTATIC - } - - public int consumeStack(ConstantPool cpg) { - if (!isStackConsumer()) return 0; - if (opcode==GETFIELD) return 1; - return getFieldSize(cpg)+(opcode==PUTFIELD?1:0); - } -} + public String getFieldName(ConstantPool cpg) { + return getName(cpg); + } + + public int produceStack(ConstantPool cpg) { + if (!isStackProducer()) { + return 0; + } + return getFieldSize(cpg); // SAME FOR GETFIELD/GETSTATIC + } + + public int consumeStack(ConstantPool cpg) { + if (!isStackConsumer()) { + return 0; + } + if (opcode == GETFIELD) { + return 1; + } + return getFieldSize(cpg) + (opcode == PUTFIELD ? 1 : 0); + } +} diff --git a/bcel-builder/src/org/aspectj/apache/bcel/generic/FieldOrMethod.java b/bcel-builder/src/org/aspectj/apache/bcel/generic/FieldOrMethod.java index 71f8157cd..bf2c73299 100644 --- a/bcel-builder/src/org/aspectj/apache/bcel/generic/FieldOrMethod.java +++ b/bcel-builder/src/org/aspectj/apache/bcel/generic/FieldOrMethod.java @@ -61,23 +61,15 @@ import org.aspectj.apache.bcel.classfile.ConstantUtf8; /** * Super class for InvokeInstruction and FieldInstruction, since they have some methods in common! * - * @version $Id: FieldOrMethod.java,v 1.7 2009/09/10 15:35:06 aclement Exp $ + * @version $Id: FieldOrMethod.java,v 1.8 2009/10/05 17:35:36 aclement Exp $ * @author M. Dahm */ public abstract class FieldOrMethod extends InstructionCP { - // private boolean dontKnowSignature=true; private String signature; - - // private boolean dontKnowName =true; private String name; - - // private boolean dontKnowClassname =true; private String classname; - /** - * @param index to constant pool - */ protected FieldOrMethod(short opcode, int index) { super(opcode, index); } @@ -89,9 +81,7 @@ public abstract class FieldOrMethod extends InstructionCP { if (signature == null) { ConstantCP cmr = (ConstantCP) cp.getConstant(index); ConstantNameAndType cnat = (ConstantNameAndType) cp.getConstant(cmr.getNameAndTypeIndex()); - signature = ((ConstantUtf8) cp.getConstant(cnat.getSignatureIndex())).getValue(); - // dontKnowSignature=false; } return signature; } @@ -104,7 +94,6 @@ public abstract class FieldOrMethod extends InstructionCP { ConstantCP cmr = (ConstantCP) cp.getConstant(index); ConstantNameAndType cnat = (ConstantNameAndType) cp.getConstant(cmr.getNameAndTypeIndex()); name = ((ConstantUtf8) cp.getConstant(cnat.getNameIndex())).getValue(); - // dontKnowName = false; } return name; } @@ -116,11 +105,11 @@ public abstract class FieldOrMethod extends InstructionCP { if (classname == null) { ConstantCP cmr = (ConstantCP) cp.getConstant(index); String str = cp.getConstantString(cmr.getClassIndex(), CONSTANT_Class); - if (str.charAt(0) == '[') + if (str.charAt(0) == '[') { classname = str; - else + } else { classname = str.replace('/', '.'); - // dontKnowClassname = false; + } } return classname; } diff --git a/bcel-builder/src/org/aspectj/apache/bcel/generic/IINC.java b/bcel-builder/src/org/aspectj/apache/bcel/generic/IINC.java index 6df506e44..d70e20308 100644 --- a/bcel-builder/src/org/aspectj/apache/bcel/generic/IINC.java +++ b/bcel-builder/src/org/aspectj/apache/bcel/generic/IINC.java @@ -53,56 +53,69 @@ package org.aspectj.apache.bcel.generic; * information on the Apache Software Foundation, please see * . */ -import java.io.*; +import java.io.DataOutputStream; +import java.io.IOException; import org.aspectj.apache.bcel.Constants; /** * IINC - Increment local variable by constant - * - * @version $Id: IINC.java,v 1.4 2008/05/28 23:52:57 aclement Exp $ - * @author M. Dahm + * + * @version $Id: IINC.java,v 1.5 2009/10/05 17:35:36 aclement Exp $ + * @author M. Dahm */ public class IINC extends InstructionLV { - private int c; + private int c; + + public IINC(int n, int c, boolean w) { + super(Constants.IINC, n); + this.c = c; + // this.wide = w;//((n > org.aspectj.apache.bcel.Constants.MAX_BYTE) || (Math.abs(c) > Byte.MAX_VALUE)); + } + + private boolean wide() { + return ((lvar > org.aspectj.apache.bcel.Constants.MAX_BYTE) || (Math.abs(c) > Byte.MAX_VALUE)); + } - public IINC(int n, int c,boolean w) { - super(Constants.IINC,n); - this.c=c; -// this.wide = w;//((n > org.aspectj.apache.bcel.Constants.MAX_BYTE) || (Math.abs(c) > Byte.MAX_VALUE)); - } + public void dump(DataOutputStream out) throws IOException { + if (wide()) { + out.writeByte(WIDE); + out.writeByte(opcode); + out.writeShort(lvar); + out.writeShort(c); + } else { + out.writeByte(opcode); + out.writeByte(lvar); + out.writeByte(c); + } + } - private boolean wide() { - return ((lvar > org.aspectj.apache.bcel.Constants.MAX_BYTE) || (Math.abs(c) > Byte.MAX_VALUE)); - } + public int getLength() { + if (wide()) { + return 6; + } else { + return 3; // includes wide byte + } + } - public void dump(DataOutputStream out) throws IOException { - if (wide()) { - out.writeByte(WIDE); - out.writeByte(opcode); - out.writeShort(lvar); - out.writeShort(c); - } else { - out.writeByte(opcode); - out.writeByte(lvar); - out.writeByte(c); - } - } - - - public int getLength() { - if (wide()) return 6; else return 3; // includes wide byte - } + public String toString(boolean verbose) { + return super.toString(verbose) + " " + c; + } - public String toString(boolean verbose) { - return super.toString(verbose) + " " + c; - } + public final int getIncrement() { + return c; + } - public final int getIncrement() { return c; } + public boolean equals(Object other) { + if (!(other instanceof IINC)) { + return false; + } + IINC o = (IINC) other; + return /* o.opcode == opcode && */o.lvar == lvar && o.c == c; + } -// //fixme promote or stick in a table -// public Type getType(ConstantPoolGen cp) { -// return Type.INT; -// } + public int hashCode() { + return opcode * 37 + lvar * (c + 17); + } } diff --git a/bcel-builder/src/org/aspectj/apache/bcel/generic/INVOKEINTERFACE.java b/bcel-builder/src/org/aspectj/apache/bcel/generic/INVOKEINTERFACE.java index 6f60afdac..b545f4d37 100644 --- a/bcel-builder/src/org/aspectj/apache/bcel/generic/INVOKEINTERFACE.java +++ b/bcel-builder/src/org/aspectj/apache/bcel/generic/INVOKEINTERFACE.java @@ -53,58 +53,75 @@ package org.aspectj.apache.bcel.generic; * information on the Apache Software Foundation, please see * . */ -import org.aspectj.apache.bcel.classfile.ConstantPool; -import org.aspectj.apache.bcel.Constants; +import java.io.DataOutputStream; +import java.io.IOException; -import java.io.*; +import org.aspectj.apache.bcel.Constants; +import org.aspectj.apache.bcel.classfile.ConstantPool; -/** +/** * INVOKEINTERFACE - Invoke interface method - *
Stack: ..., objectref, [arg1, [arg2 ...]] -> ...
- * - * @version $Id: INVOKEINTERFACE.java,v 1.3 2008/05/28 23:52:58 aclement Exp $ - * @author M. Dahm + * + *
+ * Stack: ..., objectref, [arg1, [arg2 ...]] -> ...
+ * 
+ * + * @version $Id: INVOKEINTERFACE.java,v 1.4 2009/10/05 17:35:36 aclement Exp $ + * @author M. Dahm */ public final class INVOKEINTERFACE extends InvokeInstruction { - private int nargs; // Number of arguments on stack (number of stack slots), called "count" in vmspec2 + private int nargs; // Number of arguments on stack (number of stack slots), called "count" in vmspec2 + public INVOKEINTERFACE(int index, int nargs, int zerobyte) { + super(Constants.INVOKEINTERFACE, index); - public INVOKEINTERFACE(int index, int nargs,int zerobyte) { - super(Constants.INVOKEINTERFACE, index); + if (nargs < 1) { + throw new ClassGenException("Number of arguments must be > 0 " + nargs); + } - if(nargs < 1) - throw new ClassGenException("Number of arguments must be > 0 " + nargs); + this.nargs = nargs; + } - this.nargs = nargs; - } + /** + * Dump instruction as byte code to stream out. + * + * @param out Output stream + */ + public void dump(DataOutputStream out) throws IOException { + out.writeByte(opcode); + out.writeShort(index); + out.writeByte(nargs); + out.writeByte(0); + } - /** - * Dump instruction as byte code to stream out. - * @param out Output stream - */ - public void dump(DataOutputStream out) throws IOException { - out.writeByte(opcode); - out.writeShort(index); - out.writeByte(nargs); - out.writeByte(0); - } + /** + * The count argument according to the Java Language Specification, Second Edition. + */ + public int getCount() { + return nargs; + } - /** - * The count argument according to the Java Language Specification, - * Second Edition. - */ - public int getCount() { return nargs; } + /** + * @return mnemonic for instruction with symbolic references resolved + */ + public String toString(ConstantPool cp) { + return super.toString(cp) + " " + nargs; + } + public int consumeStack(ConstantPool cpg) { // nargs is given in byte-code + return nargs; // nargs includes this reference + } - /** - * @return mnemonic for instruction with symbolic references resolved - */ - public String toString(ConstantPool cp) { - return super.toString(cp) + " " + nargs; - } + public boolean equals(Object other) { + if (!(other instanceof INVOKEINTERFACE)) { + return false; + } + INVOKEINTERFACE o = (INVOKEINTERFACE) other; + return o.opcode == opcode && o.index == index && o.nargs == nargs; + } - public int consumeStack(ConstantPool cpg) { // nargs is given in byte-code - return nargs; // nargs includes this reference - } + public int hashCode() { + return opcode * 37 + index * (nargs + 17); + } } diff --git a/bcel-builder/src/org/aspectj/apache/bcel/generic/Instruction.java b/bcel-builder/src/org/aspectj/apache/bcel/generic/Instruction.java index ae85e06a0..ffdf63051 100644 --- a/bcel-builder/src/org/aspectj/apache/bcel/generic/Instruction.java +++ b/bcel-builder/src/org/aspectj/apache/bcel/generic/Instruction.java @@ -67,7 +67,7 @@ import com.sun.org.apache.bcel.internal.generic.BranchInstruction; /** * Abstract super class for all Java byte codes. * - * @version $Id: Instruction.java,v 1.8 2009/09/14 20:29:10 aclement Exp $ + * @version $Id: Instruction.java,v 1.9 2009/10/05 17:35:36 aclement Exp $ * @author M. Dahm */ public class Instruction implements Cloneable, Serializable, Constants { @@ -92,7 +92,9 @@ public class Instruction implements Cloneable, Serializable, Constants { * @see BranchInstruction * @return (shallow) copy of an instruction */ + // GET RID OF THIS - make it throw an exception and track the callers final public Instruction copy() { + // if overridden correctly can just return 'this' here if (InstructionConstants.INSTRUCTIONS[opcode] != null) { // immutable instructions do not need copying return this; } else { @@ -107,7 +109,7 @@ public class Instruction implements Cloneable, Serializable, Constants { } /** - * Read an instruction from (byte code) input stream and return the appropiate object. + * Read an instruction bytecode from an input stream and return the appropriate object. * * @param file file to read from * @return instruction object being read @@ -115,7 +117,6 @@ public class Instruction implements Cloneable, Serializable, Constants { public static final Instruction readInstruction(ByteSequence bytes) throws IOException { boolean wide = false; short opcode = (short) bytes.readUnsignedByte(); - Instruction obj = null; if (opcode == Constants.WIDE) { wide = true; @@ -128,6 +129,7 @@ public class Instruction implements Cloneable, Serializable, Constants { return constantInstruction; } + Instruction obj = null; try { switch (opcode) { case Constants.BIPUSH: @@ -257,9 +259,10 @@ public class Instruction implements Cloneable, Serializable, Constants { public int getLength() { // if it is zero, it should have been provided by an overriding implementation of getLength() int len = Constants.iLen[opcode]; - if (len == 0) { - throw new IllegalStateException("Length not right for " + getName().toUpperCase()); - } + assert len != 0; + // if (len == 0) { + // throw new IllegalStateException("Length not right for " + getName().toUpperCase()); + // } return len; } @@ -268,38 +271,49 @@ public class Instruction implements Cloneable, Serializable, Constants { } @Override - public boolean equals(Object that) { - if (!(that instanceof Instruction)) { - return false; + public boolean equals(Object other) { + if (this.getClass() != Instruction.class) { + throw new RuntimeException("NO WAY " + this.getClass()); } - Instruction i1 = this; - Instruction i2 = (Instruction) that; - if (i1.opcode == i2.opcode) { - if (i1.isConstantInstruction()) { - return i1.getValue().equals(i2.getValue()); - } else if (i1.isIndexedInstruction()) { - return i1.getIndex() == i2.getIndex(); - } else if (i1.opcode == Constants.NEWARRAY) { - return ((InstructionByte) i1).getTypecode() == ((InstructionByte) i2).getTypecode(); - } else { - return true; - } + if (!(other instanceof Instruction)) { + return false; } - - return false; + return ((Instruction) other).opcode == opcode; + + // IMPLEMENT EQUALS AND HASHCODE IN THE SUBTYPES! + + // Instruction i1 = this; + // Instruction i2 = (Instruction) that; + // if (i1.opcode == i2.opcode) { + // if (i1.isConstantInstruction()) { + // return i1.getValue().equals(i2.getValue()); + // } else if (i1.isIndexedInstruction()) { + // return i1.getIndex() == i2.getIndex(); + // } else if (i1.opcode == Constants.NEWARRAY) { + // return ((InstructionByte) i1).getTypecode() == ((InstructionByte) i2).getTypecode(); + // } else { + // return true; + // } + // } + // + // return false; } @Override public int hashCode() { - int result = 17 + opcode * 37; - if (isConstantInstruction()) { - result = 37 * getValue().hashCode() + result; - } else if (isIndexedInstruction()) { - result = 37 * getIndex() + result; - } else if (opcode == Constants.NEWARRAY) { - result = 37 * ((InstructionByte) this).getTypecode() + result; + if (this.getClass() != Instruction.class) { + throw new RuntimeException("NO WAY " + this.getClass()); } - return result; + return opcode * 37; + // int result = 17 + opcode * 37; + // if (isConstantInstruction()) { + // result = 37 * getValue().hashCode() + result; + // } else if (isIndexedInstruction()) { + // result = 37 * getIndex() + result; + // } else if (opcode == Constants.NEWARRAY) { + // result = 37 * ((InstructionByte) this).getTypecode() + result; + // } + // return result; } public Type getType() { @@ -316,9 +330,10 @@ public class Instruction implements Cloneable, Serializable, Constants { } public Number getValue() { - if ((instFlags[opcode] & CONSTANT_INST) == 0) { - throw new RuntimeException(getName() + " is not a constant instruction"); - } + assert (instFlags[opcode] & CONSTANT_INST) == 0; + // if ((instFlags[opcode] & CONSTANT_INST) == 0) { + // throw new RuntimeException(getName() + " is not a constant instruction"); + // } switch (opcode) { case ICONST_M1: case ICONST_0: @@ -349,6 +364,11 @@ public class Instruction implements Cloneable, Serializable, Constants { return (Constants.instFlags[opcode] & LOAD_INST) != 0; } + // remove these from here, leave them in the InstructionLV + public boolean isASTORE() { + return false; + } + public boolean isALOAD() { return false; } @@ -357,13 +377,9 @@ public class Instruction implements Cloneable, Serializable, Constants { return (Constants.instFlags[opcode] & STORE_INST) != 0; } - public boolean isASTORE() { - return false; - } - - public boolean containsTarget(InstructionHandle ih) { - throw new IllegalStateException("Dont ask!!"); - } + // public boolean containsTarget(InstructionHandle ih) { + // throw new IllegalStateException("Dont ask!!"); + // } public boolean isJsrInstruction() { return (Constants.instFlags[opcode] & JSR_INSTRUCTION) != 0; @@ -394,10 +410,11 @@ public class Instruction implements Cloneable, Serializable, Constants { } public ObjectType getLoadClassType(ConstantPool cpg) { - if ((Constants.instFlags[opcode] & Constants.LOADCLASS_INST) == 0) { - throw new IllegalStateException("This opcode " + opcode + " does not have the property " - + Long.toHexString(Constants.LOADCLASS_INST)); - } + assert (Constants.instFlags[opcode] & Constants.LOADCLASS_INST) == 0; + // if ((Constants.instFlags[opcode] & Constants.LOADCLASS_INST) == 0) { + // throw new IllegalStateException("This opcode " + opcode + " does not have the property " + // + Long.toHexString(Constants.LOADCLASS_INST)); + // } Type t = getType(cpg); if (t instanceof ArrayType) { t = ((ArrayType) t).getBasicType(); @@ -409,9 +426,9 @@ public class Instruction implements Cloneable, Serializable, Constants { return (Constants.instFlags[opcode] & RET_INST) != 0; } - public boolean isGoto() { - return opcode == GOTO || opcode == GOTO_W; - } + // public boolean isGoto() { + // return opcode == GOTO || opcode == GOTO_W; + // } public boolean isLocalVariableInstruction() { return (Constants.instFlags[opcode] & LV_INST) != 0; diff --git a/bcel-builder/src/org/aspectj/apache/bcel/generic/InstructionBranch.java b/bcel-builder/src/org/aspectj/apache/bcel/generic/InstructionBranch.java index 0a5912247..53fed8e52 100644 --- a/bcel-builder/src/org/aspectj/apache/bcel/generic/InstructionBranch.java +++ b/bcel-builder/src/org/aspectj/apache/bcel/generic/InstructionBranch.java @@ -65,7 +65,7 @@ import org.aspectj.apache.bcel.classfile.ConstantPool; * about an instruction it doesnt yet know the position if (targetInstruction). targetInstruction (if set) overrides targetIndex * * @see InstructionList - * @version $Id: InstructionBranch.java,v 1.5 2008/08/28 00:03:03 aclement Exp $ + * @version $Id: InstructionBranch.java,v 1.6 2009/10/05 17:35:36 aclement Exp $ * @author M. Dahm */ public class InstructionBranch extends Instruction implements InstructionTargeter { @@ -171,7 +171,7 @@ public class InstructionBranch extends Instruction implements InstructionTargete } else { opcode = GOTO_W; } - return 2; + return 2; // instruction jump destination grows from a short to a long } else { throw new IllegalStateException("Unable to pack method, jump (with opcode=" + opcode + ") is too far: " + Math.abs(i)); diff --git a/bcel-builder/src/org/aspectj/apache/bcel/generic/InstructionByte.java b/bcel-builder/src/org/aspectj/apache/bcel/generic/InstructionByte.java index fcd46dc9f..5ba8a9abe 100644 --- a/bcel-builder/src/org/aspectj/apache/bcel/generic/InstructionByte.java +++ b/bcel-builder/src/org/aspectj/apache/bcel/generic/InstructionByte.java @@ -93,4 +93,16 @@ public class InstructionByte extends Instruction { public final Type getType() { return new ArrayType(BasicType.getType(theByte), 1); } + + public boolean equals(Object other) { + if (!(other instanceof InstructionByte)) { + return false; + } + InstructionByte o = (InstructionByte) other; + return o.opcode == opcode && o.theByte == theByte; + } + + public int hashCode() { + return opcode * 37 + theByte; + } } \ No newline at end of file diff --git a/bcel-builder/src/org/aspectj/apache/bcel/generic/InstructionCP.java b/bcel-builder/src/org/aspectj/apache/bcel/generic/InstructionCP.java index e2b4f9c68..09222d6a4 100644 --- a/bcel-builder/src/org/aspectj/apache/bcel/generic/InstructionCP.java +++ b/bcel-builder/src/org/aspectj/apache/bcel/generic/InstructionCP.java @@ -60,24 +60,22 @@ import java.io.IOException; import org.aspectj.apache.bcel.Constants; import org.aspectj.apache.bcel.classfile.Constant; import org.aspectj.apache.bcel.classfile.ConstantClass; +import org.aspectj.apache.bcel.classfile.ConstantDouble; +import org.aspectj.apache.bcel.classfile.ConstantFloat; +import org.aspectj.apache.bcel.classfile.ConstantInteger; +import org.aspectj.apache.bcel.classfile.ConstantLong; import org.aspectj.apache.bcel.classfile.ConstantPool; - -import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen; -import com.sun.org.apache.bcel.internal.generic.INVOKEVIRTUAL; -import com.sun.org.apache.bcel.internal.generic.LDC; +import org.aspectj.apache.bcel.classfile.ConstantString; +import org.aspectj.apache.bcel.classfile.ConstantUtf8; /** - * Slass for instructions that use an index into the constant pool such as LDC, INVOKEVIRTUAL, etc. - * - * @see ConstantPoolGen - * @see LDC - * @see INVOKEVIRTUAL + * Class for instructions that use an index into the constant pool such as LDC, INVOKEVIRTUAL, etc. * - * @version $Id: InstructionCP.java,v 1.5 2009/09/14 20:29:10 aclement Exp $ + * @version $Id: InstructionCP.java,v 1.6 2009/10/05 17:35:36 aclement Exp $ * @author M. Dahm */ public class InstructionCP extends Instruction { - protected int index; // index to constant pool + protected int index; public InstructionCP(short opcode, int index) { super(opcode); @@ -180,36 +178,47 @@ public class InstructionCP extends Instruction { } else { return Type.getType(name); } - default: // Never reached + default: throw new RuntimeException("Unknown or invalid constant type at " + index); } } @Override - public Object getValue(ConstantPool cpg) { - org.aspectj.apache.bcel.classfile.Constant c = cpg.getConstant(index); + public Object getValue(ConstantPool constantPool) { + Constant constant = constantPool.getConstant(index); - switch (c.getTag()) { - case org.aspectj.apache.bcel.Constants.CONSTANT_String: - int i = ((org.aspectj.apache.bcel.classfile.ConstantString) c).getStringIndex(); - c = cpg.getConstant(i); - return ((org.aspectj.apache.bcel.classfile.ConstantUtf8) c).getValue(); + switch (constant.getTag()) { + case Constants.CONSTANT_String: + int i = ((ConstantString) constant).getStringIndex(); + constant = constantPool.getConstant(i); + return ((ConstantUtf8) constant).getValue(); - case org.aspectj.apache.bcel.Constants.CONSTANT_Float: - return new Float(((org.aspectj.apache.bcel.classfile.ConstantFloat) c).getValue()); + case Constants.CONSTANT_Float: + return ((ConstantFloat) constant).getValue(); - case org.aspectj.apache.bcel.Constants.CONSTANT_Integer: - return new Integer(((org.aspectj.apache.bcel.classfile.ConstantInteger) c).getValue()); + case Constants.CONSTANT_Integer: + return ((ConstantInteger) constant).getValue(); - // from ldc2_w: - case org.aspectj.apache.bcel.Constants.CONSTANT_Long: - return new Long(((org.aspectj.apache.bcel.classfile.ConstantLong) c).getValue()); + case Constants.CONSTANT_Long: + return ((ConstantLong) constant).getValue(); - case org.aspectj.apache.bcel.Constants.CONSTANT_Double: - return new Double(((org.aspectj.apache.bcel.classfile.ConstantDouble) c).getValue()); - default: // Never reached + case Constants.CONSTANT_Double: + return ((ConstantDouble) constant).getValue(); + default: throw new RuntimeException("Unknown or invalid constant type at " + index); } } + public boolean equals(Object other) { + if (!(other instanceof InstructionCP)) { + return false; + } + InstructionCP o = (InstructionCP) other; + return o.opcode == opcode && o.index == index; + } + + public int hashCode() { + return opcode * 37 + index; + } + } diff --git a/bcel-builder/src/org/aspectj/apache/bcel/generic/InstructionHandle.java b/bcel-builder/src/org/aspectj/apache/bcel/generic/InstructionHandle.java index d114a600e..2f2691df1 100644 --- a/bcel-builder/src/org/aspectj/apache/bcel/generic/InstructionHandle.java +++ b/bcel-builder/src/org/aspectj/apache/bcel/generic/InstructionHandle.java @@ -68,7 +68,7 @@ import org.aspectj.apache.bcel.classfile.Utility; * doubly-linked list. From the outside only the next and the previous instruction (handle) are accessible. One can traverse the * list via an Enumeration returned by InstructionList.elements(). * - * @version $Id: InstructionHandle.java,v 1.8 2009/09/28 16:39:46 aclement Exp $ + * @version $Id: InstructionHandle.java,v 1.9 2009/10/05 17:35:36 aclement Exp $ * @author M. Dahm * @see Instruction * @see BranchHandle @@ -77,9 +77,17 @@ import org.aspectj.apache.bcel.classfile.Utility; public class InstructionHandle implements java.io.Serializable { InstructionHandle next, prev; // Will be set from the outside Instruction instruction; - protected int i_position = -1; // byte code offset of instruction + protected int pos = -1; // byte code offset of instruction private Set targeters = Collections.emptySet(); + protected InstructionHandle(Instruction i) { + setInstruction(i); + } + + static final InstructionHandle getInstructionHandle(Instruction i) { + return new InstructionHandle(i); + } + public final InstructionHandle getNext() { return next; } @@ -102,41 +110,19 @@ public class InstructionHandle implements java.io.Serializable { instruction = i; } - protected InstructionHandle(Instruction i) { - setInstruction(i); - } - - static final InstructionHandle getInstructionHandle(Instruction i) { - return new InstructionHandle(i); - } - - /** - * Called by InstructionList.setPositions when setting the position for every instruction. In the presence of variable length - * instructions 'setPositions()' performs multiple passes over the instruction list to calculate the correct (byte) positions - * and offsets by calling this function. - * - * @param offset additional offset caused by preceding (variable length) instructions - * @param max_offset the maximum offset that may be caused by these instructions - * @return additional offset caused by possible change of this instruction's length - */ - protected int updatePosition(int offset, int max_offset) { - i_position += offset; - return 0; - } - /** * @return the position, i.e., the byte code offset of the contained instruction. This is accurate only after * InstructionList.setPositions() has been called. */ public int getPosition() { - return i_position; + return pos; } /** * Set the position, i.e., the byte code offset of the contained instruction. */ void setPosition(int pos) { - i_position = pos; + this.pos = pos; } /** @@ -147,7 +133,7 @@ public class InstructionHandle implements java.io.Serializable { next = prev = null; instruction.dispose(); instruction = null; - i_position = -1; + pos = -1; removeAllTargeters(); } @@ -179,7 +165,6 @@ public class InstructionHandle implements java.io.Serializable { return !targeters.isEmpty(); } - public Set getTargeters() { return targeters; } @@ -194,7 +179,7 @@ public class InstructionHandle implements java.io.Serializable { * @return a (verbose) string representation of the contained instruction. */ public String toString(boolean verbose) { - return Utility.format(i_position, 4, false, ' ') + ": " + instruction.toString(verbose); + return Utility.format(pos, 4, false, ' ') + ": " + instruction.toString(verbose); } public String toString() { diff --git a/bcel-builder/src/org/aspectj/apache/bcel/generic/InstructionLV.java b/bcel-builder/src/org/aspectj/apache/bcel/generic/InstructionLV.java index b49a76870..73c278016 100644 --- a/bcel-builder/src/org/aspectj/apache/bcel/generic/InstructionLV.java +++ b/bcel-builder/src/org/aspectj/apache/bcel/generic/InstructionLV.java @@ -61,7 +61,7 @@ import org.aspectj.apache.bcel.Constants; /** * Abstract super class for instructions dealing with local variables. * - * @version $Id: InstructionLV.java,v 1.4 2008/08/28 00:05:01 aclement Exp $ + * @version $Id: InstructionLV.java,v 1.5 2009/10/05 17:35:36 aclement Exp $ * @author M. Dahm */ public class InstructionLV extends Instruction { @@ -263,4 +263,16 @@ public class InstructionLV extends Instruction { return lvar > Constants.MAX_BYTE; } + public boolean equals(Object other) { + if (!(other instanceof InstructionLV)) { + return false; + } + InstructionLV o = (InstructionLV) other; + return o.opcode == opcode && o.lvar == lvar; + } + + public int hashCode() { + return opcode * 37 + lvar; + } + } diff --git a/bcel-builder/src/org/aspectj/apache/bcel/generic/InstructionList.java b/bcel-builder/src/org/aspectj/apache/bcel/generic/InstructionList.java index 46d1198d1..c5e2ab66f 100644 --- a/bcel-builder/src/org/aspectj/apache/bcel/generic/InstructionList.java +++ b/bcel-builder/src/org/aspectj/apache/bcel/generic/InstructionList.java @@ -76,7 +76,7 @@ import org.aspectj.apache.bcel.util.ByteSequence; * * A list is finally dumped to a byte code array with getByteCode. * - * @version $Id: InstructionList.java,v 1.9 2009/09/10 03:59:33 aclement Exp $ + * @version $Id: InstructionList.java,v 1.10 2009/10/05 17:35:36 aclement Exp $ * @author M. Dahm * @see Instruction * @see InstructionHandle @@ -247,35 +247,34 @@ public class InstructionList implements Serializable { /** * Append another list after instruction (handle) ih contained in this list. Consumes argument list, i.e., it becomes empty. * - * @param ih where to append the instruction list - * @param il Instruction list to append to this one + * @param appendTo where to append the instruction list + * @param appendee Instruction list to append to this one * @return instruction handle pointing to the first appended instruction */ - public InstructionHandle append(InstructionHandle ih, InstructionList il) { - if (il == null) { - throw new ClassGenException("Appending null InstructionList"); - } + public InstructionHandle append(InstructionHandle appendTo, InstructionList appendee) { + assert appendee != null; - if (il.isEmpty()) { - return ih; + if (appendee.isEmpty()) { + return appendTo; } - InstructionHandle next = ih.next, ret = il.start; + InstructionHandle next = appendTo.next; + InstructionHandle ret = appendee.start; - ih.next = il.start; - il.start.prev = ih; + appendTo.next = appendee.start; + appendee.start.prev = appendTo; - il.end.next = next; + appendee.end.next = next; if (next != null) { - next.prev = il.end; + next.prev = appendee.end; } else { - end = il.end; // Update end ... + end = appendee.end; // Update end ... } - length += il.length; // Update length + length += appendee.length; // Update length - il.clear(); + appendee.clear(); return ret; } @@ -304,9 +303,7 @@ public class InstructionList implements Serializable { * @return instruction handle of the first appended instruction */ public InstructionHandle append(InstructionList il) { - if (il == null) { - throw new ClassGenException("Appending null InstructionList"); - } + assert il != null; if (il.isEmpty()) { return null; @@ -853,41 +850,13 @@ public class InstructionList implements Serializable { * @param check Perform sanity checks, e.g. if all targeted instructions really belong to this list */ public void setPositions(boolean check) { - int max_additional_bytes = 0, additional_bytes = 0; + int maxAdditionalBytes = 0; int index = 0, count = 0; int[] pos = new int[length]; // Pass 0: Sanity checks if (check) { - for (InstructionHandle ih = start; ih != null; ih = ih.next) { - Instruction i = ih.instruction; - - if (i instanceof InstructionBranch) { // target instruction within list? - Instruction inst = ((InstructionBranch) i).getTarget().instruction; - if (!contains(inst)) { - throw new ClassGenException("Branch target of " + Constants.OPCODE_NAMES[i.opcode] + ":" + inst - + " not in instruction list"); - } - - if (i instanceof InstructionSelect) { - InstructionHandle[] targets = ((InstructionSelect) i).getTargets(); - - for (int j = 0; j < targets.length; j++) { - inst = targets[j].instruction; - if (!contains(inst)) { - throw new ClassGenException("Branch target of " + Constants.OPCODE_NAMES[i.opcode] + ":" + inst - + " not in instruction list"); - } - } - } - - if (!(ih instanceof BranchHandle)) { - throw new ClassGenException("Branch instruction " + Constants.OPCODE_NAMES[i.opcode] + ":" + inst - + " not contained in BranchHandle."); - } - - } - } + checkInstructionList(); } // Pass 1: Set position numbers and sum up the maximum number of bytes an @@ -904,40 +873,81 @@ public class InstructionList implements Serializable { switch (i.opcode) { case Constants.JSR: case Constants.GOTO: - max_additional_bytes += 2; + maxAdditionalBytes += 2; break; case Constants.TABLESWITCH: case Constants.LOOKUPSWITCH: - max_additional_bytes += 3; + maxAdditionalBytes += 3; break; } index += i.getLength(); } + // OPTIMIZE positions will only move around if there have been expanding instructions + // if (max_additional_bytes==0...) { + // + // } + /* * Pass 2: Expand the variable-length (Branch)Instructions depending on the target offset (short or int) and ensure that * branch targets are within this list. */ + int offset = 0; for (InstructionHandle ih = start; ih != null; ih = ih.next) { - additional_bytes += ih.updatePosition(additional_bytes, max_additional_bytes); + if (ih instanceof BranchHandle) { + offset += ((BranchHandle) ih).updatePosition(offset, maxAdditionalBytes); + } } - - /* - * Pass 3: Update position numbers (which may have changed due to the preceding expansions), like pass 1. - */ - index = count = 0; - for (InstructionHandle ih = start; ih != null; ih = ih.next) { - Instruction i = ih.instruction; - ih.setPosition(index); - pos[count++] = index; - index += i.getLength(); + if (offset != 0) { + /* + * Pass 3: Update position numbers (which may have changed due to the preceding expansions), like pass 1. + */ + index = count = 0; + for (InstructionHandle ih = start; ih != null; ih = ih.next) { + Instruction i = ih.instruction; + ih.setPosition(index); + pos[count++] = index; + index += i.getLength(); + } } positions = new int[count]; // Trim to proper size System.arraycopy(pos, 0, positions, 0, count); } + private void checkInstructionList() { + for (InstructionHandle ih = start; ih != null; ih = ih.next) { + Instruction i = ih.instruction; + + if (i instanceof InstructionBranch) { // target instruction within list? + Instruction inst = ((InstructionBranch) i).getTarget().instruction; + if (!contains(inst)) { + throw new ClassGenException("Branch target of " + Constants.OPCODE_NAMES[i.opcode] + ":" + inst + + " not in instruction list"); + } + + if (i instanceof InstructionSelect) { + InstructionHandle[] targets = ((InstructionSelect) i).getTargets(); + + for (int j = 0; j < targets.length; j++) { + inst = targets[j].instruction; + if (!contains(inst)) { + throw new ClassGenException("Branch target of " + Constants.OPCODE_NAMES[i.opcode] + ":" + inst + + " not in instruction list"); + } + } + } + + if (!(ih instanceof BranchHandle)) { + throw new ClassGenException("Branch instruction " + Constants.OPCODE_NAMES[i.opcode] + ":" + inst + + " not contained in BranchHandle."); + } + + } + } + } + /** * When everything is finished, use this method to convert the instruction list into an array of bytes. * diff --git a/bcel-builder/src/org/aspectj/apache/bcel/generic/InstructionSelect.java b/bcel-builder/src/org/aspectj/apache/bcel/generic/InstructionSelect.java index dcebe3a0f..b4e00c027 100644 --- a/bcel-builder/src/org/aspectj/apache/bcel/generic/InstructionSelect.java +++ b/bcel-builder/src/org/aspectj/apache/bcel/generic/InstructionSelect.java @@ -61,7 +61,7 @@ import org.aspectj.apache.bcel.util.ByteSequence; /** * Select - Abstract super class for LOOKUPSWITCH and TABLESWITCH instructions. * - * @version $Id: InstructionSelect.java,v 1.3 2008/08/28 00:05:41 aclement Exp $ + * @version $Id: InstructionSelect.java,v 1.4 2009/10/05 17:35:36 aclement Exp $ * @author M. Dahm * @see LOOKUPSWITCH * @see TABLESWITCH @@ -78,15 +78,13 @@ public abstract class InstructionSelect extends InstructionBranch { protected short length; /** - * (Match, target) pairs for switch. `Match' and `targets' must have the - * same length of course. + * (Match, target) pairs for switch. `Match' and `targets' must have the same length of course. * * @param match array of matching values * @param targets instruction targets * @param target default instruction target */ - InstructionSelect(short opcode, int[] match, InstructionHandle[] targets, - InstructionHandle target) { + InstructionSelect(short opcode, int[] match, InstructionHandle[] targets, InstructionHandle target) { super(opcode, target); this.targets = targets; @@ -97,8 +95,7 @@ public abstract class InstructionSelect extends InstructionBranch { this.match = match; if ((matchLength = match.length) != targets.length) { - throw new ClassGenException( - "Match and target array have not the same length"); + throw new ClassGenException("Match and target array have not the same length"); } indices = new int[matchLength]; @@ -106,37 +103,30 @@ public abstract class InstructionSelect extends InstructionBranch { protected int getTargetOffset(InstructionHandle target) { if (target == null) { - throw new ClassGenException("Target of " + super.toString(true) - + " is invalid null handle"); + throw new ClassGenException("Target of " + super.toString(true) + " is invalid null handle"); } int t = target.getPosition(); if (t < 0) { - throw new ClassGenException( - "Invalid branch target position offset for " - + super.toString(true) + ":" + t + ":" + target); + throw new ClassGenException("Invalid branch target position offset for " + super.toString(true) + ":" + t + ":" + + target); } return t - positionOfThisInstruction; } /** - * Since this is a variable length instruction, it may shift the following - * instructions which then need to update their position. + * Since this is a variable length instruction, it may shift the following instructions which then need to update their + * position. * - * Called by InstructionList.setPositions when setting the position for - * every instruction. In the presence of variable length instructions - * `setPositions' performs multiple passes over the instruction list to - * calculate the correct (byte) positions and offsets by calling this - * function. + * Called by InstructionList.setPositions when setting the position for every instruction. In the presence of variable length + * instructions `setPositions' performs multiple passes over the instruction list to calculate the correct (byte) positions and + * offsets by calling this function. * - * @param offset additional offset caused by preceding (variable length) - * instructions - * @param max_offset the maximum offset that may be caused by these - * instructions - * @return additional offset caused by possible change of this instruction's - * length + * @param offset additional offset caused by preceding (variable length) instructions + * @param max_offset the maximum offset that may be caused by these instructions + * @return additional offset caused by possible change of this instruction's length */ protected int updatePosition(int offset, int max_offset) { positionOfThisInstruction += offset; // Additional offset caused by @@ -170,8 +160,7 @@ public abstract class InstructionSelect extends InstructionBranch { out.writeInt(targetIndex); } - public InstructionSelect(short opcode, ByteSequence bytes) - throws IOException { + public InstructionSelect(short opcode, ByteSequence bytes) throws IOException { super(opcode); padding = (4 - bytes.getIndex() % 4) % 4; // Compute number of pad bytes @@ -198,8 +187,7 @@ public abstract class InstructionSelect extends InstructionBranch { s = targets[i].getInstruction().toString(); } - buf.append("(" + match[i] + ", " + s + " = {" + indices[i] - + "})"); + buf.append("(" + match[i] + ", " + s + " = {" + indices[i] + "})"); } } else { buf.append(" ..."); @@ -268,14 +256,6 @@ public abstract class InstructionSelect extends InstructionBranch { } } - public boolean equals(Object other) { - return this == other; - } - - public int hashCode() { - return opcode * 37; - } - /** * @return array of match indices */ @@ -290,6 +270,14 @@ public abstract class InstructionSelect extends InstructionBranch { return indices; } + public boolean equals(Object other) { + return this == other; + } + + public int hashCode() { + return opcode * 37; + } + /** * @return array of match targets */ diff --git a/bcel-builder/src/org/aspectj/apache/bcel/generic/InstructionShort.java b/bcel-builder/src/org/aspectj/apache/bcel/generic/InstructionShort.java index dd8a72eb0..99054cbff 100644 --- a/bcel-builder/src/org/aspectj/apache/bcel/generic/InstructionShort.java +++ b/bcel-builder/src/org/aspectj/apache/bcel/generic/InstructionShort.java @@ -61,20 +61,32 @@ import java.io.IOException; * Instruction that needs one short */ public class InstructionShort extends Instruction { - private final short s; + private final short value; - public InstructionShort(short opcode, short s) { + public InstructionShort(short opcode, short value) { super(opcode); - this.s = s; + this.value = value; } public void dump(DataOutputStream out) throws IOException { out.writeByte(opcode); - out.writeShort(s); + out.writeShort(value); } public String toString(boolean verbose) { - return super.toString(verbose) + " " + s; + return super.toString(verbose) + " " + value; + } + + public boolean equals(Object other) { + if (!(other instanceof InstructionShort)) { + return false; + } + InstructionShort o = (InstructionShort) other; + return o.opcode == opcode && o.value == value; + } + + public int hashCode() { + return opcode * 37 + value; } } diff --git a/bcel-builder/src/org/aspectj/apache/bcel/generic/InvokeInstruction.java b/bcel-builder/src/org/aspectj/apache/bcel/generic/InvokeInstruction.java index fbc55a66a..89cd43474 100644 --- a/bcel-builder/src/org/aspectj/apache/bcel/generic/InvokeInstruction.java +++ b/bcel-builder/src/org/aspectj/apache/bcel/generic/InvokeInstruction.java @@ -61,72 +61,77 @@ import org.aspectj.apache.bcel.classfile.ConstantPool; /** * Super class for the INVOKExxx family of instructions. - * - * @version $Id: InvokeInstruction.java,v 1.5 2008/05/28 23:52:54 aclement Exp $ - * @author M. Dahm + * + * @version $Id: InvokeInstruction.java,v 1.6 2009/10/05 17:35:36 aclement Exp $ + * @author M. Dahm */ public class InvokeInstruction extends FieldOrMethod { - /** - * @param index to constant pool - */ - public InvokeInstruction(short opcode, int index) { - super(opcode, index); - } + /** + * @param index to constant pool + */ + public InvokeInstruction(short opcode, int index) { + super(opcode, index); + } - /** - * @return mnemonic for instruction with symbolic references resolved - */ - public String toString(ConstantPool cp) { - Constant c = cp.getConstant(index); - StringTokenizer tok = new StringTokenizer(cp.constantToString(c)); + /** + * @return mnemonic for instruction with symbolic references resolved + */ + public String toString(ConstantPool cp) { + Constant c = cp.getConstant(index); + StringTokenizer tok = new StringTokenizer(cp.constantToString(c)); - return Constants.OPCODE_NAMES[opcode] + " " + - tok.nextToken().replace('.', '/') + tok.nextToken(); - } + return Constants.OPCODE_NAMES[opcode] + " " + tok.nextToken().replace('.', '/') + tok.nextToken(); + } - /** - * Also works for instructions whose stack effect depends on the - * constant pool entry they reference. - * @return Number of words consumed from stack by this instruction - */ - public int consumeStack(ConstantPool cpg) { - String signature = getSignature(cpg); - int sum = Type.getArgumentSizes(signature); - if (opcode!=Constants.INVOKESTATIC) sum+=1; - return sum; - } + /** + * Also works for instructions whose stack effect depends on the constant pool entry they reference. + * + * @return Number of words consumed from stack by this instruction + */ + public int consumeStack(ConstantPool cpg) { + String signature = getSignature(cpg); + int sum = Type.getArgumentSizes(signature); + if (opcode != Constants.INVOKESTATIC) { + sum += 1; + } + return sum; + } - /** - * Also works for instructions whose stack effect depends on the - * constant pool entry they reference. - * @return Number of words produced onto stack by this instruction - */ - public int produceStack(ConstantPool cpg) { - return getReturnType(cpg).getSize(); - } + /** + * Also works for instructions whose stack effect depends on the constant pool entry they reference. + * + * @return Number of words produced onto stack by this instruction + */ + public int produceStack(ConstantPool cpg) { + return getReturnType(cpg).getSize(); + } - /** @return return type of referenced method. - */ - public Type getType(ConstantPool cpg) { - return getReturnType(cpg); - } + /** + * @return return type of referenced method. + */ + public Type getType(ConstantPool cpg) { + return getReturnType(cpg); + } - /** @return name of referenced method. - */ - public String getMethodName(ConstantPool cpg) { - return getName(cpg); - } + /** + * @return name of referenced method. + */ + public String getMethodName(ConstantPool cpg) { + return getName(cpg); + } - /** @return return type of referenced method. - */ - public Type getReturnType(ConstantPool cpg) { - return Type.getReturnType(getSignature(cpg)); - } + /** + * @return return type of referenced method. + */ + public Type getReturnType(ConstantPool cpg) { + return Type.getReturnType(getSignature(cpg)); + } - /** @return argument types of referenced method. - */ - public Type[] getArgumentTypes(ConstantPool cpg) { - return Type.getArgumentTypes(getSignature(cpg)); - } + /** + * @return argument types of referenced method. + */ + public Type[] getArgumentTypes(ConstantPool cpg) { + return Type.getArgumentTypes(getSignature(cpg)); + } } diff --git a/bcel-builder/src/org/aspectj/apache/bcel/generic/LocalVariableTag.java b/bcel-builder/src/org/aspectj/apache/bcel/generic/LocalVariableTag.java index 724f0cad8..7a4fab4e9 100644 --- a/bcel-builder/src/org/aspectj/apache/bcel/generic/LocalVariableTag.java +++ b/bcel-builder/src/org/aspectj/apache/bcel/generic/LocalVariableTag.java @@ -14,28 +14,30 @@ package org.aspectj.apache.bcel.generic; public final class LocalVariableTag extends Tag { - private Type type; // not always known, in which case signature has to be used private final String signature; private String name; private int slot; - private final int startPos; - boolean remapped = false; + private final int startPosition; + private boolean remapped = false; + + private int hashCode = 0; + private Type type; // not always known, in which case signature has to be used // AMC - pr101047, two local vars with the same name can share the same slot, but must in that case // have different start positions. - public LocalVariableTag(String sig, String name, int slot, int startPosition) { - this.signature = sig; + public LocalVariableTag(String signature, String name, int slot, int startPosition) { + this.signature = signature; this.name = name; this.slot = slot; - this.startPos = startPosition; + this.startPosition = startPosition; } - public LocalVariableTag(Type t, String sig, String name, int slot, int startPosition) { - this.type = t; - this.signature = sig; + public LocalVariableTag(Type type, String signature, String name, int slot, int startPosition) { + this.type = type; + this.signature = signature; this.name = name; this.slot = slot; - this.startPos = startPosition; + this.startPosition = startPosition; } public String getName() { @@ -57,6 +59,12 @@ public final class LocalVariableTag extends Tag { public void updateSlot(int newSlot) { this.slot = newSlot; this.remapped = true; + this.hashCode = 0; + } + + public void setName(String name) { + this.name = name; + this.hashCode = 0; } public boolean isRemapped() { @@ -68,25 +76,19 @@ public final class LocalVariableTag extends Tag { } public boolean equals(Object other) { - if (!(other instanceof LocalVariableTag)) + if (!(other instanceof LocalVariableTag)) { return false; + } LocalVariableTag o = (LocalVariableTag) other; - return o.slot == slot && o.startPos == startPos && o.signature.equals(signature) && o.name.equals(name); + return o.slot == slot && o.startPosition == startPosition && o.signature.equals(signature) && o.name.equals(name); } - public void setName(String name) { - this.name = name; - } - - private int hashCode = 0; - public int hashCode() { if (hashCode == 0) { - int ret = 17; - ret = 37 * ret + signature.hashCode(); + int ret = signature.hashCode(); ret = 37 * ret + name.hashCode(); ret = 37 * ret + slot; - ret = 37 * ret + startPos; + ret = 37 * ret + startPosition; hashCode = ret; } return hashCode; diff --git a/bcel-builder/src/org/aspectj/apache/bcel/generic/MULTIANEWARRAY.java b/bcel-builder/src/org/aspectj/apache/bcel/generic/MULTIANEWARRAY.java index eddc2e995..94a213a25 100644 --- a/bcel-builder/src/org/aspectj/apache/bcel/generic/MULTIANEWARRAY.java +++ b/bcel-builder/src/org/aspectj/apache/bcel/generic/MULTIANEWARRAY.java @@ -53,109 +53,131 @@ package org.aspectj.apache.bcel.generic; * information on the Apache Software Foundation, please see * . */ -import java.io.*; -import org.aspectj.apache.bcel.classfile.ConstantPool; +import java.io.DataOutputStream; +import java.io.IOException; + import org.aspectj.apache.bcel.Constants; import org.aspectj.apache.bcel.ExceptionConstants; +import org.aspectj.apache.bcel.classfile.ConstantPool; -/** +/** * MULTIANEWARRAY - Create new mutidimensional array of references - *
Stack: ..., count1, [count2, ...] -> ..., arrayref
- * - * @version $Id: MULTIANEWARRAY.java,v 1.3 2008/05/28 23:52:59 aclement Exp $ - * @author M. Dahm + * + *
+ * Stack: ..., count1, [count2, ...] -> ..., arrayref
+ * 
+ * + * @version $Id: MULTIANEWARRAY.java,v 1.4 2009/10/05 17:35:36 aclement Exp $ + * @author M. Dahm */ public class MULTIANEWARRAY extends InstructionCP { - private short dimensions; - - public MULTIANEWARRAY(int index, short dimensions) { - super(Constants.MULTIANEWARRAY, index); - this.dimensions = dimensions; - } - - /** - * Dump instruction as byte code to stream out. - * @param out Output stream - */ - public void dump(DataOutputStream out) throws IOException { - out.writeByte(opcode); - out.writeShort(index); - out.writeByte(dimensions); - } - - /** - * Read needed data (i.e., no. dimension) from file. - */ -// protected void initFromFile(ByteSequence bytes, boolean wide) -// throws IOException -// { -// super.initFromFile(bytes, wide); -// dimensions = bytes.readByte(); -//// length = 4; -// } - - /** - * @return number of dimensions to be created - */ - public final short getDimensions() { return dimensions; } - - /** - * @return mnemonic for instruction - */ - public String toString(boolean verbose) { - return super.toString(verbose) + " " + index + " " + dimensions; - } - - /** - * @return mnemonic for instruction with symbolic references resolved - */ - public String toString(ConstantPool cp) { - return super.toString(cp) + " " + dimensions; - } - - /** - * Also works for instructions whose stack effect depends on the - * constant pool entry they reference. - * @return Number of words consumed from stack by this instruction - */ - public int consumeStack(ConstantPool cpg) { return dimensions; } - - public Class[] getExceptions() { - Class[] cs = new Class[2 + ExceptionConstants.EXCS_CLASS_AND_INTERFACE_RESOLUTION.length]; - - System.arraycopy(ExceptionConstants.EXCS_CLASS_AND_INTERFACE_RESOLUTION, 0, - cs, 0, ExceptionConstants.EXCS_CLASS_AND_INTERFACE_RESOLUTION.length); - - cs[ExceptionConstants.EXCS_CLASS_AND_INTERFACE_RESOLUTION.length+1] = ExceptionConstants.NEGATIVE_ARRAY_SIZE_EXCEPTION; - cs[ExceptionConstants.EXCS_CLASS_AND_INTERFACE_RESOLUTION.length] = ExceptionConstants.ILLEGAL_ACCESS_ERROR; - - return cs; - } - - public ObjectType getLoadClassType(ConstantPool cpg) { - Type t = getType(cpg); - - if (t instanceof ArrayType){ - t = ((ArrayType) t).getBasicType(); - } - - return (t instanceof ObjectType)? (ObjectType) t : null; - } - -// /** -// * Call corresponding visitor method(s). The order is: -// * Call visitor methods of implemented interfaces first, then -// * call methods according to the class hierarchy in descending order, -// * i.e., the most specific visitXXX() call comes last. -// * -// * @param v Visitor object -// */ -// public void accept(Visitor v) { -// v.visitLoadClass(this); -// v.visitAllocationInstruction(this); -// v.visitExceptionThrower(this); -// v.visitTypedInstruction(this); -// v.visitCPInstruction(this); -// v.visitMULTIANEWARRAY(this); -// } + private short dimensions; + + public MULTIANEWARRAY(int index, short dimensions) { + super(Constants.MULTIANEWARRAY, index); + this.dimensions = dimensions; + } + + /** + * Dump instruction as byte code to stream out. + * + * @param out Output stream + */ + public void dump(DataOutputStream out) throws IOException { + out.writeByte(opcode); + out.writeShort(index); + out.writeByte(dimensions); + } + + /** + * Read needed data (i.e., no. dimension) from file. + */ + // protected void initFromFile(ByteSequence bytes, boolean wide) + // throws IOException + // { + // super.initFromFile(bytes, wide); + // dimensions = bytes.readByte(); + // // length = 4; + // } + + /** + * @return number of dimensions to be created + */ + public final short getDimensions() { + return dimensions; + } + + /** + * @return mnemonic for instruction + */ + public String toString(boolean verbose) { + return super.toString(verbose) + " " + index + " " + dimensions; + } + + /** + * @return mnemonic for instruction with symbolic references resolved + */ + public String toString(ConstantPool cp) { + return super.toString(cp) + " " + dimensions; + } + + /** + * Also works for instructions whose stack effect depends on the constant pool entry they reference. + * + * @return Number of words consumed from stack by this instruction + */ + public int consumeStack(ConstantPool cpg) { + return dimensions; + } + + public Class[] getExceptions() { + Class[] cs = new Class[2 + ExceptionConstants.EXCS_CLASS_AND_INTERFACE_RESOLUTION.length]; + + System.arraycopy(ExceptionConstants.EXCS_CLASS_AND_INTERFACE_RESOLUTION, 0, cs, 0, + ExceptionConstants.EXCS_CLASS_AND_INTERFACE_RESOLUTION.length); + + cs[ExceptionConstants.EXCS_CLASS_AND_INTERFACE_RESOLUTION.length + 1] = ExceptionConstants.NEGATIVE_ARRAY_SIZE_EXCEPTION; + cs[ExceptionConstants.EXCS_CLASS_AND_INTERFACE_RESOLUTION.length] = ExceptionConstants.ILLEGAL_ACCESS_ERROR; + + return cs; + } + + public ObjectType getLoadClassType(ConstantPool cpg) { + Type t = getType(cpg); + + if (t instanceof ArrayType) { + t = ((ArrayType) t).getBasicType(); + } + + return (t instanceof ObjectType) ? (ObjectType) t : null; + } + + // /** + // * Call corresponding visitor method(s). The order is: + // * Call visitor methods of implemented interfaces first, then + // * call methods according to the class hierarchy in descending order, + // * i.e., the most specific visitXXX() call comes last. + // * + // * @param v Visitor object + // */ + // public void accept(Visitor v) { + // v.visitLoadClass(this); + // v.visitAllocationInstruction(this); + // v.visitExceptionThrower(this); + // v.visitTypedInstruction(this); + // v.visitCPInstruction(this); + // v.visitMULTIANEWARRAY(this); + // } + + public boolean equals(Object other) { + if (!(other instanceof MULTIANEWARRAY)) { + return false; + } + MULTIANEWARRAY o = (MULTIANEWARRAY) other; + return o.opcode == opcode && o.index == index && o.dimensions == dimensions; + } + + public int hashCode() { + return opcode * 37 + index * (dimensions + 17); + } } diff --git a/bcel-builder/src/org/aspectj/apache/bcel/generic/MethodGen.java b/bcel-builder/src/org/aspectj/apache/bcel/generic/MethodGen.java index 15c9000e9..94c42938f 100644 --- a/bcel-builder/src/org/aspectj/apache/bcel/generic/MethodGen.java +++ b/bcel-builder/src/org/aspectj/apache/bcel/generic/MethodGen.java @@ -84,7 +84,7 @@ import org.aspectj.apache.bcel.classfile.annotation.RuntimeParamAnnos; * While generating code it may be necessary to insert NOP operations. You can use the `removeNOPs' method to get rid off them. The * resulting method object can be obtained via the `getMethod()' method. * - * @version $Id: MethodGen.java,v 1.15 2009/09/15 19:40:14 aclement Exp $ + * @version $Id: MethodGen.java,v 1.16 2009/10/05 17:35:36 aclement Exp $ * @author M. Dahm * @author Patrick C. Beard [setMaxStack()] * @see InstructionList @@ -264,8 +264,9 @@ public class MethodGen extends FieldGenOrMethodGen { for (int k = 0; k < ln.length; k++) { LineNumber l = ln[k]; int lnum = l.getLineNumber(); - if (lnum > highestLineNumber) + if (lnum > highestLineNumber) { highestLineNumber = lnum; + } LineNumberTag lt = new LineNumberTag(lnum); il.findHandle(l.getStartPC(), arrayOfInstructions, true).addTargeter(lt); } @@ -290,8 +291,9 @@ public class MethodGen extends FieldGenOrMethodGen { byte b = t.getType(); if (b != Constants.T_ADDRESS) { int increment = t.getSize(); - if (l.getIndex() + increment > maxLocals) + if (l.getIndex() + increment > maxLocals) { maxLocals = l.getIndex() + increment; + } } int end = l.getStartPC() + l.getLength(); do { @@ -311,24 +313,29 @@ public class MethodGen extends FieldGenOrMethodGen { InstructionHandle end = il.findHandle(l.getStartPC() + l.getLength(), arrayOfInstructions); // AMC, this actually gives us the first instruction AFTER the range, // so move back one... (findHandle can't cope with mid-instruction indices) - if (end != null) + if (end != null) { end = end.getPrev(); + } // Repair malformed handles - if (null == start) + if (null == start) { start = il.getStart(); - if (null == end) + } + if (null == end) { end = il.getEnd(); + } addLocalVariable(l.getName(), Type.getType(l.getSignature()), l.getIndex(), start, end); } } - } else + } else { addCodeAttribute(a); + } } } else if (a instanceof ExceptionTable) { String[] names = ((ExceptionTable) a).getExceptionNames(); - for (int j = 0; j < names.length; j++) + for (int j = 0; j < names.length; j++) { addException(names[j]); + } } else if (a instanceof RuntimeAnnos) { RuntimeAnnos runtimeAnnotations = (RuntimeAnnos) a; List l = runtimeAnnotations.getAnnotations(); @@ -395,10 +402,12 @@ public class MethodGen extends FieldGenOrMethodGen { LocalVariableGen h; do { - while (vars[i].getIndex() < m) + while (vars[i].getIndex() < m) { i++; - while (m < vars[j].getIndex()) + } + while (m < vars[j].getIndex()) { j--; + } if (i <= j) { h = vars[i]; @@ -409,10 +418,12 @@ public class MethodGen extends FieldGenOrMethodGen { } } while (i <= j); - if (l < j) + if (l < j) { sort(vars, l, j); - if (i < r) + } + if (i < r) { sort(vars, i, r); + } } /* @@ -427,15 +438,18 @@ public class MethodGen extends FieldGenOrMethodGen { localVariablesList.toArray(lg); for (int i = 0; i < size; i++) { - if (lg[i].getStart() == null) + if (lg[i].getStart() == null) { lg[i].setStart(il.getStart()); + } - if (lg[i].getEnd() == null) + if (lg[i].getEnd() == null) { lg[i].setEnd(il.getEnd()); + } } - if (size > 1) + if (size > 1) { sort(lg, 0, size - 1); + } return lg; } @@ -448,8 +462,9 @@ public class MethodGen extends FieldGenOrMethodGen { int size = lg.length; LocalVariable[] lv = new LocalVariable[size]; - for (int i = 0; i < size; i++) + for (int i = 0; i < size; i++) { lv[i] = lg[i].getLocalVariable(cp); + } return new LocalVariableTable(cp.addUtf8("LocalVariableTable"), 2 + lv.length * 10, lv, cp); } @@ -516,8 +531,9 @@ public class MethodGen extends FieldGenOrMethodGen { */ public CodeExceptionGen addExceptionHandler(InstructionHandle start_pc, InstructionHandle end_pc, InstructionHandle handler_pc, ObjectType catch_type) { - if ((start_pc == null) || (end_pc == null) || (handler_pc == null)) + if ((start_pc == null) || (end_pc == null) || (handler_pc == null)) { throw new ClassGenException("Exception handler target is null instruction"); + } CodeExceptionGen c = new CodeExceptionGen(start_pc, end_pc, handler_pc, catch_type); exceptionsList.add(c); @@ -605,8 +621,9 @@ public class MethodGen extends FieldGenOrMethodGen { int[] ex = new int[size]; try { - for (int i = 0; i < size; i++) + for (int i = 0; i < size; i++) { ex[i] = cp.addClass(exceptionsThrown.get(i)); + } } catch (ArrayIndexOutOfBoundsException e) { } @@ -625,8 +642,9 @@ public class MethodGen extends FieldGenOrMethodGen { } public void addParameterAnnotationsAsAttribute(ConstantPool cp) { - if (!hasParameterAnnotations) + if (!hasParameterAnnotations) { return; + } Attribute[] attrs = Utility.getParameterAnnotationAttributes(cp, param_annotations); if (attrs != null) { for (int i = 0; i < attrs.length; i++) { @@ -674,8 +692,9 @@ public class MethodGen extends FieldGenOrMethodGen { */ byte[] byte_code = null; - if (il != null) + if (il != null) { byte_code = il.getByteCode(); + } LineNumberTable lnt = null; LocalVariableTable lvt = null; @@ -684,11 +703,13 @@ public class MethodGen extends FieldGenOrMethodGen { /* * Create LocalVariableTable and LineNumberTable attributes (for debuggers, e.g.) */ - if ((localVariablesList.size() > 0) && !stripAttributes) + if ((localVariablesList.size() > 0) && !stripAttributes) { addCodeAttribute(lvt = getLocalVariableTable(cp)); + } - if ((lineNumbersList.size() > 0) && !stripAttributes) + if ((lineNumbersList.size() > 0) && !stripAttributes) { addCodeAttribute(lnt = getLineNumberTable(cp)); + } Attribute[] code_attrs = getCodeAttributes(); @@ -696,8 +717,9 @@ public class MethodGen extends FieldGenOrMethodGen { * Each attribute causes 6 additional header bytes */ int attrs_len = 0; - for (int i = 0; i < code_attrs.length; i++) + for (int i = 0; i < code_attrs.length; i++) { attrs_len += (code_attrs[i].getLength() + 6); + } CodeException[] c_exc = getCodeExceptions(); int exc_len = c_exc.length * 8; // Every entry takes 8 bytes @@ -709,8 +731,9 @@ public class MethodGen extends FieldGenOrMethodGen { List attributes = getAttributes(); for (int i = 0; i < attributes.size(); i++) { Attribute a = attributes.get(i); - if (a instanceof Code) + if (a instanceof Code) { removeAttribute(a); + } } code = new Code(cp.addUtf8("Code"), 8 + byte_code.length + // prologue byte code @@ -726,21 +749,26 @@ public class MethodGen extends FieldGenOrMethodGen { ExceptionTable et = null; - if (exceptionsThrown.size() > 0) + if (exceptionsThrown.size() > 0) { addAttribute(et = getExceptionTable(cp)); // Add `Exceptions' if there are "throws" clauses + } Method m = new Method(modifiers, name_index, signature_index, getAttributesImmutable(), cp); // Undo effects of adding attributes // OPTIMIZE why redo this? is there a better way to clean up? - if (lvt != null) + if (lvt != null) { removeCodeAttribute(lvt); - if (lnt != null) + } + if (lnt != null) { removeCodeAttribute(lnt); - if (code != null) + } + if (code != null) { removeAttribute(code); - if (et != null) + } + if (et != null) { removeAttribute(et); + } // J5TODO: Remove the annotation attributes that may have been added return m; } @@ -807,10 +835,11 @@ public class MethodGen extends FieldGenOrMethodGen { } public String[] getArgumentNames() { - if (parameterNames != null) + if (parameterNames != null) { return parameterNames.clone(); - else + } else { return new String[0]; + } } public void setArgumentName(int i, String name) { @@ -838,10 +867,11 @@ public class MethodGen extends FieldGenOrMethodGen { * Computes max. stack size by performing control flow analysis. */ public void setMaxStack() { - if (il != null) + if (il != null) { maxStack = getMaxStack(cp, il, getExceptionHandlers()); - else + } else { maxStack = 0; + } } /** @@ -851,9 +881,11 @@ public class MethodGen extends FieldGenOrMethodGen { if (il != null) { int max = isStatic() ? 0 : 1; - if (parameterTypes != null) - for (int i = 0; i < parameterTypes.length; i++) + if (parameterTypes != null) { + for (int i = 0; i < parameterTypes.length; i++) { max += parameterTypes[i].getSize(); + } + } for (InstructionHandle ih = il.getStart(); ih != null; ih = ih.getNext()) { Instruction ins = ih.getInstruction(); @@ -861,14 +893,16 @@ public class MethodGen extends FieldGenOrMethodGen { if ((ins instanceof InstructionLV) || (ins instanceof RET)) { int index = ins.getIndex() + ins.getType(cp).getSize(); - if (index > max) + if (index > max) { max = index; + } } } maxLocals = max; - } else + } else { maxLocals = 0; + } } public void stripAttributes(boolean flag) { @@ -890,8 +924,9 @@ public class MethodGen extends FieldGenOrMethodGen { Hashtable visitedTargets = new Hashtable(); public void push(InstructionHandle target, int stackDepth) { - if (visited(target)) + if (visited(target)) { return; + } branchTargets.push(visit(target, stackDepth)); } @@ -925,17 +960,19 @@ public class MethodGen extends FieldGenOrMethodGen { public static int getMaxStack(ConstantPool cp, InstructionList il, CodeExceptionGen[] et) { BranchStack branchTargets = new BranchStack(); - int stackDepth = 0, maxStackDepth = 0; + int stackDepth = 0; + int maxStackDepth = 0; + /* * Initially, populate the branch stack with the exception handlers, because these aren't (necessarily) branched to - * explicitly. in each case, the stack will have depth 1, containing the exception object. + * explicitly. In each case, the stack will have depth 1, containing the exception object. */ - for (int i = 0; i < et.length; i++) { - InstructionHandle handler_pc = et[i].getHandlerPC(); - if (handler_pc != null) { + for (int i = 0, max = et.length; i < max; i++) { + InstructionHandle handlerPos = et[i].getHandlerPC(); + if (handlerPos != null) { // it must be at least 1 since there is an exception handler maxStackDepth = 1; - branchTargets.push(handler_pc, 1); + branchTargets.push(handlerPos, 1); } } @@ -948,8 +985,9 @@ public class MethodGen extends FieldGenOrMethodGen { int delta = prod - con; stackDepth += delta; - if (stackDepth > maxStackDepth) + if (stackDepth > maxStackDepth) { maxStackDepth = stackDepth; + } // choose the next instruction based on whether current is a branch. if (instruction instanceof InstructionBranch) { @@ -958,15 +996,17 @@ public class MethodGen extends FieldGenOrMethodGen { // explore all of the select's targets. the default target is handled below. InstructionSelect select = (InstructionSelect) branch; InstructionHandle[] targets = select.getTargets(); - for (int i = 0; i < targets.length; i++) + for (int i = 0; i < targets.length; i++) { branchTargets.push(targets[i], stackDepth); + } // nothing to fall through to. ih = null; } else if (!(branch.isIfInstruction())) { // if an instruction that comes back to following PC, // push next instruction, with stack depth reduced by 1. - if (opcode == Constants.JSR || opcode == Constants.JSR_W) + if (opcode == Constants.JSR || opcode == Constants.JSR_W) { branchTargets.push(ih.getNext(), stackDepth - 1); + } ih = null; } // for all branches, the target of the branch is pushed on the branch stack. @@ -976,12 +1016,14 @@ public class MethodGen extends FieldGenOrMethodGen { } else { // check for instructions that terminate the method. if (opcode == Constants.ATHROW || opcode == Constants.RET - || (opcode >= Constants.IRETURN && opcode <= Constants.RETURN)) + || (opcode >= Constants.IRETURN && opcode <= Constants.RETURN)) { ih = null; + } } // normal case, go to the next instruction. - if (ih != null) + if (ih != null) { ih = ih.getNext(); + } // if we have no more instructions, see if there are any deferred branches to explore. if (ih == null) { BranchTarget bt = branchTargets.pop(); @@ -1009,8 +1051,9 @@ public class MethodGen extends FieldGenOrMethodGen { StringBuffer buf = new StringBuffer(signature); if (exceptionsThrown.size() > 0) { - for (Iterator e = exceptionsThrown.iterator(); e.hasNext();) + for (Iterator e = exceptionsThrown.iterator(); e.hasNext();) { buf.append("\n\t\tthrows " + e.next()); + } } return buf.toString(); @@ -1023,8 +1066,9 @@ public class MethodGen extends FieldGenOrMethodGen { */ public List getAnnotationsOnParameter(int i) { ensureExistingParameterAnnotationsUnpacked(); - if (!hasParameterAnnotations || i > parameterTypes.length) + if (!hasParameterAnnotations || i > parameterTypes.length) { return null; + } return param_annotations[i]; } @@ -1055,10 +1099,11 @@ public class MethodGen extends FieldGenOrMethodGen { hasParameterAnnotations = true; RuntimeParamAnnos rpa = (RuntimeParamAnnos) attribute; - if (rpa.areVisible()) + if (rpa.areVisible()) { paramAnnVisAttr = rpa; - else + } else { paramAnnInvisAttr = rpa; + } for (int j = 0; j < parameterTypes.length; j++) { // This returns Annotation[] ... AnnotationGen[] annos = rpa.getAnnotationsOnParameter(j); @@ -1071,10 +1116,12 @@ public class MethodGen extends FieldGenOrMethodGen { } } } - if (paramAnnVisAttr != null) + if (paramAnnVisAttr != null) { removeAttribute(paramAnnVisAttr); - if (paramAnnInvisAttr != null) + } + if (paramAnnInvisAttr != null) { removeAttribute(paramAnnInvisAttr); + } haveUnpackedParameterAnnotations = true; } diff --git a/bcel-builder/src/org/aspectj/apache/bcel/generic/RET.java b/bcel-builder/src/org/aspectj/apache/bcel/generic/RET.java index 1dc19d446..0fd2f498d 100644 --- a/bcel-builder/src/org/aspectj/apache/bcel/generic/RET.java +++ b/bcel-builder/src/org/aspectj/apache/bcel/generic/RET.java @@ -66,12 +66,12 @@ import org.aspectj.apache.bcel.classfile.ConstantPool; * Stack: ..., -> ..., address * * - * @version $Id: RET.java,v 1.4 2009/10/04 03:21:45 aclement Exp $ + * @version $Id: RET.java,v 1.5 2009/10/05 17:35:36 aclement Exp $ * @author M. Dahm */ public class RET extends Instruction { private boolean wide; - private int index; // index to local variable containg the return address + private int index; // index to local variable containing the return address public RET(int index, boolean wide) { super(Constants.RET); @@ -82,7 +82,7 @@ public class RET extends Instruction { public void dump(DataOutputStream out) throws IOException { if (wide) { - out.writeByte(org.aspectj.apache.bcel.Constants.WIDE); + out.writeByte(Constants.WIDE); } out.writeByte(opcode); if (wide) { @@ -106,7 +106,7 @@ public class RET extends Instruction { public final void setIndex(int index) { this.index = index; - this.wide = index > org.aspectj.apache.bcel.Constants.MAX_BYTE; + this.wide = index > Constants.MAX_BYTE; } public String toString(boolean verbose) { @@ -117,4 +117,16 @@ public class RET extends Instruction { return ReturnaddressType.NO_TARGET; } + public boolean equals(Object other) { + if (!(other instanceof RET)) { + return false; + } + RET o = (RET) other; + return o.opcode == opcode && o.index == index; + } + + public int hashCode() { + return opcode * 37 + index; + } + } diff --git a/bcel-builder/src/org/aspectj/apache/bcel/generic/Type.java b/bcel-builder/src/org/aspectj/apache/bcel/generic/Type.java index a98facde2..d337fc796 100644 --- a/bcel-builder/src/org/aspectj/apache/bcel/generic/Type.java +++ b/bcel-builder/src/org/aspectj/apache/bcel/generic/Type.java @@ -67,7 +67,7 @@ import org.aspectj.apache.bcel.classfile.Utility; * Abstract super class for all possible java types, namely basic types such as int, object types like String and array types, e.g. * int[] * - * @version $Id: Type.java,v 1.12 2009/09/10 03:59:34 aclement Exp $ + * @version $Id: Type.java,v 1.13 2009/10/05 17:35:36 aclement Exp $ * @author M. Dahm * * modified: AndyClement 2-mar-05: Removed unnecessary static and optimized @@ -177,8 +177,9 @@ public abstract class Type { public static final Type getType(String signature) { Type t = commonTypes.get(signature); - if (t != null) + if (t != null) { return t; + } byte type = Utility.typeOfSignature(signature); if (type <= Constants.T_VOID) { return BasicType.getType(type); @@ -212,8 +213,9 @@ public abstract class Type { genericDepth--; break; case ';': - if (genericDepth == 0) + if (genericDepth == 0) { endOfSigReached = true; + } break; default: } @@ -248,8 +250,9 @@ public abstract class Type { } else { // type == T_REFERENCE // Format is 'Lblahblah;' int index = signature.indexOf(';'); // Look for closing ';' - if (index < 0) + if (index < 0) { throw new ClassFormatException("Invalid signature: " + signature); + } // generics awareness int nextAngly = signature.indexOf('<'); @@ -269,8 +272,9 @@ public abstract class Type { genericDepth--; break; case ';': - if (genericDepth == 0) + if (genericDepth == 0) { endOfSigReached = true; + } break; default: } @@ -312,8 +316,9 @@ public abstract class Type { Type[] types; try { // Read all declarations between for `(' and `)' - if (signature.charAt(0) != '(') + if (signature.charAt(0) != '(') { throw new ClassFormatException("Invalid method signature: " + signature); + } index = 1; // current string position @@ -337,8 +342,9 @@ public abstract class Type { */ public static int getArgumentSizes(String signature) { int size = 0; - if (signature.charAt(0) != '(') + if (signature.charAt(0) != '(') { throw new ClassFormatException("Invalid method signature: " + signature); + } int index = 1; // current string position try { @@ -375,8 +381,9 @@ public abstract class Type { genericDepth--; break; case ';': - if (genericDepth == 0) + if (genericDepth == 0) { endOfSigReached = true; + } break; default: }