git-svn-id: https://svn.code.sf.net/p/jode/code/trunk@1347 379699f6-c40d-0410-875b-85095c16579emaster
parent
7714d5d503
commit
14b4dd94f8
@ -0,0 +1,214 @@ |
|||||||
|
package net.sf.jode.bytecode; |
||||||
|
import junit.framework.*; |
||||||
|
import java.io.*; |
||||||
|
|
||||||
|
public class BasicBlockWriterTest extends TestCase implements Opcodes { |
||||||
|
public BasicBlockWriterTest(String name) { |
||||||
|
super(name); |
||||||
|
} |
||||||
|
|
||||||
|
GrowableConstantPool gcp = new GrowableConstantPool(); |
||||||
|
Instruction[] someNops; |
||||||
|
Instruction[] manyNops; |
||||||
|
Instruction[] whileHead; |
||||||
|
Instruction[] whileCond; |
||||||
|
Instruction[] whileFoot; |
||||||
|
|
||||||
|
/** |
||||||
|
* The whileHead block in bytecode |
||||||
|
*/ |
||||||
|
private final static String whileHeadStr="\3="; |
||||||
|
/** |
||||||
|
* The whileCond block in bytecode, without the if_icmpeq instruction. |
||||||
|
*/ |
||||||
|
private final static String whileCondStr="\34\33"; |
||||||
|
/** |
||||||
|
* The whileFoot block in bytecode. |
||||||
|
*/ |
||||||
|
private final static String whileFootStr="\204\2\1"; |
||||||
|
/** |
||||||
|
* The someNops block in bytecode, without the if_icmpeq instruction. |
||||||
|
*/ |
||||||
|
private final static String someNopsStr="\0\0"; |
||||||
|
|
||||||
|
public void setUp() { |
||||||
|
Instruction nop = Instruction.forOpcode(opc_nop); |
||||||
|
someNops = new Instruction[] { nop, nop }; |
||||||
|
manyNops = new Instruction[35000]; |
||||||
|
for (int i = 0; i < manyNops.length; i++) |
||||||
|
manyNops[i] = nop; |
||||||
|
|
||||||
|
whileHead = new Instruction[] { |
||||||
|
Instruction.forOpcode(opc_ldc, new Integer(0)), |
||||||
|
Instruction.forOpcode(opc_istore, LocalVariableInfo.getInfo(2)), |
||||||
|
}; |
||||||
|
whileCond = new Instruction[] { |
||||||
|
Instruction.forOpcode(opc_iload, LocalVariableInfo.getInfo(2)), |
||||||
|
Instruction.forOpcode(opc_iload, LocalVariableInfo.getInfo(1)), |
||||||
|
Instruction.forOpcode(opc_if_icmpeq) |
||||||
|
}; |
||||||
|
whileFoot = new Instruction[] { |
||||||
|
Instruction.forOpcode(opc_iinc, LocalVariableInfo.getInfo(2), 1), |
||||||
|
}; |
||||||
|
} |
||||||
|
|
||||||
|
public byte[] write(BasicBlockWriter bbw) throws IOException { |
||||||
|
ByteArrayOutputStream baos = new ByteArrayOutputStream(); |
||||||
|
DataOutputStream dos = new DataOutputStream(baos); |
||||||
|
bbw.write(gcp, dos); |
||||||
|
dos.close(); |
||||||
|
return baos.toByteArray(); |
||||||
|
} |
||||||
|
|
||||||
|
public void testEmpty() throws IOException { |
||||||
|
BasicBlocks bb = new BasicBlocks(new MethodInfo("foo", "()V", 0)); |
||||||
|
bb.setBlocks(new Block[0], null, new Handler[0]); |
||||||
|
BasicBlockWriter bbw = new BasicBlockWriter(bb, gcp); |
||||||
|
gcp.write(new DataOutputStream(new ByteArrayOutputStream())); |
||||||
|
|
||||||
|
assertEquals("Code differs", |
||||||
|
"\0\0\0\1\0\0\0\1" /* no stack, one local, length 1 */ |
||||||
|
+"\261" /* opc_return */ |
||||||
|
+"\0\0" /* no exception handlers */, |
||||||
|
new String(write(bbw))); |
||||||
|
} |
||||||
|
|
||||||
|
public void testSimple() throws IOException { |
||||||
|
Block bb1 = new Block(); |
||||||
|
Block bb2 = new Block(); |
||||||
|
bb1.setCode(someNops, new Block[] {bb2}); |
||||||
|
bb2.setCode(someNops, new Block[] {null}); |
||||||
|
BasicBlocks bb = new BasicBlocks(new MethodInfo("foo", "()V", 0)); |
||||||
|
bb.setBlocks(new Block[] { bb1, bb2}, bb1, new Handler[0]); |
||||||
|
BasicBlockWriter bbw = new BasicBlockWriter(bb, gcp); |
||||||
|
gcp.write(new DataOutputStream(new ByteArrayOutputStream())); |
||||||
|
|
||||||
|
assertEquals("Code differs", |
||||||
|
"\0\0\0\1\0\0\0\5" /* no stack, one local, length 5 */ |
||||||
|
+someNopsStr+someNopsStr+"\261" |
||||||
|
+"\0\0" /* no exception handlers */, |
||||||
|
new String(write(bbw))); |
||||||
|
} |
||||||
|
|
||||||
|
public void testWhile() throws IOException { |
||||||
|
Block b1 = new Block(); |
||||||
|
Block b2 = new Block(); |
||||||
|
Block b3 = new Block(); |
||||||
|
Block b4 = new Block(); |
||||||
|
b1.setCode(whileHead, new Block[] { b2 }); |
||||||
|
b2.setCode(whileCond, new Block[] { null, b3 }); |
||||||
|
b3.setCode(someNops, new Block[] { b4 }); |
||||||
|
b4.setCode(whileFoot, new Block[] { b2 }); |
||||||
|
BasicBlocks bb = new BasicBlocks(new MethodInfo("a", "(I)V", 0)); |
||||||
|
bb.setBlocks(new Block[] { b1, b2, b3, b4}, b1, new Handler[0]); |
||||||
|
BasicBlockWriter bbw = new BasicBlockWriter(bb, gcp); |
||||||
|
gcp.write(new DataOutputStream(new ByteArrayOutputStream())); |
||||||
|
assertEquals(5, bbw.blockAddr.length); |
||||||
|
assertEquals(0, bbw.blockAddr[0]); |
||||||
|
assertEquals(2, bbw.blockAddr[1]); |
||||||
|
assertEquals(7, bbw.blockAddr[2]); |
||||||
|
assertEquals(9, bbw.blockAddr[3]); |
||||||
|
assertEquals(16, bbw.blockAddr[4]); |
||||||
|
|
||||||
|
assertEquals("Code differs", |
||||||
|
"\0\2\0\3\0\0\0\20" |
||||||
|
+whileHeadStr+whileCondStr+"\237\0\13" |
||||||
|
+someNopsStr+whileFootStr+"\247\377\366"+"\261"+"\0\0", |
||||||
|
new String(write(bbw))); |
||||||
|
} |
||||||
|
|
||||||
|
public void testTableSwitch() throws IOException { |
||||||
|
Block b1 = new Block(); |
||||||
|
Block b2 = new Block(); |
||||||
|
Instruction[] switchBlock = new Instruction[] { |
||||||
|
Instruction.forOpcode(opc_iload, LocalVariableInfo.getInfo(1)), |
||||||
|
Instruction.forOpcode(opc_lookupswitch, new int[] { 1, 3, 5}) |
||||||
|
}; |
||||||
|
b1.setCode(switchBlock, new Block[] { b2, null, b1, null }); |
||||||
|
b2.setCode(someNops, new Block[] { null }); |
||||||
|
BasicBlocks bb = new BasicBlocks(new MethodInfo("s", "(I)V", 0)); |
||||||
|
bb.setBlocks(new Block[] { b1, b2 }, b1, new Handler[0]); |
||||||
|
BasicBlockWriter bbw = new BasicBlockWriter(bb, gcp); |
||||||
|
gcp.write(new DataOutputStream(new ByteArrayOutputStream())); |
||||||
|
assertEquals(3, bbw.blockAddr.length); |
||||||
|
assertEquals(0, bbw.blockAddr[0]); |
||||||
|
assertEquals(36, bbw.blockAddr[1]); |
||||||
|
assertEquals(39, bbw.blockAddr[2]); |
||||||
|
assertEquals("Code differs", |
||||||
|
"\0\1\0\2\0\0\0\47" |
||||||
|
+"\33\252\0\0" /*iload_0 + tableswitch + align */ |
||||||
|
+"\0\0\0\45\0\0\0\1\0\0\0\5" /* def, low, high */ |
||||||
|
+"\0\0\0\43\0\0\0\45\0\0\0\45\0\0\0\45\377\377\377\377" |
||||||
|
+someNopsStr+"\261"+"\0\0", |
||||||
|
new String(write(bbw))); |
||||||
|
} |
||||||
|
|
||||||
|
public void testLookupSwitch() throws IOException { |
||||||
|
Block b1 = new Block(); |
||||||
|
Block b2 = new Block(); |
||||||
|
Instruction[] switchBlock = new Instruction[] { |
||||||
|
Instruction.forOpcode(opc_iload, LocalVariableInfo.getInfo(1)), |
||||||
|
Instruction.forOpcode(opc_lookupswitch, new int[] { 1, 5, 7}) |
||||||
|
}; |
||||||
|
b1.setCode(switchBlock, new Block[] { b2, null, b1, null }); |
||||||
|
b2.setCode(someNops, new Block[] { null }); |
||||||
|
BasicBlocks bb = new BasicBlocks(new MethodInfo("s", "(I)V", 0)); |
||||||
|
bb.setBlocks(new Block[] { b1, b2 }, b1, new Handler[0]); |
||||||
|
BasicBlockWriter bbw = new BasicBlockWriter(bb, gcp); |
||||||
|
gcp.write(new DataOutputStream(new ByteArrayOutputStream())); |
||||||
|
assertEquals(3, bbw.blockAddr.length); |
||||||
|
assertEquals(0, bbw.blockAddr[0]); |
||||||
|
assertEquals(36, bbw.blockAddr[1]); |
||||||
|
assertEquals(39, bbw.blockAddr[2]); |
||||||
|
assertEquals("Code differs", |
||||||
|
"\0\1\0\2\0\0\0\47" |
||||||
|
+"\33\253\0\0" /*iload_0 + lookupswitch + align */ |
||||||
|
+"\0\0\0\45\0\0\0\3" /* def , nitem */ |
||||||
|
+"\0\0\0\1\0\0\0\43" |
||||||
|
+"\0\0\0\5\0\0\0\45" |
||||||
|
+"\0\0\0\7\377\377\377\377" |
||||||
|
+someNopsStr+"\261"+"\0\0", |
||||||
|
new String(write(bbw))); |
||||||
|
} |
||||||
|
|
||||||
|
public void testException() throws IOException { |
||||||
|
Block b1 = new Block(); |
||||||
|
Block b2 = new Block(); |
||||||
|
Instruction[] catchInstrs = new Instruction[] { |
||||||
|
Instruction.forOpcode(opc_athrow) |
||||||
|
}; |
||||||
|
b1.setCode(someNops, new Block[] { null }); |
||||||
|
b2.setCode(catchInstrs, new Block[0]); |
||||||
|
BasicBlocks bb = new BasicBlocks(new MethodInfo("e", "()V", 0)); |
||||||
|
Handler h = new Handler(b1, b1, b2, "java.lang.RuntimeException"); |
||||||
|
bb.setBlocks(new Block[] { b1, b2 }, b1, new Handler[] {h}); |
||||||
|
assertEquals(0, b1.blockNr); |
||||||
|
assertEquals(1, b2.blockNr); |
||||||
|
assertEquals(1, b1.catchers.length); |
||||||
|
assertEquals(0, b2.catchers.length); |
||||||
|
assertSame(h, b1.catchers[0]); |
||||||
|
BasicBlockWriter bbw = new BasicBlockWriter(bb, gcp); |
||||||
|
gcp.write(new DataOutputStream(new ByteArrayOutputStream())); |
||||||
|
int cpoolEntry = gcp.putClassName("java.lang.RuntimeException"); |
||||||
|
assertEquals(3, bbw.blockAddr.length); |
||||||
|
assertEquals(0, bbw.blockAddr[0]); |
||||||
|
assertEquals(3, bbw.blockAddr[1]); |
||||||
|
assertEquals(4, bbw.blockAddr[2]); |
||||||
|
assertEquals("Code differs", |
||||||
|
"\0\1\0\1\0\0\0\4" |
||||||
|
+ someNopsStr + "\261" + "\277" |
||||||
|
+ "\0\1\0\0\0\3\0\3\0"+(char)cpoolEntry, |
||||||
|
new String(write(bbw))); |
||||||
|
} |
||||||
|
|
||||||
|
public static Test suite() { |
||||||
|
TestSuite suite = new TestSuite(); |
||||||
|
suite.addTest(new BasicBlockWriterTest("testEmpty")); |
||||||
|
suite.addTest(new BasicBlockWriterTest("testSimple")); |
||||||
|
suite.addTest(new BasicBlockWriterTest("testWhile")); |
||||||
|
suite.addTest(new BasicBlockWriterTest("testTableSwitch")); |
||||||
|
suite.addTest(new BasicBlockWriterTest("testLookupSwitch")); |
||||||
|
suite.addTest(new BasicBlockWriterTest("testException")); |
||||||
|
return suite; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,47 @@ |
|||||||
|
package net.sf.jode.bytecode; |
||||||
|
import junit.framework.*; |
||||||
|
import java.io.*; |
||||||
|
|
||||||
|
public class BasicBlocksTest extends TestCase implements Opcodes { |
||||||
|
public BasicBlocksTest(String name) { |
||||||
|
super(name); |
||||||
|
} |
||||||
|
|
||||||
|
public void testJsr() { |
||||||
|
Block b0 = new Block(); |
||||||
|
Block b1 = new Block(); |
||||||
|
Block b2 = new Block(); |
||||||
|
b0.setCode(new Instruction[] { |
||||||
|
Instruction.forOpcode(opc_jsr) |
||||||
|
}, new Block[] { b1, null }); |
||||||
|
b1.setCode(new Instruction[] { |
||||||
|
Instruction.forOpcode(opc_astore, LocalVariableInfo.getInfo(2)), |
||||||
|
Instruction.forOpcode(opc_iinc, LocalVariableInfo.getInfo(1), -1), |
||||||
|
Instruction.forOpcode(opc_iload, LocalVariableInfo.getInfo(1)), |
||||||
|
Instruction.forOpcode(opc_ifeq) |
||||||
|
}, new Block[] { b2, b0 }); |
||||||
|
b2.setCode(new Instruction[] { |
||||||
|
Instruction.forOpcode(opc_ret, LocalVariableInfo.getInfo(0)), |
||||||
|
}, new Block[0]); |
||||||
|
assertEquals("pop0", 0, b0.maxpop); |
||||||
|
assertEquals("push0", 0, b0.maxpush); |
||||||
|
assertEquals("delta0", 0, b0.delta); |
||||||
|
assertEquals("pop1", 1, b1.maxpop); |
||||||
|
assertEquals("push1", 0, b1.maxpush); |
||||||
|
assertEquals("delta1", -1, b1.delta); |
||||||
|
assertEquals("pop2", 0, b2.maxpop); |
||||||
|
assertEquals("push2", 0, b2.maxpush); |
||||||
|
assertEquals("delta2", 0, b2.delta); |
||||||
|
BasicBlocks bb = new BasicBlocks(new MethodInfo("foo", "(I)V", 0)); |
||||||
|
bb.setBlocks(new Block[] { b0, b1, b2 }, b0, new Handler[0]); |
||||||
|
assertEquals("stack0", 0, b0.stackHeight); |
||||||
|
assertEquals("stack1", 1, b1.stackHeight); |
||||||
|
assertEquals("stack2", 0, b2.stackHeight); |
||||||
|
} |
||||||
|
|
||||||
|
public static Test suite() { |
||||||
|
TestSuite suite = new TestSuite(); |
||||||
|
suite.addTest(new BasicBlocksTest("testJsr")); |
||||||
|
return suite; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,44 @@ |
|||||||
|
package net.sf.jode.bytecode; |
||||||
|
import junit.framework.*; |
||||||
|
import java.io.*; |
||||||
|
|
||||||
|
public class BlockTest extends TestCase implements Opcodes { |
||||||
|
public BlockTest(String name) { |
||||||
|
super(name); |
||||||
|
} |
||||||
|
|
||||||
|
public void testJsr() { |
||||||
|
Block b1 = new Block(); |
||||||
|
Block b2 = new Block(); |
||||||
|
Instruction jsr = Instruction.forOpcode(opc_jsr); |
||||||
|
b1.setCode(new Instruction[] { jsr }, new Block[] { b2, null } ); |
||||||
|
assertEquals("pop", 0, b1.maxpop); |
||||||
|
assertEquals("push", 0, b1.maxpush); |
||||||
|
assertEquals("delta", 0, b1.delta); |
||||||
|
try { |
||||||
|
b1.setCode(new Instruction[] { jsr }, new Block[] { b2 }); |
||||||
|
fail("jsr must have two successors"); |
||||||
|
} catch (IllegalArgumentException ex) { |
||||||
|
} |
||||||
|
try { |
||||||
|
b1.setCode(new Instruction[] { jsr }, |
||||||
|
new Block[] { null, b2 }); |
||||||
|
fail("jsr succ mustn't be null"); |
||||||
|
} catch (IllegalArgumentException ex) { |
||||||
|
} |
||||||
|
try { |
||||||
|
b1.setCode(new Instruction[] { jsr, |
||||||
|
Instruction.forOpcode(opc_nop) }, |
||||||
|
new Block[] { null, b2 }); |
||||||
|
fail("jsr must be last in block"); |
||||||
|
} catch (IllegalArgumentException ex) { |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
public static Test suite() { |
||||||
|
TestSuite suite = new TestSuite(); |
||||||
|
suite.addTest(new BlockTest("testJsr")); |
||||||
|
return suite; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,358 @@ |
|||||||
|
package net.sf.jode.flow; |
||||||
|
import net.sf.jode.decompiler.LocalInfo; |
||||||
|
import junit.framework.*; |
||||||
|
import net.sf.jode.expr.*; |
||||||
|
import net.sf.jode.type.Type; |
||||||
|
import net.sf.jode.decompiler.TabbedPrintWriter; |
||||||
|
import net.sf.jode.GlobalOptions; |
||||||
|
|
||||||
|
public class TrExcTest extends TestCase { |
||||||
|
private static final boolean VERBOSE = false; |
||||||
|
|
||||||
|
public TrExcTest(String name) { |
||||||
|
super (name); |
||||||
|
} |
||||||
|
|
||||||
|
public void setUp() { |
||||||
|
GlobalOptions.debuggingFlags |= GlobalOptions.DEBUG_CHECK; |
||||||
|
if (VERBOSE) |
||||||
|
GlobalOptions.debuggingFlags |
||||||
|
|= GlobalOptions.DEBUG_ANALYZE | GlobalOptions.DEBUG_FLOW; |
||||||
|
} |
||||||
|
|
||||||
|
FlowBlock[] createFlowBlocks(int n) { |
||||||
|
FlowBlock[] flows = new FlowBlock[n]; |
||||||
|
for (int i = 0; i < n; i++) |
||||||
|
flows[i] = new FlowBlock(null, i, i > 0 ? flows[i-1] : null); |
||||||
|
return flows; |
||||||
|
} |
||||||
|
|
||||||
|
public void testSynchronized11() throws java.io.IOException { |
||||||
|
FlowBlock[] flows = createFlowBlocks(5); |
||||||
|
LocalInfo thisLocal = new LocalInfo(null, 0); |
||||||
|
LocalInfo tmpLocal = new LocalInfo(null, 1); |
||||||
|
LocalInfo tmp2Local = new LocalInfo(null, 2); |
||||||
|
|
||||||
|
/* Monitorenter */ |
||||||
|
flows[0].appendReadBlock |
||||||
|
(new InstructionBlock |
||||||
|
(new LocalLoadOperator(Type.tUObject, null, thisLocal)), thisLocal); |
||||||
|
flows[0].appendBlock |
||||||
|
(new InstructionBlock(new MonitorEnterOperator())); |
||||||
|
flows[0].setSuccessors(new FlowBlock[] { flows[1] }); |
||||||
|
|
||||||
|
/* Synchronized Blocks */ |
||||||
|
flows[1].appendReadBlock |
||||||
|
(new InstructionBlock |
||||||
|
(new LocalLoadOperator(Type.tUObject, null, thisLocal)), thisLocal); |
||||||
|
flows[1].appendWriteBlock |
||||||
|
(new InstructionBlock |
||||||
|
(new StoreInstruction |
||||||
|
(new LocalStoreOperator(Type.tUObject, tmpLocal))), tmpLocal); |
||||||
|
flows[1].appendBlock(new JsrBlock()); |
||||||
|
flows[1].setSuccessors(new FlowBlock[] { flows[4], flows[2] }); |
||||||
|
|
||||||
|
flows[2].appendReadBlock |
||||||
|
(new InstructionBlock |
||||||
|
(new LocalLoadOperator(Type.tUObject, null, tmpLocal)), tmpLocal); |
||||||
|
flows[2].appendBlock |
||||||
|
(new ReturnBlock(new NopOperator(Type.tUObject))); |
||||||
|
flows[2].setSuccessors(new FlowBlock[] { FlowBlock.END_OF_METHOD }); |
||||||
|
|
||||||
|
/* Catch Exception Blocks */ |
||||||
|
flows[3].appendReadBlock |
||||||
|
(new InstructionBlock |
||||||
|
(new LocalLoadOperator(Type.tUObject, null, thisLocal)), thisLocal); |
||||||
|
flows[3].appendBlock |
||||||
|
(new InstructionBlock(new MonitorExitOperator())); |
||||||
|
flows[3].appendBlock |
||||||
|
(new ThrowBlock(new NopOperator(Type.tUObject))); |
||||||
|
flows[3].setSuccessors(new FlowBlock[0]); |
||||||
|
|
||||||
|
/* monitorexit subroutine */ |
||||||
|
flows[4].appendWriteBlock |
||||||
|
(new InstructionBlock |
||||||
|
(new StoreInstruction |
||||||
|
(new LocalStoreOperator(Type.tUObject, tmp2Local))), tmp2Local); |
||||||
|
flows[4].appendReadBlock |
||||||
|
(new InstructionBlock |
||||||
|
(new LocalLoadOperator(Type.tUObject, null, thisLocal)), thisLocal); |
||||||
|
flows[4].appendBlock |
||||||
|
(new InstructionBlock(new MonitorExitOperator())); |
||||||
|
flows[4].appendReadBlock |
||||||
|
(new RetBlock(tmp2Local), tmp2Local); |
||||||
|
flows[4].setSuccessors(new FlowBlock[0]); |
||||||
|
|
||||||
|
flows[0].addStartPred(); |
||||||
|
TransformExceptionHandlers exc = new TransformExceptionHandlers(flows); |
||||||
|
exc.addHandler(flows[1],flows[2],flows[3], null); |
||||||
|
exc.analyze(); |
||||||
|
flows[0].analyze(); |
||||||
|
flows[0].removeStartPred(); |
||||||
|
if (VERBOSE) |
||||||
|
flows[0].dumpSource(new TabbedPrintWriter(GlobalOptions.err)); |
||||||
|
assertTrue(flows[0].getBlock() instanceof SynchronizedBlock); |
||||||
|
assertTrue(flows[0].getBlock().getSubBlocks()[0] |
||||||
|
instanceof ReturnBlock); |
||||||
|
} |
||||||
|
|
||||||
|
public void testSynchronized13() throws java.io.IOException { |
||||||
|
FlowBlock[] flows = createFlowBlocks(5); |
||||||
|
LocalInfo thisLocal = new LocalInfo(null, 0); |
||||||
|
LocalInfo tmpLocal = new LocalInfo(null, 1); |
||||||
|
LocalInfo tmp2Local = new LocalInfo(null, 2); |
||||||
|
|
||||||
|
/* Monitorenter */ |
||||||
|
flows[0].appendReadBlock |
||||||
|
(new InstructionBlock |
||||||
|
(new LocalLoadOperator(Type.tUObject, null, thisLocal)), thisLocal); |
||||||
|
flows[0].appendBlock |
||||||
|
(new InstructionBlock(new MonitorEnterOperator())); |
||||||
|
flows[0].setSuccessors(new FlowBlock[] { flows[1] }); |
||||||
|
|
||||||
|
/* Synchronized Blocks */ |
||||||
|
flows[1].appendReadBlock |
||||||
|
(new InstructionBlock |
||||||
|
(new LocalLoadOperator(Type.tUObject, null, thisLocal)), thisLocal); |
||||||
|
flows[1].appendWriteBlock |
||||||
|
(new InstructionBlock |
||||||
|
(new StoreInstruction |
||||||
|
(new LocalStoreOperator(Type.tUObject, tmpLocal))), tmpLocal); |
||||||
|
flows[1].appendReadBlock |
||||||
|
(new InstructionBlock |
||||||
|
(new LocalLoadOperator(Type.tUObject, null, thisLocal)), thisLocal); |
||||||
|
flows[1].appendBlock |
||||||
|
(new InstructionBlock(new MonitorExitOperator())); |
||||||
|
flows[1].setSuccessors(new FlowBlock[] { flows[2] }); |
||||||
|
|
||||||
|
flows[2].appendReadBlock |
||||||
|
(new InstructionBlock |
||||||
|
(new LocalLoadOperator(Type.tUObject, null, tmpLocal)), tmpLocal); |
||||||
|
flows[2].appendBlock |
||||||
|
(new ReturnBlock(new NopOperator(Type.tUObject))); |
||||||
|
flows[2].setSuccessors(new FlowBlock[] { FlowBlock.END_OF_METHOD }); |
||||||
|
|
||||||
|
/* Catch Exception Blocks */ |
||||||
|
flows[3].appendReadBlock |
||||||
|
(new InstructionBlock |
||||||
|
(new LocalLoadOperator(Type.tUObject, null, thisLocal)), thisLocal); |
||||||
|
flows[3].appendBlock |
||||||
|
(new InstructionBlock(new MonitorExitOperator())); |
||||||
|
flows[3].appendBlock |
||||||
|
(new ThrowBlock(new NopOperator(Type.tUObject))); |
||||||
|
flows[3].setSuccessors(new FlowBlock[0]); |
||||||
|
|
||||||
|
/* monitorexit subroutine */ |
||||||
|
flows[4].appendWriteBlock |
||||||
|
(new InstructionBlock |
||||||
|
(new StoreInstruction |
||||||
|
(new LocalStoreOperator(Type.tUObject, tmp2Local))), tmp2Local); |
||||||
|
flows[4].appendReadBlock |
||||||
|
(new InstructionBlock |
||||||
|
(new LocalLoadOperator(Type.tUObject, null, thisLocal)), thisLocal); |
||||||
|
flows[4].appendBlock |
||||||
|
(new InstructionBlock(new MonitorExitOperator())); |
||||||
|
flows[4].appendReadBlock |
||||||
|
(new RetBlock(tmp2Local), tmp2Local); |
||||||
|
flows[4].setSuccessors(new FlowBlock[0]); |
||||||
|
|
||||||
|
flows[0].addStartPred(); |
||||||
|
TransformExceptionHandlers exc = new TransformExceptionHandlers(flows); |
||||||
|
exc.addHandler(flows[1],flows[2],flows[3], null); |
||||||
|
exc.analyze(); |
||||||
|
flows[0].analyze(); |
||||||
|
flows[0].removeStartPred(); |
||||||
|
if (VERBOSE) |
||||||
|
flows[0].dumpSource(new TabbedPrintWriter(GlobalOptions.err)); |
||||||
|
assertTrue(flows[0].getBlock() instanceof SynchronizedBlock); |
||||||
|
assertTrue(flows[0].getBlock().getSubBlocks()[0] |
||||||
|
instanceof ReturnBlock); |
||||||
|
} |
||||||
|
|
||||||
|
public void testSpecialFin() throws java.io.IOException { |
||||||
|
FlowBlock[] flows = createFlowBlocks(3); |
||||||
|
LocalInfo thisLocal = new LocalInfo(null, 0); |
||||||
|
LocalInfo tmpLocal = new LocalInfo(null, 1); |
||||||
|
LocalInfo tmp2Local = new LocalInfo(null, 2); |
||||||
|
|
||||||
|
/* Try Blocks */ |
||||||
|
flows[0].setSuccessors(new FlowBlock[] { flows[2] }); |
||||||
|
|
||||||
|
/* Catch Exception Blocks */ |
||||||
|
flows[1].appendBlock(new SpecialBlock(SpecialBlock.POP, 1, 0)); |
||||||
|
flows[1].setSuccessors(new FlowBlock[] { flows[2] }); |
||||||
|
|
||||||
|
/* subroutine */ |
||||||
|
flows[2].appendBlock(new DescriptionBlock("/*FINALLY*/")); |
||||||
|
flows[2].setSuccessors(new FlowBlock[] { FlowBlock.END_OF_METHOD }); |
||||||
|
|
||||||
|
flows[0].addStartPred(); |
||||||
|
TransformExceptionHandlers exc = new TransformExceptionHandlers(flows); |
||||||
|
exc.addHandler(flows[0],flows[0],flows[1], null); |
||||||
|
exc.analyze(); |
||||||
|
flows[0].analyze(); |
||||||
|
flows[0].removeStartPred(); |
||||||
|
if (VERBOSE) |
||||||
|
flows[0].dumpSource(new TabbedPrintWriter(GlobalOptions.err)); |
||||||
|
assertTrue("Try", flows[0].getBlock() instanceof TryBlock); |
||||||
|
assertTrue("Empty", flows[0].getBlock().getSubBlocks()[0] instanceof EmptyBlock); |
||||||
|
assertTrue("Finally", flows[0].getBlock().getSubBlocks()[1] instanceof FinallyBlock); |
||||||
|
assertTrue("Descr", flows[0].getBlock().getSubBlocks()[1].getSubBlocks()[0] instanceof DescriptionBlock); |
||||||
|
} |
||||||
|
|
||||||
|
public void testSpecialFinTryLoops() throws java.io.IOException { |
||||||
|
FlowBlock[] flows = createFlowBlocks(3); |
||||||
|
LocalInfo thisLocal = new LocalInfo(null, 0); |
||||||
|
LocalInfo tmpLocal = new LocalInfo(null, 1); |
||||||
|
LocalInfo tmp2Local = new LocalInfo(null, 2); |
||||||
|
|
||||||
|
/* Try Blocks */ |
||||||
|
flows[0].setSuccessors(new FlowBlock[] { flows[0] }); |
||||||
|
|
||||||
|
/* Catch Exception Blocks */ |
||||||
|
flows[1].appendBlock(new SpecialBlock(SpecialBlock.POP, 1, 0)); |
||||||
|
flows[1].setSuccessors(new FlowBlock[] { flows[2] }); |
||||||
|
|
||||||
|
/* subroutine */ |
||||||
|
flows[2].appendBlock(new DescriptionBlock("/*FINALLY*/")); |
||||||
|
flows[2].setSuccessors(new FlowBlock[] { FlowBlock.END_OF_METHOD }); |
||||||
|
|
||||||
|
flows[0].addStartPred(); |
||||||
|
TransformExceptionHandlers exc = new TransformExceptionHandlers(flows); |
||||||
|
exc.addHandler(flows[0],flows[0],flows[1], null); |
||||||
|
exc.analyze(); |
||||||
|
flows[0].analyze(); |
||||||
|
flows[0].removeStartPred(); |
||||||
|
if (VERBOSE) |
||||||
|
flows[0].dumpSource(new TabbedPrintWriter(GlobalOptions.err)); |
||||||
|
assertTrue("Try", flows[0].getBlock() instanceof TryBlock); |
||||||
|
assertTrue("Loop", flows[0].getBlock().getSubBlocks()[0] instanceof LoopBlock); |
||||||
|
assertTrue("Empty", flows[0].getBlock().getSubBlocks()[0].getSubBlocks()[0] instanceof EmptyBlock); |
||||||
|
assertTrue("Finally", flows[0].getBlock().getSubBlocks()[1] instanceof FinallyBlock); |
||||||
|
assertTrue("Descr", flows[0].getBlock().getSubBlocks()[1].getSubBlocks()[0] instanceof DescriptionBlock); |
||||||
|
} |
||||||
|
|
||||||
|
public void testFinBreaksJikes() throws java.io.IOException { |
||||||
|
FlowBlock[] flows = createFlowBlocks(5); |
||||||
|
LocalInfo thisLocal = new LocalInfo(null, 0); |
||||||
|
LocalInfo tmpLocal = new LocalInfo(null, 1); |
||||||
|
LocalInfo tmp2Local = new LocalInfo(null, 2); |
||||||
|
|
||||||
|
/* Try Blocks */ |
||||||
|
flows[0].appendBlock(new JsrBlock()); |
||||||
|
flows[0].setSuccessors(new FlowBlock[] { flows[3], flows[4] }); |
||||||
|
|
||||||
|
/* Catch Exception Blocks */ |
||||||
|
flows[1].appendWriteBlock |
||||||
|
(new InstructionBlock |
||||||
|
(new StoreInstruction |
||||||
|
(new LocalStoreOperator(Type.tUObject, tmpLocal))), tmpLocal); |
||||||
|
flows[1].appendBlock(new JsrBlock()); |
||||||
|
flows[1].setSuccessors(new FlowBlock[] { flows[3], flows[2] }); |
||||||
|
|
||||||
|
flows[2].appendReadBlock |
||||||
|
(new InstructionBlock |
||||||
|
(new LocalLoadOperator(Type.tUObject, null, tmpLocal)), tmpLocal); |
||||||
|
flows[2].appendBlock |
||||||
|
(new ThrowBlock(new NopOperator(Type.tUObject))); |
||||||
|
flows[2].setSuccessors(new FlowBlock[0]); |
||||||
|
|
||||||
|
/* subroutine */ |
||||||
|
flows[3].appendBlock(new SpecialBlock(SpecialBlock.POP, 1, 0)); |
||||||
|
flows[3].setSuccessors(new FlowBlock[] { flows[4] }); |
||||||
|
|
||||||
|
flows[4].appendBlock(new DescriptionBlock("/*HERE*/")); |
||||||
|
flows[4].setSuccessors(new FlowBlock[] { FlowBlock.END_OF_METHOD }); |
||||||
|
|
||||||
|
flows[0].addStartPred(); |
||||||
|
TransformExceptionHandlers exc = new TransformExceptionHandlers(flows); |
||||||
|
exc.addHandler(flows[0],flows[0],flows[1], null); |
||||||
|
exc.analyze(); |
||||||
|
flows[0].analyze(); |
||||||
|
flows[0].removeStartPred(); |
||||||
|
if (VERBOSE) |
||||||
|
flows[0].dumpSource(new TabbedPrintWriter(GlobalOptions.err)); |
||||||
|
assertTrue("Sequ", flows[0].getBlock() instanceof SequentialBlock); |
||||||
|
assertTrue("Loop", flows[0].getBlock().getSubBlocks()[0] instanceof LoopBlock); |
||||||
|
assertTrue("Try", flows[0].getBlock().getSubBlocks()[0].getSubBlocks()[0] instanceof TryBlock); |
||||||
|
assertTrue("Empty", flows[0].getBlock().getSubBlocks()[0].getSubBlocks()[0].getSubBlocks()[0] instanceof EmptyBlock); |
||||||
|
assertTrue("Finally", flows[0].getBlock().getSubBlocks()[0].getSubBlocks()[0].getSubBlocks()[1] instanceof FinallyBlock); |
||||||
|
assertTrue("Break", flows[0].getBlock().getSubBlocks()[0].getSubBlocks()[0].getSubBlocks()[1].getSubBlocks()[0] instanceof BreakBlock); |
||||||
|
assertTrue("Descr", flows[0].getBlock().getSubBlocks()[1] |
||||||
|
instanceof DescriptionBlock); |
||||||
|
} |
||||||
|
|
||||||
|
public void testFinCondBreaks() throws java.io.IOException { |
||||||
|
FlowBlock[] flows = createFlowBlocks(6); |
||||||
|
LocalInfo thisLocal = new LocalInfo(null, 0); |
||||||
|
LocalInfo tmpLocal = new LocalInfo(null, 1); |
||||||
|
LocalInfo tmp2Local = new LocalInfo(null, 2); |
||||||
|
|
||||||
|
/* Try Blocks */ |
||||||
|
flows[0].appendBlock(new JsrBlock()); |
||||||
|
flows[0].setSuccessors(new FlowBlock[] { flows[3], flows[5] }); |
||||||
|
|
||||||
|
/* Catch Exception Blocks */ |
||||||
|
flows[1].appendWriteBlock |
||||||
|
(new InstructionBlock |
||||||
|
(new StoreInstruction |
||||||
|
(new LocalStoreOperator(Type.tUObject, tmpLocal))), tmpLocal); |
||||||
|
flows[1].appendBlock(new JsrBlock()); |
||||||
|
flows[1].setSuccessors(new FlowBlock[] { flows[3], flows[2] }); |
||||||
|
|
||||||
|
flows[2].appendReadBlock |
||||||
|
(new InstructionBlock |
||||||
|
(new LocalLoadOperator(Type.tUObject, null, tmpLocal)), tmpLocal); |
||||||
|
flows[2].appendBlock |
||||||
|
(new ThrowBlock(new NopOperator(Type.tUObject))); |
||||||
|
flows[2].setSuccessors(new FlowBlock[0]); |
||||||
|
|
||||||
|
/* subroutine */ |
||||||
|
flows[3].appendWriteBlock |
||||||
|
(new InstructionBlock |
||||||
|
(new StoreInstruction |
||||||
|
(new LocalStoreOperator(Type.tUObject, tmp2Local))), tmp2Local); |
||||||
|
flows[3].appendReadBlock |
||||||
|
(new InstructionBlock |
||||||
|
(new LocalLoadOperator(Type.tUObject, null, thisLocal)), thisLocal); |
||||||
|
flows[3].appendBlock(new ConditionalBlock |
||||||
|
(new CompareUnaryOperator |
||||||
|
(Type.tUObject, Operator.EQUALS_OP))); |
||||||
|
flows[3].setSuccessors(new FlowBlock[] { flows[4], flows[5] }); |
||||||
|
flows[4].appendReadBlock |
||||||
|
(new RetBlock(tmp2Local), tmp2Local); |
||||||
|
flows[4].setSuccessors(new FlowBlock[0]); |
||||||
|
|
||||||
|
flows[5].appendBlock(new DescriptionBlock("/*HERE*/")); |
||||||
|
flows[5].setSuccessors(new FlowBlock[] { FlowBlock.END_OF_METHOD }); |
||||||
|
|
||||||
|
flows[0].addStartPred(); |
||||||
|
TransformExceptionHandlers exc = new TransformExceptionHandlers(flows); |
||||||
|
exc.addHandler(flows[0],flows[0],flows[1], null); |
||||||
|
exc.analyze(); |
||||||
|
flows[0].analyze(); |
||||||
|
flows[0].removeStartPred(); |
||||||
|
if (VERBOSE) |
||||||
|
flows[0].dumpSource(new TabbedPrintWriter(GlobalOptions.err)); |
||||||
|
assertTrue("Sequ", flows[0].getBlock() instanceof SequentialBlock); |
||||||
|
assertTrue("Loop", flows[0].getBlock().getSubBlocks()[0] instanceof LoopBlock); |
||||||
|
assertTrue("Try", flows[0].getBlock().getSubBlocks()[0].getSubBlocks()[0] instanceof TryBlock); |
||||||
|
assertTrue("Empty", flows[0].getBlock().getSubBlocks()[0].getSubBlocks()[0].getSubBlocks()[0] instanceof EmptyBlock); |
||||||
|
assertTrue("Finally", flows[0].getBlock().getSubBlocks()[0].getSubBlocks()[0].getSubBlocks()[1] instanceof FinallyBlock); |
||||||
|
assertTrue("If", flows[0].getBlock().getSubBlocks()[0].getSubBlocks()[0].getSubBlocks()[1].getSubBlocks()[0] instanceof IfThenElseBlock); |
||||||
|
assertTrue("Break", flows[0].getBlock().getSubBlocks()[0].getSubBlocks()[0].getSubBlocks()[1].getSubBlocks()[0].getSubBlocks()[0] instanceof BreakBlock); |
||||||
|
assertTrue("Descr", flows[0].getBlock().getSubBlocks()[1] |
||||||
|
instanceof DescriptionBlock); |
||||||
|
} |
||||||
|
|
||||||
|
public static Test suite() { |
||||||
|
TestSuite suite = new TestSuite(); |
||||||
|
suite.addTest(new TrExcTest("testSynchronized11")); |
||||||
|
suite.addTest(new TrExcTest("testSynchronized13")); |
||||||
|
suite.addTest(new TrExcTest("testSpecialFin")); |
||||||
|
suite.addTest(new TrExcTest("testSpecialFinTryLoops")); |
||||||
|
suite.addTest(new TrExcTest("testFinBreaksJikes")); |
||||||
|
suite.addTest(new TrExcTest("testFinCondBreaks")); |
||||||
|
return suite; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,186 @@ |
|||||||
|
package net.sf.jode.obfuscator.modules; |
||||||
|
import net.sf.jode.bytecode.*; |
||||||
|
import net.sf.jode.GlobalOptions; |
||||||
|
import junit.framework.*; |
||||||
|
import java.util.BitSet; |
||||||
|
import java.io.PrintWriter; |
||||||
|
|
||||||
|
public class ConstAnaTest extends TestCase implements Opcodes { |
||||||
|
ConstantAnalyzer ca; |
||||||
|
Instruction[] callJsrInstr; |
||||||
|
BasicBlocks jsrMethod; |
||||||
|
|
||||||
|
public ConstAnaTest(String name) { |
||||||
|
super(name); |
||||||
|
} |
||||||
|
|
||||||
|
public void setUp() { |
||||||
|
ca = new ConstantAnalyzer(); |
||||||
|
createJsrMethod(); |
||||||
|
} |
||||||
|
|
||||||
|
public void createJsrMethod() { |
||||||
|
callJsrInstr = new Instruction[] { |
||||||
|
Instruction.forOpcode(opc_jsr) |
||||||
|
}; |
||||||
|
|
||||||
|
Block b0 = new Block(); |
||||||
|
Block b1 = new Block(); |
||||||
|
Block b2 = new Block(); |
||||||
|
b0.setCode(callJsrInstr, new Block[] { b1, null }); |
||||||
|
b1.setCode(new Instruction[] { |
||||||
|
Instruction.forOpcode(opc_astore, LocalVariableInfo.getInfo(2)), |
||||||
|
Instruction.forOpcode(opc_iinc, LocalVariableInfo.getInfo(1), -1), |
||||||
|
Instruction.forOpcode(opc_iload, LocalVariableInfo.getInfo(1)), |
||||||
|
Instruction.forOpcode(opc_ifeq) |
||||||
|
}, new Block[] { b2, b0 }); |
||||||
|
b2.setCode(new Instruction[] { |
||||||
|
Instruction.forOpcode(opc_ret, LocalVariableInfo.getInfo(2)), |
||||||
|
}, new Block[0]); |
||||||
|
jsrMethod = new BasicBlocks(new MethodInfo("foo", "(I)V", 0)); |
||||||
|
jsrMethod.setBlocks(new Block[] { b0, b1, b2 }, |
||||||
|
b0, new Handler[0]); |
||||||
|
} |
||||||
|
|
||||||
|
public void testSimple() throws Exception { |
||||||
|
Block b0 = new Block(); |
||||||
|
Block b1 = new Block(); |
||||||
|
Block b2 = new Block(); |
||||||
|
b0.setCode(new Instruction[] { |
||||||
|
Instruction.forOpcode(opc_iinc, LocalVariableInfo.getInfo(1), 1), |
||||||
|
Instruction.forOpcode(opc_iinc, LocalVariableInfo.getInfo(2), 1), |
||||||
|
Instruction.forOpcode(opc_iinc, LocalVariableInfo.getInfo(3), 1), |
||||||
|
}, new Block[] { b1 }); |
||||||
|
b1.setCode(new Instruction[] { |
||||||
|
Instruction.forOpcode(opc_ldc, new Integer(0)), |
||||||
|
Instruction.forOpcode(opc_istore, LocalVariableInfo.getInfo(1)), |
||||||
|
Instruction.forOpcode(opc_ldc, new Integer(4)), |
||||||
|
Instruction.forOpcode(opc_istore, LocalVariableInfo.getInfo(2)), |
||||||
|
Instruction.forOpcode(opc_ldc, new Integer(0)), |
||||||
|
Instruction.forOpcode(opc_istore, LocalVariableInfo.getInfo(3)), |
||||||
|
Instruction.forOpcode(opc_iload, LocalVariableInfo.getInfo(1)), |
||||||
|
Instruction.forOpcode(opc_ifeq) |
||||||
|
}, new Block[] { b2, b0 }); |
||||||
|
b2.setCode(new Instruction[] { |
||||||
|
Instruction.forOpcode(opc_iinc, LocalVariableInfo.getInfo(1), 1), |
||||||
|
Instruction.forOpcode(opc_iload, LocalVariableInfo.getInfo(1)), |
||||||
|
Instruction.forOpcode(opc_iload, LocalVariableInfo.getInfo(2)), |
||||||
|
Instruction.forOpcode(opc_if_icmplt) |
||||||
|
}, new Block[] { b2, null }); |
||||||
|
BasicBlocks bb = new BasicBlocks(new MethodInfo("foo", "()V", 0)); |
||||||
|
bb.setBlocks(new Block[] { b0, b1, b2 }, b1, new Handler[0]); |
||||||
|
|
||||||
|
ca.analyzeCode(null, bb); |
||||||
|
|
||||||
|
BitSet reachable = (BitSet) ca.bbInfos.get(bb); |
||||||
|
assertEquals("Reachable set", |
||||||
|
"{1, 2}", reachable.toString()); |
||||||
|
assertEquals("constant flow", |
||||||
|
ca.CONSTANTFLOW, |
||||||
|
Class.forName("net.sf.jode.obfuscator.modules.ConstantAnalyzer$ConstantInfo") |
||||||
|
.getDeclaredField("flags") |
||||||
|
.getInt(ca.constantInfos.get(b1.getInstructions()[7]))); |
||||||
|
ca.transformCode(bb); |
||||||
|
|
||||||
|
Block[] blocks = bb.getBlocks(); |
||||||
|
assertEquals(2, blocks.length); |
||||||
|
assertEquals(1, blocks[0].getSuccs().length); |
||||||
|
assertEquals(blocks[1], blocks[0].getSuccs()[0]); |
||||||
|
assertEquals(2, blocks[1].getSuccs().length); |
||||||
|
assertEquals(blocks[1], blocks[1].getSuccs()[0]); |
||||||
|
assertEquals(null, blocks[1].getSuccs()[1]); |
||||||
|
} |
||||||
|
|
||||||
|
public void testJsr() throws Exception { |
||||||
|
Block[] blocks = jsrMethod.getBlocks(); |
||||||
|
|
||||||
|
ca.analyzeCode(null, jsrMethod); |
||||||
|
|
||||||
|
BitSet reachable = (BitSet) ca.bbInfos.get(jsrMethod); |
||||||
|
assertEquals("Reachable set", |
||||||
|
"{0, 1, 2}", reachable.toString()); |
||||||
|
ca.transformCode(jsrMethod); |
||||||
|
|
||||||
|
blocks = jsrMethod.getBlocks(); |
||||||
|
assertEquals(3, blocks.length); |
||||||
|
assertEquals(2, blocks[0].getSuccs().length); |
||||||
|
assertEquals(blocks[1], blocks[0].getSuccs()[0]); |
||||||
|
assertEquals(null, blocks[0].getSuccs()[1]); |
||||||
|
assertEquals(2, blocks[1].getSuccs().length); |
||||||
|
assertEquals(0, blocks[2].getSuccs().length); |
||||||
|
} |
||||||
|
|
||||||
|
public void testNestedJsr() throws Exception { |
||||||
|
Block b0 = new Block(); |
||||||
|
Block b1 = new Block(); |
||||||
|
Block b2 = new Block(); |
||||||
|
Block b3 = new Block(); |
||||||
|
Block b4 = new Block(); |
||||||
|
Block b5 = new Block(); |
||||||
|
Block b6 = new Block(); |
||||||
|
Block b7 = new Block(); |
||||||
|
Block b8 = new Block(); |
||||||
|
Block b9 = new Block(); |
||||||
|
|
||||||
|
b0.setCode(new Instruction[] { |
||||||
|
Instruction.forOpcode(opc_jsr) |
||||||
|
}, new Block[] { b2, b1 }); |
||||||
|
b1.setCode(new Instruction[] { |
||||||
|
Instruction.forOpcode(opc_jsr) |
||||||
|
}, new Block[] { b5, null }); |
||||||
|
b2.setCode(new Instruction[] { |
||||||
|
Instruction.forOpcode(opc_astore, LocalVariableInfo.getInfo(2)), |
||||||
|
Instruction.forOpcode(opc_iload, LocalVariableInfo.getInfo(1)), |
||||||
|
Instruction.forOpcode(opc_ifeq) |
||||||
|
}, new Block[] { b3, b7 }); |
||||||
|
b3.setCode(new Instruction[] { |
||||||
|
Instruction.forOpcode(opc_jsr) |
||||||
|
}, new Block[] { b5, b1 }); |
||||||
|
b4.setCode(new Instruction[] { |
||||||
|
Instruction.forOpcode(opc_ret, LocalVariableInfo.getInfo(2)), |
||||||
|
}, new Block[0]); |
||||||
|
b5.setCode(new Instruction[] { |
||||||
|
Instruction.forOpcode(opc_astore, LocalVariableInfo.getInfo(3)), |
||||||
|
Instruction.forOpcode(opc_ret, LocalVariableInfo.getInfo(3)), |
||||||
|
}, new Block[0]); |
||||||
|
b6.setCode(new Instruction[] { |
||||||
|
Instruction.forOpcode(opc_astore, LocalVariableInfo.getInfo(3)) |
||||||
|
}, new Block[] { b4 }); |
||||||
|
b7.setCode(new Instruction[] { |
||||||
|
Instruction.forOpcode(opc_iload, LocalVariableInfo.getInfo(1)), |
||||||
|
Instruction.forOpcode(opc_ifeq) |
||||||
|
}, new Block[] { b8, b4 }); |
||||||
|
b8.setCode(new Instruction[] { |
||||||
|
Instruction.forOpcode(opc_jsr) |
||||||
|
}, new Block[] { b6, b9 }); |
||||||
|
b9.setCode(new Instruction[0], new Block[] { b7 }); |
||||||
|
|
||||||
|
BasicBlocks bb = new BasicBlocks(new MethodInfo("foo", "(I)V", 0)); |
||||||
|
bb.setBlocks(new Block[] { b0, b1, b2, b3, b4, b5, b6, b7, b8, b9 }, |
||||||
|
b0, new Handler[0]); |
||||||
|
ca.analyzeCode(null, bb); |
||||||
|
|
||||||
|
BitSet reachable = (BitSet) ca.bbInfos.get(bb); |
||||||
|
assertEquals("Reachable set", |
||||||
|
"{0, 1, 2, 3, 4, 5, 6, 7, 8}", reachable.toString()); |
||||||
|
assertNotNull("Constant Flow", |
||||||
|
ca.constantInfos.get(b8.getInstructions()[0])); |
||||||
|
|
||||||
|
ca.transformCode(bb); |
||||||
|
|
||||||
|
Block[] blocks = bb.getBlocks(); |
||||||
|
assertEquals(9, blocks.length); |
||||||
|
assertEquals(2, blocks[0].getSuccs().length); |
||||||
|
assertEquals(2, blocks[1].getSuccs().length); |
||||||
|
assertEquals(2, blocks[3].getSuccs().length); |
||||||
|
assertEquals(1, blocks[8].getSuccs().length); |
||||||
|
} |
||||||
|
|
||||||
|
public static Test suite() { |
||||||
|
TestSuite suite = new TestSuite(); |
||||||
|
suite.addTest(new ConstAnaTest("testSimple")); |
||||||
|
suite.addTest(new ConstAnaTest("testJsr")); |
||||||
|
suite.addTest(new ConstAnaTest("testNestedJsr")); |
||||||
|
return suite; |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue