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