Preventing duplicate field access
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
BIN
testData/classes/pkg/TestFieldSingleAccess.class
Normal file
BIN
testData/classes/pkg/TestFieldSingleAccess.class
Normal file
Binary file not shown.
40
testData/results/TestFieldSingleAccess.dec
Normal file
40
testData/results/TestFieldSingleAccess.dec
Normal file
@@ -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() {
|
||||
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
|
||||
|
||||
67
testData/src/pkg/TestFieldSingleAccess.jasm
Normal file
67
testData/src/pkg/TestFieldSingleAccess.jasm
Normal file
@@ -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
|
||||
Reference in New Issue
Block a user