diff options
author | chiba <chiba@30ef5769-5b8d-40dd-aea6-55b5d6557bb3> | 2007-05-29 03:51:47 +0000 |
---|---|---|
committer | chiba <chiba@30ef5769-5b8d-40dd-aea6-55b5d6557bb3> | 2007-05-29 03:51:47 +0000 |
commit | 2cecffb9c750eeb468700e90a00710821ad534c3 (patch) | |
tree | 7c6dfb8e1ee17a43344953e3061c7243ec2023c3 /src/main | |
parent | f57f2a7450beac7f29b7287ed27f4ff32b8ed3dc (diff) | |
download | javassist-2cecffb9c750eeb468700e90a00710821ad534c3.tar.gz javassist-2cecffb9c750eeb468700e90a00710821ad534c3.zip |
fixed bugs of javassist.bytecode.stackmap
git-svn-id: http://anonsvn.jboss.org/repos/javassist/trunk@375 30ef5769-5b8d-40dd-aea6-55b5d6557bb3
Diffstat (limited to 'src/main')
5 files changed, 73 insertions, 23 deletions
diff --git a/src/main/javassist/bytecode/stackmap/Liveness.java b/src/main/javassist/bytecode/stackmap/Liveness.java index 8676b969..a086e0cc 100644 --- a/src/main/javassist/bytecode/stackmap/Liveness.java +++ b/src/main/javassist/bytecode/stackmap/Liveness.java @@ -60,6 +60,7 @@ public class Liveness { private void computeLiveness1(TypedBlock tb) { if (tb.updating) { + // a loop was detected. computeLiveness1u(tb); return; } @@ -193,12 +194,12 @@ public class Liveness { boolean changed = false; for (int i = 0; i < n; i++) { TypedBlock tb = blocks[i]; - if (tb.status == DONE) - tb.status = NOT_YET; - else { + if (tb.status == CHANGED_NOW) { tb.status = CHANGED_LAST; changed = true; } + else + tb.status = NOT_YET; } return changed; diff --git a/src/main/javassist/bytecode/stackmap/MapMaker.java b/src/main/javassist/bytecode/stackmap/MapMaker.java index 17725903..7dabbf65 100644 --- a/src/main/javassist/bytecode/stackmap/MapMaker.java +++ b/src/main/javassist/bytecode/stackmap/MapMaker.java @@ -114,6 +114,7 @@ public class MapMaker extends Tracer { throws BadBytecode { TypedBlock first = blocks[0]; + fixParamTypes(first); TypeData[] srcTypes = first.localsTypes; copyFrom(srcTypes.length, srcTypes, this.localsTypes); make(code, first); @@ -123,6 +124,26 @@ public class MapMaker extends Tracer { evalExpected(blocks[i]); } + /* + * If a parameter type is String but it is used only as Object + * within the method body, this MapMaker class will report its type + * is Object. To avoid this, fixParamTypes calls TypeData.setType() + * on each parameter type. + */ + private void fixParamTypes(TypedBlock first) throws BadBytecode { + TypeData[] types = first.localsTypes; + int n = types.length; + for (int i = 0; i < n; i++) { + TypeData t = types[i]; + if (t instanceof TypeData.ClassName) { + /* Skip the following statement if t.isNullType() is true + * although a parameter type is never null type. + */ + TypeData.setType(t, t.getName(), classPool); + } + } + } + // Phase 1 private void make(byte[] code, TypedBlock tb) @@ -283,7 +304,6 @@ public class MapMaker extends Tracer { } else offsetDelta += bb.length; - } return writer.toStackMapTable(cpool); diff --git a/src/main/javassist/bytecode/stackmap/Tracer.java b/src/main/javassist/bytecode/stackmap/Tracer.java index bae3ae16..8142f103 100644 --- a/src/main/javassist/bytecode/stackmap/Tracer.java +++ b/src/main/javassist/bytecode/stackmap/Tracer.java @@ -307,7 +307,7 @@ public abstract class Tracer implements TypeTag { return 2; } - private int doOpcode54_95(int pos, byte[] code, int op) { + private int doOpcode54_95(int pos, byte[] code, int op) throws BadBytecode { TypeData[] localsTypes = this.localsTypes; TypeData[] stackTypes = this.stackTypes; switch (op) { @@ -366,11 +366,18 @@ public abstract class Tracer implements TypeTag { case Opcode.LASTORE : case Opcode.FASTORE : case Opcode.DASTORE : + stackTop -= (op == Opcode.LASTORE || op == Opcode.DASTORE) ? 4 : 3; + break; case Opcode.AASTORE : + TypeData.setType(stackTypes[stackTop - 1], + TypeData.ArrayElement.getElementType(stackTypes[stackTop - 3].getName()), + classPool); + stackTop -= 3; + break; case Opcode.BASTORE : case Opcode.CASTORE : case Opcode.SASTORE : - stackTop -= (op == Opcode.LASTORE || op == Opcode.DASTORE) ? 4 : 3; + stackTop -= 3; break; case Opcode.POP : stackTop--; @@ -437,7 +444,6 @@ public abstract class Tracer implements TypeTag { stackTop--; // implicit upcast might be done. localsTypes[index] = stackTypes[stackTop].copy(); - return 2; } @@ -632,6 +638,7 @@ public abstract class Tracer implements TypeTag { = new TypeData.ClassName(type); return 3; } case Opcode.ARRAYLENGTH : + TypeData.setType(stackTypes[stackTop - 1], "[Ljava.lang.Object;", classPool); stackTypes[stackTop - 1] = INTEGER; break; case Opcode.ATHROW : @@ -639,17 +646,18 @@ public abstract class Tracer implements TypeTag { visitThrow(pos, code); break; case Opcode.CHECKCAST : { - // TypeData.setType(stackData[stackTop - 1], "java.lang.Object", classPool); + // TypeData.setType(stackTypes[stackTop - 1], "java.lang.Object", classPool); int i = ByteArray.readU16bit(code, pos + 1); stackTypes[stackTop - 1] = new TypeData.ClassName(cpool.getClassInfo(i)); return 3; } case Opcode.INSTANCEOF : - // TypeData.setType(stackData[stackTop - 1], "java.lang.Object", classPool); + // TypeData.setType(stackTypes[stackTop - 1], "java.lang.Object", classPool); stackTypes[stackTop - 1] = INTEGER; return 3; case Opcode.MONITORENTER : case Opcode.MONITOREXIT : stackTop--; + // TypeData.setType(stackTypes[stackTop], "java.lang.Object", classPool); break; case Opcode.WIDE : return doWIDE(pos, code); diff --git a/src/main/javassist/bytecode/stackmap/TypeData.java b/src/main/javassist/bytecode/stackmap/TypeData.java index 804264a0..6c073702 100644 --- a/src/main/javassist/bytecode/stackmap/TypeData.java +++ b/src/main/javassist/bytecode/stackmap/TypeData.java @@ -209,20 +209,20 @@ public abstract class TypeData { return; ArrayList equiv = this.equivalences; - String name = this.expectedName; int n = equiv.size(); - for (int i = 0; i < n; i++) { - TypeData td = (TypeData)equiv.get(i); - if (td instanceof TypeName) { - TypeName tn = (TypeName)td; - if (update(cp, name, tn.expectedName)) - name = tn.expectedName; + String name = evalExpectedType2(equiv, n); + if (name == null) { + name = this.expectedName; + for (int i = 0; i < n; i++) { + TypeData td = (TypeData)equiv.get(i); + if (td instanceof TypeName) { + TypeName tn = (TypeName)td; + if (update(cp, name, tn.expectedName)) + name = tn.expectedName; + } } } - if (name == null) - name = evalExpectedType2(equivalences, n); - for (int i = 0; i < n; i++) { TypeData td = (TypeData)equiv.get(i); if (td instanceof TypeName) { @@ -257,6 +257,14 @@ public abstract class TypeData { return true; else if (oldName.equals(typeName)) return false; + else if (typeName.charAt(0) == '[' + && oldName.equals("[Ljava.lang.Object;")) { + /* this rule is not correct but Tracer class sets the type + of the operand of arraylength to java.lang.Object[]. + Thus, int[] etc. must be a subtype of java.lang.Object[]. + */ + return true; + } try { if (cache == null) @@ -365,10 +373,10 @@ public abstract class TypeData { public String getExpected() throws BadBytecode { String en = expectedName; if (en == null) { - ArrayList equiv = equivalences; - if (equiv.size() == 1) - return getName(); - else + // ArrayList equiv = equivalences; + // if (equiv.size() == 1) + // return getName(); + // else return "java.lang.Object"; } else @@ -416,6 +424,16 @@ public abstract class TypeData { else return "[L" + elementType.replace('.', '/') + ";"; } + + public static String getElementType(String arrayType) { + char c = arrayType.charAt(1); + if (c == 'L') + return arrayType.substring(2, arrayType.length() - 1).replace('/', '.'); + else if (c == '[') + return arrayType.substring(1); + else + return arrayType; + } } /** diff --git a/src/main/javassist/bytecode/stackmap/TypedBlock.java b/src/main/javassist/bytecode/stackmap/TypedBlock.java index 9d908755..42ab3497 100644 --- a/src/main/javassist/bytecode/stackmap/TypedBlock.java +++ b/src/main/javassist/bytecode/stackmap/TypedBlock.java @@ -7,7 +7,10 @@ public class TypedBlock extends BasicBlock { public TypeData[] stackTypes, localsTypes; // set by a Liveness object. + // inputs[i] is true if the i-th variable is used within this block. public boolean[] inputs; + + // working area for Liveness class. public boolean updating; public int status; public byte[] localsUsage; |