Browse Source

optimization

tags/V1_6_7
aclement 14 years ago
parent
commit
9b9952cc69
21 changed files with 837 additions and 659 deletions
  1. 23
    12
      bcel-builder/src/org/aspectj/apache/bcel/classfile/Code.java
  2. 62
    59
      bcel-builder/src/org/aspectj/apache/bcel/generic/BranchHandle.java
  3. 43
    38
      bcel-builder/src/org/aspectj/apache/bcel/generic/FieldInstruction.java
  4. 4
    15
      bcel-builder/src/org/aspectj/apache/bcel/generic/FieldOrMethod.java
  5. 51
    38
      bcel-builder/src/org/aspectj/apache/bcel/generic/IINC.java
  6. 56
    39
      bcel-builder/src/org/aspectj/apache/bcel/generic/INVOKEINTERFACE.java
  7. 65
    48
      bcel-builder/src/org/aspectj/apache/bcel/generic/Instruction.java
  8. 2
    2
      bcel-builder/src/org/aspectj/apache/bcel/generic/InstructionBranch.java
  9. 12
    0
      bcel-builder/src/org/aspectj/apache/bcel/generic/InstructionByte.java
  10. 38
    29
      bcel-builder/src/org/aspectj/apache/bcel/generic/InstructionCP.java
  11. 14
    29
      bcel-builder/src/org/aspectj/apache/bcel/generic/InstructionHandle.java
  12. 13
    1
      bcel-builder/src/org/aspectj/apache/bcel/generic/InstructionLV.java
  13. 73
    63
      bcel-builder/src/org/aspectj/apache/bcel/generic/InstructionList.java
  14. 25
    37
      bcel-builder/src/org/aspectj/apache/bcel/generic/InstructionSelect.java
  15. 17
    5
      bcel-builder/src/org/aspectj/apache/bcel/generic/InstructionShort.java
  16. 62
    57
      bcel-builder/src/org/aspectj/apache/bcel/generic/InvokeInstruction.java
  17. 23
    21
      bcel-builder/src/org/aspectj/apache/bcel/generic/LocalVariableTag.java
  18. 121
    99
      bcel-builder/src/org/aspectj/apache/bcel/generic/MULTIANEWARRAY.java
  19. 102
    55
      bcel-builder/src/org/aspectj/apache/bcel/generic/MethodGen.java
  20. 16
    4
      bcel-builder/src/org/aspectj/apache/bcel/generic/RET.java
  21. 15
    8
      bcel-builder/src/org/aspectj/apache/bcel/generic/Type.java

+ 23
- 12
bcel-builder/src/org/aspectj/apache/bcel/classfile/Code.java View File

@@ -68,7 +68,7 @@ import org.aspectj.apache.bcel.Constants;
* This attribute has attributes itself, namely <em>LineNumberTable</em> which is used for debugging purposes and
* <em>LocalVariableTable</em> 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 <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A>
* @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");
}

+ 62
- 59
bcel-builder/src/org/aspectj/apache/bcel/generic/BranchHandle.java View File

@@ -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 <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A>
* @version $Id: BranchHandle.java,v 1.5 2009/10/05 17:35:36 aclement Exp $
* @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A>
*/
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;
}
}


+ 43
- 38
bcel-builder/src/org/aspectj/apache/bcel/generic/FieldInstruction.java View File

@@ -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 <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A>
*
* @version $Id: FieldInstruction.java,v 1.7 2009/10/05 17:35:36 aclement Exp $
* @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A>
*/
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);
}
}

+ 4
- 15
bcel-builder/src/org/aspectj/apache/bcel/generic/FieldOrMethod.java View File

@@ -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 <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A>
*/
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;
}

+ 51
- 38
bcel-builder/src/org/aspectj/apache/bcel/generic/IINC.java View File

@@ -53,56 +53,69 @@ package org.aspectj.apache.bcel.generic;
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*/
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 <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A>
*
* @version $Id: IINC.java,v 1.5 2009/10/05 17:35:36 aclement Exp $
* @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A>
*/
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);
}

}

+ 56
- 39
bcel-builder/src/org/aspectj/apache/bcel/generic/INVOKEINTERFACE.java View File

