*** empty log message ***

git-svn-id: https://svn.code.sf.net/p/jode/code/trunk@102 379699f6-c40d-0410-875b-85095c16579e
stable
jochen 26 years ago
parent af9ce24395
commit 90567a56b1
  1. 1
      jode/jode/decompiler/LocalVariableTable.java
  2. 39
      jode/jode/expr/ComplexExpression.java
  3. 22
      jode/jode/expr/ConstOperator.java
  4. 15
      jode/jode/expr/ConstructorOperator.java
  5. 17
      jode/jode/expr/Expression.java
  6. 16
      jode/jode/expr/GetFieldOperator.java
  7. 45
      jode/jode/expr/InvokeOperator.java
  8. 21
      jode/jode/expr/PutFieldOperator.java
  9. 9
      jode/jode/flow/CatchBlock.java
  10. 4
      jode/jode/flow/CombineIfGotoExpressions.java
  11. 7
      jode/jode/flow/CreateIfThenElseOperator.java
  12. 14
      jode/jode/flow/TryBlock.java

@ -19,7 +19,6 @@
package jode; package jode;
import java.util.Enumeration; import java.util.Enumeration;
import gnu.bytecode.CpoolUtf8;
import gnu.bytecode.LocalVarsAttr; import gnu.bytecode.LocalVarsAttr;
import gnu.bytecode.Variable; import gnu.bytecode.Variable;
import gnu.bytecode.Spy; import gnu.bytecode.Spy;

