*** empty log message ***

git-svn-id: https://svn.code.sf.net/p/jode/code/trunk@117 379699f6-c40d-0410-875b-85095c16579e
stable
jochen 26 years ago
parent efbdca398f
commit 0192af7705
  1. 38
      jode/jode/decompiler/ClassAnalyzer.java
  2. 19
      jode/jode/decompiler/CodeAnalyzer.java
  3. 18
      jode/jode/decompiler/FieldAnalyzer.java
  4. 91
      jode/jode/decompiler/ImportHandler.java
  5. 25
      jode/jode/decompiler/LocalInfo.java
  6. 39
      jode/jode/decompiler/MethodAnalyzer.java
  7. 15
      jode/jode/expr/ComplexExpression.java
  8. 23
      jode/jode/expr/ConstOperator.java
  9. 11
      jode/jode/expr/ConstantArrayOperator.java
  10. 7
      jode/jode/expr/Expression.java
  11. 2
      jode/jode/expr/GetFieldOperator.java
  12. 4
      jode/jode/expr/LocalLoadOperator.java
  13. 10
      jode/jode/expr/PutFieldOperator.java
  14. 6
      jode/jode/expr/StoreInstruction.java
  15. 1
      jode/jode/flow/CaseBlock.java
  16. 24
      jode/jode/flow/CompleteSynchronized.java
  17. 12
      jode/jode/flow/InstructionBlock.java
  18. 12
      jode/jode/flow/SequentialBlock.java
  19. 15
      jode/jode/flow/StructuredBlock.java
  20. 7
      jode/jode/flow/SynchronizedBlock.java
  21. 4
      jode/jode/flow/TransformExceptionHandlers.java
  22. 10
      jode/jode/flow/VariableSet.java

