Merge metal-prototype-branch
authorjdv
Mon, 22 Jul 2019 11:07:24 +0530
branchmetal-prototype-branch
changeset 57477 05637b1896c6
parent 57476 64365a5764cd (current diff)
parent 55752 8ae33203d600 (diff)
child 57504 f72a3278a493
Merge
src/java.base/share/classes/jdk/internal/access/JavaNetSocketAccess.java
src/java.base/share/classes/jdk/internal/access/JavaNetURLClassLoaderAccess.java
test/jdk/sun/misc/ClassLoaderUtil/test.jar
--- a/make/autoconf/flags.m4	Fri Jul 19 15:11:33 2019 +0530
+++ b/make/autoconf/flags.m4	Mon Jul 22 11:07:24 2019 +0530
@@ -176,6 +176,10 @@
     AC_MSG_WARN([Ignoring LDFLAGS($LDFLAGS) found in environment. Use --with-extra-ldflags])
   fi
 
+  if test "x$ASFLAGS" != "x"; then
+    AC_MSG_WARN([Ignoring ASFLAGS($ASFLAGS) found in environment. Use --with-extra-asflags])
+  fi
+
   AC_ARG_WITH(extra-cflags, [AS_HELP_STRING([--with-extra-cflags],
       [extra flags to be used when compiling jdk c-files])])
 
@@ -185,9 +189,13 @@
   AC_ARG_WITH(extra-ldflags, [AS_HELP_STRING([--with-extra-ldflags],
       [extra flags to be used when linking jdk])])
 
+  AC_ARG_WITH(extra-asflags, [AS_HELP_STRING([--with-extra-asflags],
+      [extra flags to be passed to the assembler])])
+
   USER_CFLAGS="$with_extra_cflags"
   USER_CXXFLAGS="$with_extra_cxxflags"
   USER_LDFLAGS="$with_extra_ldflags"
+  USER_ASFLAGS="$with_extra_asflags"
 ])
 
 # Setup the sysroot flags and add them to global CFLAGS and LDFLAGS so
@@ -280,10 +288,12 @@
   EXTRA_CFLAGS="$MACHINE_FLAG $USER_CFLAGS"
   EXTRA_CXXFLAGS="$MACHINE_FLAG $USER_CXXFLAGS"
   EXTRA_LDFLAGS="$MACHINE_FLAG $USER_LDFLAGS"
+  EXTRA_ASFLAGS="$USER_ASFLAGS"
 
   AC_SUBST(EXTRA_CFLAGS)
   AC_SUBST(EXTRA_CXXFLAGS)
   AC_SUBST(EXTRA_LDFLAGS)
+  AC_SUBST(EXTRA_ASFLAGS)
 
   # For autoconf testing to work, the global flags must also be stored in the
   # "unnamed" CFLAGS etc.
--- a/make/autoconf/spec.gmk.in	Fri Jul 19 15:11:33 2019 +0530
+++ b/make/autoconf/spec.gmk.in	Mon Jul 22 11:07:24 2019 +0530
@@ -489,6 +489,7 @@
 EXTRA_CFLAGS = @EXTRA_CFLAGS@
 EXTRA_CXXFLAGS = @EXTRA_CXXFLAGS@
 EXTRA_LDFLAGS = @EXTRA_LDFLAGS@
+EXTRA_ASFLAGS = @EXTRA_ASFLAGS@
 
 CXX:=@FIXPATH@ @CCACHE@ @ICECC@ @CXX@
 
--- a/make/hotspot/lib/CompileJvm.gmk	Fri Jul 19 15:11:33 2019 +0530
+++ b/make/hotspot/lib/CompileJvm.gmk	Mon Jul 22 11:07:24 2019 +0530
@@ -47,6 +47,8 @@
     $(EXTRA_LDFLAGS) \
     #
 
+JVM_ASFLAGS += $(EXTRA_ASFLAGS)
+
 JVM_LIBS += \
     $(JVM_LIBS_FEATURES) \
     #
--- a/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp	Fri Jul 19 15:11:33 2019 +0530
+++ b/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp	Mon Jul 22 11:07:24 2019 +0530
@@ -800,6 +800,7 @@
 #endif
 
   // Class initialization barrier for static methods
+  address c2i_no_clinit_check_entry = NULL;
   if (VM_Version::supports_fast_class_init_checks()) {
     Label L_skip_barrier;
 
@@ -812,13 +813,15 @@
     __ load_method_holder(rscratch2, rmethod);
     __ clinit_barrier(rscratch2, rscratch1, &L_skip_barrier);
     __ far_jump(RuntimeAddress(SharedRuntime::get_handle_wrong_method_stub()));
+
     __ bind(L_skip_barrier);
+    c2i_no_clinit_check_entry = __ pc();
   }
 
   gen_c2i_adapter(masm, total_args_passed, comp_args_on_stack, sig_bt, regs, skip_fixup);
 
   __ flush();
-  return AdapterHandlerLibrary::new_entry(fingerprint, i2c_entry, c2i_entry, c2i_unverified_entry);
+  return AdapterHandlerLibrary::new_entry(fingerprint, i2c_entry, c2i_entry, c2i_unverified_entry, c2i_no_clinit_check_entry);
 }
 
 int SharedRuntime::c_calling_convention(const BasicType *sig_bt,
--- a/src/hotspot/cpu/ppc/sharedRuntime_ppc.cpp	Fri Jul 19 15:11:33 2019 +0530
+++ b/src/hotspot/cpu/ppc/sharedRuntime_ppc.cpp	Mon Jul 22 11:07:24 2019 +0530
@@ -1277,6 +1277,7 @@
   c2i_entry = __ pc();
 
   // Class initialization barrier for static methods
+  address c2i_no_clinit_check_entry = NULL;
   if (VM_Version::supports_fast_class_init_checks()) {
     Label L_skip_barrier;
 
@@ -1295,11 +1296,12 @@
     __ bctr();
 
     __ bind(L_skip_barrier);
+    c2i_no_clinit_check_entry = __ pc();
   }
 
   gen_c2i_adapter(masm, total_args_passed, comp_args_on_stack, sig_bt, regs, call_interpreter, ientry);
 
-  return AdapterHandlerLibrary::new_entry(fingerprint, i2c_entry, c2i_entry, c2i_unverified_entry);
+  return AdapterHandlerLibrary::new_entry(fingerprint, i2c_entry, c2i_entry, c2i_unverified_entry, c2i_no_clinit_check_entry);
 }
 
 #ifdef COMPILER2
--- a/src/hotspot/cpu/s390/sharedRuntime_s390.cpp	Fri Jul 19 15:11:33 2019 +0530
+++ b/src/hotspot/cpu/s390/sharedRuntime_s390.cpp	Mon Jul 22 11:07:24 2019 +0530
@@ -2713,6 +2713,7 @@
   address c2i_entry = __ pc();
 
   // Class initialization barrier for static methods
+  address c2i_no_clinit_check_entry = NULL;
   if (VM_Version::supports_fast_class_init_checks()) {
     Label L_skip_barrier;
 
@@ -2729,11 +2730,12 @@
     __ z_br(klass);
 
     __ bind(L_skip_barrier);
+    c2i_no_clinit_check_entry = __ pc();
   }
 
   gen_c2i_adapter(masm, total_args_passed, comp_args_on_stack, sig_bt, regs, skip_fixup);
 
-  return AdapterHandlerLibrary::new_entry(fingerprint, i2c_entry, c2i_entry, c2i_unverified_entry);
+  return AdapterHandlerLibrary::new_entry(fingerprint, i2c_entry, c2i_entry, c2i_unverified_entry, c2i_no_clinit_check_entry);
 }
 
 // This function returns the adjust size (in number of words) to a c2i adapter
--- a/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp	Fri Jul 19 15:11:33 2019 +0530
+++ b/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp	Mon Jul 22 11:07:24 2019 +0530
@@ -971,10 +971,8 @@
 
   address c2i_entry = __ pc();
 
-  BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler();
-  bs->c2i_entry_barrier(masm);
-
   // Class initialization barrier for static methods
+  address c2i_no_clinit_check_entry = NULL;
   if (VM_Version::supports_fast_class_init_checks()) {
     Label L_skip_barrier;
     Register method = rbx;
@@ -993,12 +991,16 @@
     __ jump(RuntimeAddress(SharedRuntime::get_handle_wrong_method_stub())); // slow path
 
     __ bind(L_skip_barrier);
+    c2i_no_clinit_check_entry = __ pc();
   }
 
+  BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler();
+  bs->c2i_entry_barrier(masm);
+
   gen_c2i_adapter(masm, total_args_passed, comp_args_on_stack, sig_bt, regs, skip_fixup);
 
   __ flush();
-  return AdapterHandlerLibrary::new_entry(fingerprint, i2c_entry, c2i_entry, c2i_unverified_entry);
+  return AdapterHandlerLibrary::new_entry(fingerprint, i2c_entry, c2i_entry, c2i_unverified_entry, c2i_no_clinit_check_entry);
 }
 
 int SharedRuntime::c_calling_convention(const BasicType *sig_bt,
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/g1/g1CardTableEntryClosure.hpp	Mon Jul 22 11:07:24 2019 +0530
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef SHARE_GC_G1_G1CARDTABLEENTRYCLOSURE_HPP
+#define SHARE_GC_G1_G1CARDTABLEENTRYCLOSURE_HPP
+
+#include "gc/shared/cardTable.hpp"
+#include "memory/allocation.hpp"
+
+// A closure class for processing card table entries.  Note that we don't
+// require these closure objects to be stack-allocated.
+class G1CardTableEntryClosure: public CHeapObj<mtGC> {
+public:
+  typedef CardTable::CardValue CardValue;
+
+  // Process the card whose card table entry is "card_ptr".  If returns
+  // "false", terminate the iteration early.
+  virtual bool do_card_ptr(CardValue* card_ptr, uint worker_id) = 0;
+};
+
+#endif // SHARE_GC_G1_G1CARDTABLEENTRYCLOSURE_HPP
--- a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp	Fri Jul 19 15:11:33 2019 +0530
+++ b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp	Mon Jul 22 11:07:24 2019 +0530
@@ -31,6 +31,7 @@
 #include "gc/g1/g1Allocator.inline.hpp"
 #include "gc/g1/g1Arguments.hpp"
 #include "gc/g1/g1BarrierSet.hpp"
+#include "gc/g1/g1CardTableEntryClosure.hpp"
 #include "gc/g1/g1CollectedHeap.inline.hpp"
 #include "gc/g1/g1CollectionSet.hpp"
 #include "gc/g1/g1CollectorState.hpp"
@@ -49,6 +50,7 @@
 #include "gc/g1/g1OopClosures.inline.hpp"
 #include "gc/g1/g1ParScanThreadState.inline.hpp"
 #include "gc/g1/g1Policy.hpp"
+#include "gc/g1/g1RedirtyCardsQueue.hpp"
 #include "gc/g1/g1RegionToSpaceMapper.hpp"
 #include "gc/g1/g1RemSet.hpp"
 #include "gc/g1/g1RootClosures.hpp"
@@ -1078,7 +1080,9 @@
 
   // Discard all remembered set updates.
   G1BarrierSet::dirty_card_queue_set().abandon_logs();
-  assert(dirty_card_queue_set().completed_buffers_num() == 0, "DCQS should be empty");
+  assert(G1BarrierSet::dirty_card_queue_set().completed_buffers_num() == 0,
+         "DCQS should be empty");
+  redirty_cards_queue_set().verify_empty();
 }
 
 void G1CollectedHeap::verify_after_full_collection() {
@@ -1517,7 +1521,7 @@
   _collection_set(this, _policy),
   _hot_card_cache(NULL),
   _rem_set(NULL),
-  _dirty_card_queue_set(false),
+  _redirty_cards_queue_set(),
   _cm(NULL),
   _cm_thread(NULL),
   _cr(NULL),
@@ -1687,8 +1691,8 @@
                                                   &bs->dirty_card_queue_buffer_allocator(),
                                                   true); // init_free_ids
 
