diff options
author | Pedro Alves <palves@redhat.com> | 2016-03-26 00:42:38 +0000 |
---|---|---|
committer | Pedro Alves <palves@redhat.com> | 2016-09-19 15:44:41 +0100 |
commit | 7877d8a30a85ce7edbf60f00619943c27caea9e7 (patch) | |
tree | 65502ab21612b0f86f01d2dfba3b60f8c7a8b830 | |
parent | 893297fc25371792fc58c6e197dc3dfdd5651608 (diff) | |
download | gdb-7877d8a30a85ce7edbf60f00619943c27caea9e7.zip gdb-7877d8a30a85ce7edbf60f00619943c27caea9e7.tar.gz gdb-7877d8a30a85ce7edbf60f00619943c27caea9e7.tar.bz2 |
Stale objfile_unlink comment
07cd4b97 added the internal_error
The next bootleneck is adding/removing objfiles from the list of
objfiles... The problem is that we iterate over the list looking for
the tail objfile every single time. When we have thousands of
objfiles, that's costly.
So keep a tail pointer to the list instead.
-rw-r--r-- | gdb/objfiles.c | 107 | ||||
-rw-r--r-- | gdb/objfiles.h | 11 | ||||
-rw-r--r-- | gdb/progspace.h | 5 |
3 files changed, 66 insertions, 57 deletions
diff --git a/gdb/objfiles.c b/gdb/objfiles.c index 0a708bb..ddefd12 100644 --- a/gdb/objfiles.c +++ b/gdb/objfiles.c @@ -53,6 +53,8 @@ #include "gdb_bfd.h" #include "btrace.h" +static void add_tail_objfile (struct objfile *objfile); + /* Keep a registry of per-objfile data-pointers required by other GDB modules. */ @@ -424,20 +426,7 @@ allocate_objfile (bfd *abfd, const char *name, int flags) objfile->sect_index_bss = -1; objfile->sect_index_rodata = -1; - /* Add this file onto the tail of the linked list of other such files. */ - - objfile->next = NULL; - if (object_files == NULL) - object_files = objfile; - else - { - struct objfile *last_one; - - for (last_one = object_files; - last_one->next; - last_one = last_one->next); - last_one->next = objfile; - } + add_tail_objfile (objfile); /* Save passed in flag bits. */ objfile->flags |= flags; @@ -522,60 +511,78 @@ objfile_separate_debug_iterate (const struct objfile *parent, return NULL; } -/* Put one object file before a specified on in the global list. +/* Put one object file before a specified one in the global list. This can be used to make sure an object file is destroyed before another when using ALL_OBJFILES_SAFE to free all objfiles. */ -void + +static void put_objfile_before (struct objfile *objfile, struct objfile *before_this) { struct objfile **objp; + gdb_assert (objfile != NULL && before_this != NULL); + gdb_assert (objfile != before_this); + unlink_objfile (objfile); - - for (objp = &object_files; *objp != NULL; objp = &((*objp)->next)) + + objfile->next = before_this; + objfile->prev = before_this->prev; + + if (before_this == objfile->pspace->objfiles) + objfile->pspace->objfiles = objfile; + else + before_this->prev->next = objfile; + + if (objfile == objfile->pspace->objfiles_tail) + objfile->pspace->objfiles_tail = before_this; + + before_this->prev = objfile; +} + +/* Add this file onto the tail of the linked list of other such + files. */ + +static void +add_tail_objfile (struct objfile *objfile) +{ + gdb_assert (objfile != NULL); + + if (objfile->pspace->objfiles == NULL) { - if (*objp == before_this) - { - objfile->next = *objp; - *objp = objfile; - return; - } + objfile->pspace->objfiles = objfile; + objfile->pspace->objfiles_tail = objfile; } - - internal_error (__FILE__, __LINE__, - _("put_objfile_before: before objfile not in list")); -} + else + { + struct objfile *last_one = objfile->pspace->objfiles_tail; -/* Unlink OBJFILE from the list of known objfiles, if it is found in the - list. + gdb_assert (objfile != last_one); - It is not a bug, or error, to call this function if OBJFILE is not known - to be in the current list. This is done in the case of mapped objfiles, - for example, just to ensure that the mapped objfile doesn't appear twice - in the list. Since the list is threaded, linking in a mapped objfile - twice would create a circular list. + last_one->next = objfile; + objfile->prev = last_one; - If OBJFILE turns out to be in the list, we zap it's NEXT pointer after - unlinking it, just to ensure that we have completely severed any linkages - between the OBJFILE and the list. */ + objfile->pspace->objfiles_tail = objfile; + } +} + +/* Unlink OBJFILE from the list of known objfiles. OBJFILE must be in + the list. */ void unlink_objfile (struct objfile *objfile) { - struct objfile **objpp; + if (objfile->prev == NULL) + objfile->pspace->objfiles = objfile->next; + else + objfile->prev->next = objfile->next; - for (objpp = &object_files; *objpp != NULL; objpp = &((*objpp)->next)) - { - if (*objpp == objfile) - { - *objpp = (*objpp)->next; - objfile->next = NULL; - return; - } - } + if (objfile->next == NULL) + objfile->pspace->objfiles_tail = objfile->prev; + else + objfile->next->prev = objfile->prev; - internal_error (__FILE__, __LINE__, - _("unlink_objfile: objfile already unlinked")); + objfile->prev = NULL; + objfile->next = NULL; } /* Add OBJFILE as a separate debug objfile of PARENT. */ diff --git a/gdb/objfiles.h b/gdb/objfiles.h index 855f831..bfb7781 100644 --- a/gdb/objfiles.h +++ b/gdb/objfiles.h @@ -272,11 +272,14 @@ struct objfile_per_bfd_storage struct objfile { - /* All struct objfile's are chained together by their next pointers. - The program space field "objfiles" (frequently referenced via - the macro "object_files") points to the first link in this chain. */ + /* All struct objfile's are chained together by their prev/next + pointers. The program space field "objfiles" (frequently + referenced via the macro "object_files") points to the first link + in this chain, and the "objfiles_tail" field points to the last + link in this chain. */ struct objfile *next; + struct objfile *prev; /* The object file's original name as specified by the user, made absolute, and tilde-expanded. However, it is not canonicalized @@ -511,8 +514,6 @@ extern void terminate_minimal_symbol_table (struct objfile *objfile); extern struct objfile *objfile_separate_debug_iterate (const struct objfile *, const struct objfile *); -extern void put_objfile_before (struct objfile *, struct objfile *); - extern void add_separate_debug_objfile (struct objfile *, struct objfile *); extern void unlink_objfile (struct objfile *); diff --git a/gdb/progspace.h b/gdb/progspace.h index d1d11f9..446dfc6 100644 --- a/gdb/progspace.h +++ b/gdb/progspace.h @@ -183,9 +183,10 @@ struct program_space (e.g. the argument to the "symbol-file" or "file" command). */ struct objfile *symfile_object_file; - /* All known objfiles are kept in a linked list. This points to - the head of this list. */ + /* All known objfiles are kept in a doubly linked list. These + point to the head and tail of this list. */ struct objfile *objfiles; + struct objfile *objfiles_tail; /* The set of target sections matching the sections mapped into this program space. Managed by both exec_ops and solib.c. */ |