@ -27,10 +27,14 @@ import gnu.bytecode.CpoolEntry;
import gnu.bytecode.CpoolValue1;
import gnu.bytecode.CpoolValue2;
import gnu.bytecode.CpoolString;
import jode.flow.TransformConstructors;
public class ClassAnalyzer implements Analyzer {
JodeEnvironment env;
Analyzer[] analyzers;
MethodAnalyzer staticConstructor;
MethodAnalyzer[] constructors;
Class clazz;
gnu.bytecode.ClassType classType;
ClassAnalyzer parent;
@ -49,6 +53,17 @@ public class ClassAnalyzer implements Analyzer {
}
}
public boolean setFieldInitializer(String fieldName, Expression expr) {
for (int i=0; i< analyzers.length; i++) {
if (analyzers[i] instanceof FieldAnalyzer) {
FieldAnalyzer field = (FieldAnalyzer) analyzers[i];
if (field.getName().equals(fieldName))
return field.setInitializer(expr);
}
}
return false;
}
public void analyze() {
int numFields = 0;
int i = 0;
@ -57,17 +72,34 @@ public class ClassAnalyzer implements Analyzer {
analyzers = new Analyzer[fields.length +
classType.getMethodCount()];
for (int j=0; j< fields.length; j++) {
analyzers[i] = new FieldAnalyzer(this, fields[j], env);
analyzers[i++].analyze();
}
staticConstructor = null;
java.util.Vector constrVector = new java.util.Vector();
for (gnu.bytecode.Method method = classType.getMethods();
method != null; method = method.getNext()) {
analyzers[i] = new MethodAnalyzer(this, method, env);
analyzers[i++].analyze();
MethodAnalyzer analyzer = new MethodAnalyzer(this, method, env);
analyzers[i++] = analyzer;
if (analyzer.isConstructor()) {
if (analyzer.isStatic())
staticConstructor = analyzer;
else
constrVector.addElement(analyzer);
}
analyzer.analyze();
}
constructors = new MethodAnalyzer[constrVector.size()];
if (constructors.length > 0) {
constrVector.copyInto(constructors);
TransformConstructors.transform(this, false, constructors);
}
if (staticConstructor != null)
TransformConstructors.transform(this, true, new MethodAnalyzer[]
{ staticConstructor });
env.useClass(clazz);
if (clazz.getSuperclass() != null)

@ -70,6 +70,10 @@ public class CodeAnalyzer implements Analyzer {
param[i] = getLocalInfo(0, i);
}
public FlowBlock getMethodHeader() {
return methodHeader;
}
private final static int SEQUENTIAL = 1;
private final static int PREDECESSORS = 2;
/**
@ -226,12 +230,12 @@ public class CodeAnalyzer implements Analyzer {
if (!li.isShadow())
li.getType().useType();
}
methodHeader.makeDeclaration(new jode.flow.VariableSet(param));
}
public void dumpSource(TabbedPrintWriter writer)
throws java.io.IOException
{
methodHeader.makeDeclaration(new jode.flow.VariableSet(param));
methodHeader.dumpSource(writer);
}
@ -244,6 +248,19 @@ public class CodeAnalyzer implements Analyzer {
return li;
}
/**
* Checks if the variable set contains a local with the given name.
*/
public LocalInfo findLocal(String name) {
Enumeration enum = allLocals.elements();
while (enum.hasMoreElements()) {
LocalInfo li = (LocalInfo) enum.nextElement();
if (li.getName().equals(name))
return li;
}
return null;
}
public LocalInfo getParamInfo(int slot) {
return param[slot];
}

@ -29,7 +29,7 @@ public class FieldAnalyzer implements Analyzer {
int modifiers;
Type type;
String fieldName;
ConstOperator constant;
Expression constant;
public FieldAnalyzer(ClassAnalyzer cla, Field fd, JodeEnvironment e)
{
@ -51,13 +51,25 @@ public class FieldAnalyzer implements Analyzer {
constant = new ConstOperator
(type.intersection(cla.getConstantType(index)),
cla.getConstantString(index));
constant.makeInitializer();
} catch (java.io.IOException ex) {
throw new AssertError("attribute too small");
}
}
}
public String getName() {
return fieldName;
}
public boolean setInitializer(Expression expr) {
expr.makeInitializer();
if (constant != null)
return constant.equals(expr);
constant = expr;
return true;
}
public void analyze() {
type.useType();
}
@ -71,7 +83,7 @@ public class FieldAnalyzer implements Analyzer {
writer.print(type.toString() + " " + fieldName);
if (constant != null) {
writer.print(" = " + constant.toString());
writer.print(" = " + constant.simplify().toString());
}
writer.println(";");
}

@ -23,7 +23,7 @@ import java.util.*;
public class JodeEnvironment {
Hashtable imports;
/* Classes that doesn't need to be qualified. */
Hashtable goodClasses = new Hashtable();
Hashtable cachedClassNames = null;
ClassAnalyzer main;
String className;
String pkg;
@ -66,7 +66,28 @@ public class JodeEnvironment {
if (pkgName.equals(pkg))
return false;
name = name.substring(pkgdelim+1);
// name without package, but _including_ leading dot.
name = name.substring(pkgdelim);
if (pkg.length() != 0) {
try {
Class.forName(pkg + name);
/* UGLY: If class doesn't conflict, above
* Instruction throws an exception and we
* doesn't reach here.
* XXX - Is there a better way to do it ???
*/
// System.err.println(""+pkgName+name
// + " conflicts with "
// + pkg+name);
return true;
} catch (ClassNotFoundException ex) {
/* BTW: Exception generation is slow. I'm
* really sad that this is the default.
*/
}
}
Enumeration enum = imports.keys();
while (enum.hasMoreElements()) {
String importName = (String) enum.nextElement();
@ -75,14 +96,16 @@ public class JodeEnvironment {
importName = importName.substring
(0, importName.length()-2);
if (!importName.equals(pkgName)) {
String checkName = importName + "." + name;
try {
Class.forName(checkName);
Class.forName(importName + name);
/* UGLY: If class doesn't conflict, above
* Instruction throws an exception and we
* doesn't reach here.
* XXX - Is there a better way to do it ???
*/
// System.err.println(""+pkgName+name
// + " conflicts with "
// + importName+name);
return true;
} catch (ClassNotFoundException ex) {
/* BTW: Exception generation is slow. I'm
@ -113,19 +136,20 @@ public class JodeEnvironment {
if (pkgvote.intValue() >= Decompiler.importPackageLimit)
continue;
/* This is a single Class import. Mark it for importation,
* but don't put it in newImports, yet.
/* This is a single Class import, that is not
* superseeded by a package import. Mark it for
* importation, but don't put it in newImports, yet.
*/
classImports.addElement(importName);
} else {
if (vote.intValue() < Decompiler.importPackageLimit)
continue;
}
newImports.put(importName, dummyVote);
}
}
imports = newImports;
cachedClassNames = new Hashtable();
/* Now check if the class import conflict with any of the
* package imports.
*/
@ -135,8 +159,12 @@ public class JodeEnvironment {
* the same name, exactly the first (in hash order) will
* be imported. */
String className = (String) enum.nextElement();
if (!conflictsImport(className))
if (!conflictsImport(className)) {
imports.put(className, dummyVote);
String name =
className.substring(className.lastIndexOf('.')+1);
cachedClassNames.put(className, name);
}
}
}
@ -201,22 +229,22 @@ public class JodeEnvironment {
int pkgdelim = name.lastIndexOf('.');
if (pkgdelim != -1) {
String pkgName = name.substring(0, pkgdelim);
if (pkgName.equals(pkg)
|| pkgName.equals("java.lang"))
if (pkgName.equals(pkg))
return;
Integer i = (Integer) imports.get(name);
if (i == null) {
/* This class wasn't imported before. Mark the package
* as used. */
i = (Integer) imports.get(pkgName+".*");
if (i != null && i.intValue() >= Decompiler.importPackageLimit)
return;
i = (i == null)? new Integer(1): new Integer(i.intValue()+1);
imports.put(pkgName+".*", i);
if (i.intValue() >= Decompiler.importPackageLimit)
Integer pkgVote = (Integer) imports.get(pkgName+".*");
if (pkgVote != null
&& pkgVote.intValue() >= Decompiler.importPackageLimit)
return;
Integer i = (Integer) imports.get(name);
if (i == null) {
/* This class wasn't imported before. Mark the whole package
* as used once more. */
pkgVote = (pkgVote == null)
? new Integer(1): new Integer(pkgVote.intValue()+1);
imports.put(pkgName+".*", pkgVote);
i = new Integer(1);
} else {
@ -250,23 +278,30 @@ public class JodeEnvironment {
* @return a legal string representation of clazz.
*/
public String classString(String name) {
if (cachedClassNames == null)
/* We are not yet clean, return the full name */
return name;
/* First look in our cache. */
String cached = (String) cachedClassNames.get(name);
if (cached != null)
return cached;
int pkgdelim = name.lastIndexOf('.');
if (pkgdelim != -1) {
/* First look in our cache. */
if (goodClasses.get(name) != null)
return name.substring(pkgdelim+1);
String pkgName = name.substring(0, pkgdelim);
Integer i;
if (pkgName.equals(pkg)
|| (( imports.get(pkgName+".*") != null
|| imports.get(name) != null)
|| (imports.get(pkgName+".*") != null
&& !conflictsImport(name))) {
goodClasses.put(name, name);
return name.substring(pkgdelim+1);
String result = name.substring(pkgdelim+1);
cachedClassNames.put(name, result);
return result;
}
}
cachedClassNames.put(name, name);
return name;
}

@ -35,6 +35,7 @@ import java.util.Vector;
public class LocalInfo {
private static int serialnr = 0;
private int slot;
private boolean isUnique;
private String name;
private Type type;
private LocalInfo shadow;
@ -126,8 +127,10 @@ public class LocalInfo {
}
return shadow.getName();
}
if (name == null)
name = "local_"+slot+"__"+serialnr++;
if (name == null) {
name = "local_"+slot+"__"+serialnr+++"_";
isUnique = true;
}
return name;
}
@ -143,10 +146,20 @@ public class LocalInfo {
* Set the name of this local.
*/
public void setName(String name) {
if (shadow != null)
shadow.setName(name);
else
this.name = name;
LocalInfo li = getLocalInfo();
li.name = name;
}
/**
* Set the name of this local.
*/
public void makeNameUnique() {
LocalInfo li = getLocalInfo();
String name = li.getName();
if (!li.isUnique) {
li.name = name + "__"+serialnr+++"_";
li.isUnique = true;
}
}
/**

@ -72,9 +72,24 @@ public class MethodAnalyzer implements Analyzer {
}
}
public jode.flow.FlowBlock getMethodHeader() {
return code != null ? code.getMethodHeader() : null;
}
public boolean isConstructor() {
return isConstructor;
}
public boolean isStatic() {
return methodType.isStatic();
}
public int getParamCount() {
return (methodType.isStatic() ? 0 : 1)
+ methodType.getParameterTypes().length;
int count = isStatic() ? 0 : 1;
Type[] paramTypes = methodType.getParameterTypes();
for (int i=0; i< paramTypes.length; i++)
count += paramTypes[i].stackSize();
return count;
}
public Type getReturnType() {
@ -88,7 +103,7 @@ public class MethodAnalyzer implements Analyzer {
return;
int offset = 0;
if (!methodType.isStatic()) {
if (!isStatic()) {
LocalInfo clazz = code.getParamInfo(0);
clazz.setType(Type.tType(this.classAnalyzer.clazz));
clazz.setName("this");
@ -96,8 +111,10 @@ public class MethodAnalyzer implements Analyzer {
}
Type[] paramTypes = methodType.getParameterTypes();
for (int i=0; i< paramTypes.length; i++)
code.getParamInfo(offset+i).setType(paramTypes[i]);
for (int i=0; i< paramTypes.length; i++) {
code.getParamInfo(offset).setType(paramTypes[i]);
offset += paramTypes[i].stackSize();
}
for (int i= 0; i< exceptions.length; i++)
exceptions[i].useType();
@ -128,11 +145,15 @@ public class MethodAnalyzer implements Analyzer {
System.err.println("");
}
if (isConstructor() && isStatic()
&& getMethodHeader().getBlock() instanceof jode.flow.EmptyBlock)
return;
writer.println("");
String modif = Modifier.toString(modifiers);
if (modif.length() > 0)
writer.print(modif+" ");
if (isConstructor && methodType.isStatic())
if (isConstructor && isStatic())
writer.print(""); /* static block */
else {
if (isConstructor)
@ -148,11 +169,13 @@ public class MethodAnalyzer implements Analyzer {
writer.print(", ");
LocalInfo li;
if (code == null) {
li = new LocalInfo(i+offset);
li = new LocalInfo(offset);
li.setType(paramTypes[i]);
li.makeNameUnique();
} else
li = code.getParamInfo(i+offset);
li = code.getParamInfo(offset);
writer.print(li.getType().toString()+" "+li.getName());
offset += paramTypes[i].stackSize();
}
writer.print(")");
}

@ -250,6 +250,8 @@ public class ComplexExpression extends Expression {
else if (subExpressions[i].getType() == Type.tError)
expr[i] = "(/*type error */" + expr[i]+")";
}
if (Decompiler.isTypeDebugging && parent != null)
return "[("+type+") "+ operator.toString(expr)+"]";
return operator.toString(expr);
}
@ -426,5 +428,18 @@ public class ComplexExpression extends Expression {
}
return this;
}
public void makeInitializer() {
operator.makeInitializer();
}
public boolean isConstant() {
if (!operator.isConstant())
return false;
for (int i=0; i< subExpressions.length; i++)
if (!subExpressions[i].isConstant())
return false;
return true;
}
}

@ -22,6 +22,8 @@ package jode;
public class ConstOperator extends NoArgOperator {
String value;
boolean isInitializer = false;
public ConstOperator(Type type, String value) {
super(type);
this.value = value;
@ -40,7 +42,12 @@ public class ConstOperator extends NoArgOperator {
((ConstOperator)o).value.equals(value);
}
public void makeInitializer() {
isInitializer = true;
}
public String toString(String[] operands) {
String value = this.value;
if (type.isOfType(Type.tBoolean)) {
if (value.equals("0"))
return "false";
@ -86,15 +93,15 @@ public class ConstOperator extends NoArgOperator {
if (type.isOfType(Type.tUInt)) {
int i = Integer.parseInt(value);
if (i < -1)
return "~0x"+Integer.toHexString(-i-1);
value = "~0x"+Integer.toHexString(-i-1);
else
return "0x"+Integer.toHexString(i);
value = "0x"+Integer.toHexString(i);
} else if (type.equals(Type.tLong)) {
long l = Long.parseLong(value);
if (l < -1)
return "~0x"+Long.toHexString(-l-1)+"L";
value = "~0x"+Long.toHexString(-l-1);
else
return "0x"+Long.toHexString(l)+"L";
value = "0x"+Long.toHexString(l);
}
}
}
@ -102,6 +109,14 @@ public class ConstOperator extends NoArgOperator {
return value+"L";
if (type.isOfType(Type.tFloat))
return value+"F";
if (!type.isOfType(Type.tInt) && type.isOfType(Type.tUInt)
&& !isInitializer)
/* One of the strange things in java. All constants
* are int and must be explicitly casted to byte,...,short.
* But in initializers this cast is unnecessary.
*/
return "("+type+") "+value;
return value;
}
}

@ -24,6 +24,7 @@ public class ConstantArrayOperator extends NoArgOperator {
ConstOperator empty;
Expression[] values;
Type argType;
boolean isInitializer;
public ConstantArrayOperator(Type type, int size) {
super(type);
@ -31,6 +32,7 @@ public class ConstantArrayOperator extends NoArgOperator {
argType = (type instanceof ArrayType)
? Type.tSubType(((ArrayType)type).getElementType()) : Type.tError;
empty = new ConstOperator(argType, "0");
empty.makeInitializer();
}
public void setType(Type newtype) {
@ -54,6 +56,7 @@ public class ConstantArrayOperator extends NoArgOperator {
setType(Type.tSuperType(Type.tArray(value.getType())));
values[index] = value;
value.parent = this;
value.makeInitializer();
return true;
}
@ -61,9 +64,13 @@ public class ConstantArrayOperator extends NoArgOperator {
return 200;
}
public void makeInitializer() {
isInitializer = true;
}
public String toString(String[] operands) {
StringBuffer result
= new StringBuffer("new ").append(type).append(" { ");
StringBuffer result = isInitializer ? new StringBuffer("{ ")
: new StringBuffer("new ").append(type).append(" { ");
for (int i=0; i< values.length; i++) {
if (i>0)
result.append(", ");

@ -128,6 +128,13 @@ public abstract class Expression {
public abstract Operator getOperator();
public void makeInitializer() {
}
public boolean isConstant() {
return true;
}
public abstract String toString();
String toString(int minPriority) {

@ -59,9 +59,11 @@ public class GetFieldOperator extends Operator {
public String toString(String[] operands) {
return staticFlag
? (classType.equals(Type.tType(codeAnalyzer.getClazz()))
&& codeAnalyzer.findLocal(fieldName) == null
? fieldName
: classType.toString() + "." + fieldName)
: (operands[0].equals("this")
&& codeAnalyzer.findLocal(fieldName) == null
? fieldName
: operands[0] + "." + fieldName);
}

@ -38,6 +38,10 @@ implements LocalVarOperator {
return false;
}
public boolean isConstant() {
return false;
}
// public void setLocalInfo(LocalInfo local) {
// local.setType(type);
// this.local = local;

@ -37,6 +37,14 @@ public class PutFieldOperator extends StoreInstruction {
classType.useType();
}
public boolean isStatic() {
return staticFlag;
}
public String getFieldName() {
return fieldName;
}
public boolean matches(Operator loadop) {
return loadop instanceof GetFieldOperator
&& ((GetFieldOperator)loadop).classType.equals(classType)
@ -61,9 +69,11 @@ public class PutFieldOperator extends StoreInstruction {
public String getLValueString(String[] operands) {
return staticFlag
? (classType.equals(Type.tType(codeAnalyzer.getClazz()))
&& codeAnalyzer.findLocal(fieldName) == null
? fieldName
: classType.toString() + "." + fieldName)
: (operands[0].equals("this")
&& codeAnalyzer.findLocal(fieldName) == null
? fieldName
: operands[0] + "." + fieldName);
}

@ -30,6 +30,10 @@ public abstract class StoreInstruction extends Operator {
lvCasts = lvalueType.toString();
}
public Type getType() {
return type == Type.tVoid ? type : getLValueType();
}
public Type getLValueType() {
return lvalueType;
}
@ -41,6 +45,8 @@ public abstract class StoreInstruction extends Operator {
if (type != Type.tVoid)
throw new AssertError("already non void");
type = lvalueType;
if (parent != null && parent.getOperator() == this)
parent.type = lvalueType;
}
public abstract boolean matches(Operator loadop);

@ -136,6 +136,7 @@ public class CaseBlock extends StructuredBlock {
ConstOperator constOp = new ConstOperator
(((SwitchBlock)outer).getInstruction().getType(),
Integer.toString(value));
constOp.makeInitializer();
writer.println("case " + constOp.toString() + ":"
+ (wantBraces ? " {" : ""));
}

@ -27,11 +27,10 @@ import jode.Expression;
public class CompleteSynchronized {
/**
* This combines the monitorenter and the initial expression
* into a synchronized statement
* This combines the monitorenter into a synchronized statement
* @param flow The FlowBlock that is transformed
*/
public static boolean transform(SynchronizedBlock synBlock,
public static boolean enter(SynchronizedBlock synBlock,
StructuredBlock last) {
if (!(last.outer instanceof SequentialBlock))
@ -59,27 +58,36 @@ public class CompleteSynchronized {
synBlock.isEntered = true;
synBlock.moveDefinitions(last.outer,last);
last.replace(last.outer);
return true;
}
/**
* This combines the initial expression describing the object
* into a synchronized statement
* @param flow The FlowBlock that is transformed
*/
public static boolean combineObject(SynchronizedBlock synBlock,
StructuredBlock last) {
/* Is there another expression? */
if (!(last.outer instanceof SynchronizedBlock))
if (!(last.outer instanceof SequentialBlock))
return false;
Expression object;
try {
SequentialBlock sequBlock =
(SequentialBlock) synBlock.outer;
SequentialBlock sequBlock = (SequentialBlock) last.outer;
ComplexExpression assign = (ComplexExpression)
((InstructionBlock) sequBlock.subBlocks[0]).getInstruction();
if (((LocalStoreOperator) assign.getOperator()).
getLocalInfo() != synBlock.local.getLocalInfo())
return true;
return false;
object = assign.getSubExpressions()[0];
} catch (ClassCastException ex) {
return true;
return false;
}
synBlock.object = object;

@ -20,6 +20,7 @@ import jode.Expression;
import jode.TabbedPrintWriter;
import jode.LocalInfo;
import jode.LocalStoreOperator;
import jode.ComplexExpression;
/**
* This is the structured block for atomic instructions.
@ -69,10 +70,13 @@ public class InstructionBlock extends InstructionContainer {
throws java.io.IOException
{
if (isDeclaration) {
writer.println
(((LocalStoreOperator) instr.getOperator())
.getLocalInfo().getType().toString()
+ " " + instr.simplify().toString() + ";");
LocalInfo local = ((LocalStoreOperator) instr.getOperator())
.getLocalInfo();
Expression expr =
((ComplexExpression) instr).getSubExpressions()[0];
expr.makeInitializer();
writer.println(local.getType() + " " + local.getName() + " = "
+ expr.simplify().toString() + ";");
} else {
if (instr.getType() != jode.Type.tVoid)
writer.print("PUSH ");

@ -100,10 +100,22 @@ public class SequentialBlock extends StructuredBlock {
* any local Variable, but lets the first sub block do this.
*/
declare = new VariableSet();
/* First we can forget any variable that is already declared.
*/
used.subtractExact(done);
/* Second, tell the first sub block that he must declare all
* variables _we_ use. */
subBlocks[0].used.unionExact(used);
subBlocks[0].makeDeclaration(done);
/* Now add the variables to the done set, since the first
* sub block has declared them.
*/
done.unionExact(used);
subBlocks[1].makeDeclaration(done);
/* Now undo the change to done. Note that the second instruction
* made done and used disjunct.
*/
done.subtractExact(used);
}
public void dumpInstruction(TabbedPrintWriter writer)

@ -341,16 +341,23 @@ public abstract class StructuredBlock {
declare = new VariableSet();
java.util.Enumeration enum = used.elements();
while (enum.hasMoreElements()) {
LocalInfo local = ((LocalInfo) enum.nextElement()).getLocalInfo();
if (!declare.contains(local))
LocalInfo local = (LocalInfo) enum.nextElement();
LocalInfo previous = done.findLocal(local.getName());
if (previous == null)
declare.addElement(local);
else if (!previous.equals(local)) {
/* A name conflict happened. */
local.makeNameUnique();
declare.addElement(local);
}
declare.subtractExact(done);
}
done.unionExact(declare);
StructuredBlock[] subs = getSubBlocks();
for (int i=0; i<subs.length; i++)
subs[i].makeDeclaration(done);
/* remove the variables again, since we leave the scope.
*/
done.subtractExact(declare);
}
public void checkConsistent() {

@ -81,7 +81,7 @@ public class SynchronizedBlock extends StructuredBlock {
throws java.io.IOException
{
if (!isEntered)
writer.print("/* missing monitorenter */");
writer.println("MISSING MONITORENTER");
writer.println("synchronized ("
+ (object != null
? object.simplify().toString()
@ -93,6 +93,9 @@ public class SynchronizedBlock extends StructuredBlock {
}
public boolean doTransformations() {
return CompleteSynchronized.transform(this, flowBlock.lastModified);
StructuredBlock last = flowBlock.lastModified;
return (!isEntered && CompleteSynchronized.enter(this, last))
|| (isEntered && object == null
&& CompleteSynchronized.combineObject(this, last));
}
}

@ -162,8 +162,6 @@ public class TransformExceptionHandlers {
* | ...
* `- catch block
*/
static int serialno=0;
static void analyzeCatchBlock(Type type,
FlowBlock tryFlow, FlowBlock catchFlow) {
@ -179,7 +177,7 @@ public class TransformExceptionHandlers {
&& ((PopOperator) instr).getCount() == 1) {
/* The exception is ignored. Create a dummy local for it */
local = new LocalInfo(-1);
local.setName("exception_"+(serialno++)+"_");
local.setName("exception");
firstInstr.removeBlock();
} else if (instr instanceof jode.LocalStoreOperator) {

@ -84,6 +84,16 @@ public class VariableSet implements Cloneable {
return false;
}
/**
* Checks if the variable set contains a local with the given name.
*/
public LocalInfo findLocal(String name) {
for (int i=0; i<count;i++)
if (locals[i].getName().equals(name))
return locals[i];
return null;
}
/**
* Removes a local info from this variable set.
*/

Loading…
Cancel
Save