This is an archive of the discontinued LLVM Phabricator instance.

[DebugInfo][NFC] Erase capacity in DWARFUnit::clearDIEs().
ClosedPublic

Authored by avl on Sep 9 2021, 4:02 AM.

Details

Summary

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.

Diff Detail

Event Timeline

avl created this revision.Sep 9 2021, 4:02 AM
avl requested review of this revision.Sep 9 2021, 4:02 AM
Herald added a project: Restricted Project. · View Herald TranscriptSep 9 2021, 4:02 AM

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)?

avl added a comment.Sep 9 2021, 10:29 AM

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()

Which standard library implementation did you observe that behavior in?

avl added a comment.Sep 9 2021, 11:01 AM

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.

dblaikie accepted this revision.Sep 9 2021, 11:39 AM

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)

This revision is now accepted and ready to land.Sep 9 2021, 11:39 AM
avl updated this revision to Diff 371690.Sep 9 2021, 12:18 PM

addressed comments.

This revision was automatically updated to reflect the committed changes.