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

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

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

Loading…
Cancel
Save