diff --git a/src/org/jetbrains/java/decompiler/modules/decompiler/SimplifyExprentsHelper.java b/src/org/jetbrains/java/decompiler/modules/decompiler/SimplifyExprentsHelper.java index 0bade66..f23fc78 100644 --- a/src/org/jetbrains/java/decompiler/modules/decompiler/SimplifyExprentsHelper.java +++ b/src/org/jetbrains/java/decompiler/modules/decompiler/SimplifyExprentsHelper.java @@ -178,7 +178,7 @@ public class SimplifyExprentsHelper { } // expr++ and expr-- - if (isIPPorIMM(current, next)) { + if (isIPPorIMM(current, next) || isIPPorIMM2(current, next)) { list.remove(index + 1); res = true; continue; @@ -458,6 +458,48 @@ public class SimplifyExprentsHelper { return false; } + private static boolean isIPPorIMM2(Exprent first, Exprent second) { + + if (first.type != Exprent.EXPRENT_ASSIGNMENT || second.type != Exprent.EXPRENT_ASSIGNMENT) { + return false; + } + + AssignmentExprent af = (AssignmentExprent)first; + AssignmentExprent as = (AssignmentExprent)second; + + if(as.getRight().type != Exprent.EXPRENT_FUNCTION) { + return false; + } + + FunctionExprent func = (FunctionExprent)as.getRight(); + + if(func.getFuncType() != FunctionExprent.FUNCTION_ADD && func.getFuncType() != FunctionExprent.FUNCTION_SUB) { + return false; + } + + Exprent econd = func.getLstOperands().get(0); + Exprent econst = func.getLstOperands().get(1); + + if(econst.type != Exprent.EXPRENT_CONST && econd.type == Exprent.EXPRENT_CONST && func.getFuncType() == FunctionExprent.FUNCTION_ADD) { + econd = econst; + econst = func.getLstOperands().get(0); + } + + if(econst.type == Exprent.EXPRENT_CONST && ((ConstExprent)econst).hasValueOne()) { + if(af.getLeft().equals(econd) && af.getRight().equals(as.getLeft()) && (af.getLeft().getExprentUse() & Exprent.MULTIPLE_USES) != 0) { + int type = func.getFuncType() == FunctionExprent.FUNCTION_ADD ? FunctionExprent.FUNCTION_IPP : FunctionExprent.FUNCTION_IMM; + + FunctionExprent ret = new FunctionExprent(type, af.getRight(), func.bytecode); + ret.setImplicitType(VarType.VARTYPE_INT); + + af.setRight(ret); + return true; + } + } + + return false; + } + private static boolean isMonitorExit(Exprent first) { if (first.type == Exprent.EXPRENT_MONITOR) { MonitorExprent expr = (MonitorExprent)first; diff --git a/src/org/jetbrains/java/decompiler/modules/decompiler/decompose/DominatorTreeExceptionFilter.java b/src/org/jetbrains/java/decompiler/modules/decompiler/decompose/DominatorTreeExceptionFilter.java index 89babeb..d8b587f 100644 --- a/src/org/jetbrains/java/decompiler/modules/decompiler/decompose/DominatorTreeExceptionFilter.java +++ b/src/org/jetbrains/java/decompiler/modules/decompiler/decompose/DominatorTreeExceptionFilter.java @@ -134,8 +134,9 @@ public class DominatorTreeExceptionFilter { exit = childid; } else { - // exit = map.containsKey(handler)?-1:mapChild.get(handler); FIXME: Eclipse bug? - exit = map.containsKey(handler) ? -1 : mapChild.get(handler); + // after replacing 'new Integer(-1)' with '-1' Eclipse throws a NullPointerException on the following line + // could be a bug in Eclipse or some obscure specification glitch, FIXME: needs further investigation + exit = map.containsKey(handler) ? new Integer(-1) : mapChild.get(handler); } if (exit != null) { diff --git a/src/org/jetbrains/java/decompiler/modules/decompiler/exps/FieldExprent.java b/src/org/jetbrains/java/decompiler/modules/decompiler/exps/FieldExprent.java index 264347e..642a86b 100644 --- a/src/org/jetbrains/java/decompiler/modules/decompiler/exps/FieldExprent.java +++ b/src/org/jetbrains/java/decompiler/modules/decompiler/exps/FieldExprent.java @@ -54,7 +54,7 @@ public class FieldExprent extends Exprent { @Override public int getExprentUse() { - return instance == null ? Exprent.MULTIPLE_USES : instance.getExprentUse() & Exprent.MULTIPLE_USES; + return 0; // multiple references to a field considered dangerous in a multithreaded environment, thus no Exprent.MULTIPLE_USES set here } @Override diff --git a/testData/classes/pkg/TestFieldSingleAccess.class b/testData/classes/pkg/TestFieldSingleAccess.class new file mode 100644 index 0000000..edc30ab Binary files /dev/null and b/testData/classes/pkg/TestFieldSingleAccess.class differ diff --git a/testData/results/TestFieldSingleAccess.dec b/testData/results/TestFieldSingleAccess.dec new file mode 100644 index 0000000..268c866 --- /dev/null +++ b/testData/results/TestFieldSingleAccess.dec @@ -0,0 +1,40 @@ +package pkg; + +public final class TestFieldSingleAccess { + public Integer field; + + public final void test() { + Integer var10000 = this.field; + if (var10000 != null) { + System.out.println(var10000); + } + + } + + public final void test1() { + synchronized(this.field) { + System.out.println('1'); + } + } +} + +class 'pkg/TestFieldSingleAccess' { + method 'test ()V' { + 1 6 + 5 7 + 8 8 + c 8 + f 11 + } + + method 'test1 ()V' { + 1 14 + 6 14 + 7 15 + a 15 + c 15 + 19 17 + } +} + +Lines mapping: diff --git a/testData/results/TestMethodReferenceSameName.dec b/testData/results/TestMethodReferenceSameName.dec index 3449a8c..2592d18 100644 --- a/testData/results/TestMethodReferenceSameName.dec +++ b/testData/results/TestMethodReferenceSameName.dec @@ -3,7 +3,6 @@ public class TestMethodReferenceSameName { private void foo() { TestMethodReferenceSameName.R1 var10000 = this.r;// 5 - this.r.getClass(); (var10000::foo).run(); }// 6 @@ -16,19 +15,18 @@ public class TestMethodReferenceSameName { class 'TestMethodReferenceSameName' { method 'foo ()V' { 1 4 - 5 5 - e 6 - 13 7 + e 5 + 13 6 } } class 'TestMethodReferenceSameName$R1' { method 'foo ()V' { - 0 11 + 0 10 } } Lines mapping: 5 <-> 5 -6 <-> 8 -9 <-> 12 +6 <-> 7 +9 <-> 11 diff --git a/testData/src/pkg/TestFieldSingleAccess.jasm b/testData/src/pkg/TestFieldSingleAccess.jasm new file mode 100644 index 0000000..57b203c --- /dev/null +++ b/testData/src/pkg/TestFieldSingleAccess.jasm @@ -0,0 +1,67 @@ +/** + * This code can be assembled with asmtools + * using asmtools jasm -g *.jasm command line. + */ +package pkg; + +super public final class TestFieldSingleAccess + version 52:0 +{ + +public Field field:"Ljava/lang/Integer;"; + +public Method "":"()V" + stack 1 locals 1 +{ + aload_0; + invokespecial Method java/lang/Object."":"()V"; + return; +} + +public final Method test:"()V" + stack 2 locals 1 +{ + aload_0; + getfield Field field:"Ljava/lang/Integer;"; + dup; + ifnull L17; + getstatic Field java/lang/System.out:"Ljava/io/PrintStream;"; + swap; + invokevirtual Method java/io/PrintStream.println:"(Ljava/lang/Object;)V"; + L17: stack_frame_type same; + return; +} + +public final Method test1:"()V" + stack 2 locals 3 +{ + aload_0; + getfield Field field:"Ljava/lang/Integer;"; + dup; + astore_1; + monitorenter; + try t0; + getstatic Field java/lang/System.out:"Ljava/io/PrintStream;"; + bipush 49; + invokevirtual Method java/io/PrintStream.println:"(C)V"; + aload_1; + monitorexit; + endtry t0; + goto L25; + catch t0 #0; + catch t1 #0; + try t1; + stack_frame_type full; + locals_map class TestFieldSingleAccess, class java/lang/Object; + stack_map class java/lang/Throwable; + astore_2; + aload_1; + monitorexit; + endtry t1; + aload_2; + athrow; + L25: stack_frame_type chop1; + return; +} + +} // end Class TestFieldSingleAccess