RFR: Reimplement TsanOopMap support using WeakHandle and ResizeableResourceHashtable [v6]
Man Cao
manc at openjdk.org
Wed Jul 24 20:28:46 UTC 2024
On Wed, 24 Jul 2024 18:50:34 GMT, Jiangli Zhou <jiangli at openjdk.org> wrote:
>> src/hotspot/share/tsan/tsanOopMapTable.cpp line 49:
>>
>>> 47:
>>> 48: void TsanOopMapTableKey::update_obj() {
>>> 49: oop obj = _wh.peek();
>>
>> Since `_obj` is `oopDesc*` and `oop` could be an object, is it better to do `oopDesc* obj = _wh.peek()`?
>
> `oopDesc*` is `oop`.
`oopDesc*` is different from `oop` in a fastdebug build, when `CHECK_UNHANDLED_OOPS` is defined.
>> src/hotspot/share/tsan/tsanOopMapTable.hpp line 78:
>>
>>> 76:
>>> 77: static bool equals(const TsanOopMapTableKey& lhs, const TsanOopMapTableKey& rhs) {
>>> 78: oop lhs_obj = lhs._obj != nullptr ? (oop)lhs._obj : lhs.object_no_keepalive();
>>
>> I think `lhs._obj` and `rhs._obj` will never be `nullptr` in practice. This is because:
>> - We never add a null oop to the table.
>> - Once `_wh.peek()` returns null, the associated entry is immediately removed. We never update `_obj` to null.
>>
>> Would it better to add an assert that `lhs._obj` and `rhs._obj` are both non-null and remove the call to `object_no_keepalive()`?
>>
>> (I find it a bit hard to reason why we would resort to `_wh` for equality. I know `JvmtiTagMapKey::_obj` would be null most of the time in contrast.)
>
> I had also considered to not check if `_obj` is nullptr and decided to keep the check. The main concern is that I don't know if there could be a case where it wants to compare an entry with freed object. I feel it's safer to keep the check.
Could we try adding an assertion? `assert(lhs._obj != nullptr && rhs._obj != nullptr)`.
Even if we run into an entry whose `_obj` is freed, `_wh.peek()` should also return null in that case. So there's no need to look at `_wh`.
>> src/hotspot/share/tsan/tsanOopMapTable.hpp line 104:
>>
>>> 102: unsigned size() const { return _table.table_size(); };
>>> 103:
>>> 104: bool add_oop_with_size(oop obj, int size);
>>
>> Type for `size` should be `jlong`, right? As `typedef ResizeableResourceHashtable` indicates.
>> Let's fix this problem also in `TsanOopMap::add_oop_with_size`. According to https://github.com/microsoft/compiler-rt/blob/master/test/tsan/java.h, the tsan callbacks take `unsigned long` for size, so `jlong` should be fine.
>>
>> (We have run into issues with overflowing size field for large objects (>4G), related to JVMTI SampledObjectAlloc. So this is a real bug that could manifest with large objects.)
>
>> Type for size should be jlong, right? As typedef ResizeableResourceHashtable indicates.
>
> The table size is `unsigned`, see https://github.com/openjdk/jdk21u-dev/blob/570a6bd7df8062ac168f39f368303feaab056978/src/hotspot/share/utilities/resourceHash.hpp#L124 and https://github.com/openjdk/jdk21u-dev/blob/570a6bd7df8062ac168f39f368303feaab056978/src/hotspot/share/utilities/resizeableResourceHash.hpp#L38.
>
> The specifically referred type (as `jlong` in your comment) in `typedef ResizeableResourceHashtable` is the type for entry `value`. That's not the table size type. Thank for flagging it though. It's a bug that I missed during code cleanup iterations. I originally tried to use oop as the entry value, hence using `jlong` was appropriate. I ended up using oop size as the entry value instead, but missed to change the value type accordingly. I've fixed to use `size_t` instead.
>
>> Let's fix this problem also in TsanOopMap::add_oop_with_size. According to https://github.com/microsoft/compiler-rt/blob/master/test/tsan/java.h, the tsan callbacks take unsigned long for size, so jlong should be fine.
>
> Are you referring to the `size` arg passed in `TsanOopMap::add_oop_with_size(oopDesc *addr, int size)`? That's the oop size, and not the table size.
>
> I've also changed the arg type to `size_t` in add_oop_with_size() functions. Note, the caller `SharedRuntime::tsan_track_obj_with_size` still passes the `size` arg as `int`. We can leave that for now and cleanup later.
I'm referring to the argument `int size` passed to `TsanOopMapTable::add_oop_with_size` and `TsanOopMap::add_oop_with_size`. Yes, `size_t` also works.
Thanks for noticing `SharedRuntime::tsan_track_obj_with_size`, we can fix it separately.
-------------
PR Review Comment: https://git.openjdk.org/tsan/pull/19#discussion_r1690368455
PR Review Comment: https://git.openjdk.org/tsan/pull/19#discussion_r1690377305
PR Review Comment: https://git.openjdk.org/tsan/pull/19#discussion_r1690363507
More information about the tsan-dev
mailing list