aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPedro Alves <palves@redhat.com>2016-03-26 00:42:38 +0000
committerPedro Alves <palves@redhat.com>2016-09-19 15:44:41 +0100
commit7877d8a30a85ce7edbf60f00619943c27caea9e7 (patch)
tree65502ab21612b0f86f01d2dfba3b60f8c7a8b830
parent893297fc25371792fc58c6e197dc3dfdd5651608 (diff)
downloadgdb-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.c107
-rw-r--r--gdb/objfiles.h11
-rw-r--r--gdb/progspace.h5
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. */