package kilim.test.ex;
import kilim.Pausable;
import kilim.Task;
public class ExYieldStack extends ExYieldBase {
public ExYieldStack(int test) {
testCase = test;
}
public void execute() throws Pausable {
doPause = false;
test();
doPause = true;
test();
}
private void test() throws Pausable {
switch (testCase) {
case 0: testStackBottom_st(); break;
case 1: testStackBottom_v(); break;
case 2: testStackBottom_av(); break;
case 3: testFactorial_st(); break;
case 4: testFactorial_av(); break;
default: new IllegalStateException("Unknown testCase " + testCase);
}
}
// load stack with a number of types, call a static pausable method
// The call to verify ensures that the stack is loaded with
// a few elements before the call to pausable_x is made.
void testStackBottom_st() throws Pausable {
verify(fd, fs, fl, fa, pausable_st(10, doPause));
}
// load stack with a number of types, call a virtual pausable method
void testStackBottom_v() throws Pausable {
verify(fd, fs, pausable_v(fl), fa, ff);
}
// load stack with a number of types, call a virtual pausable method
// on another object
void testStackBottom_av() throws Pausable {
verify(fd, fs, fl, fa, new ExYieldStack(testCase).pausable_v(10));
}
// test a deep hierarchy that makes the state stack grow, have
// long parameters and return values, and pause in the middle
// of the computation so it is saves longs on the stack
void testFactorial_st() throws Pausable {
long n = fact_st(15L, doPause);
if (n != 1307674368000L) {
throw new RuntimeException("Incorrect factorial, n =" + n);
}
}
// Issue 8 on github
void testLoop() throws Pausable {
// The other tests don't test constant propagation, but not dynamic operands
// on stack.
}
static long fact_st(long n, boolean doPause) throws Pausable {
// System.out.println("n = " + n + ", doPause = " + doPause);
if (n == 1) {
if (doPause) Task.sleep(10);
return 1L;
}
if (n == 10) {
// Initial state stack is 10 elements long, so it is worth
// testing a pause here.
if (doPause) Task.sleep(10);
}
return n * fact_st(n-1, doPause);
}
void testFactorial_av() throws Pausable {
long n = new ExYieldStack(testCase).fact_av(15L, doPause);
if (n != 1307674368000L) {
throw new RuntimeException("Incorrect factorial, n =" + n);
}
}
long fact_av(long n, boolean doPause) throws Pausable {
if (n == 1) {
if (doPause) Task.sleep(50);
return 1L;
}
if (n == 10) {
// Initial state stack is 10 elements long, so it is worth
// testing a pause here.
if (doPause) Task.sleep(50);
}
return n * new ExYieldStack(testCase).fact_av(n-1, doPause);
}
static float pausable_st(int i, boolean doPause) throws Pausable {
if (doPause) {
Task.sleep(50);
}
return 11.0f;
}
long pausable_v(long l) throws Pausable {
if (doPause) {
Task.sleep(50);
}
return l;
}
static void verify(double ad, Object as, long al, Object aa, float aii) {
verify(ad);
verify((String) as);
verify(al);
verify((String[][]) aa);
}
void dummySyncTest() throws Pausable {
// just making sure that the weaver doesn't barf if we call
// call a pausable function from _outside_ a synchronized block.
synchronized(this) {
notify(); // dummy non-pausable method in a sync block
}
pausable_st(0, false);
synchronized(this) {
notify(); // dummy non-pausable method in a sync block
}
}
}