import java.util.concurrent.locks.LockSupport;
import java.util.concurrent.CountDownLatch;

public class Test {

    static value class SmallValue {
        int x1;
        int x2;
        
        public SmallValue(int i) {
            this.x1 = i;
            this.x2 = i;
        }

        public String toString() {
            return "x1 = " + x1 + ", x2 = " + x2;
        }

        public void verify(String loc, int i) {
            if (x1 != i || x2 != i) {
                new RuntimeException("Incorrect result at " + loc + " for i = " + i + ": " + this).printStackTrace(System.out);
                System.exit(1);
            }
        }
    }

    // Large value class that requires stack extension/repair
    static value class LargeValue {
        int x1;
        int x2;
        int x3;
        int x4;
        int x5;
        int x6;
        int x7;
        int x8;
        int x9;
        int x10;
        
        public LargeValue(int i) {
            this.x1 = i;
            this.x2 = i;
            this.x3 = i;
            this.x4 = i;
            this.x5 = i;
            this.x6 = i;
            this.x7 = i;
            this.x8 = i;
            this.x9 = i;
            this.x10 = i;
        }

        public String toString() {
            return "x1 = " + x1 + ", x2 = " + x2 + ", x3 = " + x3 + ", x4 = " + x4 + ", x5 = " + x5 +
                   ", x6 = " + x6 + ", x7 = " + x7 + ", x8 = " + x8 + ", x9 = " + x9 + ", x10 = " + x10;
        }

        public void verify(String loc, int i) {
            if (x1 != i || x2 != i || x3 != i || x4 != i || x5 != i ||
                x6 != i || x7 != i || x8 != i || x9 != i || x10 != i) {
                new RuntimeException("Incorrect result at " + loc + " for i = " + i + ": " + this).printStackTrace(System.out);
                System.exit(1);
            }
        }
    }

    public static SmallValue testSmall(SmallValue val, int i, boolean park) {
        val.verify("entry", i);
        if (park) {
            LockSupport.parkNanos(1000);
        }
        val.verify("exit", i);
        return val;
    }

    public static LargeValue testLarge(LargeValue val, int i, boolean park) {
        val.verify("entry", i);
        if (park) {
            LockSupport.parkNanos(1000);
        }
        val.verify("exit",i);
        return val;
    }

    public static void main(String[] args) throws Exception {
        CountDownLatch cdl = new CountDownLatch(1);
        Thread.ofVirtual().name("vt1").start(() -> {
            // Trigger compilation
            for (int i = 0; i < 50_000; i++) {
                //testSmall(new SmallValue(i), i, (i % 1000) == 0).verify("return", i);
                testLarge(new LargeValue(i), i, (i % 1000) == 0).verify("return", i);
            }
            cdl.countDown();
        });
        cdl.await();
    }
}
