/*
 * Copyright 2009 Goldman Sachs International.  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 6865031
 * @summary Application gives bad result (throws bad exception) with compressed oops
 * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+UseCompressedOops -XX:HeapBaseMinAddress=32g -XX:-LoopUnswitching -XX:CompileCommand=inline,AbstractMemoryEfficientList.equals Test hello goodbye
 */

import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

interface MyList {
    public int size();
    public Object set(final int index, final Object element);
    public Object get(final int index);
}

abstract class AbstractMemoryEfficientList implements MyList {
    abstract public int size();
    abstract public Object get(final int index);
    abstract public Object set(final int index, final Object element);

    public boolean equals(Object o) {
        if (o == this) {
            return true;
        }

        if (!(o instanceof MyList)) {
            return false;
        }

        final MyList that = (MyList) o;
        if (this.size() != that.size()) {
            return false;
        }

        for (int i = 0; i < this.size(); i++) {
            try {
                if (!((this.get(i)).equals(that.get(i)))) {
                    return false;
                }
            } catch (IndexOutOfBoundsException e) {
                System.out.println("THROWING RT EXC");
                System.out.println("concurrent modification of this:" + this.getClass() + ":" + System.identityHashCode(this) + "; that:" + that.getClass() + ":" + System.identityHashCode(that) + "; i:" + i);
                e.printStackTrace();
                System.exit(97);
                throw new RuntimeException("concurrent modification of this:" + this.getClass() + ":" + System.identityHashCode(this) + "; that:" + that.getClass() + ":" + System.identityHashCode(that) + "; i:" + i, e);
            }
        }
        return true;
    }

    public int hashCode() {
        int hashCode = 1;
        for (int i = 0; i < this.size(); i++) {
            Object obj = this.get(i);
            hashCode = 31 * hashCode + (obj == null ? 0 : obj.hashCode());
        }
        return hashCode;
    }
}

final class SingletonList extends AbstractMemoryEfficientList {
    private Object element1;

    SingletonList(final Object obj1) {
        super();
        this.element1 = obj1;
    }

    public int size() {
        return 1;
    }

    public Object get(final int index) {
        if (index == 0) {
            return this.element1;
        } else {
            throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + this.size());
        }
    }

    public Object set(final int index, final Object element) {
        if (index == 0) {
            final Object previousElement = this.element1;
            this.element1 = element;
            return previousElement;
        } else {
            throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + this.size());
        }
    }
}

final class DoubletonList extends AbstractMemoryEfficientList {
    private Object element1;
    private Object element2;

    DoubletonList(final Object obj1, final Object obj2) {
        this.element1 = obj1;
        this.element2 = obj2;
    }

    public int size() {
        return 2;
    }

    public Object get(final int index) {
        switch (index) {
            case 0 : return this.element1;
            case 1 : return this.element2;
            default: throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + this.size());
        }
    }

    public Object set(final int index, final Object element) {
        switch (index) {
            case 0 :
            {
                final Object previousElement = this.element1;
                this.element1 = element;
                return previousElement;
            }
            case 1 :
            {
                final Object previousElement = this.element2;
                this.element2 = element;
                return previousElement;
            }
            default : throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + this.size());
        }
    }
}

class WeakPool<V> {
    protected static final int DEFAULT_INITIAL_CAPACITY = 16;
    private static final int MAXIMUM_CAPACITY = 1 << 30;
    private static final float DEFAULT_LOAD_FACTOR = 0.75f;

    protected Entry<V>[] table;

    private int size;
    protected int threshold;
    private final float loadFactor;
    private final ReferenceQueue<V> queue = new ReferenceQueue<V>();

    public WeakPool()
    {
        this.loadFactor = DEFAULT_LOAD_FACTOR;
        threshold = DEFAULT_INITIAL_CAPACITY;
        table = new Entry[DEFAULT_INITIAL_CAPACITY];
    }

    /**
     * Check for equality of non-null reference x and possibly-null y.  By
     * default uses Object.equals.
     */
    private boolean eq(Object x, Object y)
    {
        return x == y || x.equals(y);
    }

    /**
     * Return index for hash code h.
     */
    private int indexFor(int h, int length)
    {
        return h & length - 1;
    }

    /**
     * Expunge stale entries from the table.
     */
    private void expungeStaleEntries()
    {
        Object r;
        while ((r = queue.poll()) != null)
        {
            Entry e = (Entry) r;
            int h = e.hash;
            int i = indexFor(h, table.length);

            // System.out.println("EXPUNGING " + h);
            Entry<V> prev = table[i];
            Entry<V> p = prev;
            while (p != null)
            {
                Entry<V> next = p.next;
                if (p == e)
                {
                    if (prev == e)
                    {
                        table[i] = next;
                    }
                    else
                    {
                        prev.next = next;
                    }
                    e.next = null;  // Help GC
                    size--;
                    break;
                }
                prev = p;
                p = next;
            }
        }
    }

