git-svn-id: https://svn.code.sf.net/p/jode/code/trunk@112 379699f6-c40d-0410-875b-85095c16579e
stable
jochen 26 years ago
parent 51bebb2180
commit b3aee060b3
  1. 10
      jode/jode/decompiler/CodeAnalyzer.java
  2. 55
      jode/jode/expr/ComplexExpression.java
  3. 130
      jode/jode/type/ClassInterfacesType.java

@ -42,7 +42,7 @@ public class CodeAnalyzer implements Analyzer {
public JodeEnvironment env; public JodeEnvironment env;
Vector allLocals = new Vector(); Vector allLocals = new Vector();
jode.flow.VariableSet param; LocalInfo[] param;
LocalVariableTable lvt; LocalVariableTable lvt;
/** /**
@ -65,9 +65,9 @@ public class CodeAnalyzer implements Analyzer {
method.classAnalyzer, attr); method.classAnalyzer, attr);
int paramCount = method.getParamCount(); int paramCount = method.getParamCount();
param = new jode.flow.VariableSet(); param = new LocalInfo[paramCount];
for (int i=0; i<paramCount; i++) for (int i=0; i<paramCount; i++)
param.addElement(getLocalInfo(0, i)); param[i] = getLocalInfo(0, i);
} }
private final static int SEQUENTIAL = 1; private final static int SEQUENTIAL = 1;
@ -231,7 +231,7 @@ public class CodeAnalyzer implements Analyzer {
public void dumpSource(TabbedPrintWriter writer) public void dumpSource(TabbedPrintWriter writer)
throws java.io.IOException throws java.io.IOException
{ {
methodHeader.makeDeclaration(param); methodHeader.makeDeclaration(new jode.flow.VariableSet(param));
methodHeader.dumpSource(writer); methodHeader.dumpSource(writer);
} }
@ -245,7 +245,7 @@ public class CodeAnalyzer implements Analyzer {
} }
public LocalInfo getParamInfo(int slot) { public LocalInfo getParamInfo(int slot) {
return (LocalInfo) param.elementAt(slot); return param[slot];
} }
public void useClass(Class clazz) public void useClass(Class clazz)

@ -155,42 +155,53 @@ public class ComplexExpression extends Expression {
public void setSubExpressions(int i, Expression expr) { public void setSubExpressions(int i, Expression expr) {
subExpressions[i] = expr; subExpressions[i] = expr;
updateSubTypes(); updateType();
} }
void updateSubTypes() { void updateSubTypes() {
boolean changed = false;
for (int i=0; i < subExpressions.length; i++) { for (int i=0; i < subExpressions.length; i++) {
Type opType;
if (i == 0 && operator instanceof ArrayStoreOperator) { if (i == 0 && operator instanceof ArrayStoreOperator) {
/* No rule without exception: /* No rule without exception:
* We can always use tSubType, except for the * We can always use tSubType, except for the
* array operand of an array store instruction. * array operand of an array store instruction.
*/ */
subExpressions[i].setType(operator.getOperandType(i)); opType = operator.getOperandType(i);
} else } else
subExpressions[i].setType opType = Type.tSubType(operator.getOperandType(i));
(Type.tSubType(operator.getOperandType(i))); Type exprType = subExpressions[i].getType();
opType = opType.intersection(exprType);
if (!opType.equals(exprType) && opType != Type.tError) {
if (Decompiler.isTypeDebugging)
System.err.println("change in "+this+": "
+exprType
+"->"+opType);
subExpressions[i].setType(opType);
changed = true;
}
} }
} }
public void updateType() { public void updateType() {
if (subExpressions.length > 0) { if (subExpressions.length > 0) {
Type types[] = new Type[subExpressions.length];
while (true) { while (true) {
boolean changed = false;
updateSubTypes(); updateSubTypes();
Type types[] = new Type[subExpressions.length];
boolean changed = false;
for (int i=0; i < types.length; i++) { for (int i=0; i < types.length; i++) {
if (i == 0 && operator instanceof ArrayStoreOperator) { if (i == 0 && operator instanceof ArrayStoreOperator) {
/* No rule without exception: /* No rule without exception:
* We can always use tSuperType, except for the * We can always use tSuperType, except for the
* array operand of an array store instruction. * array operand of an array store instruction.
*/ */
types[i] = subExpressions[i].getType(); types[i] = subExpressions[i].getType();
} else } else
types[i] = Type.tSuperType types[i] = Type.tSuperType
(subExpressions[i].getType()); (subExpressions[i].getType());
types[i] = Type opType = operator.getOperandType(i);
types[i].intersection(operator.getOperandType(i)); types[i] = types[i].intersection(opType);
if (types[i] != Type.tError if (!types[i].equals(opType)
&& !types[i].equals(operator.getOperandType(i))) { && types[i] != Type.tError) {
if (Decompiler.isTypeDebugging) if (Decompiler.isTypeDebugging)
System.err.println("change in "+this+": " System.err.println("change in "+this+": "
+operator.getOperandType(i) +operator.getOperandType(i)
@ -198,26 +209,24 @@ public class ComplexExpression extends Expression {
changed = true; changed = true;
} }
} }
if (changed) if (!changed)
operator.setOperandType(types);
else
break; break;
operator.setOperandType(types);
} }
} }
setType(operator.getType()); Type newType = type.intersection(operator.getType());
}
public void setType(Type newType) {
newType = type.intersection(newType);
if (!newType.equals(type)) { if (!newType.equals(type)) {
type = newType; type = newType;
operator.setType(type);
updateSubTypes();
if (parent != null) if (parent != null)
parent.updateType(); parent.updateType();
} }
} }
public void setType(Type newType) {
operator.setType(newType);
updateType();
}
public boolean isVoid() { public boolean isVoid() {
return operator.getType() == Type.tVoid; return operator.getType() == Type.tVoid;
} }

@ -37,7 +37,7 @@ public class ClassInterfacesType extends Type {
Class clazz; Class clazz;
Class ifaces[]; Class ifaces[];
public final static Class cObject = Object.class; public final static Class cObject = new Object().getClass();
public ClassInterfacesType(String clazzName) { public ClassInterfacesType(String clazzName) {
super(TC_CLASS); super(TC_CLASS);
@ -47,7 +47,7 @@ public class ClassInterfacesType extends Type {
this.clazz = null; this.clazz = null;
ifaces = new Class[] {clazz}; ifaces = new Class[] {clazz};
} else { } else {
this.clazz = clazz; this.clazz = (clazz == cObject) ? null : clazz;
ifaces = new Class[0]; ifaces = new Class[0];
} }
} catch (ClassNotFoundException ex) { } catch (ClassNotFoundException ex) {
@ -61,7 +61,7 @@ public class ClassInterfacesType extends Type {
this.clazz = null; this.clazz = null;
ifaces = new Class[] { clazz }; ifaces = new Class[] { clazz };
} else { } else {
this.clazz = clazz; this.clazz = (clazz == cObject) ? null : clazz;
ifaces = new Class[0]; ifaces = new Class[0];
} }
} }
@ -74,7 +74,7 @@ public class ClassInterfacesType extends Type {
private static Type create(Class clazz, Class[] ifaces) { private static Type create(Class clazz, Class[] ifaces) {
/* Make sure that every {java.lang.Object} equals tObject */ /* Make sure that every {java.lang.Object} equals tObject */
if (ifaces.length == 0 && (clazz == cObject || clazz == null)) if (ifaces.length == 0 && clazz == null)
return tObject; return tObject;
return new ClassInterfacesType(clazz, ifaces); return new ClassInterfacesType(clazz, ifaces);
} }
@ -117,8 +117,7 @@ public class ClassInterfacesType extends Type {
ClassInterfacesType bottom = (ClassInterfacesType) bottomType; ClassInterfacesType bottom = (ClassInterfacesType) bottomType;
if (bottom.clazz != null if (bottom.clazz != null) {
&& bottom.clazz != cObject) {
/* The searched type must be a class type. /* The searched type must be a class type.
*/ */
if (this.ifaces.length != 0 if (this.ifaces.length != 0
@ -130,19 +129,20 @@ public class ClassInterfacesType extends Type {
for (int i=0; i < bottom.ifaces.length; i++) { for (int i=0; i < bottom.ifaces.length; i++) {
if (!implementedBy(bottom.ifaces[i], this.clazz)) if (!implementedBy(bottom.ifaces[i], this.clazz))
return tError; return tError;
} }
if (bottom.clazz == this.clazz if (bottom.clazz == this.clazz
&& bottom.ifaces.length == 0) && bottom.ifaces.length == 0)
return bottom; return bottom;
return tRange(bottom, create(this.clazz, new Class[0])); return tRange(bottom, this);
} else { } else {
/* Now bottom.clazz is null (or tObject), find all /* Now bottom.clazz is null (or tObject), find all
* classes/interfaces that implement all bottom.ifaces. * classes/interfaces that implement all bottom.ifaces.
*/ */
Class clazz = this.clazz; Class clazz = this.clazz;
if (clazz != null) { if (clazz != null) {
for (int i=0; i < bottom.ifaces.length; i++) { for (int i=0; i < bottom.ifaces.length; i++) {
@ -152,48 +152,70 @@ public class ClassInterfacesType extends Type {
} }
} }
} }
Vector ifaces = new Vector();
/* If bottom is a single interface and equals some top
* interface, then bottom is the only possible type.
*/
if (clazz == null && bottom.ifaces.length == 1) {
for (int i=0; i< this.ifaces.length; i++) {
if (this.ifaces[i] == bottom.ifaces[0])
return bottom;
}
}
Class[] ifaces = new Class[this.ifaces.length];
int count = 0;
big_loop: big_loop:
for (int j=0; j < this.ifaces.length; j++) { for (int j=0; j < this.ifaces.length; j++) {
for (int i=0; i < bottom.ifaces.length; i++) { for (int i=0; i < bottom.ifaces.length; i++) {
if (!implementedBy(bottom.ifaces[i], this.ifaces[j])) if (!implementedBy(bottom.ifaces[i], this.ifaces[j]))
continue big_loop; continue big_loop;
} }
ifaces.addElement(this.ifaces[j]); ifaces[count++] = (this.ifaces[j]);
} }
/* If bottom and the new top are the same single interface if (count < ifaces.length) {
* return it. Class[] shortIfaces = new Class[count];
*/ System.arraycopy(ifaces, 0, shortIfaces, 0, count);
if (clazz == null ifaces = shortIfaces;
&& bottom.ifaces.length == 1 && ifaces.size() == 1 } else if (clazz == this.clazz)
&& bottom.ifaces[0] == ifaces.elementAt(0)) return tRange(bottom, this);
return bottom; return tRange(bottom, create(clazz, ifaces));
}
}
Class[] ifaceArray = new Class[ifaces.size()]; private boolean implementsAllIfaces(Class[] otherIfaces) {
ifaces.copyInto(ifaceArray); big:
return tRange(bottom, create(clazz, ifaceArray)); for (int i=0; i < otherIfaces.length; i++) {
Class iface = otherIfaces[i];
if (clazz != null && implementedBy(iface, clazz))
continue big;
for (int j=0; j < this.ifaces.length; j++) {
if (implementedBy(iface, ifaces[j]))
continue big;
}
return false;
} }
return true;
} }
/** /**
* Returns the specialized type of this and type. * Returns the specialized type of this and type.
* We have two classes and multiple interfaces. The result * We have two classes and multiple interfaces. The result
* should be the object that is the the child of both objects * should be the object that extends both objects
* and the union of all interfaces. * and the union of all interfaces.
*/ */
public Type getSpecializedType(Type type) { public Type getSpecializedType(Type type) {
int code = type.typecode;
if (type.getTypeCode() == TC_UNKNOWN) if (code == TC_UNKNOWN)
return this; return this;
if (type.getTypeCode() == TC_ARRAY && this == tObject) if (code == TC_ARRAY && this == tObject)
return type; return type;
if (type.getTypeCode() != TC_CLASS) if (code != TC_CLASS)
return tError; return tError;
ClassInterfacesType other = (ClassInterfacesType) type; ClassInterfacesType other = (ClassInterfacesType) type;
Class clazz; Class clazz;
Vector ifaces = new Vector();
/* First determine the clazz, one of the two classes must be a sub /* First determine the clazz, one of the two classes must be a sub
* class of the other or null. * class of the other or null.
@ -210,10 +232,21 @@ public class ClassInterfacesType extends Type {
else else
return tError; return tError;
/* Most time one of the two classes is already more specialized.
* Optimize for this case.
*/
if (clazz == this.clazz
&& implementsAllIfaces(other.ifaces))
return this;
else if (clazz == other.clazz
&& other.implementsAllIfaces(this.ifaces))
return other;
/* The interfaces are simply the union of both interfaces set. /* The interfaces are simply the union of both interfaces set.
* But we can simplify this, if an interface is implemented by * But we can simplify this, if an interface is implemented by
* another or by the class, we can omit it. * another or by the class, we can omit it.
*/ */
Vector ifaces = new Vector();
big_loop_this: big_loop_this:
for (int i=0; i< this.ifaces.length; i++) { for (int i=0; i< this.ifaces.length; i++) {
Class iface = this.ifaces[i]; Class iface = this.ifaces[i];
@ -248,9 +281,6 @@ public class ClassInterfacesType extends Type {
*/ */
ifaces.addElement(iface); ifaces.addElement(iface);
} }
if (clazz == cObject && ifaces.size() > 0)
/* Every interface implies tObject, so remove it */
clazz = null;
Class[] ifaceArray = new Class[ifaces.size()]; Class[] ifaceArray = new Class[ifaces.size()];
ifaces.copyInto(ifaceArray); ifaces.copyInto(ifaceArray);
@ -258,25 +288,21 @@ public class ClassInterfacesType extends Type {
} }
/** /**
* Returns the generalized type of this and type. * Returns the generalized type of this and type. We have two
* We have two classes and multiple interfaces. The result * classes and multiple interfaces. The result should be the
* should be the object that is the the parent of both objects and * object that is the the super class of both objects and all
* all interfaces, that one class or interface of this and of type * interfaces, that one class or interface of each type
* implements. * implements. */
*/
public Type getGeneralizedType(Type type) { public Type getGeneralizedType(Type type) {
int code = type.typecode;
Class clazz; if (code == TC_UNKNOWN)
Vector ifaces = new Vector();
if (type.getTypeCode() == TC_UNKNOWN)
return this; return this;
if (type.getTypeCode() == TC_ARRAY) if (code == TC_ARRAY)
return tObject; return tObject;
if (type.getTypeCode() != TC_CLASS) if (code != TC_CLASS)
return tError; return tError;
ClassInterfacesType other = (ClassInterfacesType) type; ClassInterfacesType other = (ClassInterfacesType) type;
Class clazz;
/* First the easy part, determine the clazz */ /* First the easy part, determine the clazz */
if (this.clazz == null || other.clazz == null) if (this.clazz == null || other.clazz == null)
@ -293,6 +319,13 @@ public class ClassInterfacesType extends Type {
clazz = null; clazz = null;
} }
if (clazz == this.clazz
&& other.implementsAllIfaces(this.ifaces))
return this;
else if (clazz == other.clazz
&& this.implementsAllIfaces(other.ifaces))
return other;
/* Now the more complicated part: find all interfaces, that are /* Now the more complicated part: find all interfaces, that are
* implemented by one interface or class in each group. * implemented by one interface or class in each group.
* *
@ -309,6 +342,9 @@ public class ClassInterfacesType extends Type {
c = c.getSuperclass(); c = c.getSuperclass();
} }
} }
Vector ifaces = new Vector();
for (int i=0; i<this.ifaces.length; i++) for (int i=0; i<this.ifaces.length; i++)
allIfaces.push(this.ifaces[i]); allIfaces.push(this.ifaces[i]);
@ -354,7 +390,7 @@ public class ClassInterfacesType extends Type {
*/ */
public void useType() { public void useType() {
if (!jode.Decompiler.isTypeDebugging) { if (!jode.Decompiler.isTypeDebugging) {
if (clazz != null && clazz != cObject) if (clazz != null)
env.useClass(clazz); env.useClass(clazz);
else if (ifaces.length > 0) else if (ifaces.length > 0)
env.useClass(ifaces[0]); env.useClass(ifaces[0]);
@ -378,14 +414,12 @@ public class ClassInterfacesType extends Type {
} }
return sb.append("}").toString(); return sb.append("}").toString();
} else { } else {
if (clazz != null && clazz != cObject) if (clazz != null)
return env.classString(clazz); return env.classString(clazz);
else if (ifaces.length > 0) else if (ifaces.length > 0)
return env.classString(ifaces[0]); return env.classString(ifaces[0]);
else if (clazz == cObject)
return env.classString(clazz);
else else
return "{<error>}"; return env.classString(cObject);
} }
} }

Loading…
Cancel
Save