@ -88,11 +88,12 @@ public class ComplexExpression extends Expression {
} }
return 1; return 1;
} }
for (int i=0; i < subExpressions.length; i++) { return subExpressions[0].canCombine(e);
int can = subExpressions[i].canCombine(e); // for (int i=0; i < subExpressions.length; i++) {
if (can != 0) // int can = subExpressions[i].canCombine(e);
return can; // if (can != 0)
} // return can;
// }
} }
return 0; return 0;
} }
@ -120,7 +121,7 @@ public class ComplexExpression extends Expression {
return this; return this;
} }
} }
throw new AssertError("combine didn't succeed"); return null;
} }
public Operator getOperator() { public Operator getOperator() {
@ -235,36 +236,32 @@ public class ComplexExpression extends Expression {
return true; return true;
} }
static Expression emptyString =
new EmptyStringOperator();
public Expression simplifyStringBuffer() { public Expression simplifyStringBuffer() {
gnu.bytecode.CpoolRef field;
if (operator instanceof InvokeOperator if (operator instanceof InvokeOperator
&& (((InvokeOperator)operator).getClassType() && (((InvokeOperator)operator).getClassType()
.equals(Type.tStringBuffer)) .equals(Type.tStringBuffer))
&& !((InvokeOperator)operator).isStatic() && !((InvokeOperator)operator).isStatic()
&& (((InvokeOperator)operator).getMethodName().equals("append")) && (((InvokeOperator)operator).getMethodName().equals("append"))
&& (((InvokeOperator)operator).getMethodType() && (((InvokeOperator)operator).getMethodType()
.getArgumentTypes().length == 1)) { .getParameterTypes().length == 1)) {
Expression e = subExpressions[0].simplifyStringBuffer(); Expression e = subExpressions[0].simplifyStringBuffer();
if (e == null) if (e == null)
return null; return null;
if (e.getOperator() instanceof EmptyStringOperator && if (e == EMPTYSTRING
subExpressions[1].getType().isOfType(Type.tString)) && subExpressions[1].getType().isOfType(Type.tString))
return subExpressions[1]; return subExpressions[1];
return new ComplexExpression return new ComplexExpression
(new StringAddOperator(), new Expression[] (new StringAddOperator(), new Expression[]
{ e, subExpressions[1] }); { e, subExpressions[1] });
} }
if (operator instanceof ConstructorOperator && if (operator instanceof ConstructorOperator
operator.getType().isOfType(Type.tStringBuffer)) { && (((ConstructorOperator) operator).getClassType()
if (subExpressions.length == 0) == Type.tStringBuffer)) {
return emptyString;
else if (subExpressions.length == 1 && if (subExpressions.length == 1 &&
subExpressions[0].getType().isOfType(Type.tString)) subExpressions[0].getType().isOfType(Type.tString))
return subExpressions[0]; return subExpressions[0];
} }
@ -276,7 +273,7 @@ public class ComplexExpression extends Expression {
InvokeOperator invoke = (InvokeOperator) operator; InvokeOperator invoke = (InvokeOperator) operator;
if (invoke.getMethodName().equals("toString") if (invoke.getMethodName().equals("toString")
&& !invoke.isStatic() && !invoke.isStatic()
&& (invoke.getClassType().equals(Type.tStringBuffer)) && invoke.getClassType().equals(Type.tStringBuffer)
&& subExpressions.length == 1) { && subExpressions.length == 1) {
Expression simple = subExpressions[0].simplifyStringBuffer(); Expression simple = subExpressions[0].simplifyStringBuffer();
if (simple != null) if (simple != null)
@ -292,7 +289,7 @@ public class ComplexExpression extends Expression {
return new ComplexExpression return new ComplexExpression
(new StringAddOperator(), new Expression[] (new StringAddOperator(), new Expression[]
{ emptyString, subExpressions[0] }); { EMPTYSTRING, subExpressions[0] });
} }
/* The pizza way (pizza is the compiler of kaffe) */ /* The pizza way (pizza is the compiler of kaffe) */
else if (invoke.getMethodName().equals("concat") else if (invoke.getMethodName().equals("concat")
@ -304,7 +301,7 @@ public class ComplexExpression extends Expression {
if (right instanceof ComplexExpression if (right instanceof ComplexExpression
&& right.getOperator() instanceof StringAddOperator && right.getOperator() instanceof StringAddOperator
&& (((ComplexExpression) right).subExpressions[0] && (((ComplexExpression) right).subExpressions[0]
== emptyString)) == EMPTYSTRING))
right = ((ComplexExpression)right).subExpressions[1]; right = ((ComplexExpression)right).subExpressions[1];
return new ComplexExpression return new ComplexExpression

@ -46,13 +46,17 @@ public class ConstOperator extends NoArgOperator {
return "false"; return "false";
else if (value.equals("1")) else if (value.equals("1"))
return "true"; return "true";
} if (type == Type.tChar) { } if (type.getBottom() == Type.tChar) {
char i = (char) Integer.parseInt(value); char c = (char) Integer.parseInt(value);
switch (i) { switch (c) {
case '\0':
return "\'\\0\'";
case '\t': case '\t':
return "\'\\t\'"; return "\'\\t\'";
case '\n': case '\n':
return "\'\\n\'"; return "\'\\n\'";
case '\r':
return "\'\\r\'";
case '\\': case '\\':
return "\'\\\\\'"; return "\'\\\\\'";
case '\"': case '\"':
@ -60,8 +64,16 @@ public class ConstOperator extends NoArgOperator {
case '\'': case '\'':
return "\'\\\'\'"; return "\'\\\'\'";
} }
if (i >= 32 && i <128) if (c < 32) {
return "\'"+i+"\'"; String oct = Integer.toOctalString(c);
return "\'\\000".substring(0, 5-oct.length())+oct+"\'";
}
if (c >= 32 && c < 127)
return "\'"+c+"\'";
else {
String hex = Integer.toHexString(c);
return "\'\\u0000".substring(0, 7-hex.length())+hex+"\'";
}
} else if (parent != null) { } else if (parent != null) {
int opindex = parent.getOperator().getOperatorIndex(); int opindex = parent.getOperator().getOperatorIndex();
if (opindex >= OPASSIGN_OP + ADD_OP if (opindex >= OPASSIGN_OP + ADD_OP

@ -35,24 +35,33 @@ public class ConstructorOperator extends Operator {
} }
public int getOperandCount() { public int getOperandCount() {
return methodType.getArgumentTypes().length; return methodType.getParameterTypes().length;
} }
public int getOperandPriority(int i) { public int getOperandPriority(int i) {
return 0; return 0;
} }
public Type getClassType() {
return classType;
}
public Type getOperandType(int i) { public Type getOperandType(int i) {
return methodType.getArgumentTypes()[i]; return methodType.getParameterTypes()[i];
} }
public void setOperandType(Type types[]) { public void setOperandType(Type types[]) {
} }
public Expression simplifyStringBuffer() {
return (getClassType() == Type.tStringBuffer)
? EMPTYSTRING : null;
}
public String toString(String[] operands) { public String toString(String[] operands) {
StringBuffer result = StringBuffer result =
new StringBuffer("new ").append(classType.toString()).append("("); new StringBuffer("new ").append(classType.toString()).append("(");
for (int i=0; i < methodType.getArgumentTypes().length; i++) { for (int i=0; i < methodType.getParameterTypes().length; i++) {
if (i>0) if (i>0)
result.append(", "); result.append(", ");
result.append(operands[i]); result.append(operands[i]);

@ -65,6 +65,8 @@ public abstract class Expression {
* conflict was found. You may wish to check for >0. * conflict was found. You may wish to check for >0.
*/ */
public int canCombine(Expression e) { public int canCombine(Expression e) {
if (!e.isVoid())
return 0;
if (e instanceof IIncOperator if (e instanceof IIncOperator
&& ((IIncOperator)e.getOperator()).matches(getOperator())) && ((IIncOperator)e.getOperator()).matches(getOperator()))
return 1; return 1;
@ -84,19 +86,30 @@ public abstract class Expression {
* @return The combined expression. * @return The combined expression.
*/ */
public Expression combine(Expression e) { public Expression combine(Expression e) {
if (e.getOperator() instanceof IIncOperator) if (e.getOperator() instanceof IIncOperator) {
if (((IIncOperator)e.getOperator()).matches(getOperator())) {
((IIncOperator)e.getOperator()).makeNonVoid(); ((IIncOperator)e.getOperator()).makeNonVoid();
else /* Do not call setType, we don't want to intersect. */
e.type = e.getOperator().getType();
return e;
}
} else {
if (((StoreInstruction)e.getOperator()).matches(getOperator())) {
((StoreInstruction)e.getOperator()).makeNonVoid(); ((StoreInstruction)e.getOperator()).makeNonVoid();
/* Do not call setType, we don't want to intersect. */ /* Do not call setType, we don't want to intersect. */
e.type = e.getOperator().getType(); e.type = e.getOperator().getType();
return e; return e;
} }
}
return null;
}
public Expression simplify() { public Expression simplify() {
return this; return this;
} }
static Expression EMPTYSTRING = new ConstOperator(Type.tString, "\"\"");
public Expression simplifyStringBuffer() { public Expression simplifyStringBuffer() {
return null; return null;
} }

@ -22,17 +22,17 @@ import gnu.bytecode.CpoolRef;
public class GetFieldOperator extends Operator { public class GetFieldOperator extends Operator {
boolean staticFlag; boolean staticFlag;
CpoolRef field;
CodeAnalyzer codeAnalyzer; CodeAnalyzer codeAnalyzer;
String fieldName;
Type classType; Type classType;
public GetFieldOperator(CodeAnalyzer codeAnalyzer, boolean staticFlag, public GetFieldOperator(CodeAnalyzer codeAnalyzer, boolean staticFlag,
CpoolRef field) { Type classType, Type type, String fieldName) {
super(Type.tType(field.getNameAndType().getType().getString()), 0); super(type, 0);
this.codeAnalyzer = codeAnalyzer; this.codeAnalyzer = codeAnalyzer;
this.staticFlag = staticFlag; this.staticFlag = staticFlag;
this.field = field; this.classType = classType;
classType = Type.tClass(field.getCpoolClass().getName().getString()); this.fieldName = fieldName;
if (staticFlag) if (staticFlag)
classType.useType(); classType.useType();
} }
@ -57,7 +57,6 @@ public class GetFieldOperator extends Operator {
} }
public String toString(String[] operands) { public String toString(String[] operands) {
String fieldName = field.getNameAndType().getName().getString();
return staticFlag return staticFlag
? (classType.equals(Type.tType(codeAnalyzer.getClazz())) ? (classType.equals(Type.tType(codeAnalyzer.getClazz()))
? fieldName ? fieldName
@ -68,7 +67,8 @@ public class GetFieldOperator extends Operator {
} }
public boolean equals(Object o) { public boolean equals(Object o) {
return (o instanceof GetFieldOperator) && return o instanceof GetFieldOperator
((GetFieldOperator)o).field == field; && ((GetFieldOperator)o).classType.equals(classType)
&& ((GetFieldOperator)o).fieldName.equals(fieldName);
} }
} }

@ -22,36 +22,27 @@ import gnu.bytecode.CpoolRef;
public final class InvokeOperator extends Operator { public final class InvokeOperator extends Operator {
CodeAnalyzer codeAnalyzer; CodeAnalyzer codeAnalyzer;
boolean staticFlag;
boolean specialFlag; boolean specialFlag;
MethodType methodType; MethodType methodType;
String methodName; String methodName;
Type classType; Type classType;
CpoolRef field;
public InvokeOperator(CodeAnalyzer codeAnalyzer, public InvokeOperator(CodeAnalyzer codeAnalyzer,
boolean staticFlag, boolean specialFlag, boolean specialFlag, Type classType,
CpoolRef field) { MethodType methodType, String methodName) {
super(Type.tUnknown, 0); super(Type.tUnknown, 0);
methodType = new MethodType(field.getNameAndType(). this.methodType = methodType;
getType().getString()); this.methodName = methodName;
methodName = field.getNameAndType().getName().getString(); this.classType = classType;
classType = Type.tClass(field.getCpoolClass().getName().getString());
this.type = methodType.getReturnType(); this.type = methodType.getReturnType();
this.codeAnalyzer = codeAnalyzer; this.codeAnalyzer = codeAnalyzer;
this.staticFlag = staticFlag;
this.specialFlag = specialFlag; this.specialFlag = specialFlag;
this.field = field; if (methodType.isStatic())
if (staticFlag)
classType.useType(); classType.useType();
} }
public boolean isStatic() { public boolean isStatic() {
return staticFlag; return methodType.isStatic();
}
public CpoolRef getField() {
return field;
} }
public MethodType getMethodType() { public MethodType getMethodType() {
@ -71,22 +62,23 @@ public final class InvokeOperator extends Operator {
} }
public int getOperandCount() { public int getOperandCount() {
return (staticFlag?0:1) + methodType.getArgumentTypes().length; return (methodType.isStatic()?0:1)
+ methodType.getParameterTypes().length;
} }
public int getOperandPriority(int i) { public int getOperandPriority(int i) {
if (!staticFlag && i == 0) if (!methodType.isStatic() && i == 0)
return 950; return 950;
return 0; return 0;
} }
public Type getOperandType(int i) { public Type getOperandType(int i) {
if (!staticFlag) { if (!methodType.isStatic()) {
if (i == 0) if (i == 0)
return getClassType(); return getClassType();
i--; i--;
} }
return methodType.getArgumentTypes()[i]; return methodType.getParameterTypes()[i];
} }
public void setOperandType(Type types[]) { public void setOperandType(Type types[]) {
@ -98,7 +90,7 @@ public final class InvokeOperator extends Operator {
public String toString(String[] operands) { public String toString(String[] operands) {
String object = String object =
staticFlag methodType.isStatic()
? (classType.equals(Type.tType(codeAnalyzer.getClazz())) ? (classType.equals(Type.tType(codeAnalyzer.getClazz()))
? "" ? ""
: classType.toString()) : classType.toString())
@ -110,7 +102,7 @@ public final class InvokeOperator extends Operator {
: "") : "")
: operands[0]); : operands[0]);
int arg = staticFlag ? 0 : 1; int arg = methodType.isStatic() ? 0 : 1;
String method; String method;
if (isConstructor()) if (isConstructor())
method = (object.length() == 0 ? "this" : object); method = (object.length() == 0 ? "this" : object);
@ -118,7 +110,7 @@ public final class InvokeOperator extends Operator {
method = (object.length() == 0 ? "" : object + ".") + methodName; method = (object.length() == 0 ? "" : object + ".") + methodName;
StringBuffer params = new StringBuffer(); StringBuffer params = new StringBuffer();
for (int i=0; i < methodType.getArgumentTypes().length; i++) { for (int i=0; i < methodType.getParameterTypes().length; i++) {
if (i>0) if (i>0)
params.append(", "); params.append(", ");
params.append(operands[arg++]); params.append(operands[arg++]);
@ -127,9 +119,10 @@ public final class InvokeOperator extends Operator {
} }
public boolean equals(Object o) { public boolean equals(Object o) {
return (o instanceof InvokeOperator) && return o instanceof InvokeOperator &&
((InvokeOperator)o).field == field && ((InvokeOperator)o).classType.equals(classType) &&
((InvokeOperator)o).staticFlag == staticFlag && ((InvokeOperator)o).methodName.equals(methodName) &&
((InvokeOperator)o).methodType.equals(methodType) &&
((InvokeOperator)o).specialFlag == specialFlag; ((InvokeOperator)o).specialFlag == specialFlag;
} }
} }

@ -23,23 +23,24 @@ import gnu.bytecode.CpoolRef;
public class PutFieldOperator extends StoreInstruction { public class PutFieldOperator extends StoreInstruction {
CodeAnalyzer codeAnalyzer; CodeAnalyzer codeAnalyzer;
boolean staticFlag; boolean staticFlag;
CpoolRef field; String fieldName;
Type classType; Type classType;
public PutFieldOperator(CodeAnalyzer codeAnalyzer, boolean staticFlag, public PutFieldOperator(CodeAnalyzer codeAnalyzer, boolean staticFlag,
CpoolRef field) { Type classType, Type type, String fieldName) {
super(Type.tType(field.getNameAndType().getType().getString()), ASSIGN_OP); super(type, ASSIGN_OP);
this.codeAnalyzer = codeAnalyzer; this.codeAnalyzer = codeAnalyzer;
this.staticFlag = staticFlag; this.staticFlag = staticFlag;
this.field = field; this.fieldName = fieldName;
classType = Type.tClass(field.getCpoolClass().getName().getString()); this.classType = classType;
if (staticFlag) if (staticFlag)
classType.useType(); classType.useType();
} }
public boolean matches(Operator loadop) { public boolean matches(Operator loadop) {
return loadop instanceof GetFieldOperator && return loadop instanceof GetFieldOperator
((GetFieldOperator)loadop).field == field; && ((GetFieldOperator)loadop).classType.equals(classType)
&& ((GetFieldOperator)loadop).fieldName.equals(fieldName);
} }
public int getLValueOperandCount() { public int getLValueOperandCount() {
@ -58,7 +59,6 @@ public class PutFieldOperator extends StoreInstruction {
} }
public String getLValueString(String[] operands) { public String getLValueString(String[] operands) {
String fieldName = field.getNameAndType().getName().getString();
return staticFlag return staticFlag
? (classType.equals(Type.tType(codeAnalyzer.getClazz())) ? (classType.equals(Type.tType(codeAnalyzer.getClazz()))
? fieldName ? fieldName
@ -69,7 +69,8 @@ public class PutFieldOperator extends StoreInstruction {
} }
public boolean equals(Object o) { public boolean equals(Object o) {
return (o instanceof PutFieldOperator) && return o instanceof PutFieldOperator
((PutFieldOperator)o).field == field; && ((PutFieldOperator)o).classType.equals(classType)
&& ((PutFieldOperator)o).fieldName.equals(fieldName);
} }
} }

@ -110,4 +110,13 @@ public class CatchBlock extends StructuredBlock {
catchBlock.dumpSource(writer); catchBlock.dumpSource(writer);
writer.untab(); writer.untab();
} }
/**
* Determines if there is a sub block, that flows through to the end
* of this block. If this returns true, you know that jump is null.
* @return true, if the jump may be safely changed.
*/
public boolean jumpMayBeChanged() {
return (catchBlock.jump != null || catchBlock.jumpMayBeChanged());
}
} }

@ -67,9 +67,13 @@ public class CombineIfGotoExpressions implements Transformation{
if (prevJump.destination == cb.jump.destination) { if (prevJump.destination == cb.jump.destination) {
operator = BinaryOperator.LOG_AND_OP; operator = BinaryOperator.LOG_AND_OP;
e[0] = cbprev.getInstruction().negate(); e[0] = cbprev.getInstruction().negate();
cb.jump.gen.unionExact(prevJump.gen);
cb.jump.kill.intersect(prevJump.kill);
} else if (prevJump.destination == cb.trueBlock.jump.destination) { } else if (prevJump.destination == cb.trueBlock.jump.destination) {
operator = BinaryOperator.LOG_OR_OP; operator = BinaryOperator.LOG_OR_OP;
e[0] = cbprev.getInstruction(); e[0] = cbprev.getInstruction();
cb.trueBlock.jump.gen.unionExact(prevJump.gen);
cb.trueBlock.jump.kill.intersect(prevJump.kill);
} else } else
return false; return false;

@ -18,6 +18,7 @@
*/ */
package jode.flow; package jode.flow;
import jode.Type;
import jode.Expression; import jode.Expression;
import jode.ComplexExpression; import jode.ComplexExpression;
import jode.IfThenElseOperator; import jode.IfThenElseOperator;
@ -149,7 +150,8 @@ public class CreateIfThenElseOperator implements Transformation {
System.err.print('?'); System.err.print('?');
IfThenElseOperator iteo = new IfThenElseOperator IfThenElseOperator iteo = new IfThenElseOperator
(e[1].getType().intersection(e[2].getType())); (Type.tSuperType(e[1].getType())
.intersection(Type.tSuperType(e[2].getType())));
((InstructionBlock)ifBlock.thenBlock). ((InstructionBlock)ifBlock.thenBlock).
setInstruction(new ComplexExpression(iteo, e)); setInstruction(new ComplexExpression(iteo, e));
@ -214,7 +216,8 @@ public class CreateIfThenElseOperator implements Transformation {
thenBlock.removeJump(); thenBlock.removeJump();
IfThenElseOperator iteo = new IfThenElseOperator IfThenElseOperator iteo = new IfThenElseOperator
(e[1].getType().intersection(e[2].getType())); (Type.tSuperType(e[1].getType())
.intersection(Type.tSuperType(e[2].getType())));
((InstructionBlock)flow.lastModified). ((InstructionBlock)flow.lastModified).
setInstruction(new ComplexExpression(iteo, e)); setInstruction(new ComplexExpression(iteo, e));

@ -100,4 +100,18 @@ public class TryBlock extends StructuredBlock {
subBlocks[i].dumpSource(writer); subBlocks[i].dumpSource(writer);
writer.println("}"); writer.println("}");
} }
/**
* Determines if there is a sub block, that flows through to the end
* of this block. If this returns true, you know that jump is null.
* @return true, if the jump may be safely changed.
*/
public boolean jumpMayBeChanged() {
for (int i=0; i<subBlocks.length;i++) {
if (subBlocks[i].jump == null
&& !subBlocks[i].jumpMayBeChanged())
return false;
}
return true;
}
} }

Loading…
Cancel
Save