Garbage collect dummy_frame_ctx_saver
Since the "finish" command and infcall's FSMs are now responsible for saving the return value, the dummy_frame_ctx_saver is no longer needed anywhere. gdb/ChangeLog: 2015-09-09 Pedro Alves <palves@redhat.com> * infcall.c (struct dummy_frame_context_saver): Delete. (dummy_frame_context_saver_free, dummy_frame_context_saver_dtor) (dummy_frame_context_saver_drop) (dummy_frame_context_saver_cleanup) (dummy_frame_context_saver_get_regs) (dummy_frame_context_saver_setup): Delete. * infcall.h (dummy_frame_context_saver_drop) (dummy_frame_context_saver_cleanup) (dummy_frame_context_saver_get_regs, dummy_frame_context_saver): Delete. (get_return_value): Remove 'ctx_saver' paremeter. Adjust. * inferior.h (get_return_value): Remove 'ctx_saver' paremeter. * python/py-finishbreakpoint.c (bpfinishpy_pre_stop_hook): Adjust.
This commit is contained in:
parent
cfc3163382
commit
0700e23e5f
6 changed files with 26 additions and 121 deletions
|
@ -1,3 +1,19 @@
|
||||||
|
2015-09-09 Pedro Alves <palves@redhat.com>
|
||||||
|
|
||||||
|
* infcall.c (struct dummy_frame_context_saver): Delete.
|
||||||
|
(dummy_frame_context_saver_free, dummy_frame_context_saver_dtor)
|
||||||
|
(dummy_frame_context_saver_drop)
|
||||||
|
(dummy_frame_context_saver_cleanup)
|
||||||
|
(dummy_frame_context_saver_get_regs)
|
||||||
|
(dummy_frame_context_saver_setup): Delete.
|
||||||
|
* infcall.h (dummy_frame_context_saver_drop)
|
||||||
|
(dummy_frame_context_saver_cleanup)
|
||||||
|
(dummy_frame_context_saver_get_regs, dummy_frame_context_saver):
|
||||||
|
Delete.
|
||||||
|
(get_return_value): Remove 'ctx_saver' paremeter. Adjust.
|
||||||
|
* inferior.h (get_return_value): Remove 'ctx_saver' paremeter.
|
||||||
|
* python/py-finishbreakpoint.c (bpfinishpy_pre_stop_hook): Adjust.
|
||||||
|
|
||||||
2015-09-09 Pedro Alves <palves@redhat.com>
|
2015-09-09 Pedro Alves <palves@redhat.com>
|
||||||
|
|
||||||
* breakpoint.c: Include "thread-fsm.h".
|
* breakpoint.c: Include "thread-fsm.h".
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
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 "defs.h"
|
#include "defs.h"
|
||||||
|
#include "infcall.h"
|
||||||
#include "breakpoint.h"
|
#include "breakpoint.h"
|
||||||
#include "tracepoint.h"
|
#include "tracepoint.h"
|
||||||
#include "target.h"
|
#include "target.h"
|
||||||
|
@ -30,7 +31,6 @@
|
||||||
#include "objfiles.h"
|
#include "objfiles.h"
|
||||||
#include "gdbcmd.h"
|
#include "gdbcmd.h"
|
||||||
#include "command.h"
|
#include "command.h"
|
||||||
#include "infcall.h"
|
|
||||||
#include "dummy-frame.h"
|
#include "dummy-frame.h"
|
||||||
#include "ada-lang.h"
|
#include "ada-lang.h"
|
||||||
#include "gdbthread.h"
|
#include "gdbthread.h"
|
||||||
|
@ -661,96 +661,6 @@ call_function_by_hand (struct value *function, int nargs, struct value **args)
|
||||||
return call_function_by_hand_dummy (function, nargs, args, NULL, NULL);
|
return call_function_by_hand_dummy (function, nargs, args, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Data for dummy_frame_context_saver. Structure can be freed only
|
|
||||||
after both dummy_frame_context_saver_dtor and
|
|
||||||
dummy_frame_context_saver_drop have been called for it. */
|
|
||||||
|
|
||||||
struct dummy_frame_context_saver
|
|
||||||
{
|
|
||||||
/* Inferior registers fetched before associated dummy_frame got freed
|
|
||||||
and before any other destructors of associated dummy_frame got called.
|
|
||||||
It is initialized to NULL. */
|
|
||||||
struct regcache *retbuf;
|
|
||||||
|
|
||||||
/* It is 1 if this dummy_frame_context_saver_drop has been already
|
|
||||||
called. */
|
|
||||||
int drop_done;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Free struct dummy_frame_context_saver. */
|
|
||||||
|
|
||||||
static void
|
|
||||||
dummy_frame_context_saver_free (struct dummy_frame_context_saver *saver)
|
|
||||||
{
|
|
||||||
regcache_xfree (saver->retbuf);
|
|
||||||
xfree (saver);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Destructor for associated dummy_frame. */
|
|
||||||
|
|
||||||
static void
|
|
||||||
dummy_frame_context_saver_dtor (void *data_voidp, int registers_valid)
|
|
||||||
{
|
|
||||||
struct dummy_frame_context_saver *data = data_voidp;
|
|
||||||
|
|
||||||
gdb_assert (data->retbuf == NULL);
|
|
||||||
|
|
||||||
if (data->drop_done)
|
|
||||||
dummy_frame_context_saver_free (data);
|
|
||||||
else if (registers_valid)
|
|
||||||
data->retbuf = regcache_dup (get_current_regcache ());
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Caller is no longer interested in this
|
|
||||||
struct dummy_frame_context_saver. After its associated dummy_frame
|
|
||||||
gets freed struct dummy_frame_context_saver can be also freed. */
|
|
||||||
|
|
||||||
void
|
|
||||||
dummy_frame_context_saver_drop (struct dummy_frame_context_saver *saver)
|
|
||||||
{
|
|
||||||
saver->drop_done = 1;
|
|
||||||
|
|
||||||
if (!find_dummy_frame_dtor (dummy_frame_context_saver_dtor, saver))
|
|
||||||
dummy_frame_context_saver_free (saver);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Stub dummy_frame_context_saver_drop compatible with make_cleanup. */
|
|
||||||
|
|
||||||
void
|
|
||||||
dummy_frame_context_saver_cleanup (void *data)
|
|
||||||
{
|
|
||||||
struct dummy_frame_context_saver *saver = data;
|
|
||||||
|
|
||||||
dummy_frame_context_saver_drop (saver);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Fetch RETBUF field of possibly opaque DTOR_DATA.
|
|
||||||
RETBUF must not be NULL. */
|
|
||||||
|
|
||||||
struct regcache *
|
|
||||||
dummy_frame_context_saver_get_regs (struct dummy_frame_context_saver *saver)
|
|
||||||
{
|
|
||||||
gdb_assert (saver->retbuf != NULL);
|
|
||||||
return saver->retbuf;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Register provider of inferior registers at the time DUMMY_ID frame of
|
|
||||||
PTID gets freed (before inferior registers get restored to those
|
|
||||||
before dummy_frame). */
|
|
||||||
|
|
||||||
struct dummy_frame_context_saver *
|
|
||||||
dummy_frame_context_saver_setup (struct frame_id dummy_id, ptid_t ptid)
|
|
||||||
{
|
|
||||||
struct dummy_frame_context_saver *saver =
|
|
||||||
XNEW (struct dummy_frame_context_saver);
|
|
||||||
|
|
||||||
saver->retbuf = NULL;
|
|
||||||
saver->drop_done = 0;
|
|
||||||
register_dummy_frame_dtor (dummy_id, inferior_ptid,
|
|
||||||
dummy_frame_context_saver_dtor, saver);
|
|
||||||
return saver;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* All this stuff with a dummy frame may seem unnecessarily complicated
|
/* All this stuff with a dummy frame may seem unnecessarily complicated
|
||||||
(why not just save registers in GDB?). The purpose of pushing a dummy
|
(why not just save registers in GDB?). The purpose of pushing a dummy
|
||||||
frame which looks just like a real frame is so that if you call a
|
frame which looks just like a real frame is so that if you call a
|
||||||
|
|
|
@ -50,13 +50,4 @@ extern struct value *
|
||||||
dummy_frame_dtor_ftype *dummy_dtor,
|
dummy_frame_dtor_ftype *dummy_dtor,
|
||||||
void *dummy_dtor_data);
|
void *dummy_dtor_data);
|
||||||
|
|
||||||
struct dummy_frame_context_saver;
|
|
||||||
extern void dummy_frame_context_saver_drop
|
|
||||||
(struct dummy_frame_context_saver *data);
|
|
||||||
extern void dummy_frame_context_saver_cleanup (void *data_voidp);
|
|
||||||
extern struct regcache *dummy_frame_context_saver_get_regs
|
|
||||||
(struct dummy_frame_context_saver *saver);
|
|
||||||
extern struct dummy_frame_context_saver *dummy_frame_context_saver_setup
|
|
||||||
(struct frame_id dummy_id, ptid_t ptid);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
19
gdb/infcmd.c
19
gdb/infcmd.c
|
@ -1585,22 +1585,15 @@ advance_command (char *arg, int from_tty)
|
||||||
right after an inferior call has finished. */
|
right after an inferior call has finished. */
|
||||||
|
|
||||||
struct value *
|
struct value *
|
||||||
get_return_value (struct value *function, struct type *value_type,
|
get_return_value (struct value *function, struct type *value_type)
|
||||||
struct dummy_frame_context_saver *ctx_saver)
|
|
||||||
{
|
{
|
||||||
struct regcache *stop_regs = NULL;
|
struct regcache *stop_regs;
|
||||||
struct gdbarch *gdbarch;
|
struct gdbarch *gdbarch;
|
||||||
struct value *value;
|
struct value *value;
|
||||||
struct cleanup *cleanup = make_cleanup (null_cleanup, NULL);
|
struct cleanup *cleanup;
|
||||||
|
|
||||||
/* If registers were not saved, use the current registers. */
|
stop_regs = regcache_dup (get_current_regcache ());
|
||||||
if (ctx_saver != NULL)
|
cleanup = make_cleanup_regcache_xfree (stop_regs);
|
||||||
stop_regs = dummy_frame_context_saver_get_regs (ctx_saver);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
stop_regs = regcache_dup (get_current_regcache ());
|
|
||||||
make_cleanup_regcache_xfree (stop_regs);
|
|
||||||
}
|
|
||||||
|
|
||||||
gdbarch = get_regcache_arch (stop_regs);
|
gdbarch = get_regcache_arch (stop_regs);
|
||||||
|
|
||||||
|
@ -1800,7 +1793,7 @@ finish_command_fsm_should_stop (struct thread_fsm *self)
|
||||||
struct value *func;
|
struct value *func;
|
||||||
|
|
||||||
func = read_var_value (f->function, NULL, get_current_frame ());
|
func = read_var_value (f->function, NULL, get_current_frame ());
|
||||||
rv->value = get_return_value (func, rv->type, NULL);
|
rv->value = get_return_value (func, rv->type);
|
||||||
rv->value_history_index = record_latest_value (rv->value);
|
rv->value_history_index = record_latest_value (rv->value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -165,10 +165,8 @@ extern void detach_command (char *, int);
|
||||||
|
|
||||||
extern void notice_new_inferior (ptid_t, int, int);
|
extern void notice_new_inferior (ptid_t, int, int);
|
||||||
|
|
||||||
struct dummy_frame_context_saver;
|
extern struct value *get_return_value (struct value *function,
|
||||||
extern struct value *get_return_value
|
struct type *value_type);
|
||||||
(struct value *function, struct type *value_type,
|
|
||||||
struct dummy_frame_context_saver *ctx_saver);
|
|
||||||
|
|
||||||
/* Prepare for execution command. TARGET is the target that will run
|
/* Prepare for execution command. TARGET is the target that will run
|
||||||
the command. BACKGROUND determines whether this is a foreground
|
the command. BACKGROUND determines whether this is a foreground
|
||||||
|
|
|
@ -107,10 +107,7 @@ bpfinishpy_pre_stop_hook (struct gdbpy_breakpoint_object *bp_obj)
|
||||||
value_object_to_value (self_finishbp->function_value);
|
value_object_to_value (self_finishbp->function_value);
|
||||||
struct type *value_type =
|
struct type *value_type =
|
||||||
type_object_to_type (self_finishbp->return_type);
|
type_object_to_type (self_finishbp->return_type);
|
||||||
|
struct value *ret = get_return_value (function, value_type);
|
||||||
/* bpfinishpy_init cannot finish into DUMMY_FRAME (throws an error
|
|
||||||
in such case) so it is OK to always pass CTX_SAVER as NULL. */
|
|
||||||
struct value *ret = get_return_value (function, value_type, NULL);
|
|
||||||
|
|
||||||
if (ret)
|
if (ret)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue