git-svn-id: https://svn.code.sf.net/p/jode/code/trunk@215 379699f6-c40d-0410-875b-85095c16579estable
parent
0ec051c685
commit
d267a860d3
@ -0,0 +1,200 @@ |
||||
package jode.test; |
||||
|
||||
public abstract class Flow { |
||||
int g; |
||||
int[] ain; |
||||
|
||||
void skip() { |
||||
for (int i=0; i<3; i++) { |
||||
if (g > 5) { |
||||
for (int j=0; j<5; j++) { |
||||
g++; |
||||
} |
||||
} |
||||
i--; |
||||
} |
||||
} |
||||
|
||||
/* This tests the while in a switch problem. |
||||
*/ |
||||
public void switchWhileTest() { |
||||
int dir = g; |
||||
int x = 0; |
||||
int y = 0; |
||||
boolean done = false; |
||||
g = 5; |
||||
switch (dir) { |
||||
case 1: |
||||
while (!done) { |
||||
done = true; |
||||
if (g > 7) |
||||
g = g - 4; |
||||
x = g; |
||||
y = g; |
||||
if (x > 7) |
||||
x = x - 4; |
||||
for (int i=0; i<4; i++) { |
||||
for (int j=0; j<5; j++) { |
||||
if (ain[j] == x + i && ain[j] == y) |
||||
done = false; |
||||
} |
||||
} |
||||
} |
||||
for (int i=0; i<5; i++) { |
||||
ain[g] = x + i; |
||||
ain[g] = y; |
||||
g += 1; |
||||
} |
||||
break; |
||||
case 2: |
||||
while (!done) { |
||||
done = true; |
||||
x = g; |
||||
y = g; |
||||
if (y > 7) |
||||
y = y - 4; |
||||
for (int i=0; i<4; i++) { |
||||
for (int j=0; j<4; j++) { |
||||
if (ain[j] == x && ain[j] == y + i) |
||||
done = false; |
||||
} |
||||
} |
||||
} |
||||
for (int i = 0; i<4; i++) { |
||||
ain[g] = x; |
||||
ain[g] = y + i; |
||||
g += 1; |
||||
} |
||||
break; |
||||
case 3: // Same code as case 2 slightly optimized
|
||||
big: |
||||
for (;;) { |
||||
x = g; |
||||
y = g; |
||||
if (y > 7) |
||||
y = y - 4; |
||||
for (int i=0; i<4; i++) { |
||||
for (int j=0; j<4; j++) { |
||||
if (ain[j] == x && ain[j] == y + i) |
||||
continue big; |
||||
} |
||||
} |
||||
break; |
||||
} |
||||
for (int i = 0; i<4; i++) { |
||||
ain[g] = x; |
||||
ain[g] = y + i; |
||||
g += 1; |
||||
} |
||||
break; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* This was an example where our flow analysis didn't find an |
||||
* elegant solution. The reason is, that we try to make |
||||
* while(true)-loops as small as possible (you can't see the real |
||||
* end of the loop, if it is breaked there like here). |
||||
* |
||||
* Look at the assembler code and you know why my Decompiler had |
||||
* problems with this. But the decompiler did produce compilable |
||||
* code which produces the same assembler code. |
||||
* |
||||
* The solution was, to make switches as big as possible, the whole |
||||
* analyze methods were overworked. |
||||
*/ |
||||
void WhileTrueSwitch() { |
||||
int i = 1; |
||||
while (true) { |
||||
switch (i) { |
||||
case 0: |
||||
return; |
||||
case 1: |
||||
i = 5; |
||||
continue; |
||||
case 2: |
||||
i = 6; |
||||
continue; |
||||
case 3: |
||||
throw new RuntimeException(); |
||||
default: |
||||
i = 7; |
||||
return; |
||||
} |
||||
} |
||||
} |
||||
|
||||
abstract int test(); |
||||
|
||||
/** |
||||
* This tests shorts and empty ifs. Especially the no op ifs can |
||||
* be optimized to very unusual code. |
||||
*/ |
||||
public void shortIf() { |
||||
while(g != 7) { |
||||
if (g == 5) |
||||
return; |
||||
else if (g != 4) |
||||
break; |
||||
else if (g == 2) |
||||
shortIf(); |
||||
else |
||||
return; |
||||
|
||||
if (g!= 7) |
||||
shortIf(); |
||||
else { |
||||
shortIf(); |
||||
return; |
||||
} |
||||
|
||||
if (g != 1) |
||||
break; |
||||
else if (g == 3) |
||||
shortIf(); |
||||
else |
||||
break; |
||||
|
||||
// javac optimizes this instruction to
|
||||
// test();
|
||||
// jikes reproduces this statement as one would expect
|
||||
if (g + 5 == test()) { |
||||
} |
||||
|
||||
// javac -O optimizes this to the following weired statements
|
||||
// PUSH g;
|
||||
// PUSH test();
|
||||
// POP2;
|
||||
// This cannot be decompiled correctly, since the == is lost.
|
||||
if (g == test()) |
||||
continue; |
||||
} |
||||
while(g == 3) { |
||||
// javac:
|
||||
// PUSH test() == 4 || test() == 3 && test() == 2;
|
||||
// POP;
|
||||
if (test() == 4 || test() == 3 && test() == 2); |
||||
// javac -O:
|
||||
// if (test() != 4 && test() == 3) {
|
||||
// PUSH test()+test() - test();
|
||||
// PUSH g-4;
|
||||
// POP2;
|
||||
// }
|
||||
if (test() == 4 || test() == 3 && test() == 2) |
||||
continue; |
||||
} |
||||
while (g==2) { |
||||
// javac:
|
||||
// test();
|
||||
// test();
|
||||
// test();
|
||||
if ((long) (test() + test() - test()) == (long)(g-4)); |
||||
// javac -O:
|
||||
// PUSH (long)(test() + test() - test()) <=> (long)(g-4)
|
||||
// POP;
|
||||
if ((long) (test() + test() - test()) == (long)(g-4)) |
||||
continue; |
||||
} |
||||
System.err.println("Hallo"); |
||||
} |
||||
} |
@ -0,0 +1,145 @@ |
||||
package jode.test; |
||||
|
||||
class A { |
||||
} |
||||
|
||||
interface I1 { |
||||
} |
||||
|
||||
interface I2 { |
||||
} |
||||
|
||||
interface I12 extends I1, I2 { |
||||
} |
||||
|
||||
class B extends A implements I1 { |
||||
} |
||||
|
||||
class C extends B implements I2, I12 { |
||||
} |
||||
|
||||
class D extends A implements I12 { |
||||
} |
||||
|
||||
class E extends A implements I2 { |
||||
} |
||||
|
||||
public class LocalTypes { |
||||
A a; |
||||
B b; |
||||
C c; |
||||
D d; |
||||
E e; |
||||
|
||||
I1 i1; |
||||
I2 i2; |
||||
I12 i12; |
||||
|
||||
boolean g_bo; |
||||
byte g_by; |
||||
short g_sh; |
||||
int g_in; |
||||
|
||||
int z; |
||||
int[]ain; |
||||
|
||||
public void arithTest() { |
||||
int a=1,b=2; |
||||
boolean x = true,y = false; |
||||
int c=0; |
||||
arithTest(); |
||||
if (x & y) { |
||||
c = 5; |
||||
arithTest(); |
||||
x &= y; |
||||
arithTest(); |
||||
x = x | y; |
||||
arithTest(); |
||||
x ^= y; |
||||
arithTest(); |
||||
x = x && y; |
||||
arithTest(); |
||||
b <<= a; |
||||
b <<= c; |
||||
} |
||||
a&=b; |
||||
} |
||||
|
||||
public void intTypeTest() { |
||||
boolean b = false; |
||||
boolean abo[] = null; |
||||
byte aby[] = null; |
||||
byte by; |
||||
int in; |
||||
short sh; |
||||
b = g_bo; |
||||
in = g_sh; |
||||
sh = (short)g_in; |
||||
by = (byte)sh; |
||||
sh = by; |
||||
in = by; |
||||
abo[0] = g_bo; |
||||
abo[1] = false; |
||||
abo[2] = true; |
||||
aby[0] = g_by; |
||||
aby[1] = 0; |
||||
aby[2] = 1; |
||||
} |
||||
|
||||
native void arrFunc(B[] b); |
||||
|
||||
/** |
||||
* This is an example where it is really hard to know, which type |
||||
* each local has. |
||||
*/ |
||||
void DifficultType () { |
||||
B myB = c; |
||||
C myC = c; |
||||
I2 myI2 = c; |
||||
I12 myI12 = c; |
||||
boolean bool = true; |
||||
B[] aB = new C[3]; |
||||
arrFunc(new C[3]); |
||||
|
||||
while (bool) { |
||||
if (bool) { |
||||
i1 = myB; |
||||
i2 = myC; |
||||
i1 = aB[0]; |
||||
} else if (bool) { |
||||
i1 = myI12; |
||||
i2 = myI2; |
||||
} else { |
||||
i1 = myC; |
||||
i2 = myI12; |
||||
} |
||||
myB = b; |
||||
if (bool) |
||||
myI2 = i12; |
||||
else { |
||||
myI12 = d; |
||||
myI2 = e; |
||||
} |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* This is an example where it is really hard to know, which type |
||||
* each local has. |
||||
*/ |
||||
void DifficultArrayType () { |
||||
boolean bool = true; |
||||
B[] aB = new C[3]; |
||||
arrFunc(new C[3]); |
||||
C[][][][][] x = new C[4][3][4][][]; |
||||
int[][][][][] y = new int[1][2][][][]; |
||||
|
||||
while (bool) { |
||||
if (bool) { |
||||
i1 = aB[0]; |
||||
aB[0] = b; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
Loading…
Reference in new issue