* [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