@@ -53,58 +53,75 @@ package org.aspectj.apache.bcel.generic;
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*/
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
* <PRE>Stack: ..., objectref, [arg1, [arg2 ...]] -&gt; ...</PRE>
*
* @version $Id: INVOKEINTERFACE.java,v 1.3 2008/05/28 23:52:58 aclement Exp $
* @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A>
*
* <PRE>
* Stack: ..., objectref, [arg1, [arg2 ...]] -&gt; ...
* </PRE>
*
* @version $Id: INVOKEINTERFACE.java,v 1.4 2009/10/05 17:35:36 aclement Exp $
* @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A>
*/
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 <B>count</B> argument according to the Java Language Specification, Second Edition.
*/
public int getCount() {
return nargs;
}

/**
* The <B>count</B> 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);
}

}

+ 65
- 48
bcel-builder/src/org/aspectj/apache/bcel/generic/Instruction.java View File

@@ -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 <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A>
*/
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;

+ 2
- 2
bcel-builder/src/org/aspectj/apache/bcel/generic/InstructionBranch.java View File

@@ -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 <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A>
*/
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));

+ 12
- 0
bcel-builder/src/org/aspectj/apache/bcel/generic/InstructionByte.java View File

@@ -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;
}
}

+ 38
- 29
bcel-builder/src/org/aspectj/apache/bcel/generic/InstructionCP.java View File

@@ -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 <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A>
*/
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;
}

}

+ 14
- 29
bcel-builder/src/org/aspectj/apache/bcel/generic/InstructionHandle.java View File

@@ -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 <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A>
* @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<InstructionTargeter> 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<InstructionTargeter> 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() {

+ 13
- 1
bcel-builder/src/org/aspectj/apache/bcel/generic/InstructionLV.java View File

@@ -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 <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A>
*/
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;
}

}

+ 73
- 63
bcel-builder/src/org/aspectj/apache/bcel/generic/InstructionList.java View File

@@ -76,7 +76,7 @@ import org.aspectj.apache.bcel.util.ByteSequence;
*
* A list is finally dumped to a byte code array with <a href="#getByteCode()">getByteCode</a>.
*
* @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 <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A>
* @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 <B>first</B> 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 <B>first</B> 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.
*

+ 25
- 37
bcel-builder/src/org/aspectj/apache/bcel/generic/InstructionSelect.java View File

@@ -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 <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A>
* @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
*/

+ 17
- 5
bcel-builder/src/org/aspectj/apache/bcel/generic/InstructionShort.java View File

@@ -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;
}

}

+ 62
- 57
bcel-builder/src/org/aspectj/apache/bcel/generic/InvokeInstruction.java View File

@@ -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 <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A>
*
* @version $Id: InvokeInstruction.java,v 1.6 2009/10/05 17:35:36 aclement Exp $
* @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A>
*/
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));
}
}

+ 23
- 21
bcel-builder/src/org/aspectj/apache/bcel/generic/LocalVariableTag.java View File

@@ -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;

+ 121
- 99
bcel-builder/src/org/aspectj/apache/bcel/generic/MULTIANEWARRAY.java View File

@@ -53,109 +53,131 @@ package org.aspectj.apache.bcel.generic;
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*/
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
* <PRE>Stack: ..., count1, [count2, ...] -&gt; ..., arrayref</PRE>
*
* @version $Id: MULTIANEWARRAY.java,v 1.3 2008/05/28 23:52:59 aclement Exp $
* @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A>
*
* <PRE>
* Stack: ..., count1, [count2, ...] -&gt; ..., arrayref
* </PRE>
*
* @version $Id: MULTIANEWARRAY.java,v 1.4 2009/10/05 17:35:36 aclement Exp $
* @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A>
*/
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);
}
}

+ 102
- 55
bcel-builder/src/org/aspectj/apache/bcel/generic/MethodGen.java View File

@@ -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 <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A>
* @author <A HREF="http://www.vmeng.com/beard">Patrick C. Beard</A> [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<AnnotationGen> 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<Attribute> 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<InstructionHandle, BranchTarget> visitedTargets = new Hashtable<InstructionHandle, BranchTarget>();

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<String> e = exceptionsThrown.iterator(); e.hasNext();)
for (Iterator<String> 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;
}


+ 16
- 4
bcel-builder/src/org/aspectj/apache/bcel/generic/RET.java View File

@@ -66,12 +66,12 @@ import org.aspectj.apache.bcel.classfile.ConstantPool;
* Stack: ..., -&gt; ..., address
* </PRE>
*
* @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 <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A>
*/
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;
}

}

+ 15
- 8
bcel-builder/src/org/aspectj/apache/bcel/generic/Type.java View File

@@ -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 <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A>
*
* 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:
}

Loading…
Cancel
Save