Author: Armin Rigo <ar...@tunes.org>
Branch: reverse-debugger
Changeset: r85393:6e38ff9d8113
Date: 2016-06-27 11:06 +0200
http://bitbucket.org/pypy/pypy/changeset/6e38ff9d8113/

Log:    Start to work on finalizers: split the log file into packets

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
@@ -1,6 +1,7 @@
 #include "common_header.h"
 #include <stdlib.h>
 #include <stdio.h>
+#include <stddef.h>
 #include <string.h>
 #include <assert.h>
 #include <sys/stat.h>
@@ -24,17 +25,19 @@
 #define WEAKREF_AFTERWARDS_DEAD    ((char)0xf2)
 #define WEAKREF_AFTERWARDS_ALIVE   ((char)0xeb)
 
+//#define ASYNC_FINALIZER       ((int16_t)0xff46)
+
 
 typedef struct {
     Signed version;
-    Signed reserved1, reserved2;
+    uint64_t reserved1, reserved2;
     int argc;
     char **argv;
 } rdb_header_t;
 
 
 rpy_revdb_t rpy_revdb;
-static char rpy_rev_buffer[16384];
+static char rpy_rev_buffer[16384];    /* max. 32768 */
 static int rpy_rev_fileno = -1;
 static unsigned char flag_io_disabled;
 
@@ -109,9 +112,6 @@
     int i;
 
     assert(RPY_RDB_REPLAY == 0);
-    rpy_revdb.buf_p = rpy_rev_buffer;
-    rpy_revdb.buf_limit = rpy_rev_buffer + sizeof(rpy_rev_buffer) - 32;
-    rpy_revdb.unique_id_seen = 1;
 
     if (filename && *filename) {
         putenv("PYPYRDB=");
@@ -137,20 +137,29 @@
         h.argv = argv;
         write_all((const char *)&h, sizeof(h));
     }
+    rpy_revdb.buf_p = rpy_rev_buffer + sizeof(int16_t);
+    rpy_revdb.buf_limit = rpy_rev_buffer + sizeof(rpy_rev_buffer) - 32;
+    rpy_revdb.unique_id_seen = 1;
+}
+
+static void flush_buffer(void)
+{
+    /* write the current buffer content to the OS */
+    ssize_t size = rpy_revdb.buf_p - rpy_rev_buffer;
+    rpy_revdb.buf_p = rpy_rev_buffer + sizeof(int16_t);
+    if (rpy_rev_fileno >= 0)
+        write_all(rpy_rev_buffer, size);
 }
 
 RPY_EXTERN
 void rpy_reverse_db_flush(void)
 {
-    /* write the current buffer content to the OS */
-
-    ssize_t wsize, size = rpy_revdb.buf_p - rpy_rev_buffer;
-    char *p;
-    rpy_revdb.buf_p = rpy_rev_buffer;
-    if (size == 0 || rpy_rev_fileno < 0)
-        return;
-
-    write_all(rpy_rev_buffer, size);
+    ssize_t packet_size = rpy_revdb.buf_p - (rpy_rev_buffer + sizeof(int16_t));
+    if (packet_size != 0) {
+        assert(0 < packet_size && packet_size <= 32767);
+        *(int16_t *)rpy_rev_buffer = packet_size;
+        flush_buffer();
+    }
 }
 
 RPY_EXTERN
@@ -176,7 +185,7 @@
     return obj->h_hash;
 }
 
-static int64_t recording_offset(void)
+static uint64_t recording_offset(void)
 {
     off_t base_offset;
     ssize_t extra_size = rpy_revdb.buf_p - rpy_rev_buffer;
@@ -516,6 +525,7 @@
 
     rpy_revdb.buf_p = rpy_rev_buffer;
     rpy_revdb.buf_limit = rpy_rev_buffer;
+    rpy_revdb.buf_readend = rpy_rev_buffer;
     rpy_revdb.stop_point_break = 1;
     rpy_revdb.unique_id_seen = 1;
 
@@ -528,19 +538,44 @@
     signal(SIGCHLD, SIG_IGN);
 }
 
+static void fetch_more(ssize_t keep, ssize_t expected_size)
+{
+    ssize_t rsize;
+    if (rpy_revdb.buf_p != rpy_rev_buffer)
+        memmove(rpy_rev_buffer, rpy_revdb.buf_p, keep);
+    rsize = read_at_least(rpy_rev_buffer + keep,
+                          expected_size - keep,
+                          sizeof(rpy_rev_buffer) - keep);
+    rpy_revdb.buf_p = rpy_rev_buffer;
+    rpy_revdb.buf_readend = rpy_rev_buffer + keep + rsize;
+    /* rpy_revdb.buf_limit is not set */
+}
+
 RPY_EXTERN
