Convert py-framefilter.c to new hash table

This converts py-framefilter.c to use the new hash table.

Change-Id: I38f4eaa8ebbcd4fd6e5e8ddc462502a92bf62f5e
Co-Authored-By: Tom Tromey <tom@tromey.com>
Approved-By: Tom Tromey <tom@tromey.com>
This commit is contained in:
Simon Marchi
2024-11-04 13:27:42 -05:00
committed by Simon Marchi
parent e77c31d28d
commit 52dedd71c8

View File

@@ -17,6 +17,7 @@
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */ along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include "gdbsupport/unordered_set.h"
#include "objfiles.h" #include "objfiles.h"
#include "symtab.h" #include "symtab.h"
#include "language.h" #include "language.h"
@@ -27,7 +28,6 @@
#include "stack.h" #include "stack.h"
#include "source.h" #include "source.h"
#include "annotate.h" #include "annotate.h"
#include "hashtab.h"
#include "demangle.h" #include "demangle.h"
#include "mi/mi-cmds.h" #include "mi/mi-cmds.h"
#include "python-internal.h" #include "python-internal.h"
@@ -731,25 +731,37 @@ py_print_args (PyObject *filter,
return EXT_LANG_BT_OK; return EXT_LANG_BT_OK;
} }
using levels_printed_hash = gdb::unordered_set<frame_info *>;
/* Print a single frame to the designated output stream, detecting /* Print a single frame to the designated output stream, detecting
whether the output is MI or console, and formatting the output whether the output is MI or console, and formatting the output
according to the conventions of that protocol. FILTER is the according to the conventions of that protocol.
frame-filter associated with this frame. FLAGS is an integer
describing the various print options. The FLAGS variables is FILTER is the frame-filter associated with this frame.
described in "apply_frame_filter" function. ARGS_TYPE is an
enumerator describing the argument format. OUT is the output FLAGS is an integer describing the various print options. The FLAGS
stream to print, INDENT is the level of indention for this frame variables is described in "apply_frame_filter" function.
(in the case of elided frames), and LEVELS_PRINTED is a hash-table
containing all the frames level that have already been printed. ARGS_TYPE is an enumerator describing the argument format.
If a frame level has been printed, do not print it again (in the
case of elided frames). Returns EXT_LANG_BT_ERROR on error, with any OUT is the output stream to print to.
GDB exceptions converted to a Python exception, or EXT_LANG_BT_OK
on success. It can also throw an exception RETURN_QUIT. */ INDENT is the level of indention for this frame (in the case of elided
frames).
LEVELS_PRINTED is a hash-table containing all the frames for which the
level has already been printed. If a level has been printed, do not print
it again (in the case of elided frames).
Returns EXT_LANG_BT_ERROR on error, with any GDB exceptions converted to a
Python exception, or EXT_LANG_BT_OK on success. It can also throw an
exception RETURN_QUIT. */
static enum ext_lang_bt_status static enum ext_lang_bt_status
py_print_frame (PyObject *filter, frame_filter_flags flags, py_print_frame (PyObject *filter, frame_filter_flags flags,
enum ext_lang_frame_args args_type, enum ext_lang_frame_args args_type,
struct ui_out *out, int indent, htab_t levels_printed) struct ui_out *out, int indent,
levels_printed_hash &levels_printed)
{ {
int has_addr = 0; int has_addr = 0;
CORE_ADDR address = 0; CORE_ADDR address = 0;
@@ -859,23 +871,16 @@ py_print_frame (PyObject *filter, frame_filter_flags flags,
&& (location_print && (location_print
|| (out->is_mi_like_p () && (print_frame_info || print_args)))) || (out->is_mi_like_p () && (print_frame_info || print_args))))
{ {
struct frame_info **slot;
int level;
slot = (frame_info **) htab_find_slot (levels_printed,
frame.get(), INSERT);
level = frame_relative_level (frame);
/* Check if this frame has already been printed (there are cases /* Check if this frame has already been printed (there are cases
where elided synthetic dummy-frames have to 'borrow' the frame where elided synthetic dummy-frames have to 'borrow' the frame
architecture from the eliding frame. If that is the case, do architecture from the eliding frame. If that is the case, do
not print 'level', but print spaces. */ not print the level, but print spaces. */
if (*slot == frame) if (!levels_printed.insert (frame.get ()).second)
out->field_skip ("level"); out->field_skip ("level");
else else
{ {
*slot = frame.get (); int level = frame_relative_level (frame);
annotate_frame_begin (print_level ? level : 0, annotate_frame_begin (print_level ? level : 0,
gdbarch, address); gdbarch, address);
out->text ("#"); out->text ("#");
@@ -1197,10 +1202,7 @@ gdbpy_apply_frame_filter (const struct extension_language_defn *extlang,
if (iterable == Py_None) if (iterable == Py_None)
return EXT_LANG_BT_NO_FILTERS; return EXT_LANG_BT_NO_FILTERS;
htab_up levels_printed (htab_create (20, levels_printed_hash levels_printed;
htab_hash_pointer,
htab_eq_pointer,
NULL));
while (true) while (true)
{ {
@@ -1232,7 +1234,7 @@ gdbpy_apply_frame_filter (const struct extension_language_defn *extlang,
try try
{ {
success = py_print_frame (item.get (), flags, args_type, out, 0, success = py_print_frame (item.get (), flags, args_type, out, 0,
levels_printed.get ()); levels_printed);
} }
catch (const gdb_exception_error &except) catch (const gdb_exception_error &except)
{ {