Author: Armin Rigo <ar...@tunes.org>
Branch: reverse-debugger
Changeset: r85095:372509ebf296
Date: 2016-06-11 11:57 +0200
http://bitbucket.org/pypy/pypy/changeset/372509ebf296/

Log:    identityhash()

diff --git a/rpython/config/translationoption.py 
b/rpython/config/translationoption.py
--- a/rpython/config/translationoption.py
+++ b/rpython/config/translationoption.py
@@ -282,7 +282,8 @@
                "Give an executable that writes a log file for reverse 
debugging",
                default=False, cmdline='--revdb',
                requires=[('translation.split_gc_address_space', True),
-                         ('translation.jit', False)]),
+                         ('translation.jit', False),
+                         ('translation.gc', 'boehm')]),
 ])
 
 def get_combined_translation_config(other_optdescr=None,
diff --git a/rpython/memory/gctransform/boehm.py 
b/rpython/memory/gctransform/boehm.py
--- a/rpython/memory/gctransform/boehm.py
+++ b/rpython/memory/gctransform/boehm.py
@@ -30,13 +30,6 @@
 
         HDRPTR = lltype.Ptr(self.HDR)
 
-        def ll_identityhash(addr):
-            obj = llmemory.cast_adr_to_ptr(addr, HDRPTR)
-            h = obj.hash
-            if h == 0:
-                obj.hash = h = ~llmemory.cast_adr_to_int(addr)
-            return h
-
         if self.translator:
             self.malloc_fixedsize_ptr = self.inittime_helper(
                 ll_malloc_fixedsize, [lltype.Signed], llmemory.GCREF)
@@ -52,9 +45,18 @@
                     inline=False)
                 self.weakref_deref_ptr = self.inittime_helper(
                     ll_weakref_deref, [llmemory.WeakRefPtr], llmemory.Address)
-            self.identityhash_ptr = self.inittime_helper(
-                ll_identityhash, [llmemory.Address], lltype.Signed,
-                inline=False)
+
+            if not translator.config.translation.reverse_debugger:
+                def ll_identityhash(addr):
+                    obj = llmemory.cast_adr_to_ptr(addr, HDRPTR)
+                    h = obj.hash
+                    if h == 0:
+                        obj.hash = h = ~llmemory.cast_adr_to_int(addr)
+                    return h
+                self.identityhash_ptr = self.inittime_helper(
+                    ll_identityhash, [llmemory.Address], lltype.Signed,
+                    inline=False)
+
             self.mixlevelannotator.finish()   # for now
             self.mixlevelannotator.backend_optimize()
 
@@ -146,10 +148,14 @@
 
     def gct_gc_identityhash(self, hop):
         v_obj = hop.spaceop.args[0]
-        v_adr = hop.genop("cast_ptr_to_adr", [v_obj],
-                          resulttype=llmemory.Address)
-        hop.genop("direct_call", [self.identityhash_ptr, v_adr],
-                  resultvar=hop.spaceop.result)
+        if not self.translator.config.translation.reverse_debugger:
+            v_addr = hop.genop("cast_ptr_to_adr", [v_obj],
+                               resulttype=llmemory.Address)
+            hop.genop("direct_call", [self.identityhash_ptr, v_addr],
+                      resultvar=hop.spaceop.result)
+        else:
+            hop.genop("revdb_identityhash", [v_obj],
+                      resultvar=hop.spaceop.result)
 
     def gct_gc_id(self, hop):
         # this is the logic from the HIDE_POINTER macro in <gc/gc.h>
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
@@ -567,6 +567,7 @@
 
     'revdb_stop_point':     LLOp(),
     'revdb_send_output':    LLOp(),
+    'revdb_identityhash':   LLOp(),
 }
 # ***** Run test_lloperation after changes. *****
 