    /**
     * Return the table after first expunging stale entries
     */
    private Entry<V>[] getTable()
    {
        expungeStaleEntries();
        return table;
    }

    /**
     * Returns the number of key-value mappings in this map.
     * This result is a snapshot, and may not reflect unprocessed
     * entries that will be removed before next attempted access
     * because they are no longer referenced.
     */
    public int size()
    {
        if (size == 0)
        {
            return 0;
        }
        expungeStaleEntries();
        return size;
    }

    /**
     * Returns <tt>true</tt> if this map contains no key-value mappings.
     * This result is a snapshot, and may not reflect unprocessed
     * entries that will be removed before next attempted access
     * because they are no longer referenced.
     */
    public boolean isEmpty()
    {
        return size() == 0;
    }

    /**
     * Returns the value stored in the pool that equals the requested key
     * or <tt>null</tt> if the map contains no mapping for
     * this key (or the key is null)
     *
     * @param key the key whose equals value is to be returned.
     * @return the object that is equal the specified key, or
     *         <tt>null</tt> if key is null or no object in the pool equals the key.
     */
    public V get(V key)
    {
        if (key == null)
        {
            return null;
        }
        int h = key.hashCode();
        Entry<V>[] tab = getTable();
        int index = indexFor(h, tab.length);
        Entry<V> e = tab[index];
        while (e != null)
        {
            V candidate = e.get();
            if (e.hash == h && eq(key, candidate))
            {
                return candidate;
            }
            e = e.next;
        }
        return null;
    }

    /**
     * Returns the entry associated with the specified key in the HashMap.
     * Returns null if the HashMap contains no mapping for this key.
     */
    Entry getEntry(Object key)
    {
        int h = key.hashCode();
        Entry[] tab = getTable();
        int index = indexFor(h, tab.length);
        Entry e = tab[index];
        while (e != null && !(e.hash == h && eq(key, e.get())))
        {
            e = e.next;
        }
        return e;
    }

    /**
     * Places the object into the pool. If the object is null, nothing happens.
     * If an equal object already exists, it is not replaced.
     *
     * @param key the object to put into the pool. key may be null.
     * @return the object in the pool that is equal to the key, or the newly placed key if no such object existed when put was called
     */
    public V put(V key)
    {
        if (key == null)
        {
            return null;
        }
        int h = key.hashCode();
        Entry<V>[] tab = getTable();
        int i = indexFor(h, tab.length);

        for (Entry<V> e = tab[i]; e != null; e = e.next)
        {
            V candidate = e.get();
            if (h == e.hash && eq(key, candidate))
            {
                return candidate;
            }
        }

        tab[i] = new Entry<V>(key, queue, h, tab[i]);

        if (++size >= threshold)
        {
            resize(tab.length * 2);
        }

    // System.out.println("Added " + key + " to pool");
        return key;
    }

    /**
     * Rehashes the contents of this map into a new array with a
     * larger capacity.  This method is called automatically when the
     * number of keys in this map reaches its threshold.
     * <p/>
     * If current capacity is MAXIMUM_CAPACITY, this method does not
     * resize the map, but but sets threshold to Integer.MAX_VALUE.
     * This has the effect of preventing future calls.
     *
     * @param newCapacity the new capacity, MUST be a power of two;
     *                    must be greater than current capacity unless current
     *                    capacity is MAXIMUM_CAPACITY (in which case value
     *                    is irrelevant).
     */
    void resize(int newCapacity)
    {
        Entry<V>[] oldTable = getTable();
        int oldCapacity = oldTable.length;
        if (oldCapacity == MAXIMUM_CAPACITY)
        {
            threshold = Integer.MAX_VALUE;
            return;
        }

        Entry<V>[] newTable = new Entry[newCapacity];
        transfer(oldTable, newTable);
        table = newTable;

        /*
         * If ignoring null elements and processing ref queue caused massive
         * shrinkage, then restore old table.  This should be rare, but avoids
         * unbounded expansion of garbage-filled tables.
         */
        if (size >= threshold / 2)
        {
            threshold = (int) (newCapacity * loadFactor);
        }
        else
        {
            expungeStaleEntries();
            transfer(newTable, oldTable);
            table = oldTable;
        }
    }

    /**
     * Transfer all entries from src to dest tables
     */
    private void transfer(Entry[] src, Entry[] dest)
    {
        for (int j = 0; j < src.length; ++j)
        {
            Entry e = src[j];
            src[j] = null;
            while (e != null)
            {
                Entry next = e.next;
                Object key = e.get();
                if (key == null)
                {
                    e.next = null;  // Help GC
                    size--;
                }
                else
                {
                    int i = indexFor(e.hash, dest.length);
                    e.next = dest[i];
                    dest[i] = e;
                }
                e = next;
            }
        }
    }

