Reuse buffers across gdb_pretty_print_insn calls
authorPedro Alves <palves@redhat.com>
Thu, 2 Feb 2017 11:11:47 +0000 (11:11 +0000)
committerPedro Alves <palves@redhat.com>
Thu, 2 Feb 2017 11:11:47 +0000 (11:11 +0000)
gdb_pretty_print_insn allocates and destroys a couple local buffers
each time it is called, which can be many times when disassembling a
region of memory.  Avoid that overhead by adding a new class that
holds the buffers and making gdb_pretty_print_insn a method of that
class, so that the buffers can be reused across calls.

gdb/ChangeLog:
2017-02-02  Pedro Alves  <palves@redhat.com>

* disasm.c (gdb_pretty_print_insn): Rename to ...
(gdb_pretty_print_disassembler::pretty_print_insn): ... this.
Remove gdbarch parameter.  Adapt to clear the object's buffers
instead of allocating new buffers, and to print using the object's
gdb_disassembler instead of calling gdb_print_insn.
(dump_insns): Use gdb_pretty_print_disassembler.
* disasm.h (gdb_pretty_print_insn): Delete declaration.
(gdb_pretty_print_disassembler): New class.
* record-btrace.c (btrace_insn_history): Use
gdb_pretty_print_disassembler.

gdb/ChangeLog
gdb/disasm.c
gdb/disasm.h
gdb/record-btrace.c

index e3bca388578491351ae123662e378b2fd10446fe..38a3beb0594a11fc163361aea7977beb71649e13 100644 (file)
@@ -1,3 +1,16 @@
+2017-02-02  Pedro Alves  <palves@redhat.com>
+
+       * disasm.c (gdb_pretty_print_insn): Rename to ...
+       (gdb_pretty_print_disassembler::pretty_print_insn): ... this.
+       Remove gdbarch parameter.  Adapt to clear the object's buffers
+       instead of allocating new buffers, and to print using the object's
+       gdb_disassembler instead of calling gdb_print_insn.
+       (dump_insns): Use gdb_pretty_print_disassembler.
+       * disasm.h (gdb_pretty_print_insn): Delete declaration.
+       (gdb_pretty_print_disassembler): New class.
+       * record-btrace.c (btrace_insn_history): Use
+       gdb_pretty_print_disassembler.
+
 2017-02-02  Pedro Alves  <palves@redhat.com>
 
        * ada-lang.c (type_as_string): Use string_file.
index 5f0e86a057b74d0c16b28442a668798d8c1c8363..64d6684b53e3981b26f94ad9a4c93bfc6d35e1d1 100644 (file)
@@ -182,9 +182,9 @@ compare_lines (const void *mle1p, const void *mle2p)
 /* See disasm.h.  */
 
 int