diff --git a/rpython/translator/c/funcgen.py b/rpython/translator/c/funcgen.py
--- a/rpython/translator/c/funcgen.py
+++ b/rpython/translator/c/funcgen.py
@@ -630,8 +630,8 @@
             gcsrc = isinstance(TSRC, Ptr) and TSRC.TO._gckind == 'gc'
             if gcsrc != gcdst:
                 raise Exception(
-                  "cast between pointer types changes the address space,\n"
-                  "but the 'split_gc_address_space' option is enabled:\n"
+                  "cast between pointer types changes the address\n"
+                  "space, but the 'split_gc_address_space' option is 
enabled:\n"
                   "  func: %s\n"
                   "    op: %s\n"
                   "  from: %s\n"
diff --git a/rpython/translator/revdb/rdb-src/revdb.c 
b/rpython/translator/revdb/rdb-src/revdb.c
--- a/rpython/translator/revdb/rdb-src/revdb.c
+++ b/rpython/translator/revdb/rdb-src/revdb.c
@@ -136,6 +136,24 @@
     write_all(rpy_rev_buffer, size);
 }
 
+RPY_EXTERN
+Signed rpy_reverse_db_identityhash(struct pypy_header0 *obj)
+{
+    /* Boehm only */
+    if (obj->h_hash == 0) {
+        Signed h;
+        /* When recording, we get the hash the normal way from the
+           pointer casted to an int, and record that.  When replaying,
+           we read it from the record.  In both cases, we cache the
+           hash in the object, so that we record/replay only once per
+           object. */
+        RPY_REVDB_EMIT(h = ~((Signed)obj);, Signed _e, h);
+        assert(h != 0);
+        obj->h_hash = h;
+    }
+    return obj->h_hash;
+}
+
 
 /* ------------------------------------------------------------ */
 /* Replaying mode                                               */
@@ -190,7 +208,7 @@
 enum { PK_MAIN_PROCESS, PK_FROZEN_PROCESS, PK_DEBUG_PROCESS };
 static unsigned char process_kind = PK_MAIN_PROCESS;
 static unsigned char flag_exit_run_debug_process;
-static unsigned char flag_executing_rpython_code;
+static unsigned char flag_io_disabled;
 static jmp_buf jmp_buf_cancel_execution;
 static uint64_t latest_fork;
 
@@ -287,7 +305,7 @@
 RPY_EXTERN
 char *rpy_reverse_db_fetch(int expected_size)
 {
-    if (!flag_executing_rpython_code) {
+    if (!flag_io_disabled) {
         ssize_t rsize, keep = rpy_revdb.buf_limit - rpy_revdb.buf_p;
         assert(keep >= 0);
         memmove(rpy_rev_buffer, rpy_revdb.buf_p, keep);
@@ -313,12 +331,12 @@
     *dinfo = rpy_revdb;   /* save the complete struct */
     rpy_revdb.buf_p = NULL;
     rpy_revdb.buf_limit = NULL;
-    flag_executing_rpython_code = 1;
+    flag_io_disabled = 1;
 }
 
 static void enable_io(rpy_revdb_t *dinfo)
 {
-    flag_executing_rpython_code = 0;
+    flag_io_disabled = 0;
     rpy_revdb = *dinfo;
 }
 
diff --git a/rpython/translator/revdb/rdb-src/revdb_include.h 
b/rpython/translator/revdb/rdb-src/revdb_include.h
--- a/rpython/translator/revdb/rdb-src/revdb_include.h
+++ b/rpython/translator/revdb/rdb-src/revdb_include.h
@@ -61,10 +61,14 @@
 #define OP_REVDB_SEND_OUTPUT(ll_string, r)                              \
     rpy_reverse_db_send_output(ll_string)
 
+#define OP_REVDB_IDENTITYHASH(obj, r)                                   \
+    r = rpy_reverse_db_identityhash((struct pypy_header0 *)(obj))
+
 RPY_EXTERN void rpy_reverse_db_flush(void);
 RPY_EXTERN char *rpy_reverse_db_fetch(int expected_size);
 RPY_EXTERN void rpy_reverse_db_break(long stop_point);
 RPY_EXTERN void rpy_reverse_db_send_output(RPyString *output);
+RPY_EXTERN Signed rpy_reverse_db_identityhash(struct pypy_header0 *obj);
 
 
 /* ------------------------------------------------------------ */
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
@@ -4,7 +4,8 @@
 from rpython.tool.udir import udir
 from rpython.translator.interactive import Translation
 from rpython.rlib.rarithmetic import LONG_BIT
-from rpython.rlib import revdb
+from rpython.rlib import objectmodel, revdb
+from rpython.rlib.rarithmetic import intmask
 """
 These tests require pexpect (UNIX-only).
 http://pexpect.sourceforge.net/
@@ -30,6 +31,24 @@
         self.cur = p + struct.calcsize(mode)
         return struct.unpack_from(mode, self.buffer, p)[0]
 
+    def read_check_argv(self, expected):
+        assert self.argc == len(expected)
+        for i in range(self.argc):
+            self.next()    # this is from "p = argv[i]"
+            s = []
+            # first we determine the length of the "char *p"
+            while True:
+                c = self.next('c')
+                if c == '\x00':
+                    break
+                s.append(c)
+            # then we really read the "char *" and copy it into a rpy string
+            # (that's why this time we don't read the final \0)
+            for c1 in s:
+                c2 = self.next('c')
+                assert c2 == c1
+            assert ''.join(s) == expected[i]
+
     def number_of_stop_points(self):
         return struct.unpack_from("q", self.buffer, len(self.buffer) - 8)[0]
 
@@ -66,14 +85,11 @@
     return RDB(self.rdbname)
 
 
-class BaseTests(object):
+class TestRecording(object):
     compile = compile
     run = run
     fetch_rdb = fetch_rdb
 
-
-class TestRecording(BaseTests):
-
     def test_simple(self):
         def main(argv):
             print argv[1:]
@@ -81,32 +97,35 @@
         self.compile(main, [], backendopt=False)
         assert self.run('abc d') == '[abc, d]\n'
         rdb = self.fetch_rdb()
-        assert rdb.argc == 3
-        #
-        got = []
-        for i in range(3):
-            rdb.next()    # this is from "p = argv[i]"
-            s = []
-            # first we determine the length of the "char *p"
-            while True:
-                c = rdb.next('c')
-                if c == '\x00':
-                    break
-                s.append(c)
-            # then we really read the "char *" and copy it into a rpy string
-            # (that's why this time we don't read the final \0)
-            for c1 in s:
-                c2 = rdb.next('c')
-                assert c2 == c1
-            got.append(''.join(s))
+        rdb.read_check_argv([self.exename, 'abc', 'd'])
         # write() call
         x = rdb.next(); assert x == len('[abc, d]\n')
         x = rdb.next('i'); assert x == 0      # errno
         x = rdb.next('q'); assert x == 0      # number of stop points
         # that's all we should get from this simple example
         assert rdb.done()
-        #
-        assert got == [self.exename, 'abc', 'd']
+
+    def test_identityhash(self):
+        def main(argv):
+            print [objectmodel.compute_identity_hash(argv),
+                   objectmodel.compute_identity_hash(argv),
+                   objectmodel.compute_identity_hash(argv)]
+            return 9
+        self.compile(main, [], backendopt=False)
+        out = self.run('Xx')
+        match = re.match(r'\[(-?\d+), \1, \1]\n', out)
+        assert match
+        hash_value = int(match.group(1))
+        rdb = self.fetch_rdb()
+        rdb.read_check_argv([self.exename, 'Xx'])
+        # compute_identity_hash() call, but only the first one
+        x = rdb.next(); assert intmask(x) == intmask(hash_value)
+        # write() call
+        x = rdb.next(); assert x == len(out)
+        x = rdb.next('i'); assert x == 0      # errno
+        # done
+        x = rdb.next('q'); assert x == 0      # number of stop points
+        assert rdb.done()
 
 
 class InteractiveTests(object):
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to