-char *rpy_reverse_db_fetch(int expected_size, const char *file, int line)
+char *rpy_reverse_db_fetch(const char *file, int line)
 {
     if (!flag_io_disabled) {
-        ssize_t rsize, keep = rpy_revdb.buf_limit - rpy_revdb.buf_p;
+        ssize_t keep;
+        ssize_t full_packet_size;
+        if (rpy_revdb.buf_limit != rpy_revdb.buf_p) {
+            fprintf(stderr, "bad log format: incomplete packet\n");
+            exit(1);
+        }
+        keep = rpy_revdb.buf_readend - rpy_revdb.buf_p;
         assert(keep >= 0);
-        memmove(rpy_rev_buffer, rpy_revdb.buf_p, keep);
-        rsize = read_at_least(rpy_rev_buffer + keep,
-                              expected_size - keep,
-                              sizeof(rpy_rev_buffer) - keep);
-        rpy_revdb.buf_p = rpy_rev_buffer;
-        rpy_revdb.buf_limit = rpy_rev_buffer + keep + rsize;
-        return rpy_rev_buffer;
+
+        if (keep < sizeof(int16_t)) {
+            /* 'keep' does not even contain the next packet header */
+            fetch_more(keep, sizeof(int16_t));
+            keep = rpy_revdb.buf_readend - rpy_rev_buffer;
+        }
+        full_packet_size = sizeof(int16_t) + *(int16_t *)rpy_revdb.buf_p;
+        if (keep < full_packet_size) {
+            fetch_more(keep, full_packet_size);
+        }
+        rpy_revdb.buf_limit = rpy_revdb.buf_p + full_packet_size;
+        rpy_revdb.buf_p += sizeof(int16_t);
+        return rpy_revdb.buf_p;
     }
     else {
         /* this is called when we are in execute_rpy_command(): we are
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
@@ -16,7 +16,7 @@
 #define RPY_RDB_DYNAMIC_REPLAY
 #endif
     bool_t watch_enabled;
-    char *buf_p, *buf_limit;
+    char *buf_p, *buf_limit, *buf_readend;
     uint64_t stop_point_seen, stop_point_break;
     uint64_t unique_id_seen, unique_id_break;
 } rpy_revdb_t;
@@ -53,8 +53,7 @@
             char *_src = rpy_revdb.buf_p;                               \
             char *_end1 = _src + sizeof(_e);                            \
             if (_end1 > rpy_revdb.buf_limit) {                          \
-                _src = rpy_reverse_db_fetch(sizeof(_e),                 \
-                                            __FILE__, __LINE__);        \
+                _src = rpy_reverse_db_fetch(__FILE__, __LINE__);        \
                 _end1 = _src + sizeof(_e);                              \
             }                                                           \
             rpy_revdb.buf_p = _end1;                                    \
@@ -114,8 +113,7 @@
     r = rpy_reverse_db_weakref_deref(weakref)
 
 RPY_EXTERN void rpy_reverse_db_flush(void);
-RPY_EXTERN char *rpy_reverse_db_fetch(int expected_size,
-                                      const char *file, int line);
+RPY_EXTERN char *rpy_reverse_db_fetch(const char *file, int line);
 RPY_EXTERN void rpy_reverse_db_stop_point(void);
 RPY_EXTERN void rpy_reverse_db_send_answer(int cmd, int64_t arg1, int64_t arg2,
                                            int64_t arg3, RPyString *extra);
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
@@ -21,19 +21,29 @@
         assert header == 'RevDB:\t' + '\t'.join(expected_argv) + '\n'
         #
         self.cur = 0
-        x = self.next('c'); assert x == '\x00'
-        x = self.next(); assert x == 0x00FF0001
-        x = self.next(); assert x == 0
-        x = self.next(); assert x == 0
-        self.argc = self.next()
-        self.argv = self.next()
+        x = self.read1('c'); assert x == '\x00'
+        x = self.read1('P'); assert x == 0x00FF0001
+        x = self.read1('P'); assert x == 0
+        x = self.read1('P'); assert x == 0
+        self.argc = self.read1('P')
+        self.argv = self.read1('P')
+        self.current_packet_end = self.cur
         self.read_check_argv(expected_argv)
 
-    def next(self, mode='P'):
+    def read1(self, mode):
         p = self.cur
         self.cur = p + struct.calcsize(mode)
         return struct.unpack_from(mode, self.buffer, p)[0]
 
+    def next(self, mode='P'):
+        if self.current_packet_end == self.cur:
+            packet_size = self.read1('h')
+            assert packet_size > 0
+            self.current_packet_end = self.cur + packet_size
+        result = self.read1(mode)
+        assert self.cur <= self.current_packet_end
+        return result
+
     def read_check_argv(self, expected):
         assert self.argc == len(expected)
         for i in range(self.argc):
diff --git a/rpython/translator/revdb/test/test_weak.py 
b/rpython/translator/revdb/test/test_weak.py
--- a/rpython/translator/revdb/test/test_weak.py
+++ b/rpython/translator/revdb/test/test_weak.py
@@ -1,5 +1,5 @@
-import weakref, gc
-from rpython.rlib import revdb
+import weakref
+from rpython.rlib import revdb, rgc
 from rpython.rlib.debug import debug_print
 from rpython.rlib.objectmodel import keepalive_until_here
 from rpython.translator.revdb.message import *
@@ -23,7 +23,7 @@
 WEAKREF_AFTERWARDS_ALIVE = chr(0xeb)
 
 
-class TestRecordingWeakref(BaseRecordingTests):
+class TestRecording(BaseRecordingTests):
 
     def test_weakref_create(self):
         class X:
@@ -71,8 +71,25 @@
         x = rdb.next('q'); assert x == 0      # number of stop points
         assert rdb.done()
 
+    def test_finalizer_light_ignored(self):
+        class X:
+            @rgc.must_be_light_finalizer
+            def __del__(self):
+                pass
+        def main(argv):
+            lst = [X() for i in range(3000)]
+            for i in range(3000):
+                lst[i] = None
+                revdb.stop_point()
+            return 9
+        self.compile(main, [], backendopt=False)
+        out = self.run('Xx')
+        rdb = self.fetch_rdb([self.exename, 'Xx'])
+        x = rdb.next('q'); assert x == 3000    # number of stop points
+        assert rdb.done()
 
-class TestReplayingWeakref(InteractiveTests):
+
+class TestReplaying(InteractiveTests):
     expected_stop_points = 1
 
     def setup_class(cls):
@@ -108,7 +125,7 @@
                 print ''.join(outp)
                 if (j % 1000) == 999:
                     debug_print('============= COLLECT ===========')
-                    gc.collect()
+                    rgc.collect()
                 debug_print('------ done', j, '.')
             assert not dead[0]
             assert not dead[-1]
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to