aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPedro Alves <palves@redhat.com>2016-03-26 11:28:38 +0000
committerPedro Alves <palves@redhat.com>2016-09-19 15:44:42 +0100
commit8f15b2c1d696bccd82269e072a80f2dc67ee2119 (patch)
treea74c7efe68a26b5b32195a2fafdba20e009bf46c
parent7877d8a30a85ce7edbf60f00619943c27caea9e7 (diff)
downloadgdb-8f15b2c1d696bccd82269e072a80f2dc67ee2119.zip
gdb-8f15b2c1d696bccd82269e072a80f2dc67ee2119.tar.gz
gdb-8f15b2c1d696bccd82269e072a80f2dc67ee2119.tar.bz2
objfile_data
The perf profile now shows objfile_data at the top. It's not that that function is expensive. It's that it's called _a lot_ of times. Whenever we register/unregister a JIT objfile, we iterate over the whole list of existing objfiles, and call objfile_data on each, through jit_find_objf_with_entry_addr. Get rid of that O(N) loop by keeping a list of JIT objfiles on the side, sorted by addr and using a binary search for the look up instead.
-rw-r--r--gdb/jit.c112
1 files changed, 89 insertions, 23 deletions
diff --git a/gdb/jit.c b/gdb/jit.c
index 81a2c26..ba6daed 100644
--- a/gdb/jit.c
+++ b/gdb/jit.c
@@ -42,6 +42,10 @@
#include "readline/tilde.h"
#include "completer.h"
+typedef struct objfile *objfile_p;
+
+DEF_VEC_P(objfile_p);
+
static const char *jit_reader_dir = NULL;
static const struct objfile_data *jit_objfile_data;
@@ -267,6 +271,9 @@ struct jit_program_space_data
set. */
struct breakpoint *jit_breakpoint;
+
+ /* VEC of JIT objfiles sorted by entry address. */
+ VEC(objfile_p) *jit_objfiles;
};
/* Per-objfile structure recording the addresses in the program space.
@@ -306,16 +313,50 @@ get_jit_objfile_data (struct objfile *objf)
return objf_data;
}
+static int
+jit_objfiles_lessthan (struct objfile *objf1, struct objfile *objf2)
+{
+ struct jit_objfile_data *objf_data1 = get_jit_objfile_data (objf1);
+ struct jit_objfile_data *objf_data2 = get_jit_objfile_data (objf2);
+
+ return objf_data1->addr < objf_data2->addr;
+}
+
+static int
+jit_objfiles_compar (const void *key, const void *o)
+{
+ CORE_ADDR entry_addr = *(CORE_ADDR *) key;
+ struct objfile **objf = (struct objfile **) o;
+ struct jit_objfile_data *objf_data = get_jit_objfile_data (*objf);
+
+ if (entry_addr < objf_data->addr)
+ return -1;
+ else if (entry_addr > objf_data->addr)
+ return 1;
+ else
+ return 0;
+}
+
+static struct jit_program_space_data *get_jit_program_space_data (void);
+
/* Remember OBJFILE has been created for struct jit_code_entry located
at inferior address ENTRY. */
static void
add_objfile_entry (struct objfile *objfile, CORE_ADDR entry)
{
+ struct jit_program_space_data *ps_data;
struct jit_objfile_data *objf_data;
+ int i;
objf_data = get_jit_objfile_data (objfile);
objf_data->addr = entry;
+
+ ps_data = get_jit_program_space_data ();
+
+ i = VEC_lower_bound (objfile_p, ps_data->jit_objfiles,
+ objfile, jit_objfiles_lessthan);
+ VEC_safe_insert (objfile_p, ps_data->jit_objfiles, i, objfile);
}
/* Return jit_program_space_data for current program space. Allocate
@@ -983,32 +1024,64 @@ jit_register_code (struct gdbarch *gdbarch,
jit_bfd_try_read_symtab (code_entry, entry_addr, gdbarch);
}
+static int jit_find_objf_with_entry_addr (CORE_ADDR entry_addr);
+
/* This function unregisters JITed code and frees the corresponding
objfile. */
static void
-jit_unregister_code (struct objfile *objfile)
+jit_unregister_code (struct gdbarch *gdbarch, CORE_ADDR entry_addr)
{
- free_objfile (objfile);
+ struct jit_program_space_data *ps_data;
+ struct objfile *removed;
+ int i;
+
+ ps_data = get_jit_program_space_data ();
+
+ i = jit_find_objf_with_entry_addr (entry_addr);
+ if (i < 0)
+ {
+ printf_unfiltered (_("Unable to find JITed code "
+ "entry at address: %s\n"),
+ paddress (gdbarch, entry_addr));
+ return;
+ }
+
+ removed = VEC_ordered_remove (objfile_p, ps_data->jit_objfiles, i);
+ free_objfile (removed);
}
-/* Look up the objfile with this code entry address. */
+/* Look up the objfile with this code entry address in the VEC of jit
+ objfiles. Returns the VEC index if found, -1 otherwise. */
-static struct objfile *
+static int
jit_find_objf_with_entry_addr (CORE_ADDR entry_addr)
{
+ struct jit_program_space_data *ps_data;
+ struct jit_objfile_data *objf_data;
+ struct objfile **base;
+ size_t nmemb;
+ struct objfile **found;
struct objfile *objf;
- ALL_OBJFILES (objf)
- {
- struct jit_objfile_data *objf_data;
+ ps_data = get_jit_program_space_data ();
- objf_data
- = (struct jit_objfile_data *) objfile_data (objf, jit_objfile_data);
- if (objf_data != NULL && objf_data->addr == entry_addr)
- return objf;
- }
- return NULL;
+ base = VEC_address (objfile_p, ps_data->jit_objfiles);
+ nmemb = VEC_length (objfile_p, ps_data->jit_objfiles);
+
+ if (nmemb == 0)
+ return -1;
+
+ found = (struct objfile **) bsearch (&entry_addr, base, nmemb,
+ sizeof (*base),
+ jit_objfiles_compar);
+ if (found == NULL)
+ return -1;
+
+ objf = *found;
+ objf_data = get_jit_objfile_data (objf);
+ gdb_assert (objf_data->addr == entry_addr);
+ return found - base;
}
/* This is called when a breakpoint is deleted. It updates the
@@ -1375,7 +1448,7 @@ jit_inferior_init (struct gdbarch *gdbarch)
/* This hook may be called many times during setup, so make sure we don't
add the same symbol file twice. */
- if (jit_find_objf_with_entry_addr (cur_entry_addr) != NULL)
+ if (jit_find_objf_with_entry_addr (cur_entry_addr) >= 0)
continue;
jit_register_code (gdbarch, cur_entry_addr, &cur_entry);
@@ -1424,7 +1497,7 @@ jit_inferior_exit_hook (struct inferior *inf)
= (struct jit_objfile_data *) objfile_data (objf, jit_objfile_data);
if (objf_data != NULL && objf_data->addr != 0)
- jit_unregister_code (objf);
+ jit_unregister_code (get_objfile_arch (objf), objf_data->addr);
}
}
@@ -1452,14 +1525,7 @@ jit_event_handler (struct gdbarch *gdbarch)
jit_register_code (gdbarch, entry_addr, &code_entry);
break;
case JIT_UNREGISTER:
- objf = jit_find_objf_with_entry_addr (entry_addr);
- if (objf == NULL)
- printf_unfiltered (_("Unable to find JITed code "
- "entry at address: %s\n"),
- paddress (gdbarch, entry_addr));
- else
- jit_unregister_code (objf);
-
+ jit_unregister_code (gdbarch, entry_addr);
break;
default:
error (_("Unknown action_flag value in JIT descriptor!"));