/*
 * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

/* @test
 * @bug 8133348
 * @summary Tests if reachabilityFence is working
 *
 * @requires vm.opt.DeoptimizeALot != true
 *
 * @run main/othervm -Xint                           -Dpremature=false ReachabilityFenceTest
 * @run main/othervm -Xbatch -XX:TieredStopAtLevel=1 -Dpremature=true  ReachabilityFenceTest
 * @run main/othervm -Xbatch -XX:TieredStopAtLevel=2 -Dpremature=true  ReachabilityFenceTest
 * @run main/othervm -Xbatch -XX:TieredStopAtLevel=3 -Dpremature=true  ReachabilityFenceTest
 * @run main/othervm -Xbatch -XX:TieredStopAtLevel=4 -Dpremature=true  ReachabilityFenceTest
 */

import java.lang.ref.Reference;
import java.util.concurrent.atomic.AtomicBoolean;

public class ReachabilityFenceTest {

    /*
     * Implementation notes:
     *
     * This test has positive and negative parts.
     *
     * Negative test is "nonFenced", and it tests that absent of reachabilityFence, the object can
     * be prematurely finalized -- this validates the test itself. Not every VM mode is expected to
     * prematurely finalize the objects, and -Dpremature option communicates that to test. If a VM mode
     * passes the negative test, then our understanding of what could happen is correct, and we can
     * go forward.
     *
     * Positive test is "fenced", and it checks that given the reachabilityFence at the end of the block,
     * the object cannot be finalized. There is no sense running a positive test when premature finalization
     * is not expected. It is a job for negative test to verify that invariant.
     *
     * The test methods should be appropriately compiled, therefore we do several iterations and run with -Xbatch.
     */

    // Enough to OSR and compile
    static final int LOOP_ITERS = Integer.getInteger("LOOP_ITERS", 50000);

    // Enough after which to start triggering GC and finalization
    static final int WARMUP_LOOP_ITERS = LOOP_ITERS - Integer.getInteger("GC_ITERS", 100);

    // Enough to switch from an OSR'ed method to compiled method
    static final int MAIN_ITERS = 3;

    static final boolean PREMATURE_FINALIZATION = Boolean.getBoolean("premature");

    public static void main(String... args) {
        // Negative test
        boolean finalized = false;
        for (int c = 0; !finalized && c < MAIN_ITERS; c++) {
            finalized |= nonFenced();
        }

        if (PREMATURE_FINALIZATION && !finalized) {
            throw new IllegalStateException("The object had never been finalized before timeout reached.");
        }

        if (!PREMATURE_FINALIZATION && finalized) {
            throw new IllegalStateException("The object had been finalized without a fence, even though we don't expect it.");
        }

        if (!PREMATURE_FINALIZATION)
            return;

        // Positive test
        finalized = false;
        for (int c = 0; !finalized && c < MAIN_ITERS; c++) {
            finalized |= fenced();
        }

        if (finalized) {
            throw new IllegalStateException("The object had been prematurely finalized.");
        }
    }

    public static boolean nonFenced() {
        AtomicBoolean finalized = new AtomicBoolean();
        MyFinalizeable o = new MyFinalizeable(finalized);

        for (int i = 0; i < LOOP_ITERS; i++) {
            if (finalized.get()) break;
            if (i > WARMUP_LOOP_ITERS) {
                System.gc();
                System.runFinalization();
            }
        }

        return finalized.get();
    }

    public static boolean fenced() {
        AtomicBoolean finalized = new AtomicBoolean();
        MyFinalizeable o = new MyFinalizeable(finalized);

        for (int i = 0; i < LOOP_ITERS; i++) {
            if (finalized.get()) break;
            if (i > WARMUP_LOOP_ITERS) {
                System.gc();
                System.runFinalization();
            }
        }

        try {
            return finalized.get();
        } finally {
            Reference.reachabilityFence(o);
        }
    }

    private static class MyFinalizeable {
        private final AtomicBoolean finalized;

        public MyFinalizeable(AtomicBoolean b) {
            this.finalized = b;
        }

        @Override
        protected void finalize() throws Throwable {
            super.finalize();
            finalized.set(true);
        }
    }
}
