Author: Armin Rigo <ar...@tunes.org> Branch: reverse-debugger Changeset: r85443:2564a81ce049 Date: 2016-06-29 10:12 +0200 http://bitbucket.org/pypy/pypy/changeset/2564a81ce049/
Log: in-progress diff --git a/pypy/interpreter/reverse_debugging.py b/pypy/interpreter/reverse_debugging.py --- a/pypy/interpreter/reverse_debugging.py +++ b/pypy/interpreter/reverse_debugging.py @@ -1,6 +1,8 @@ import sys from rpython.rlib import revdb from rpython.rlib.debug import make_sure_not_resized +from rpython.rlib.objectmodel import specialize +from rpython.rtyper.annlowlevel import cast_gcref_to_instance from pypy.interpreter.error import OperationError, oefmt from pypy.interpreter.baseobjspace import W_Root from pypy.interpreter import gateway, typedef @@ -8,40 +10,63 @@ class DBState: extend_syntax_with_dollar_num = False + breakpoint_funcnames = [] + printed_objects = {} metavars = [] + watch_progs = [] + watch_futures = {} dbstate = DBState() def setup_revdb(space): + """Called at run-time, before the space is set up. + + The various register_debug_command() lines attach functions + to some commands that 'revdb.py' can call, if we are running + in replay mode. + """ assert space.config.translation.reverse_debugger dbstate.space = space - #make_sure_not_resized(dbstate.breakpoint_funcnames) - #make_sure_not_resized(dbstate.watch_progs) + dbstate.w_future = space.w_Ellipsis # a random prebuilt object + + make_sure_not_resized(dbstate.breakpoint_funcnames) + make_sure_not_resized(dbstate.watch_progs) make_sure_not_resized(dbstate.metavars) + revdb.register_debug_command(revdb.CMD_PRINT, lambda_print) revdb.register_debug_command(revdb.CMD_BACKTRACE, lambda_backtrace) #revdb.register_debug_command(revdb.CMD_LOCALS, lambda_locals) #revdb.register_debug_command(revdb.CMD_BREAKPOINTS, lambda_breakpoints) #revdb.register_debug_command(revdb.CMD_MOREINFO, lambda_moreinfo) - #revdb.register_debug_command("ALLOCATING", lambda_allocating) - #revdb.register_debug_command(revdb.CMD_ATTACHID, lambda_attachid) + revdb.register_debug_command("ALLOCATING", lambda_allocating) + revdb.register_debug_command(revdb.CMD_ATTACHID, lambda_attachid) #revdb.register_debug_command(revdb.CMD_CHECKWATCH, lambda_checkwatch) #revdb.register_debug_command(revdb.CMD_WATCHVALUES, lambda_watchvalues) -def load_metavar(oparg): + +def load_metavar(index): + assert index >= 0 space = dbstate.space metavars = dbstate.metavars - w_var = metavars[oparg] if oparg < len(metavars) else None + w_var = metavars[index] if index < len(metavars) else None if w_var is None: raise oefmt(space.w_NameError, "no constant object '$%d'", - oparg) - if w_var is space.w_Ellipsis: + index) + if w_var is dbstate.w_future: raise oefmt(space.w_RuntimeError, "'$%d' refers to an object created later in time", - oparg) + index) return w_var +def set_metavar(index, w_obj): + assert index >= 0 + if index >= len(dbstate.metavars): + missing = index + 1 - len(dbstate.metavars) + dbstate.metavars = dbstate.metavars + [None] * missing + dbstate.metavars[index] = w_obj + + def fetch_cur_frame(): ec = dbstate.space.getexecutioncontext() frame = ec.topframeref() @@ -76,6 +101,25 @@ softspace = typedef.interp_attrproperty("softspace", W_RevDBOutput), ) +def revdb_displayhook(space, w_obj): + """Modified sys.displayhook() that also outputs '$NUM = ', + for non-prebuilt objects. Such objects are then recorded in + 'printed_objects'. + """ + if space.is_w(w_obj, space.w_None): + return + uid = revdb.get_unique_id(w_obj) + if uid > 0: + dbstate.printed_objects[uid] = w_obj + revdb.send_nextnid(uid) # outputs '$NUM = ' + space.setitem(space.builtin.w_dict, space.wrap('_'), w_obj) + revdb.send_output(space.str_w(space.repr(w_obj))) + revdb.send_output("\n") + +@specialize.memo() +def get_revdb_displayhook(space): + return space.wrap(gateway.interp2app(revdb_displayhook)) + def command_print(cmd, expression): frame = fetch_cur_frame() @@ -85,8 +129,10 @@ try: code = compile(expression, 'exec') w_revdb_output = space.wrap(W_RevDBOutput(space)) + w_displayhook = get_revdb_displayhook(space) space.sys.setdictvalue(space, 'stdout', w_revdb_output) space.sys.setdictvalue(space, 'stderr', w_revdb_output) + space.sys.setdictvalue(space, 'displayhook', w_displayhook) try: code.exec_code(space, frame.get_w_globals(), @@ -141,3 +187,29 @@ while len(frames) > 0: show_frame(frames.pop(), indent=' ') lambda_backtrace = lambda: command_backtrace + + +def command_allocating(uid, gcref): + w_obj = cast_gcref_to_instance(W_Root, gcref) + dbstate.printed_objects[uid] = w_obj + try: + index_metavar = dbstate.watch_futures.pop(uid) + except KeyError: + pass + else: + set_metavar(index_metavar, w_obj) +lambda_allocating = lambda: command_allocating + + +def command_attachid(cmd, extra): + space = dbstate.space + index_metavar = cmd.c_arg1 + uid = cmd.c_arg2 + try: + w_obj = dbstate.printed_objects[uid] + except KeyError: + # uid not found, probably a future object + dbstate.watch_futures[uid] = index_metavar + w_obj = dbstate.w_future + set_metavar(index_metavar, w_obj) +lambda_attachid = lambda: command_attachid _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit