diff options
author | chiba <chiba@30ef5769-5b8d-40dd-aea6-55b5d6557bb3> | 2009-10-15 10:32:49 +0000 |
---|---|---|
committer | chiba <chiba@30ef5769-5b8d-40dd-aea6-55b5d6557bb3> | 2009-10-15 10:32:49 +0000 |
commit | 7cf3a5fce3acfd198867eb0f0aced97d40d83ecb (patch) | |
tree | 3e0f9844690f9bedbdf3f2221f12f234fd8adfc7 /src/main | |
parent | c6ec7f23fac10ba8c9afa751b34bb00efd276a1c (diff) | |
download | javassist-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.java | 15 | ||||
-rw-r--r-- | src/main/javassist/bytecode/MethodInfo.java | 31 | ||||
-rw-r--r-- | src/main/javassist/bytecode/StackMap.java | 93 | ||||
-rw-r--r-- | src/main/javassist/bytecode/stackmap/MapMaker.java | 59 | ||||
-rw-r--r-- | src/main/javassist/bytecode/stackmap/Tracer.java | 25 |
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><init></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 { |