Changed version to 1.2

Add 2001 to copyright years.
Better JSR/synchronized handling (see Changelog)
Better .class field handling
Fixed memory usage of UnifyHash.
Fixed moving of field initializers.


git-svn-id: https://svn.code.sf.net/p/jode/code/branches/branch_1_1@1298 379699f6-c40d-0410-875b-85095c16579e
branch_1_1
hoenicke 24 years ago
parent 4aebd22542
commit 1f87c3817c
  1. 37
      jode/ChangeLog
  2. 2
      jode/configure.in
  3. 4
      jode/jode/GlobalOptions.java.in
  4. 15
      jode/jode/bytecode/BytecodeInfo.java.in
  5. 2
      jode/jode/bytecode/ClassInfo.java.in
  6. 38
      jode/jode/bytecode/SearchPath.java
  7. 2
      jode/jode/decompiler/Main.java
  8. 67
      jode/jode/expr/IfThenElseOperator.java
  9. 3
      jode/jode/expr/InvokeOperator.java.in
  10. 12
      jode/jode/flow/CatchBlock.java.in
  11. 11
      jode/jode/flow/EmptyBlock.java
  12. 12
      jode/jode/flow/StructuredBlock.java.in
  13. 30
      jode/jode/flow/TransformConstructors.java
  14. 371
      jode/jode/flow/TransformExceptionHandlers.java.in
  15. 6
      jode/jode/obfuscator/ClassBundle.java.in
  16. 24
      jode/jode/obfuscator/TranslationTable.java.in
  17. 2
      jode/jode/obfuscator/modules/ModifierMatcher.java.in
  18. 2
      jode/jode/type/ClassInterfacesType.java
  19. 75
      jode/jode/util/UnifyHash.java.in

@ -1,3 +1,40 @@
2001-02-04 Jochen Hoenicke <jochen@gnu.org>
* jode/expr/IfThenElseOperator.java (simplify): Allow in the class$
simplification the then and else part to be swapped.
* jode/bytecode/ClassInfo.java.in (read): Accept class version
1.3.
* jode/type/ClassInterfacesType.java (keywords): Added the package
and import keywords.
* jode/flow/TransformExceptionHandlers.java.in:
(getPredecessor): New function.
(getMonitorExitSlot): New function.
(skipFinExitChain): New function.
(removeJSR): Replaced by ...
(removeBadJSR): ... this.
(checkAndRemoveJSR): Use the new functions. Much simpler and
handles nested synchronized blocks. It now traces the whole JSR
and monitorexit chain before a jump to the first entry via
skipFinExitChain, then checks and remove the first JSR
resp. monitorexit. JSR jumps are simply ignored now.
(checkAndRemoveMonitorExit): likewise.
* jode/flow/StructuredBlock.java.in (prependBlock): New function.
* jode/flow/CatchBlock.java.in (makeDeclaration): Generate name
of dummyLocal, since nobody else will generate it.
2001-02-03 Jochen Hoenicke <jochen@gnu.org>
* jode/bytecode/BytecodeInfo.java.in (read): Remove bogus
exceptionHandlers, whose catchers just throw the exception again.
This kind of entries are inserted by an obfuscator and would break
JODE.
* jode/util/UnifyHash.java.in (iterateHashCode): Call cleanUp,
to clean unneeded references.
* jode/flow/TransformConstructors.java (transformOneField):
Changed to private. Take field number as parameter. Check that
expression doesn't contain a FieldOperator for a later field of
the same class or a PutFieldOperator. Changed all callers.
2001-02-01 Jochen Hoenicke <jochen@gnu.org> 2001-02-01 Jochen Hoenicke <jochen@gnu.org>
* jode/jvm/CodeVerifier.java.in (Type.mergeType): If array elem * jode/jvm/CodeVerifier.java.in (Type.mergeType): If array elem

@ -1,7 +1,7 @@
dnl Process this file with autoconf to produce a configure script. dnl Process this file with autoconf to produce a configure script.
AC_INIT() AC_INIT()
AM_INIT_AUTOMAKE(jode, 1.0.93) AM_INIT_AUTOMAKE(jode, 1.0.94)
dnl Checks for programs. dnl Checks for programs.
dnl AC_PROG_CXX dnl AC_PROG_CXX

@ -1,4 +1,4 @@
/* GlobalOptions Copyright (C) 1999-2000 Jochen Hoenicke. /* GlobalOptions Copyright (C) 1999-2001 Jochen Hoenicke.
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -25,7 +25,7 @@ public class GlobalOptions {
public final static String version = "@VERSION@"; public final static String version = "@VERSION@";
public final static String email = "jochen@gnu.org"; public final static String email = "jochen@gnu.org";
public final static String copyright = public final static String copyright =
"Jode (c) 1998-2000 Jochen Hoenicke <"+email+">"; "Jode (c) 1998-2001 Jochen Hoenicke <"+email+">";
public final static String URL = "http://jode.sourceforge.net/"; public final static String URL = "http://jode.sourceforge.net/";
public static PrintWriter err = new PrintWriter(System.err, true); public static PrintWriter err = new PrintWriter(System.err, true);

@ -847,6 +847,21 @@ public class BytecodeInfo extends BinaryInfo implements Opcodes {
int index = input.readUnsignedShort(); int index = input.readUnsignedShort();
exceptionHandlers[i].type = (index == 0) ? null exceptionHandlers[i].type = (index == 0) ? null
: cp.getClassName(index); : cp.getClassName(index);
if (exceptionHandlers[i].catcher.getOpcode() == opc_athrow) {
/* There is an obfuscator, which inserts bogus
* exception entries jumping directly to a throw
* instruction. Remove those handlers.
*/
handlersLength--;
i--;
}
}
if (handlersLength < exceptionHandlers.length) {
Handler[] newHandlers = new Handler[handlersLength];
System.arraycopy(exceptionHandlers, 0, newHandlers, 0,
handlersLength);
exceptionHandlers = newHandlers;
} }
} }
readAttributes(cp, input, FULLINFO); readAttributes(cp, input, FULLINFO);

