Re: [PATCH 2/2] Free multidicts from blockvector

Simon Marchi
2025-10-24T16:27:41Z

On 10/24/25 10:08 AM, Tom Tromey wrote:
> Simon> Ideally it would be struct block's just to call that. You could add a
> Simon> destructor to struct block and call it explicitly here. It would be the
> Simon> same result, but would be more correct encapsulation-wise. But I guess
> Simon> this is fine too for the time being.
>
> Tom> Yeah. I have kind of an aversion to explicit destructor calls.
> Tom> Though maybe not for any good reason.
>
> I was thinking about this last night and realized there's a bigger
> issue, which is that blocks are allocated on an obstack:
>
> struct block : public allocate_on_obstack<block>
>
> and
>
> block = new (&m_objfile->objfile_obstack) struct block;
>
> but allocate_on_obstack requires that the object be trivially
> destructible.
>
> Maybe this could be remedied by resurrecting Jan's obstack allocator;
> making an "obstack_ptr" class that explicitly calls the destructor but
> not 'delete'; and finally changing blockvector to hold these.

I guess that this restriction of "objects allocated on obstack must be
trivially destructible" is a bit artificial and arbitrary? It is
technically fine to allocate on obstack an object having a destructor,
as long as you ensure the destructor is called at some point. I guess
the restriction was put because it's easy to forget and error prone.
This obstack_ptr you talk about (obstack_unique_ptr?) sounds like a good
way to automate it.

I was wondering if we needed to keep allocating these on an obstack, but
my understanding is that obstack is a good choice here because:

- We can't use a vector<block> to store them, since the blocks
themselves can't move, as that would break the parent (superblock)
relationship

- There is a ton of blocks created, so it's nice to be able to free
their memory in O(1). Unfortunately, having to free
block::m_multidict means that part is O(n), but the less we have to
do in O(n) the better I guess?

Simon