test/compiler/6865031/Test.java

Mon, 28 Jul 2014 15:06:38 -0700

author
fzhinkin
date
Mon, 28 Jul 2014 15:06:38 -0700
changeset 6997
dbb05f6d93c4
parent 1907
c18cbe5936b8
child 6876
710a3c8b516e
permissions
-rw-r--r--

8051344: JVM crashed in Compile::start() during method parsing w/ UseRTMDeopt turned on
Summary: call rtm_deopt() only if there were no compilation bailouts before.
Reviewed-by: kvn

     1 /*
     2  * Copyright 2009 Goldman Sachs International.  All Rights Reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.
     8  *
     9  * This code is distributed in the hope that it will be useful, but WITHOUT
    10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    12  * version 2 for more details (a copy is included in the LICENSE file that
    13  * accompanied this code).
    14  *
    15  * You should have received a copy of the GNU General Public License version
    16  * 2 along with this work; if not, write to the Free Software Foundation,
    17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    18  *
    19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    20  * or visit www.oracle.com if you need additional information or have any
    21  * questions.
    22  *
    23  */
    25 /*
    26  * @test
    27  * @bug 6865031
    28  * @summary Application gives bad result (throws bad exception) with compressed oops
    29  * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+UseCompressedOops -XX:HeapBaseMinAddress=32g -XX:-LoopUnswitching -XX:CompileCommand=inline,AbstractMemoryEfficientList.equals Test hello goodbye
    30  */
    32 import java.lang.ref.ReferenceQueue;
    33 import java.lang.ref.WeakReference;
    34 import java.util.ArrayList;
    35 import java.util.Arrays;
    36 import java.util.List;
    38 interface MyList {
    39     public int size();
    40     public Object set(final int index, final Object element);
    41     public Object get(final int index);
    42 }
    44 abstract class AbstractMemoryEfficientList implements MyList {
    45     abstract public int size();
    46     abstract public Object get(final int index);
    47     abstract public Object set(final int index, final Object element);
    49     public boolean equals(Object o) {
    50         if (o == this) {
    51             return true;
    52         }
    54         if (!(o instanceof MyList)) {
    55             return false;
    56         }
    58         final MyList that = (MyList) o;
    59         if (this.size() != that.size()) {
    60             return false;
    61         }
    63         for (int i = 0; i < this.size(); i++) {
    64             try {
    65                 if (!((this.get(i)).equals(that.get(i)))) {
    66                     return false;
    67                 }
    68             } catch (IndexOutOfBoundsException e) {
    69                 System.out.println("THROWING RT EXC");
    70                 System.out.println("concurrent modification of this:" + this.getClass() + ":" + System.identityHashCode(this) + "; that:" + that.getClass() + ":" + System.identityHashCode(that) + "; i:" + i);
    71                 e.printStackTrace();
    72                 System.exit(97);
    73                 throw new RuntimeException("concurrent modification of this:" + this.getClass() + ":" + System.identityHashCode(this) + "; that:" + that.getClass() + ":" + System.identityHashCode(that) + "; i:" + i, e);
    74             }
    75         }
    76         return true;
    77     }
    79     public int hashCode() {
    80         int hashCode = 1;
    81         for (int i = 0; i < this.size(); i++) {
    82             Object obj = this.get(i);
    83             hashCode = 31 * hashCode + (obj == null ? 0 : obj.hashCode());
    84         }
    85         return hashCode;
    86     }
    87 }
    89 final class SingletonList extends AbstractMemoryEfficientList {
    90     private Object element1;
    92     SingletonList(final Object obj1) {
    93         super();
    94         this.element1 = obj1;
    95     }
    97     public int size() {
    98         return 1;
    99     }
   101     public Object get(final int index) {
   102         if (index == 0) {
   103             return this.element1;
   104         } else {
   105             throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + this.size());
   106         }
   107     }
   109     public Object set(final int index, final Object element) {
   110         if (index == 0) {
   111             final Object previousElement = this.element1;
   112             this.element1 = element;
   113             return previousElement;
   114         } else {
   115             throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + this.size());
   116         }
   117     }
   118 }
   120 final class DoubletonList extends AbstractMemoryEfficientList {
   121     private Object element1;
   122     private Object element2;
   124     DoubletonList(final Object obj1, final Object obj2) {
   125         this.element1 = obj1;
   126         this.element2 = obj2;
   127     }
   129     public int size() {
   130         return 2;
   131     }
   133     public Object get(final int index) {
   134         switch (index) {
   135             case 0 : return this.element1;
   136             case 1 : return this.element2;
   137             default: throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + this.size());
   138         }
   139     }
   141     public Object set(final int index, final Object element) {
   142         switch (index) {
   143             case 0 :
   144             {
   145                 final Object previousElement = this.element1;
   146                 this.element1 = element;
   147                 return previousElement;
   148             }
   149             case 1 :
   150             {
   151                 final Object previousElement = this.element2;
   152                 this.element2 = element;
   153                 return previousElement;
   154             }
   155             default : throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + this.size());
   156         }
   157     }
   158 }
   160 class WeakPool<V> {
   161     protected static final int DEFAULT_INITIAL_CAPACITY = 16;
   162     private static final int MAXIMUM_CAPACITY = 1 << 30;
   163     private static final float DEFAULT_LOAD_FACTOR = 0.75f;
   165     protected Entry<V>[] table;
   167     private int size;
   168     protected int threshold;
   169     private final float loadFactor;
   170     private final ReferenceQueue<V> queue = new ReferenceQueue<V>();
   172     public WeakPool()
   173     {
   174         this.loadFactor = DEFAULT_LOAD_FACTOR;
   175         threshold = DEFAULT_INITIAL_CAPACITY;
   176         table = new Entry[DEFAULT_INITIAL_CAPACITY];
   177     }
   179     /**
   180      * Check for equality of non-null reference x and possibly-null y.  By
   181      * default uses Object.equals.
   182      */
   183     private boolean eq(Object x, Object y)
   184     {
   185         return x == y || x.equals(y);
   186     }
   188     /**
   189      * Return index for hash code h.
   190      */
   191     private int indexFor(int h, int length)
   192     {
   193         return h & length - 1;
   194     }
   196     /**
   197      * Expunge stale entries from the table.
   198      */
   199     private void expungeStaleEntries()
   200     {
   201         Object r;
   202         while ((r = queue.poll()) != null)
   203         {
   204             Entry e = (Entry) r;
   205             int h = e.hash;
   206             int i = indexFor(h, table.length);
   208             // System.out.println("EXPUNGING " + h);
   209             Entry<V> prev = table[i];
   210             Entry<V> p = prev;
   211             while (p != null)
   212             {
   213                 Entry<V> next = p.next;
   214                 if (p == e)
   215                 {
   216                     if (prev == e)
   217                     {
   218                         table[i] = next;
   219                     }
   220                     else
   221                     {
   222                         prev.next = next;
   223                     }
   224                     e.next = null;  // Help GC
   225                     size--;
   226                     break;
   227                 }
   228                 prev = p;
   229                 p = next;
   230             }
   231         }
   232     }
   234     /**
   235      * Return the table after first expunging stale entries
   236      */
   237     private Entry<V>[] getTable()
   238     {
   239         expungeStaleEntries();
   240         return table;
   241     }
   243     /**
   244      * Returns the number of key-value mappings in this map.
   245      * This result is a snapshot, and may not reflect unprocessed
   246      * entries that will be removed before next attempted access
   247      * because they are no longer referenced.
   248      */
   249     public int size()
   250     {
   251         if (size == 0)
   252         {
   253             return 0;
   254         }
   255         expungeStaleEntries();
   256         return size;
   257     }
   259     /**
   260      * Returns <tt>true</tt> if this map contains no key-value mappings.
   261      * This result is a snapshot, and may not reflect unprocessed
   262      * entries that will be removed before next attempted access
   263      * because they are no longer referenced.
   264      */
   265     public boolean isEmpty()
   266     {
   267         return size() == 0;
   268     }
   270     /**
   271      * Returns the value stored in the pool that equals the requested key
   272      * or <tt>null</tt> if the map contains no mapping for
   273      * this key (or the key is null)
   274      *
   275      * @param key the key whose equals value is to be returned.
   276      * @return the object that is equal the specified key, or
   277      *         <tt>null</tt> if key is null or no object in the pool equals the key.
   278      */
   279     public V get(V key)
   280     {
   281         if (key == null)
   282         {
   283             return null;
   284         }
   285         int h = key.hashCode();
   286         Entry<V>[] tab = getTable();
   287         int index = indexFor(h, tab.length);
   288         Entry<V> e = tab[index];
   289         while (e != null)
   290         {
   291             V candidate = e.get();
   292             if (e.hash == h && eq(key, candidate))
   293             {
   294                 return candidate;
   295             }
   296             e = e.next;
   297         }
   298         return null;
   299     }
   301     /**
   302      * Returns the entry associated with the specified key in the HashMap.
   303      * Returns null if the HashMap contains no mapping for this key.
   304      */
   305     Entry getEntry(Object key)
   306     {
   307         int h = key.hashCode();
   308         Entry[] tab = getTable();
   309         int index = indexFor(h, tab.length);
   310         Entry e = tab[index];
   311         while (e != null && !(e.hash == h && eq(key, e.get())))
   312         {
   313             e = e.next;
   314         }
   315         return e;
   316     }
   318     /**
   319      * Places the object into the pool. If the object is null, nothing happens.
   320      * If an equal object already exists, it is not replaced.
   321      *
   322      * @param key the object to put into the pool. key may be null.
   323      * @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
   324      */
   325     public V put(V key)
   326     {
   327         if (key == null)
   328         {
   329             return null;
   330         }
   331         int h = key.hashCode();
   332         Entry<V>[] tab = getTable();
   333         int i = indexFor(h, tab.length);
   335         for (Entry<V> e = tab[i]; e != null; e = e.next)
   336         {
   337             V candidate = e.get();
   338             if (h == e.hash && eq(key, candidate))
   339             {
   340                 return candidate;
   341             }
   342         }
   344         tab[i] = new Entry<V>(key, queue, h, tab[i]);
   346         if (++size >= threshold)
   347         {
   348             resize(tab.length * 2);
   349         }
   351     // System.out.println("Added " + key + " to pool");
   352         return key;
   353     }
   355     /**
   356      * Rehashes the contents of this map into a new array with a
   357      * larger capacity.  This method is called automatically when the
   358      * number of keys in this map reaches its threshold.
   359      * <p/>
   360      * If current capacity is MAXIMUM_CAPACITY, this method does not
   361      * resize the map, but but sets threshold to Integer.MAX_VALUE.
   362      * This has the effect of preventing future calls.
   363      *
   364      * @param newCapacity the new capacity, MUST be a power of two;
   365      *                    must be greater than current capacity unless current
   366      *                    capacity is MAXIMUM_CAPACITY (in which case value
   367      *                    is irrelevant).
   368      */
   369     void resize(int newCapacity)
   370     {
   371         Entry<V>[] oldTable = getTable();
   372         int oldCapacity = oldTable.length;
   373         if (oldCapacity == MAXIMUM_CAPACITY)
   374         {
   375             threshold = Integer.MAX_VALUE;
   376             return;
   377         }
   379         Entry<V>[] newTable = new Entry[newCapacity];
   380         transfer(oldTable, newTable);
   381         table = newTable;
   383         /*
   384          * If ignoring null elements and processing ref queue caused massive
   385          * shrinkage, then restore old table.  This should be rare, but avoids
   386          * unbounded expansion of garbage-filled tables.
   387          */
   388         if (size >= threshold / 2)
   389         {
   390             threshold = (int) (newCapacity * loadFactor);
   391         }
   392         else
   393         {
   394             expungeStaleEntries();
   395             transfer(newTable, oldTable);
   396             table = oldTable;
   397         }
   398     }
   400     /**
   401      * Transfer all entries from src to dest tables
   402      */
   403     private void transfer(Entry[] src, Entry[] dest)
   404     {
   405         for (int j = 0; j < src.length; ++j)
   406         {
   407             Entry e = src[j];
   408             src[j] = null;
   409             while (e != null)
   410             {
   411                 Entry next = e.next;
   412                 Object key = e.get();
   413                 if (key == null)
   414                 {
   415                     e.next = null;  // Help GC
   416                     size--;
   417                 }
   418                 else
   419                 {
   420                     int i = indexFor(e.hash, dest.length);
   421                     e.next = dest[i];
   422                     dest[i] = e;
   423                 }
   424                 e = next;
   425             }
   426         }
   427     }
   429     /**
   430      * Removes the object in the pool that equals the key.
   431      *
   432      * @param key
   433      * @return previous value associated with specified key, or <tt>null</tt>
   434      *         if there was no mapping for key or the key is null.
   435      */
   436     public V removeFromPool(V key)
   437     {
   438         if (key == null)
   439         {
   440             return null;
   441         }
   442         int h = key.hashCode();
   443         Entry<V>[] tab = getTable();
   444         int i = indexFor(h, tab.length);
   445         Entry<V> prev = tab[i];
   446         Entry<V> e = prev;
   448         while (e != null)
   449         {
   450             Entry<V> next = e.next;
   451             V candidate = e.get();
   452             if (h == e.hash && eq(key, candidate))
   453             {
   454                 size--;
   455                 if (prev == e)
   456                 {
   457                     tab[i] = next;
   458                 }
   459                 else
   460                 {
   461                     prev.next = next;
   462                 }
   463                 return candidate;
   464             }
   465             prev = e;
   466             e = next;
   467         }
   469         return null;
   470     }
   472     /**
   473      * Removes all mappings from this map.
   474      */
   475     public void clear()
   476     {
   477         // clear out ref queue. We don't need to expunge entries
   478         // since table is getting cleared.
   479         while (queue.poll() != null)
   480         {
   481             // nop
   482         }
   484         table = new Entry[DEFAULT_INITIAL_CAPACITY];
   485         threshold = DEFAULT_INITIAL_CAPACITY;
   486         size = 0;
   488         // Allocation of array may have caused GC, which may have caused
   489         // additional entries to go stale.  Removing these entries from the
   490         // reference queue will make them eligible for reclamation.
   491         while (queue.poll() != null)
   492         {
   493             // nop
   494         }
   495     }
   497     /**
   498      * The entries in this hash table extend WeakReference, using its main ref
   499      * field as the key.
   500      */
   501     protected static class Entry<V>
   502     extends WeakReference<V>
   503     {
   504         private final int hash;
   505         private Entry<V> next;
   507         /**
   508          * Create new entry.
   509          */
   510         Entry(final V key, final ReferenceQueue<V> queue, final int hash, final Entry<V> next)
   511         {
   512             super(key, queue);
   513             this.hash = hash;
   514             this.next = next;
   515         }
   517         public V getKey()
   518         {
   519             return super.get();
   520         }
   522         public boolean equals(Object o)
   523         {
   524             if (!(o instanceof WeakPool.Entry))
   525             {
   526                 return false;
   527             }
   528             WeakPool.Entry<V> that = (WeakPool.Entry<V>) o;
   529             V k1 = this.getKey();
   530             V k2 = that.getKey();
   531             return (k1==k2 || k1.equals(k2));
   532         }
   534         public int hashCode()
   535         {
   536             return this.hash;
   537         }
   539         public String toString()
   540         {
   541             return String.valueOf(this.getKey());
   542         }
   543     }
   544 }
   546 final class MultiSynonymKey {
   547     private List<MyList> keys;
   549     public MultiSynonymKey() {
   550         keys = new ArrayList<MyList>();
   551     }
   553     public MultiSynonymKey(MyList... arg) {
   554         keys = Arrays.asList(arg);
   555     }
   557     public List<MyList> getKeys() {
   558         return keys;
   559     }
   561     public int hashCode() {
   562         return this.getKeys().hashCode();
   563     }
   565     public boolean equals(Object obj) {
   566         if (this == obj) {
   567             return true;
   568         }
   570         if (!(obj instanceof MultiSynonymKey)) {
   571             return false;
   572         }
   574         MultiSynonymKey that = (MultiSynonymKey) obj;
   575         return this.getKeys().equals(that.getKeys());
   576     }
   578     public String toString() {
   579         return this.getClass().getName() + this.getKeys().toString();
   580     }
   581 }
   583 public class Test extends Thread {
   584     static public Test test;
   585     static private byte[] arg1;
   586     static private byte[] arg2;
   587     static public WeakPool<MultiSynonymKey> wp;
   588     public volatile MultiSynonymKey ml1;
   589     public volatile MultiSynonymKey ml2;
   590     private volatile MultiSynonymKey ml3;
   592     public void run() {
   593         int count=0;
   594         while (true) {
   595             try {
   596                 Thread.sleep(10);
   597             } catch (Exception e) {}
   598             synchronized (wp) {
   599                 ml2 = new MultiSynonymKey(new DoubletonList(new String(arg1), new String(arg2)));
   600                 wp.put(ml2);
   601                 ml3 = new MultiSynonymKey(new DoubletonList(new String(arg1), new String(arg2)));
   602             }
   603             try {
   604                 Thread.sleep(10);
   605             } catch (Exception e) {}
   606             synchronized (wp) {
   607                 ml1 = new MultiSynonymKey(new SingletonList(new String(arg1)));
   608                 wp.put(ml1);
   609                 ml3 = new MultiSynonymKey(new SingletonList(new String(arg1)));
   610             }
   611             if (count++==100)
   612                 System.exit(95);
   613         }
   614     }
   616     public static void main(String[] args) throws Exception {
   617         wp = new WeakPool<MultiSynonymKey>();
   618         test = new Test();
   620         test.arg1 = args[0].getBytes();
   621         test.arg2 = args[1].getBytes();
   623         test.ml1 = new MultiSynonymKey(new SingletonList(new String(test.arg1)));
   624         test.ml2 = new MultiSynonymKey(new DoubletonList(new String(test.arg1), new String(test.arg2)));
   625         test.ml3 = new MultiSynonymKey(new DoubletonList(new String(test.arg1), new String(test.arg2)));
   627         wp.put(test.ml1);
   628         wp.put(test.ml2);
   630         test.setDaemon(true);
   631         test.start();
   633         int counter = 0;
   634         while (true) {
   635             synchronized (wp) {
   636                 MultiSynonymKey foo = test.ml3;
   638                 if (wp.put(foo) == foo) {
   639                     // System.out.println("foo " + counter);
   640                     // System.out.println(foo);
   641                 }
   642             }
   643             counter++;
   644         }
   645     }
   647     private boolean eq(Object x, Object y) {
   648         return x == y || x.equals(y);
   649     }
   650 }

mercurial