/* Copyright (c) 2006, Sriram Srinivasan
*
* You may distribute this software under the terms of the license
* specified in the file "License"
*/
package kilim.test;
import static kilim.Constants.D_ARRAY_BOOLEAN;
import static kilim.Constants.D_BOOLEAN;
import static kilim.Constants.D_DOUBLE;
import static kilim.Constants.D_INT;
import static kilim.Constants.D_LONG;
import static kilim.Constants.D_OBJECT;
import static kilim.Constants.D_RETURN_ADDRESS;
import static kilim.Constants.D_STRING;
import static kilim.Constants.D_THROWABLE;
import static kilim.Constants.D_UNDEFINED;
import kilim.analysis.BasicBlock;
import kilim.analysis.Frame;
import kilim.analysis.MethodFlow;
import kilim.analysis.Usage;
import kilim.analysis.Value;
public class TestFrame extends Base {
protected void setUp() throws Exception {
cache("kilim.test.ex.ExFrame");
}
public void testMethodFrame() {
MethodFlow flow = getFlow("kitchensink");
if (flow == null)
return;
for (BasicBlock bb : flow.getBasicBlocks()) {
if (bb.startPos == 0) {
Frame f = bb.startFrame;
assertEquals("Lkilim/test/ex/ExFrame;", f.getLocal(0).getTypeDesc());
assertSame(D_INT, f.getLocal(1).getTypeDesc());
assertSame(D_LONG, f.getLocal(2).getTypeDesc());
// Note LONG and BOOLEAN take up two words
assertSame(D_BOOLEAN, f.getLocal(4).getTypeDesc());
assertSame(D_DOUBLE, f.getLocal(5).getTypeDesc());
assertEquals("[[Ljava/lang/String;", f.getLocal(7).getTypeDesc());
}
}
}
public void testStack() {
Frame f = new Frame(1, 4);
f.push(Value.make(0, D_LONG));
f.push(Value.make(0, D_DOUBLE));
f.push(Value.make(0, D_ARRAY_BOOLEAN));
f.push(Value.make(0, D_RETURN_ADDRESS));
f.pop();
f.pop();
f.pop();
assertSame(D_LONG, f.pop().getTypeDesc());
}
public void testLocals() {
Frame f = new Frame(4, 1);
f.setLocal(0, Value.make(10, D_LONG));
f.setLocal(2, Value.make(12, D_DOUBLE));
f.setLocal(0, Value.make(20, D_INT));
f.setLocal(1, Value.make(31, D_STRING));
assertSame(D_INT, f.getLocal(0).getTypeDesc());
assertSame(D_STRING, f.getLocal(1).getTypeDesc());
assertSame(D_DOUBLE, f.getLocal(2).getTypeDesc());
}
public void testMergeUnchangedTypes() {
Frame f = new Frame(4, 4);
f.setLocal(1, Value.make(0, D_INT));
f.setLocal(2, Value.make(0, "[Ljava/lang/Object;"));
f.setLocal(3, Value.make(0, "Ljava/lang/reflect/AccessibleObject;"));
f.push(Value.make(0, "Ljava/lang/Object;"));
Frame g = new Frame(4, 4);
g.setLocal(1, Value.make(0, D_INT));
g.setLocal(2, Value.make(0, "[Ljava/lang/Object;"));
g.setLocal(3, Value.make(0, "Ljava/lang/reflect/Field;"));
g.push(Value.make(0, "Ljava/io/Serializable;"));
Usage usage = new Usage(4);
usage.setLiveIn(1);
usage.setLiveIn(2);
usage.setLiveIn(3);
assertEquals(f, f.merge(g, /* localsOnly= */false, usage));
}
public void testMergeChangedTypes() {
Frame f = new Frame(4, 4);
f.setLocal(0, Value.make(0, D_INT));
f.setLocal(1, Value.make(0, "Ljava/lang/reflect/Field;"));
f.setLocal(2, Value.make(0, "[Ljava/lang/Object;"));
f.push(Value.make(0, "Ljava/io/Serializable;"));
Frame g = new Frame(4, 4);
g.setLocal(0, Value.make(0, D_INT));
g.setLocal(1, Value.make(0, "Ljava/lang/reflect/AccessibleObject;"));
g.setLocal(2, Value.make(0, "[Ljava/lang/Object;"));
g.push(Value.make(0, "Ljava/lang/Object;"));
Usage usage = new Usage(4);
for (int i = 0; i < 4; i++)
usage.setLiveIn(i);
Frame h = f.merge(g, /* localsOnly= */false, usage);
assertNotSame(f, h);
for (int i = 0; i < 4; i++) {
assertEquals(g.getLocal(i), h.getLocal(i));
}
}
public void testMergeUnchangedIfNoUsage() {
Frame f = new Frame(4, 4);
f.setLocal(0, Value.make(0, D_RETURN_ADDRESS));
f.setLocal(1, Value.make(0, D_INT));
f.setLocal(2, Value.make(0, D_DOUBLE));
Frame g = new Frame(4, 4);
g.setLocal(0, Value.make(0, D_INT));
g.setLocal(1, Value.make(0, D_DOUBLE));
g.setLocal(3, Value.make(0, D_THROWABLE));
Usage noUsage = new Usage(4); // default, everything is untouched.
assertSame(f, f.merge(g, /* localsOnly= */true, noUsage));
for (int i = 0; i < 4; i++) {
noUsage.write(i); // set everything to OVERWRITTEN
}
assertSame(f, f.merge(g, /* localsOnly= */true, noUsage));
}
public void testIncompatibleMerge() {
Frame f = new Frame(4, 4);
f.setLocal(0, Value.make(0, D_OBJECT));
Frame g = new Frame(4, 4);
g.setLocal(0, Value.make(0, D_INT));
Usage usage = new Usage(4);
for (int i = 0; i < 4; i++) {
usage.setLiveIn(i); // set everything to READ
}
f = f.merge(g, true, usage);
assertTrue(f.getLocal(0).getTypeDesc() == D_UNDEFINED);
}
}