Author: Armin Rigo <[email protected]>
Branch: reverse-debugger
Changeset: r85212:4ab10ccbb305
Date: 2016-06-17 16:06 +0200
http://bitbucket.org/pypy/pypy/changeset/4ab10ccbb305/

Log:    Update track_object() to allow tracking any number of objects

diff --git a/rpython/rlib/revdb.py b/rpython/rlib/revdb.py
--- a/rpython/rlib/revdb.py
+++ b/rpython/rlib/revdb.py
@@ -91,29 +91,20 @@
     """
     return llop.revdb_get_unique_id(lltype.SignedLongLong, x)
 
-def track_object(unique_id):
+def track_object(unique_id, callback):
     """Track the creation of the object given by its unique_id, which must
     be in the future (i.e. >= currently_created_objects()).  Call this
     before go_forward().  If go_forward() goes over the creation of this
-    object, then afterwards, get_tracked_object() returns the object.
-    Going forward is also interrupted at the following stop point.
-    Object tracking is lost by jump_in_time(), like everything else.
+    object, then 'callback(gcref)' is called.  Careful in callback(),
+    gcref is not fully initialized and should not be immediately read from,
+    only stored for later.  The purpose of callback() is to possibly
+    call track_object() again to track the next object, and/or to call
+    breakpoint().  Note: object tracking remains activated until one of:
+    (1) we reach the creation time in go_forward(); (2) we call
+    track_object() to track a different object; (3) we call jump_in_time().
     """
-    llop.revdb_track_object(lltype.Void, unique_id)
-
[email protected](0)
-def get_tracked_object(Class=llmemory.GCREF):   # or an RPython class
-    """Get the tracked object if it was created during the last go_forward().
-    Otherwise, returns None.  (Note: this API is minimal: to get an
-    object from its unique id, you need first to search backward for a
-    time where currently_created_objects() is lower than the unique_id,
-    then use track_object() and go_forward() to come back.  You can't
-    really track several objects, only one.)
-    """
-    x = llop.revdb_get_tracked_object(llmemory.GCREF)
-    if Class is llmemory.GCREF:
-        return x
-    return cast_gcref_to_instance(Class, x)
+    ll_callback = llhelper(_CALLBACK_GCREF_FNPTR, callback)
+    llop.revdb_track_object(lltype.Void, unique_id, ll_callback)
 
 
 # ____________________________________________________________
@@ -132,6 +123,8 @@
     return callback_wrapper
 _CALLBACK_ARG_FNPTR = lltype.Ptr(lltype.FuncType([lltype.Ptr(rstr.STR)],
                                                  lltype.Void))
+_CALLBACK_GCREF_FNPTR = lltype.Ptr(lltype.FuncType([llmemory.GCREF],
+                                                   lltype.Void))
 
 
 class RegisterDebugCommand(ExtRegistryEntry):
diff --git a/rpython/rtyper/lltypesystem/lloperation.py 
b/rpython/rtyper/lltypesystem/lloperation.py
--- a/rpython/rtyper/lltypesystem/lloperation.py
+++ b/rpython/rtyper/lltypesystem/lloperation.py
@@ -573,7 +573,6 @@
     'revdb_identityhash':   LLOp(),
     'revdb_get_unique_id':  LLOp(sideeffects=False),
     'revdb_track_object':   LLOp(),
-    'revdb_get_tracked_object': LLOp(sideeffects=False),
 }
 # ***** Run test_lloperation after changes. *****
 
diff --git a/rpython/translator/revdb/src-revdb/revdb.c 
b/rpython/translator/revdb/src-revdb/revdb.c
--- a/rpython/translator/revdb/src-revdb/revdb.c
+++ b/rpython/translator/revdb/src-revdb/revdb.c
@@ -900,23 +900,22 @@
     }
 }
 
-static void *tracked_object;
+static void (*unique_id_callback)(void *);
 
 RPY_EXTERN
 uint64_t rpy_reverse_db_unique_id_break(void *new_object)
 {
     rpy_revdb.unique_id_break = 0;
-    tracked_object = new_object;
-    rpy_revdb.stop_point_break = rpy_revdb.stop_point_seen + 1;
+    unique_id_callback(new_object);
     return rpy_revdb.unique_id_seen;
 }
 
 RPY_EXTERN
-void rpy_reverse_db_track_object(long long unique_id)
+void rpy_reverse_db_track_object(long long unique_id, void callback(void *))
 {
     if (stopped_uid <= 0) {
         fprintf(stderr, "stopped_uid should not be <= 0\n");
-        exit(1);
+        return;
     }
     if (unique_id <= 0) {
         printf("cannot track a prebuilt or debugger-created object\n");
@@ -926,15 +925,10 @@
         printf("cannot track the creation of an object already created\n");
         return;
     }
+    assert(callback != NULL);
+    unique_id_callback = callback;
     rpy_revdb.unique_id_break = unique_id;
-    tracked_object = NULL;
 }
 
-RPY_EXTERN
-void *rpy_reverse_db_get_tracked_object(void)
-{
-    return tracked_object;
-}
-
 
 /* ------------------------------------------------------------ */
diff --git a/rpython/translator/revdb/src-revdb/revdb_include.h 
b/rpython/translator/revdb/src-revdb/revdb_include.h
--- a/rpython/translator/revdb/src-revdb/revdb_include.h
+++ b/rpython/translator/revdb/src-revdb/revdb_include.h
@@ -96,11 +96,8 @@
 #define OP_REVDB_GET_UNIQUE_ID(x, r)                                    \
     r = ((struct pypy_header0 *)x)->h_uid
 
-#define OP_REVDB_TRACK_OBJECT(uid, r)                                   \
-    rpy_reverse_db_track_object(uid)
-
-#define OP_REVDB_GET_TRACKED_OBJECT(r)                                  \
-    r = rpy_reverse_db_get_tracked_object()
+#define OP_REVDB_TRACK_OBJECT(uid, callback, r)                         \
+    rpy_reverse_db_track_object(uid, callback)
 
 RPY_EXTERN void rpy_reverse_db_flush(void);
 RPY_EXTERN char *rpy_reverse_db_fetch(int expected_size,
@@ -113,8 +110,8 @@
                                            RPyString *arg);
 RPY_EXTERN long long rpy_reverse_db_get_value(char value_id);
 RPY_EXTERN uint64_t rpy_reverse_db_unique_id_break(void *new_object);
-RPY_EXTERN void rpy_reverse_db_track_object(long long unique_id);
-RPY_EXTERN void *rpy_reverse_db_get_tracked_object(void);
+RPY_EXTERN void rpy_reverse_db_track_object(long long unique_id,
+                                            void callback(void *));
 
 
 /* ------------------------------------------------------------ */
diff --git a/rpython/translator/revdb/test/test_basic.py 
b/rpython/translator/revdb/test/test_basic.py
--- a/rpython/translator/revdb/test/test_basic.py
+++ b/rpython/translator/revdb/test/test_basic.py
@@ -6,6 +6,8 @@
 from rpython.rlib.rarithmetic import LONG_BIT
 from rpython.rlib import objectmodel, revdb
 from rpython.rlib.rarithmetic import intmask
+from rpython.rtyper.annlowlevel import cast_gcref_to_instance
+from rpython.rtyper.lltypesystem import lltype, llmemory
 """
 These tests require pexpect (UNIX-only).
 http://pexpect.sourceforge.net/