-  dirty_card_queue_set().initialize(DirtyCardQ_CBL_mon,
-                                    &bs->dirty_card_queue_buffer_allocator());
+  // Use same buffer allocator as dirty card qset, to allow merging.
+  _redirty_cards_queue_set.initialize(&bs->dirty_card_queue_buffer_allocator());
 
   // Create the hot card cache.
   _hot_card_cache = new G1HotCardCache(this);
@@ -3213,18 +3217,43 @@
 
 class G1RedirtyLoggedCardsTask : public AbstractGangTask {
  private:
-  G1DirtyCardQueueSet* _queue;
+  G1RedirtyCardsQueueSet* _qset;
   G1CollectedHeap* _g1h;
+  BufferNode* volatile _nodes;
+
+  void apply(G1CardTableEntryClosure* cl, BufferNode* node, uint worker_id) {
+    void** buf = BufferNode::make_buffer_from_node(node);
+    size_t limit = _qset->buffer_size();
+    for (size_t i = node->index(); i < limit; ++i) {
+      CardTable::CardValue* card_ptr = static_cast<CardTable::CardValue*>(buf[i]);
+      bool result = cl->do_card_ptr(card_ptr, worker_id);
+      assert(result, "Closure should always return true");
+    }
+  }
+
+  void par_apply(G1CardTableEntryClosure* cl, uint worker_id) {
+    BufferNode* next = Atomic::load(&_nodes);
+    while (next != NULL) {
+      BufferNode* node = next;
+      next = Atomic::cmpxchg(node->next(), &_nodes, node);
+      if (next == node) {
+        apply(cl, node, worker_id);
+        next = node->next();
+      }
+    }
+  }
+
  public:
-  G1RedirtyLoggedCardsTask(G1DirtyCardQueueSet* queue, G1CollectedHeap* g1h) : AbstractGangTask("Redirty Cards"),
-    _queue(queue), _g1h(g1h) { }
+  G1RedirtyLoggedCardsTask(G1RedirtyCardsQueueSet* qset, G1CollectedHeap* g1h) :
+    AbstractGangTask("Redirty Cards"),
+    _qset(qset), _g1h(g1h), _nodes(qset->all_completed_buffers()) { }
 
   virtual void work(uint worker_id) {
     G1GCPhaseTimes* p = _g1h->phase_times();
     G1GCParPhaseTimesTracker x(p, G1GCPhaseTimes::RedirtyCards, worker_id);
 
     RedirtyLoggedCardTableEntryClosure cl(_g1h);
-    _queue->par_apply_closure_to_all_completed_buffers(&cl);
+    par_apply(&cl, worker_id);
 
     p->record_thread_work_item(G1GCPhaseTimes::RedirtyCards, worker_id, cl.num_dirtied());
   }
@@ -3233,13 +3262,12 @@
 void G1CollectedHeap::redirty_logged_cards() {
   double redirty_logged_cards_start = os::elapsedTime();
 
-  G1RedirtyLoggedCardsTask redirty_task(&dirty_card_queue_set(), this);
-  dirty_card_queue_set().reset_for_par_iteration();
+  G1RedirtyLoggedCardsTask redirty_task(&redirty_cards_queue_set(), this);
   workers()->run_task(&redirty_task);
 
   G1DirtyCardQueueSet& dcq = G1BarrierSet::dirty_card_queue_set();
-  dcq.merge_bufferlists(&dirty_card_queue_set());
-  assert(dirty_card_queue_set().completed_buffers_num() == 0, "All should be consumed");
+  dcq.merge_bufferlists(&redirty_cards_queue_set());
+  redirty_cards_queue_set().verify_empty();
 
   phase_times()->record_redirty_logged_cards_time_ms((os::elapsedTime() - redirty_logged_cards_start) * 1000.0);
 }
@@ -3571,7 +3599,7 @@
   // Should G1EvacuationFailureALot be in effect for this GC?
   NOT_PRODUCT(set_evacuation_failure_alot_for_current_gc();)
 
-  assert(dirty_card_queue_set().completed_buffers_num() == 0, "Should be empty");
+  redirty_cards_queue_set().verify_empty();
 }
 
 class G1EvacuateRegionsBaseTask : public AbstractGangTask {
--- a/src/hotspot/share/gc/g1/g1CollectedHeap.hpp	Fri Jul 19 15:11:33 2019 +0530
+++ b/src/hotspot/share/gc/g1/g1CollectedHeap.hpp	Mon Jul 22 11:07:24 2019 +0530
@@ -31,7 +31,6 @@
 #include "gc/g1/g1CollectionSet.hpp"
 #include "gc/g1/g1CollectorState.hpp"
 #include "gc/g1/g1ConcurrentMark.hpp"
-#include "gc/g1/g1DirtyCardQueue.hpp"
 #include "gc/g1/g1EdenRegions.hpp"
 #include "gc/g1/g1EvacFailure.hpp"
 #include "gc/g1/g1EvacStats.hpp"
@@ -42,6 +41,7 @@
 #include "gc/g1/g1HRPrinter.hpp"
 #include "gc/g1/g1HeapRegionAttr.hpp"
 #include "gc/g1/g1MonitoringSupport.hpp"
+#include "gc/g1/g1RedirtyCardsQueue.hpp"
 #include "gc/g1/g1SurvivorRegions.hpp"
 #include "gc/g1/g1YCTypes.hpp"
 #include "gc/g1/heapRegionManager.hpp"
@@ -73,6 +73,7 @@
 class SpaceClosure;
 class CompactibleSpaceClosure;
 class Space;
+class G1CardTableEntryClosure;
 class G1CollectionSet;
 class G1Policy;
 class G1HotCardCache;
@@ -775,7 +776,7 @@
 
   // A set of cards that cover the objects for which the Rsets should be updated
   // concurrently after the collection.
-  G1DirtyCardQueueSet _dirty_card_queue_set;
+  G1RedirtyCardsQueueSet _redirty_cards_queue_set;
 
   // After a collection pause, convert the regions in the collection set into free
   // regions.
@@ -935,7 +936,9 @@
   uint num_task_queues() const;
 
   // A set of cards where updates happened during the GC
-  G1DirtyCardQueueSet& dirty_card_queue_set() { return _dirty_card_queue_set; }
+  G1RedirtyCardsQueueSet& redirty_cards_queue_set() {
+    return _redirty_cards_queue_set;
+  }
 
   // Create a G1CollectedHeap.
   // Must call the initialize method afterwards.
--- a/src/hotspot/share/gc/g1/g1DirtyCardQueue.cpp	Fri Jul 19 15:11:33 2019 +0530
+++ b/src/hotspot/share/gc/g1/g1DirtyCardQueue.cpp	Mon Jul 22 11:07:24 2019 +0530
@@ -23,9 +23,11 @@
  */
 
 #include "precompiled.hpp"
+#include "gc/g1/g1CardTableEntryClosure.hpp"
 #include "gc/g1/g1CollectedHeap.inline.hpp"
 #include "gc/g1/g1DirtyCardQueue.hpp"
 #include "gc/g1/g1FreeIdSet.hpp"
+#include "gc/g1/g1RedirtyCardsQueue.hpp"
 #include "gc/g1/g1RemSet.hpp"
 #include "gc/g1/g1ThreadLocalData.hpp"
 #include "gc/g1/heapRegionRemSet.hpp"
@@ -90,8 +92,7 @@
   _completed_buffers_padding(0),
   _free_ids(NULL),
   _processed_buffers_mut(0),
-  _processed_buffers_rs_thread(0),
-  _cur_par_buffer_node(NULL)
+  _processed_buffers_rs_thread(0)
 {
   _all_active = true;
 }
@@ -211,26 +212,22 @@
 // Merge lists of buffers. Notify the processing threads.
 // The source queue is emptied as a result. The queues
 // must share the monitor.
-void G1DirtyCardQueueSet::merge_bufferlists(G1DirtyCardQueueSet *src) {
-  assert(_cbl_mon == src->_cbl_mon, "Should share the same lock");
+void G1DirtyCardQueueSet::merge_bufferlists(G1RedirtyCardsQueueSet* src) {
+  assert(allocator() == src->allocator(), "precondition");
+  const G1RedirtyCardsBufferList from = src->take_all_completed_buffers();
+  if (from._head == NULL) return;
+
   MutexLocker x(_cbl_mon, Mutex::_no_safepoint_check_flag);
   if (_completed_buffers_tail == NULL) {
     assert(_completed_buffers_head == NULL, "Well-formedness");
-    _completed_buffers_head = src->_completed_buffers_head;
-    _completed_buffers_tail = src->_completed_buffers_tail;
+    _completed_buffers_head = from._head;
+    _completed_buffers_tail = from._tail;
   } else {
     assert(_completed_buffers_head != NULL, "Well formedness");
-    if (src->_completed_buffers_head != NULL) {
-      _completed_buffers_tail->set_next(src->_completed_buffers_head);
-      _completed_buffers_tail = src->_completed_buffers_tail;
-    }
+    _completed_buffers_tail->set_next(from._head);
+    _completed_buffers_tail = from._tail;
   }
-  _n_completed_buffers += src->_n_completed_buffers;
-
-  src->_n_completed_buffers = 0;
-  src->_completed_buffers_head = NULL;
-  src->_completed_buffers_tail = NULL;
-  src->set_process_completed_buffers(false);
+  _n_completed_buffers += from._count;
 
   assert(_completed_buffers_head == NULL && _completed_buffers_tail == NULL ||
          _completed_buffers_head != NULL && _completed_buffers_tail != NULL,
@@ -240,7 +237,6 @@
 
 bool G1DirtyCardQueueSet::apply_closure_to_buffer(G1CardTableEntryClosure* cl,
                                                   BufferNode* node,
-                                                  bool consume,
                                                   uint worker_i) {
   if (cl == NULL) return true;
   bool result = true;
@@ -255,10 +251,8 @@
       break;
     }
   }
-  if (consume) {
-    assert(i <= buffer_size(), "invariant");
-    node->set_index(i);
-  }
+  assert(i <= buffer_size(), "invariant");
+  node->set_index(i);
   return result;
 }
 
@@ -299,7 +293,7 @@
 
   uint worker_i = _free_ids->claim_par_id(); // temporarily claim an id
   G1RefineCardConcurrentlyClosure cl;
-  bool result = apply_closure_to_buffer(&cl, node, true, worker_i);
+  bool result = apply_closure_to_buffer(&cl, node, worker_i);
   _free_ids->release_par_id(worker_i); // release the id
 
   if (result) {
@@ -328,7 +322,7 @@
   if (nd == NULL) {
     return false;
   } else {
-    if (apply_closure_to_buffer(cl, nd, true, worker_i)) {
+    if (apply_closure_to_buffer(cl, nd, worker_i)) {
       assert_fully_consumed(nd, buffer_size());
       // Done with fully processed buffer.
       deallocate_buffer(nd);
@@ -342,21 +336,6 @@
   }
 }
 
-void G1DirtyCardQueueSet::par_apply_closure_to_all_completed_buffers(G1CardTableEntryClosure* cl) {
-  BufferNode* nd = _cur_par_buffer_node;
-  while (nd != NULL) {
-    BufferNode* next = nd->next();
-    BufferNode* actual = Atomic::cmpxchg(next, &_cur_par_buffer_node, nd);
-    if (actual == nd) {
-      bool b = apply_closure_to_buffer(cl, nd, false);
-      guarantee(b, "Should not stop early.");
-      nd = next;
-    } else {
-      nd = actual;
-    }
-  }
-}
-
 void G1DirtyCardQueueSet::abandon_logs() {
   assert(SafepointSynchronize::is_at_safepoint(), "Must be at safepoint.");
   abandon_completed_buffers();
--- a/src/hotspot/share/gc/g1/g1DirtyCardQueue.hpp	Fri Jul 19 15:11:33 2019 +0530
+++ b/src/hotspot/share/gc/g1/g1DirtyCardQueue.hpp	Mon Jul 22 11:07:24 2019 +0530
@@ -25,26 +25,16 @@
 #ifndef SHARE_GC_G1_G1DIRTYCARDQUEUE_HPP
 #define SHARE_GC_G1_G1DIRTYCARDQUEUE_HPP
 
-#include "gc/shared/cardTable.hpp"
 #include "gc/shared/ptrQueue.hpp"
 #include "memory/allocation.hpp"
 
+class G1CardTableEntryClosure;
 class G1DirtyCardQueueSet;
 class G1FreeIdSet;
+class G1RedirtyCardsQueueSet;
 class Thread;
 class Monitor;
 
-// A closure class for processing card table entries.  Note that we don't
-// require these closure objects to be stack-allocated.
-class G1CardTableEntryClosure: public CHeapObj<mtGC> {
-public:
-  typedef CardTable::CardValue CardValue;
-
-  // Process the card whose card table entry is "card_ptr".  If returns
-  // "false", terminate the iteration early.
-  virtual bool do_card_ptr(CardValue* card_ptr, uint worker_i) = 0;
-};
-
 // A ptrQueue whose elements are "oops", pointers to object heads.
 class G1DirtyCardQueue: public PtrQueue {
 protected:
@@ -95,12 +85,12 @@
   // buffer_size.  If all closure applications return true, then
   // returns true.  Stops processing after the first closure
   // application that returns false, and returns false from this
-  // function.  If "consume" is true, the node's index is updated to
-  // exclude the processed elements, e.g. up to the element for which
-  // the closure returned false.
+  // function.  The node's index is updated to exclude the processed
+  // elements, e.g. up to the element for which the closure returned
+  // false, or one past the last element if the closure always
+  // returned true.
   bool apply_closure_to_buffer(G1CardTableEntryClosure* cl,
                                BufferNode* node,
-                               bool consume,
                                uint worker_i = 0);
 
   // If there are more than stop_at completed buffers, pop one, apply
@@ -135,9 +125,6 @@
   jint _processed_buffers_mut;
   jint _processed_buffers_rs_thread;
 
-  // Current buffer node used for parallel iteration.
-  BufferNode* volatile _cur_par_buffer_node;
-
 public:
   G1DirtyCardQueueSet(bool notify_when_complete = true);
   ~G1DirtyCardQueueSet();
@@ -183,7 +170,7 @@
   // Notify the consumer if the number of buffers crossed the threshold
   void notify_if_necessary();
 
-  void merge_bufferlists(G1DirtyCardQueueSet* src);
+  void merge_bufferlists(G1RedirtyCardsQueueSet* src);
 
   // Apply G1RefineCardConcurrentlyClosure to completed buffers until there are stop_at
   // completed buffers remaining.
@@ -193,12 +180,6 @@
   // must never return false. Must only be called during GC.
   bool apply_closure_during_gc(G1CardTableEntryClosure* cl, uint worker_i);
 
-  void reset_for_par_iteration() { _cur_par_buffer_node = _completed_buffers_head; }
-  // Applies the current closure to all completed buffers, non-consumptively.
-  // Can be used in parallel, all callers using the iteration state initialized
-  // by reset_for_par_iteration.
-  void par_apply_closure_to_all_completed_buffers(G1CardTableEntryClosure* cl);
-
   // If a full collection is happening, reset partial logs, and release
   // completed ones: the full collection will make them all irrelevant.
   void abandon_logs();
--- a/src/hotspot/share/gc/g1/g1EvacFailure.cpp	Fri Jul 19 15:11:33 2019 +0530
+++ b/src/hotspot/share/gc/g1/g1EvacFailure.cpp	Mon Jul 22 11:07:24 2019 +0530
@@ -26,10 +26,10 @@
 #include "gc/g1/g1CollectedHeap.inline.hpp"
 #include "gc/g1/g1CollectorState.hpp"
 #include "gc/g1/g1ConcurrentMark.inline.hpp"
-#include "gc/g1/g1DirtyCardQueue.hpp"
 #include "gc/g1/g1EvacFailure.hpp"
 #include "gc/g1/g1HeapVerifier.hpp"
 #include "gc/g1/g1OopClosures.inline.hpp"
+#include "gc/g1/g1RedirtyCardsQueue.hpp"
 #include "gc/g1/heapRegion.hpp"
 #include "gc/g1/heapRegionRemSet.hpp"
 #include "gc/shared/preservedMarks.inline.hpp"
@@ -40,7 +40,7 @@
 class UpdateLogBuffersDeferred : public BasicOopIterateClosure {
 private:
   G1CollectedHeap* _g1h;
-  G1DirtyCardQueue* _dcq;
+  G1RedirtyCardsQueue* _rdcq;
   G1CardTable*    _ct;
 
   // Remember the last enqueued card to avoid enqueuing the same card over and over;
@@ -48,8 +48,8 @@
   size_t _last_enqueued_card;
 
 public:
-  UpdateLogBuffersDeferred(G1DirtyCardQueue* dcq) :
-    _g1h(G1CollectedHeap::heap()), _dcq(dcq), _ct(_g1h->card_table()), _last_enqueued_card(SIZE_MAX) {}
+  UpdateLogBuffersDeferred(G1RedirtyCardsQueue* rdcq) :
+    _g1h(G1CollectedHeap::heap()), _rdcq(rdcq), _ct(_g1h->card_table()), _last_enqueued_card(SIZE_MAX) {}
 
   virtual void do_oop(narrowOop* p) { do_oop_work(p); }
   virtual void do_oop(      oop* p) { do_oop_work(p); }
@@ -67,7 +67,7 @@
     }
     size_t card_index = _ct->index_for(p);
     if (card_index != _last_enqueued_card) {
-      _dcq->enqueue(_ct->byte_for_index(card_index));
+      _rdcq->enqueue(_ct->byte_for_index(card_index));
       _last_enqueued_card = card_index;
     }
   }
@@ -199,15 +199,15 @@
   G1CollectedHeap* _g1h;
   uint _worker_id;
 
-  G1DirtyCardQueue _dcq;
+  G1RedirtyCardsQueue _rdcq;
   UpdateLogBuffersDeferred _log_buffer_cl;
 
 public:
   RemoveSelfForwardPtrHRClosure(uint worker_id) :
     _g1h(G1CollectedHeap::heap()),
     _worker_id(worker_id),
-    _dcq(&_g1h->dirty_card_queue_set()),
-    _log_buffer_cl(&_dcq) {
+    _rdcq(&_g1h->redirty_cards_queue_set()),
+    _log_buffer_cl(&_rdcq) {
   }
 
   size_t remove_self_forward_ptr_by_walking_hr(HeapRegion* hr,
--- a/src/hotspot/share/gc/g1/g1HotCardCache.cpp	Fri Jul 19 15:11:33 2019 +0530
+++ b/src/hotspot/share/gc/g1/g1HotCardCache.cpp	Mon Jul 22 11:07:24 2019 +0530
@@ -23,6 +23,7 @@
  */
 
 #include "precompiled.hpp"
+#include "gc/g1/g1CardTableEntryClosure.hpp"
 #include "gc/g1/g1CollectedHeap.inline.hpp"
 #include "gc/g1/g1DirtyCardQueue.hpp"
 #include "gc/g1/g1HotCardCache.hpp"
--- a/src/hotspot/share/gc/g1/g1ParScanThreadState.cpp	Fri Jul 19 15:11:33 2019 +0530
+++ b/src/hotspot/share/gc/g1/g1ParScanThreadState.cpp	Mon Jul 22 11:07:24 2019 +0530
@@ -43,7 +43,7 @@
                                            size_t optional_cset_length)
   : _g1h(g1h),
     _refs(g1h->task_queue(worker_id)),
-    _dcq(&g1h->dirty_card_queue_set()),
+    _rdcq(&g1h->redirty_cards_queue_set()),
     _ct(g1h->card_table()),
     _closures(NULL),
     _plab_allocator(NULL),
@@ -88,7 +88,7 @@
 
 // Pass locally gathered statistics to global state.
 void G1ParScanThreadState::flush(size_t* surviving_young_words) {
-  _dcq.flush();
+  _rdcq.flush();
   // Update allocation statistics.
   _plab_allocator->flush_and_retire_stats();
   _g1h->policy()->record_age_table(&_age_table);
--- a/src/hotspot/share/gc/g1/g1ParScanThreadState.hpp	Fri Jul 19 15:11:33 2019 +0530
+++ b/src/hotspot/share/gc/g1/g1ParScanThreadState.hpp	Mon Jul 22 11:07:24 2019 +0530
@@ -27,7 +27,7 @@
 
 #include "gc/g1/g1CardTable.hpp"
 #include "gc/g1/g1CollectedHeap.hpp"
-#include "gc/g1/g1DirtyCardQueue.hpp"
+#include "gc/g1/g1RedirtyCardsQueue.hpp"
 #include "gc/g1/g1OopClosures.hpp"
 #include "gc/g1/g1Policy.hpp"
 #include "gc/g1/g1RemSet.hpp"
@@ -46,7 +46,7 @@
 class G1ParScanThreadState : public CHeapObj<mtGC> {
   G1CollectedHeap* _g1h;
   RefToScanQueue* _refs;
-  G1DirtyCardQueue _dcq;
+  G1RedirtyCardsQueue _rdcq;
   G1CardTable* _ct;
   G1EvacuationRootClosures* _closures;
 
@@ -81,7 +81,7 @@
 
 #define PADDING_ELEM_NUM (DEFAULT_CACHE_LINE_SIZE / sizeof(size_t))
 
-  G1DirtyCardQueue& dirty_card_queue()           { return _dcq; }
+  G1RedirtyCardsQueue& redirty_cards_queue()     { return _rdcq; }
   G1CardTable* ct()                              { return _ct; }
 
   G1HeapRegionAttr dest(G1HeapRegionAttr original) const {
@@ -133,7 +133,7 @@
     size_t card_index = ct()->index_for(p);
     // If the card hasn't been added to the buffer, do it.
     if (_last_enqueued_card != card_index) {
-      dirty_card_queue().enqueue(ct()->byte_for_index(card_index));
+      redirty_cards_queue().enqueue(ct()->byte_for_index(card_index));
       _last_enqueued_card = card_index;
     }
   }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/g1/g1RedirtyCardsQueue.cpp	Mon Jul 22 11:07:24 2019 +0530
@@ -0,0 +1,163 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "gc/g1/g1RedirtyCardsQueue.hpp"
+#include "runtime/atomic.hpp"
+#include "utilities/debug.hpp"
+#include "utilities/macros.hpp"
+
+// G1RedirtyCardsBufferList
+
+G1RedirtyCardsBufferList::G1RedirtyCardsBufferList() :
+  _head(NULL), _tail(NULL), _count(0) {}
+
+G1RedirtyCardsBufferList::G1RedirtyCardsBufferList(BufferNode* head,
+                                                   BufferNode* tail,
+                                                   size_t count) :
+  _head(head), _tail(tail), _count(count)
+{
+  assert((_head == NULL) == (_tail == NULL), "invariant");
+  assert((_head == NULL) == (_count == 0), "invariant");
+}
+
+// G1RedirtyCardsQueueBase::LocalQSet
+
+G1RedirtyCardsQueueBase::LocalQSet::LocalQSet(G1RedirtyCardsQueueSet* shared_qset) :
+  PtrQueueSet(),
+  _shared_qset(shared_qset),
+  _buffers()
+{
+  PtrQueueSet::initialize(_shared_qset->allocator());
+}
+
+G1RedirtyCardsQueueBase::LocalQSet::~LocalQSet() {
+  assert(_buffers._head == NULL, "unflushed qset");
+  assert(_buffers._tail == NULL, "invariant");
+  assert(_buffers._count == 0, "invariant");
+}
+
+void G1RedirtyCardsQueueBase::LocalQSet::enqueue_completed_buffer(BufferNode* node) {
+  ++_buffers._count;
+  node->set_next(_buffers._head);
+  _buffers._head = node;
+  if (_buffers._tail == NULL) {
+    _buffers._tail = node;
+  }
+}
+
+G1RedirtyCardsBufferList
+G1RedirtyCardsQueueBase::LocalQSet::take_all_completed_buffers() {
+  G1RedirtyCardsBufferList result = _buffers;
+  _buffers = G1RedirtyCardsBufferList();
+  return result;
+}
+
+void G1RedirtyCardsQueueBase::LocalQSet::flush() {
+  _shared_qset->merge_bufferlist(this);
+}
+
+// G1RedirtyCardsQueue
+
+G1RedirtyCardsQueue::G1RedirtyCardsQueue(G1RedirtyCardsQueueSet* qset) :
+  G1RedirtyCardsQueueBase(qset), // Init _local_qset before passing to PtrQueue.
+  PtrQueue(&_local_qset, true /* active (always) */)
+{}
+
+G1RedirtyCardsQueue::~G1RedirtyCardsQueue() {
+  flush();
+}
+
+void G1RedirtyCardsQueue::handle_completed_buffer() {
+  enqueue_completed_buffer();
+}
+
+void G1RedirtyCardsQueue::flush() {
+  flush_impl();
+  _local_qset.flush();
+}
+
+// G1RedirtyCardsQueueSet
+
+G1RedirtyCardsQueueSet::G1RedirtyCardsQueueSet() :
+  PtrQueueSet(),
+  _list(),
+  _count(0),
+  _tail(NULL)
+  DEBUG_ONLY(COMMA _collecting(true))
+{}
+
+G1RedirtyCardsQueueSet::~G1RedirtyCardsQueueSet() {
+  verify_empty();
+}
+
+#ifdef ASSERT
+void G1RedirtyCardsQueueSet::verify_empty() const {
+  assert(_list.empty(), "precondition");
+  assert(_tail == NULL, "invariant");
+  assert(_count == 0, "invariant");
+}
+#endif // ASSERT
+
+BufferNode* G1RedirtyCardsQueueSet::all_completed_buffers() const {
+  DEBUG_ONLY(_collecting = false;)
+  return _list.top();
+}
+
+G1RedirtyCardsBufferList G1RedirtyCardsQueueSet::take_all_completed_buffers() {
+  DEBUG_ONLY(_collecting = false;)
+  G1RedirtyCardsBufferList result(_list.pop_all(), _tail, _count);
+  _tail = NULL;
+  _count = 0;
+  DEBUG_ONLY(_collecting = true;)
+  return result;
+}
+
+void G1RedirtyCardsQueueSet::update_tail(BufferNode* node) {
+  // Node is the tail of a (possibly single element) list just prepended to
+  // _list.  If, after that prepend, node's follower is NULL, then node is
+  // also the tail of _list, so record it as such.
+  if (node->next() == NULL) {
+    assert(_tail == NULL, "invariant");
+    _tail = node;
+  }
+}
+
+void G1RedirtyCardsQueueSet::enqueue_completed_buffer(BufferNode* node) {
+  assert(_collecting, "precondition");
+  Atomic::inc(&_count);
+  _list.push(*node);
+  update_tail(node);
+}
+
+void G1RedirtyCardsQueueSet::merge_bufferlist(LocalQSet* src) {
+  assert(_collecting, "precondition");
+  const G1RedirtyCardsBufferList from = src->take_all_completed_buffers();
+  if (from._head != NULL) {
+    assert(from._tail != NULL, "invariant");
+    Atomic::add(from._count, &_count);
+    _list.prepend(*from._head, *from._tail);
+    update_tail(from._tail);
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/g1/g1RedirtyCardsQueue.hpp	Mon Jul 22 11:07:24 2019 +0530
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef SHARE_GC_G1_G1REDIRTYCARDSQUEUE_HPP
+#define SHARE_GC_G1_G1REDIRTYCARDSQUEUE_HPP
+
+#include "gc/shared/ptrQueue.hpp"
+#include "memory/allocation.hpp"
+#include "memory/padded.hpp"
+
+class G1CardTableEntryClosure;
+class G1RedirtyCardsQueue;
+class G1RedirtyCardsQueueSet;
+
+struct G1RedirtyCardsBufferList {
+  BufferNode* _head;
+  BufferNode* _tail;
+  size_t _count;
+
+  G1RedirtyCardsBufferList();
+  G1RedirtyCardsBufferList(BufferNode* head, BufferNode* tail, size_t count);
+};
+
+// Provide G1RedirtyCardsQueue with a thread-local qset.  It provides an
+// uncontended staging area for completed buffers, to be flushed to the
+// shared qset en masse.  Using the "base from member" idiom so the local
+// qset is constructed before being passed to the PtrQueue constructor.
+class G1RedirtyCardsQueueBase {
+  friend class G1RedirtyCardsQueue;
+  friend class G1RedirtyCardsQueueSet;
+
+  class LocalQSet : public PtrQueueSet {
+    G1RedirtyCardsQueueSet* _shared_qset;
+    G1RedirtyCardsBufferList _buffers;
+
+  public:
+    LocalQSet(G1RedirtyCardsQueueSet* shared_qset);
+    ~LocalQSet();
+
+    // Add the buffer to the local list.
+    virtual void enqueue_completed_buffer(BufferNode* node);
+
+    // Transfer all completed buffers to the shared qset.
+    void flush();
+
+    G1RedirtyCardsBufferList take_all_completed_buffers();
+  };
+
+  G1RedirtyCardsQueueBase(G1RedirtyCardsQueueSet* shared_qset) :
+    _local_qset(shared_qset) {}
+
+  ~G1RedirtyCardsQueueBase() {}
+
+  LocalQSet _local_qset;
+};
+
+// Worker-local queues of card table entries.
+class G1RedirtyCardsQueue : private G1RedirtyCardsQueueBase, public PtrQueue {
+protected:
+  virtual void handle_completed_buffer();
+
+public:
+  G1RedirtyCardsQueue(G1RedirtyCardsQueueSet* qset);
+
+  // Flushes the queue.
+  ~G1RedirtyCardsQueue();
+
+  // Flushes all enqueued cards to qset.
+  void flush();
+};
+
+// Card table entries to be redirtied and the cards reprocessed later.
+// Has two phases, collecting and processing.  During the collecting
+// phase buffers are added to the set.  Once collecting is complete and
+// processing starts, buffers can no longer be added.  Taking all the
+// collected (and processed) buffers reverts back to collecting, allowing
+// the set to be reused for another round of redirtying.
+class G1RedirtyCardsQueueSet : public PtrQueueSet {
+  DEFINE_PAD_MINUS_SIZE(1, DEFAULT_CACHE_LINE_SIZE, 0);
+  BufferNode::Stack _list;
+  DEFINE_PAD_MINUS_SIZE(2, DEFAULT_CACHE_LINE_SIZE, sizeof(size_t));
+  volatile size_t _count;
+  DEFINE_PAD_MINUS_SIZE(3, DEFAULT_CACHE_LINE_SIZE, sizeof(BufferNode*));
+  BufferNode* _tail;
+  DEBUG_ONLY(mutable bool _collecting;)
+
+  typedef G1RedirtyCardsQueueBase::LocalQSet LocalQSet;
+
+  void update_tail(BufferNode* node);
+
+public:
+  G1RedirtyCardsQueueSet();
+  ~G1RedirtyCardsQueueSet();
+
+  using PtrQueueSet::initialize;
+
+  void verify_empty() const NOT_DEBUG_RETURN;
+
+  // Collect buffers.  These functions are thread-safe.
+  // precondition: Must not be concurrent with buffer processing.
+  virtual void enqueue_completed_buffer(BufferNode* node);
+  void merge_bufferlist(LocalQSet* src);
+
+  // Processing phase operations.
+  // precondition: Must not be concurrent with buffer collection.
+  BufferNode* all_completed_buffers() const;
+  G1RedirtyCardsBufferList take_all_completed_buffers();
+};
+
+#endif // SHARE_GC_G1_G1REDIRTYCARDSQUEUE_HPP
--- a/src/hotspot/share/gc/g1/g1RemSet.cpp	Fri Jul 19 15:11:33 2019 +0530
+++ b/src/hotspot/share/gc/g1/g1RemSet.cpp	Mon Jul 22 11:07:24 2019 +0530
@@ -26,6 +26,7 @@
 #include "gc/g1/g1BarrierSet.hpp"
 #include "gc/g1/g1BlockOffsetTable.inline.hpp"
 #include "gc/g1/g1CardTable.inline.hpp"
+#include "gc/g1/g1CardTableEntryClosure.hpp"
 #include "gc/g1/g1CollectedHeap.inline.hpp"
 #include "gc/g1/g1ConcurrentRefine.hpp"
 #include "gc/g1/g1DirtyCardQueue.hpp"
--- a/src/hotspot/share/gc/shared/ptrQueue.hpp	Fri Jul 19 15:11:33 2019 +0530
+++ b/src/hotspot/share/gc/shared/ptrQueue.hpp	Mon Jul 22 11:07:24 2019 +0530
@@ -296,6 +296,10 @@
 class PtrQueueSet {
   BufferNode::Allocator* _allocator;
 
+  // Noncopyable - not defined.
+  PtrQueueSet(const PtrQueueSet&);
+  PtrQueueSet& operator=(const PtrQueueSet&);
+
 protected:
   bool _all_active;
 
@@ -309,6 +313,9 @@
 
 public:
 
+  // Return the associated BufferNode allocator.
+  BufferNode::Allocator* allocator() const { return _allocator; }
+
   // Return the buffer for a BufferNode of size buffer_size().
   void** allocate_buffer();
 
--- a/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp	Fri Jul 19 15:11:33 2019 +0530
+++ b/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp	Mon Jul 22 11:07:24 2019 +0530
@@ -3016,7 +3016,7 @@
 }
 
 uint ShenandoahLoadReferenceBarrierNode::hash() const {
-  return Node::hash() + _native ? 1 : 0;
+  return Node::hash() + (_native ? 1 : 0);
 }
 
 bool ShenandoahLoadReferenceBarrierNode::cmp( const Node &n ) const {
--- a/src/hotspot/share/oops/method.cpp	Fri Jul 19 15:11:33 2019 +0530
+++ b/src/hotspot/share/oops/method.cpp	Mon Jul 22 11:07:24 2019 +0530
@@ -146,6 +146,12 @@
   return adapter()->get_c2i_unverified_entry();
 }
 
+address Method::get_c2i_no_clinit_check_entry() {
+  assert(VM_Version::supports_fast_class_init_checks(), "");
+  assert(adapter() != NULL, "must have");
+  return adapter()->get_c2i_no_clinit_check_entry();
+}
+
 char* Method::name_and_sig_as_C_string() const {
   return name_and_sig_as_C_string(constants()->pool_holder(), name(), signature());
 }
@@ -1045,7 +1051,7 @@
                                                               _c2i_entry ---------------------------------+->[c2i entry..]
  _i2i_entry  -------------+                                   _i2c_entry ---------------+-> [i2c entry..] |
  _from_interpreted_entry  |                                   _c2i_unverified_entry     |                 |
-         |                |                                                             |                 |
+         |                |                                   _c2i_no_clinit_check_entry|                 |
          |                |  (_cds_entry_table: CODE)                                   |                 |
          |                +->[0]: jmp _entry_table[0] --> (i2i_entry_for "zero_locals") |                 |
          |                |                               (allocated at run time)       |                 |
--- a/src/hotspot/share/oops/method.hpp	Fri Jul 19 15:11:33 2019 +0530
+++ b/src/hotspot/share/oops/method.hpp	Mon Jul 22 11:07:24 2019 +0530
@@ -481,6 +481,7 @@
   address get_i2c_entry();
   address get_c2i_entry();
   address get_c2i_unverified_entry();
+  address get_c2i_no_clinit_check_entry();
   AdapterHandlerEntry* adapter() const {
     return constMethod()->adapter();
   }
--- a/src/hotspot/share/runtime/sharedRuntime.cpp	Fri Jul 19 15:11:33 2019 +0530
+++ b/src/hotspot/share/runtime/sharedRuntime.cpp	Mon Jul 22 11:07:24 2019 +0530
@@ -1446,7 +1446,19 @@
     guarantee(callee != NULL && callee->is_method(), "bad handshake");
     thread->set_vm_result_2(callee);
     thread->set_callee_target(NULL);
-    return callee->get_c2i_entry();
+    if (caller_frame.is_entry_frame() && VM_Version::supports_fast_class_init_checks()) {
+      // Bypass class initialization checks in c2i when caller is in native.
+      // JNI calls to static methods don't have class initialization checks.
+      // Fast class initialization checks are present in c2i adapters and call into
+      // SharedRuntime::handle_wrong_method() on the slow path.
+      //
+      // JVM upcalls may land here as well, but there's a proper check present in
+      // LinkResolver::resolve_static_call (called from JavaCalls::call_static),
+      // so bypassing it in c2i adapter is benign.
+      return callee->get_c2i_no_clinit_check_entry();
+    } else {
+      return callee->get_c2i_entry();
+    }
   }
 
   // Must be compiled to compiled path which is safe to stackwalk
@@ -2450,9 +2462,9 @@
     : BasicHashtable<mtCode>(293, (DumpSharedSpaces ? sizeof(CDSAdapterHandlerEntry) : sizeof(AdapterHandlerEntry))) { }
 
   // Create a new entry suitable for insertion in the table
-  AdapterHandlerEntry* new_entry(AdapterFingerPrint* fingerprint, address i2c_entry, address c2i_entry, address c2i_unverified_entry) {
+  AdapterHandlerEntry* new_entry(AdapterFingerPrint* fingerprint, address i2c_entry, address c2i_entry, address c2i_unverified_entry, address c2i_no_clinit_check_entry) {
     AdapterHandlerEntry* entry = (AdapterHandlerEntry*)BasicHashtable<mtCode>::new_entry(fingerprint->compute_hash());
-    entry->init(fingerprint, i2c_entry, c2i_entry, c2i_unverified_entry);
+    entry->init(fingerprint, i2c_entry, c2i_entry, c2i_unverified_entry, c2i_no_clinit_check_entry);
     if (DumpSharedSpaces) {
       ((CDSAdapterHandlerEntry*)entry)->init();
     }
@@ -2601,8 +2613,9 @@
 AdapterHandlerEntry* AdapterHandlerLibrary::new_entry(AdapterFingerPrint* fingerprint,
                                                       address i2c_entry,
                                                       address c2i_entry,
-                                                      address c2i_unverified_entry) {
-  return _adapters->new_entry(fingerprint, i2c_entry, c2i_entry, c2i_unverified_entry);
+                                                      address c2i_unverified_entry,
+                                                      address c2i_no_clinit_check_entry) {
+  return _adapters->new_entry(fingerprint, i2c_entry, c2i_entry, c2i_unverified_entry, c2i_no_clinit_check_entry);
 }
 
 AdapterHandlerEntry* AdapterHandlerLibrary::get_adapter(const methodHandle& method) {
@@ -2778,6 +2791,7 @@
   if (base == NULL)  base = _c2i_entry;
   assert(base <= _c2i_entry || _c2i_entry == NULL, "");
   assert(base <= _c2i_unverified_entry || _c2i_unverified_entry == NULL, "");
+  assert(base <= _c2i_no_clinit_check_entry || _c2i_no_clinit_check_entry == NULL, "");
   return base;
 }
 
@@ -2791,6 +2805,8 @@
     _c2i_entry += delta;
   if (_c2i_unverified_entry != NULL)
     _c2i_unverified_entry += delta;
+  if (_c2i_no_clinit_check_entry != NULL)
+    _c2i_no_clinit_check_entry += delta;
   assert(base_address() == new_base, "");
 }
 
@@ -3129,10 +3145,20 @@
 }
 
 void AdapterHandlerEntry::print_adapter_on(outputStream* st) const {
-  st->print_cr("AHE@" INTPTR_FORMAT ": %s i2c: " INTPTR_FORMAT " c2i: " INTPTR_FORMAT " c2iUV: " INTPTR_FORMAT,
-               p2i(this), fingerprint()->as_string(),
-               p2i(get_i2c_entry()), p2i(get_c2i_entry()), p2i(get_c2i_unverified_entry()));
-
+  st->print("AHE@" INTPTR_FORMAT ": %s", p2i(this), fingerprint()->as_string());
+  if (get_i2c_entry() != NULL) {
+    st->print(" i2c: " INTPTR_FORMAT, p2i(get_i2c_entry()));
+  }
+  if (get_c2i_entry() != NULL) {
+    st->print(" c2i: " INTPTR_FORMAT, p2i(get_c2i_entry()));
+  }
+  if (get_c2i_unverified_entry() != NULL) {
+    st->print(" c2iUV: " INTPTR_FORMAT, p2i(get_c2i_unverified_entry()));
+  }
+  if (get_c2i_no_clinit_check_entry() != NULL) {
+    st->print(" c2iNCI: " INTPTR_FORMAT, p2i(get_c2i_no_clinit_check_entry()));
+  }
+  st->cr();
 }
 
 #if INCLUDE_CDS
--- a/src/hotspot/share/runtime/sharedRuntime.hpp	Fri Jul 19 15:11:33 2019 +0530
+++ b/src/hotspot/share/runtime/sharedRuntime.hpp	Mon Jul 22 11:07:24 2019 +0530
@@ -636,6 +636,7 @@
   address _i2c_entry;
   address _c2i_entry;
   address _c2i_unverified_entry;
+  address _c2i_no_clinit_check_entry;
 
 #ifdef ASSERT
   // Captures code and signature used to generate this adapter when
@@ -644,11 +645,12 @@
   int            _saved_code_length;
 #endif
 
-  void init(AdapterFingerPrint* fingerprint, address i2c_entry, address c2i_entry, address c2i_unverified_entry) {
+  void init(AdapterFingerPrint* fingerprint, address i2c_entry, address c2i_entry, address c2i_unverified_entry, address c2i_no_clinit_check_entry) {
     _fingerprint = fingerprint;
     _i2c_entry = i2c_entry;
     _c2i_entry = c2i_entry;
     _c2i_unverified_entry = c2i_unverified_entry;
+    _c2i_no_clinit_check_entry = c2i_no_clinit_check_entry;
 #ifdef ASSERT
     _saved_code = NULL;
     _saved_code_length = 0;
@@ -661,9 +663,11 @@
   AdapterHandlerEntry();
 
  public:
-  address get_i2c_entry()            const { return _i2c_entry; }
-  address get_c2i_entry()            const { return _c2i_entry; }
-  address get_c2i_unverified_entry() const { return _c2i_unverified_entry; }
+  address get_i2c_entry()                  const { return _i2c_entry; }
+  address get_c2i_entry()                  const { return _c2i_entry; }
+  address get_c2i_unverified_entry()       const { return _c2i_unverified_entry; }
+  address get_c2i_no_clinit_check_entry()  const { return _c2i_no_clinit_check_entry; }
+
   address base_address();
   void relocate(address new_base);
 
@@ -709,7 +713,10 @@
  public:
 
   static AdapterHandlerEntry* new_entry(AdapterFingerPrint* fingerprint,
-                                        address i2c_entry, address c2i_entry, address c2i_unverified_entry);
+                                        address i2c_entry,
+                                        address c2i_entry,
+                                        address c2i_unverified_entry,
+                                        address c2i_no_clinit_check_entry = NULL);
   static void create_native_wrapper(const methodHandle& method);
   static AdapterHandlerEntry* get_adapter(const methodHandle& method);
 
--- a/src/hotspot/share/runtime/thread.cpp	Fri Jul 19 15:11:33 2019 +0530
+++ b/src/hotspot/share/runtime/thread.cpp	Mon Jul 22 11:07:24 2019 +0530
@@ -2969,11 +2969,6 @@
     }
   }
 
-  // callee_target is never live across a gc point so NULL it here should
-  // it still contain a methdOop.
-
-  set_callee_target(NULL);
-
   assert(vframe_array_head() == NULL, "deopt in progress at a safepoint!");
   // If we have deferred set_locals there might be oops waiting to be
   // written
--- a/src/java.base/share/classes/java/net/ServerSocket.java	Fri Jul 19 15:11:33 2019 +0530
+++ b/src/java.base/share/classes/java/net/ServerSocket.java	Mon Jul 22 11:07:24 2019 +0530
@@ -27,17 +27,11 @@
 
 import java.io.FileDescriptor;
 import java.io.IOException;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
 import java.nio.channels.ServerSocketChannel;
-import java.security.AccessController;
-import java.security.PrivilegedExceptionAction;
 import java.util.Objects;
 import java.util.Set;
 import java.util.Collections;
 
-import jdk.internal.access.JavaNetSocketAccess;
-import jdk.internal.access.SharedSecrets;
 import sun.net.PlatformSocketImpl;
 
 /**
@@ -1116,27 +1110,4 @@
         }
         return options;
     }
-
-    static {
-        SharedSecrets.setJavaNetSocketAccess(
-            new JavaNetSocketAccess() {
-                @Override
-                public ServerSocket newServerSocket(SocketImpl impl) {
-                    return new ServerSocket(impl);
-                }
-
-                @Override
-                public SocketImpl newSocketImpl(Class<? extends SocketImpl> implClass) {
-                    try {
-                        Constructor<? extends SocketImpl> ctor =
-                            implClass.getDeclaredConstructor();
-                        return ctor.newInstance();
-                    } catch (NoSuchMethodException | InstantiationException |
-                             IllegalAccessException | InvocationTargetException e) {
-                        throw new AssertionError(e);
-                    }
-                }
-            }
-        );
-    }
 }
--- a/src/java.base/share/classes/java/net/URLClassLoader.java	Fri Jul 19 15:11:33 2019 +0530
+++ b/src/java.base/share/classes/java/net/URLClassLoader.java	Mon Jul 22 11:07:24 2019 +0530
@@ -52,7 +52,6 @@
 
 import jdk.internal.loader.Resource;
 import jdk.internal.loader.URLClassPath;
-import jdk.internal.access.JavaNetURLClassLoaderAccess;
 import jdk.internal.access.SharedSecrets;
 import jdk.internal.perf.PerfCounter;
 import sun.net.www.ParseUtil;
@@ -822,14 +821,6 @@
     }
 
     static {
-        SharedSecrets.setJavaNetURLClassLoaderAccess(
-            new JavaNetURLClassLoaderAccess() {
-                @Override
-                public AccessControlContext getAccessControlContext(URLClassLoader u) {
-                    return u.acc;
-                }
-            }
-        );
         ClassLoader.registerAsParallelCapable();
     }
 }
--- a/src/java.base/share/classes/jdk/internal/access/JavaNetSocketAccess.java	Fri Jul 19 15:11:33 2019 +0530
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,41 +0,0 @@
-/*
- * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.
- */
-
-package jdk.internal.access;
-
-import java.net.ServerSocket;
-import java.net.SocketImpl;
-
-public interface JavaNetSocketAccess {
-    /**
-     * Creates a ServerSocket associated with the given SocketImpl.
-     */
-    ServerSocket newServerSocket(SocketImpl impl);
-
-    /*
-     * Constructs a SocketImpl instance of the given class.
-     */
-    SocketImpl newSocketImpl(Class<? extends SocketImpl> implClass);
-}
--- a/src/java.base/share/classes/jdk/internal/access/JavaNetURLClassLoaderAccess.java	Fri Jul 19 15:11:33 2019 +0530
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,33 +0,0 @@
-/*
- * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.
- */
-
-package jdk.internal.access;
-
-import java.net.URLClassLoader;
-import java.security.AccessControlContext;
-
-public interface JavaNetURLClassLoaderAccess {
-    AccessControlContext getAccessControlContext(URLClassLoader u);;
-}
--- a/src/java.base/share/classes/jdk/internal/access/SharedSecrets.java	Fri Jul 19 15:11:33 2019 +0530
+++ b/src/java.base/share/classes/jdk/internal/access/SharedSecrets.java	Mon Jul 22 11:07:24 2019 +0530
@@ -58,10 +58,8 @@
     private static JavaIOAccess javaIOAccess;
     private static JavaNetInetAddressAccess javaNetInetAddressAccess;
     private static JavaNetHttpCookieAccess javaNetHttpCookieAccess;
-    private static JavaNetSocketAccess javaNetSocketAccess;
     private static JavaNetUriAccess javaNetUriAccess;
     private static JavaNetURLAccess javaNetURLAccess;
-    private static JavaNetURLClassLoaderAccess javaNetURLClassLoaderAccess;
     private static JavaNioAccess javaNioAccess;
     private static JavaIOFileDescriptorAccess javaIOFileDescriptorAccess;
     private static JavaIOFilePermissionAccess javaIOFilePermissionAccess;
@@ -151,16 +149,6 @@
         return javaNetURLAccess;
     }
 
-    public static void setJavaNetURLClassLoaderAccess(JavaNetURLClassLoaderAccess jnua) {
-        javaNetURLClassLoaderAccess = jnua;
-    }
-
-    public static JavaNetURLClassLoaderAccess getJavaNetURLClassLoaderAccess() {
-        if (javaNetURLClassLoaderAccess == null)
-            unsafe.ensureClassInitialized(java.net.URLClassLoader.class);
-        return javaNetURLClassLoaderAccess;
-    }
-
     public static void setJavaNetInetAddressAccess(JavaNetInetAddressAccess jna) {
         javaNetInetAddressAccess = jna;
     }
@@ -181,16 +169,6 @@
         return javaNetHttpCookieAccess;
     }
 
-    public static void setJavaNetSocketAccess(JavaNetSocketAccess jnsa) {
-        javaNetSocketAccess = jnsa;
-    }
-
-    public static JavaNetSocketAccess getJavaNetSocketAccess() {
-        if (javaNetSocketAccess == null)
-            unsafe.ensureClassInitialized(java.net.ServerSocket.class);
-        return javaNetSocketAccess;
-    }
-
     public static void setJavaNioAccess(JavaNioAccess jna) {
         javaNioAccess = jna;
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/gc/metaspace/TestSizeTransitions.java	Mon Jul 22 11:07:24 2019 +0530
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2019, Twitter, Inc.
+ * 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.
+ *
+ */
+
+package gc.metaspace;
+
+import jdk.test.lib.process.ProcessTools;
+import jdk.test.lib.process.OutputAnalyzer;
+
+/* @test TestSizeTransitionsSerial
+ * @key gc
+ * @requires vm.gc.Serial
+ * @summary Tests that the metaspace size transition logging is done correctly.
+ * @library /test/lib
+ * @run driver gc.metaspace.TestSizeTransitions false -XX:+UseSerialGC
+ * @run driver gc.metaspace.TestSizeTransitions true  -XX:+UseSerialGC
+ */
+
+/* @test TestSizeTransitionsParallel
+ * @key gc
+ * @requires vm.gc.Parallel
+ * @summary Tests that the metaspace size transition logging is done correctly.
+ * @library /test/lib
+ * @run driver gc.metaspace.TestSizeTransitions false -XX:+UseParallelGC
+ * @run driver gc.metaspace.TestSizeTransitions true  -XX:+UseParallelGC
+ */
+
+/* @test TestSizeTransitionsG1
+ * @key gc
+ * @requires vm.gc.G1
+ * @summary Tests that the metaspace size transition logging is done correctly.
+ * @library /test/lib
+ * @run driver gc.metaspace.TestSizeTransitions false -XX:+UseG1GC
+ * @run driver gc.metaspace.TestSizeTransitions true  -XX:+UseG1GC
+ */
+
+/* @test TestSizeTransitionsCMS
+ * @key gc
+ * @requires vm.gc.ConcMarkSweep
+ * @summary Tests that the metaspace size transition logging is done correctly.
+ * @library /test/lib
+ * @run driver gc.metaspace.TestSizeTransitions false -XX:+UseConcMarkSweepGC
+ * @run driver gc.metaspace.TestSizeTransitions true  -XX:+UseConcMarkSweepGC
+ */
+
+public class TestSizeTransitions {
+  public static class Run {
+    public static void main(String... args) throws Exception {
+      System.out.println("Run started.");
+
+      // easiest way to generate a metaspace transition is to ask for a full GC
+      System.gc();
+
+      System.out.println("Run finished.");
+    }
+  }
+
+  // matches the log tags
+  //   e.g., [0.043s][info][gc]
+  private static final String LOG_TAGS_REGEX = "(\\[.*\\])+ ";
+
+  // matches a size transition
+  //   e.g., 177K(4864K)->177K(4864K)
+  private static final String SIZE_TRANSITION_REGEX = "\\d+K\\(\\d+K\\)->\\d+K\\(\\d+K\\)";
+
+  // matches -coops metaspace size transitions
+  private static final String NO_COOPS_REGEX =
+    String.format("^%s.* Metaspace: %s$",
+                  LOG_TAGS_REGEX,
+                  SIZE_TRANSITION_REGEX);
+
+  // matches +coops metaspace size transitions
+  private static final String COOPS_REGEX =
+    String.format("^%s.* Metaspace: %s NonClass: %s Class: %s$",
+                  LOG_TAGS_REGEX,
+                  SIZE_TRANSITION_REGEX,
+                  SIZE_TRANSITION_REGEX,
+                  SIZE_TRANSITION_REGEX);
+
+  public static void main(String... args) throws Exception {
+    // args: <use-coops> <gc-arg>
+    if (args.length != 2) {
+      throw new RuntimeException("wrong number of args: " + args.length);
+    }
+
+    final boolean useCoops = Boolean.parseBoolean(args[0]);
+    final String gcArg = args[1];
+    final String[] jvmArgs = {
+      useCoops ? "-XX:+UseCompressedOops" : "-XX:-UseCompressedOops",
+      gcArg,
+      "-Xmx256m",
+      "-Xlog:gc,gc+metaspace=info",
+      TestSizeTransitions.Run.class.getName()
+    };
+
+    System.out.println("JVM args:");
+    for (String a : jvmArgs) {
+      System.out.println("  " + a);
+    }
+
+    final ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(jvmArgs);
+    final OutputAnalyzer output = new OutputAnalyzer(pb.start());
+    System.out.println(output.getStdout());
+    output.shouldHaveExitValue(0);
+
+    if (useCoops) {
+      output.stdoutShouldMatch(COOPS_REGEX);
+      output.stdoutShouldNotMatch(NO_COOPS_REGEX);
+    } else {
+      output.stdoutShouldMatch(NO_COOPS_REGEX);
+      output.stdoutShouldNotMatch(COOPS_REGEX);
+    }
+  }
+}
--- a/test/hotspot/jtreg/runtime/clinit/ClassInitBarrier.java	Fri Jul 19 15:11:33 2019 +0530
+++ b/test/hotspot/jtreg/runtime/clinit/ClassInitBarrier.java	Mon Jul 22 11:07:24 2019 +0530
@@ -27,24 +27,24 @@
  *
  * @requires !vm.graal.enabled
  *
- * @run main/othervm/native -Xbatch -XX:CompileCommand=dontinline,*::test* -Xint                   -DTHROW=false ClassInitBarrier
- * @run main/othervm/native -Xbatch -XX:CompileCommand=dontinline,*::test* -Xint                   -DTHROW=true  ClassInitBarrier
+ * @run main/othervm/native -Xbatch -XX:CompileCommand=dontinline,*::test* -Xint                   -DTHROW=false -Xcheck:jni ClassInitBarrier
+ * @run main/othervm/native -Xbatch -XX:CompileCommand=dontinline,*::test* -Xint                   -DTHROW=true  -Xcheck:jni ClassInitBarrier
  *
- * @run main/othervm/native -Xbatch -XX:CompileCommand=dontinline,*::test* -XX:TieredStopAtLevel=1 -DTHROW=false ClassInitBarrier
- * @run main/othervm/native -Xbatch -XX:CompileCommand=dontinline,*::test* -XX:TieredStopAtLevel=1 -DTHROW=true  ClassInitBarrier
+ * @run main/othervm/native -Xbatch -XX:CompileCommand=dontinline,*::test* -XX:TieredStopAtLevel=1 -DTHROW=false -Xcheck:jni ClassInitBarrier
+ * @run main/othervm/native -Xbatch -XX:CompileCommand=dontinline,*::test* -XX:TieredStopAtLevel=1 -DTHROW=true  -Xcheck:jni ClassInitBarrier
  *
- * @run main/othervm/native -Xbatch -XX:CompileCommand=dontinline,*::test* -XX:-TieredCompilation  -DTHROW=false ClassInitBarrier
- * @run main/othervm/native -Xbatch -XX:CompileCommand=dontinline,*::test* -XX:-TieredCompilation  -DTHROW=true  ClassInitBarrier
+ * @run main/othervm/native -Xbatch -XX:CompileCommand=dontinline,*::test* -XX:-TieredCompilation  -DTHROW=false -Xcheck:jni ClassInitBarrier
+ * @run main/othervm/native -Xbatch -XX:CompileCommand=dontinline,*::test* -XX:-TieredCompilation  -DTHROW=true  -Xcheck:jni ClassInitBarrier
  *
- * @run main/othervm/native -Xbatch -XX:CompileCommand=dontinline,*::test* -XX:TieredStopAtLevel=1 -DTHROW=false -XX:CompileCommand=dontinline,*::static* ClassInitBarrier
- * @run main/othervm/native -Xbatch -XX:CompileCommand=dontinline,*::test* -XX:TieredStopAtLevel=1 -DTHROW=true  -XX:CompileCommand=dontinline,*::static* ClassInitBarrier
- * @run main/othervm/native -Xbatch -XX:CompileCommand=dontinline,*::test* -XX:-TieredCompilation  -DTHROW=false -XX:CompileCommand=dontinline,*::static* ClassInitBarrier
- * @run main/othervm/native -Xbatch -XX:CompileCommand=dontinline,*::test* -XX:-TieredCompilation  -DTHROW=true  -XX:CompileCommand=dontinline,*::static* ClassInitBarrier
+ * @run main/othervm/native -Xbatch -XX:CompileCommand=dontinline,*::test* -XX:TieredStopAtLevel=1 -DTHROW=false -XX:CompileCommand=dontinline,*::static* -Xcheck:jni ClassInitBarrier
+ * @run main/othervm/native -Xbatch -XX:CompileCommand=dontinline,*::test* -XX:TieredStopAtLevel=1 -DTHROW=true  -XX:CompileCommand=dontinline,*::static* -Xcheck:jni ClassInitBarrier
+ * @run main/othervm/native -Xbatch -XX:CompileCommand=dontinline,*::test* -XX:-TieredCompilation  -DTHROW=false -XX:CompileCommand=dontinline,*::static* -Xcheck:jni ClassInitBarrier
+ * @run main/othervm/native -Xbatch -XX:CompileCommand=dontinline,*::test* -XX:-TieredCompilation  -DTHROW=true  -XX:CompileCommand=dontinline,*::static* -Xcheck:jni ClassInitBarrier
  *
- * @run main/othervm/native -Xbatch -XX:CompileCommand=dontinline,*::test* -XX:TieredStopAtLevel=1 -DTHROW=false -XX:CompileCommand=exclude,*::static* ClassInitBarrier
- * @run main/othervm/native -Xbatch -XX:CompileCommand=dontinline,*::test* -XX:TieredStopAtLevel=1 -DTHROW=true  -XX:CompileCommand=exclude,*::static* ClassInitBarrier
- * @run main/othervm/native -Xbatch -XX:CompileCommand=dontinline,*::test* -XX:-TieredCompilation  -DTHROW=false -XX:CompileCommand=exclude,*::static* ClassInitBarrier
- * @run main/othervm/native -Xbatch -XX:CompileCommand=dontinline,*::test* -XX:-TieredCompilation  -DTHROW=true  -XX:CompileCommand=exclude,*::static* ClassInitBarrier
+ * @run main/othervm/native -Xbatch -XX:CompileCommand=dontinline,*::test* -XX:TieredStopAtLevel=1 -DTHROW=false -XX:CompileCommand=exclude,*::static* -Xcheck:jni ClassInitBarrier
+ * @run main/othervm/native -Xbatch -XX:CompileCommand=dontinline,*::test* -XX:TieredStopAtLevel=1 -DTHROW=true  -XX:CompileCommand=exclude,*::static* -Xcheck:jni ClassInitBarrier
+ * @run main/othervm/native -Xbatch -XX:CompileCommand=dontinline,*::test* -XX:-TieredCompilation  -DTHROW=false -XX:CompileCommand=exclude,*::static* -Xcheck:jni ClassInitBarrier
+ * @run main/othervm/native -Xbatch -XX:CompileCommand=dontinline,*::test* -XX:-TieredCompilation  -DTHROW=true  -XX:CompileCommand=exclude,*::static* -Xcheck:jni ClassInitBarrier
  */
 
 import jdk.test.lib.Asserts;
@@ -70,6 +70,10 @@
     static class Test {
         static class A {
             static {
+                if (!init(B.class)) {
+                    throw new Error("init failed");
+                }
+
                 changePhase(Phase.IN_PROGRESS);
                 runTests();      // interpreted mode
                 warmup();        // trigger compilation
@@ -89,13 +93,15 @@
 
             int f;
             void m() {}
+
+            static native boolean init(Class<B> cls);
         }
 
         static class B extends A {}
 
-        static void testInvokeStatic(Runnable action)        { A.staticM(action); }
-        static void testInvokeStaticSync(Runnable action)    { A.staticS(action); }
-        static void testInvokeStaticNative(Runnable action)  { A.staticN(action); }
+        static void testInvokeStatic(Runnable action)       { A.staticM(action); }
+        static void testInvokeStaticSync(Runnable action)   { A.staticS(action); }
+        static void testInvokeStaticNative(Runnable action) { A.staticN(action); }
 
         static int  testGetStatic(Runnable action)    { int v = A.staticF; action.run(); return v;   }
         static void testPutStatic(Runnable action)    { A.staticF = 1;     action.run(); }
@@ -106,20 +112,45 @@
         static void testPutField(A recv, Runnable action)      { recv.f = 1;     action.run(); }
         static void testInvokeVirtual(A recv, Runnable action) { recv.m();       action.run(); }
 
+        static native void testInvokeStaticJNI(Runnable action);
+        static native void testInvokeStaticSyncJNI(Runnable action);
+        static native void testInvokeStaticNativeJNI(Runnable action);
+
+        static native int  testGetStaticJNI(Runnable action);
+        static native void testPutStaticJNI(Runnable action);
+        static native A    testNewInstanceAJNI(Runnable action);
+        static native B    testNewInstanceBJNI(Runnable action);
+
+        static native int  testGetFieldJNI(A recv, Runnable action);
+        static native void testPutFieldJNI(A recv, Runnable action);
+        static native void testInvokeVirtualJNI(A recv, Runnable action);
+
         static void runTests() {
             checkBlockingAction(Test::testInvokeStatic);       // invokestatic
+            checkBlockingAction(Test::testInvokeStaticSync);   // invokestatic
             checkBlockingAction(Test::testInvokeStaticNative); // invokestatic
-            checkBlockingAction(Test::testInvokeStaticSync);   // invokestatic
             checkBlockingAction(Test::testGetStatic);          // getstatic
             checkBlockingAction(Test::testPutStatic);          // putstatic
             checkBlockingAction(Test::testNewInstanceA);       // new
 
+            checkNonBlockingAction(Test::testInvokeStaticJNI);       // invokestatic
+            checkNonBlockingAction(Test::testInvokeStaticSyncJNI);   // invokestatic
+            checkNonBlockingAction(Test::testInvokeStaticNativeJNI); // invokestatic
+            checkNonBlockingAction(Test::testGetStaticJNI);          // getstatic
+            checkNonBlockingAction(Test::testPutStaticJNI);          // putstatic
+            checkBlockingAction(Test::testNewInstanceAJNI);          // new
+
             A recv = testNewInstanceB(NON_BLOCKING.get());  // trigger B initialization
             checkNonBlockingAction(Test::testNewInstanceB); // new: NO BLOCKING: same thread: A being initialized, B fully initialized
 
             checkNonBlockingAction(recv, Test::testGetField);      // getfield
             checkNonBlockingAction(recv, Test::testPutField);      // putfield
             checkNonBlockingAction(recv, Test::testInvokeVirtual); // invokevirtual
+
+            checkNonBlockingAction(Test::testNewInstanceBJNI);        // new: NO BLOCKING: same thread: A being initialized, B fully initialized
+            checkNonBlockingAction(recv, Test::testGetFieldJNI);      // getfield
+            checkNonBlockingAction(recv, Test::testPutFieldJNI);      // putfield
+            checkNonBlockingAction(recv, Test::testInvokeVirtualJNI); // invokevirtual
         }
 
         static void warmup() {
--- a/test/hotspot/jtreg/runtime/clinit/libClassInitBarrier.cpp	Fri Jul 19 15:11:33 2019 +0530
+++ b/test/hotspot/jtreg/runtime/clinit/libClassInitBarrier.cpp	Mon Jul 22 11:07:24 2019 +0530
@@ -25,6 +25,17 @@
 
 static jmethodID methodId;
 
+static jclass test_class_A;
+static jclass test_class_B;
+
+static jmethodID test_staticM_id;
+static jmethodID test_staticS_id;
+static jmethodID test_staticN_id;
+static jmethodID test_A_m_id;
+
+static jfieldID test_staticF_id;
+static jfieldID test_A_f_id;
+
 extern "C" {
     JNIEXPORT jboolean JNICALL Java_ClassInitBarrier_init(JNIEnv* env, jclass cls) {
         jclass runnable = env->FindClass("java/lang/Runnable");
@@ -36,7 +47,103 @@
         return JNI_TRUE;
     }
 
+    JNIEXPORT jboolean JNICALL Java_ClassInitBarrier_00024Test_00024A_init(JNIEnv* env, jclass cls, jclass arg1) {
+        test_class_A = (jclass)env->NewGlobalRef(cls);
+        if (test_class_A == NULL)  return JNI_FALSE;
+
+        test_class_B = (jclass)env->NewGlobalRef(arg1);
+        if (test_class_B == NULL)  return JNI_FALSE;
+
+        test_staticM_id = env->GetStaticMethodID(test_class_A, "staticM", "(Ljava/lang/Runnable;)V");
+        if (test_staticM_id == NULL)  return JNI_FALSE;
+
+        test_staticS_id = env->GetStaticMethodID(test_class_A, "staticS", "(Ljava/lang/Runnable;)V");
+        if (test_staticS_id == NULL)  return JNI_FALSE;
+
+        test_staticN_id = env->GetStaticMethodID(test_class_A, "staticN", "(Ljava/lang/Runnable;)V");
+        if (test_staticN_id == NULL)  return JNI_FALSE;
+
+        test_A_m_id = env->GetMethodID(test_class_A, "m", "()V");
+        if (test_A_m_id == NULL)  return JNI_FALSE;
+
+        test_staticF_id = env->GetStaticFieldID(test_class_A, "staticF", "I");
+        if (test_staticF_id == NULL)  return JNI_FALSE;
+
+        test_A_f_id = env->GetFieldID(test_class_A, "f", "I");
+        if (test_A_f_id == NULL)  return JNI_FALSE;
+
+        return JNI_TRUE;
+    }
+
     JNIEXPORT void JNICALL Java_ClassInitBarrier_00024Test_00024A_staticN(JNIEnv* env, jclass cls, jobject action) {
         env->CallVoidMethod(action, methodId);
     }
+
+    JNIEXPORT void JNICALL Java_ClassInitBarrier_00024Test_testInvokeStaticJNI(JNIEnv* env, jclass cls, jobject action) {
+        env->CallStaticVoidMethod(test_class_A, test_staticM_id, action);
+    }
+
+    JNIEXPORT void JNICALL Java_ClassInitBarrier_00024Test_testInvokeStaticSyncJNI(JNIEnv* env, jclass cls, jobject action) {
+        env->CallStaticVoidMethod(test_class_A, test_staticS_id, action);
+    }
+
+    JNIEXPORT void JNICALL Java_ClassInitBarrier_00024Test_testInvokeStaticNativeJNI(JNIEnv* env, jclass cls, jobject action) {
+        env->CallStaticVoidMethod(test_class_A, test_staticN_id, action);
+    }
+
+    JNIEXPORT jint JNICALL Java_ClassInitBarrier_00024Test_testGetStaticJNI(JNIEnv* env, jclass cls, jobject action) {
+        jint v = env->GetStaticIntField(test_class_A, test_staticF_id); // int v = A.staticF;
+        env->CallVoidMethod(action, methodId);                          // action.run();
+        return v;
+    }
+
+    JNIEXPORT void JNICALL Java_ClassInitBarrier_00024Test_testPutStaticJNI(JNIEnv* env, jclass cls, jobject action) {
+        env->SetStaticIntField(test_class_A, test_staticF_id, 1); // A.staticF = 1;
+        env->CallVoidMethod(action, methodId);                    // action.run();
+    }
+
+    JNIEXPORT jobject JNICALL Java_ClassInitBarrier_00024Test_testNewInstanceAJNI(JNIEnv* env, jclass cls, jobject action) {
+        jobject obj = env->AllocObject(test_class_A); // A obj = new A();
+        if (env->ExceptionOccurred()) {
+          return NULL;
+        } else if (obj == NULL) {
+          jclass errorClass = env->FindClass("java/lang/AssertionError");
+          int ret = env->ThrowNew(errorClass, "JNI: AllocObject: allocation failed, but no exception thrown");
+          return NULL;
+        }
+        env->CallVoidMethod(action, methodId);        // action.run();
+        return obj;
+    }
+
+    JNIEXPORT jobject JNICALL Java_ClassInitBarrier_00024Test_testNewInstanceBJNI(JNIEnv* env, jclass cls, jobject action) {
+        jobject obj = env->AllocObject(test_class_B); // B obj = new B();
+        if (env->ExceptionOccurred()) {
+          return NULL;
+        } else if (obj == NULL) {
+          jclass errorClass = env->FindClass("java/lang/AssertionError");
+          int ret = env->ThrowNew(errorClass, "JNI: AllocObject: allocation failed, but no exception thrown");
+          return NULL;
+        }
+        env->CallVoidMethod(action, methodId);        // action.run();
+        return obj;
+    }
+
+    JNIEXPORT jint JNICALL Java_ClassInitBarrier_00024Test_testGetFieldJNI(JNIEnv* env, jclass cls, jobject recv, jobject action) {
+        jint v = env->GetIntField(recv, test_A_f_id); // int v = recv.f;
+        env->CallVoidMethod(action, methodId);        // action.run();
+        return v;
+    }
+
+    JNIEXPORT void JNICALL Java_ClassInitBarrier_00024Test_testPutFieldJNI(JNIEnv* env, jclass cls, jobject recv, jobject action) {
+        env->SetIntField(recv, test_A_f_id, 1); // A.staticF = 1;
+        env->CallVoidMethod(action, methodId);  // action.run();
+    }
+
+    JNIEXPORT void JNICALL Java_ClassInitBarrier_00024Test_testInvokeVirtualJNI(JNIEnv* env, jclass cls, jobject recv, jobject action) {
+        env->CallVoidMethod(recv, test_A_m_id); // recv.m();
+        if (env->ExceptionOccurred()) {
+            return;
+        }
+        env->CallVoidMethod(action, methodId);  // action.run();
+    }
 }
Binary file test/jdk/sun/misc/ClassLoaderUtil/test.jar has changed