On Mon, 16 Nov 2020 23:30:25 GMT, Coleen Phillimore <cole...@openjdk.org> wrote:
>> This change turns the HashTable that JVMTI uses for object tagging into a >> regular Hotspot hashtable - the one in hashtable.hpp with resizing and >> rehashing. Instead of pointing directly to oops so that GC has to walk the >> table to follow oops and then to rehash the table, this table points to >> WeakHandle. GC walks the backing OopStorages concurrently. >> >> The hash function for the table is a hash of the lower 32 bits of the >> address. A flag is set during GC (gc_notification if in a safepoint, and >> through a call to JvmtiTagMap::needs_processing()) so that the table is >> rehashed at the next use. >> >> The gc_notification mechanism of weak oop processing is used to notify Jvmti >> to post ObjectFree events. In concurrent GCs there can be a window of time >> between weak oop marking where the oop is unmarked, so dead (the phantom >> load in peek returns NULL) but the gc_notification hasn't been done yet. In >> this window, a heap walk or GetObjectsWithTags call would not find an object >> before the ObjectFree event is posted. This is dealt with in two ways: >> >> 1. In the Heap walk, there's an unconditional table walk to post events if >> events are needed to post. >> 2. For GetObjectWithTags, if a dead oop is found in the table and posting is >> required, we use the VM thread to post the event. >> >> Event posting cannot be done in a JavaThread because the posting needs to be >> done while holding the table lock, so that the JvmtiEnv state doesn't change >> before posting is done. ObjectFree callbacks are limited in what they can >> do as per the JVMTI Specification. The allowed callbacks to the VM already >> have code to allow NonJava threads. >> >> To avoid rehashing, I also tried to use object->identity_hash() but this >> breaks because entries can be added to the table during heapwalk, where the >> objects use marking. The starting markWord is saved and restored. Adding a >> hashcode during this operation makes restoring the former markWord (locked, >> inflated, etc) too complicated. Plus we don't want all these objects to >> have hashcodes because locking operations after tagging would have to always >> use inflated locks. >> >> Much of this change is to remove serial weak oop processing for the >> weakProcessor, ZGC and Shenandoah. The GCs have been stress tested with >> jvmti code. >> >> It has also been tested with tier1-6. >> >> Thank you to Stefan, Erik and Kim for their help with this change. > > Coleen Phillimore has updated the pull request incrementally with one > additional commit since the last revision: > > Fix minimal build. Hi Coleen, It looks good to me. Just a couple of nits below. src/hotspot/share/prims/jvmtiTagMap.cpp: There is a double-check for _needs_cleaning, so the one at line 136 can be removed: 136 if (_needs_cleaning && 137 post_events && 138 env()->is_enabled(JVMTI_EVENT_OBJECT_FREE)) { 139 remove_dead_entries(true /* post_object_free */); 1158 void JvmtiTagMap::remove_dead_entries(bool post_object_free) { 1159 assert(is_locked(), "precondition"); 1160 if (_needs_cleaning) { 1161 log_info(jvmti, table)("TagMap table needs cleaning%s", 1162 (post_object_free ? " and posting" : "")); 1163 hashmap()->remove_dead_entries(env(), post_object_free); 1164 _needs_cleaning = false; 1165 } 1166 } test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach021/attach021Agent00.cpp: The change below is not needed as the call to nsk_jvmti_aod_disableEventAndFinish() does exactly the same: - nsk_jvmti_aod_disableEventAndFinish(agentName, JVMTI_EVENT_OBJECT_FREE, success, jvmti, jni); + + /* Flush any pending ObjectFree events, which may set success to 1 */ + if (jvmti->SetEventNotificationMode(JVMTI_DISABLE, + JVMTI_EVENT_OBJECT_FREE, + NULL) != JVMTI_ERROR_NONE) { + success = 0; + } + + nsk_aod_agentFinished(jni, agentName, success); } ------------- Marked as reviewed by sspitsyn (Reviewer). PR: https://git.openjdk.java.net/jdk/pull/967