8219468: ZGC: Extract iteration functionality into a new ZNMethodTableIteration class
authorstefank
Wed, 20 Feb 2019 12:04:12 +0100
changeset 53893 ad56513c7e07
parent 53892 33790c8e4647
child 53894 bf1133e7dfba
8219468: ZGC: Extract iteration functionality into a new ZNMethodTableIteration class Reviewed-by: pliden
src/hotspot/share/gc/z/zNMethodTable.cpp
src/hotspot/share/gc/z/zNMethodTable.hpp
src/hotspot/share/gc/z/zNMethodTableIteration.cpp
src/hotspot/share/gc/z/zNMethodTableIteration.hpp
--- a/src/hotspot/share/gc/z/zNMethodTable.cpp	Wed Feb 20 11:42:49 2019 +0100
+++ b/src/hotspot/share/gc/z/zNMethodTable.cpp	Wed Feb 20 12:04:12 2019 +0100
@@ -33,6 +33,7 @@
 #include "gc/z/zNMethodAllocator.hpp"
 #include "gc/z/zNMethodData.hpp"
 #include "gc/z/zNMethodTable.hpp"
+#include "gc/z/zNMethodTableIteration.hpp"
 #include "gc/z/zOopClosures.inline.hpp"
 #include "gc/z/zTask.hpp"
 #include "gc/z/zWorkers.hpp"
@@ -46,11 +47,9 @@
 
 ZNMethodTableEntry* ZNMethodTable::_table = NULL;
 size_t ZNMethodTable::_size = 0;
-ZNMethodTableEntry* ZNMethodTable::_iter_table = NULL;
-size_t ZNMethodTable::_iter_table_size = 0;
 size_t ZNMethodTable::_nregistered = 0;
 size_t ZNMethodTable::_nunregistered = 0;
-volatile size_t ZNMethodTable::_claimed = 0;
+ZNMethodTableIteration ZNMethodTable::_iteration;
 
 static ZNMethodData* gc_data(const nmethod* nm) {
   return nm->gc_data<ZNMethodData>();
@@ -60,6 +59,15 @@
   return nm->set_gc_data<ZNMethodData>(data);
 }
 
+ZNMethodTableEntry* ZNMethodTable::create(size_t size) {
+  void* const mem = ZNMethodAllocator::allocate(size * sizeof(ZNMethodTableEntry));
+  return ::new (mem) ZNMethodTableEntry[size];
+}
+
+void ZNMethodTable::destroy(ZNMethodTableEntry* table) {
+  ZNMethodAllocator::free(table);
+}
+
 void ZNMethodTable::attach_gc_data(nmethod* nm) {
   GrowableArray<oop*> immediate_oops;
   bool non_immediate_oops = false;
@@ -182,7 +190,7 @@
                          _nunregistered, percent_of(_nunregistered, _size), 0.0);
 
   // Allocate new table
-  ZNMethodTableEntry* const new_table = new ZNMethodTableEntry[new_size];
+  ZNMethodTableEntry* const new_table = ZNMethodTable::create(new_size);
 
   // Transfer all registered entries
   for (size_t i = 0; i < _size; i++) {
@@ -192,10 +200,8 @@
     }
   }
 
-  if (_iter_table != _table) {
-    // Delete old table
-    delete [] _table;
-  }
+  // Free old table
+  ZNMethodTable::destroy(_table);
 
   // Install new table
   _table = new_table;
