Change allocation of type-copying hash table

When an objfile is destroyed, types that are still in use and
allocated on that objfile are copied.  A temporary hash map is created
during this process, and it is allocated on the destroyed objfile's
obstack -- which normally is fine, as that is going to be destroyed
shortly anyway.

However, this approach requires that the objfile be passed to registry
destruction, and this won't be possible in the rewritten registry.
This patch changes the copied type hash table to simply use the heap
instead.  It also removes the 'objfile' parameter from
copy_type_recursive, to make this all more clear.

This patch also fixes an apparent bug in copy_type_recursive.
Previously it was copying the dynamic property list to the dying
objfile's obstack:

-      = copy_dynamic_prop_list (&objfile->objfile_obstack,

However I think this is incorrect -- that obstack is about to be
destroyed.
This commit is contained in:
Tom Tromey 2022-05-24 15:17:19 -06:00
parent b382c16682
commit bde539c2f9
6 changed files with 27 additions and 42 deletions

View file

@ -109,8 +109,8 @@ do_module_cleanup (void *arg, int registers_valid)
static type * static type *
create_copied_type_recursive (objfile *objfile, type *func_type) create_copied_type_recursive (objfile *objfile, type *func_type)
{ {
htab_up copied_types = create_copied_types_hash (objfile); htab_up copied_types = create_copied_types_hash ();
func_type = copy_type_recursive (objfile, func_type, copied_types.get ()); func_type = copy_type_recursive (func_type, copied_types.get ());
return func_type; return func_type;
} }

View file

@ -5562,7 +5562,7 @@ recursive_dump_type (struct type *type, int spaces)
/* Trivial helpers for the libiberty hash table, for mapping one /* Trivial helpers for the libiberty hash table, for mapping one
type to another. */ type to another. */
struct type_pair : public allocate_on_obstack struct type_pair
{ {
type_pair (struct type *old_, struct type *newobj_) type_pair (struct type *old_, struct type *newobj_)
: old (old_), newobj (newobj_) : old (old_), newobj (newobj_)
@ -5589,22 +5589,20 @@ type_pair_eq (const void *item_lhs, const void *item_rhs)
} }
/* Allocate the hash table used by copy_type_recursive to walk /* Allocate the hash table used by copy_type_recursive to walk
types without duplicates. We use OBJFILE's obstack, because types without duplicates. */
OBJFILE is about to be deleted. */
htab_up htab_up
create_copied_types_hash (struct objfile *objfile) create_copied_types_hash ()
{ {
return htab_up (htab_create_alloc_ex (1, type_pair_hash, type_pair_eq, return htab_up (htab_create_alloc (1, type_pair_hash, type_pair_eq,
NULL, &objfile->objfile_obstack, htab_delete_entry<type_pair>,
hashtab_obstack_allocate, xcalloc, xfree));
dummy_obstack_deallocate));
} }
/* Recursively copy (deep copy) a dynamic attribute list of a type. */ /* Recursively copy (deep copy) a dynamic attribute list of a type. */
static struct dynamic_prop_list * static struct dynamic_prop_list *
copy_dynamic_prop_list (struct obstack *objfile_obstack, copy_dynamic_prop_list (struct obstack *storage,
struct dynamic_prop_list *list) struct dynamic_prop_list *list)
{ {
struct dynamic_prop_list *copy = list; struct dynamic_prop_list *copy = list;
@ -5615,7 +5613,7 @@ copy_dynamic_prop_list (struct obstack *objfile_obstack,
struct dynamic_prop_list *node_copy; struct dynamic_prop_list *node_copy;
node_copy = ((struct dynamic_prop_list *) node_copy = ((struct dynamic_prop_list *)
obstack_copy (objfile_obstack, *node_ptr, obstack_copy (storage, *node_ptr,
sizeof (struct dynamic_prop_list))); sizeof (struct dynamic_prop_list)));
node_copy->prop = (*node_ptr)->prop; node_copy->prop = (*node_ptr)->prop;
*node_ptr = node_copy; *node_ptr = node_copy;
@ -5632,9 +5630,7 @@ copy_dynamic_prop_list (struct obstack *objfile_obstack,
it is not associated with OBJFILE. */ it is not associated with OBJFILE. */
struct type * struct type *
copy_type_recursive (struct objfile *objfile, copy_type_recursive (struct type *type, htab_t copied_types)
struct type *type,
htab_t copied_types)
{ {
void **slot; void **slot;
struct type *new_type; struct type *new_type;
@ -5642,10 +5638,6 @@ copy_type_recursive (struct objfile *objfile,
if (!type->is_objfile_owned ()) if (!type->is_objfile_owned ())
return type; return type;
/* This type shouldn't be pointing to any types in other objfiles;
if it did, the type might disappear unexpectedly. */
gdb_assert (type->objfile_owner () == objfile);
struct type_pair pair (type, nullptr); struct type_pair pair (type, nullptr);
slot = htab_find_slot (copied_types, &pair, INSERT); slot = htab_find_slot (copied_types, &pair, INSERT);
@ -5656,8 +5648,7 @@ copy_type_recursive (struct objfile *objfile,
/* We must add the new type to the hash table immediately, in case /* We must add the new type to the hash table immediately, in case
we encounter this type again during a recursive call below. */ we encounter this type again during a recursive call below. */
struct type_pair *stored struct type_pair *stored = new type_pair (type, new_type);
= new (&objfile->objfile_obstack) struct type_pair (type, new_type);
*slot = stored; *slot = stored;
@ -5690,8 +5681,7 @@ copy_type_recursive (struct objfile *objfile,
TYPE_FIELD_BITSIZE (new_type, i) = TYPE_FIELD_BITSIZE (type, i); TYPE_FIELD_BITSIZE (new_type, i) = TYPE_FIELD_BITSIZE (type, i);
if (type->field (i).type ()) if (type->field (i).type ())
new_type->field (i).set_type new_type->field (i).set_type
(copy_type_recursive (objfile, type->field (i).type (), (copy_type_recursive (type->field (i).type (), copied_types));
copied_types));
if (type->field (i).name ()) if (type->field (i).name ())
new_type->field (i).set_name (xstrdup (type->field (i).name ())); new_type->field (i).set_name (xstrdup (type->field (i).name ()));
@ -5736,16 +5726,14 @@ copy_type_recursive (struct objfile *objfile,
if (type->main_type->dyn_prop_list != NULL) if (type->main_type->dyn_prop_list != NULL)
new_type->main_type->dyn_prop_list new_type->main_type->dyn_prop_list
= copy_dynamic_prop_list (&objfile->objfile_obstack, = copy_dynamic_prop_list (gdbarch_obstack (new_type->arch_owner ()),
type->main_type->dyn_prop_list); type->main_type->dyn_prop_list);
/* Copy pointers to other types. */ /* Copy pointers to other types. */
if (TYPE_TARGET_TYPE (type)) if (TYPE_TARGET_TYPE (type))
TYPE_TARGET_TYPE (new_type) = TYPE_TARGET_TYPE (new_type) =
copy_type_recursive (objfile, copy_type_recursive (TYPE_TARGET_TYPE (type), copied_types);
TYPE_TARGET_TYPE (type),
copied_types);
/* Maybe copy the type_specific bits. /* Maybe copy the type_specific bits.
@ -5774,7 +5762,7 @@ copy_type_recursive (struct objfile *objfile,
break; break;
case TYPE_SPECIFIC_SELF_TYPE: case TYPE_SPECIFIC_SELF_TYPE:
set_type_self_type (new_type, set_type_self_type (new_type,
copy_type_recursive (objfile, TYPE_SELF_TYPE (type), copy_type_recursive (TYPE_SELF_TYPE (type),
copied_types)); copied_types));
break; break;
case TYPE_SPECIFIC_FIXED_POINT: case TYPE_SPECIFIC_FIXED_POINT:

View file

@ -2875,10 +2875,9 @@ extern int class_or_union_p (const struct type *);
extern void maintenance_print_type (const char *, int); extern void maintenance_print_type (const char *, int);
extern htab_up create_copied_types_hash (struct objfile *objfile); extern htab_up create_copied_types_hash ();
extern struct type *copy_type_recursive (struct objfile *objfile, extern struct type *copy_type_recursive (struct type *type,
struct type *type,
htab_t copied_types); htab_t copied_types);
extern struct type *copy_type (const struct type *type); extern struct type *copy_type (const struct type *type);

View file

@ -360,7 +360,7 @@ tyscm_copy_type_recursive (void **slot, void *info)
gdb_assert (objfile != NULL); gdb_assert (objfile != NULL);
htab_empty (copied_types); htab_empty (copied_types);
t_smob->type = copy_type_recursive (objfile, t_smob->type, copied_types); t_smob->type = copy_type_recursive (t_smob->type, copied_types);
/* The eq?-hashtab that the type lived in is going away. /* The eq?-hashtab that the type lived in is going away.
Add the type to its new eq?-hashtab: Otherwise if/when the type is later Add the type to its new eq?-hashtab: Otherwise if/when the type is later
@ -391,7 +391,7 @@ save_objfile_types (struct objfile *objfile, void *datum)
if (!gdb_scheme_initialized) if (!gdb_scheme_initialized)
return; return;
htab_up copied_types = create_copied_types_hash (objfile); htab_up copied_types = create_copied_types_hash ();
if (htab != NULL) if (htab != NULL)
{ {

View file

@ -1123,7 +1123,7 @@ save_objfile_types (struct objfile *objfile, void *datum)
operating on. */ operating on. */
gdbpy_enter enter_py (objfile->arch ()); gdbpy_enter enter_py (objfile->arch ());
htab_up copied_types = create_copied_types_hash (objfile); htab_up copied_types = create_copied_types_hash ();
while (obj) while (obj)
{ {
@ -1131,8 +1131,7 @@ save_objfile_types (struct objfile *objfile, void *datum)
htab_empty (copied_types.get ()); htab_empty (copied_types.get ());
obj->type = copy_type_recursive (objfile, obj->type, obj->type = copy_type_recursive (obj->type, copied_types.get ());
copied_types.get ());
obj->next = NULL; obj->next = NULL;
obj->prev = NULL; obj->prev = NULL;

View file

@ -2571,11 +2571,10 @@ preserve_one_value (struct value *value, struct objfile *objfile,
htab_t copied_types) htab_t copied_types)
{ {
if (value->type->objfile_owner () == objfile) if (value->type->objfile_owner () == objfile)
value->type = copy_type_recursive (objfile, value->type, copied_types); value->type = copy_type_recursive (value->type, copied_types);
if (value->enclosing_type->objfile_owner () == objfile) if (value->enclosing_type->objfile_owner () == objfile)
value->enclosing_type = copy_type_recursive (objfile, value->enclosing_type = copy_type_recursive (value->enclosing_type,
value->enclosing_type,
copied_types); copied_types);
} }
@ -2591,7 +2590,7 @@ preserve_one_internalvar (struct internalvar *var, struct objfile *objfile,
if (var->u.integer.type if (var->u.integer.type
&& var->u.integer.type->objfile_owner () == objfile) && var->u.integer.type->objfile_owner () == objfile)
var->u.integer.type var->u.integer.type
= copy_type_recursive (objfile, var->u.integer.type, copied_types); = copy_type_recursive (var->u.integer.type, copied_types);
break; break;
case INTERNALVAR_VALUE: case INTERNALVAR_VALUE:
@ -2612,7 +2611,7 @@ preserve_one_varobj (struct varobj *varobj, struct objfile *objfile,
&& varobj->type->objfile_owner () == objfile) && varobj->type->objfile_owner () == objfile)
{ {
varobj->type varobj->type
= copy_type_recursive (objfile, varobj->type, copied_types); = copy_type_recursive (varobj->type, copied_types);
} }
if (varobj->value != nullptr) if (varobj->value != nullptr)
@ -2632,7 +2631,7 @@ preserve_values (struct objfile *objfile)
/* Create the hash table. We allocate on the objfile's obstack, since /* Create the hash table. We allocate on the objfile's obstack, since
it is soon to be deleted. */ it is soon to be deleted. */
htab_up copied_types = create_copied_types_hash (objfile); htab_up copied_types = create_copied_types_hash ();
for (const value_ref_ptr &item : value_history) for (const value_ref_ptr &item : value_history)
preserve_one_value (item.get (), objfile, copied_types.get ()); preserve_one_value (item.get (), objfile, copied_types.get ());