    /**
     * Removes the object in the pool that equals the key.
     *
     * @param key
     * @return previous value associated with specified key, or <tt>null</tt>
     *         if there was no mapping for key or the key is null.
     */
    public V removeFromPool(V key)
    {
        if (key == null)
        {
            return null;
        }
        int h = key.hashCode();
        Entry<V>[] tab = getTable();
        int i = indexFor(h, tab.length);
        Entry<V> prev = tab[i];
        Entry<V> e = prev;

        while (e != null)
        {
            Entry<V> next = e.next;
            V candidate = e.get();
            if (h == e.hash && eq(key, candidate))
            {
                size--;
                if (prev == e)
                {
                    tab[i] = next;
                }
                else
                {
                    prev.next = next;
                }
                return candidate;
            }
            prev = e;
            e = next;
        }

        return null;
    }

    /**
     * Removes all mappings from this map.
     */
    public void clear()
    {
        // clear out ref queue. We don't need to expunge entries
        // since table is getting cleared.
        while (queue.poll() != null)
        {
            // nop
        }

        table = new Entry[DEFAULT_INITIAL_CAPACITY];
        threshold = DEFAULT_INITIAL_CAPACITY;
        size = 0;

        // Allocation of array may have caused GC, which may have caused
        // additional entries to go stale.  Removing these entries from the
        // reference queue will make them eligible for reclamation.
        while (queue.poll() != null)
        {
            // nop
        }
    }

    /**
     * The entries in this hash table extend WeakReference, using its main ref
     * field as the key.
     */
    protected static class Entry<V>
    extends WeakReference<V>
    {
        private final int hash;
        private Entry<V> next;

        /**
         * Create new entry.
         */
        Entry(final V key, final ReferenceQueue<V> queue, final int hash, final Entry<V> next)
        {
            super(key, queue);
            this.hash = hash;
            this.next = next;
        }

        public V getKey()
        {
            return super.get();
        }

        public boolean equals(Object o)
        {
            if (!(o instanceof WeakPool.Entry))
            {
                return false;
            }
            WeakPool.Entry<V> that = (WeakPool.Entry<V>) o;
            V k1 = this.getKey();
            V k2 = that.getKey();
            return (k1==k2 || k1.equals(k2));
        }

        public int hashCode()
        {
            return this.hash;
        }

        public String toString()
        {
            return String.valueOf(this.getKey());
        }
    }
}

final class MultiSynonymKey {
    private List<MyList> keys;

    public MultiSynonymKey() {
        keys = new ArrayList<MyList>();
    }

    public MultiSynonymKey(MyList... arg) {
        keys = Arrays.asList(arg);
    }

    public List<MyList> getKeys() {
        return keys;
    }

    public int hashCode() {
        return this.getKeys().hashCode();
    }

    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }

        if (!(obj instanceof MultiSynonymKey)) {
            return false;
        }

        MultiSynonymKey that = (MultiSynonymKey) obj;
        return this.getKeys().equals(that.getKeys());
    }

    public String toString() {
        return this.getClass().getName() + this.getKeys().toString();
    }
}

public class Test extends Thread {
    static public Test test;
    static private byte[] arg1;
    static private byte[] arg2;
    static public WeakPool<MultiSynonymKey> wp;
    public volatile MultiSynonymKey ml1;
    public volatile MultiSynonymKey ml2;
    private volatile MultiSynonymKey ml3;

    public void run() {
        int count=0;
        while (true) {
            try {
                Thread.sleep(10);
            } catch (Exception e) {}
            synchronized (wp) {
                ml2 = new MultiSynonymKey(new DoubletonList(new String(arg1), new String(arg2)));
                wp.put(ml2);
                ml3 = new MultiSynonymKey(new DoubletonList(new String(arg1), new String(arg2)));
            }
            try {
                Thread.sleep(10);
            } catch (Exception e) {}
            synchronized (wp) {
                ml1 = new MultiSynonymKey(new SingletonList(new String(arg1)));
                wp.put(ml1);
                ml3 = new MultiSynonymKey(new SingletonList(new String(arg1)));
            }
            if (count++==100)
                System.exit(95);
        }
    }

    public static void main(String[] args) throws Exception {
        wp = new WeakPool<MultiSynonymKey>();
        test = new Test();

        test.arg1 = args[0].getBytes();
        test.arg2 = args[1].getBytes();

        test.ml1 = new MultiSynonymKey(new SingletonList(new String(test.arg1)));
        test.ml2 = new MultiSynonymKey(new DoubletonList(new String(test.arg1), new String(test.arg2)));
        test.ml3 = new MultiSynonymKey(new DoubletonList(new String(test.arg1), new String(test.arg2)));

        wp.put(test.ml1);
        wp.put(test.ml2);

        test.setDaemon(true);
        test.start();

        int counter = 0;
        while (true) {
            synchronized (wp) {
                MultiSynonymKey foo = test.ml3;

                if (wp.put(foo) == foo) {
                    // System.out.println("foo " + counter);
                    // System.out.println(foo);
                }
            }
            counter++;
        }
    }

    private boolean eq(Object x, Object y) {
        return x == y || x.equals(y);
    }
}
