[jboss-cvs] javassist/src/main/javassist/bytecode ...
Shigeru Chiba
chiba at is.titech.ac.jp
Thu May 1 06:47:58 EDT 2008
User: chiba
Date: 08/05/01 06:47:58
Modified: src/main/javassist/bytecode StackMapTable.java
LocalVariableAttribute.java CodeAttribute.java
Descriptor.java
Log:
fixed JASSIST-47 and 60.
Revision Changes Path
1.13 +88 -0 javassist/src/main/javassist/bytecode/StackMapTable.java
(In the diff below, changes in quantity of whitespace are not shown.)
Index: StackMapTable.java
===================================================================
RCS file: /cvsroot/jboss/javassist/src/main/javassist/bytecode/StackMapTable.java,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -b -r1.12 -r1.13
--- StackMapTable.java 15 Apr 2008 07:39:24 -0000 1.12
+++ StackMapTable.java 1 May 2008 10:47:58 -0000 1.13
@@ -425,6 +425,94 @@
}
/**
+ * Updates this stack map table when a new local variable is added.
+ *
+ * @param index the index of the added local variable.
+ * @param tag the type tag of that local variable.
+ * @param classInfo the index of the <code>CONSTANT_Class_info</code> structure
+ * in a constant pool table. This should be zero unless the tag
+ * is <code>ITEM_Object</code>.
+ *
+ * @see #typeTagOf(char)
+ * @see ConstPool
+ */
+ public void insertLocal(int index, int tag, int classInfo)
+ throws BadBytecode
+ {
+ byte[] data = new InsertLocal(this.get(), index, tag, classInfo).doit();
+ this.set(data);
+ }
+
+ /**
+ * Returns the tag of the type specified by the
+ * descriptor. This method returns <code>INTEGER</code>
+ * unless the descriptor is either D (double), F (float),
+ * J (long), L (class type), or [ (array).
+ *
+ * @param descriptor the type descriptor.
+ * @see Descriptor
+ */
+ public static int typeTagOf(char descriptor) {
+ switch (descriptor) {
+ case 'D' :
+ return DOUBLE;
+ case 'F' :
+ return FLOAT;
+ case 'J' :
+ return LONG;
+ case 'L' :
+ case '[' :
+ return OBJECT;
+ // case 'V' :
+ default :
+ return INTEGER;
+ }
+ }
+
+ static class InsertLocal extends SimpleCopy {
+ private int varIndex;
+ private int varTag, varData;
+
+ public InsertLocal(byte[] data, int varIndex, int varTag, int varData) {
+ super(data);
+ this.varIndex = varIndex;
+ this.varTag = varTag;
+ this.varData = varData;
+ }
+
+ public void fullFrame(int pos, int offsetDelta, int[] localTags, int[] localData,
+ int[] stackTags, int[] stackData) {
+ int len = localTags.length;
+ if (len < varIndex) {
+ super.fullFrame(pos, offsetDelta, localTags, localData, stackTags, stackData);
+ return;
+ }
+
+ int typeSize = (varTag == LONG || varTag == DOUBLE) ? 2 : 1;
+ int[] localTags2 = new int[len + typeSize];
+ int[] localData2 = new int[len + typeSize];
+ int index = varIndex;
+ int j = 0;
+ for (int i = 0; i < len; i++) {
+ if (j == index)
+ j += typeSize;
+
+ localTags2[j] = localTags[i];
+ localData2[j++] = localData[i];
+ }
+
+ localTags2[index] = varTag;
+ localData2[index] = varData;
+ if (typeSize > 1) {
+ localTags2[index + 1] = TOP;
+ localData2[index + 1] = 0;
+ }
+
+ super.fullFrame(pos, offsetDelta, localTags2, localData2, stackTags, stackData);
+ }
+ }
+
+ /**
* A writer of stack map tables.
*/
public static class Writer {
1.12 +16 -0 javassist/src/main/javassist/bytecode/LocalVariableAttribute.java
(In the diff below, changes in quantity of whitespace are not shown.)
Index: LocalVariableAttribute.java
===================================================================
RCS file: /cvsroot/jboss/javassist/src/main/javassist/bytecode/LocalVariableAttribute.java,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -b -r1.11 -r1.12
--- LocalVariableAttribute.java 13 Aug 2007 09:06:31 -0000 1.11
+++ LocalVariableAttribute.java 1 May 2008 10:47:58 -0000 1.12
@@ -92,6 +92,22 @@
}
/**
+ * For each <code>local_variable_table[i].index</code>,
+ * this method increases <code>index</code> by <code>delta</code>.
+ *
+ * @param lessThan the index does not change if it
+ * is less than this value.
+ */
+ public void shiftIndex(int lessThan, int delta) {
+ int size = info.length;
+ for (int i = 2; i < size; i += 10){
+ int org = ByteArray.readU16bit(info, i + 8);
+ if (org >= lessThan)
+ ByteArray.write16bit(org + delta, info, i + 8);
+ }
+ }
+
+ /**
* Returns <code>local_variable_table_length</code>.
* This represents the number of entries in the table.
*/
1.15 +144 -15 javassist/src/main/javassist/bytecode/CodeAttribute.java
(In the diff below, changes in quantity of whitespace are not shown.)
Index: CodeAttribute.java
===================================================================
RCS file: /cvsroot/jboss/javassist/src/main/javassist/bytecode/CodeAttribute.java,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -b -r1.14 -r1.15
--- CodeAttribute.java 14 Nov 2007 08:39:42 -0000 1.14
+++ CodeAttribute.java 1 May 2008 10:47:58 -0000 1.15
@@ -395,9 +395,8 @@
newcode[i] = (byte)(index >> 8);
newcode[i + 1] = (byte)index;
}
-}
-final class LdcEntry {
+ static class LdcEntry {
LdcEntry next;
int where;
int index;
@@ -416,4 +415,134 @@
return code;
}
+ }
+
+ /**
+ * Changes the index numbers of the local variables
+ * to append a new parameter.
+ * This method does not update <code>LocalVariableAttribute</code>
+ * or <code>StackMapTable</code>. These attributes must be
+ * explicitly updated.
+ *
+ * @param where the index of the new parameter.
+ * @param size the type size of the new parameter (1 or 2).
+ *
+ * @see LocalVariableAttribute#shiftIndex(int, int)
+ * @see StackMapTable#insertLocal(int, int, int)
+ */
+ public void insertLocalVar(int where, int size) throws BadBytecode {
+ CodeIterator ci = iterator();
+ while (ci.hasNext())
+ shiftIndex(ci, where, size);
+
+ setMaxLocals(getMaxLocals() + size);
+ }
+
+ /**
+ * @param lessThan If the index of the local variable is
+ * less than this value, it does not change.
+ * Otherwise, the index is increased.
+ * @param delta the indexes of the local variables are
+ * increased by this value.
+ */
+ private static void shiftIndex(CodeIterator ci, int lessThan, int delta) throws BadBytecode {
+ int index = ci.next();
+ int opcode = ci.byteAt(index);
+ if (opcode < ILOAD)
+ return;
+ else if (opcode < IASTORE) {
+ if (opcode < ILOAD_0) {
+ // iload, lload, fload, dload, aload
+ shiftIndex8(ci, index, opcode, lessThan, delta);
+ }
+ else if (opcode < IALOAD) {
+ // iload_0, ..., aload_3
+ shiftIndex0(ci, index, opcode, lessThan, delta, ILOAD_0, ILOAD);
+ }
+ else if (opcode < ISTORE)
+ return;
+ else if (opcode < ISTORE_0) {
+ // istore, lstore, ...
+ shiftIndex8(ci, index, opcode, lessThan, delta);
+ }
+ else {
+ // istore_0, ..., astore_3
+ shiftIndex0(ci, index, opcode, lessThan, delta, ISTORE_0, ISTORE);
+ }
+ }
+ else if (opcode == IINC) {
+ int var = ci.byteAt(index + 1);
+ if (var < lessThan)
+ return;
+
+ var += delta;
+ if (var < 0x100)
+ ci.writeByte(var, index + 1);
+ else {
+ int plus = ci.byteAt(index + 2);
+ ci.insertExGap(3);
+ ci.writeByte(WIDE, index);
+ ci.writeByte(IINC, index + 1);
+ ci.write16bit(var, index + 2);
+ ci.write16bit(plus, index + 4);
+ }
+ }
+ else if (opcode == RET)
+ shiftIndex8(ci, index, opcode, lessThan, delta);
+ else if (opcode == WIDE) {
+ int var = ci.u16bitAt(index + 2);
+ if (var < lessThan)
+ return;
+
+ var += delta;
+ ci.write16bit(var, index + 2);
+ }
+ }
+
+ private static void shiftIndex8(CodeIterator ci, int index, int opcode,
+ int lessThan, int delta)
+ throws BadBytecode
+ {
+ int var = ci.byteAt(index + 1);
+ if (var < lessThan)
+ return;
+
+ var += delta;
+ if (var < 0x100)
+ ci.writeByte(var, index + 1);
+ else {
+ ci.insertExGap(2);
+ ci.writeByte(WIDE, index);
+ ci.writeByte(opcode, index + 1);
+ ci.write16bit(var, index + 2);
+ }
+ }
+
+ private static void shiftIndex0(CodeIterator ci, int index, int opcode,
+ int lessThan, int delta,
+ int opcode_i_0, int opcode_i)
+ throws BadBytecode
+ {
+ int var = (opcode - opcode_i_0) % 4;
+ if (var < lessThan)
+ return;
+
+ var += delta;
+ if (var < 4)
+ ci.writeByte(opcode + delta, index);
+ else {
+ opcode = (opcode - opcode_i_0) / 4 + opcode_i;
+ if (var < 0x100) {
+ ci.insertExGap(1);
+ ci.writeByte(opcode, index);
+ ci.writeByte(var, index + 1);
+ }
+ else {
+ ci.insertExGap(3);
+ ci.writeByte(WIDE, index);
+ ci.writeByte(opcode, index + 1);
+ ci.write16bit(var, index + 2);
+ }
+ }
+ }
}
1.22 +37 -0 javassist/src/main/javassist/bytecode/Descriptor.java
(In the diff below, changes in quantity of whitespace are not shown.)
Index: Descriptor.java
===================================================================
RCS file: /cvsroot/jboss/javassist/src/main/javassist/bytecode/Descriptor.java,v
retrieving revision 1.21
retrieving revision 1.22
diff -u -b -r1.21 -r1.22
--- Descriptor.java 4 Jun 2007 03:11:09 -0000 1.21
+++ Descriptor.java 1 May 2008 10:47:58 -0000 1.22
@@ -353,6 +353,43 @@
}
/**
+ * Appends a parameter type to the parameter list represented
+ * by the given descriptor. The appended parameter becomes
+ * the last parameter.
+ *
+ * @param type the type of the appended parameter.
+ * @param desc descriptor
+ */
+ public static String appendParameter(CtClass type, String descriptor) {
+ int i = descriptor.indexOf(')');
+ if (i < 0)
+ return descriptor;
+ else {
+ StringBuffer newdesc = new StringBuffer();
+ newdesc.append(descriptor.substring(0, i));
+ toDescriptor(newdesc, type);
+ newdesc.append(descriptor.substring(i));
+ return newdesc.toString();
+ }
+ }
+
+ /**
+ * Inserts a parameter type at the beginning of the parameter
+ * list represented
+ * by the given descriptor.
+ *
+ * @param type the type of the inserted parameter.
+ * @param descriptor the descriptor of the method.
+ */
+ public static String insertParameter(CtClass type,
+ String descriptor) {
+ if (descriptor.charAt(0) != '(')
+ return descriptor;
+ else
+ return "(" + of(type) + descriptor.substring(1);
+ }
+
+ /**
* Changes the return type included in the given descriptor.
*
* <p><code>classname</code> must not be an array type.
More information about the jboss-cvs-commits
mailing list