DWARFUnit::clearDIEs() uses std::vector::shrink_to_fit() to make
capacity of DieArray matched with its size(). The shrink_to_fit()
is not binding request to make capacity match with size().
Thus the memory could still be reserved after DWARFUnit::clearDIEs()
is called. This patch erases capacity when DWARFUnit::clearDIEs() is requested.
So the memory occupied by dies would be freed.
Details
Diff Detail
- Repository
- rG LLVM Github Monorepo
Event Timeline
Have you observed this to be a problem in practice? Might be worth getting that implementation fixed, rather than working around the low-quality implementation (if that's the issue - if the implementation has a good reason for not taking the shrink_to_fit hint, then maybe this patch is the way to go)?
I used clearDIEs() in this patch https://reviews.llvm.org/D96035 and observed that memory is not freed. Looking at the reason I found that shrink_to_fit() does not change a capacity and as the result the memory stay used.
The use case in D96035 is: load dies of DWARFUnit, clone dies to output, clean loaded dies by calling DWARFUnit::clear().
The comment says that it is not guaranteed that capacity would be reduced:
/** A non-binding request to reduce capacity() to size(). */ void shrink_to_fit()
The used implementation come from /usr/include/c++/9/bits/allocator.h :
template<typename _Tp>
struct __shrink_to_fit_aux<_Tp, true>
{
static bool
_S_do_it(_Tp& __c) noexcept
{
#if __cpp_exceptions
try
{
_Tp(__make_move_if_noexcept_iterator(__c.begin()),
__make_move_if_noexcept_iterator(__c.end()),
__c.get_allocator()).swap(__c);
return true;
}
catch(...)
{ return false; }
#else
return false; <<< this path is taken which do nothing.
#endif
}
};which belongs to gcc 9.3.0 libstdc++ library.
eh, curious. Fair enough.
Might be a simpler/tidier way to write this, not sure...
DieArray = (KeepCUDie && !DieArray.empty()) ? std::vector<DWARFDebugInfoEntry>({DieArray[0]}) : std::vector<DWARFDebugInfoEntry>();Maybe that'd work? Maybe include a comment about not using shrink_to_fit because some implementations don't respect it under certain conditions? (possibly naming the specific implementation/conditions to make it easier for someone to know whether the workaround is still useful if they're revisiting this code in the future)