/* * Copyright (c) 2015, 2022, 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.
*/
size_t ZMark::calculate_nstripes(uint nworkers) const { // Calculate the number of stripes from the number of workers we use, // where the number of stripes must be a power of two and we want to // have at least one worker per stripe. const size_t nstripes = round_down_power_of_2(nworkers); return MIN2(nstripes, ZMarkStripesMax);
}
void ZMark::start() { // Verification if (ZVerifyMarking) {
verify_all_stacks_empty();
}
// Increment global sequence number to invalidate // marking information for all pages.
ZGlobalSeqNum++;
// Note that we start a marking cycle. // Unlike other GCs, the color switch implicitly changes the nmethods // to be armed, and the thread-local disarm values are lazily updated // when JavaThreads wake up from safepoints.
CodeCache::on_gc_marking_cycle_start();
// Set number of workers to use
_nworkers = _workers->active_workers();
// Set number of mark stripes to use, based on number // of workers we will use in the concurrent mark phase. const size_t nstripes = calculate_nstripes(_nworkers);
_stripes.set_nstripes(nstripes);
void ZMark::follow_large_array(uintptr_t addr, size_t size, bool finalizable) {
assert(size <= (size_t)arrayOopDesc::max_array_length(T_OBJECT) * oopSize, "Too large");
assert(size > ZMarkPartialArrayMinSize, "Too small, should not be split"); const uintptr_t start = addr; const uintptr_t end = start + size;
// Calculate the aligned middle start/end/size, where the middle start // should always be greater than the start (hence the +1 below) to make // sure we always do some follow work, not just split the array into pieces. const uintptr_t middle_start = align_up(start + 1, ZMarkPartialArrayMinSize); const size_t middle_size = align_down(end - middle_start, ZMarkPartialArrayMinSize); const uintptr_t middle_end = middle_start + middle_size;
// Mark if (mark && !page->mark_object(addr, finalizable, inc_live)) { // Already marked return;
}
// Increment live if (inc_live) { // Update live objects/bytes for page. We use the aligned object // size since that is the actual number of bytes used on the page // and alignment paddings can never be reclaimed. const size_t size = ZUtils::object_size(addr); const size_t aligned_size = align_up(size, page->object_alignment());
context->cache()->inc_live(page, aligned_size);
}
// Follow if (follow) { if (is_array(addr)) {
follow_array_object(objArrayOop(ZOop::from_address(addr)), finalizable);
} else { const oop obj = ZOop::from_address(addr);
follow_object(obj, finalizable);
if (_terminate.enter_stage0()) { // Last thread entered stage 0, flush if (Atomic::load(&_work_terminateflush) &&
Atomic::load(&_work_nterminateflush) != ZMarkTerminateFlushMax) { // Exit stage 0 to allow other threads to continue marking
_terminate.exit_stage0();
// Flush before termination if (!try_flush(&_work_nterminateflush)) { // No more work available, skip further flush attempts
Atomic::store(&_work_terminateflush, false);
}
// Don't terminate, regardless of whether we successfully // flushed out more work or not. We've already exited // termination stage 0, to allow other threads to continue // marking, so this thread has to return false and also // make another round of attempted marking. returnfalse;
}
}
for (;;) { if (_terminate.enter_stage1()) { // Last thread entered stage 1, terminate returntrue;
}
// Idle to give the other threads // a chance to enter termination.
idle();
if (!_terminate.try_exit_stage1()) { // All workers in stage 1, terminate returntrue;
}
if (_terminate.try_exit_stage0()) { // More work available, don't terminate returnfalse;
}
}
}
class ZMarkNoTimeout : public StackObj { public: bool has_expired() { // No timeout, but check for signal to abort return ZAbort::should_abort();
}
};
// Flush and free worker stacks. Needed here since // the set of workers executing during root scanning // can be different from the set of workers executing // during mark.
_mark->flush_and_free();
}
};
class ZMarkTask : public ZTask { private:
ZMark* const _mark; const uint64_t _timeout_in_micros;
// Use nconcurrent number of worker threads to maintain the // worker/stripe distribution used during concurrent mark.
ZMarkTask task(this, ZMarkCompleteTimeout);
_workers->run(&task);
// Successful if all stripes are empty return _stripes.is_empty();
}
bool ZMark::try_end() { // Flush all mark stacks if (!flush(true/* at_safepoint */)) { // Mark completed returntrue;
}
// Try complete marking by doing a limited // amount of mark work in this phase. return try_complete();
}
bool ZMark::end() { // Try end marking if (!try_end()) { // Mark not completed
_ncontinue++; returnfalse;
}
// Verification if (ZVerifyMarking) {
verify_all_stacks_empty();
}
// Note that we finished a marking cycle. // Unlike other GCs, we do not arm the nmethods // when marking terminates.
CodeCache::on_gc_marking_cycle_finish();
// Mark completed returntrue;
}
void ZMark::free() { // Free any unused mark stack space
_allocator.free();
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.