-gdb_pretty_print_insn (struct gdbarch *gdbarch, struct ui_out *uiout,
-                      const struct disasm_insn *insn,
-                      int flags)
+gdb_pretty_print_disassembler::pretty_print_insn (struct ui_out *uiout,
+                                                 const struct disasm_insn *insn,
+                                                 int flags)
 {
   /* parts of the symbolic representation of the address */
   int unmapped;
@@ -195,6 +195,7 @@ gdb_pretty_print_insn (struct gdbarch *gdbarch, struct ui_out *uiout,
   char *filename = NULL;
   char *name = NULL;
   CORE_ADDR pc;
+  struct gdbarch *gdbarch = arch ();
 
   ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, NULL);
   pc = insn->addr;
@@ -248,7 +249,7 @@ gdb_pretty_print_insn (struct gdbarch *gdbarch, struct ui_out *uiout,
   if (name != NULL)
     xfree (name);
 
-  string_file stb;
+  m_insn_stb.clear ();
 
   if (flags & DISASSEMBLY_RAW_INSN)
     {
@@ -259,25 +260,25 @@ gdb_pretty_print_insn (struct gdbarch *gdbarch, struct ui_out *uiout,
 
       /* Build the opcodes using a temporary stream so we can
         write them out in a single go for the MI.  */
-      string_file opcode_stream;
+      m_opcode_stb.clear ();
 
-      size = gdb_print_insn (gdbarch, pc, &stb, NULL);
+      size = m_di.print_insn (pc);
       end_pc = pc + size;
 
       for (;pc < end_pc; ++pc)
        {
          read_code (pc, &data, 1);
-         opcode_stream.printf ("%s%02x", spacer, (unsigned) data);
+         m_opcode_stb.printf ("%s%02x", spacer, (unsigned) data);
          spacer = " ";
        }
 
-      uiout->field_stream ("opcodes", opcode_stream);
+      uiout->field_stream ("opcodes", m_opcode_stb);
       uiout->text ("\t");
     }
   else
-    size = gdb_print_insn (gdbarch, pc, &stb, NULL);
+    size = m_di.print_insn (pc);
 
-  uiout->field_stream ("inst", stb);
+  uiout->field_stream ("inst", m_insn_stb);
   do_cleanups (ui_out_chain);
   uiout->text ("\n");
 
@@ -295,11 +296,13 @@ dump_insns (struct gdbarch *gdbarch,
   memset (&insn, 0, sizeof (insn));
   insn.addr = low;
 
+  gdb_pretty_print_disassembler disasm (gdbarch);
+
   while (insn.addr < high && (how_many < 0 || num_displayed < how_many))
     {
       int size;
 
-      size = gdb_pretty_print_insn (gdbarch, uiout, &insn, flags);
+      size = disasm.pretty_print_insn (uiout, &insn, flags);
       if (size <= 0)
        break;
 
index dcc01e19befb6f3b3c53182427e426fb13daf9d2..385cae6865c06d26a5403d0458ed4882bb11c699 100644 (file)
@@ -97,11 +97,34 @@ extern void gdb_disassembly (struct gdbarch *gdbarch, struct ui_out *uiout,
 extern int gdb_print_insn (struct gdbarch *gdbarch, CORE_ADDR memaddr,
                           struct ui_file *stream, int *branch_delay_insns);
 
-/* Prints the instruction INSN into UIOUT and returns the length of
-   the printed instruction in bytes.  */
+/* Class used to pretty-print an instruction.  */
 
-extern int gdb_pretty_print_insn (struct gdbarch *gdbarch, struct ui_out *uiout,
-                                 const struct disasm_insn *insn, int flags);
+class gdb_pretty_print_disassembler
+{
+public:
+  explicit gdb_pretty_print_disassembler (struct gdbarch *gdbarch)
+    : m_di (gdbarch, &m_insn_stb)
+  {}
+
+  /* Prints the instruction INSN into UIOUT and returns the length of
+     the printed instruction in bytes.  */
+  int pretty_print_insn (struct ui_out *uiout, const struct disasm_insn *insn,
+                        int flags);
+
+private:
+  /* Returns the architecture used for disassembling.  */
+  struct gdbarch *arch () { return m_di.arch (); }
+
+  /* The disassembler used for instruction printing.  */
+  gdb_disassembler m_di;
+
+  /* The buffer used to build the instruction string.  The
+     disassembler is initialized with this stream.  */
+  string_file m_insn_stb;
+
+  /* The buffer used to build the raw opcodes string.  */
+  string_file m_opcode_stb;
+};
 
 /* Return the length in bytes of the instruction at address MEMADDR in
    debugged memory.  */
index 35e96add70585a7284617c99d42d71e56a555e93..daa06968a0242da46311e9160ca4ccba046f404e 100644 (file)
@@ -719,6 +719,8 @@ btrace_insn_history (struct ui_out *uiout,
      instructions corresponding to that line.  */
   ui_item_chain = NULL;
 
+  gdb_pretty_print_disassembler disasm (gdbarch);
+
   for (it = *begin; btrace_insn_cmp (&it, end) != 0; btrace_insn_next (&it, 1))
     {
       const struct btrace_insn *insn;
@@ -772,7 +774,7 @@ btrace_insn_history (struct ui_out *uiout,
          if ((insn->flags & BTRACE_INSN_FLAG_SPECULATIVE) != 0)
            dinsn.is_speculative = 1;
 
-         gdb_pretty_print_insn (gdbarch, uiout, &dinsn, flags);
+         disasm.pretty_print_insn (uiout, &dinsn, flags);
        }
     }