Use of C++ dynamic global object initialization with thread guards
Florian Weimer
fweimer at redhat.com
Mon Dec 4 07:28:32 UTC 2023
As far as I understand it, the Hotspot C++ style guide advises not use
C++ run-time library features. However, it seems that the use of
dynamic initialization guards (that involve calls to __cxa_guard_acquire
and __cxa_guard_release) has increased quite a bit over the years.
The implementation of __cxa_guard_acquire is not entirely trivial
because it detects recursive initialization and throws
__gnu_cxx::recursive_init_error, which means that it pulls in the C++
unwinder (at least with a traditional GNU/Linux build of libstdc++.a).
Furthermore, most uses of C++ dynamic initialization involve a
computation that is idempotent and have unused bit patterns in the
initialized value. This means that a separate guard variable is not
needed, and a simple atomic store/atomic load could be used.
In other cases, the use of global objects seems unnecessary. For
example, src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointManager.cpp
has a dynamically initialized static variable max_elem_size:
“
BufferPtr JfrCheckpointManager::lease_global(Thread* thread, bool previous_epoch /* false */, size_t size /* 0 */) {
JfrCheckpointMspace* const mspace = instance()._global_mspace;
assert(mspace != nullptr, "invariant");
static const size_t max_elem_size = mspace->min_element_size(); // min is max
BufferPtr buffer;
if (size <= max_elem_size) {
buffer = mspace_acquire_live(size, mspace, thread, previous_epoch);
if (buffer != nullptr) {
buffer->set_lease();
DEBUG_ONLY(assert_lease(buffer);)
return buffer;
}
}
buffer = mspace_allocate_transient_lease_to_live_list(size, mspace, thread, previous_epoch);
DEBUG_ONLY(assert_lease(buffer);)
return buffer;
}
”
The min_element_size() member function is inline and just returns
_min_element_size, which is declared const, so it cannot change over
time. This means that caching that value is pointless, and the static
should probably removed.
Would it make sense to minimize the use of __cxa_guard_acquire and
__cxa_guard_release? There are currently 400 such calls, but many of
them appear in templated code, so I could get it down to ~80 calls with
about a days of work.
Those calls are clearly visible in --with-stdc++lib=dynamic, so it would
be possible to add a regression test to avoid introducing further such
calls.
Thanks,
Florian
More information about the hotspot-dev
mailing list