8280396: G1: Full gc mark stack draining should prefer to make work available to other threads

Reviewed-by: sjohanss, ayang
This commit is contained in:
Thomas Schatzl 2022-01-25 16:27:30 +00:00
parent fe77250fa4
commit 674a97b27e
2 changed files with 40 additions and 18 deletions

@ -1,5 +1,5 @@
/*
* Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2017, 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
@ -71,8 +71,6 @@ class G1FullGCMarker : public CHeapObj<mtGC> {
G1RegionMarkStatsCache _mark_stats_cache;
inline bool is_empty();
inline bool pop_object(oop& obj);
inline bool pop_objarray(ObjArrayTask& array);
inline void push_objarray(oop obj, size_t index);
inline bool mark_object(oop obj);
@ -80,6 +78,14 @@ class G1FullGCMarker : public CHeapObj<mtGC> {
inline void follow_object(oop obj);
inline void follow_array(objArrayOop array);
inline void follow_array_chunk(objArrayOop array, int index);
inline void drain_oop_stack();
// Transfer contents from the objArray task queue overflow stack to the shared
// objArray stack.
// Returns true and a valid task if there has not been enough space in the shared
// objArray stack, otherwise the task is invalid.
inline bool transfer_objArray_overflow_stack(ObjArrayTask& task);
public:
G1FullGCMarker(G1FullCollector* collector,
uint worker_id,

@ -1,5 +1,5 @@
/*
* Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2017, 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
@ -91,20 +91,12 @@ inline bool G1FullGCMarker::is_empty() {
return _oop_stack.is_empty() && _objarray_stack.is_empty();
}
inline bool G1FullGCMarker::pop_object(oop& oop) {
return _oop_stack.pop_overflow(oop) || _oop_stack.pop_local(oop);
}
inline void G1FullGCMarker::push_objarray(oop obj, size_t index) {
ObjArrayTask task(obj, index);
assert(task.is_valid(), "bad ObjArrayTask");
_objarray_stack.push(task);
}
inline bool G1FullGCMarker::pop_objarray(ObjArrayTask& arr) {
return _objarray_stack.pop_overflow(arr) || _objarray_stack.pop_local(arr);
}
inline void G1FullGCMarker::follow_array(objArrayOop array) {
follow_klass(array->klass());
// Don't push empty arrays to avoid unnecessary work.
@ -159,16 +151,40 @@ inline void G1FullGCMarker::follow_object(oop obj) {
}
}
void G1FullGCMarker::drain_stack() {
do {
oop obj;
while (pop_object(obj)) {
inline void G1FullGCMarker::drain_oop_stack() {
oop obj;
while (_oop_stack.pop_overflow(obj)) {
if (!_oop_stack.try_push_to_taskqueue(obj)) {
assert(_bitmap->is_marked(obj), "must be marked");
follow_object(obj);
}
// Process ObjArrays one at a time to avoid marking stack bloat.
}
while (_oop_stack.pop_local(obj)) {
assert(_bitmap->is_marked(obj), "must be marked");
follow_object(obj);
}
}
inline bool G1FullGCMarker::transfer_objArray_overflow_stack(ObjArrayTask& task) {
// It is desirable to move as much as possible work from the overflow queue to
// the shared queue as quickly as possible.
while (_objarray_stack.pop_overflow(task)) {
if (!_objarray_stack.try_push_to_taskqueue(task)) {
return true;
}
}
return false;
}
void G1FullGCMarker::drain_stack() {
do {
// First, drain regular oop stack.
drain_oop_stack();
// Then process ObjArrays one at a time to avoid marking stack bloat.
ObjArrayTask task;
if (pop_objarray(task)) {
if (transfer_objArray_overflow_stack(task) ||
_objarray_stack.pop_local(task)) {
follow_array_chunk(objArrayOop(task.obj()), task.index());
}
} while (!is_empty());