JDK-8202813 : Move vm_weak processing from SystemDictionary to WeakProcessor
  • Type: Enhancement
  • Component: hotspot
  • Sub-Component: gc
  • Priority: P4
  • Status: Resolved
  • Resolution: Fixed
  • OS: generic
  • CPU: generic
  • Submitted: 2018-05-08
  • Updated: 2018-06-21
  • Resolved: 2018-05-29
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 11
11 b16Fixed
Related Reports
Relates :  
Description
SystemDictionary::do_unloading presently clears dead entries from vm_weak_oop_storage as an initial step.  That should instead be done by the preceeding WeakProcessor usage.  Doing so requires some conditionalization of the WeakProcessor, because not all weak reference processing should do it.  This change will also make it easy to include vm_weak_oop_storage in a parallelized WeakProcessor.

Comments
I added a few Pause time screen shots from Jenny's tool to the bug report that show no significant differences in average (young) pause time. The goal of this change is to allow for parallel processing of the vm weak oop storage, so this will only improve.
29-05-2018

For ParallelGC, SystemDictionary::always_strong_oops_do() calls SystemDictionary::roots_oops_do(closure, NULL) and is used for marking. So roots_oops_do() does NOT mark weak oops in SystemDictionary::vm_weak_oop_storage() in full gc. ParallelScavenge calls SystemDictionary::oops_do() so does mark weak oops in SystemDictionary::vm_weak_oop_storage(). ParallelGC adjust phase calls SystemDictionary::oops_do() with AdjustPointerClosure: SystemDictionary::oops_do(adjust_pointer_closure()); ClassLoaderDataGraph::cld_do(adjust_cld_closure()); // Now adjust pointers in remaining weak roots. (All of which should // have been cleared if they pointed to non-surviving objects.) // Global (weak) JNI handles WeakProcessor::oops_do(adjust_pointer_closure()); It appears from here that moving processing from SystemDictionary::vm_weak_oop_storage() from SystemDictionary::oops_do() to WeakProcessor::oops_do() is equivalent.
24-05-2018

My proposed change moves the SystemDictionary::vm_weak_oop_storage() processing from SystemDictionay::{roots_}oops_do and do_unloading() into the WeakProcessor. The weak oops in the System Dictionary oop_storage are processed with weak oops from JNI. With this change all roots in the System Dictionary are strong roots, so only an oops_do() function is provided. With this change the processing of weak oops can be done in parallel in the WeakProcessor. Why is this move safe? 1. The WeakProcessor is called before SystemDictionary::do_unloading for all collectors. 2. If ClassUnloading, for SystemDictionary::roots_oops_do, weak == NULL and the marking phase skips marking the weak oops in SystemDictionary::vm_weak_oop_storage(). The oops in WeakProcessor are not marked in the marking phase. 3. If !ClassUnloading, the oops are marked in the walk of the ClassLoaderDataGraph which happens before (concurrently with) the SystemDictionary::root_oops_do call. The oops in the ClassLoaderData::_handles area are also present in SystemDictionary::vm_weak_oop_storage, so also will be marked when walking ClassLoaderDataGraph. 4. The only exception to this is the ResolvedMethodTable. These oops are in SystemDictionary::vm_weak_oops_storage also and for some GCs (not G1), the table is cleaned during class unloading. If !ClassUnloading, the table will not be cleaned, which is an existing problem. The references in vm_weak_oop_storages will be cleared however by the WeakProcessor. The ResolvedMethodTable, when switched to oop_storage, has null checks for cleared oops. 5. In adjust and evacuate phase, in SystemDictionary::roots_oops_do, weak == strong and all oops are followed. By moving the processing to the WeakProcessor, the oops are cleaned if they're not alive here and only the alive oops are processed. Depending on ClassUnloading, the oops that are alive will already be marked so they will get adjusted and evacuated.
24-05-2018