@@ -314,6 +316,10 @@
         def _nothing(arg):
             pass
         #
+        def callback_track_obj(gcref):
+            revdb.send_output("callback_track_obj\n")
+            dbstate.gcref = gcref
+        #
         def blip(cmdline):
             revdb.send_output('<<<' + cmdline + '>>>\n')
             if cmdline == 'oops':
@@ -345,11 +351,14 @@
                     revdb.currently_created_objects()))
             if cmdline.startswith('track-object '):
                 uid = int(cmdline[len('track-object '):])
-                revdb.track_object(uid)
+                dbstate.gcref = lltype.nullptr(llmemory.GCREF.TO)
+                revdb.track_object(uid, callback_track_obj)
             if cmdline == 'get-tracked-object':
-                obj = revdb.get_tracked_object(Stuff)
-                revdb.send_output('None\n' if obj is None else
-                                  ('obj.x=%d\n' % obj.x))
+                if dbstate.gcref:
+                    revdb.send_output('got obj.x=%d\n' % (
+                        cast_gcref_to_instance(Stuff, dbstate.gcref).x,))
+                else:
+                    revdb.send_output('none\n')
             if cmdline == 'first-created-uid':
                 revdb.send_output('first-created-uid=%d\n' % (
                     revdb.first_created_object_uid(),))
@@ -503,32 +512,24 @@
         child.expectx('<<<track-object %d>>>\r\n' % object_id_3rd +
                       'blipped\r\n'
                       '(1)$ ')
-        prev_time = 1
-        for i in [1, 2, 3]:
+        for i in [1, 2]:
             child.sendline('r get-tracked-object')
             child.expectx('<<<get-tracked-object>>>\r\n'
-                          'None\r\n'
+                          'none\r\n'
                           'blipped\r\n'
-                          '(%d)$ ' % prev_time)
-            child.sendline('__forward %d' % (i - prev_time))
-            child.expectx('(%d)$ ' % i)
-            prev_time = i
-            child.sendline('r print-id')
-            child.expect(re.escape('<<<print-id>>>\r\n')
-                         + r'obj.x=%d (\d+) (\d+)' % (1000 + prev_time - 1)
-                         + re.escape('\r\n'
-                                     'blipped\r\n'
-                                     '(%d)$ ' % prev_time))
+                          '(%d)$ ' % i)
+            child.sendline('__forward 1')
+            child.expectx('(%d)$ ' % (i + 1))
         child.sendline('r get-tracked-object')
         child.expectx('<<<get-tracked-object>>>\r\n'
-                      'obj.x=1002\r\n'
+                      'got obj.x=1002\r\n'
                       'blipped\r\n'
                       '(3)$ ')
         child.sendline('__go 3')
         child.expectx('(3)$ ')
         child.sendline('r get-tracked-object')
         child.expectx('<<<get-tracked-object>>>\r\n'
-                      'None\r\n'
+                      'none\r\n'
                       'blipped\r\n'
                       '(3)$ ')
         #
@@ -559,13 +560,21 @@
         child.expectx('<<<track-object %d>>>\r\n' % object_id_2nd +
                       'blipped\r\n'
                       '(1)$ ')
-        child.sendline('__forward 5')
-        child.expectx('(2)$ ')
+        child.sendline('__forward 2')
+        child.expectx('(3)$ ')
         child.sendline('r get-tracked-object')
         child.expectx('<<<get-tracked-object>>>\r\n'
-                      'obj.x=1001\r\n'
+                      'got obj.x=1001\r\n'
                       'blipped\r\n'
-                      '(2)$ ')
+                      '(3)$ ')
+        child.sendline('__forward 1')
+        child.expectx('At end.\r\n'
+                      '(3)$ ')
+        child.sendline('r get-tracked-object')
+        child.expectx('<<<get-tracked-object>>>\r\n'
+                      'none\r\n'
+                      'blipped\r\n'
+                      '(3)$ ')
 
     def test_first_created_uid(self):
         child = self.replay()
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to