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>
* 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.
AC_INIT()
AM_INIT_AUTOMAKE(jode, 1.0.93)
AM_INIT_AUTOMAKE(jode, 1.0.94)
dnl Checks for programs.
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
* 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 email = "jochen@gnu.org";
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 static PrintWriter err = new PrintWriter(System.err, true);

@ -847,6 +847,21 @@ public class BytecodeInfo extends BinaryInfo implements Opcodes {
int index = input.readUnsignedShort();
exceptionHandlers[i].type = (index == 0) ? null
: 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);

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

@ -379,26 +379,26 @@ public class SearchPath {
while ((ze = zis.getNextEntry()) != null) {
if (ze.getName().equals(fullname)) {
///#ifdef JDK11
// The skip method in jdk1.1.7 ZipInputStream
// is buggy. We return a wrapper that fixes
// this.
return new FilterInputStream(zis) {
private byte[] tmpbuf = new byte[512];
public long skip(long n) throws IOException {
long skipped = 0;
while (n > 0) {
int count = read(tmpbuf, 0,
(int)Math.min(n, 512L));
if (count == -1)
return skipped;
skipped += count;
n -= count;
}
return skipped;
}
};
/// // The skip method in jdk1.1.7 ZipInputStream
/// // is buggy. We return a wrapper that fixes
/// // this.
/// return new FilterInputStream(zis) {
/// private byte[] tmpbuf = new byte[512];
/// public long skip(long n) throws IOException {
/// long skipped = 0;
/// while (n > 0) {
/// int count = read(tmpbuf, 0,
/// (int)Math.min(n, 512L));
/// if (count == -1)
/// return skipped;
/// skipped += count;
/// n -= count;
/// }
/// return skipped;
/// }
/// };
///#else
/// return zis;
return zis;
///#endif
}
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
* 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
&& (subExpressions[1] instanceof GetFieldOperator)
&& (subExpressions[2] instanceof StoreInstruction)) {
// Check for
// class$classname != null ? class$classname :
// (class$classname = class$("classname"))
// and replace with
// classname.class
&& ((((CompareUnaryOperator) subExpressions[0])
.getOperatorIndex() & ~1) == Operator.COMPARE_OP)) {
CompareUnaryOperator cmp
= (CompareUnaryOperator) subExpressions[0];
GetFieldOperator get = (GetFieldOperator) subExpressions[1];
StoreInstruction put = (StoreInstruction) subExpressions[2];
FieldAnalyzer field;
if (cmp.getOperatorIndex() == Operator.NOTEQUALS_OP
&& put.getLValue() instanceof PutFieldOperator
&& ((field = ((PutFieldOperator)put.getLValue()).getField())
!= null) && field.isSynthetic()
&& put.lvalueMatches(get)
&& cmp.subExpressions[0] instanceof GetFieldOperator
&& put.lvalueMatches((GetFieldOperator)cmp.subExpressions[0])
&& 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));
int cmpType = cmp.getOperatorIndex() & 1;
if ((subExpressions[2 - cmpType] instanceof GetFieldOperator)
&& (subExpressions[1 + cmpType] instanceof StoreInstruction)) {
// Check for
// class$classname != null ? class$classname :
// (class$classname = class$("classname"))
// and replace with
// classname.class
GetFieldOperator get
= (GetFieldOperator) subExpressions[2 - cmpType];
StoreInstruction put
= (StoreInstruction) subExpressions[1 + cmpType];
int opIndex = cmp.getOperatorIndex();
FieldAnalyzer field;
if (put.getLValue() instanceof PutFieldOperator
&& ((field = ((PutFieldOperator)put.getLValue())
.getField()) != null) && field.isSynthetic()
&& put.lvalueMatches(get)
&& (cmp.subExpressions[0] instanceof GetFieldOperator)
&& put.lvalueMatches((GetFieldOperator)
cmp.subExpressions[0])
&& 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.
*/
InnerClassInfo outer = getOuterClassInfo(clazz);
if (outer != null && outer.name == null)
if (outer != null && outer.name == null
&& (Options.options & Options.OPTION_ANON) != 0)
anonymousNew = true;
clazzAna = methodAnalyzer.getClassAnalyzer(clazz);
if ((~Options.options &

@ -20,6 +20,7 @@
package jode.flow;
import jode.type.Type;
import jode.decompiler.LocalInfo;
import jode.decompiler.Declarable;
import jode.expr.Expression;
import jode.expr.LocalLoadOperator;
import jode.expr.LocalStoreOperator;
@ -27,6 +28,7 @@ import jode.expr.StoreInstruction;
import jode.util.SimpleSet;
import @COLLECTIONS@.Collections;
import @COLLECTIONS@.Iterator;
import @COLLECTIONS@.Set;
@ -160,6 +162,16 @@ public class CatchBlock extends StructuredBlock {
ib.appendBlock(catchBlock);
catchBlock = ib;
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;
}
/**
* 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)
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.
*/

@ -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
* 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
* @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 LocalLoadOperator)) {
if ((GlobalOptions.debuggingFlags
@ -594,11 +595,21 @@ public class TransformConstructors {
+" "+outerValues);
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) {
Operator op = (Operator) expr;
Expression[] subExpr = op.getSubExpressions();
for (int i=0; i< subExpr.length; i++) {
Expression transformed = transformFieldInitializer(subExpr[i]);
Expression transformed
= transformFieldInitializer(fieldSlot, subExpr[i]);
if (transformed == null)
return null;
if (transformed != subExpr[i])
@ -675,7 +686,7 @@ public class TransformConstructors {
break big_loop;
Expression expr = store.getSubExpressions()[1];
expr = transformFieldInitializer(expr);
expr = transformFieldInitializer(field, expr);
if (expr == null)
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];
expr = transformFieldInitializer(expr);
expr = transformFieldInitializer(field, expr);
if (expr == null)
return -1;
@ -772,9 +789,6 @@ public class TransformConstructors {
GlobalOptions.err.println(" field " + pfo.getFieldName()
+ " = " + expr);
int field = clazzAnalyzer.getFieldIndex(pfo.getFieldName(),
pfo.getFieldType());
// if field does not exists: -1 <= lastField.
if (field <= lastField
|| !(clazzAnalyzer.getField(field).setInitializer(expr))) {

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

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

@ -24,7 +24,7 @@ import @COLLECTIONS@.TreeMap;
import @COLLECTIONS@.Iterator;
///#ifndef JDK12
import @COLLECTIONS@.Comparator;
///import @COLLECTIONS@.Comparator;
///#endif
import java.io.InputStream;
@ -37,17 +37,17 @@ import java.io.IOException;
public class TranslationTable extends TreeMap {
///#ifndef JDK12
public TranslationTable() {
super(createStringComparator());
}
private static Comparator createStringComparator() {
return new Comparator() {
public int compare(Object o1, Object o2) {
return ((String) o1).compareTo((String) o2);
}
};
}
/// public TranslationTable() {
/// super(createStringComparator());
/// }
///
/// private static Comparator createStringComparator() {
/// return new Comparator() {
/// public int compare(Object o1, Object o2) {
/// return ((String) o1).compareTo((String) o2);
/// }
/// };
/// }
///#endif
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("STATIC") ? Modifier.STATIC
///#ifdef JDK12
/// : str.equals("STRICT") ? Modifier.STRICT
: str.equals("STRICT") ? Modifier.STRICT
///#endif
: str.equals("SYNCHRONIZED") ? Modifier.SYNCHRONIZED
: str.equals("TRANSIENT") ? Modifier.TRANSIENT

@ -509,6 +509,8 @@ public class ClassInterfacesType extends ReferenceType {
private final static Hashtable keywords = new Hashtable();
static {
keywords.put("package", Boolean.TRUE);
keywords.put("import", Boolean.TRUE);
keywords.put("if", Boolean.TRUE);
keywords.put("else", 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
* it under the terms of the GNU General Public License as published by
@ -19,8 +19,8 @@
package jode.util;
///#ifdef JDK12
///import java.lang.ref.WeakReference;
///import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
import java.lang.ref.ReferenceQueue;
///#endif
import @COLLECTIONS@.Comparator;
@ -40,28 +40,28 @@ public class UnifyHash extends AbstractCollection {
private static final float DEFAULT_LOAD_FACTOR = 0.75F;
///#ifdef JDK12
/// private ReferenceQueue queue = new ReferenceQueue();
private ReferenceQueue queue = new ReferenceQueue();
///#endif
static class Bucket
///#ifdef JDK12
/// extends WeakReference
extends WeakReference
///#endif
{
///#ifdef JDK12
/// public Bucket(Object o, ReferenceQueue q) {
/// super(o, q);
/// }
///#else
public Bucket(Object o) {
this.obj = o;
}
Object obj;
public Object get() {
return obj;
public Bucket(Object o, ReferenceQueue q) {
super(o, q);
}
///#else
/// public Bucket(Object o) {
/// this.obj = o;
/// }
///
/// Object obj;
///
/// public Object get() {
/// return obj;
/// }
///#endif
int hash;
@ -107,21 +107,21 @@ public class UnifyHash extends AbstractCollection {
}
///#ifdef JDK12
/// public final void cleanUp() {
/// Bucket died;
/// while ((died = (Bucket)queue.poll()) != null) {
/// int diedSlot = Math.abs(died.hash % buckets.length);
/// if (buckets[diedSlot] == died)
/// buckets[diedSlot] = died.next;
/// else {
/// Bucket b = buckets[diedSlot];
/// while (b.next != died)
/// b = b.next;
/// b.next = died.next;
/// }
/// size--;
/// }
/// }
public final void cleanUp() {
Bucket died;
while ((died = (Bucket)queue.poll()) != null) {
int diedSlot = Math.abs(died.hash % buckets.length);
if (buckets[diedSlot] == died)
buckets[diedSlot] = died.next;
else {
Bucket b = buckets[diedSlot];
while (b.next != died)
b = b.next;
b.next = died.next;
}
size--;
}
}
///#endif
@ -131,7 +131,7 @@ public class UnifyHash extends AbstractCollection {
public Iterator iterator() {
///#ifdef JDK12
/// cleanUp();
cleanUp();
///#endif
return new Iterator() {
@ -182,6 +182,9 @@ public class UnifyHash extends AbstractCollection {
}
public Iterator iterateHashCode(final int hash) {
///#ifdef JDK12
cleanUp();
///#endif
return new Iterator() {
private int known = modCount;
private Bucket nextBucket
@ -232,9 +235,9 @@ public class UnifyHash extends AbstractCollection {
int slot = Math.abs(hash % buckets.length);
///#ifdef JDK12
/// Bucket b = new Bucket(o, queue);
Bucket b = new Bucket(o, queue);
///#else
Bucket b = new Bucket(o);
/// Bucket b = new Bucket(o);
///#endif
b.hash = hash;
b.next = buckets[slot];
@ -243,7 +246,7 @@ public class UnifyHash extends AbstractCollection {
public Object unify(Object o, int hash, Comparator comparator) {
///#ifdef JDK12
/// cleanUp();
cleanUp();
///#endif
int slot = Math.abs(hash % buckets.length);
for (Bucket b = buckets[slot]; b != null; b = b.next) {

Loading…
Cancel
Save