RFR: Reimplement TsanOopMap support using WeakHandle and ResizeableResourceHashtable [v11]
Jiangli Zhou
jiangli at openjdk.org
Mon Jul 29 20:06:22 UTC 2024
On Sat, 27 Jul 2024 00:28:10 GMT, Jiangli Zhou <jiangli at openjdk.org> wrote:
>> The new implementation for TsanOopMap support in JDK 21 is partially modeled after [JvmtiTagMap](https://github.com/openjdk/jdk21u-dev/blob/cdbd94f8fa97847c02e1f0f4c6cd75f457a62e25/src/hotspot/share/prims/jvmtiTagMap.hpp#L37) and [JvmtiTagMapTable](https://github.com/openjdk/jdk21u-dev/blob/cdbd94f8fa97847c02e1f0f4c6cd75f457a62e25/src/hotspot/share/prims/jvmtiTagMapTable.hpp#L43):
>>
>> - Use [WeakHandle](https://github.com/openjdk/jdk21u-dev/blob/cdbd94f8fa97847c02e1f0f4c6cd75f457a62e25/src/hotspot/share/oops/weakHandle.hpp#L42) for handling oops in the table entries;
>> - Use ResizeableResourceHashtable to for the underlying hash table. Table growing/resizing and removal of freed object entries are mostly handled within ResizeableResourceHashtable, except some small parts are done within TsanOopMapTable. That makes the new implementation simpler.
>>
>> The TsanOopMapTable contains entries consisting of TsanOopMapTableKey:oop_size (key:value) pairs. The TsanOopMapTableKey contains:
>>
>> - A Weakhandle that holds a pointer to the oop;
>> - The original (or updated) address of the object in Java heap;
>>
>> For TsanOopMapTable support, I added a new weak OopStorage, which is created during tsan_init(). All WeakHandles used for tracking Tsan interested Java objects are created from that OopStorage. GC processes these WeakHandles with `WeakProcessor::Task::work` in concurrent worker threads.
>>
>> To notify Tsan about object free/move in time, I added a call in WeakProcessor::Task::work to process the TsanOopMap:
>>
>> - If an object is freed by GC, call __tsan_java_free to notify Tsan. Remove the entry from the table.
>> - If an object is moved by GC, update the raw address in the entry using the new oop address obtained from the WeakHandle and add the “move” to a GrowableArray.
>> - After all entries in TsanOopMap are processed, sort the “moves” in the GrowableArray and notify Tsan by calling __tsan_java_move for each object in the sorted array. This part is the existing implementation from JDK 11 for Tsan support.
>>
>> Note all above operations occur during GC, before any of the mutators sees a moved or freed Java object.
>>
>> As an alternative, I initially experimented with doing the above operations concurrently (to mutators) in ServiceThread after GC finished processing the WeakHandles. That could occur after mutators sees moved objects and resulted incorrect data being recorded in Tsan.
>>
>> Suppressed following Tsan errors in JDK:
>> 1) In `java.util.concu...
>
> Jiangli Zhou has updated the pull request incrementally with one additional commit since the last revision:
>
> - Use cast_from_oop<T> in various places when coverting oop to different types.
> - Change TsanOopMapTableKey::_obj to 'oop'.
> - Change TsanOopMapTableKey::equals to just do `lhs._obj == rhs._obj`.
>
Thanks for the careful and thorough review! It helps make the code cleaner.
-------------
PR Comment: https://git.openjdk.org/tsan/pull/19#issuecomment-2256795187
More information about the tsan-dev
mailing list