ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/ConcurrentHashMap.java
(Generate patch)

Comparing jsr166/src/main/java/util/concurrent/ConcurrentHashMap.java (file contents):
Revision 1.273 by jsr166, Wed Apr 29 18:01:41 2015 UTC vs.
Revision 1.318 by jsr166, Sat Aug 10 16:48:05 2019 UTC

# Line 39 | Line 39 | import java.util.function.ToIntFunction;
39   import java.util.function.ToLongBiFunction;
40   import java.util.function.ToLongFunction;
41   import java.util.stream.Stream;
42 + import jdk.internal.misc.Unsafe;
43  
44   /**
45   * A hash table supporting full concurrency of retrievals and
# Line 121 | Line 122 | import java.util.stream.Stream;
122   * being concurrently updated by other threads; for example, when
123   * computing a snapshot summary of the values in a shared registry.
124   * There are three kinds of operation, each with four forms, accepting
125 < * functions with Keys, Values, Entries, and (Key, Value) arguments
126 < * and/or return values. Because the elements of a ConcurrentHashMap
127 < * are not ordered in any particular way, and may be processed in
128 < * different orders in different parallel executions, the correctness
129 < * of supplied functions should not depend on any ordering, or on any
130 < * other objects or values that may transiently change while
131 < * computation is in progress; and except for forEach actions, should
132 < * ideally be side-effect-free. Bulk operations on {@link java.util.Map.Entry}
133 < * objects do not support method {@code setValue}.
125 > * functions with keys, values, entries, and (key, value) pairs as
126 > * arguments and/or return values. Because the elements of a
127 > * ConcurrentHashMap are not ordered in any particular way, and may be
128 > * processed in different orders in different parallel executions, the
129 > * correctness of supplied functions should not depend on any
130 > * ordering, or on any other objects or values that may transiently
131 > * change while computation is in progress; and except for forEach
132 > * actions, should ideally be side-effect-free. Bulk operations on
133 > * {@link Map.Entry} objects do not support method {@code setValue}.
134   *
135   * <ul>
136 < * <li> forEach: Perform a given action on each element.
136 > * <li>forEach: Performs a given action on each element.
137   * A variant form applies a given transformation on each element
138 < * before performing the action.</li>
138 > * before performing the action.
139   *
140 < * <li> search: Return the first available non-null result of
140 > * <li>search: Returns the first available non-null result of
141   * applying a given function on each element; skipping further
142 < * search when a result is found.</li>
142 > * search when a result is found.
143   *
144 < * <li> reduce: Accumulate each element.  The supplied reduction
144 > * <li>reduce: Accumulates each element.  The supplied reduction
145   * function cannot rely on ordering (more formally, it should be
146   * both associative and commutative).  There are five variants:
147   *
148   * <ul>
149   *
150 < * <li> Plain reductions. (There is not a form of this method for
150 > * <li>Plain reductions. (There is not a form of this method for
151   * (key, value) function arguments since there is no corresponding
152 < * return type.)</li>
152 > * return type.)
153   *
154 < * <li> Mapped reductions that accumulate the results of a given
155 < * function applied to each element.</li>
154 > * <li>Mapped reductions that accumulate the results of a given
155 > * function applied to each element.
156   *
157 < * <li> Reductions to scalar doubles, longs, and ints, using a
158 < * given basis value.</li>
157 > * <li>Reductions to scalar doubles, longs, and ints, using a
158 > * given basis value.
159   *
160   * </ul>
160 * </li>
161   * </ul>
162   *
163   * <p>These bulk operations accept a {@code parallelismThreshold}
# Line 224 | Line 224 | import java.util.stream.Stream;
224   * <p>All arguments to all task methods must be non-null.
225   *
226   * <p>This class is a member of the
227 < * <a href="{@docRoot}/../technotes/guides/collections/index.html">
227 > * <a href="{@docRoot}/java.base/java/util/package-summary.html#CollectionsFramework">
228   * Java Collections Framework</a>.
229   *
230   * @since 1.5
# Line 268 | Line 268 | public class ConcurrentHashMap<K,V> exte
268       * Table accesses require volatile/atomic reads, writes, and
269       * CASes.  Because there is no other way to arrange this without
270       * adding further indirections, we use intrinsics
271 <     * (sun.misc.Unsafe) operations.
271 >     * (jdk.internal.misc.Unsafe) operations.
272       *
273       * We use the top (sign) bit of Node hash fields for control
274       * purposes -- it is available anyway because of addressing
# Line 356 | Line 356 | public class ConcurrentHashMap<K,V> exte
356       * cases where old nodes can be reused because their next fields
357       * won't change.  On average, only about one-sixth of them need
358       * cloning when a table doubles. The nodes they replace will be
359 <     * garbage collectable as soon as they are no longer referenced by
359 >     * garbage collectible as soon as they are no longer referenced by
360       * any reader thread that may be in the midst of concurrently
361       * traversing table.  Upon transfer, the old table bin contains
362       * only a special forwarding node (with hash field "MOVED") that
# Line 448 | Line 448 | public class ConcurrentHashMap<K,V> exte
448       *
449       * Maintaining API and serialization compatibility with previous
450       * versions of this class introduces several oddities. Mainly: We
451 <     * leave untouched but unused constructor arguments refering to
451 >     * leave untouched but unused constructor arguments referring to
452       * concurrencyLevel. We accept a loadFactor constructor argument,
453       * but apply it only to initial table capacity (which is the only
454       * time that we can guarantee to honor it.) We also declare an
# Line 543 | Line 543 | public class ConcurrentHashMap<K,V> exte
543       * The number of bits used for generation stamp in sizeCtl.
544       * Must be at least 6 for 32bit arrays.
545       */
546 <    private static int RESIZE_STAMP_BITS = 16;
546 >    private static final int RESIZE_STAMP_BITS = 16;
547  
548      /**
549       * The maximum number of threads that can help resize.
# Line 567 | Line 567 | public class ConcurrentHashMap<K,V> exte
567      /** Number of CPUS, to place bounds on some sizings */
568      static final int NCPU = Runtime.getRuntime().availableProcessors();
569  
570 <    /** For serialization compatibility. */
570 >    /**
571 >     * Serialized pseudo-fields, provided only for jdk7 compatibility.
572 >     * @serialField segments Segment[]
573 >     *   The segments, each of which is a specialized hash table.
574 >     * @serialField segmentMask int
575 >     *   Mask value for indexing into segments. The upper bits of a
576 >     *   key's hash code are used to choose the segment.
577 >     * @serialField segmentShift int
578 >     *   Shift value for indexing within segments.
579 >     */
580      private static final ObjectStreamField[] serialPersistentFields = {
581          new ObjectStreamField("segments", Segment[].class),
582          new ObjectStreamField("segmentMask", Integer.TYPE),
583 <        new ObjectStreamField("segmentShift", Integer.TYPE)
583 >        new ObjectStreamField("segmentShift", Integer.TYPE),
584      };
585  
586      /* ---------------- Nodes -------------- */
# Line 590 | Line 599 | public class ConcurrentHashMap<K,V> exte
599          volatile V val;
600          volatile Node<K,V> next;
601  
602 <        Node(int hash, K key, V val, Node<K,V> next) {
602 >        Node(int hash, K key, V val) {
603              this.hash = hash;
604              this.key = key;
605              this.val = val;
606 +        }
607 +
608 +        Node(int hash, K key, V val, Node<K,V> next) {
609 +            this(hash, key, val);
610              this.next = next;
611          }
612  
# Line 660 | Line 673 | public class ConcurrentHashMap<K,V> exte
673       * See Hackers Delight, sec 3.2
674       */
675      private static final int tableSizeFor(int c) {
676 <        int n = c - 1;
664 <        n |= n >>> 1;
665 <        n |= n >>> 2;
666 <        n |= n >>> 4;
667 <        n |= n >>> 8;
668 <        n |= n >>> 16;
676 >        int n = -1 >>> Integer.numberOfLeadingZeros(c - 1);
677          return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;
678      }
679  
# Line 675 | Line 683 | public class ConcurrentHashMap<K,V> exte
683       */
684      static Class<?> comparableClassFor(Object x) {
685          if (x instanceof Comparable) {
686 <            Class<?> c; Type[] ts, as; Type t; ParameterizedType p;
686 >            Class<?> c; Type[] ts, as; ParameterizedType p;
687              if ((c = x.getClass()) == String.class) // bypass checks
688                  return c;
689              if ((ts = c.getGenericInterfaces()) != null) {
690 <                for (int i = 0; i < ts.length; ++i) {
691 <                    if (((t = ts[i]) instanceof ParameterizedType) &&
690 >                for (Type t : ts) {
691 >                    if ((t instanceof ParameterizedType) &&
692                          ((p = (ParameterizedType)t).getRawType() ==
693                           Comparable.class) &&
694                          (as = p.getActualTypeArguments()) != null &&
# Line 705 | Line 713 | public class ConcurrentHashMap<K,V> exte
713      /* ---------------- Table element access -------------- */
714  
715      /*
716 <     * Volatile access methods are used for table elements as well as
716 >     * Atomic access methods are used for table elements as well as
717       * elements of in-progress next table while resizing.  All uses of
718       * the tab arguments must be null checked by callers.  All callers
719       * also paranoically precheck that tab's length is not zero (or an
# Line 715 | Line 723 | public class ConcurrentHashMap<K,V> exte
723       * errors by users, these checks must operate on local variables,
724       * which accounts for some odd-looking inline assignments below.
725       * Note that calls to setTabAt always occur within locked regions,
726 <     * and so in principle require only release ordering, not
719 <     * full volatile semantics, but are currently coded as volatile
720 <     * writes to be conservative.
726 >     * and so require only release ordering.
727       */
728  
729      @SuppressWarnings("unchecked")
730      static final <K,V> Node<K,V> tabAt(Node<K,V>[] tab, int i) {
731 <        return (Node<K,V>)U.getObjectVolatile(tab, ((long)i << ASHIFT) + ABASE);
731 >        return (Node<K,V>)U.getObjectAcquire(tab, ((long)i << ASHIFT) + ABASE);
732      }
733  
734      static final <K,V> boolean casTabAt(Node<K,V>[] tab, int i,
735                                          Node<K,V> c, Node<K,V> v) {
736 <        return U.compareAndSwapObject(tab, ((long)i << ASHIFT) + ABASE, c, v);
736 >        return U.compareAndSetObject(tab, ((long)i << ASHIFT) + ABASE, c, v);
737      }
738  
739      static final <K,V> void setTabAt(Node<K,V>[] tab, int i, Node<K,V> v) {
740 <        U.putObjectVolatile(tab, ((long)i << ASHIFT) + ABASE, v);
740 >        U.putObjectRelease(tab, ((long)i << ASHIFT) + ABASE, v);
741      }
742  
743      /* ---------------- Fields -------------- */
# Line 804 | Line 810 | public class ConcurrentHashMap<K,V> exte
810       * elements is negative
811       */
812      public ConcurrentHashMap(int initialCapacity) {
813 <        if (initialCapacity < 0)
808 <            throw new IllegalArgumentException();
809 <        int cap = ((initialCapacity >= (MAXIMUM_CAPACITY >>> 1)) ?
810 <                   MAXIMUM_CAPACITY :
811 <                   tableSizeFor(initialCapacity + (initialCapacity >>> 1) + 1));
812 <        this.sizeCtl = cap;
813 >        this(initialCapacity, LOAD_FACTOR, 1);
814      }
815  
816      /**
# Line 843 | Line 844 | public class ConcurrentHashMap<K,V> exte
844  
845      /**
846       * Creates a new, empty map with an initial table size based on
847 <     * the given number of elements ({@code initialCapacity}), table
848 <     * density ({@code loadFactor}), and number of concurrently
847 >     * the given number of elements ({@code initialCapacity}), initial
848 >     * table density ({@code loadFactor}), and number of concurrently
849       * updating threads ({@code concurrencyLevel}).
850       *
851       * @param initialCapacity the initial capacity. The implementation
# Line 982 | Line 983 | public class ConcurrentHashMap<K,V> exte
983          int hash = spread(key.hashCode());
984          int binCount = 0;
985          for (Node<K,V>[] tab = table;;) {
986 <            Node<K,V> f; int n, i, fh;
986 >            Node<K,V> f; int n, i, fh; K fk; V fv;
987              if (tab == null || (n = tab.length) == 0)
988                  tab = initTable();
989              else if ((f = tabAt(tab, i = (n - 1) & hash)) == null) {
990 <                if (casTabAt(tab, i, null,
990 <                             new Node<K,V>(hash, key, value, null)))
990 >                if (casTabAt(tab, i, null, new Node<K,V>(hash, key, value)))
991                      break;                   // no lock when adding to empty bin
992              }
993              else if ((fh = f.hash) == MOVED)
994                  tab = helpTransfer(tab, f);
995 +            else if (onlyIfAbsent // check first node without acquiring lock
996 +                     && fh == hash
997 +                     && ((fk = f.key) == key || (fk != null && key.equals(fk)))
998 +                     && (fv = f.val) != null)
999 +                return fv;
1000              else {
1001                  V oldVal = null;
1002                  synchronized (f) {
# Line 1010 | Line 1015 | public class ConcurrentHashMap<K,V> exte
1015                                  }
1016                                  Node<K,V> pred = e;
1017                                  if ((e = e.next) == null) {
1018 <                                    pred.next = new Node<K,V>(hash, key,
1014 <                                                              value, null);
1018 >                                    pred.next = new Node<K,V>(hash, key, value);
1019                                      break;
1020                                  }
1021                              }
# Line 1202 | Line 1206 | public class ConcurrentHashMap<K,V> exte
1206       */
1207      public KeySetView<K,V> keySet() {
1208          KeySetView<K,V> ks;
1209 <        return (ks = keySet) != null ? ks : (keySet = new KeySetView<K,V>(this, null));
1209 >        if ((ks = keySet) != null) return ks;
1210 >        return keySet = new KeySetView<K,V>(this, null);
1211      }
1212  
1213      /**
# Line 1225 | Line 1230 | public class ConcurrentHashMap<K,V> exte
1230       */
1231      public Collection<V> values() {
1232          ValuesView<K,V> vs;
1233 <        return (vs = values) != null ? vs : (values = new ValuesView<K,V>(this));
1233 >        if ((vs = values) != null) return vs;
1234 >        return values = new ValuesView<K,V>(this);
1235      }
1236  
1237      /**
# Line 1247 | Line 1253 | public class ConcurrentHashMap<K,V> exte
1253       */
1254      public Set<Map.Entry<K,V>> entrySet() {
1255          EntrySetView<K,V> es;
1256 <        return (es = entrySet) != null ? es : (entrySet = new EntrySetView<K,V>(this));
1256 >        if ((es = entrySet) != null) return es;
1257 >        return entrySet = new EntrySetView<K,V>(this);
1258      }
1259  
1260      /**
# Line 1339 | Line 1346 | public class ConcurrentHashMap<K,V> exte
1346  
1347      /**
1348       * Stripped-down version of helper class used in previous version,
1349 <     * declared for the sake of serialization compatibility
1349 >     * declared for the sake of serialization compatibility.
1350       */
1351      static class Segment<K,V> extends ReentrantLock implements Serializable {
1352          private static final long serialVersionUID = 2249069246763182397L;
# Line 1348 | Line 1355 | public class ConcurrentHashMap<K,V> exte
1355      }
1356  
1357      /**
1358 <     * Saves the state of the {@code ConcurrentHashMap} instance to a
1359 <     * stream (i.e., serializes it).
1358 >     * Saves this map to a stream (that is, serializes it).
1359 >     *
1360       * @param s the stream
1361       * @throws java.io.IOException if an I/O error occurs
1362       * @serialData
1363 <     * the key (Object) and value (Object)
1364 <     * for each key-value mapping, followed by a null pair.
1363 >     * the serialized fields, followed by the key (Object) and value
1364 >     * (Object) for each key-value mapping, followed by a null pair.
1365       * The key-value mappings are emitted in no particular order.
1366       */
1367      private void writeObject(java.io.ObjectOutputStream s)
# Line 1390 | Line 1397 | public class ConcurrentHashMap<K,V> exte
1397          }
1398          s.writeObject(null);
1399          s.writeObject(null);
1393        segments = null; // throw away
1400      }
1401  
1402      /**
1403 <     * Reconstitutes the instance from a stream (that is, deserializes it).
1403 >     * Reconstitutes this map from a stream (that is, deserializes it).
1404       * @param s the stream
1405       * @throws ClassNotFoundException if the class of a serialized object
1406       *         could not be found
# Line 1428 | Line 1434 | public class ConcurrentHashMap<K,V> exte
1434          if (size == 0L)
1435              sizeCtl = 0;
1436          else {
1437 <            int n;
1438 <            if (size >= (long)(MAXIMUM_CAPACITY >>> 1))
1439 <                n = MAXIMUM_CAPACITY;
1434 <            else {
1435 <                int sz = (int)size;
1436 <                n = tableSizeFor(sz + (sz >>> 1) + 1);
1437 <            }
1437 >            long ts = (long)(1.0 + size / LOAD_FACTOR);
1438 >            int n = (ts >= (long)MAXIMUM_CAPACITY) ?
1439 >                MAXIMUM_CAPACITY : tableSizeFor((int)ts);
1440              @SuppressWarnings("unchecked")
1441              Node<K,V>[] tab = (Node<K,V>[])new Node<?,?>[n];
1442              int mask = n - 1;
# Line 1594 | Line 1596 | public class ConcurrentHashMap<K,V> exte
1596      }
1597  
1598      /**
1599 <     * Helper method for EntrySet.removeIf
1599 >     * Helper method for EntrySetView.removeIf.
1600       */
1601      boolean removeEntryIf(Predicate<? super Entry<K,V>> function) {
1602          if (function == null) throw new NullPointerException();
# Line 1614 | Line 1616 | public class ConcurrentHashMap<K,V> exte
1616      }
1617  
1618      /**
1619 <     * Helper method for Values.removeIf
1619 >     * Helper method for ValuesView.removeIf.
1620       */
1621 <    boolean removeValueIf(Predicate<? super  V> function) {
1621 >    boolean removeValueIf(Predicate<? super V> function) {
1622          if (function == null) throw new NullPointerException();
1623          Node<K,V>[] t;
1624          boolean removed = false;
# Line 1661 | Line 1663 | public class ConcurrentHashMap<K,V> exte
1663          V val = null;
1664          int binCount = 0;
1665          for (Node<K,V>[] tab = table;;) {
1666 <            Node<K,V> f; int n, i, fh;
1666 >            Node<K,V> f; int n, i, fh; K fk; V fv;
1667              if (tab == null || (n = tab.length) == 0)
1668                  tab = initTable();
1669              else if ((f = tabAt(tab, i = (n - 1) & h)) == null) {
# Line 1672 | Line 1674 | public class ConcurrentHashMap<K,V> exte
1674                          Node<K,V> node = null;
1675                          try {
1676                              if ((val = mappingFunction.apply(key)) != null)
1677 <                                node = new Node<K,V>(h, key, val, null);
1677 >                                node = new Node<K,V>(h, key, val);
1678                          } finally {
1679                              setTabAt(tab, i, node);
1680                          }
# Line 1683 | Line 1685 | public class ConcurrentHashMap<K,V> exte
1685              }
1686              else if ((fh = f.hash) == MOVED)
1687                  tab = helpTransfer(tab, f);
1688 +            else if (fh == h    // check first node without acquiring lock
1689 +                     && ((fk = f.key) == key || (fk != null && key.equals(fk)))
1690 +                     && (fv = f.val) != null)
1691 +                return fv;
1692              else {
1693                  boolean added = false;
1694                  synchronized (f) {
# Line 1703 | Line 1709 | public class ConcurrentHashMap<K,V> exte
1709                                          if (pred.next != null)
1710                                              throw new IllegalStateException("Recursive update");
1711                                          added = true;
1712 <                                        pred.next = new Node<K,V>(h, key, val, null);
1712 >                                        pred.next = new Node<K,V>(h, key, val);
1713                                      }
1714                                      break;
1715                                  }
# Line 1872 | Line 1878 | public class ConcurrentHashMap<K,V> exte
1878                          try {
1879                              if ((val = remappingFunction.apply(key, null)) != null) {
1880                                  delta = 1;
1881 <                                node = new Node<K,V>(h, key, val, null);
1881 >                                node = new Node<K,V>(h, key, val);
1882                              }
1883                          } finally {
1884                              setTabAt(tab, i, node);
# Line 1914 | Line 1920 | public class ConcurrentHashMap<K,V> exte
1920                                          if (pred.next != null)
1921                                              throw new IllegalStateException("Recursive update");
1922                                          delta = 1;
1923 <                                        pred.next =
1918 <                                            new Node<K,V>(h, key, val, null);
1923 >                                        pred.next = new Node<K,V>(h, key, val);
1924                                      }
1925                                      break;
1926                                  }
# Line 1993 | Line 1998 | public class ConcurrentHashMap<K,V> exte
1998              if (tab == null || (n = tab.length) == 0)
1999                  tab = initTable();
2000              else if ((f = tabAt(tab, i = (n - 1) & h)) == null) {
2001 <                if (casTabAt(tab, i, null, new Node<K,V>(h, key, value, null))) {
2001 >                if (casTabAt(tab, i, null, new Node<K,V>(h, key, value))) {
2002                      delta = 1;
2003                      val = value;
2004                      break;
# Line 2028 | Line 2033 | public class ConcurrentHashMap<K,V> exte
2033                                  if ((e = e.next) == null) {
2034                                      delta = 1;
2035                                      val = value;
2036 <                                    pred.next =
2032 <                                        new Node<K,V>(h, key, val, null);
2036 >                                    pred.next = new Node<K,V>(h, key, val);
2037                                      break;
2038                                  }
2039                              }
# Line 2075 | Line 2079 | public class ConcurrentHashMap<K,V> exte
2079      // Hashtable legacy methods
2080  
2081      /**
2082 <     * Legacy method testing if some key maps into the specified value
2079 <     * in this table.
2082 >     * Tests if some key maps into the specified value in this table.
2083       *
2084 <     * @deprecated This method is identical in functionality to
2084 >     * <p>Note that this method is identical in functionality to
2085       * {@link #containsValue(Object)}, and exists solely to ensure
2086       * full compatibility with class {@link java.util.Hashtable},
2087       * which supported this method prior to introduction of the
2088 <     * Java Collections framework.
2088 >     * Java Collections Framework.
2089       *
2090       * @param  value a value to search for
2091       * @return {@code true} if and only if some key maps to the
# Line 2091 | Line 2094 | public class ConcurrentHashMap<K,V> exte
2094       *         {@code false} otherwise
2095       * @throws NullPointerException if the specified value is null
2096       */
2094    @Deprecated
2097      public boolean contains(Object value) {
2098          return containsValue(value);
2099      }
# Line 2192 | Line 2194 | public class ConcurrentHashMap<K,V> exte
2194      static final class ForwardingNode<K,V> extends Node<K,V> {
2195          final Node<K,V>[] nextTable;
2196          ForwardingNode(Node<K,V>[] tab) {
2197 <            super(MOVED, null, null, null);
2197 >            super(MOVED, null, null);
2198              this.nextTable = tab;
2199          }
2200  
# Line 2224 | Line 2226 | public class ConcurrentHashMap<K,V> exte
2226      }
2227  
2228      /**
2229 <     * A place-holder node used in computeIfAbsent and compute
2229 >     * A place-holder node used in computeIfAbsent and compute.
2230       */
2231      static final class ReservationNode<K,V> extends Node<K,V> {
2232          ReservationNode() {
2233 <            super(RESERVED, null, null, null);
2233 >            super(RESERVED, null, null);
2234          }
2235  
2236          Node<K,V> find(int h, Object k) {
# Line 2254 | Line 2256 | public class ConcurrentHashMap<K,V> exte
2256          while ((tab = table) == null || tab.length == 0) {
2257              if ((sc = sizeCtl) < 0)
2258                  Thread.yield(); // lost initialization race; just spin
2259 <            else if (U.compareAndSwapInt(this, SIZECTL, sc, -1)) {
2259 >            else if (U.compareAndSetInt(this, SIZECTL, sc, -1)) {
2260                  try {
2261                      if ((tab = table) == null || tab.length == 0) {
2262                          int n = (sc > 0) ? sc : DEFAULT_CAPACITY;
# Line 2283 | Line 2285 | public class ConcurrentHashMap<K,V> exte
2285       * @param check if <0, don't check resize, if <= 1 only check if uncontended
2286       */
2287      private final void addCount(long x, int check) {
2288 <        CounterCell[] as; long b, s;
2289 <        if ((as = counterCells) != null ||
2290 <            !U.compareAndSwapLong(this, BASECOUNT, b = baseCount, s = b + x)) {
2291 <            CounterCell a; long v; int m;
2288 >        CounterCell[] cs; long b, s;
2289 >        if ((cs = counterCells) != null ||
2290 >            !U.compareAndSetLong(this, BASECOUNT, b = baseCount, s = b + x)) {
2291 >            CounterCell c; long v; int m;
2292              boolean uncontended = true;
2293 <            if (as == null || (m = as.length - 1) < 0 ||
2294 <                (a = as[ThreadLocalRandom.getProbe() & m]) == null ||
2293 >            if (cs == null || (m = cs.length - 1) < 0 ||
2294 >                (c = cs[ThreadLocalRandom.getProbe() & m]) == null ||
2295                  !(uncontended =
2296 <                  U.compareAndSwapLong(a, CELLVALUE, v = a.value, v + x))) {
2296 >                  U.compareAndSetLong(c, CELLVALUE, v = c.value, v + x))) {
2297                  fullAddCount(x, uncontended);
2298                  return;
2299              }
# Line 2303 | Line 2305 | public class ConcurrentHashMap<K,V> exte
2305              Node<K,V>[] tab, nt; int n, sc;
2306              while (s >= (long)(sc = sizeCtl) && (tab = table) != null &&
2307                     (n = tab.length) < MAXIMUM_CAPACITY) {
2308 <                int rs = resizeStamp(n);
2308 >                int rs = resizeStamp(n) << RESIZE_STAMP_SHIFT;
2309                  if (sc < 0) {
2310 <                    if ((sc >>> RESIZE_STAMP_SHIFT) != rs || sc == rs + 1 ||
2311 <                        sc == rs + MAX_RESIZERS || (nt = nextTable) == null ||
2310 <                        transferIndex <= 0)
2310 >                    if (sc == rs + MAX_RESIZERS || sc == rs + 1 ||
2311 >                        (nt = nextTable) == null || transferIndex <= 0)
2312                          break;
2313 <                    if (U.compareAndSwapInt(this, SIZECTL, sc, sc + 1))
2313 >                    if (U.compareAndSetInt(this, SIZECTL, sc, sc + 1))
2314                          transfer(tab, nt);
2315                  }
2316 <                else if (U.compareAndSwapInt(this, SIZECTL, sc,
2316 <                                             (rs << RESIZE_STAMP_SHIFT) + 2))
2316 >                else if (U.compareAndSetInt(this, SIZECTL, sc, rs + 2))
2317                      transfer(tab, null);
2318                  s = sumCount();
2319              }
# Line 2327 | Line 2327 | public class ConcurrentHashMap<K,V> exte
2327          Node<K,V>[] nextTab; int sc;
2328          if (tab != null && (f instanceof ForwardingNode) &&
2329              (nextTab = ((ForwardingNode<K,V>)f).nextTable) != null) {
2330 <            int rs = resizeStamp(tab.length);
2330 >            int rs = resizeStamp(tab.length) << RESIZE_STAMP_SHIFT;
2331              while (nextTab == nextTable && table == tab &&
2332                     (sc = sizeCtl) < 0) {
2333 <                if ((sc >>> RESIZE_STAMP_SHIFT) != rs || sc == rs + 1 ||
2334 <                    sc == rs + MAX_RESIZERS || transferIndex <= 0)
2333 >                if (sc == rs + MAX_RESIZERS || sc == rs + 1 ||
2334 >                    transferIndex <= 0)
2335                      break;
2336 <                if (U.compareAndSwapInt(this, SIZECTL, sc, sc + 1)) {
2336 >                if (U.compareAndSetInt(this, SIZECTL, sc, sc + 1)) {
2337                      transfer(tab, nextTab);
2338                      break;
2339                  }
# Line 2356 | Line 2356 | public class ConcurrentHashMap<K,V> exte
2356              Node<K,V>[] tab = table; int n;
2357              if (tab == null || (n = tab.length) == 0) {
2358                  n = (sc > c) ? sc : c;
2359 <                if (U.compareAndSwapInt(this, SIZECTL, sc, -1)) {
2359 >                if (U.compareAndSetInt(this, SIZECTL, sc, -1)) {
2360                      try {
2361                          if (table == tab) {
2362                              @SuppressWarnings("unchecked")
# Line 2373 | Line 2373 | public class ConcurrentHashMap<K,V> exte
2373                  break;
2374              else if (tab == table) {
2375                  int rs = resizeStamp(n);
2376 <                if (U.compareAndSwapInt(this, SIZECTL, sc,
2376 >                if (U.compareAndSetInt(this, SIZECTL, sc,
2377                                          (rs << RESIZE_STAMP_SHIFT) + 2))
2378                      transfer(tab, null);
2379              }
# Line 2414 | Line 2414 | public class ConcurrentHashMap<K,V> exte
2414                      i = -1;
2415                      advance = false;
2416                  }
2417 <                else if (U.compareAndSwapInt
2417 >                else if (U.compareAndSetInt
2418                           (this, TRANSFERINDEX, nextIndex,
2419                            nextBound = (nextIndex > stride ?
2420                                         nextIndex - stride : 0))) {
# Line 2431 | Line 2431 | public class ConcurrentHashMap<K,V> exte
2431                      sizeCtl = (n << 1) - (n >>> 1);
2432                      return;
2433                  }
2434 <                if (U.compareAndSwapInt(this, SIZECTL, sc = sizeCtl, sc - 1)) {
2434 >                if (U.compareAndSetInt(this, SIZECTL, sc = sizeCtl, sc - 1)) {
2435                      if ((sc - 2) != resizeStamp(n) << RESIZE_STAMP_SHIFT)
2436                          return;
2437                      finishing = advance = true;
# Line 2511 | Line 2511 | public class ConcurrentHashMap<K,V> exte
2511                              setTabAt(tab, i, fwd);
2512                              advance = true;
2513                          }
2514 +                        else if (f instanceof ReservationNode)
2515 +                            throw new IllegalStateException("Recursive update");
2516                      }
2517                  }
2518              }
# Line 2523 | Line 2525 | public class ConcurrentHashMap<K,V> exte
2525       * A padded cell for distributing counts.  Adapted from LongAdder
2526       * and Striped64.  See their internal docs for explanation.
2527       */
2528 <    @sun.misc.Contended static final class CounterCell {
2528 >    @jdk.internal.vm.annotation.Contended static final class CounterCell {
2529          volatile long value;
2530          CounterCell(long x) { value = x; }
2531      }
2532  
2533      final long sumCount() {
2534 <        CounterCell[] as = counterCells; CounterCell a;
2534 >        CounterCell[] cs = counterCells;
2535          long sum = baseCount;
2536 <        if (as != null) {
2537 <            for (int i = 0; i < as.length; ++i) {
2538 <                if ((a = as[i]) != null)
2539 <                    sum += a.value;
2538 <            }
2536 >        if (cs != null) {
2537 >            for (CounterCell c : cs)
2538 >                if (c != null)
2539 >                    sum += c.value;
2540          }
2541          return sum;
2542      }
# Line 2550 | Line 2551 | public class ConcurrentHashMap<K,V> exte
2551          }
2552          boolean collide = false;                // True if last slot nonempty
2553          for (;;) {
2554 <            CounterCell[] as; CounterCell a; int n; long v;
2555 <            if ((as = counterCells) != null && (n = as.length) > 0) {
2556 <                if ((a = as[(n - 1) & h]) == null) {
2554 >            CounterCell[] cs; CounterCell c; int n; long v;
2555 >            if ((cs = counterCells) != null && (n = cs.length) > 0) {
2556 >                if ((c = cs[(n - 1) & h]) == null) {
2557                      if (cellsBusy == 0) {            // Try to attach new Cell
2558                          CounterCell r = new CounterCell(x); // Optimistic create
2559                          if (cellsBusy == 0 &&
2560 <                            U.compareAndSwapInt(this, CELLSBUSY, 0, 1)) {
2560 >                            U.compareAndSetInt(this, CELLSBUSY, 0, 1)) {
2561                              boolean created = false;
2562                              try {               // Recheck under lock
2563                                  CounterCell[] rs; int m, j;
# Line 2578 | Line 2579 | public class ConcurrentHashMap<K,V> exte
2579                  }
2580                  else if (!wasUncontended)       // CAS already known to fail
2581                      wasUncontended = true;      // Continue after rehash
2582 <                else if (U.compareAndSwapLong(a, CELLVALUE, v = a.value, v + x))
2582 >                else if (U.compareAndSetLong(c, CELLVALUE, v = c.value, v + x))
2583                      break;
2584 <                else if (counterCells != as || n >= NCPU)
2584 >                else if (counterCells != cs || n >= NCPU)
2585                      collide = false;            // At max size or stale
2586                  else if (!collide)
2587                      collide = true;
2588                  else if (cellsBusy == 0 &&
2589 <                         U.compareAndSwapInt(this, CELLSBUSY, 0, 1)) {
2589 >                         U.compareAndSetInt(this, CELLSBUSY, 0, 1)) {
2590                      try {
2591 <                        if (counterCells == as) {// Expand table unless stale
2592 <                            CounterCell[] rs = new CounterCell[n << 1];
2592 <                            for (int i = 0; i < n; ++i)
2593 <                                rs[i] = as[i];
2594 <                            counterCells = rs;
2595 <                        }
2591 >                        if (counterCells == cs) // Expand table unless stale
2592 >                            counterCells = Arrays.copyOf(cs, n << 1);
2593                      } finally {
2594                          cellsBusy = 0;
2595                      }
# Line 2601 | Line 2598 | public class ConcurrentHashMap<K,V> exte
2598                  }
2599                  h = ThreadLocalRandom.advanceProbe(h);
2600              }
2601 <            else if (cellsBusy == 0 && counterCells == as &&
2602 <                     U.compareAndSwapInt(this, CELLSBUSY, 0, 1)) {
2601 >            else if (cellsBusy == 0 && counterCells == cs &&
2602 >                     U.compareAndSetInt(this, CELLSBUSY, 0, 1)) {
2603                  boolean init = false;
2604                  try {                           // Initialize table
2605 <                    if (counterCells == as) {
2605 >                    if (counterCells == cs) {
2606                          CounterCell[] rs = new CounterCell[2];
2607                          rs[h & 1] = new CounterCell(x);
2608                          counterCells = rs;
# Line 2617 | Line 2614 | public class ConcurrentHashMap<K,V> exte
2614                  if (init)
2615                      break;
2616              }
2617 <            else if (U.compareAndSwapLong(this, BASECOUNT, v = baseCount, v + x))
2617 >            else if (U.compareAndSetLong(this, BASECOUNT, v = baseCount, v + x))
2618                  break;                          // Fall back on using base
2619          }
2620      }
# Line 2655 | Line 2652 | public class ConcurrentHashMap<K,V> exte
2652      }
2653  
2654      /**
2655 <     * Returns a list on non-TreeNodes replacing those in given list.
2655 >     * Returns a list of non-TreeNodes replacing those in given list.
2656       */
2657      static <K,V> Node<K,V> untreeify(Node<K,V> b) {
2658          Node<K,V> hd = null, tl = null;
2659          for (Node<K,V> q = b; q != null; q = q.next) {
2660 <            Node<K,V> p = new Node<K,V>(q.hash, q.key, q.val, null);
2660 >            Node<K,V> p = new Node<K,V>(q.hash, q.key, q.val);
2661              if (tl == null)
2662                  hd = p;
2663              else
# Line 2673 | Line 2670 | public class ConcurrentHashMap<K,V> exte
2670      /* ---------------- TreeNodes -------------- */
2671  
2672      /**
2673 <     * Nodes for use in TreeBins
2673 >     * Nodes for use in TreeBins.
2674       */
2675      static final class TreeNode<K,V> extends Node<K,V> {
2676          TreeNode<K,V> parent;  // red-black tree links
# Line 2766 | Line 2763 | public class ConcurrentHashMap<K,V> exte
2763           * Creates bin with initial set of nodes headed by b.
2764           */
2765          TreeBin(TreeNode<K,V> b) {
2766 <            super(TREEBIN, null, null, null);
2766 >            super(TREEBIN, null, null);
2767              this.first = b;
2768              TreeNode<K,V> r = null;
2769              for (TreeNode<K,V> x = b, next; x != null; x = next) {
# Line 2813 | Line 2810 | public class ConcurrentHashMap<K,V> exte
2810           * Acquires write lock for tree restructuring.
2811           */
2812          private final void lockRoot() {
2813 <            if (!U.compareAndSwapInt(this, LOCKSTATE, 0, WRITER))
2813 >            if (!U.compareAndSetInt(this, LOCKSTATE, 0, WRITER))
2814                  contendedLock(); // offload to separate method
2815          }
2816  
# Line 2831 | Line 2828 | public class ConcurrentHashMap<K,V> exte
2828              boolean waiting = false;
2829              for (int s;;) {
2830                  if (((s = lockState) & ~WAITER) == 0) {
2831 <                    if (U.compareAndSwapInt(this, LOCKSTATE, s, WRITER)) {
2831 >                    if (U.compareAndSetInt(this, LOCKSTATE, s, WRITER)) {
2832                          if (waiting)
2833                              waiter = null;
2834                          return;
2835                      }
2836                  }
2837                  else if ((s & WAITER) == 0) {
2838 <                    if (U.compareAndSwapInt(this, LOCKSTATE, s, s | WAITER)) {
2838 >                    if (U.compareAndSetInt(this, LOCKSTATE, s, s | WAITER)) {
2839                          waiting = true;
2840                          waiter = Thread.currentThread();
2841                      }
# Line 2863 | Line 2860 | public class ConcurrentHashMap<K,V> exte
2860                              return e;
2861                          e = e.next;
2862                      }
2863 <                    else if (U.compareAndSwapInt(this, LOCKSTATE, s,
2863 >                    else if (U.compareAndSetInt(this, LOCKSTATE, s,
2864                                                   s + READER)) {
2865                          TreeNode<K,V> r, p;
2866                          try {
# Line 3236 | Line 3233 | public class ConcurrentHashMap<K,V> exte
3233          }
3234  
3235          /**
3236 <         * Recursive invariant check
3236 >         * Checks invariants recursively for the tree of Nodes rooted at t.
3237           */
3238          static <K,V> boolean checkInvariants(TreeNode<K,V> t) {
3239              TreeNode<K,V> tp = t.parent, tl = t.left, tr = t.right,
# Line 3260 | Line 3257 | public class ConcurrentHashMap<K,V> exte
3257              return true;
3258          }
3259  
3260 <        private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
3261 <        private static final long LOCKSTATE;
3262 <        static {
3266 <            try {
3267 <                LOCKSTATE = U.objectFieldOffset
3268 <                    (TreeBin.class.getDeclaredField("lockState"));
3269 <            } catch (ReflectiveOperationException e) {
3270 <                throw new Error(e);
3271 <            }
3272 <        }
3260 >        private static final Unsafe U = Unsafe.getUnsafe();
3261 >        private static final long LOCKSTATE
3262 >                = U.objectFieldOffset(TreeBin.class, "lockState");
3263      }
3264  
3265      /* ----------------Table Traversal -------------- */
# Line 3423 | Line 3413 | public class ConcurrentHashMap<K,V> exte
3413  
3414      static final class KeyIterator<K,V> extends BaseIterator<K,V>
3415          implements Iterator<K>, Enumeration<K> {
3416 <        KeyIterator(Node<K,V>[] tab, int index, int size, int limit,
3416 >        KeyIterator(Node<K,V>[] tab, int size, int index, int limit,
3417                      ConcurrentHashMap<K,V> map) {
3418 <            super(tab, index, size, limit, map);
3418 >            super(tab, size, index, limit, map);
3419          }
3420  
3421          public final K next() {
# Line 3443 | Line 3433 | public class ConcurrentHashMap<K,V> exte
3433  
3434      static final class ValueIterator<K,V> extends BaseIterator<K,V>
3435          implements Iterator<V>, Enumeration<V> {
3436 <        ValueIterator(Node<K,V>[] tab, int index, int size, int limit,
3436 >        ValueIterator(Node<K,V>[] tab, int size, int index, int limit,
3437                        ConcurrentHashMap<K,V> map) {
3438 <            super(tab, index, size, limit, map);
3438 >            super(tab, size, index, limit, map);
3439          }
3440  
3441          public final V next() {
# Line 3463 | Line 3453 | public class ConcurrentHashMap<K,V> exte
3453  
3454      static final class EntryIterator<K,V> extends BaseIterator<K,V>
3455          implements Iterator<Map.Entry<K,V>> {
3456 <        EntryIterator(Node<K,V>[] tab, int index, int size, int limit,
3456 >        EntryIterator(Node<K,V>[] tab, int size, int index, int limit,
3457                        ConcurrentHashMap<K,V> map) {
3458 <            super(tab, index, size, limit, map);
3458 >            super(tab, size, index, limit, map);
3459          }
3460  
3461          public final Map.Entry<K,V> next() {
# Line 3481 | Line 3471 | public class ConcurrentHashMap<K,V> exte
3471      }
3472  
3473      /**
3474 <     * Exported Entry for EntryIterator
3474 >     * Exported Entry for EntryIterator.
3475       */
3476      static final class MapEntry<K,V> implements Map.Entry<K,V> {
3477          final K key; // non-null
# Line 3534 | Line 3524 | public class ConcurrentHashMap<K,V> exte
3524              this.est = est;
3525          }
3526  
3527 <        public Spliterator<K> trySplit() {
3527 >        public KeySpliterator<K,V> trySplit() {
3528              int i, f, h;
3529              return (h = ((i = baseIndex) + (f = baseLimit)) >>> 1) <= i ? null :
3530                  new KeySpliterator<K,V>(tab, baseSize, baseLimit = h,
# Line 3573 | Line 3563 | public class ConcurrentHashMap<K,V> exte
3563              this.est = est;
3564          }
3565  
3566 <        public Spliterator<V> trySplit() {
3566 >        public ValueSpliterator<K,V> trySplit() {
3567              int i, f, h;
3568              return (h = ((i = baseIndex) + (f = baseLimit)) >>> 1) <= i ? null :
3569                  new ValueSpliterator<K,V>(tab, baseSize, baseLimit = h,
# Line 3613 | Line 3603 | public class ConcurrentHashMap<K,V> exte
3603              this.est = est;
3604          }
3605  
3606 <        public Spliterator<Map.Entry<K,V>> trySplit() {
3606 >        public EntrySpliterator<K,V> trySplit() {
3607              int i, f, h;
3608              return (h = ((i = baseIndex) + (f = baseLimit)) >>> 1) <= i ? null :
3609                  new EntrySpliterator<K,V>(tab, baseSize, baseLimit = h,
# Line 4425 | Line 4415 | public class ConcurrentHashMap<K,V> exte
4415          public abstract boolean contains(Object o);
4416          public abstract boolean remove(Object o);
4417  
4418 <        private static final String oomeMsg = "Required array size too large";
4418 >        private static final String OOME_MSG = "Required array size too large";
4419  
4420          public final Object[] toArray() {
4421              long sz = map.mappingCount();
4422              if (sz > MAX_ARRAY_SIZE)
4423 <                throw new OutOfMemoryError(oomeMsg);
4423 >                throw new OutOfMemoryError(OOME_MSG);
4424              int n = (int)sz;
4425              Object[] r = new Object[n];
4426              int i = 0;
4427              for (E e : this) {
4428                  if (i == n) {
4429                      if (n >= MAX_ARRAY_SIZE)
4430 <                        throw new OutOfMemoryError(oomeMsg);
4430 >                        throw new OutOfMemoryError(OOME_MSG);
4431                      if (n >= MAX_ARRAY_SIZE - (MAX_ARRAY_SIZE >>> 1) - 1)
4432                          n = MAX_ARRAY_SIZE;
4433                      else
# Line 4453 | Line 4443 | public class ConcurrentHashMap<K,V> exte
4443          public final <T> T[] toArray(T[] a) {
4444              long sz = map.mappingCount();
4445              if (sz > MAX_ARRAY_SIZE)
4446 <                throw new OutOfMemoryError(oomeMsg);
4446 >                throw new OutOfMemoryError(OOME_MSG);
4447              int m = (int)sz;
4448              T[] r = (a.length >= m) ? a :
4449                  (T[])java.lang.reflect.Array
# Line 4463 | Line 4453 | public class ConcurrentHashMap<K,V> exte
4453              for (E e : this) {
4454                  if (i == n) {
4455                      if (n >= MAX_ARRAY_SIZE)
4456 <                        throw new OutOfMemoryError(oomeMsg);
4456 >                        throw new OutOfMemoryError(OOME_MSG);
4457                      if (n >= MAX_ARRAY_SIZE - (MAX_ARRAY_SIZE >>> 1) - 1)
4458                          n = MAX_ARRAY_SIZE;
4459                      else
# Line 4516 | Line 4506 | public class ConcurrentHashMap<K,V> exte
4506              return true;
4507          }
4508  
4509 <        public final boolean removeAll(Collection<?> c) {
4509 >        public boolean removeAll(Collection<?> c) {
4510              if (c == null) throw new NullPointerException();
4511              boolean modified = false;
4512 <            for (Iterator<E> it = iterator(); it.hasNext();) {
4513 <                if (c.contains(it.next())) {
4514 <                    it.remove();
4515 <                    modified = true;
4512 >            // Use (c instanceof Set) as a hint that lookup in c is as
4513 >            // efficient as this view
4514 >            Node<K,V>[] t;
4515 >            if ((t = map.table) == null) {
4516 >                return false;
4517 >            } else if (c instanceof Set<?> && c.size() > t.length) {
4518 >                for (Iterator<?> it = iterator(); it.hasNext(); ) {
4519 >                    if (c.contains(it.next())) {
4520 >                        it.remove();
4521 >                        modified = true;
4522 >                    }
4523                  }
4524 +            } else {
4525 +                for (Object e : c)
4526 +                    modified |= remove(e);
4527              }
4528              return modified;
4529          }
# Line 4710 | Line 4710 | public class ConcurrentHashMap<K,V> exte
4710              throw new UnsupportedOperationException();
4711          }
4712  
4713 +        @Override public boolean removeAll(Collection<?> c) {
4714 +            if (c == null) throw new NullPointerException();
4715 +            boolean modified = false;
4716 +            for (Iterator<V> it = iterator(); it.hasNext();) {
4717 +                if (c.contains(it.next())) {
4718 +                    it.remove();
4719 +                    modified = true;
4720 +                }
4721 +            }
4722 +            return modified;
4723 +        }
4724 +
4725          public boolean removeIf(Predicate<? super V> filter) {
4726              return map.removeValueIf(filter);
4727          }
# Line 4858 | Line 4870 | public class ConcurrentHashMap<K,V> exte
4870          }
4871  
4872          /**
4873 <         * Same as Traverser version
4873 >         * Same as Traverser version.
4874           */
4875          final Node<K,V> advance() {
4876              Node<K,V> e;
# Line 6303 | Line 6315 | public class ConcurrentHashMap<K,V> exte
6315      }
6316  
6317      // Unsafe mechanics
6318 <    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
6318 >    private static final Unsafe U = Unsafe.getUnsafe();
6319      private static final long SIZECTL;
6320      private static final long TRANSFERINDEX;
6321      private static final long BASECOUNT;
# Line 6313 | Line 6325 | public class ConcurrentHashMap<K,V> exte
6325      private static final int ASHIFT;
6326  
6327      static {
6328 <        try {
6329 <            SIZECTL = U.objectFieldOffset
6330 <                (ConcurrentHashMap.class.getDeclaredField("sizeCtl"));
6331 <            TRANSFERINDEX = U.objectFieldOffset
6332 <                (ConcurrentHashMap.class.getDeclaredField("transferIndex"));
6333 <            BASECOUNT = U.objectFieldOffset
6334 <                (ConcurrentHashMap.class.getDeclaredField("baseCount"));
6335 <            CELLSBUSY = U.objectFieldOffset
6336 <                (ConcurrentHashMap.class.getDeclaredField("cellsBusy"));
6337 <
6338 <            CELLVALUE = U.objectFieldOffset
6339 <                (CounterCell.class.getDeclaredField("value"));
6340 <
6341 <            ABASE = U.arrayBaseOffset(Node[].class);
6342 <            int scale = U.arrayIndexScale(Node[].class);
6343 <            if ((scale & (scale - 1)) != 0)
6344 <                throw new Error("array index scale not a power of two");
6333 <            ASHIFT = 31 - Integer.numberOfLeadingZeros(scale);
6334 <        } catch (ReflectiveOperationException e) {
6335 <            throw new Error(e);
6336 <        }
6328 >        SIZECTL = U.objectFieldOffset
6329 >            (ConcurrentHashMap.class, "sizeCtl");
6330 >        TRANSFERINDEX = U.objectFieldOffset
6331 >            (ConcurrentHashMap.class, "transferIndex");
6332 >        BASECOUNT = U.objectFieldOffset
6333 >            (ConcurrentHashMap.class, "baseCount");
6334 >        CELLSBUSY = U.objectFieldOffset
6335 >            (ConcurrentHashMap.class, "cellsBusy");
6336 >
6337 >        CELLVALUE = U.objectFieldOffset
6338 >            (CounterCell.class, "value");
6339 >
6340 >        ABASE = U.arrayBaseOffset(Node[].class);
6341 >        int scale = U.arrayIndexScale(Node[].class);
6342 >        if ((scale & (scale - 1)) != 0)
6343 >            throw new ExceptionInInitializerError("array index scale not a power of two");
6344 >        ASHIFT = 31 - Integer.numberOfLeadingZeros(scale);
6345  
6346          // Reduce the risk of rare disastrous classloading in first call to
6347          // LockSupport.park: https://bugs.openjdk.java.net/browse/JDK-8074773
6348          Class<?> ensureLoaded = LockSupport.class;
6349 +
6350 +        // Eager class load observed to help JIT during startup
6351 +        ensureLoaded = ReservationNode.class;
6352      }
6353   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines