/*
 * Copyright (c) 2018, 2022, 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 TestFromCardCacheIndex.java
 * @bug 8196485
 * @summary Ensure that G1 does not miss a remembered set entry due to from card cache default value indices.
 * @requires vm.gc.G1
 * @requires vm.debug
 * @requires vm.bits != "32"
 * @library /test/lib
 * @modules java.base/jdk.internal.misc
 *          java.management
 * @build jdk.test.whitebox.WhiteBox
 * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
 * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. -Xms20M -Xmx20M -XX:+UseCompressedOops -XX:G1HeapRegionSize=1M -XX:HeapBaseMinAddress=2199011721216 -XX:+UseG1GC -verbose:gc gc.g1.TestFromCardCacheIndex
 */
package gc.g1;

import jdk.test.whitebox.WhiteBox;

/**
 * Repeatedly tries to generate references from objects that contained a card with the same index
 * of the from card cache default value.
 */
public class TestFromCardCacheIndex {
    private static WhiteBox WB;

    // Shift value to calculate card indices from addresses.
    private static final int CardSizeShift = 9;

    /**
     * Returns the last address on the heap within the object.
     *
     * @param The Object array to get the last address from.
     */
    private static long getObjectLastAddress(Object[] o) {
        return WB.getObjectAddress(o) + WB.getObjectSize(o) - 1;
    }

    /**
     * Returns the (truncated) 32 bit card index for the given address.
     *
     * @param The address to get the 32 bit card index from.
     */
    private static int getCardIndex32bit(long address) {
        return (int)(address >> CardSizeShift);
    }

    // The source arrays that are placed on the heap in old gen.
    private static int numArrays = 7000;
    private static int arraySize = 508;
    // Size of a humongous byte array, a bit less than a 1M region. This makes sure
    // that we always create a cross-region reference when referencing it.
    private static int byteArraySize = 1024*1023;

    public static void main(String[] args) {
        WB = jdk.test.whitebox.WhiteBox.getWhiteBox();
        for (int i = 0; i < 5; i++) {
          runTest();
          WB.fullGC();
        }
    }

    public static void runTest() {
        System.out.println("Starting test");

        // Spray the heap with random object arrays in the hope that we get one
        // at the proper place.
        Object[][] arrays = new Object[numArrays][];
        for (int i = 0; i < numArrays; i++) {
            arrays[i] = new Object[arraySize];
        }

        // Make sure that everything is in old gen.
        WB.fullGC();

        // Find if we got an allocation at the right spot.
        Object[] arrayWithCardMinus1 = findArray(arrays);

        if (arrayWithCardMinus1 == null) {
            System.out.println("Array with card -1 not found. Trying again.");
            return;
        } else {
            System.out.println("Array with card -1 found.");
        }

        System.out.println("Modifying the last card in the array with a new object in a different region...");
        // Create a target object that is guaranteed to be in a different region.
        byte[] target = new byte[byteArraySize];

        // Modify the last entry of the object we found.
        arrayWithCardMinus1[arraySize - 1] = target;

        target = null;
        // Make sure that the dirty cards are flushed by doing a GC.
        System.out.println("Doing a GC.");
        WB.youngGC();

        System.out.println("The crash didn't reproduce. Trying again.");
    }

    /**
     * Finds an returns an array that contains a (32 bit truncated) card with value -1.
     */
    private static Object[] findArray(Object[][] arrays) {
        for (int i = 0; i < arrays.length; i++) {
            Object[] target = arrays[i];
            if (target == null) {
                continue;
            }
            WB.getObjectAddress(target); // startAddress not used
            final long lastAddress = getObjectLastAddress(target);
            final int card = getCardIndex32bit(lastAddress);
            if (card == -1) {
                Object[] foundArray = target;
                return foundArray;
            }
        }
        return null;
    }
}

