/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* 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_implementation/g1/g1CollectedHeap.inline.hpp"
#include "gc_implementation/g1/satbQueue.hpp"
#include "memory/allocation.inline.hpp"
#include "memory/sharedHeap.hpp"
#include "runtime/mutexLocker.hpp"
#include "runtime/thread.hpp"
#include "runtime/vmThread.hpp"
// The buffer might contain refs into the CSet. We have to filter it
// first before we flush it, otherwise we might end up with an
// enqueued buffer with refs into the CSet which breaks our invariants.
filter();
}
// This method removes entries from an SATB buffer that will not be
// useful to the concurrent marking threads. An entry is removed if it
// satisfies one of the following conditions:
//
// * it points to an object outside the G1 heap (G1's concurrent
// marking only visits objects inside the G1 heap),
// * it points to an object that has been allocated since marking
// started (according to SATB those objects do not need to be
// visited during marking), or
// * it points to an object that has already been marked (no need to
// process it again).
//
// The rest of the entries will be retained and are compacted towards
// the top of the buffer. Note that, because we do not allow old
// regions in the CSet during marking, all objects on the CSet regions
// are young (eden or survivors) and therefore implicitly live. So any
// references into the CSet will be removed during filtering.
// nothing to do
return;
}
// Used for sanity checking at the end of the loop.
while (i > _index) {
assert(i > 0, "we should have at least one more entry to process");
i -= oopSize;
// 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.
*p = NULL;
if (retain) {
"new_index should never be below i, as we alwaysr compact 'up'");
"the source as we always compact 'up'");
"we should have already cleared the destination location");
}
}
#ifdef ASSERT
"should match the number of entries we calculated");
"should match the number of retained entries we calculated");
#endif // ASSERT
}
// 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.
"we should have taken the lock before calling this");
// Even if G1SATBBufferEnqueueingThresholdPercent == 0 we have to
// filter the buffer given that this will remove any references into
// the CSet as we currently assume that no such refs will appear in
// enqueued buffers.
// This method should only be called if there is a non-NULL buffer
// that is full.
filter();
return should_enqueue;
}
}
}
}
}
// There can be NULL entries because of destructors.
}
}
}
#ifndef PRODUCT
// Helpful for debugging
}
}
#endif // PRODUCT
#ifdef ASSERT
"Not an oop");
}
}
#endif
#ifdef _MSC_VER // the use of 'this' below gets a warning, make it go away
#endif // _MSC_VER
_shared_satb_queue(this, true /*perm*/) { }
if (ParallelGCThreads > 0) {
}
}
t->satb_mark_queue().handle_zero_index();
}
#ifdef ASSERT
bool expected_active) {
}
}
#endif // ASSERT
bool expected_active) {
#ifdef ASSERT
if (_all_active != expected_active) {
// I leave this here as a guarantee, instead of an assert, so
// that it will still be compiled in if we choose to uncomment
// the #ifdef ASSERT in a product build. The whole block is
// within an #ifdef ASSERT so the guarantee will not be compiled
// in a product build anyway.
guarantee(false,
"SATB queue set has an unexpected active value");
}
#endif // ASSERT
_all_active = b;
#ifdef ASSERT
if (active != expected_active) {
// I leave this here as a guarantee, instead of an assert, so
// that it will still be compiled in if we choose to uncomment
// the #ifdef ASSERT in a product build. The whole block is
// within an #ifdef ASSERT so the guarantee will not be compiled
// in a product build anyway.
guarantee(false,
"thread has an unexpected active value in its SATB queue");
}
#endif // ASSERT
t->satb_mark_queue().set_active(b);
}
}
t->satb_mark_queue().filter();
}
shared_satb_queue()->filter();
}
}
_par_closures[i] = par_closure;
}
}
}
if (t->claim_oops_do(true, parity)) {
}
}
// We also need to claim the VMThread so that its parity is updated
// otherwise the next call to Thread::possibly_parallel_oops_do inside
// a StrongRootsScope might skip the VMThread because it has a stale
// parity that matches the parity set by the StrongRootsScope
//
// Whichever worker succeeds in claiming the VMThread gets to do
// the shared queue.
}
}
int worker) {
{
if (_completed_buffers_head != NULL) {
if (_n_completed_buffers == 0) _process_completed = false;
}
}
return true;
} else {
return false;
}
}
}
}
}
}
#ifndef PRODUCT
// Helpful for debugging
gclog_or_tty->cr();
int i = 0;
i += 1;
}
}
gclog_or_tty->cr();
}
#endif // PRODUCT
{
while (_completed_buffers_head != NULL) {
}
_n_completed_buffers = 0;
}
while (buffers_to_delete != NULL) {
}
// So we can safely manipulate these queues.
t->satb_mark_queue().reset();
}
shared_satb_queue()->reset();
}