/* * Copyright (c) 2001, 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. *
*/
inline HeapWord* HeapRegion::par_allocate_impl(size_t min_word_size,
size_t desired_word_size,
size_t* actual_size) { do {
HeapWord* obj = top();
size_t available = pointer_delta(end(), obj);
size_t want_to_allocate = MIN2(available, desired_word_size); if (want_to_allocate >= min_word_size) {
HeapWord* new_top = obj + want_to_allocate;
HeapWord* result = Atomic::cmpxchg(&_top, obj, new_top); // result can be one of two: // the old top value: the exchange succeeded // otherwise: the new value of the top is returned. if (result == obj) {
assert(is_object_aligned(obj) && is_object_aligned(new_top), "checking alignment");
*actual_size = want_to_allocate; return obj;
}
} else { return NULL;
}
} while (true);
}
inlinebool HeapRegion::block_is_obj(const HeapWord* const p, HeapWord* const pb) const {
assert(p >= bottom() && p < top(), "precondition");
assert(!is_continues_humongous(), "p must point to block-start");
if (obj_in_parsable_area(p, pb)) { returntrue;
}
// When class unloading is enabled it is not safe to only consider top() to conclude if the // given pointer is a valid object. The situation can occur both for class unloading in a // Full GC and during a concurrent cycle. // To make sure dead objects can be handled without always keeping an additional bitmap, we // scrub dead objects and create filler objects that are considered dead. We do this even if // class unloading is disabled to avoid special code. // From Remark until the region has been completely scrubbed obj_is_parsable will return false // and we have to use the bitmap to know if a block is a valid object. return is_marked_in_bitmap(cast_to_oop(p));
}
inlinebool HeapRegion::is_obj_dead(const oop obj, HeapWord* const pb) const {
assert(is_in_reserved(obj), "Object " PTR_FORMAT " must be in region", p2i(obj));
// Objects in closed archive regions are always live. if (is_closed_archive()) { returnfalse;
}
// From Remark until a region has been concurrently scrubbed, parts of the // region is not guaranteed to be parsable. Use the bitmap for liveness. if (obj_in_unparsable_area(obj, pb)) { return !is_marked_in_bitmap(obj);
}
// This object is in the parsable part of the heap, live unless scrubbed. return G1CollectedHeap::is_obj_filler(obj);
}
set_top(new_top); // After a compaction the mark bitmap in a non-pinned regions is invalid. // But all objects are live, we get this by setting TAMS to bottom.
init_top_at_mark_start();
while (next_addr < limit) {
Prefetch::write(next_addr, PrefetchScanIntervalInBytes); // This explicit is_marked check is a way to avoid // some extra work done by get_next_marked_addr for // the case where next_addr is marked. if (bitmap->is_marked(next_addr)) {
oop current = cast_to_oop(next_addr);
next_addr += closure->apply(current);
} else {
next_addr = bitmap->get_next_marked_addr(next_addr, limit);
}
}
assert(next_addr == limit, "Should stop the scan at the limit.");
}
HeapWord* prev_addr; while (next_addr < top()) {
prev_addr = next_addr;
next_addr = prev_addr + cast_to_oop(prev_addr)->size();
update_bot_for_block(prev_addr, next_addr);
}
assert(next_addr == top(), "Should stop the scan at the limit.");
}
inlinevoid HeapRegion::update_bot_for_obj(HeapWord* obj_start, size_t obj_size) {
assert(is_old(), "should only do BOT updates for old regions");
HeapWord* obj_end = obj_start + obj_size;
assert(is_in(obj_start), "obj_start must be in this region: " HR_FORMAT " obj_start " PTR_FORMAT " obj_end " PTR_FORMAT,
HR_FORMAT_PARAMS(this),
p2i(obj_start), p2i(obj_end));
inlinevoid HeapRegion::reset_top_at_mark_start() { // We do not need a release store here because // // - if this method is called during concurrent bitmap clearing, we do not read // the bitmap any more for live/dead information (we do not read the bitmap at // all at that point). // - otherwise we reclaim regions only during GC and we do not read tams and the // bitmap concurrently.
set_top_at_mark_start(bottom());
}
// If concurrent and klass_or_null is NULL, then space has been // allocated but the object has not yet been published by setting // the klass. That can only happen if the card is stale. However, // we've already set the card clean, so we must return failure, // since the allocating thread could have performed a write to the // card that might be missed otherwise. if (!in_gc_pause && (obj->klass_or_null_acquire() == NULL)) { return NULL;
}
// We have a well-formed humongous object at the start of sr. // Only filler objects follow a humongous object in the containing // regions, and we can ignore those. So only process the one // humongous object. if (obj->is_objArray() || (sr->bottom() < mr.start())) { // objArrays are always marked precisely, so limit processing // with mr. Non-objArrays might be precisely marked, and since // it's humongous it's worthwhile avoiding full processing. // However, the card could be stale and only cover filler // objects. That should be rare, so not worth checking for; // instead let it fall out from the bounded iteration.
obj->oop_iterate(cl, mr); return mr.end();
} else { // If obj is not an objArray and mr contains the start of the // obj, then this could be an imprecise mark, and we need to // process the entire object.
size_t size = obj->oop_iterate_size(cl); // We have scanned to the end of the object, but since there can be no objects // after this humongous object in the region, we can return the end of the // region if it is greater. return MAX2(cast_from_oop<HeapWord*>(obj) + size, mr.end());
}
}
while (true) { // Using bitmap to locate marked objs in the unparsable area
cur = bitmap->get_next_marked_addr(cur, end); if (cur == end) { return end;
}
assert(bitmap->is_marked(cur), "inv");
oop obj = cast_to_oop(cur);
assert(oopDesc::is_oop(obj, true), "Not an oop at " PTR_FORMAT, p2i(cur));
if (cur >= end) { return is_precise ? end : cur;
}
}
}
// Applies cl to all reference fields of live objects in mr in non-humongous regions. // // For performance, the strategy here is to divide the work into two parts: areas // below parsable_bottom (unparsable) and above parsable_bottom. The unparsable parts // use the bitmap to locate live objects. // Otherwise we would need to check for every object what the current location is; // we expect that the amount of GCs executed during scrubbing is very low so such // tests would be unnecessary almost all the time. template <class Closure, bool in_gc_pause> inline HeapWord* HeapRegion::oops_on_memregion_iterate(MemRegion mr, Closure* cl) { // Cache the boundaries of the memory region in some const locals
HeapWord* const start = mr.start();
HeapWord* const end = mr.end();
// Find the obj that extends onto mr.start(). // // The BOT itself is stable enough to be read at any time as // // * during refinement the individual elements of the BOT are read and written // atomically and any visible mix of new and old BOT entries will eventually lead // to some (possibly outdated) object start. // // * during GC the BOT does not change while reading, and the objects corresponding // to these block starts are valid as "holes" are filled atomically wrt to // safepoints. //
HeapWord* cur = block_start(start, pb); if (!obj_in_parsable_area(start, pb)) { // Limit the MemRegion to the part of the area to scan to the unparsable one as using the bitmap // is slower than blindly iterating the objects.
MemRegion mr_in_unparsable(mr.start(), MIN2(mr.end(), pb));
cur = oops_on_memregion_iterate_in_unparsable<Closure>(mr_in_unparsable, cur, cl); // We might have scanned beyond end at this point because of imprecise iteration. if (cur >= end) { return cur;
} // Parsable_bottom is always the start of a valid parsable object, so we must either // have stopped at parsable_bottom, or already iterated beyond end. The // latter case is handled above.
assert(cur == pb, "must be cur " PTR_FORMAT " pb " PTR_FORMAT, p2i(cur), p2i(pb));
}
assert(cur < top(), "must be cur " PTR_FORMAT " top " PTR_FORMAT, p2i(cur), p2i(top()));
// All objects >= pb are parsable. So we can just take object sizes directly. while (true) {
oop obj = cast_to_oop(cur);
assert(oopDesc::is_oop(obj, true), "Not an oop at " PTR_FORMAT, p2i(cur));
bool is_precise = false;
cur += obj->size(); // Process live object's references.
// Non-objArrays are usually marked imprecise at the object // start, in which case we need to iterate over them in full. // objArrays are precisely marked, but can still be iterated // over in full if completely covered. if (!obj->is_objArray() || (cast_from_oop<HeapWord*>(obj) >= start && cur <= end)) {
obj->oop_iterate(cl);
} else {
obj->oop_iterate(cl, mr);
is_precise = true;
} if (cur >= end) { return is_precise ? end : cur;
}
}
}
template <bool in_gc_pause, class Closure>
HeapWord* HeapRegion::oops_on_memregion_seq_iterate_careful(MemRegion mr,
Closure* cl) {
assert(MemRegion(bottom(), top()).contains(mr), "Card region not in heap region");
// Special handling for humongous regions. if (is_humongous()) { return do_oops_on_memregion_in_humongous<Closure, in_gc_pause>(mr, cl);
}
assert(is_old() || is_archive(), "Wrongly trying to iterate over region %u type %s", _hrm_index, get_type_str());
// Because mr has been trimmed to what's been allocated in this // region, the objects in these parts of the heap have non-NULL // klass pointers. There's no need to use klass_or_null to detect // in-progress allocation. // We might be in the progress of scrubbing this region and in this // case there might be objects that have their classes unloaded and // therefore needs to be scanned using the bitmap.
¤ 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.0.1Bemerkung:
(vorverarbeitet am 2026-05-02)
¤
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.