/*
 * Copyright (C) 2016 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 {
    String getName() {
        return "Main1";
    }

    void printError(String msg) {
        System.out.println(msg);
    }

    void foo(int i) {
        if (i != 1) {
            printError("error1");
        }
    }

    int getValue1() {
        return 1;
    }
    int getValue2() {
        return 2;
    }
    int getValue3() {
        return 3;
    }
    int getValue4() {
        return 4;
    }
    int getValue5() {
        return 5;
    }
    int getValue6() {
        return 6;
    }
}

class Main2 extends Main1 {
    String getName() {
        return "Main2";
    }

    void foo(int i) {
        if (i != 2) {
            printError("error2");
        }
    }
}

class Main3 extends Main1 {
    String getName() {
        return "Main3";
    }
}

public class Main {
    static Main1 sMain1;
    static Main1 sMain2;

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

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

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

        sMain1.foo(sMain1.getClass() == Main1.class ? 1 : 2);

        if (createMain2) {
            // Wait for the other thread to start.
            while (!sOtherThreadStarted);
            // Create an Main2 instance and assign it to sMain2.
            // sMain1 is kept the same.
            sMain2 = Helper.createMain2();
            // 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 Main2 is linked by
        // calling Helper.createMain2(), 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.
        sMain1.foo(sMain1.getClass() == Main1.class ? 1 : 2);
        if ((createMain2 || wait) && sHasJIT && !sIsOptimizing) {
            // This method should be deoptimized right after Main2 is created.
            assertIsInterpreted();
        }

        if (sMain2 != null) {
            sMain2.foo(sMain2.getClass() == Main1.class ? 1 : 2);
        }
    }

    static Main1[] sArray;

    static long calcValue(Main1 m) {
        return m.getValue1()
                + m.getValue2() * 2
                + m.getValue3() * 3
                + m.getValue4() * 4
                + m.getValue5() * 5
                + m.getValue6() * 6;
    }

    static long testNoOverrideLoop(int count) {
        long sum = 0;
        for (int i=0; i<count; i++) {
            sum += calcValue(sArray[0]);
            sum += calcValue(sArray[1]);
            sum += calcValue(sArray[2]);
        }
        return sum;
    }

    static void testNoOverride() {
        sArray = new Main1[3];
        sArray[0] = new Main1();
        sArray[1] = Helper.createMain2();
        sArray[2] = Helper.createMain3();
        long sum = 0;
        // Loop enough to get methods JITed.
        for (int i=0; i<100; i++) {
            testNoOverrideLoop(1);
        }
        ensureJitCompiled(Main.class, "testNoOverrideLoop");
        ensureJitCompiled(Main.class, "calcValue");

        long t1 = System.currentTimeMillis();
        sum = testNoOverrideLoop(100000);
        long t2 = System.currentTimeMillis();
        if (sum != 27300000L) {
            System.out.println("Unexpected result.");
        }
    }

    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);
        }
    }

    // Test scenarios under which CHA-based devirtualization happens,
    // and class loading that overrides a method can invalidate compiled code.
    // Also test pure non-overriding case, which is more for checking generated
    // code form.
    public static void main(String[] args) {
        System.loadLibrary(args[0]);

        // CHeck some boot-image methods.

        // We would want to have this, but currently setting single-implementation in the boot image
        // does not work well with app images. b/34193647
        final boolean ARRAYLIST_SIZE_EXPECTED = false;
        assertSingleImplementation(java.util.ArrayList.class, "size", ARRAYLIST_SIZE_EXPECTED);

        // java.util.LinkedHashMap overrides get().
        assertSingleImplementation(java.util.HashMap.class, "get", false);

        // We don't set single-implementation modifier bit for final classes or methods
        // since we can devirtualize without CHA for those cases. However hasSingleImplementation()
        // should return true for those cases.
        assertSingleImplementation(java.lang.String.class, "charAt", true);
        assertSingleImplementation(java.lang.Thread.class, "join", true);

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

        // sMain1 is an instance of Main1. Main2 hasn't bee loaded yet.
        sMain1 = new Main1();

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

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

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

        // This will create Main2 instance in the middle of testOverride().
        testOverride(true, false, false);
        assertSingleImplementation(Main1.class, "foo", false);
        assertSingleImplementation(Main1.class, "getValue1", true);

        testNoOverride();
    }

    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 createMain2() in another class to avoid class loading due to verifier.
class Helper {
    static Main1 createMain2() {
        return new Main2();
    }
    static Main1 createMain3() {
        return new Main3();
    }
}
