diff options
author | Daniel Jacobowitz <dan@debian.org> | 2004-02-24 03:27:21 +0000 |
---|---|---|
committer | Daniel Jacobowitz <dan@debian.org> | 2004-02-24 03:27:21 +0000 |
commit | 1c84ee9362c31259204fb2e8aacfdaaeb529d931 (patch) | |
tree | c73cd114167d6ddd4598093f74b965313bd786f6 /gdb | |
parent | eae3198ce301d74478dfa4e59240bc0adc822ca8 (diff) | |
download | gdb-1c84ee9362c31259204fb2e8aacfdaaeb529d931.tar.gz |
* dwarf2read.c (MAX_CACHE_AGE): Lower to 5.
(struct dwarf2_cu): Add dependencies and mark fields.
(free_one_comp_unit): New function, broken out from
free_comp_units_worker.
(dwarf2_add_dependence, dwarf2_clear_marks, dwarf2_mark)
(dwarf2_mark_helper): New functions.
(psymtab_to_symtab_1): Call free_one_comp_unit. Re-enable
aging.
(read_full_die): Call dwarf2_add_dependence.
(free_comp_units_worker): Call free_one_comp_unit. Use
marking to free old comp units.
Diffstat (limited to 'gdb')
-rw-r--r-- | gdb/ChangeLog.intercu | 14 | ||||
-rw-r--r-- | gdb/dwarf2read.c | 139 |
2 files changed, 127 insertions, 26 deletions
diff --git a/gdb/ChangeLog.intercu b/gdb/ChangeLog.intercu index 1a101374006..a3c6be777a5 100644 --- a/gdb/ChangeLog.intercu +++ b/gdb/ChangeLog.intercu @@ -1,5 +1,19 @@ 2004-02-23 Daniel Jacobowitz <drow@mvista.com> + * dwarf2read.c (MAX_CACHE_AGE): Lower to 5. + (struct dwarf2_cu): Add dependencies and mark fields. + (free_one_comp_unit): New function, broken out from + free_comp_units_worker. + (dwarf2_add_dependence, dwarf2_clear_marks, dwarf2_mark) + (dwarf2_mark_helper): New functions. + (psymtab_to_symtab_1): Call free_one_comp_unit. Re-enable + aging. + (read_full_die): Call dwarf2_add_dependence. + (free_comp_units_worker): Call free_one_comp_unit. Use + marking to free old comp units. + +2004-02-23 Daniel Jacobowitz <drow@mvista.com> + * dwarf2read.c (struct dwarf2_cu): Add dies. (struct dwarf2_per_cu_data): Shrink length field to add new queued flag. diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c index 66303177b50..d1b6f64a45e 100644 --- a/gdb/dwarf2read.c +++ b/gdb/dwarf2read.c @@ -52,9 +52,12 @@ #include "gdb_assert.h" #include <sys/types.h> -/* Loaded secondary compilation units are kept in memory until they have not - been referenced for the processing of this many compilation units. */ -#define MAX_CACHE_AGE 20 +/* Loaded secondary compilation units are kept in memory until they + have not been referenced for the processing of this many + compilation units. Set this to zero to disable caching. Cache + sizes of up to at least twenty will improve startup time for + typical inter-CU-reference binaries, at an obvious memory cost. */ +#define MAX_CACHE_AGE 5 #ifndef DWARF2_REG_TO_REGNUM #define DWARF2_REG_TO_REGNUM(REG) (REG) @@ -336,6 +339,14 @@ struct dwarf2_cu /* Full DIEs if read in. */ struct die_info *dies; + + /* A tree of pointers to dwarf2_per_cu_data objects for compilation + units referenced by this one. Only set during full symbol processing; + partial symbol tables do not have dependencies. */ + splay_tree dependencies; + + /* Mark used when releasing cached dies. */ + unsigned int mark : 1; }; struct dwarf2_per_cu_data @@ -976,6 +987,8 @@ static struct dwarf2_per_cu_data *dwarf2_find_containing_comp_unit static struct partial_symtab *dwarf2_find_comp_unit_psymtab (unsigned int offset, struct objfile *objfile); +static void free_one_comp_unit (struct dwarf2_cu *); + static void clear_per_cu_pointer (void *); static void free_cached_comp_units (void *); @@ -998,6 +1011,13 @@ static struct dwarf2_cu *load_full_comp_unit (struct partial_symtab *, static void process_full_comp_unit (struct partial_symtab *, struct dwarf2_cu *); +static void dwarf2_add_dependence (struct dwarf2_cu *, + struct dwarf2_per_cu_data *); + +static void dwarf2_mark (struct dwarf2_cu *); + +static void dwarf2_clear_marks (struct dwarf2_per_cu_data *); + /* Allocation function for the libiberty splay tree which uses an obstack. */ static void * splay_tree_obstack_allocate (int size, void *data) @@ -2347,11 +2367,7 @@ psymtab_to_symtab_1 (struct partial_symtab *pst) struct dwarf2_cu *cu; cu = load_full_comp_unit (pst, NULL); process_full_comp_unit (pst, cu); - /* FIXME: This is in two places now. That's one too many. */ - obstack_free (&cu->partial_die_obstack, NULL); - if (cu->dies) - free_die_list (cu->dies); - xfree (cu); + free_one_comp_unit (cu); } else { @@ -2369,20 +2385,10 @@ psymtab_to_symtab_1 (struct partial_symtab *pst) process_queue (pst->objfile); - /* FIXME drow/2004-02-23: Obviously, this is bad. We want to - keep compilation units in memory. The problem is that we do - not currently store the dependence information, so CUs used - by a cached CU may drop out of the cache before it does. - Then we don't know to reload them, but we never should have - let them go at all. When some dependence graph is - implemented, we can re-enable aging. Be careful of cycles! - - This is a very important performance improvement. My testing - shows a factor of six loss from disabling the caching. */ -#if 0 + /* Aging is a very important performance improvement. My + testing shows a factor of six loss from disabling the + caching. */ age_cached_comp_units (NULL); -#endif - free_cached_comp_units (NULL); } } @@ -5391,6 +5397,8 @@ read_full_die (struct die_info **diep, bfd *abfd, char *info_ptr, per_cu = dwarf2_find_containing_comp_unit (DW_ADDR (&die->attrs[i]), cu); + dwarf2_add_dependence (cu, per_cu); + /* If it's already on the queue, we have nothing to do. */ if (per_cu->queued) continue; @@ -9087,6 +9095,17 @@ dwarf2_find_comp_unit_psymtab (unsigned int offset, struct objfile *objfile) offset); } +/* Release one cached compilation unit, CU. */ + +static void +free_one_comp_unit (struct dwarf2_cu *cu) +{ + obstack_free (&cu->partial_die_obstack, NULL); + if (cu->dies) + free_die_list (cu->dies); + xfree (cu); +} + /* Helper function for cleaning up the compilation unit cache. Walk this objfile's read_in_chain. If AGING, increase the age counter on each compilation unit, and free any that are too old. Otherwise, @@ -9098,6 +9117,19 @@ free_comp_units_worker (struct dwarf2_cu *target_cu, int aging) { struct dwarf2_per_cu_data *per_cu, **last_chain; + if (aging) + { + dwarf2_clear_marks (dwarf2_per_objfile->read_in_chain); + per_cu = dwarf2_per_objfile->read_in_chain; + while (per_cu != NULL) + { + per_cu->cu->last_used ++; + if (per_cu->cu->last_used <= MAX_CACHE_AGE) + dwarf2_mark (per_cu->cu); + per_cu = per_cu->cu->read_in_chain; + } + } + per_cu = dwarf2_per_objfile->read_in_chain; last_chain = &dwarf2_per_objfile->read_in_chain; while (per_cu != NULL) @@ -9106,14 +9138,11 @@ free_comp_units_worker (struct dwarf2_cu *target_cu, int aging) next_cu = per_cu->cu->read_in_chain; - if ((aging && per_cu->cu->last_used > MAX_CACHE_AGE) + if ((aging && !per_cu->cu->mark) || (target_cu && per_cu->cu == target_cu) || (!aging && target_cu == NULL)) { - obstack_free (&per_cu->cu->partial_die_obstack, NULL); - if (per_cu->cu->dies) - free_die_list (per_cu->cu->dies); - xfree (per_cu->cu); + free_one_comp_unit (per_cu->cu); per_cu->cu = NULL; *last_chain = next_cu; } @@ -9247,6 +9276,64 @@ reset_die_and_siblings_types (struct die_info *start_die, struct dwarf2_cu *cu) } } +/* Add a dependence relationship from CU to REF_PER_CU. */ + +static void +dwarf2_add_dependence (struct dwarf2_cu *cu, + struct dwarf2_per_cu_data *ref_per_cu) +{ + if (cu->dependencies == NULL) + cu->dependencies + = splay_tree_new_with_allocator (splay_tree_compare_ints, + NULL, NULL, + splay_tree_obstack_allocate, + splay_tree_obstack_deallocate, + &cu->partial_die_obstack); + + if (splay_tree_lookup (cu->dependencies, ref_per_cu->offset) == NULL) + splay_tree_insert (cu->dependencies, ref_per_cu->offset, + (splay_tree_value) ref_per_cu); +} + +/* Set the mark field in CU and in every other compilation unit in the + cache that we must keep because we are keeping CU. */ + +static int +dwarf2_mark_helper (splay_tree_node node, void *data) +{ + struct dwarf2_per_cu_data *per_cu; + + per_cu = (struct dwarf2_per_cu_data *) node->value; + if (per_cu->cu->mark) + return 0; + per_cu->cu->mark = 1; + + if (per_cu->cu->dependencies != NULL) + splay_tree_foreach (per_cu->cu->dependencies, dwarf2_mark_helper, NULL); + + return 0; +} + +static void +dwarf2_mark (struct dwarf2_cu *cu) +{ + if (cu->mark) + return; + cu->mark = 1; + if (cu->dependencies != NULL) + splay_tree_foreach (cu->dependencies, dwarf2_mark_helper, NULL); +} + +static void +dwarf2_clear_marks (struct dwarf2_per_cu_data *per_cu) +{ + while (per_cu) + { + per_cu->cu->mark = 0; + per_cu = per_cu->cu->read_in_chain; + } +} + void _initialize_dwarf2_read (void); void |