import javassist.CtClass;
import javassist.CtPrimitiveType;
+class ByteVector implements Cloneable {
+ private byte[] buffer;
+ private int size;
+
+ public ByteVector() {
+ buffer = new byte[64];
+ size = 0;
+ }
+
+ public Object clone() throws CloneNotSupportedException {
+ ByteVector bv = (ByteVector)super.clone();
+ bv.buffer = (byte[])buffer.clone();
+ return bv;
+ }
+
+ public final int getSize() { return size; }
+
+ public final byte[] copy() {
+ byte[] b = new byte[size];
+ arraycopy(buffer, b, size);
+ return b;
+ }
+
+ public int read(int offset) {
+ if (offset < 0 || size <= offset)
+ throw new ArrayIndexOutOfBoundsException(offset);
+
+ return buffer[offset];
+ }
+
+ public void write(int offset, int value) {
+ if (offset < 0 || size <= offset)
+ throw new ArrayIndexOutOfBoundsException(offset);
+
+ buffer[offset] = (byte)value;
+ }
+
+ public void add(int code) {
+ addGap(1);
+ buffer[size - 1] = (byte)code;
+ }
+
+ public void addGap(int length) {
+ if (size + length > buffer.length) {
+ int newSize = size << 1;
+ if (newSize < size + length)
+ newSize = size + length;
+
+ byte[] newBuf = new byte[newSize];
+ arraycopy(buffer, newBuf, size);
+ buffer = newBuf;
+ }
+
+ size += length;
+ }
+
+ private static void arraycopy(byte[] src, byte[] dest, int size) {
+ for (int i = 0; i < size; i++)
+ dest[i] = src[i];
+ }
+}
+
/**
* A utility class for producing a bytecode sequence.
*
* @see ConstPool
* @see CodeAttribute
*/
-public class Bytecode implements Opcode {
+public class Bytecode extends ByteVector implements Cloneable, Opcode {
/**
* Represents the <code>CtClass</code> file using the
* constant pool table given to this <code>Bytecode</code> object.
*/
public static final CtClass THIS = ConstPool.THIS;
- static final int bufsize = 64;
ConstPool constPool;
int maxStack, maxLocals;
ExceptionTable tryblocks;
- Bytecode next;
- byte[] buffer;
- int num;
-
private int stackDepth;
/**
* @param localvars <code>max_locals</code>.
*/
public Bytecode(ConstPool cp, int stacksize, int localvars) {
- this();
constPool = cp;
maxStack = stacksize;
maxLocals = localvars;
this(cp, 0, 0);
}
- /* used in add().
+ /**
+ * Creates and returns a copy of this object.
+ * The constant pool object is shared between this object
+ * and the cloned object.
*/
- private Bytecode() {
- buffer = new byte[bufsize];
- num = 0;
- next = null;
+ public Object clone() {
+ try {
+ Bytecode bc = (Bytecode)super.clone();
+ bc.tryblocks = (ExceptionTable)tryblocks.clone();
+ return bc;
+ }
+ catch (CloneNotSupportedException cnse) {
+ throw new RuntimeException(cnse);
+ }
}
/**
* Returns the length of the bytecode sequence.
*/
public int length() {
- int len = 0;
- Bytecode b = this;
- while (b != null) {
- len += b.num;
- b = b.next;
- }
-
- return len;
- }
-
- private void copy(byte[] dest, int index) {
- Bytecode b = this;
- while (b != null) {
- System.arraycopy(b.buffer, 0, dest, index, b.num);
- index += b.num;
- b = b.next;
- }
+ return getSize();
}
/**
* Returns the produced bytecode sequence.
*/
public byte[] get() {
- byte[] b = new byte[length()];
- copy(b, 0);
- return b;
+ return copy();
}
/**
* that have been added so far.
*/
public int currentPc() {
- int n = 0;
- Bytecode b = this;
- while (b != null) {
- n += b.num;
- b = b.next;
- }
-
- return n;
+ return getSize();
}
/**
* @throws ArrayIndexOutOfBoundsException if offset is invalid.
*/
public int read(int offset) {
- if (offset < 0)
- return Opcode.NOP;
- else if (offset < num)
- return buffer[offset];
- else
- try {
- return next.read(offset - num);
- }
- catch (NullPointerException e) {
- throw new ArrayIndexOutOfBoundsException(offset);
- }
+ return super.read(offset);
}
/**
* @throws ArrayIndexOutOfBoundsException if offset is invalid.
*/
public void write(int offset, int value) {
- if (offset < num)
- buffer[offset] = (byte)value;
- else
- try {
- next.write(offset - num, value);
- }
- catch (NullPointerException e) {
- throw new ArrayIndexOutOfBoundsException(offset);
- }
+ super.write(offset, value);
}
/**
* Appends an 8bit value to the end of the bytecode sequence.
*/
public void add(int code) {
- if (num < bufsize)
- buffer[num++] = (byte)code;
- else {
- if (next == null)
- next = new Bytecode();
-
- next.add(code);
- }
+ super.add(code);
}
/**
* @param length the gap length in byte.
*/
public void addGap(int length) {
- if (num < bufsize) {
- num += length;
- if (num <= bufsize)
- return;
- else {
- length = num - bufsize;
- num = bufsize;
- }
- }
-
- if (next == null)
- next = new Bytecode();
-
- next.addGap(length);
+ super.addGap(length);
}
/**
package javassist.bytecode;
final class LongVector {
- static final int SIZE = 128;
- private int num;
- private Object[] objects;
- private LongVector next;
+ static final int ASIZE = 128;
+ static final int ABITS = 7; // ASIZE = 2^ABITS
+ static final int VSIZE = 8;
+ private Object[][] objects;
+ private int elements;
public LongVector() {
- this(SIZE);
+ objects = new Object[VSIZE][];
+ elements = 0;
}
public LongVector(int initialSize) {
- num = 0;
- objects = new Object[initialSize];
- next = null;
+ int vsize = ((initialSize >> ABITS) & ~(VSIZE - 1)) + VSIZE;
+ objects = new Object[vsize][];
+ elements = 0;
}
- public void addElement(Object obj) {
- LongVector p = this;
- while (p.next != null)
- p = p.next;
+ public int size() { return elements; }
- if (p.num < p.objects.length)
- p.objects[p.num++] = obj;
- else {
- LongVector q = p.next = new LongVector(SIZE);
- q.objects[q.num++] = obj;
- }
- }
-
- public int size() {
- LongVector p = this;
- int s = 0;
- while (p != null) {
- s += p.num;
- p = p.next;
- }
-
- return s;
- }
+ public int capacity() { return objects.length * ASIZE; }
public Object elementAt(int i) {
- LongVector p = this;
- while (p != null)
- if (i < p.num)
- return p.objects[i];
- else {
- i -= p.num;
- p = p.next;
- }
+ if (i < 0 || elements <= i)
+ return null;
- return null;
+ return objects[i >> ABITS][i & (ASIZE - 1)];
}
-/*
- public static void main(String [] args) {
- LongVector v = new LongVector(4);
- int i;
- for (i = 0; i < 128; ++i)
- v.addElement(new Integer(i));
-
- System.out.println(v.size());
- for (i = 0; i < v.size(); ++i) {
- System.out.print(v.elementAt(i));
- System.out.print(", ");
+ public void addElement(Object value) {
+ int nth = elements >> ABITS;
+ int offset = elements & (ASIZE - 1);
+ int len = objects.length;
+ if (nth >= len) {
+ Object[][] newObj = new Object[len + VSIZE][];
+ System.arraycopy(objects, 0, newObj, 0, len);
+ objects = newObj;
}
+
+ if (objects[nth] == null)
+ objects[nth] = new Object[ASIZE];
+
+ objects[nth][offset] = value;
+ elements++;
}
-*/
}