Details
Description
This code in ReferenceProcessor::discover_reference enqueues a reference during discovery looks like this:
if (_discovery_is_mt) {
[1] add_to_discovered_list_mt(*list, obj, discovered_addr);
} else {
[2] // We do a raw store here: the field will be visited later when processing
// the discovered references.
oop current_head = list->head();
// The last ref must have its discovered field pointing to itself.
oop next_discovered = (current_head != NULL) ? current_head : obj;
assert(discovered == NULL, "control point invariant");
RawAccess<>::oop_store(discovered_addr, next_discovered);
list->set_head(obj);
list->inc_length(1);
log_develop_trace(gc, ref)("Discovered reference (" INTPTR_FORMAT ": %s)", p2i(obj), obj->klass()->internal_name());
}
[2] argues that there is no need for a barrier because we visit this later when processing the discovered references *during gc*.
However, some G1 code sets _discovery_is_mt to false for concurrent precleaning (in G1ConcurrentMark::preclean()). This causes missing barriers in G1.
[1] executes a barrier always, just because we are using multiple threads, even during gc when it is not required.
This adds overhead for parallel gc and G1 during GC.
I.e. there is a confusion between "atomicity" and "degree of parallelism" in this code.
if (_discovery_is_mt) {
[1] add_to_discovered_list_mt(*list, obj, discovered_addr);
} else {
[2] // We do a raw store here: the field will be visited later when processing
// the discovered references.
oop current_head = list->head();
// The last ref must have its discovered field pointing to itself.
oop next_discovered = (current_head != NULL) ? current_head : obj;
assert(discovered == NULL, "control point invariant");
RawAccess<>::oop_store(discovered_addr, next_discovered);
list->set_head(obj);
list->inc_length(1);
log_develop_trace(gc, ref)("Discovered reference (" INTPTR_FORMAT ": %s)", p2i(obj), obj->klass()->internal_name());
}
[2] argues that there is no need for a barrier because we visit this later when processing the discovered references *during gc*.
However, some G1 code sets _discovery_is_mt to false for concurrent precleaning (in G1ConcurrentMark::preclean()). This causes missing barriers in G1.
[1] executes a barrier always, just because we are using multiple threads, even during gc when it is not required.
This adds overhead for parallel gc and G1 during GC.
I.e. there is a confusion between "atomicity" and "degree of parallelism" in this code.
Attachments
Issue Links
- relates to
-
JDK-8273185 Rename the term "atomic" in ReferenceProcessor
-
- Resolved
-