/*
 * Copyright (C) 2017 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

class Main1 implements Base {
}

class Main2 extends Main1 {
    public void foobar() {}
}

class Main3 implements Base {
    public int foo(int i) {
        if (i != 3) {
            printError("error3");
        }
        return -(i + 10);
    }
}

public class Main {
    static Base sMain1;
    static Base sMain2;
    static Base sMain3;

    static boolean sIsOptimizing = true;
    static boolean sHasJIT = true;
    static volatile boolean sOtherThreadStarted;

    private static void assertSingleImplementation(Class<?> clazz, String method_name, boolean b) {
        if (hasSingleImplementation(clazz, method_name) != b) {
            System.out.println(clazz + "." + method_name +
                    " doesn't have single implementation value of " + b);
        }
    }

    static int getValue(Class<?> cls) {
        if (cls == Main1.class || cls == Main2.class) {
            return 1;
        }
        return 3;
    }

    // sMain1.foo()/sMain2.foo() will be always be Base.foo() before Main3 is loaded/linked.
    // So sMain1.foo() can be devirtualized to Base.foo() and be inlined.
    // After Helper.createMain3() which links in Main3, live testImplement() on stack
    // should be deoptimized.
    static void testImplement(boolean createMain3, boolean wait, boolean setHasJIT) {
        if (setHasJIT) {
            if (isInterpreted()) {
                sHasJIT = false;
            }
            return;
        }

        if (createMain3 && (sIsOptimizing || sHasJIT)) {
            assertIsManaged();
        }

        if (sMain1.foo(getValue(sMain1.getClass())) != 11) {
            System.out.println("11 expected.");
        }
        if (sMain1.$noinline$bar() != -1) {
            System.out.println("-1 expected.");
        }
        if (sMain2.foo(getValue(sMain2.getClass())) != 11) {
            System.out.println("11 expected.");
        }

        if (createMain3) {
            // Wait for the other thread to start.
            while (!sOtherThreadStarted);
            // Create an Main2 instance and assign it to sMain2.
            // sMain1 is kept the same.
            sMain3 = Helper.createMain3();
            // Wake up the other thread.
            synchronized(Main.class) {
                Main.class.notify();
            }
        } else if (wait) {
            // This is the other thread.
            synchronized(Main.class) {
                sOtherThreadStarted = true;
                // Wait for Main2 to be linked and deoptimization is triggered.
                try {
                    Main.class.wait();
                } catch (Exception e) {
                }
            }
        }

        // There should be a deoptimization here right after Main3 is linked by
        // calling Helper.createMain3(), even though sMain1 didn't change.
        // The behavior here would be different if inline-cache is used, which
        // doesn't deoptimize since sMain1 still hits the type cache.
        if (sMain1.foo(getValue(sMain1.getClass())) != 11) {
            System.out.println("11 expected.");
        }
        if ((createMain3 || wait) && sHasJIT && !sIsOptimizing) {
            // This method should be deoptimized right after Main3 is created.
            assertIsInterpreted();
        }

        if (sMain3 != null) {
            if (sMain3.foo(getValue(sMain3.getClass())) != -13) {
                System.out.println("-13 expected.");
            }
        }
    }

    // Test scenarios under which CHA-based devirtualization happens,
    // and class loading that implements a method can invalidate compiled code.
    public static void main(String[] args) {
        System.loadLibrary(args[0]);

        if (isInterpreted()) {
            sIsOptimizing = false;
        }

        // sMain1 is an instance of Main1.
        // sMain2 is an instance of Main2.
        // Neither Main1 nor Main2 override default method Base.foo().
        // Main3 hasn't bee loaded yet.
        sMain1 = new Main1();
        sMain2 = new Main2();

        ensureJitCompiled(Main.class, "testImplement");
        testImplement(false, false, true);

        if (sHasJIT && !sIsOptimizing) {
            assertSingleImplementation(Base.class, "foo", true);
            assertSingleImplementation(Main1.class, "foo", true);
        } else {
            // Main3 is verified ahead-of-time so it's linked in already.
        }

        // Create another thread that also calls sMain1.foo().
        // Try to test suspend and deopt another thread.
        new Thread() {
            public void run() {
                testImplement(false, true, false);
            }
        }.start();

        // This will create Main3 instance in the middle of testImplement().
        testImplement(true, false, false);
        assertSingleImplementation(Base.class, "foo", false);
        assertSingleImplementation(Main1.class, "foo", true);
        assertSingleImplementation(sMain3.getClass(), "foo", true);
    }

    private static native void ensureJitCompiled(Class<?> itf, String method_name);
    private static native void assertIsInterpreted();
    private static native void assertIsManaged();
    private static native boolean isInterpreted();
    private static native boolean hasSingleImplementation(Class<?> clazz, String method_name);
}

// Put createMain3() in another class to avoid class loading due to verifier.
class Helper {
    static Base createMain3() {
        return new Main3();
    }
}
