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

Reply via email to