aboutsummaryrefslogtreecommitdiffstats
path: root/src/main
diff options
context:
space:
mode:
authorchiba <chiba@30ef5769-5b8d-40dd-aea6-55b5d6557bb3>2009-10-15 10:32:49 +0000
committerchiba <chiba@30ef5769-5b8d-40dd-aea6-55b5d6557bb3>2009-10-15 10:32:49 +0000
commit7cf3a5fce3acfd198867eb0f0aced97d40d83ecb (patch)
tree3e0f9844690f9bedbdf3f2221f12f234fd8adfc7 /src/main
parentc6ec7f23fac10ba8c9afa751b34bb00efd276a1c (diff)
downloadjavassist-7cf3a5fce3acfd198867eb0f0aced97d40d83ecb.tar.gz
javassist-7cf3a5fce3acfd198867eb0f0aced97d40d83ecb.zip
for implementing StackMap attributes (JIRA 95)
git-svn-id: http://anonsvn.jboss.org/repos/javassist/trunk@495 30ef5769-5b8d-40dd-aea6-55b5d6557bb3
Diffstat (limited to 'src/main')
-rw-r--r--src/main/javassist/bytecode/CodeAttribute.java15
-rw-r--r--src/main/javassist/bytecode/MethodInfo.java31
-rw-r--r--src/main/javassist/bytecode/StackMap.java93
-rw-r--r--src/main/javassist/bytecode/stackmap/MapMaker.java59
-rw-r--r--src/main/javassist/bytecode/stackmap/Tracer.java25
5 files changed, 149 insertions, 74 deletions
diff --git a/src/main/javassist/bytecode/CodeAttribute.java b/src/main/javassist/bytecode/CodeAttribute.java
index 0f81ae59..32f69467 100644
--- a/src/main/javassist/bytecode/CodeAttribute.java
+++ b/src/main/javassist/bytecode/CodeAttribute.java
@@ -316,6 +316,21 @@ public class CodeAttribute extends AttributeInfo implements Opcode {
}
/**
+ * Adds a stack map table for J2ME (CLDC). If another copy of stack map table
+ * is already contained, the old one is removed.
+ *
+ * @param smt the stack map table added to this code attribute.
+ * If it is null, a new stack map is not added.
+ * Only the old stack map is removed.
+ * @since 3.12
+ */
+ public void setAttribute(StackMap sm) {
+ AttributeInfo.remove(attributes, StackMapTable.tag);
+ if (sm != null)
+ attributes.add(sm);
+ }
+
+ /**
* Copies code.
*/
private byte[] copyCode(ConstPool destCp, Map classnames,
diff --git a/src/main/javassist/bytecode/MethodInfo.java b/src/main/javassist/bytecode/MethodInfo.java
index eae31e10..6d819371 100644
--- a/src/main/javassist/bytecode/MethodInfo.java
+++ b/src/main/javassist/bytecode/MethodInfo.java
@@ -39,6 +39,13 @@ public final class MethodInfo {
LinkedList attribute; // may be null
/**
+ * If this value is true, Javassist maintains a <code>StackMap</code> attribute
+ * generated by the <code>preverify</code> tool of J2ME (CLDC). The initial
+ * value of this field is <code>false</code>.
+ */
+ public static boolean doPreverify = false;
+
+ /**
* The name of constructors: <code>&lt;init&gt</code>.
*/
public static final String nameInit = "<init>";
@@ -375,11 +382,13 @@ public final class MethodInfo {
/**
* Rebuilds a stack map table if the class file is for Java 6
* or later. Java 5 or older Java VMs do not recognize a stack
- * map table.
+ * map table. If <code>doPreverify</code> is true, this method
+ * also rebuilds a stack map for J2ME (CLDC).
*
* @param pool used for making type hierarchy.
* @param cf rebuild if this class file is for Java 6 or later.
* @see #rebuildStackMap(ClassPool)
+ * @see #rebuildStackMapForME(ClassPool)
* @since 3.6
*/
public void rebuildStackMapIf6(ClassPool pool, ClassFile cf)
@@ -387,6 +396,9 @@ public final class MethodInfo {
{
if (cf.getMajorVersion() >= ClassFile.JAVA_6)
rebuildStackMap(pool);
+
+ if (doPreverify)
+ rebuildStackMapForME(pool);
}
/**
@@ -407,6 +419,23 @@ public final class MethodInfo {
}
/**
+ * Rebuilds a stack map table for J2ME (CLDC). If no stack map table is included,
+ * a new one is created. If this <code>MethodInfo</code> does not
+ * include a code attribute, nothing happens.
+ *
+ * @param pool used for making type hierarchy.
+ * @see StackMapTable
+ * @since 3.12
+ */
+ public void rebuildStackMapForME(ClassPool pool) throws BadBytecode {
+ CodeAttribute ca = getCodeAttribute();
+ if (ca != null) {
+ StackMap sm = MapMaker.make2(pool, this);
+ ca.setAttribute(sm);
+ }
+ }
+
+ /**
* Returns the line number of the source line corresponding to the specified
* bytecode contained in this method.
*
diff --git a/src/main/javassist/bytecode/StackMap.java b/src/main/javassist/bytecode/StackMap.java
index b5748d90..caef3d80 100644
--- a/src/main/javassist/bytecode/StackMap.java
+++ b/src/main/javassist/bytecode/StackMap.java
@@ -15,11 +15,10 @@
package javassist.bytecode;
-import java.io.DataInputStream;
import java.io.ByteArrayOutputStream;
+import java.io.DataInputStream;
import java.io.IOException;
import java.util.Map;
-import javassist.bytecode.stackmap.*;
/**
* Another <code>stack_map</code> attribute defined in CLDC 1.1 for J2ME.
@@ -157,77 +156,45 @@ public class StackMap extends AttributeInfo {
return pos;
}
- int i;
-
- static class NullType extends TypeData.BasicType {
- NullType() {
- super("null", StackMapTable.NULL);
- }
- }
-
- static final NullType nullType = new NullType();
+ /**
+ * Internal use only.
+ */
+ public static class Writer {
+ // see javassist.bytecode.stackmap.MapMaker
- static class Conv extends StackMapTable.Walker {
private ByteArrayOutputStream output;
- private ConstPool pool;
- private int offset;
- private TypedBlock frame;
- // more than one entries must be included!
-
- public Conv(byte[] data, MethodInfo minfo, CodeAttribute ca)
- throws BadBytecode {
- super(data);
+ /**
+ * Constructs a writer.
+ */
+ public Writer() {
output = new ByteArrayOutputStream();
- pool = minfo.getConstPool();
- offset = -1;
- frame = TypedBlock.make(minfo, ca);
- }
-
- private void write16bit(int value) {
- output.write((byte) (value >>> 8));
- output.write((byte) value);
- }
-
- private void writeFrame() {
- int numLocals = frame.numLocals;
- int numStack = frame.stackTop;
- }
-
- private void writeTypes(TypeData[] types, int num) {
- for (int i = 0; i < num; i++) {
- TypeData t = types[i];
- int tag = t.getTypeTag();
- if (t.is2WordType())
- i++;
-
- output.write(tag);
- if (tag == UNINIT) {
- write16bit(t.getTypeData(pool));
- }
- }
- }
-
- public void sameFrame(int pos, int offsetDelta) {
- offset += offsetDelta + 1;
- }
-
- public void sameLocals(int pos, int offsetDelta, int stackTag,
- int stackData) {
- offset += offsetDelta + 1;
}
- public void chopFrame(int pos, int offsetDelta, int k) {
- offset += offsetDelta + 1;
+ /**
+ * Converts to a <code>StackMap</code> attribute.
+ */
+ public StackMap toStackMap(ConstPool cp) {
+ return new StackMap(cp, output.toByteArray());
}
- public void appendFrame(int pos, int offsetDelta, int[] tags, int[] data) {
- offset += offsetDelta + 1;
+ /**
+ * Writes a <code>union verification_type_info</code> value.
+ *
+ * @param data <code>cpool_index</code> or <code>offset</code>.
+ */
+ public void writeVerifyTypeInfo(int tag, int data) {
+ output.write(tag);
+ if (tag == StackMap.OBJECT || tag == StackMap.UNINIT)
+ write16bit(data);
}
- public void fullFrame(int pos, int offsetDelta, int[] localTags,
- int[] localData, int[] stackTags, int[] stackData) {
- offset += offsetDelta + 1;
+ /**
+ * Writes a 16bit value.
+ */
+ public void write16bit(int value) {
+ output.write((value >>> 8) & 0xff);
+ output.write(value & 0xff);
}
}
}
diff --git a/src/main/javassist/bytecode/stackmap/MapMaker.java b/src/main/javassist/bytecode/stackmap/MapMaker.java
index c96073f8..df3300cc 100644
--- a/src/main/javassist/bytecode/stackmap/MapMaker.java
+++ b/src/main/javassist/bytecode/stackmap/MapMaker.java
@@ -97,6 +97,27 @@ public class MapMaker extends Tracer {
return mm.toStackMap(blocks);
}
+ /**
+ * Computes the stack map table for J2ME.
+ * It returns null if the given method does not have to have a
+ * stack map table.
+ */
+ public static StackMap make2(ClassPool classes, MethodInfo minfo)
+ throws BadBytecode
+ {
+ CodeAttribute ca = minfo.getCodeAttribute();
+ if (ca == null)
+ return null;
+
+ TypedBlock[] blocks = TypedBlock.makeBlocks(minfo, ca, true);
+ if (blocks == null)
+ return null;
+
+ MapMaker mm = new MapMaker(classes, minfo, ca);
+ mm.make(blocks, ca.getCode());
+ return mm.toStackMap2(minfo.getConstPool(), blocks);
+ }
+
public MapMaker(ClassPool classes, MethodInfo minfo, CodeAttribute ca) {
super(classes, minfo.getConstPool(),
ca.getMaxStack(), ca.getMaxLocals(),
@@ -441,4 +462,42 @@ public class MapMaker extends Tracer {
return num;
}
+
+ // Phase 3 for J2ME
+
+ public StackMap toStackMap2(ConstPool cp, TypedBlock[] blocks) {
+ StackMap.Writer writer = new StackMap.Writer();
+ int n = blocks.length;
+ int i;
+ if (blocks[0].incoming > 0) // the first instruction is a branch target.
+ i = 1;
+ else
+ i = 0;
+
+ writer.write16bit(n - i);
+ for (; i < n; i++)
+ writeStackFrame(writer, cp, blocks[i].position, blocks[i]);
+
+ return writer.toStackMap(cp);
+ }
+
+ private void writeStackFrame(StackMap.Writer writer, ConstPool cp, int offset, TypedBlock tb) {
+ writer.write16bit(offset);
+ writeVerifyTypeInfo(writer, cp, tb.localsTypes, tb.numLocals);
+ writeVerifyTypeInfo(writer, cp, tb.stackTypes, tb.stackTop);
+ }
+
+ private void writeVerifyTypeInfo(StackMap.Writer writer, ConstPool cp, TypeData[] types, int num) {
+ writer.write16bit(num);
+ for (int i = 0; i < num; i++) {
+ TypeData td = types[i];
+ if (td == TOP)
+ writer.writeVerifyTypeInfo(StackMap.TOP, 0);
+ else {
+ writer.writeVerifyTypeInfo(td.getTypeTag(), td.getTypeData(cp));
+ if (td.is2WordType())
+ i++;
+ }
+ }
+ }
}
diff --git a/src/main/javassist/bytecode/stackmap/Tracer.java b/src/main/javassist/bytecode/stackmap/Tracer.java
index 993ab050..77f56b64 100644
--- a/src/main/javassist/bytecode/stackmap/Tracer.java
+++ b/src/main/javassist/bytecode/stackmap/Tracer.java
@@ -84,7 +84,7 @@ public abstract class Tracer implements TypeTag {
* a stack element has a more specific type, this method updates the
* type of it.
*
- * @pos the position of the instruction.
+ * @param pos the position of the instruction.
* @return the size of the instruction at POS.
*/
protected int doOpcode(int pos, byte[] code) throws BadBytecode {
@@ -699,16 +699,21 @@ public abstract class Tracer implements TypeTag {
doALOAD(index);
break; }
case Opcode.ISTORE :
- return doWIDE_STORE(pos, code, INTEGER);
+ doWIDE_STORE(pos, code, INTEGER);
+ break;
case Opcode.LSTORE :
- return doWIDE_STORE(pos, code, LONG);
+ doWIDE_STORE(pos, code, LONG);
+ break;
case Opcode.FSTORE :
- return doWIDE_STORE(pos, code, FLOAT);
+ doWIDE_STORE(pos, code, FLOAT);
+ break;
case Opcode.DSTORE :
- return doWIDE_STORE(pos, code, DOUBLE);
+ doWIDE_STORE(pos, code, DOUBLE);
+ break;
case Opcode.ASTORE : {
int index = ByteArray.readU16bit(code, pos + 2);
- return doASTORE(index); }
+ doASTORE(index);
+ break; }
case Opcode.IINC :
// this does not call writeLocal().
return 6;
@@ -722,14 +727,14 @@ public abstract class Tracer implements TypeTag {
return 4;
}
- private int doWIDE_XLOAD(int pos, byte[] code, TypeData type) {
+ private void doWIDE_XLOAD(int pos, byte[] code, TypeData type) {
int index = ByteArray.readU16bit(code, pos + 2);
- return doXLOAD(index, type);
+ doXLOAD(index, type);
}
- private int doWIDE_STORE(int pos, byte[] code, TypeData type) {
+ private void doWIDE_STORE(int pos, byte[] code, TypeData type) {
int index = ByteArray.readU16bit(code, pos + 2);
- return doXSTORE(index, type);
+ doXSTORE(index, type);
}
private int doPutField(int pos, byte[] code, boolean notStatic) throws BadBytecode {