Author: Armin Rigo <[email protected]>
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
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit