Preventing duplicate field access

master
upnotes 6 years ago
parent 5650f57ad2
commit c3ff7141ab
  1. 44
      src/org/jetbrains/java/decompiler/modules/decompiler/SimplifyExprentsHelper.java
  2. 5
      src/org/jetbrains/java/decompiler/modules/decompiler/decompose/DominatorTreeExceptionFilter.java
  3. 2
      src/org/jetbrains/java/decompiler/modules/decompiler/exps/FieldExprent.java
  4. BIN
      testData/classes/pkg/TestFieldSingleAccess.class
  5. 40
      testData/results/TestFieldSingleAccess.dec
  6. 12
      testData/results/TestMethodReferenceSameName.dec
  7. 67
      testData/src/pkg/TestFieldSingleAccess.jasm

@ -178,7 +178,7 @@ public class SimplifyExprentsHelper {
} }
// expr++ and expr-- // expr++ and expr--
if (isIPPorIMM(current, next)) { if (isIPPorIMM(current, next) || isIPPorIMM2(current, next)) {
list.remove(index + 1); list.remove(index + 1);
res = true; res = true;
continue; continue;
@ -458,6 +458,48 @@ public class SimplifyExprentsHelper {
return false; 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) { private static boolean isMonitorExit(Exprent first) {
if (first.type == Exprent.EXPRENT_MONITOR) { if (first.type == Exprent.EXPRENT_MONITOR) {
MonitorExprent expr = (MonitorExprent)first; MonitorExprent expr = (MonitorExprent)first;

@ -134,8 +134,9 @@ public class DominatorTreeExceptionFilter {
exit = childid; exit = childid;
} }
else { else {
// exit = map.containsKey(handler)?-1:mapChild.get(handler); FIXME: Eclipse bug? // after replacing 'new Integer(-1)' with '-1' Eclipse throws a NullPointerException on the following line
exit = map.containsKey(handler) ? -1 : mapChild.get(handler); // 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) { if (exit != null) {

@ -54,7 +54,7 @@ public class FieldExprent extends Exprent {
@Override @Override
public int getExprentUse() { 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 @Override

@ -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:

@ -3,7 +3,6 @@ public class TestMethodReferenceSameName {
private void foo() { private void foo() {
TestMethodReferenceSameName.R1 var10000 = this.r;// 5 TestMethodReferenceSameName.R1 var10000 = this.r;// 5
this.r.getClass();
(var10000::foo).run(); (var10000::foo).run();
}// 6 }// 6
@ -16,19 +15,18 @@ public class TestMethodReferenceSameName {
class 'TestMethodReferenceSameName' { class 'TestMethodReferenceSameName' {
method 'foo ()V' { method 'foo ()V' {
1 4 1 4
5 5 e 5
e 6 13 6
13 7
} }
} }
class 'TestMethodReferenceSameName$R1' { class 'TestMethodReferenceSameName$R1' {
method 'foo ()V' { method 'foo ()V' {
0 11 0 10
} }
} }
Lines mapping: Lines mapping:
5 <-> 5 5 <-> 5
6 <-> 8 6 <-> 7
9 <-> 12 9 <-> 11

@ -0,0 +1,67 @@
/**
* This code can be assembled with <a href="https://wiki.openjdk.java.net/display/CodeTools/asmtools">asmtools</a>
* using <code>asmtools jasm -g *.jasm</code> command line.
*/
package pkg;
super public final class TestFieldSingleAccess
version 52:0
{
public Field field:"Ljava/lang/Integer;";
public Method "<init>":"()V"
stack 1 locals 1
{
aload_0;
invokespecial Method java/lang/Object."<init>":"()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
Loading…
Cancel
Save