@ -288,7 +288,7 @@ public class ClassInfo extends BinaryInfo {
int version = input.readUnsignedShort(); int version = input.readUnsignedShort();
version |= input.readUnsignedShort() << 16; version |= input.readUnsignedShort() << 16;
if (version < (45 << 16 | 0) if (version < (45 << 16 | 0)
|| version > (46 << 16 | 0)) || version > (47 << 16 | 0))
throw new ClassFormatException("Wrong class version"); throw new ClassFormatException("Wrong class version");
/* constant pool */ /* constant pool */

@ -379,26 +379,26 @@ public class SearchPath {
while ((ze = zis.getNextEntry()) != null) { while ((ze = zis.getNextEntry()) != null) {
if (ze.getName().equals(fullname)) { if (ze.getName().equals(fullname)) {
///#ifdef JDK11 ///#ifdef JDK11
// The skip method in jdk1.1.7 ZipInputStream /// // The skip method in jdk1.1.7 ZipInputStream
// is buggy. We return a wrapper that fixes /// // is buggy. We return a wrapper that fixes
// this. /// // this.
return new FilterInputStream(zis) { /// return new FilterInputStream(zis) {
private byte[] tmpbuf = new byte[512]; /// private byte[] tmpbuf = new byte[512];
public long skip(long n) throws IOException { /// public long skip(long n) throws IOException {
long skipped = 0; /// long skipped = 0;
while (n > 0) { /// while (n > 0) {
int count = read(tmpbuf, 0, /// int count = read(tmpbuf, 0,
(int)Math.min(n, 512L)); /// (int)Math.min(n, 512L));
if (count == -1) /// if (count == -1)
return skipped; /// return skipped;
skipped += count; /// skipped += count;
n -= count; /// n -= count;
} /// }
return skipped; /// return skipped;
} /// }
}; /// };
///#else ///#else
/// return zis; return zis;
///#endif ///#endif
} }
zis.closeEntry(); zis.closeEntry();

@ -1,4 +1,4 @@
/* Main Copyright (C) 1998-1999 Jochen Hoenicke. /* Main Copyright (C) 1998-2001 Jochen Hoenicke.
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by

@ -59,37 +59,46 @@ public class IfThenElseOperator extends Operator {
} }
} }
if (subExpressions[0] instanceof CompareUnaryOperator if (subExpressions[0] instanceof CompareUnaryOperator
&& (subExpressions[1] instanceof GetFieldOperator) && ((((CompareUnaryOperator) subExpressions[0])
&& (subExpressions[2] instanceof StoreInstruction)) { .getOperatorIndex() & ~1) == Operator.COMPARE_OP)) {
// Check for
// class$classname != null ? class$classname :
// (class$classname = class$("classname"))
// and replace with
// classname.class
CompareUnaryOperator cmp CompareUnaryOperator cmp
= (CompareUnaryOperator) subExpressions[0]; = (CompareUnaryOperator) subExpressions[0];
GetFieldOperator get = (GetFieldOperator) subExpressions[1]; int cmpType = cmp.getOperatorIndex() & 1;
StoreInstruction put = (StoreInstruction) subExpressions[2]; if ((subExpressions[2 - cmpType] instanceof GetFieldOperator)
FieldAnalyzer field; && (subExpressions[1 + cmpType] instanceof StoreInstruction)) {
if (cmp.getOperatorIndex() == Operator.NOTEQUALS_OP // Check for
&& put.getLValue() instanceof PutFieldOperator // class$classname != null ? class$classname :
&& ((field = ((PutFieldOperator)put.getLValue()).getField()) // (class$classname = class$("classname"))
!= null) && field.isSynthetic() // and replace with
&& put.lvalueMatches(get) // classname.class
&& cmp.subExpressions[0] instanceof GetFieldOperator GetFieldOperator get
&& put.lvalueMatches((GetFieldOperator)cmp.subExpressions[0]) = (GetFieldOperator) subExpressions[2 - cmpType];
&& put.subExpressions[1] instanceof InvokeOperator) { StoreInstruction put
InvokeOperator invoke = (InvokeOperator) put.subExpressions[1]; = (StoreInstruction) subExpressions[1 + cmpType];
if (invoke.isGetClass() int opIndex = cmp.getOperatorIndex();
&& invoke.subExpressions[0] instanceof ConstOperator FieldAnalyzer field;
&& (invoke.subExpressions[0].getType() if (put.getLValue() instanceof PutFieldOperator
.equals(Type.tString))) { && ((field = ((PutFieldOperator)put.getLValue())
String clazz = (String) .getField()) != null) && field.isSynthetic()
((ConstOperator)invoke.subExpressions[0]).getValue(); && put.lvalueMatches(get)
if (field.setClassConstant(clazz)) && (cmp.subExpressions[0] instanceof GetFieldOperator)
return new ClassFieldOperator(clazz.charAt(0) == '[' && put.lvalueMatches((GetFieldOperator)
? Type.tType(clazz) cmp.subExpressions[0])
: Type.tClass(clazz)); && put.subExpressions[1] instanceof InvokeOperator) {
InvokeOperator invoke = (InvokeOperator)
put.subExpressions[1];
if (invoke.isGetClass()
&& invoke.subExpressions[0] instanceof ConstOperator
&& (invoke.subExpressions[0].getType()
.equals(Type.tString))) {
String clazz = (String)
((ConstOperator)invoke.subExpressions[0])
.getValue();
if (field.setClassConstant(clazz))
return new ClassFieldOperator
(clazz.charAt(0) == '['
? Type.tType(clazz) : Type.tClass(clazz));
}
} }
} }
} }

@ -835,7 +835,8 @@ public final class InvokeOperator extends Operator
* super class and anonymousNew will be set. * super class and anonymousNew will be set.
*/ */
InnerClassInfo outer = getOuterClassInfo(clazz); InnerClassInfo outer = getOuterClassInfo(clazz);
if (outer != null && outer.name == null) if (outer != null && outer.name == null
&& (Options.options & Options.OPTION_ANON) != 0)
anonymousNew = true; anonymousNew = true;
clazzAna = methodAnalyzer.getClassAnalyzer(clazz); clazzAna = methodAnalyzer.getClassAnalyzer(clazz);
if ((~Options.options & if ((~Options.options &

@ -20,6 +20,7 @@
package jode.flow; package jode.flow;
import jode.type.Type; import jode.type.Type;
import jode.decompiler.LocalInfo; import jode.decompiler.LocalInfo;
import jode.decompiler.Declarable;
import jode.expr.Expression; import jode.expr.Expression;
import jode.expr.LocalLoadOperator; import jode.expr.LocalLoadOperator;
import jode.expr.LocalStoreOperator; import jode.expr.LocalStoreOperator;
@ -27,6 +28,7 @@ import jode.expr.StoreInstruction;
import jode.util.SimpleSet; import jode.util.SimpleSet;
import @COLLECTIONS@.Collections; import @COLLECTIONS@.Collections;
import @COLLECTIONS@.Iterator;
import @COLLECTIONS@.Set; import @COLLECTIONS@.Set;
@ -160,6 +162,16 @@ public class CatchBlock extends StructuredBlock {
ib.appendBlock(catchBlock); ib.appendBlock(catchBlock);
catchBlock = ib; catchBlock = ib;
exceptionLocal = dummyLocal; exceptionLocal = dummyLocal;
String localName = dummyLocal.guessName();
Iterator doneIter = done.iterator();
while (doneIter.hasNext()) {
Declarable previous = (Declarable) doneIter.next();
if (localName.equals(previous.getName())) {
/* A name conflict happened. */
dummyLocal.makeNameUnique();
break;
}
}
} }
} }
} }

@ -56,6 +56,17 @@ public class EmptyBlock extends StructuredBlock {
return block; return block;
} }
/**
* Prepends a block to this block.
* @return the new combined block.
*/
public StructuredBlock prependBlock(StructuredBlock block) {
/* For empty blocks: append == prepend modulo jump */
block = appendBlock(block);
block.moveJump(this.jump);
return block;
}
public void dumpInstruction(TabbedPrintWriter writer) public void dumpInstruction(TabbedPrintWriter writer)
throws java.io.IOException throws java.io.IOException
{ {

@ -301,6 +301,18 @@ public abstract class StructuredBlock {
} }
} }
/**
* Prepends a block to this block.
* @return the new combined block.
*/
public StructuredBlock prependBlock(StructuredBlock block) {
SequentialBlock sequBlock = new SequentialBlock();
sequBlock.replace(this);
sequBlock.setFirst(block);
sequBlock.setSecond(this);
return sequBlock;
}
/** /**
* Removes this block, or replaces it with an EmptyBlock. * Removes this block, or replaces it with an EmptyBlock.
*/ */

@ -1,4 +1,4 @@
/* TransformConstructors Copyright (C) 1998-1999 Jochen Hoenicke. /* TransformConstructors Copyright (C) 1998-2001 Jochen Hoenicke.
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -573,7 +573,8 @@ public class TransformConstructors {
* @param expr the initializer to check * @param expr the initializer to check
* @return the transformed initializer or null if expr is not valid. * @return the transformed initializer or null if expr is not valid.
*/ */
public Expression transformFieldInitializer(Expression expr) { private Expression transformFieldInitializer(int fieldSlot,
Expression expr) {
if (expr instanceof LocalVarOperator) { if (expr instanceof LocalVarOperator) {
if (!(expr instanceof LocalLoadOperator)) { if (!(expr instanceof LocalLoadOperator)) {
if ((GlobalOptions.debuggingFlags if ((GlobalOptions.debuggingFlags
@ -594,11 +595,21 @@ public class TransformConstructors {
+" "+outerValues); +" "+outerValues);
return null; return null;
} }
if (expr instanceof FieldOperator) {
if (expr instanceof PutFieldOperator)
return null;
FieldOperator fo = (FieldOperator) expr;
if (fo.getClassInfo() == clazzAnalyzer.getClazz()
&& clazzAnalyzer.getFieldIndex(fo.getFieldName(),
fo.getFieldType()) >= fieldSlot)
return null;
}
if (expr instanceof Operator) { if (expr instanceof Operator) {
Operator op = (Operator) expr; Operator op = (Operator) expr;
Expression[] subExpr = op.getSubExpressions(); Expression[] subExpr = op.getSubExpressions();
for (int i=0; i< subExpr.length; i++) { for (int i=0; i< subExpr.length; i++) {
Expression transformed = transformFieldInitializer(subExpr[i]); Expression transformed
= transformFieldInitializer(fieldSlot, subExpr[i]);
if (transformed == null) if (transformed == null)
return null; return null;
if (transformed != subExpr[i]) if (transformed != subExpr[i])
@ -675,7 +686,7 @@ public class TransformConstructors {
break big_loop; break big_loop;
Expression expr = store.getSubExpressions()[1]; Expression expr = store.getSubExpressions()[1];
expr = transformFieldInitializer(expr); expr = transformFieldInitializer(field, expr);
if (expr == null) if (expr == null)
break big_loop; break big_loop;
@ -762,8 +773,14 @@ public class TransformConstructors {
} }
} }
int field = clazzAnalyzer.getFieldIndex(pfo.getFieldName(),
pfo.getFieldType());
if (field <= lastField)
return -1;
Expression expr = store.getSubExpressions()[1]; Expression expr = store.getSubExpressions()[1];
expr = transformFieldInitializer(expr); expr = transformFieldInitializer(field, expr);
if (expr == null) if (expr == null)
return -1; return -1;
@ -772,9 +789,6 @@ public class TransformConstructors {
GlobalOptions.err.println(" field " + pfo.getFieldName() GlobalOptions.err.println(" field " + pfo.getFieldName()
+ " = " + expr); + " = " + expr);
int field = clazzAnalyzer.getFieldIndex(pfo.getFieldName(),
pfo.getFieldType());
// if field does not exists: -1 <= lastField. // if field does not exists: -1 <= lastField.
if (field <= lastField if (field <= lastField
|| !(clazzAnalyzer.getField(field).setInitializer(expr))) { || !(clazzAnalyzer.getField(field).setInitializer(expr))) {

@ -180,11 +180,7 @@ public class TransformExceptionHandlers {
* @param ret the ReturnBlock. * @param ret the ReturnBlock.
*/ */
private void removeReturnLocal(ReturnBlock ret) { private void removeReturnLocal(ReturnBlock ret) {
if (ret.outer == null StructuredBlock pred = getPredecessor(ret);
|| !(ret.outer instanceof SequentialBlock))
return;
StructuredBlock pred = ret.outer.getSubBlocks()[0];
if (!(pred instanceof InstructionBlock)) if (!(pred instanceof InstructionBlock))
return; return;
Expression instr = ((InstructionBlock) pred).getInstruction(); Expression instr = ((InstructionBlock) pred).getInstruction();
@ -203,15 +199,13 @@ public class TransformExceptionHandlers {
} }
/** /**
* Remove the JSR's jumping to the specified subRoutine. It * Remove the wrongly placed JSRs jumping to the specified
* is checked if the next block is a leaving instruction, and * subRoutine. The right JSRs are already removed, but we have to
* otherwise the JsrBlock is not removed (to give the user a * replace the wrong ones with a warning.
* hint that something went wrong). This will also remove the
* local javac generates for returns.
* @param tryFlow the FlowBLock of the try block. * @param tryFlow the FlowBLock of the try block.
* @param subRoutine the FlowBlock of the sub routine. * @param subRoutine the FlowBlock of the sub routine.
*/ */
private void removeJSR(FlowBlock tryFlow, StructuredBlock catchBlock, private void removeBadJSR(FlowBlock tryFlow, StructuredBlock catchBlock,
FlowBlock subRoutine) { FlowBlock subRoutine) {
Jump nextJump; Jump nextJump;
for (Jump jumps = tryFlow.getJumps(subRoutine); for (Jump jumps = tryFlow.getJumps(subRoutine);
@ -225,64 +219,96 @@ public class TransformExceptionHandlers {
/* This is the mandatory jsr in the catch block */ /* This is the mandatory jsr in the catch block */
continue; continue;
} }
if (prev.outer.getNextFlowBlock() != null) { /* We have a JSR to the subroutine, which is badly placed.
/* The jsr is directly before a jump, okay. */ * We complain here.
tryFlow.removeSuccessor(jumps); */
prev.removeJump(); DescriptionBlock msg
prev.outer.removeBlock(); = new DescriptionBlock("ERROR: JSR FINALLY BLOCK!");
continue; tryFlow.removeSuccessor(jumps);
} prev.removeJump();
if (prev.outer.outer instanceof SequentialBlock msg.replace(prev.outer);
&& prev.outer.outer.getSubBlocks()[0] == prev.outer) { } else {
SequentialBlock seq = (SequentialBlock) prev.outer.outer; /* We have a jump to the subroutine, that is wrong.
if (seq.subBlocks[1] instanceof JsrBlock * We complain here.
|| (seq.subBlocks[1] instanceof SequentialBlock */
&& seq.subBlocks[1].getSubBlocks()[0] DescriptionBlock msg
instanceof JsrBlock)) { = new DescriptionBlock("ERROR: GOTO FINALLY BLOCK!");
/* The jsr is followed by a jsr, okay. */ tryFlow.removeSuccessor(jumps);
tryFlow.removeSuccessor(jumps); prev.removeJump();
prev.removeJump(); prev.appendBlock(msg);
prev.outer.removeBlock(); }
continue; }
} }
if (seq.subBlocks[1] instanceof ReturnBlock
&& !(seq.subBlocks[1] instanceof ThrowBlock)) { private static StructuredBlock getPredecessor(StructuredBlock stmt)
{
/* The jsr is followed by a return, okay. */ if (stmt.outer instanceof SequentialBlock) {
tryFlow.removeSuccessor(jumps); SequentialBlock seq = (SequentialBlock) stmt.outer;
prev.removeJump(); if (seq.subBlocks[1] == stmt)
ReturnBlock ret = (ReturnBlock) seq.subBlocks[1]; return seq.subBlocks[0];
prev.outer.removeBlock(); else if (seq.outer instanceof SequentialBlock)
return seq.outer.getSubBlocks()[0];
removeReturnLocal(ret); }
continue; return null;
} }
}
/**
* Gets the slot of the monitorexit instruction instr in the
* stmt, or -1 if stmt isn't a InstructionBlock with a
* monitorexit instruction.
* @param stmt the stmt, may be null.
*/
private static int getMonitorExitSlot(StructuredBlock stmt) {
if (stmt instanceof InstructionBlock) {
Expression instr = ((InstructionBlock) stmt).getInstruction();
if (instr instanceof MonitorExitOperator) {
MonitorExitOperator monExit = (MonitorExitOperator)instr;
if (monExit.getFreeOperandCount() == 0
&& (monExit.getSubExpressions()[0]
instanceof LocalLoadOperator))
return ((LocalLoadOperator) monExit.getSubExpressions()[0])
.getLocalInfo().getSlot();
} }
/* Now we have a jump to the subroutine, that is wrong.
* We complain here.
*/
DescriptionBlock msg
= new DescriptionBlock("ERROR: GOTO FINALLY BLOCK!");
tryFlow.removeSuccessor(jumps);
prev.removeJump();
prev.appendBlock(msg);
} }
return -1;
} }
public void checkAndRemoveJSR(FlowBlock tryFlow, private boolean isMonitorExitSubRoutine(FlowBlock subRoutine,
StructuredBlock catchBlock, LocalInfo local) {
FlowBlock subRoutine, if (transformSubRoutine(subRoutine.block)
int startOutExit, int endOutExit) { && getMonitorExitSlot(subRoutine.block) == local.getSlot())
boolean foundSub = false; return true;
return false;
}
private static StructuredBlock skipFinExitChain(StructuredBlock block)
{
StructuredBlock pred, result;
if (block instanceof ReturnBlock)
pred = getPredecessor(block);
else
pred = block;
result = null;
while (pred instanceof JsrBlock
|| getMonitorExitSlot(pred) >= 0) {
result = pred;
pred = getPredecessor(pred);
}
return result;
}
private void checkAndRemoveJSR(FlowBlock tryFlow,
StructuredBlock catchBlock,
FlowBlock subRoutine,
int startOutExit, int endOutExit) {
Iterator iter = tryFlow.getSuccessors().iterator(); Iterator iter = tryFlow.getSuccessors().iterator();
dest_loop: dest_loop:
while (iter.hasNext()) { while (iter.hasNext()) {
FlowBlock dest = (FlowBlock) iter.next(); FlowBlock dest = (FlowBlock) iter.next();
if (dest == subRoutine) { if (dest == subRoutine)
foundSub = true;
continue dest_loop; continue dest_loop;
}
boolean isFirstJump = true; boolean isFirstJump = true;
for (Jump jumps = tryFlow.getJumps(dest); for (Jump jumps = tryFlow.getJumps(dest);
@ -295,41 +321,34 @@ public class TransformExceptionHandlers {
*/ */
continue; continue;
} }
if (prev instanceof JsrBlock) {
/* The jump is directly preceeded by a jsr.
* Everything okay.
*/
continue;
}
if (prev instanceof EmptyBlock if (prev instanceof EmptyBlock
&& prev.outer instanceof JsrBlock) { && prev.outer instanceof JsrBlock) {
/* If jump is a jsr check the outer /* This jump is really a jsr, since it doesn't
* block instead. * leave the block forever, we can ignore it.
*/ */
prev = prev.outer; continue;
}
if ((prev instanceof ReturnBlock
|| prev instanceof JsrBlock)
&& prev.outer instanceof SequentialBlock) {
SequentialBlock seq = (SequentialBlock) prev.outer;
if (seq.subBlocks[1] == prev
&& (seq.subBlocks[0] instanceof JsrBlock)) {
/* The jump is preceeded by another jsr, okay.
*/
continue;
}
if (seq.subBlocks[0] == prev
&& seq.outer instanceof SequentialBlock
&& (seq.outer.getSubBlocks()[0] instanceof JsrBlock)) {
/* Again the jump is preceeded by another jsr, okay.
*/
continue;
}
} }
StructuredBlock pred = skipFinExitChain(prev);
if (pred instanceof JsrBlock) {
StructuredBlock jsrInner = ((JsrBlock) pred).innerBlock;
if (jsrInner instanceof EmptyBlock
&& jsrInner.jump != null
&& jsrInner.jump.destination == subRoutine) {
/* The jump is preceeded by the right jsr. Remove
* the jsr.
*/
tryFlow.removeSuccessor(jsrInner.jump);
jsrInner.removeJump();
pred.removeBlock();
if (prev instanceof ReturnBlock)
removeReturnLocal((ReturnBlock) prev);
continue;
}
}
if (isFirstJump) { if (pred == null && isFirstJump) {
/* Now we have a jump that is not preceded by the /* Now we have a jump that is not preceded by any
* jsr. There's a last chance: the jump jumps * jsr. There's a last chance: the jump jumps
* directly to a correct jsr instruction, which * directly to a correct jsr instruction, which
* lies outside the try/catch block. * lies outside the try/catch block.
@ -360,45 +379,21 @@ public class TransformExceptionHandlers {
*/ */
DescriptionBlock msg DescriptionBlock msg
= new DescriptionBlock("ERROR: NO JSR TO FINALLY"); = new DescriptionBlock("ERROR: NO JSR TO FINALLY");
prev.appendBlock(msg); if (pred != null)
msg.moveJump(jumps); pred.prependBlock(msg);
} else {
} prev.appendBlock(msg);
if (foundSub) msg.moveJump(prev.jump);
removeJSR(tryFlow, catchBlock, subRoutine); }
}
static boolean isMonitorExit(Expression instr, LocalInfo local) {
if (instr instanceof MonitorExitOperator) {
MonitorExitOperator monExit = (MonitorExitOperator)instr;
if (monExit.getFreeOperandCount() == 0
&& monExit.getSubExpressions()[0] instanceof LocalLoadOperator
&& (((LocalLoadOperator) monExit.getSubExpressions()[0])
.getLocalInfo().getSlot() == local.getSlot())) {
return true;
} }
} }
return false; removeBadJSR(tryFlow, catchBlock, subRoutine);
} }
boolean isMonitorExitSubRoutine(FlowBlock subRoutine, LocalInfo local) { private void checkAndRemoveMonitorExit(FlowBlock tryFlow,
if (transformSubRoutine(subRoutine.block)) { StructuredBlock catchBlock,
if (subRoutine.block instanceof InstructionBlock) { LocalInfo local,
Expression instr = int start, int end) {
((InstructionBlock)subRoutine.block)
.getInstruction();
if (isMonitorExit(instr, local)) {
return true;
}
}
}
return false;
}
public void checkAndRemoveMonitorExit(FlowBlock tryFlow,
StructuredBlock catchBlock,
LocalInfo local,
int start, int end) {
FlowBlock subRoutine = null; FlowBlock subRoutine = null;
Iterator succs = tryFlow.getSuccessors().iterator(); Iterator succs = tryFlow.getSuccessors().iterator();
dest_loop: dest_loop:
@ -409,91 +404,57 @@ public class TransformExceptionHandlers {
jumps != null; jumps = jumps.next, isFirstJump = false) { jumps != null; jumps = jumps.next, isFirstJump = false) {
StructuredBlock prev = jumps.prev; StructuredBlock prev = jumps.prev;
if (prev instanceof ThrowBlock) { if (prev instanceof ThrowBlock) {
/* The jump is a throw. We have a catch all block /* The jump is a throw. We have a catch-all block
* that will do the monitorexit. * that will do the finally.
*/
continue;
}
if (prev instanceof JsrBlock) {
/* The jump is directly preceeded by a jsr.
*/ */
continue; continue;
} }
if (prev instanceof EmptyBlock if (prev instanceof EmptyBlock
&& prev.outer instanceof JsrBlock) { && prev.outer instanceof JsrBlock) {
/* If jump is a jsr check the outer /* This jump is really a jsr, since it doesn't
* block instead. * leave the block forever, we can ignore it.
*/
prev = prev.outer;
}
/* If the block is a jsr or a return block, check if
* it is preceeded by another jsr.
*/
if ((prev instanceof JsrBlock
|| prev instanceof ReturnBlock)
&& prev.outer instanceof SequentialBlock) {
SequentialBlock seq = (SequentialBlock) prev.outer;
StructuredBlock pred = null;
if (seq.subBlocks[1] == prev)
pred = seq.subBlocks[0];
else if (seq.outer instanceof SequentialBlock)
pred = seq.outer.getSubBlocks()[0];
if (pred != null) {
if (pred instanceof JsrBlock)
/* The jump is preceeded by another jsr, okay.
*/
continue;
if (pred instanceof InstructionBlock) {
Expression instr =
((InstructionBlock)pred).getInstruction();
if (isMonitorExit(instr, local)) {
pred.removeBlock();
if (prev instanceof ReturnBlock)
removeReturnLocal((ReturnBlock) prev);
continue;
}
}
}
}
if (prev instanceof InstructionBlock
&& isMonitorExit(((InstructionBlock)prev).instr, local)) {
/* This is probably the last expression in the
* synchronized block, and has the right monitor exit
* attached. Remove this block.
*/
prev.removeBlock();
continue;
}
if (isFirstJump) {
/* This is the first jump to that destination.
* Check if the destination does the monitorExit
*/ */
continue;
}
StructuredBlock pred = skipFinExitChain(prev);
if (pred instanceof JsrBlock) {
StructuredBlock jsrInner = ((JsrBlock) pred).innerBlock;
if (jsrInner instanceof EmptyBlock
&& jsrInner.jump != null) {
FlowBlock dest = jsrInner.jump.destination;
/* The block is a jsr that is not preceeded by
* another jsr. This must be the monitorexit
* subroutine.
*/
if (prev instanceof JsrBlock) {
if (subRoutine == null if (subRoutine == null
&& successor.getAddr() >= start && dest.getAddr() >= start
&& successor.getNextAddr() <= end) { && dest.getNextAddr() <= end) {
successor.analyze(start, end); dest.analyze(start, end);
if (isMonitorExitSubRoutine(dest, local))
if (isMonitorExitSubRoutine(successor, local)) subRoutine = dest;
subRoutine = successor;
} }
if (subRoutine == successor) if (dest == subRoutine) {
continue dest_loop; /* The jump is preceeded by the right jsr. Remove
* the jsr.
*/
tryFlow.removeSuccessor(jsrInner.jump);
jsrInner.removeJump();
pred.removeBlock();
if (prev instanceof ReturnBlock)
removeReturnLocal((ReturnBlock) prev);
continue;
}
} }
} else if (getMonitorExitSlot(pred) == local.getSlot()) {
/* The jump is preceeded by the right monitor
* exit instruction.
*/
pred.removeBlock();
if (prev instanceof ReturnBlock)
removeReturnLocal((ReturnBlock) prev);
continue;
}
if (pred == null && isFirstJump) {
/* Now we have a jump that is not preceded by a /* Now we have a jump that is not preceded by a
* monitorexit. There's a last chance: the jump * monitorexit. There's a last chance: the jump
* jumps directly to the correct monitorexit * jumps directly to the correct monitorexit
@ -521,17 +482,15 @@ public class TransformExceptionHandlers {
} }
if (subRoutine == dest) { if (subRoutine == dest) {
successor.removeSuccessor(jsrInner.jump);
jsrInner.removeJump();
sb.removeBlock(); sb.removeBlock();
continue dest_loop; continue dest_loop;
} }
} }
if (sb instanceof InstructionBlock) { if (getMonitorExitSlot(sb) == local.getSlot()) {
Expression instr = ((InstructionBlock)sb) sb.removeBlock();
.getInstruction(); continue dest_loop;
if (isMonitorExit(instr, local)) {
sb.removeBlock();
continue dest_loop;
}
} }
} }
} }
@ -546,7 +505,7 @@ public class TransformExceptionHandlers {
} }
if (subRoutine != null) { if (subRoutine != null) {
removeJSR(tryFlow, catchBlock, subRoutine); removeBadJSR(tryFlow, catchBlock, subRoutine);
tryFlow.mergeAddr(subRoutine); tryFlow.mergeAddr(subRoutine);
} }
} }

@ -38,7 +38,7 @@ import @COLLECTIONS@.TreeMap;
import @COLLECTIONEXTRA@.UnsupportedOperationException; import @COLLECTIONEXTRA@.UnsupportedOperationException;
///#ifdef JDK12 ///#ifdef JDK12
///import @COLLECTIONS@.WeakHashMap; import @COLLECTIONS@.WeakHashMap;
///#endif ///#endif
public class ClassBundle implements OptionHandler { public class ClassBundle implements OptionHandler {
@ -74,9 +74,9 @@ public class ClassBundle implements OptionHandler {
} }
///#ifdef JDK12 ///#ifdef JDK12
/// private static final Map aliasesHash = new WeakHashMap(); private static final Map aliasesHash = new WeakHashMap();
///#else ///#else
private static final Map aliasesHash = new HashMap(); /// private static final Map aliasesHash = new HashMap();
///#endif ///#endif
private static final Map clazzCache = new HashMap(); private static final Map clazzCache = new HashMap();
private static final Map referenceCache = new HashMap(); private static final Map referenceCache = new HashMap();

@ -24,7 +24,7 @@ import @COLLECTIONS@.TreeMap;
import @COLLECTIONS@.Iterator; import @COLLECTIONS@.Iterator;
///#ifndef JDK12 ///#ifndef JDK12
import @COLLECTIONS@.Comparator; ///import @COLLECTIONS@.Comparator;
///#endif ///#endif
import java.io.InputStream; import java.io.InputStream;
@ -37,17 +37,17 @@ import java.io.IOException;
public class TranslationTable extends TreeMap { public class TranslationTable extends TreeMap {
///#ifndef JDK12 ///#ifndef JDK12
public TranslationTable() { /// public TranslationTable() {
super(createStringComparator()); /// super(createStringComparator());
} /// }
///
private static Comparator createStringComparator() { /// private static Comparator createStringComparator() {
return new Comparator() { /// return new Comparator() {
public int compare(Object o1, Object o2) { /// public int compare(Object o1, Object o2) {
return ((String) o1).compareTo((String) o2); /// return ((String) o1).compareTo((String) o2);
} /// }
}; /// };
} /// }
///#endif ///#endif
public void load(InputStream in) throws IOException { public void load(InputStream in) throws IOException {

@ -109,7 +109,7 @@ public class ModifierMatcher implements IdentifierMatcher, OptionHandler, Clonea
: str.equals("NATIVE") ? Modifier.NATIVE : str.equals("NATIVE") ? Modifier.NATIVE
: str.equals("STATIC") ? Modifier.STATIC : str.equals("STATIC") ? Modifier.STATIC
///#ifdef JDK12 ///#ifdef JDK12
/// : str.equals("STRICT") ? Modifier.STRICT : str.equals("STRICT") ? Modifier.STRICT
///#endif ///#endif
: str.equals("SYNCHRONIZED") ? Modifier.SYNCHRONIZED : str.equals("SYNCHRONIZED") ? Modifier.SYNCHRONIZED
: str.equals("TRANSIENT") ? Modifier.TRANSIENT : str.equals("TRANSIENT") ? Modifier.TRANSIENT

@ -509,6 +509,8 @@ public class ClassInterfacesType extends ReferenceType {
private final static Hashtable keywords = new Hashtable(); private final static Hashtable keywords = new Hashtable();
static { static {
keywords.put("package", Boolean.TRUE);
keywords.put("import", Boolean.TRUE);
keywords.put("if", Boolean.TRUE); keywords.put("if", Boolean.TRUE);
keywords.put("else", Boolean.TRUE); keywords.put("else", Boolean.TRUE);
keywords.put("for", Boolean.TRUE); keywords.put("for", Boolean.TRUE);

@ -1,4 +1,4 @@
/* UnifyHash Copyright (C) 1999 Jochen Hoenicke. /* UnifyHash Copyright (C) 1999-2001 Jochen Hoenicke.
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -19,8 +19,8 @@
package jode.util; package jode.util;
///#ifdef JDK12 ///#ifdef JDK12
///import java.lang.ref.WeakReference; import java.lang.ref.WeakReference;
///import java.lang.ref.ReferenceQueue; import java.lang.ref.ReferenceQueue;
///#endif ///#endif
import @COLLECTIONS@.Comparator; import @COLLECTIONS@.Comparator;
@ -40,28 +40,28 @@ public class UnifyHash extends AbstractCollection {
private static final float DEFAULT_LOAD_FACTOR = 0.75F; private static final float DEFAULT_LOAD_FACTOR = 0.75F;
///#ifdef JDK12 ///#ifdef JDK12
/// private ReferenceQueue queue = new ReferenceQueue(); private ReferenceQueue queue = new ReferenceQueue();
///#endif ///#endif
static class Bucket static class Bucket
///#ifdef JDK12 ///#ifdef JDK12
/// extends WeakReference extends WeakReference
///#endif ///#endif
{ {
///#ifdef JDK12 ///#ifdef JDK12
/// public Bucket(Object o, ReferenceQueue q) { public Bucket(Object o, ReferenceQueue q) {
/// super(o, q); super(o, q);
/// }
///#else
public Bucket(Object o) {
this.obj = o;
}
Object obj;
public Object get() {
return obj;
} }
///#else
/// public Bucket(Object o) {
/// this.obj = o;
/// }
///
/// Object obj;
///
/// public Object get() {
/// return obj;
/// }
///#endif ///#endif
int hash; int hash;
@ -107,21 +107,21 @@ public class UnifyHash extends AbstractCollection {
} }
///#ifdef JDK12 ///#ifdef JDK12
/// public final void cleanUp() { public final void cleanUp() {
/// Bucket died; Bucket died;
/// while ((died = (Bucket)queue.poll()) != null) { while ((died = (Bucket)queue.poll()) != null) {
/// int diedSlot = Math.abs(died.hash % buckets.length); int diedSlot = Math.abs(died.hash % buckets.length);
/// if (buckets[diedSlot] == died) if (buckets[diedSlot] == died)
/// buckets[diedSlot] = died.next; buckets[diedSlot] = died.next;
/// else { else {
/// Bucket b = buckets[diedSlot]; Bucket b = buckets[diedSlot];
/// while (b.next != died) while (b.next != died)
/// b = b.next; b = b.next;
/// b.next = died.next; b.next = died.next;
/// } }
/// size--; size--;
/// } }
/// } }
///#endif ///#endif
@ -131,7 +131,7 @@ public class UnifyHash extends AbstractCollection {
public Iterator iterator() { public Iterator iterator() {
///#ifdef JDK12 ///#ifdef JDK12
/// cleanUp(); cleanUp();
///#endif ///#endif
return new Iterator() { return new Iterator() {
@ -182,6 +182,9 @@ public class UnifyHash extends AbstractCollection {
} }
public Iterator iterateHashCode(final int hash) { public Iterator iterateHashCode(final int hash) {
///#ifdef JDK12
cleanUp();
///#endif
return new Iterator() { return new Iterator() {
private int known = modCount; private int known = modCount;
private Bucket nextBucket private Bucket nextBucket
@ -232,9 +235,9 @@ public class UnifyHash extends AbstractCollection {
int slot = Math.abs(hash % buckets.length); int slot = Math.abs(hash % buckets.length);
///#ifdef JDK12 ///#ifdef JDK12
/// Bucket b = new Bucket(o, queue); Bucket b = new Bucket(o, queue);
///#else ///#else
Bucket b = new Bucket(o); /// Bucket b = new Bucket(o);
///#endif ///#endif
b.hash = hash; b.hash = hash;
b.next = buckets[slot]; b.next = buckets[slot];
@ -243,7 +246,7 @@ public class UnifyHash extends AbstractCollection {
public Object unify(Object o, int hash, Comparator comparator) { public Object unify(Object o, int hash, Comparator comparator) {
///#ifdef JDK12 ///#ifdef JDK12
/// cleanUp(); cleanUp();
///#endif ///#endif
int slot = Math.abs(hash % buckets.length); int slot = Math.abs(hash % buckets.length);
for (Bucket b = buckets[slot]; b != null; b = b.next) { for (Bucket b = buckets[slot]; b != null; b = b.next) {

Loading…
Cancel
Save