* [patch] [1/5] Types reference counting [base]
@ 2009-04-11 10:21 Jan Kratochvil
2009-04-11 11:25 ` Eli Zaretskii
` (2 more replies)
0 siblings, 3 replies; 9+ messages in thread
From: Jan Kratochvil @ 2009-04-11 10:21 UTC (permalink / raw)
To: gdb-patches
Hi,
a base implementation of types reference counting.
Thanks,
Jan
gdb/
2009-04-11 Tom Tromey <tromey@redhat.com>
Jan Kratochvil <jan.kratochvil@redhat.com>
Start reference counting standalone allocated types.
* gdbtypes.c (struct type_group, struct type_group_link)
(type_group_link_table, type_group_age, alloc_type_discardable)
(alloc_type_as_parent): New.
(make_pointer_type, make_reference_type): Change alloc_type for
alloc_type_as_parent.
(copy_type_recursive): Change alloc_type for alloc_type_discardable.
(type_group_link_hash, type_group_link_equal, type_init_group)
(type_incref, type_decref): New.
(_initialize_gdbtypes): Initialize `type_group_link_table'.
* gdbtypes.h (type_incref, type_decref): New prototypes.
* value.c (allocate_value_lazy, deprecated_set_value_type, value_free)
(value_copy, preserve_one_value, value_static_field)
(value_primitive_field): Call type_incref and type_decref appropriately.
gdb/doc/
2009-04-11 Jan Kratochvil <jan.kratochvil@redhat.com>
* gdbint.texinfo (Symbol Handling): New anchor `Builtin Types'. Move
types `from Memory Management for Symbol Files' to a new subsection
`Memory Management for Types'.
diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c
index fb52e1a..c866353 100644
--- a/gdb/gdbtypes.c
+++ b/gdb/gdbtypes.c
@@ -146,7 +146,56 @@ static void print_bit_vector (B_TYPE *, int);
static void print_arg_types (struct field *, int, int);
static void dump_fn_fieldlists (struct type *, int);
static void print_cplus_stuff (struct type *, int);
+static void type_init_group (struct type *type);
+/* Any type structures which are connected through their `struct type *' are
+ tracked by the same type_group. Only the discardable (neither permanent
+ types nor types allocated from objfile obstack) type structures get tracked
+ by type_group structures. */
+
+struct type_group
+{
+ /* Sum of all the external references to any of the type structures tracked
+ by this type_group. */
+ int use_count;
+
+ /* Number of the type_group_links structures tracked by this type_group. It
+ matches the length of list `link_list->group_next->...->group_next'. */
+ int link_count;
+
+ /* Head of an unordered list of all type structures of this type_group. Next
+ items are linked by `type_group_link->group_next'. */
+ struct type_group_link *link_list;
+};
+
+/* Linking entry between a type structure and type_group structure. Only
+ discardable types have such link present. This link exists only once for
+ each discardable main_type, all type instances for such one main_type should
+ be iterated by `TYPE_CHAIN (type_group_link->type)'. */
+
+struct type_group_link
+{
+ /* Arbitrary type for main_type being represented by this type_group_link.
+ Each discardable main_type gets its separate type_group_link. */
+ struct type *type;
+
+ /* Marker this type_group_link has been visited by the type_group_link_check
+ graph traversal by this pass. Current pass is represented by
+ TYPE_GROUP_AGE. */
+ unsigned age : 1;
+
+ struct type_group *group;
+
+ /* Next type_group_link belonging to this type_group structure or NULL for
+ the last node of the list. */
+ struct type_group_link *group_next;
+};
+
+/* The hash table holding all `struct type_group_link *' references. */
+static htab_t type_group_link_table;
+
+/* Current type_group_link_check pass used for `type_group_link->age'. */
+static unsigned type_group_age;
/* Alloc a new type structure and fill it with some defaults. If
OBJFILE is non-NULL, then allocate the space for the type structure
@@ -183,6 +232,43 @@ alloc_type (struct objfile *objfile)
return type;
}
+/* Allocate a new type by an alloc_type call but make the new type discardable
+ on next garbage collection by free_all_types. Use type_incref for reference
+ counting of such new type. */
+
+static struct type *
+alloc_type_discardable (void)
+{
+ struct type *type = alloc_type (NULL);
+
+ type_init_group (type);
+
+ return type;
+}
+
+/* Allocate a new type like alloc_type or alloc_type_discardable copying the
+ discardability state of PARENT_TYPE (its current reference count
+ notwithstanding). */
+
+static struct type *
+alloc_type_as_parent (struct type *parent_type)
+{
+ struct type *type = alloc_type (TYPE_OBJFILE (parent_type));
+
+ if (TYPE_OBJFILE (parent_type) == NULL)
+ {
+ struct type_group_link link, *found;
+
+ link.type = type;
+ found = htab_find (type_group_link_table, &link);
+ /* Not a permanent type? */
+ if (found)
+ type_init_group (type);
+ }
+
+ return type;
+}
+
/* Alloc a new type instance structure, fill it with some defaults,
and point it at OLDTYPE. Allocate the new type instance from the
same place as OLDTYPE. */
@@ -248,7 +334,7 @@ make_pointer_type (struct type *type, struct type **typeptr)
if (typeptr == 0 || *typeptr == 0) /* We'll need to allocate one. */
{
- ntype = alloc_type (TYPE_OBJFILE (type));
+ ntype = alloc_type_as_parent (type);
if (typeptr)
*typeptr = ntype;
}
@@ -328,7 +414,7 @@ make_reference_type (struct type *type, struct type **typeptr)
if (typeptr == 0 || *typeptr == 0) /* We'll need to allocate one. */
{
- ntype = alloc_type (TYPE_OBJFILE (type));
+ ntype = alloc_type_as_parent (type);
if (typeptr)
*typeptr = ntype;
}
@@ -2954,7 +3040,7 @@ copy_type_recursive (struct objfile *objfile,
if (*slot != NULL)
return ((struct type_pair *) *slot)->new;
- new_type = alloc_type (NULL);
+ new_type = alloc_type_discardable ();
/* We must add the new type to the hash table immediately, in case
we encounter this type again during a recursive call below. */
@@ -3068,6 +3154,102 @@ copy_type (const struct type *type)
return new_type;
}
+/* Hash function for type_group_link_table. */
+
+static hashval_t
+type_group_link_hash (const void *p)
+{
+ const struct type_group_link *link = p;
+
+ return htab_hash_pointer (TYPE_MAIN_TYPE (link->type));
+}
+
+/* Equality function for type_group_link_table. */
+
+static int
+type_group_link_equal (const void *a, const void *b)
+{
+ const struct type_group_link *left = a;
+ const struct type_group_link *right = b;
+
+ return TYPE_MAIN_TYPE (left->type) == TYPE_MAIN_TYPE (right->type);
+}
+
+/* Define currently permanent TYPE as being reclaimable during free_all_types.
+ TYPE is required to be now permanent. TYPE will be left with zero reference
+ count, early type_incref call is probably appropriate. */
+
+static void
+type_init_group (struct type *type)
+{
+ void **slot;
+ struct type_group *group;
+ struct type_group_link *link;
+
+ gdb_assert (TYPE_OBJFILE (type) == NULL);
+
+ group = XNEW (struct type_group);
+ link = XNEW (struct type_group_link);
+
+ group->use_count = 0;
+ group->link_count = 1;
+ group->link_list = link;
+
+ link->type = type;
+ link->age = type_group_age;
+ link->group = group;
+ link->group_next = NULL;
+
+ slot = htab_find_slot (type_group_link_table, link, INSERT);
+ gdb_assert (!*slot);
+ *slot = link;
+}
+
+/* Increment the reference count for TYPE. For permanent or objfile associated
+ types nothing happens. */
+
+void
+type_incref (struct type *type)
+{
+ struct type_group_link link, *found;
+
+ if (TYPE_OBJFILE (type))
+ return;
+
+ link.type = type;
+ found = htab_find (type_group_link_table, &link);
+ /* A permanent type? */
+ if (!found)
+ return;
+
+ found->group->use_count++;
+}
+
+/* Decrement the reference count for TYPE. For permanent or objfile associated
+ types nothing happens.
+
+ Even if TYPE has no more references still do not delete it as callers may
+ hold pointers to types dynamically generated by check_typedef. Always rely
+ just on the free_all_types garbage collector. */
+
+void
+type_decref (struct type *type)
+{
+ struct type_group_link link, *found;
+
+ if (TYPE_OBJFILE (type))
+ return;
+
+ link.type = type;
+ found = htab_find (type_group_link_table, &link);
+ /* A permanent type? */
+ if (!found)
+ return;
+
+ gdb_assert (found->group->use_count > 0);
+ found->group->use_count--;
+}
+
static struct type *
build_flt (int bit, char *name, const struct floatformat **floatformats)
{
@@ -3276,6 +3458,10 @@ _initialize_gdbtypes (void)
{
gdbtypes_data = gdbarch_data_register_post_init (gdbtypes_post_init);
+ type_group_link_table = htab_create_alloc (20, type_group_link_hash,
+ type_group_link_equal, NULL,
+ xcalloc, xfree);
+
/* FIXME: The following types are architecture-neutral. However,
they contain pointer_type and reference_type fields potentially
caching pointer or reference types that *are* architecture
diff --git a/gdb/gdbtypes.h b/gdb/gdbtypes.h
index 3c4e948..41cd7a3 100644
--- a/gdb/gdbtypes.h
+++ b/gdb/gdbtypes.h
@@ -1275,4 +1275,8 @@ extern struct type *copy_type_recursive (struct objfile *objfile,
extern struct type *copy_type (const struct type *type);
+extern void type_incref (struct type *type);
+
+extern void type_decref (struct type *type);
+
#endif /* GDBTYPES_H */
diff --git a/gdb/value.c b/gdb/value.c
index 9c08a41..38b4f91 100644
--- a/gdb/value.c
+++ b/gdb/value.c
@@ -247,7 +247,9 @@ allocate_value_lazy (struct type *type)
val->next = all_values;
all_values = val;
val->type = type;
+ type_incref (type);
val->enclosing_type = type;
+ type_incref (type);
VALUE_LVAL (val) = not_lval;
VALUE_ADDRESS (val) = 0;
VALUE_FRAME_ID (val) = null_frame_id;
@@ -357,6 +359,8 @@ value_type (struct value *value)
void
deprecated_set_value_type (struct value *value, struct type *type)
{
+ type_incref (type);
+ type_decref (value->type);
value->type = type;
}
@@ -574,6 +578,9 @@ value_free (struct value *val)
{
if (val)
{
+ type_decref (val->type);
+ type_decref (val->enclosing_type);
+
if (VALUE_LVAL (val) == lval_computed)
{
struct lval_funcs *funcs = val->location.computed.funcs;
@@ -677,6 +684,8 @@ value_copy (struct value *arg)
val = allocate_value_lazy (encl_type);
else
val = allocate_value (encl_type);
+ type_incref (arg->type);
+ type_decref (val->type);
val->type = arg->type;
VALUE_LVAL (val) = VALUE_LVAL (arg);
val->location = arg->location;
@@ -1163,12 +1172,22 @@ preserve_one_value (struct value *value, struct objfile *objfile,
htab_t copied_types)
{
if (TYPE_OBJFILE (value->type) == objfile)
- value->type = copy_type_recursive (objfile, value->type, copied_types);
+ {
+ /* No need to decref the old type here, since we know it has no
+ reference count. */
+ value->type = copy_type_recursive (objfile, value->type, copied_types);
+ type_incref (value->type);
+ }
if (TYPE_OBJFILE (value->enclosing_type) == objfile)
- value->enclosing_type = copy_type_recursive (objfile,
- value->enclosing_type,
- copied_types);
+ {
+ /* No need to decref the old type here, since we know it has no
+ reference count. */
+ value->enclosing_type = copy_type_recursive (objfile,
+ value->enclosing_type,
+ copied_types);
+ type_incref (value->enclosing_type);
+ }
}
/* Update the internal variables and value history when OBJFILE is
@@ -1557,6 +1576,8 @@ value_static_field (struct type *type, int fieldno)
struct value *
value_change_enclosing_type (struct value *val, struct type *new_encl_type)
{
+ type_incref (new_encl_type);
+ type_decref (val->enclosing_type);
if (TYPE_LENGTH (new_encl_type) > TYPE_LENGTH (value_enclosing_type (val)))
val->contents =
(gdb_byte *) xrealloc (val->contents, TYPE_LENGTH (new_encl_type));
@@ -1612,6 +1633,8 @@ value_primitive_field (struct value *arg1, int offset,
memcpy (value_contents_all_raw (v), value_contents_all_raw (arg1),
TYPE_LENGTH (value_enclosing_type (arg1)));
}
+ type_incref (type);
+ type_decref (v->type);
v->type = type;
v->offset = value_offset (arg1);
v->embedded_offset = (offset + value_embedded_offset (arg1)
diff --git a/gdb/doc/gdbint.texinfo b/gdb/doc/gdbint.texinfo
index 187da2f..ea8696c 100644
--- a/gdb/doc/gdbint.texinfo
+++ b/gdb/doc/gdbint.texinfo
@@ -2320,6 +2320,7 @@ types map to one @code{TYPE_CODE_*} type, and are distinguished by
other members of the type struct, such as whether the type is signed
or unsigned, and how many bits it uses.
+@anchor{Builtin Types}
@unnumberedsubsec Builtin Types (e.g., @code{builtin_type_void}, @code{builtin_type_char}).
These are instances of type structs that roughly correspond to
@@ -2523,10 +2524,39 @@ released when the objfile is unloaded or reloaded. Therefore one
objfile must not reference symbol or type data from another objfile;
they could be unloaded at different times.
-User convenience variables, et cetera, have associated types. Normally
-these types live in the associated objfile. However, when the objfile
-is unloaded, those types are deep copied to global memory, so that
-the values of the user variables and history items are not lost.
+@subsection Memory Management for Types
+
+@code{TYPE_OBJFILE} macro indicates the current memory owner of the type.
+Non-@code{NULL} value indicates it is owned by an objfile (specifically by its
+obstack) and in such case the type remains valid till the objfile is unloaded
+or reloaded. For such types with an associated objfile no reference counting
+is being made.
+
+User convenience variables, et cetera, have associated types. Normally these
+types live in the associated objfile. However, when the objfile is unloaded,
+those types are deep copied to global memory, so that the values of the user
+variables and history items are not lost. During the copy they will get their
+@code{TYPE_OBJFILE} set to @code{NULL} and become so called reclaimable types.
+
+Types with @code{NULL TYPE_OBJFILE} can be either permanent types
+(@pxref{Builtin Types}) or reclaimable types which will be deallocated after the
+last object referencing them is removed. Permanent types are allocated by the
+function @code{alloc_type} (and its derivations like @code{init_type})
+specifying objfile as @code{NULL}. The reclaimable types are created the same
+way but moreover they need to have @code{type_init_group} called to start their
+tracking as being possibly deallocatable.
+
+When @value{GDBN} gets idle it always calls the @code{free_all_types} function
+which deallocates any unused types. To prevent deallocation of types still in
+use you must use @code{type_incref} (and matching @code{type_decref}) for
+reference counting of any reclaimable type. You will probably need to first
+increase the reference count right after calling @code{type_init_group}.
+
+@code{free_all_types} automatically checks for any cross-type references such
+as through @code{TYPE_TARGET_TYPE}, @code{TYPE_POINTER_TYPE} etc. and prevents
+early deallocation for any such existing references. Reclaimable types may
+reference any other reclaimable types or even permanent types. But permanent
+types must not reference reclaimable types (nor an objfile associated type).
@node Language Support
^ permalink raw reply [flat|nested] 9+ messages in thread* Re: [patch] [1/5] Types reference counting [base] 2009-04-11 10:21 [patch] [1/5] Types reference counting [base] Jan Kratochvil @ 2009-04-11 11:25 ` Eli Zaretskii 2009-04-11 18:15 ` Jan Kratochvil 2009-04-16 21:26 ` Tom Tromey 2009-05-25 8:10 ` obsolete: " Jan Kratochvil 2 siblings, 1 reply; 9+ messages in thread From: Eli Zaretskii @ 2009-04-11 11:25 UTC (permalink / raw) To: Jan Kratochvil; +Cc: gdb-patches > Date: Sat, 11 Apr 2009 12:20:45 +0200 > From: Jan Kratochvil <jan.kratochvil@redhat.com> > > a base implementation of types reference counting. Thanks. > gdb/doc/ Thanks, I have a few comments about this part of your patch. > 2009-04-11 Jan Kratochvil <jan.kratochvil@redhat.com> > > * gdbint.texinfo (Symbol Handling): New anchor `Builtin Types'. Move > types `from Memory Management for Symbol Files' to a new subsection > `Memory Management for Types'. Please also add in the log an entry which explicitly says that `Memory Management for Types' was added ("New node."). See below. > +@subsection Memory Management for Types I'd prefer not to have sections without an associated @node. Such a manual is harder to navigate. Please add a @node here. That's assuming that having a separate subsection here is justified; maybe it isn't. Also, a @cindex entry (with the same text as the subsection name, only in lower case) would be useful here. > +@code{TYPE_OBJFILE} macro indicates the current memory owner of the type. It would be good to have a @findex entry for each macro you describe (TYPE_OBJFILE etc.). > +@code{TYPE_OBJFILE} set to @code{NULL} and become so called reclaimable types. "so-called", with a dash, and I suggest a @dfn around "reclaimable types", since you are introducing new terminology. > +Types with @code{NULL TYPE_OBJFILE} can be either permanent types Please don't put @code around several separate words, because that causes the whitespace to be typeset incorrectly. Please use a separate @code for each word. Actually, I'd reword this as Types with @code{TYPE_OBJFILE} set to @code{NULL} can be .. or Types with null @code{TYPE_OBJFILE} can be ... > +(@pxref{Builtin Types}) or reclaimable types which will be deallocated after the > +last object referencing them is removed. But the text below says that actually they will be deallocated only when GDB becomes idle, right? > +as through @code{TYPE_TARGET_TYPE}, @code{TYPE_POINTER_TYPE} etc. and prevents ^^ Please add either a @: or a comma after any period that doesn't end a sentence, so that TeX would not typeset that as a sentence end. ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [patch] [1/5] Types reference counting [base] 2009-04-11 11:25 ` Eli Zaretskii @ 2009-04-11 18:15 ` Jan Kratochvil 2009-04-11 19:30 ` Eli Zaretskii 0 siblings, 1 reply; 9+ messages in thread From: Jan Kratochvil @ 2009-04-11 18:15 UTC (permalink / raw) To: Eli Zaretskii; +Cc: gdb-patches Hi Eli, included an updated patch, only the doc part is updated. On Sat, 11 Apr 2009 13:24:56 +0200, Eli Zaretskii wrote: > > +(@pxref{Builtin Types}) or reclaimable types which will be deallocated after the > > +last object referencing them is removed. > > But the text below says that actually they will be deallocated only > when GDB becomes idle, right? You are right, now it reads: Types with null @code{TYPE_OBJFILE} can be either permanent types (@pxref{Builtin Types}) or reclaimable types which will be deallocated at the first idle @value{GDBN} moment if the last object referencing them is removed. > > +as through @code{TYPE_TARGET_TYPE}, @code{TYPE_POINTER_TYPE} etc. and prevents > ^^ > Please add either a @: or a comma after any period that doesn't end a > sentence, so that TeX would not typeset that as a sentence end. Done, BTW do you know some way how to generate .tex (not .dvi or .pdf) from .texinfo? Thanks, Jan gdb/ 2009-04-11 Tom Tromey <tromey@redhat.com> Jan Kratochvil <jan.kratochvil@redhat.com> Start reference counting standalone allocated types. * gdbtypes.c (struct type_group, struct type_group_link) (type_group_link_table, type_group_age, alloc_type_discardable) (alloc_type_as_parent): New. (make_pointer_type, make_reference_type): Change alloc_type for alloc_type_as_parent. (copy_type_recursive): Change alloc_type for alloc_type_discardable. (type_group_link_hash, type_group_link_equal, type_init_group) (type_incref, type_decref): New. (_initialize_gdbtypes): Initialize `type_group_link_table'. * gdbtypes.h (type_incref, type_decref): New prototypes. * value.c (allocate_value_lazy, deprecated_set_value_type, value_free) (value_copy, preserve_one_value, value_static_field) (value_primitive_field): Call type_incref and type_decref appropriately. gdb/doc/ 2009-04-11 Jan Kratochvil <jan.kratochvil@redhat.com> * gdbint.texinfo (Symbol Handling): New menu. (Partial Symbol Tables, Object File Formats, Debugging File Formats) (Adding a New Symbol Reader to GDB): New nodes from existing sections. (Types): New node from existing section. New anchor `Builtin Types'. (Memory Management for Symbol Files): New node from existing section. Move types to ... (Memory Management for Types): ... here, in a new node. diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c index fb52e1a..c866353 100644 --- a/gdb/gdbtypes.c +++ b/gdb/gdbtypes.c @@ -146,7 +146,56 @@ static void print_bit_vector (B_TYPE *, int); static void print_arg_types (struct field *, int, int); static void dump_fn_fieldlists (struct type *, int); static void print_cplus_stuff (struct type *, int); +static void type_init_group (struct type *type); +/* Any type structures which are connected through their `struct type *' are + tracked by the same type_group. Only the discardable (neither permanent + types nor types allocated from objfile obstack) type structures get tracked + by type_group structures. */ + +struct type_group +{ + /* Sum of all the external references to any of the type structures tracked + by this type_group. */ + int use_count; + + /* Number of the type_group_links structures tracked by this type_group. It + matches the length of list `link_list->group_next->...->group_next'. */ + int link_count; + + /* Head of an unordered list of all type structures of this type_group. Next + items are linked by `type_group_link->group_next'. */ + struct type_group_link *link_list; +}; + +/* Linking entry between a type structure and type_group structure. Only + discardable types have such link present. This link exists only once for + each discardable main_type, all type instances for such one main_type should + be iterated by `TYPE_CHAIN (type_group_link->type)'. */ + +struct type_group_link +{ + /* Arbitrary type for main_type being represented by this type_group_link. + Each discardable main_type gets its separate type_group_link. */ + struct type *type; + + /* Marker this type_group_link has been visited by the type_group_link_check + graph traversal by this pass. Current pass is represented by + TYPE_GROUP_AGE. */ + unsigned age : 1; + + struct type_group *group; + + /* Next type_group_link belonging to this type_group structure or NULL for + the last node of the list. */ + struct type_group_link *group_next; +}; + +/* The hash table holding all `struct type_group_link *' references. */ +static htab_t type_group_link_table; + +/* Current type_group_link_check pass used for `type_group_link->age'. */ +static unsigned type_group_age; /* Alloc a new type structure and fill it with some defaults. If OBJFILE is non-NULL, then allocate the space for the type structure @@ -183,6 +232,43 @@ alloc_type (struct objfile *objfile) return type; } +/* Allocate a new type by an alloc_type call but make the new type discardable + on next garbage collection by free_all_types. Use type_incref for reference + counting of such new type. */ + +static struct type * +alloc_type_discardable (void) +{ + struct type *type = alloc_type (NULL); + + type_init_group (type); + + return type; +} + +/* Allocate a new type like alloc_type or alloc_type_discardable copying the + discardability state of PARENT_TYPE (its current reference count + notwithstanding). */ + +static struct type * +alloc_type_as_parent (struct type *parent_type) +{ + struct type *type = alloc_type (TYPE_OBJFILE (parent_type)); + + if (TYPE_OBJFILE (parent_type) == NULL) + { + struct type_group_link link, *found; + + link.type = type; + found = htab_find (type_group_link_table, &link); + /* Not a permanent type? */ + if (found) + type_init_group (type); + } + + return type; +} + /* Alloc a new type instance structure, fill it with some defaults, and point it at OLDTYPE. Allocate the new type instance from the same place as OLDTYPE. */ @@ -248,7 +334,7 @@ make_pointer_type (struct type *type, struct type **typeptr) if (typeptr == 0 || *typeptr == 0) /* We'll need to allocate one. */ { - ntype = alloc_type (TYPE_OBJFILE (type)); + ntype = alloc_type_as_parent (type); if (typeptr) *typeptr = ntype; } @@ -328,7 +414,7 @@ make_reference_type (struct type *type, struct type **typeptr) if (typeptr == 0 || *typeptr == 0) /* We'll need to allocate one. */ { - ntype = alloc_type (TYPE_OBJFILE (type)); + ntype = alloc_type_as_parent (type); if (typeptr) *typeptr = ntype; } @@ -2954,7 +3040,7 @@ copy_type_recursive (struct objfile *objfile, if (*slot != NULL) return ((struct type_pair *) *slot)->new; - new_type = alloc_type (NULL); + new_type = alloc_type_discardable (); /* We must add the new type to the hash table immediately, in case we encounter this type again during a recursive call below. */ @@ -3068,6 +3154,102 @@ copy_type (const struct type *type) return new_type; } +/* Hash function for type_group_link_table. */ + +static hashval_t +type_group_link_hash (const void *p) +{ + const struct type_group_link *link = p; + + return htab_hash_pointer (TYPE_MAIN_TYPE (link->type)); +} + +/* Equality function for type_group_link_table. */ + +static int +type_group_link_equal (const void *a, const void *b) +{ + const struct type_group_link *left = a; + const struct type_group_link *right = b; + + return TYPE_MAIN_TYPE (left->type) == TYPE_MAIN_TYPE (right->type); +} + +/* Define currently permanent TYPE as being reclaimable during free_all_types. + TYPE is required to be now permanent. TYPE will be left with zero reference + count, early type_incref call is probably appropriate. */ + +static void +type_init_group (struct type *type) +{ + void **slot; + struct type_group *group; + struct type_group_link *link; + + gdb_assert (TYPE_OBJFILE (type) == NULL); + + group = XNEW (struct type_group); + link = XNEW (struct type_group_link); + + group->use_count = 0; + group->link_count = 1; + group->link_list = link; + + link->type = type; + link->age = type_group_age; + link->group = group; + link->group_next = NULL; + + slot = htab_find_slot (type_group_link_table, link, INSERT); + gdb_assert (!*slot); + *slot = link; +} + +/* Increment the reference count for TYPE. For permanent or objfile associated + types nothing happens. */ + +void +type_incref (struct type *type) +{ + struct type_group_link link, *found; + + if (TYPE_OBJFILE (type)) + return; + + link.type = type; + found = htab_find (type_group_link_table, &link); + /* A permanent type? */ + if (!found) + return; + + found->group->use_count++; +} + +/* Decrement the reference count for TYPE. For permanent or objfile associated + types nothing happens. + + Even if TYPE has no more references still do not delete it as callers may + hold pointers to types dynamically generated by check_typedef. Always rely + just on the free_all_types garbage collector. */ + +void +type_decref (struct type *type) +{ + struct type_group_link link, *found; + + if (TYPE_OBJFILE (type)) + return; + + link.type = type; + found = htab_find (type_group_link_table, &link); + /* A permanent type? */ + if (!found) + return; + + gdb_assert (found->group->use_count > 0); + found->group->use_count--; +} + static struct type * build_flt (int bit, char *name, const struct floatformat **floatformats) { @@ -3276,6 +3458,10 @@ _initialize_gdbtypes (void) { gdbtypes_data = gdbarch_data_register_post_init (gdbtypes_post_init); + type_group_link_table = htab_create_alloc (20, type_group_link_hash, + type_group_link_equal, NULL, + xcalloc, xfree); + /* FIXME: The following types are architecture-neutral. However, they contain pointer_type and reference_type fields potentially caching pointer or reference types that *are* architecture diff --git a/gdb/gdbtypes.h b/gdb/gdbtypes.h index 3c4e948..41cd7a3 100644 --- a/gdb/gdbtypes.h +++ b/gdb/gdbtypes.h @@ -1275,4 +1275,8 @@ extern struct type *copy_type_recursive (struct objfile *objfile, extern struct type *copy_type (const struct type *type); +extern void type_incref (struct type *type); + +extern void type_decref (struct type *type); + #endif /* GDBTYPES_H */ diff --git a/gdb/value.c b/gdb/value.c index 9c08a41..38b4f91 100644 --- a/gdb/value.c +++ b/gdb/value.c @@ -247,7 +247,9 @@ allocate_value_lazy (struct type *type) val->next = all_values; all_values = val; val->type = type; + type_incref (type); val->enclosing_type = type; + type_incref (type); VALUE_LVAL (val) = not_lval; VALUE_ADDRESS (val) = 0; VALUE_FRAME_ID (val) = null_frame_id; @@ -357,6 +359,8 @@ value_type (struct value *value) void deprecated_set_value_type (struct value *value, struct type *type) { + type_incref (type); + type_decref (value->type); value->type = type; } @@ -574,6 +578,9 @@ value_free (struct value *val) { if (val) { + type_decref (val->type); + type_decref (val->enclosing_type); + if (VALUE_LVAL (val) == lval_computed) { struct lval_funcs *funcs = val->location.computed.funcs; @@ -677,6 +684,8 @@ value_copy (struct value *arg) val = allocate_value_lazy (encl_type); else val = allocate_value (encl_type); + type_incref (arg->type); + type_decref (val->type); val->type = arg->type; VALUE_LVAL (val) = VALUE_LVAL (arg); val->location = arg->location; @@ -1163,12 +1172,22 @@ preserve_one_value (struct value *value, struct objfile *objfile, htab_t copied_types) { if (TYPE_OBJFILE (value->type) == objfile) - value->type = copy_type_recursive (objfile, value->type, copied_types); + { + /* No need to decref the old type here, since we know it has no + reference count. */ + value->type = copy_type_recursive (objfile, value->type, copied_types); + type_incref (value->type); + } if (TYPE_OBJFILE (value->enclosing_type) == objfile) - value->enclosing_type = copy_type_recursive (objfile, - value->enclosing_type, - copied_types); + { + /* No need to decref the old type here, since we know it has no + reference count. */ + value->enclosing_type = copy_type_recursive (objfile, + value->enclosing_type, + copied_types); + type_incref (value->enclosing_type); + } } /* Update the internal variables and value history when OBJFILE is @@ -1557,6 +1576,8 @@ value_static_field (struct type *type, int fieldno) struct value * value_change_enclosing_type (struct value *val, struct type *new_encl_type) { + type_incref (new_encl_type); + type_decref (val->enclosing_type); if (TYPE_LENGTH (new_encl_type) > TYPE_LENGTH (value_enclosing_type (val))) val->contents = (gdb_byte *) xrealloc (val->contents, TYPE_LENGTH (new_encl_type)); @@ -1612,6 +1633,8 @@ value_primitive_field (struct value *arg1, int offset, memcpy (value_contents_all_raw (v), value_contents_all_raw (arg1), TYPE_LENGTH (value_enclosing_type (arg1))); } + type_incref (type); + type_decref (v->type); v->type = type; v->offset = value_offset (arg1); v->embedded_offset = (offset + value_embedded_offset (arg1) diff --git a/gdb/doc/gdbint.texinfo b/gdb/doc/gdbint.texinfo index 187da2f..e937663 100644 --- a/gdb/doc/gdbint.texinfo +++ b/gdb/doc/gdbint.texinfo @@ -2111,6 +2111,18 @@ time, and so we attempt to handle symbols incrementally. For instance, we create @dfn{partial symbol tables} consisting of only selected symbols, and only expand them to full symbol tables when necessary. +@menu +* Symbol Reading:: +* Partial Symbol Tables:: +* Types:: +* Object File Formats:: +* Debugging File Formats:: +* Adding a New Symbol Reader to GDB:: +* Memory Management for Symbol Files:: +* Memory Management for Types:: +@end menu + +@node Symbol Reading @section Symbol Reading @cindex symbol reading @@ -2203,6 +2215,7 @@ symtab. Upon return, @code{pst->readin} should have been set to 1, and zero if there were no symbols in that part of the symbol file. @end table +@node Partial Symbol Tables @section Partial Symbol Tables @value{GDBN} has three types of symbol tables: @@ -2298,6 +2311,7 @@ and all the psymbols themselves are allocated in a pair of large arrays on an obstack, so there is little to be gained by trying to free them unless you want to do a lot more work. +@node Types @section Types @unnumberedsubsec Fundamental Types (e.g., @code{FT_VOID}, @code{FT_BOOLEAN}). @@ -2320,6 +2334,7 @@ types map to one @code{TYPE_CODE_*} type, and are distinguished by other members of the type struct, such as whether the type is signed or unsigned, and how many bits it uses. +@anchor{Builtin Types} @unnumberedsubsec Builtin Types (e.g., @code{builtin_type_void}, @code{builtin_type_char}). These are instances of type structs that roughly correspond to @@ -2334,6 +2349,7 @@ only one instance exists, while @file{c-lang.c} builds as many @code{TYPE_CODE_INT} types as needed, with each one associated with some particular objfile. +@node Object File Formats @section Object File Formats @cindex object file formats @@ -2419,6 +2435,7 @@ SOM, which is a cross-language ABI). The SOM reader is in @file{somread.c}. +@node Debugging File Formats @section Debugging File Formats This section describes characteristics of debugging information that @@ -2490,6 +2507,7 @@ DWARF 3 is an improved version of DWARF 2. @cindex SOM debugging info Like COFF, the SOM definition includes debugging information. +@node Adding a New Symbol Reader to GDB @section Adding a New Symbol Reader to @value{GDBN} @cindex adding debugging info reader @@ -2512,6 +2530,7 @@ will only ever be implemented by one object file format may be called directly. This interface should be described in a file @file{bfd/lib@var{xyz}.h}, which is included by @value{GDBN}. +@node Memory Management for Symbol Files @section Memory Management for Symbol Files Most memory associated with a loaded symbol file is stored on @@ -2523,10 +2542,46 @@ released when the objfile is unloaded or reloaded. Therefore one objfile must not reference symbol or type data from another objfile; they could be unloaded at different times. -User convenience variables, et cetera, have associated types. Normally -these types live in the associated objfile. However, when the objfile -is unloaded, those types are deep copied to global memory, so that -the values of the user variables and history items are not lost. +@node Memory Management for Types +@section Memory Management for Types +@cindex memory management for types + +@findex TYPE_OBJFILE +@code{TYPE_OBJFILE} macro indicates the current memory owner of the type. +Non-@code{NULL} value indicates it is owned by an objfile (specifically by its +obstack) and in such case the type remains valid till the objfile is unloaded +or reloaded. For such types with an associated objfile no reference counting +is being made. + +User convenience variables, et cetera, have associated types. Normally these +types live in the associated objfile. However, when the objfile is unloaded, +those types are deep copied to global memory, so that the values of the user +variables and history items are not lost. During the copy they will get their +@code{TYPE_OBJFILE} set to @code{NULL} and become so-called @dfn{reclaimable} +types. + +Types with null @code{TYPE_OBJFILE} can be either permanent types +(@pxref{Builtin Types}) or reclaimable types which will be deallocated at the +first idle @value{GDBN} moment if the last object referencing them is removed. +Permanent types are allocated by the function @code{alloc_type} (and its +derivations like @code{init_type}) specifying objfile as @code{NULL}. The +reclaimable types are created the same way but moreover they need to have +@code{type_init_group} called to start their tracking as being possibly +deallocatable. + +@findex free_all_types +When @value{GDBN} gets idle it always calls the @code{free_all_types} function +which deallocates any unused types. To prevent deallocation of types still in +use you must use @code{type_incref} (and matching @code{type_decref}) for +reference counting of any reclaimable type. You will probably need to first +increase the reference count right after calling @code{type_init_group}. + +@code{free_all_types} automatically checks for any cross-type references such +as through @code{TYPE_TARGET_TYPE}, @code{TYPE_POINTER_TYPE} etc.@: and +prevents early deallocation for any such existing references. Reclaimable +types may reference any other reclaimable types or even permanent types. But +permanent types must not reference reclaimable types (nor an objfile associated +type). @node Language Support ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [patch] [1/5] Types reference counting [base] 2009-04-11 18:15 ` Jan Kratochvil @ 2009-04-11 19:30 ` Eli Zaretskii 2009-04-11 19:45 ` Jan Kratochvil 0 siblings, 1 reply; 9+ messages in thread From: Eli Zaretskii @ 2009-04-11 19:30 UTC (permalink / raw) To: Jan Kratochvil; +Cc: gdb-patches > Date: Sat, 11 Apr 2009 20:15:23 +0200 > From: Jan Kratochvil <jan.kratochvil@redhat.com> > Cc: gdb-patches@sourceware.org > > included an updated patch, only the doc part is updated. It's fine with me, thanks. > BTW do you know some way how to generate .tex (not .dvi or .pdf) from > .texinfo? There's no way, AFAIK. Why do you need that? ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [patch] [1/5] Types reference counting [base] 2009-04-11 19:30 ` Eli Zaretskii @ 2009-04-11 19:45 ` Jan Kratochvil 2009-04-11 21:10 ` Eli Zaretskii 0 siblings, 1 reply; 9+ messages in thread From: Jan Kratochvil @ 2009-04-11 19:45 UTC (permalink / raw) To: Eli Zaretskii; +Cc: gdb-patches On Sat, 11 Apr 2009 21:29:57 +0200, Eli Zaretskii wrote: > > BTW do you know some way how to generate .tex (not .dvi or .pdf) from > > .texinfo? > > There's no way, AFAIK. Why do you need that? As you were objecting the @: formatting which has no effect on the .info files and with my eyes I could not even find a visual difference for the .pdf files. I was just automatically attempting to verify the fix, no problem. Thanks, Jan ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [patch] [1/5] Types reference counting [base] 2009-04-11 19:45 ` Jan Kratochvil @ 2009-04-11 21:10 ` Eli Zaretskii 2009-04-11 21:21 ` Jan Kratochvil 0 siblings, 1 reply; 9+ messages in thread From: Eli Zaretskii @ 2009-04-11 21:10 UTC (permalink / raw) To: Jan Kratochvil; +Cc: gdb-patches > Date: Sat, 11 Apr 2009 21:45:31 +0200 > From: Jan Kratochvil <jan.kratochvil@redhat.com> > Cc: gdb-patches@sourceware.org > > On Sat, 11 Apr 2009 21:29:57 +0200, Eli Zaretskii wrote: > > > BTW do you know some way how to generate .tex (not .dvi or .pdf) from > > > .texinfo? > > > > There's no way, AFAIK. Why do you need that? > > As you were objecting the @: formatting which has no effect on the .info files > and with my eyes I could not even find a visual difference for the .pdf files. Well, the Texinfo manual instructs to do so, see the node "Not Ending a Sentence" there. I don't think I ever measured the difference myself. In any case, if it were possible to generate .tex from a Texinfo source, this difference would not be visible there, because .tex is _input_ to TeX, not its output. The output is DVI. ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [patch] [1/5] Types reference counting [base] 2009-04-11 21:10 ` Eli Zaretskii @ 2009-04-11 21:21 ` Jan Kratochvil 0 siblings, 0 replies; 9+ messages in thread From: Jan Kratochvil @ 2009-04-11 21:21 UTC (permalink / raw) To: Eli Zaretskii; +Cc: gdb-patches On Sat, 11 Apr 2009 23:09:54 +0200, Eli Zaretskii wrote: > In any case, if it were possible to generate .tex from a Texinfo > source, this difference would not be visible there, Found out now texi2dvi is just a shell script. Just @: is left there intact as it is all processed directly by texinfo.tex and its catcode of `@'. So you are right seeing the .tex file does not help in any way. Thanks, Jan ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [patch] [1/5] Types reference counting [base] 2009-04-11 10:21 [patch] [1/5] Types reference counting [base] Jan Kratochvil 2009-04-11 11:25 ` Eli Zaretskii @ 2009-04-16 21:26 ` Tom Tromey 2009-05-25 8:10 ` obsolete: " Jan Kratochvil 2 siblings, 0 replies; 9+ messages in thread From: Tom Tromey @ 2009-04-16 21:26 UTC (permalink / raw) To: gdb-patches >>>>> "Jan" == Jan Kratochvil <jan.kratochvil@redhat.com> writes: Jan> a base implementation of types reference counting. This is ok. Tom ^ permalink raw reply [flat|nested] 9+ messages in thread
* obsolete: Re: [patch] [1/5] Types reference counting [base] 2009-04-11 10:21 [patch] [1/5] Types reference counting [base] Jan Kratochvil 2009-04-11 11:25 ` Eli Zaretskii 2009-04-16 21:26 ` Tom Tromey @ 2009-05-25 8:10 ` Jan Kratochvil 2 siblings, 0 replies; 9+ messages in thread From: Jan Kratochvil @ 2009-05-25 8:10 UTC (permalink / raw) To: gdb-patches This patch (not checked in) got now obsoleted by: [patch 5/8] Types GC [type_group framework] http://sourceware.org/ml/gdb-patches/2009-05/msg00548.html ^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2009-05-25 8:10 UTC | newest] Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2009-04-11 10:21 [patch] [1/5] Types reference counting [base] Jan Kratochvil 2009-04-11 11:25 ` Eli Zaretskii 2009-04-11 18:15 ` Jan Kratochvil 2009-04-11 19:30 ` Eli Zaretskii 2009-04-11 19:45 ` Jan Kratochvil 2009-04-11 21:10 ` Eli Zaretskii 2009-04-11 21:21 ` Jan Kratochvil 2009-04-16 21:26 ` Tom Tromey 2009-05-25 8:10 ` obsolete: " Jan Kratochvil
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox