8077571: ObjPtrQueue is poorly named
Summary: Renamed to SATBMarkQueue and renamed files.
Reviewed-by: brutisso, tschatzl, dholmes, twisti
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfig.java Mon Nov 09 11:35:45 2015 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfig.java Fri Nov 06 16:30:40 2015 -0500
@@ -1063,7 +1063,7 @@
@HotSpotVMField(name = "JavaThread::_osthread", type = "OSThread*", get = HotSpotVMField.Type.OFFSET) @Stable public int osThreadOffset;
@HotSpotVMField(name = "JavaThread::_dirty_card_queue", type = "DirtyCardQueue", get = HotSpotVMField.Type.OFFSET) @Stable public int javaThreadDirtyCardQueueOffset;
@HotSpotVMField(name = "JavaThread::_is_method_handle_return", type = "int", get = HotSpotVMField.Type.OFFSET) @Stable public int threadIsMethodHandleReturnOffset;
- @HotSpotVMField(name = "JavaThread::_satb_mark_queue", type = "ObjPtrQueue", get = HotSpotVMField.Type.OFFSET) @Stable public int javaThreadSatbMarkQueueOffset;
+ @HotSpotVMField(name = "JavaThread::_satb_mark_queue", type = "SATBMarkQueue", get = HotSpotVMField.Type.OFFSET) @Stable public int javaThreadSatbMarkQueueOffset;
@HotSpotVMField(name = "JavaThread::_vm_result", type = "oop", get = HotSpotVMField.Type.OFFSET) @Stable public int threadObjectResultOffset;
@HotSpotVMField(name = "JavaThread::_jvmci_counters", type = "jlong*", get = HotSpotVMField.Type.OFFSET) @Stable public int jvmciCountersThreadOffset;
--- a/hotspot/src/share/vm/gc/g1/g1SATBCardTableModRefBS.cpp Mon Nov 09 11:35:45 2015 +0000
+++ b/hotspot/src/share/vm/gc/g1/g1SATBCardTableModRefBS.cpp Fri Nov 06 16:30:40 2015 -0500
@@ -26,7 +26,7 @@
#include "gc/g1/g1CollectedHeap.inline.hpp"
#include "gc/g1/g1SATBCardTableModRefBS.hpp"
#include "gc/g1/heapRegion.hpp"
-#include "gc/g1/satbQueue.hpp"
+#include "gc/g1/satbMarkQueue.hpp"
#include "gc/shared/memset_with_concurrent_readers.hpp"
#include "oops/oop.inline.hpp"
#include "runtime/atomic.inline.hpp"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/gc/g1/satbMarkQueue.cpp Fri Nov 06 16:30:40 2015 -0500
@@ -0,0 +1,370 @@
+/*
+ * Copyright (c) 2001, 2015, 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/g1CollectedHeap.inline.hpp"
+#include "gc/g1/satbMarkQueue.hpp"
+#include "gc/shared/collectedHeap.hpp"
+#include "memory/allocation.inline.hpp"
+#include "oops/oop.inline.hpp"
+#include "runtime/mutexLocker.hpp"
+#include "runtime/safepoint.hpp"
+#include "runtime/thread.hpp"
+#include "runtime/vmThread.hpp"
+
+SATBMarkQueue::SATBMarkQueue(SATBMarkQueueSet* qset, bool permanent) :
+ // SATB queues are only active during marking cycles. We create
+ // them with their active field set to false. If a thread is
+ // created during a cycle and its SATB queue needs to be activated
+ // before the thread starts running, we'll need to set its active
+ // field to true. This is done in JavaThread::initialize_queues().
+ PtrQueue(qset, permanent, false /* active */)
+{ }
+
+void SATBMarkQueue::flush() {
+ // Filter now to possibly save work later. If filtering empties the
+ // buffer then flush_impl can deallocate the buffer.
+ filter();
+ flush_impl();
+}
+
+// Return true if a SATB buffer entry refers to an object that
+// requires marking.
+//
+// The entry must point into the G1 heap. In particular, it must not
+// be a NULL pointer. NULL pointers are pre-filtered and never
+// inserted into a SATB buffer.
+//
+// An entry that is below the NTAMS pointer for the containing heap
+// region requires marking. Such an entry must point to a valid object.
+//
+// An entry that is at least the NTAMS pointer for the containing heap
+// region might be any of the following, none of which should be marked.
+//
+// * A reference to an object allocated since marking started.
+// According to SATB, such objects are implicitly kept live and do
+// not need to be dealt with via SATB buffer processing.
+//
+// * A reference to a young generation object. Young objects are
+// handled separately and are not marked by concurrent marking.
+//
+// * A stale reference to a young generation object. If a young
+// generation object reference is recorded and not filtered out
+// before being moved by a young collection, the reference becomes
+// stale.
+//
+// * A stale reference to an eagerly reclaimed humongous object. If a
+// humongous object is recorded and then reclaimed, the reference
+// becomes stale.
+//
+// The stale reference cases are implicitly handled by the NTAMS
+// comparison. Because of the possibility of stale references, buffer
+// processing must be somewhat circumspect and not assume entries
+// in an unfiltered buffer refer to valid objects.
+
+inline bool requires_marking(const void* entry, G1CollectedHeap* heap) {
+ // Includes rejection of NULL pointers.
+ assert(heap->is_in_reserved(entry),
+ "Non-heap pointer in SATB buffer: " PTR_FORMAT, p2i(entry));
+
+ HeapRegion* region = heap->heap_region_containing(entry);
+ assert(region != NULL, "No region for " PTR_FORMAT, p2i(entry));
+ if (entry >= region->next_top_at_mark_start()) {
+ return false;
+ }
+
+ assert(((oop)entry)->is_oop(true /* ignore mark word */),
+ "Invalid oop in SATB buffer: " PTR_FORMAT, p2i(entry));
+
+ return true;
+}
+
+// This method removes entries from a SATB buffer that will not be
+// useful to the concurrent marking threads. Entries are retained if
+// they require marking and are not already marked. Retained entries
+// are compacted toward the top of the buffer.
+
+void SATBMarkQueue::filter() {
+ G1CollectedHeap* g1h = G1CollectedHeap::heap();
+ void** buf = _buf;
+
+ if (buf == NULL) {
+ // nothing to do
+ return;
+ }
+
+ // Used for sanity checking at the end of the loop.
+ DEBUG_ONLY(size_t entries = 0; size_t retained = 0;)
+
+ assert(_index <= _sz, "invariant");
+ void** limit = &buf[byte_index_to_index(_index)];
+ void** src = &buf[byte_index_to_index(_sz)];
+ void** dst = src;
+
+ while (limit < src) {
+ DEBUG_ONLY(entries += 1;)
+ --src;
+ void* entry = *src;
+ // NULL the entry so that unused parts of the buffer contain NULLs
+ // at the end. If we are going to retain it we will copy it to its
+ // final place. If we have retained all entries we have visited so
+ // far, we'll just end up copying it to the same place.
+ *src = NULL;
+
+ if (requires_marking(entry, g1h) && !g1h->isMarkedNext((oop)entry)) {
+ --dst;
+ assert(*dst == NULL, "filtering destination should be clear");
+ *dst = entry;
+ DEBUG_ONLY(retained += 1;);
+ }
+ }
+ size_t new_index = pointer_delta(dst, buf, 1);
+
+#ifdef ASSERT
+ size_t entries_calc = (_sz - _index) / sizeof(void*);
+ assert(entries == entries_calc, "the number of entries we counted "
+ "should match the number of entries we calculated");
+ size_t retained_calc = (_sz - new_index) / sizeof(void*);
+ assert(retained == retained_calc, "the number of retained entries we counted "
+ "should match the number of retained entries we calculated");
+#endif // ASSERT
+
+ _index = new_index;
+}
+
+// This method will first apply the above filtering to the buffer. If
+// post-filtering a large enough chunk of the buffer has been cleared
+// we can re-use the buffer (instead of enqueueing it) and we can just
+// allow the mutator to carry on executing using the same buffer
+// instead of replacing it.
+
+bool SATBMarkQueue::should_enqueue_buffer() {
+ assert(_lock == NULL || _lock->owned_by_self(),
+ "we should have taken the lock before calling this");
+
+ // If G1SATBBufferEnqueueingThresholdPercent == 0 we could skip filtering.
+
+ // This method should only be called if there is a non-NULL buffer
+ // that is full.
+ assert(_index == 0, "pre-condition");
+ assert(_buf != NULL, "pre-condition");
+
+ filter();
+
+ size_t percent_used = ((_sz - _index) * 100) / _sz;
+ bool should_enqueue = percent_used > G1SATBBufferEnqueueingThresholdPercent;
+ return should_enqueue;
+}
+
+void SATBMarkQueue::apply_closure_and_empty(SATBBufferClosure* cl) {
+ assert(SafepointSynchronize::is_at_safepoint(),
+ "SATB queues must only be processed at safepoints");
+ if (_buf != NULL) {
+ assert(_index % sizeof(void*) == 0, "invariant");
+ assert(_sz % sizeof(void*) == 0, "invariant");
+ assert(_index <= _sz, "invariant");
+ cl->do_buffer(_buf + byte_index_to_index(_index),
+ byte_index_to_index(_sz - _index));
+ _index = _sz;
+ }
+}
+
+#ifndef PRODUCT
+// Helpful for debugging
+
+void SATBMarkQueue::print(const char* name) {
+ print(name, _buf, _index, _sz);
+}
+
+void SATBMarkQueue::print(const char* name,
+ void** buf, size_t index, size_t sz) {
+ gclog_or_tty->print_cr(" SATB BUFFER [%s] buf: " PTR_FORMAT " "
+ "index: " SIZE_FORMAT " sz: " SIZE_FORMAT,
+ name, p2i(buf), index, sz);
+}
+#endif // PRODUCT
+
+SATBMarkQueueSet::SATBMarkQueueSet() :
+ PtrQueueSet(),
+ _shared_satb_queue(this, true /* permanent */) { }
+
+void SATBMarkQueueSet::initialize(Monitor* cbl_mon, Mutex* fl_lock,
+ int process_completed_threshold,
+ Mutex* lock) {
+ PtrQueueSet::initialize(cbl_mon, fl_lock, process_completed_threshold, -1);
+ _shared_satb_queue.set_lock(lock);
+}
+
+void SATBMarkQueueSet::handle_zero_index_for_thread(JavaThread* t) {
+ t->satb_mark_queue().handle_zero_index();
+}
+
+#ifdef ASSERT
+void SATBMarkQueueSet::dump_active_states(bool expected_active) {
+ gclog_or_tty->print_cr("Expected SATB active state: %s",
+ expected_active ? "ACTIVE" : "INACTIVE");
+ gclog_or_tty->print_cr("Actual SATB active states:");
+ gclog_or_tty->print_cr(" Queue set: %s", is_active() ? "ACTIVE" : "INACTIVE");
+ for (JavaThread* t = Threads::first(); t; t = t->next()) {
+ gclog_or_tty->print_cr(" Thread \"%s\" queue: %s", t->name(),
+ t->satb_mark_queue().is_active() ? "ACTIVE" : "INACTIVE");
+ }
+ gclog_or_tty->print_cr(" Shared queue: %s",
+ shared_satb_queue()->is_active() ? "ACTIVE" : "INACTIVE");
+}
+
+void SATBMarkQueueSet::verify_active_states(bool expected_active) {
+ // Verify queue set state
+ if (is_active() != expected_active) {
+ dump_active_states(expected_active);
+ guarantee(false, "SATB queue set has an unexpected active state");
+ }
+
+ // Verify thread queue states
+ for (JavaThread* t = Threads::first(); t; t = t->next()) {
+ if (t->satb_mark_queue().is_active() != expected_active) {
+ dump_active_states(expected_active);
+ guarantee(false, "Thread SATB queue has an unexpected active state");
+ }
+ }
+
+ // Verify shared queue state
+ if (shared_satb_queue()->is_active() != expected_active) {
+ dump_active_states(expected_active);
+ guarantee(false, "Shared SATB queue has an unexpected active state");
+ }
+}
+#endif // ASSERT
+
+void SATBMarkQueueSet::set_active_all_threads(bool active, bool expected_active) {
+ assert(SafepointSynchronize::is_at_safepoint(), "Must be at safepoint.");
+#ifdef ASSERT
+ verify_active_states(expected_active);
+#endif // ASSERT
+ _all_active = active;
+ for (JavaThread* t = Threads::first(); t; t = t->next()) {
+ t->satb_mark_queue().set_active(active);
+ }
+ shared_satb_queue()->set_active(active);
+}
+
+void SATBMarkQueueSet::filter_thread_buffers() {
+ for(JavaThread* t = Threads::first(); t; t = t->next()) {
+ t->satb_mark_queue().filter();
+ }
+ shared_satb_queue()->filter();
+}
+
+bool SATBMarkQueueSet::apply_closure_to_completed_buffer(SATBBufferClosure* cl) {
+ BufferNode* nd = NULL;
+ {
+ MutexLockerEx x(_cbl_mon, Mutex::_no_safepoint_check_flag);
+ if (_completed_buffers_head != NULL) {
+ nd = _completed_buffers_head;
+ _completed_buffers_head = nd->next();
+ if (_completed_buffers_head == NULL) _completed_buffers_tail = NULL;
+ _n_completed_buffers--;
+ if (_n_completed_buffers == 0) _process_completed = false;
+ }
+ }
+ if (nd != NULL) {
+ void **buf = BufferNode::make_buffer_from_node(nd);
+ // Skip over NULL entries at beginning (e.g. push end) of buffer.
+ // Filtering can result in non-full completed buffers; see
+ // should_enqueue_buffer.
+ assert(_sz % sizeof(void*) == 0, "invariant");
+ size_t limit = SATBMarkQueue::byte_index_to_index(_sz);
+ for (size_t i = 0; i < limit; ++i) {
+ if (buf[i] != NULL) {
+ // Found the end of the block of NULLs; process the remainder.
+ cl->do_buffer(buf + i, limit - i);
+ break;
+ }
+ }
+ deallocate_buffer(buf);
+ return true;
+ } else {
+ return false;
+ }
+}
+
+#ifndef PRODUCT
+// Helpful for debugging
+
+#define SATB_PRINTER_BUFFER_SIZE 256
+
+void SATBMarkQueueSet::print_all(const char* msg) {
+ char buffer[SATB_PRINTER_BUFFER_SIZE];
+ assert(SafepointSynchronize::is_at_safepoint(), "Must be at safepoint.");
+
+ gclog_or_tty->cr();
+ gclog_or_tty->print_cr("SATB BUFFERS [%s]", msg);
+
+ BufferNode* nd = _completed_buffers_head;
+ int i = 0;
+ while (nd != NULL) {
+ void** buf = BufferNode::make_buffer_from_node(nd);
+ jio_snprintf(buffer, SATB_PRINTER_BUFFER_SIZE, "Enqueued: %d", i);
+ SATBMarkQueue::print(buffer, buf, 0, _sz);
+ nd = nd->next();
+ i += 1;
+ }
+
+ for (JavaThread* t = Threads::first(); t; t = t->next()) {
+ jio_snprintf(buffer, SATB_PRINTER_BUFFER_SIZE, "Thread: %s", t->name());
+ t->satb_mark_queue().print(buffer);
+ }
+
+ shared_satb_queue()->print("Shared");
+
+ gclog_or_tty->cr();
+}
+#endif // PRODUCT
+
+void SATBMarkQueueSet::abandon_partial_marking() {
+ BufferNode* buffers_to_delete = NULL;
+ {
+ MutexLockerEx x(_cbl_mon, Mutex::_no_safepoint_check_flag);
+ while (_completed_buffers_head != NULL) {
+ BufferNode* nd = _completed_buffers_head;
+ _completed_buffers_head = nd->next();
+ nd->set_next(buffers_to_delete);
+ buffers_to_delete = nd;
+ }
+ _completed_buffers_tail = NULL;
+ _n_completed_buffers = 0;
+ DEBUG_ONLY(assert_completed_buffer_list_len_correct_locked());
+ }
+ while (buffers_to_delete != NULL) {
+ BufferNode* nd = buffers_to_delete;
+ buffers_to_delete = nd->next();
+ deallocate_buffer(BufferNode::make_buffer_from_node(nd));
+ }
+ assert(SafepointSynchronize::is_at_safepoint(), "Must be at safepoint.");
+ // So we can safely manipulate these queues.
+ for (JavaThread* t = Threads::first(); t; t = t->next()) {
+ t->satb_mark_queue().reset();
+ }
+ shared_satb_queue()->reset();
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/gc/g1/satbMarkQueue.hpp Fri Nov 06 16:30:40 2015 -0500
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2001, 2015, 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_VM_GC_G1_SATBMARKQUEUE_HPP
+#define SHARE_VM_GC_G1_SATBMARKQUEUE_HPP
+
+#include "gc/g1/ptrQueue.hpp"
+#include "memory/allocation.hpp"
+
+class JavaThread;
+class SATBMarkQueueSet;
+
+// Base class for processing the contents of a SATB buffer.
+class SATBBufferClosure : public StackObj {
+protected:
+ ~SATBBufferClosure() { }
+
+public:
+ // Process the SATB entries in the designated buffer range.
+ virtual void do_buffer(void** buffer, size_t size) = 0;
+};
+
+// A PtrQueue whose elements are (possibly stale) pointers to object heads.
+class SATBMarkQueue: public PtrQueue {
+ friend class SATBMarkQueueSet;
+
+private:
+ // Filter out unwanted entries from the buffer.
+ void filter();
+
+public:
+ SATBMarkQueue(SATBMarkQueueSet* qset, bool permanent = false);
+
+ // Process queue entries and free resources.
+ void flush();
+
+ // Apply cl to the active part of the buffer.
+ // Prerequisite: Must be at a safepoint.
+ void apply_closure_and_empty(SATBBufferClosure* cl);
+
+ // Overrides PtrQueue::should_enqueue_buffer(). See the method's
+ // definition for more information.
+ virtual bool should_enqueue_buffer();
+
+#ifndef PRODUCT
+ // Helpful for debugging
+ void print(const char* name);
+ static void print(const char* name, void** buf, size_t index, size_t sz);
+#endif // PRODUCT
+};
+
+class SATBMarkQueueSet: public PtrQueueSet {
+ SATBMarkQueue _shared_satb_queue;
+
+#ifdef ASSERT
+ void dump_active_states(bool expected_active);
+ void verify_active_states(bool expected_active);
+#endif // ASSERT
+
+public:
+ SATBMarkQueueSet();
+
+ void initialize(Monitor* cbl_mon, Mutex* fl_lock,
+ int process_completed_threshold,
+ Mutex* lock);
+
+ static void handle_zero_index_for_thread(JavaThread* t);
+
+ // Apply "set_active(active)" to all SATB queues in the set. It should be
+ // called only with the world stopped. The method will assert that the
+ // SATB queues of all threads it visits, as well as the SATB queue
+ // set itself, has an active value same as expected_active.
+ void set_active_all_threads(bool active, bool expected_active);
+
+ // Filter all the currently-active SATB buffers.
+ void filter_thread_buffers();
+
+ // If there exists some completed buffer, pop and process it, and
+ // return true. Otherwise return false. Processing a buffer
+ // consists of applying the closure to the buffer range starting
+ // with the first non-NULL entry to the end of the buffer; the
+ // leading entries may be NULL due to filtering.
+ bool apply_closure_to_completed_buffer(SATBBufferClosure* cl);
+
+#ifndef PRODUCT
+ // Helpful for debugging
+ void print_all(const char* msg);
+#endif // PRODUCT
+
+ SATBMarkQueue* shared_satb_queue() { return &_shared_satb_queue; }
+
+ // If a marking is being abandoned, reset any unprocessed log buffers.
+ void abandon_partial_marking();
+};
+
+#endif // SHARE_VM_GC_G1_SATBMARKQUEUE_HPP
--- a/hotspot/src/share/vm/gc/g1/satbQueue.cpp Mon Nov 09 11:35:45 2015 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,370 +0,0 @@
-/*
- * Copyright (c) 2001, 2015, 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/g1CollectedHeap.inline.hpp"
-#include "gc/g1/satbQueue.hpp"
-#include "gc/shared/collectedHeap.hpp"
-#include "memory/allocation.inline.hpp"
-#include "oops/oop.inline.hpp"
-#include "runtime/mutexLocker.hpp"
-#include "runtime/safepoint.hpp"
-#include "runtime/thread.hpp"
-#include "runtime/vmThread.hpp"
-
-ObjPtrQueue::ObjPtrQueue(SATBMarkQueueSet* qset, bool permanent) :
- // SATB queues are only active during marking cycles. We create
- // them with their active field set to false. If a thread is
- // created during a cycle and its SATB queue needs to be activated
- // before the thread starts running, we'll need to set its active
- // field to true. This is done in JavaThread::initialize_queues().
- PtrQueue(qset, permanent, false /* active */)
-{ }
-
-void ObjPtrQueue::flush() {
- // Filter now to possibly save work later. If filtering empties the
- // buffer then flush_impl can deallocate the buffer.
- filter();
- flush_impl();
-}
-
-// Return true if a SATB buffer entry refers to an object that
-// requires marking.
-//
-// The entry must point into the G1 heap. In particular, it must not
-// be a NULL pointer. NULL pointers are pre-filtered and never
-// inserted into a SATB buffer.
-//
-// An entry that is below the NTAMS pointer for the containing heap
-// region requires marking. Such an entry must point to a valid object.
-//
-// An entry that is at least the NTAMS pointer for the containing heap
-// region might be any of the following, none of which should be marked.
-//
-// * A reference to an object allocated since marking started.
-// According to SATB, such objects are implicitly kept live and do
-// not need to be dealt with via SATB buffer processing.
-//
-// * A reference to a young generation object. Young objects are
-// handled separately and are not marked by concurrent marking.
-//
-// * A stale reference to a young generation object. If a young
-// generation object reference is recorded and not filtered out
-// before being moved by a young collection, the reference becomes
-// stale.
-//
-// * A stale reference to an eagerly reclaimed humongous object. If a
-// humongous object is recorded and then reclaimed, the reference
-// becomes stale.
-//
-// The stale reference cases are implicitly handled by the NTAMS
-// comparison. Because of the possibility of stale references, buffer
-// processing must be somewhat circumspect and not assume entries
-// in an unfiltered buffer refer to valid objects.
-
-inline bool requires_marking(const void* entry, G1CollectedHeap* heap) {
- // Includes rejection of NULL pointers.
- assert(heap->is_in_reserved(entry),
- "Non-heap pointer in SATB buffer: " PTR_FORMAT, p2i(entry));
-
- HeapRegion* region = heap->heap_region_containing(entry);
- assert(region != NULL, "No region for " PTR_FORMAT, p2i(entry));
- if (entry >= region->next_top_at_mark_start()) {
- return false;
- }
-
- assert(((oop)entry)->is_oop(true /* ignore mark word */),
- "Invalid oop in SATB buffer: " PTR_FORMAT, p2i(entry));
-
- return true;
-}
-
-// This method removes entries from a SATB buffer that will not be
-// useful to the concurrent marking threads. Entries are retained if
-// they require marking and are not already marked. Retained entries
-// are compacted toward the top of the buffer.
-
-void ObjPtrQueue::filter() {
- G1CollectedHeap* g1h = G1CollectedHeap::heap();
- void** buf = _buf;
-
- if (buf == NULL) {
- // nothing to do
- return;
- }
-
- // Used for sanity checking at the end of the loop.
- DEBUG_ONLY(size_t entries = 0; size_t retained = 0;)
-
- assert(_index <= _sz, "invariant");
- void** limit = &buf[byte_index_to_index(_index)];
- void** src = &buf[byte_index_to_index(_sz)];
- void** dst = src;
-
- while (limit < src) {
- DEBUG_ONLY(entries += 1;)
- --src;
- void* entry = *src;
- // NULL the entry so that unused parts of the buffer contain NULLs
- // at the end. If we are going to retain it we will copy it to its
- // final place. If we have retained all entries we have visited so
- // far, we'll just end up copying it to the same place.
- *src = NULL;
-
- if (requires_marking(entry, g1h) && !g1h->isMarkedNext((oop)entry)) {
- --dst;
- assert(*dst == NULL, "filtering destination should be clear");
- *dst = entry;
- DEBUG_ONLY(retained += 1;);
- }
- }
- size_t new_index = pointer_delta(dst, buf, 1);
-
-#ifdef ASSERT
- size_t entries_calc = (_sz - _index) / sizeof(void*);
- assert(entries == entries_calc, "the number of entries we counted "
- "should match the number of entries we calculated");
- size_t retained_calc = (_sz - new_index) / sizeof(void*);
- assert(retained == retained_calc, "the number of retained entries we counted "
- "should match the number of retained entries we calculated");
-#endif // ASSERT
-
- _index = new_index;
-}
-
-// This method will first apply the above filtering to the buffer. If
-// post-filtering a large enough chunk of the buffer has been cleared
-// we can re-use the buffer (instead of enqueueing it) and we can just
-// allow the mutator to carry on executing using the same buffer
-// instead of replacing it.
-
-bool ObjPtrQueue::should_enqueue_buffer() {
- assert(_lock == NULL || _lock->owned_by_self(),
- "we should have taken the lock before calling this");
-
- // If G1SATBBufferEnqueueingThresholdPercent == 0 we could skip filtering.
-
- // This method should only be called if there is a non-NULL buffer
- // that is full.
- assert(_index == 0, "pre-condition");
- assert(_buf != NULL, "pre-condition");
-
- filter();
-
- size_t percent_used = ((_sz - _index) * 100) / _sz;
- bool should_enqueue = percent_used > G1SATBBufferEnqueueingThresholdPercent;
- return should_enqueue;
-}
-
-void ObjPtrQueue::apply_closure_and_empty(SATBBufferClosure* cl) {
- assert(SafepointSynchronize::is_at_safepoint(),
- "SATB queues must only be processed at safepoints");
- if (_buf != NULL) {
- assert(_index % sizeof(void*) == 0, "invariant");
- assert(_sz % sizeof(void*) == 0, "invariant");
- assert(_index <= _sz, "invariant");
- cl->do_buffer(_buf + byte_index_to_index(_index),
- byte_index_to_index(_sz - _index));
- _index = _sz;
- }
-}
-
-#ifndef PRODUCT
-// Helpful for debugging
-
-void ObjPtrQueue::print(const char* name) {
- print(name, _buf, _index, _sz);
-}
-
-void ObjPtrQueue::print(const char* name,
- void** buf, size_t index, size_t sz) {
- gclog_or_tty->print_cr(" SATB BUFFER [%s] buf: " PTR_FORMAT " "
- "index: " SIZE_FORMAT " sz: " SIZE_FORMAT,
- name, p2i(buf), index, sz);
-}
-#endif // PRODUCT
-
-SATBMarkQueueSet::SATBMarkQueueSet() :
- PtrQueueSet(),
- _shared_satb_queue(this, true /* permanent */) { }
-
-void SATBMarkQueueSet::initialize(Monitor* cbl_mon, Mutex* fl_lock,
- int process_completed_threshold,
- Mutex* lock) {
- PtrQueueSet::initialize(cbl_mon, fl_lock, process_completed_threshold, -1);
- _shared_satb_queue.set_lock(lock);
-}
-
-void SATBMarkQueueSet::handle_zero_index_for_thread(JavaThread* t) {
- t->satb_mark_queue().handle_zero_index();
-}
-
-#ifdef ASSERT
-void SATBMarkQueueSet::dump_active_states(bool expected_active) {
- gclog_or_tty->print_cr("Expected SATB active state: %s",
- expected_active ? "ACTIVE" : "INACTIVE");
- gclog_or_tty->print_cr("Actual SATB active states:");
- gclog_or_tty->print_cr(" Queue set: %s", is_active() ? "ACTIVE" : "INACTIVE");
- for (JavaThread* t = Threads::first(); t; t = t->next()) {
- gclog_or_tty->print_cr(" Thread \"%s\" queue: %s", t->name(),
- t->satb_mark_queue().is_active() ? "ACTIVE" : "INACTIVE");
- }
- gclog_or_tty->print_cr(" Shared queue: %s",
- shared_satb_queue()->is_active() ? "ACTIVE" : "INACTIVE");
-}
-
-void SATBMarkQueueSet::verify_active_states(bool expected_active) {
- // Verify queue set state
- if (is_active() != expected_active) {
- dump_active_states(expected_active);
- guarantee(false, "SATB queue set has an unexpected active state");
- }
-
- // Verify thread queue states
- for (JavaThread* t = Threads::first(); t; t = t->next()) {
- if (t->satb_mark_queue().is_active() != expected_active) {
- dump_active_states(expected_active);
- guarantee(false, "Thread SATB queue has an unexpected active state");
- }
- }
-
- // Verify shared queue state
- if (shared_satb_queue()->is_active() != expected_active) {
- dump_active_states(expected_active);
- guarantee(false, "Shared SATB queue has an unexpected active state");
- }
-}
-#endif // ASSERT
-
-void SATBMarkQueueSet::set_active_all_threads(bool active, bool expected_active) {
- assert(SafepointSynchronize::is_at_safepoint(), "Must be at safepoint.");
-#ifdef ASSERT
- verify_active_states(expected_active);
-#endif // ASSERT
- _all_active = active;
- for (JavaThread* t = Threads::first(); t; t = t->next()) {
- t->satb_mark_queue().set_active(active);
- }
- shared_satb_queue()->set_active(active);
-}
-
-void SATBMarkQueueSet::filter_thread_buffers() {
- for(JavaThread* t = Threads::first(); t; t = t->next()) {
- t->satb_mark_queue().filter();
- }
- shared_satb_queue()->filter();
-}
-
-bool SATBMarkQueueSet::apply_closure_to_completed_buffer(SATBBufferClosure* cl) {
- BufferNode* nd = NULL;
- {
- MutexLockerEx x(_cbl_mon, Mutex::_no_safepoint_check_flag);
- if (_completed_buffers_head != NULL) {
- nd = _completed_buffers_head;
- _completed_buffers_head = nd->next();
- if (_completed_buffers_head == NULL) _completed_buffers_tail = NULL;
- _n_completed_buffers--;
- if (_n_completed_buffers == 0) _process_completed = false;
- }
- }
- if (nd != NULL) {
- void **buf = BufferNode::make_buffer_from_node(nd);
- // Skip over NULL entries at beginning (e.g. push end) of buffer.
- // Filtering can result in non-full completed buffers; see
- // should_enqueue_buffer.
- assert(_sz % sizeof(void*) == 0, "invariant");
- size_t limit = ObjPtrQueue::byte_index_to_index(_sz);
- for (size_t i = 0; i < limit; ++i) {
- if (buf[i] != NULL) {
- // Found the end of the block of NULLs; process the remainder.
- cl->do_buffer(buf + i, limit - i);
- break;
- }
- }
- deallocate_buffer(buf);
- return true;
- } else {
- return false;
- }
-}
-
-#ifndef PRODUCT
-// Helpful for debugging
-
-#define SATB_PRINTER_BUFFER_SIZE 256
-
-void SATBMarkQueueSet::print_all(const char* msg) {
- char buffer[SATB_PRINTER_BUFFER_SIZE];
- assert(SafepointSynchronize::is_at_safepoint(), "Must be at safepoint.");
-
- gclog_or_tty->cr();
- gclog_or_tty->print_cr("SATB BUFFERS [%s]", msg);
-
- BufferNode* nd = _completed_buffers_head;
- int i = 0;
- while (nd != NULL) {
- void** buf = BufferNode::make_buffer_from_node(nd);
- jio_snprintf(buffer, SATB_PRINTER_BUFFER_SIZE, "Enqueued: %d", i);
- ObjPtrQueue::print(buffer, buf, 0, _sz);
- nd = nd->next();
- i += 1;
- }
-
- for (JavaThread* t = Threads::first(); t; t = t->next()) {
- jio_snprintf(buffer, SATB_PRINTER_BUFFER_SIZE, "Thread: %s", t->name());
- t->satb_mark_queue().print(buffer);
- }
-
- shared_satb_queue()->print("Shared");
-
- gclog_or_tty->cr();
-}
-#endif // PRODUCT
-
-void SATBMarkQueueSet::abandon_partial_marking() {
- BufferNode* buffers_to_delete = NULL;
- {
- MutexLockerEx x(_cbl_mon, Mutex::_no_safepoint_check_flag);
- while (_completed_buffers_head != NULL) {
- BufferNode* nd = _completed_buffers_head;
- _completed_buffers_head = nd->next();
- nd->set_next(buffers_to_delete);
- buffers_to_delete = nd;
- }
- _completed_buffers_tail = NULL;
- _n_completed_buffers = 0;
- DEBUG_ONLY(assert_completed_buffer_list_len_correct_locked());
- }
- while (buffers_to_delete != NULL) {
- BufferNode* nd = buffers_to_delete;
- buffers_to_delete = nd->next();
- deallocate_buffer(BufferNode::make_buffer_from_node(nd));
- }
- assert(SafepointSynchronize::is_at_safepoint(), "Must be at safepoint.");
- // So we can safely manipulate these queues.
- for (JavaThread* t = Threads::first(); t; t = t->next()) {
- t->satb_mark_queue().reset();
- }
- shared_satb_queue()->reset();
-}
--- a/hotspot/src/share/vm/gc/g1/satbQueue.hpp Mon Nov 09 11:35:45 2015 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,117 +0,0 @@
-/*
- * Copyright (c) 2001, 2015, 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_VM_GC_G1_SATBQUEUE_HPP
-#define SHARE_VM_GC_G1_SATBQUEUE_HPP
-
-#include "gc/g1/ptrQueue.hpp"
-#include "memory/allocation.hpp"
-
-class JavaThread;
-class SATBMarkQueueSet;
-
-// Base class for processing the contents of a SATB buffer.
-class SATBBufferClosure : public StackObj {
-protected:
- ~SATBBufferClosure() { }
-
-public:
- // Process the SATB entries in the designated buffer range.
- virtual void do_buffer(void** buffer, size_t size) = 0;
-};
-
-// A ptrQueue whose elements are "oops", pointers to object heads.
-class ObjPtrQueue: public PtrQueue {
- friend class SATBMarkQueueSet;
-
-private:
- // Filter out unwanted entries from the buffer.
- void filter();
-
-public:
- ObjPtrQueue(SATBMarkQueueSet* qset, bool permanent = false);
-
- // Process queue entries and free resources.
- void flush();
-
- // Apply cl to the active part of the buffer.
- // Prerequisite: Must be at a safepoint.
- void apply_closure_and_empty(SATBBufferClosure* cl);
-
- // Overrides PtrQueue::should_enqueue_buffer(). See the method's
- // definition for more information.
- virtual bool should_enqueue_buffer();
-
-#ifndef PRODUCT
- // Helpful for debugging
- void print(const char* name);
- static void print(const char* name, void** buf, size_t index, size_t sz);
-#endif // PRODUCT
-};
-
-class SATBMarkQueueSet: public PtrQueueSet {
- ObjPtrQueue _shared_satb_queue;
-
-#ifdef ASSERT
- void dump_active_states(bool expected_active);
- void verify_active_states(bool expected_active);
-#endif // ASSERT
-
-public:
- SATBMarkQueueSet();
-
- void initialize(Monitor* cbl_mon, Mutex* fl_lock,
- int process_completed_threshold,
- Mutex* lock);
-
- static void handle_zero_index_for_thread(JavaThread* t);
-
- // Apply "set_active(active)" to all SATB queues in the set. It should be
- // called only with the world stopped. The method will assert that the
- // SATB queues of all threads it visits, as well as the SATB queue
- // set itself, has an active value same as expected_active.
- void set_active_all_threads(bool active, bool expected_active);
-
- // Filter all the currently-active SATB buffers.
- void filter_thread_buffers();
-
- // If there exists some completed buffer, pop and process it, and
- // return true. Otherwise return false. Processing a buffer
- // consists of applying the closure to the buffer range starting
- // with the first non-NULL entry to the end of the buffer; the
- // leading entries may be NULL due to filtering.
- bool apply_closure_to_completed_buffer(SATBBufferClosure* cl);
-
-#ifndef PRODUCT
- // Helpful for debugging
- void print_all(const char* msg);
-#endif // PRODUCT
-
- ObjPtrQueue* shared_satb_queue() { return &_shared_satb_queue; }
-
- // If a marking is being abandoned, reset any unprocessed log buffers.
- void abandon_partial_marking();
-};
-
-#endif // SHARE_VM_GC_G1_SATBQUEUE_HPP
--- a/hotspot/src/share/vm/precompiled/precompiled.hpp Mon Nov 09 11:35:45 2015 +0000
+++ b/hotspot/src/share/vm/precompiled/precompiled.hpp Fri Nov 06 16:30:40 2015 -0500
@@ -304,7 +304,7 @@
# include "gc/g1/g1OopClosures.hpp"
# include "gc/g1/g1_globals.hpp"
# include "gc/g1/ptrQueue.hpp"
-# include "gc/g1/satbQueue.hpp"
+# include "gc/g1/satbMarkQueue.hpp"
# include "gc/parallel/gcAdaptivePolicyCounters.hpp"
# include "gc/parallel/objectStartArray.hpp"
# include "gc/parallel/parMarkBitMap.hpp"
--- a/hotspot/src/share/vm/runtime/thread.cpp Mon Nov 09 11:35:45 2015 +0000
+++ b/hotspot/src/share/vm/runtime/thread.cpp Fri Nov 06 16:30:40 2015 -0500
@@ -1938,7 +1938,7 @@
assert(!SafepointSynchronize::is_at_safepoint(),
"we should not be at a safepoint");
- ObjPtrQueue& satb_queue = satb_mark_queue();
+ SATBMarkQueue& satb_queue = satb_mark_queue();
SATBMarkQueueSet& satb_queue_set = satb_mark_queue_set();
// The SATB queue should have been constructed with its active
// field set to false.
--- a/hotspot/src/share/vm/runtime/thread.hpp Mon Nov 09 11:35:45 2015 +0000
+++ b/hotspot/src/share/vm/runtime/thread.hpp Fri Nov 06 16:30:40 2015 -0500
@@ -49,7 +49,7 @@
#include "utilities/top.hpp"
#if INCLUDE_ALL_GCS
#include "gc/g1/dirtyCardQueue.hpp"
-#include "gc/g1/satbQueue.hpp"
+#include "gc/g1/satbMarkQueue.hpp"
#endif // INCLUDE_ALL_GCS
#ifdef TARGET_ARCH_zero
# include "stack_zero.hpp"
@@ -992,7 +992,7 @@
#if INCLUDE_ALL_GCS
// Support for G1 barriers
- ObjPtrQueue _satb_mark_queue; // Thread-local log for SATB barrier.
+ SATBMarkQueue _satb_mark_queue; // Thread-local log for SATB barrier.
// Set of all such queues.
static SATBMarkQueueSet _satb_mark_queue_set;
@@ -1727,7 +1727,7 @@
#if INCLUDE_ALL_GCS
// SATB marking queue support
- ObjPtrQueue& satb_mark_queue() { return _satb_mark_queue; }
+ SATBMarkQueue& satb_mark_queue() { return _satb_mark_queue; }
static SATBMarkQueueSet& satb_mark_queue_set() {
return _satb_mark_queue_set;
}
--- a/hotspot/src/share/vm/runtime/vmStructs.cpp Mon Nov 09 11:35:45 2015 +0000
+++ b/hotspot/src/share/vm/runtime/vmStructs.cpp Fri Nov 06 16:30:40 2015 -0500
@@ -1030,7 +1030,7 @@
nonstatic_field(JavaThread, _stack_size, size_t) \
nonstatic_field(JavaThread, _vframe_array_head, vframeArray*) \
nonstatic_field(JavaThread, _vframe_array_last, vframeArray*) \
- nonstatic_field(JavaThread, _satb_mark_queue, ObjPtrQueue) \
+ nonstatic_field(JavaThread, _satb_mark_queue, SATBMarkQueue) \
nonstatic_field(JavaThread, _dirty_card_queue, DirtyCardQueue) \
nonstatic_field(Thread, _resource_area, ResourceArea*) \
nonstatic_field(CompilerThread, _env, ciEnv*) \
@@ -1622,7 +1622,7 @@
declare_toplevel_type(MemRegion) \
declare_toplevel_type(ThreadLocalAllocBuffer) \
declare_toplevel_type(VirtualSpace) \
- declare_toplevel_type(ObjPtrQueue) \
+ declare_toplevel_type(SATBMarkQueue) \
declare_toplevel_type(DirtyCardQueue) \
\
/* Pointers to Garbage Collection types */ \