@@ -323,7 +329,7 @@
 void ZNMethodTable::wait_until_iteration_done() {
   assert(CodeCache_lock->owned_by_self(), "Lock must be held");
 
-  while (_iter_table != NULL) {
+  while (_iteration.in_progress()) {
     CodeCache_lock->wait(Monitor::_no_safepoint_check_flag);
   }
 }
@@ -363,21 +369,14 @@
   ZNMethodAllocator::activate_deferred_frees();
 
   // Prepare iteration
-  _iter_table = _table;
-  _iter_table_size = _size;
-  _claimed = 0;
+  _iteration.nmethods_do_begin(_table, _size);
 }
 
 void ZNMethodTable::nmethods_do_end() {
   MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
 
   // Finish iteration
-  if (_iter_table != _table) {
-    delete [] _iter_table;
-  }
-  _iter_table = NULL;
-
-  assert(_claimed >= _iter_table_size, "Failed to claim all table entries");
+  _iteration.nmethods_do_end();
 
   // Process deferred frees
   ZNMethodAllocator::deactivate_and_process_deferred_frees();
@@ -436,25 +435,7 @@
 }
 
 void ZNMethodTable::nmethods_do(NMethodClosure* cl) {
-  for (;;) {
-    // Claim table partition. Each partition is currently sized to span
-    // two cache lines. This number is just a guess, but seems to work well.
-    const size_t partition_size = (ZCacheLineSize * 2) / sizeof(ZNMethodTableEntry);
-    const size_t partition_start = MIN2(Atomic::add(partition_size, &_claimed) - partition_size, _iter_table_size);
-    const size_t partition_end = MIN2(partition_start + partition_size, _iter_table_size);
-    if (partition_start == partition_end) {
-      // End of table
-      break;
-    }
-
-    // Process table partition
-    for (size_t i = partition_start; i < partition_end; i++) {
-      const ZNMethodTableEntry entry = _iter_table[i];
-      if (entry.registered()) {
-        cl->do_nmethod(entry.method());
-      }
-    }
-  }
+  _iteration.nmethods_do(cl);
 }
 
 class ZNMethodTableUnlinkClosure : public NMethodClosure {
--- a/src/hotspot/share/gc/z/zNMethodTable.hpp	Wed Feb 20 11:42:49 2019 +0100
+++ b/src/hotspot/share/gc/z/zNMethodTable.hpp	Wed Feb 20 12:04:12 2019 +0100
@@ -28,8 +28,10 @@
 #include "gc/z/zGlobals.hpp"
 #include "gc/z/zLock.hpp"
 #include "gc/z/zNMethodTableEntry.hpp"
+#include "gc/z/zNMethodTableIteration.hpp"
 #include "memory/allocation.hpp"
 
+class nmethod;
 class NMethodClosure;
 class ZNMethodData;
 class ZNMethodDataOops;
@@ -37,13 +39,14 @@
 
 class ZNMethodTable : public AllStatic {
 private:
-  static ZNMethodTableEntry* _table;
-  static size_t              _size;
-  static ZNMethodTableEntry* _iter_table;
-  static size_t              _iter_table_size;
-  static size_t              _nregistered;
-  static size_t              _nunregistered;
-  static volatile size_t     _claimed ATTRIBUTE_ALIGNED(ZCacheLineSize);
+  static ZNMethodTableEntry*    _table;
+  static size_t                 _size;
+  static size_t                 _nregistered;
+  static size_t                 _nunregistered;
+  static ZNMethodTableIteration _iteration;
+
+  static ZNMethodTableEntry* create(size_t size);
+  static void destroy(ZNMethodTableEntry* table);
 
   static void attach_gc_data(nmethod* nm);
   static void detach_gc_data(nmethod* nm);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/z/zNMethodTableIteration.cpp	Wed Feb 20 12:04:12 2019 +0100
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2017, 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/z/zNMethodTableEntry.hpp"
+#include "gc/z/zNMethodTableIteration.hpp"
+#include "memory/iterator.hpp"
+#include "runtime/atomic.hpp"
+#include "utilities/debug.hpp"
+#include "utilities/globalDefinitions.hpp"
+
+ZNMethodTableIteration::ZNMethodTableIteration() :
+    _table(NULL),
+    _size(0),
+    _claimed(0) {}
+
+bool ZNMethodTableIteration::in_progress() const {
+  return _table != NULL;
+}
+
+void ZNMethodTableIteration::nmethods_do_begin(ZNMethodTableEntry* table, size_t size) {
+  assert(!in_progress(), "precondition");
+
+  _table = table;
+  _size = size;
+  _claimed = 0;
+}
+
+void ZNMethodTableIteration::nmethods_do_end() {
+  assert(_claimed >= _size, "Failed to claim all table entries");
+
+  // Finish iteration
+  _table = NULL;
+}
+
+void ZNMethodTableIteration::nmethods_do(NMethodClosure* cl) {
+  for (;;) {
+    // Claim table partition. Each partition is currently sized to span
+    // two cache lines. This number is just a guess, but seems to work well.
+    const size_t partition_size = (ZCacheLineSize * 2) / sizeof(ZNMethodTableEntry);
+    const size_t partition_start = MIN2(Atomic::add(partition_size, &_claimed) - partition_size, _size);
+    const size_t partition_end = MIN2(partition_start + partition_size, _size);
+    if (partition_start == partition_end) {
+      // End of table
+      break;
+    }
+
+    // Process table partition
+    for (size_t i = partition_start; i < partition_end; i++) {
+      const ZNMethodTableEntry entry = _table[i];
+      if (entry.registered()) {
+        cl->do_nmethod(entry.method());
+      }
+    }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/z/zNMethodTableIteration.hpp	Wed Feb 20 12:04:12 2019 +0100
@@ -0,0 +1,48 @@
+/*
+ * 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_Z_ZNMETHODTABLEITERATION_HPP
+#define SHARE_GC_Z_ZNMETHODTABLEITERATION_HPP
+
+#include "gc/z/zGlobals.hpp"
+
+class NMethodClosure;
+class ZNMethodTableEntry;
+
+class ZNMethodTableIteration {
+private:
+  ZNMethodTableEntry* _table;
+  size_t              _size;
+  volatile size_t     _claimed ATTRIBUTE_ALIGNED(ZCacheLineSize);
+
+public:
+  ZNMethodTableIteration();
+
+  bool in_progress() const;
+
+  void nmethods_do_begin(ZNMethodTableEntry* table, size_t size);
+  void nmethods_do_end();
+  void nmethods_do(NMethodClosure* cl);
+};
+
+#endif // SHARE_GC_Z_ZNMETHODTABLEITERATION_HPP