[pypy-commit] pypy reverse-debugger-updated: in-progress (not working so far): trying to get

arigo pypy.commits at gmail.com
Sun May 13 17:17:42 EDT 2018


Author: Armin Rigo <arigo at tunes.org>
Branch: reverse-debugger-updated
Changeset: r94548:c8c3a21ba942
Date: 2018-05-13 23:16 +0200
http://bitbucket.org/pypy/pypy/changeset/c8c3a21ba942/

Log:	in-progress (not working so far): trying to get
	get_raw_address_of_string() to never raise ValueError

diff --git a/rpython/rtyper/lltypesystem/rffi.py b/rpython/rtyper/lltypesystem/rffi.py
--- a/rpython/rtyper/lltypesystem/rffi.py
+++ b/rpython/rtyper/lltypesystem/rffi.py
@@ -809,6 +809,7 @@
             lltype.free(cp, flavor='raw', track_allocation=True)
         else:
             lltype.free(cp, flavor='raw', track_allocation=False)
+    free_charp._annenforceargs_ = [None, bool]
 
     # str -> already-existing char[maxsize]
     def str2chararray(s, array, maxsize):
@@ -1330,14 +1331,6 @@
         )
 
 
-class RawBytes(object):
-    # literal copy of _cffi_backend/func.py
-    def __init__(self, string):
-        self.ptr = str2charp(string, track_allocation=False)
-    def __del__(self):
-        if free_charp is not None:    # CPython shutdown
-            free_charp(self.ptr, track_allocation=False)
-
 # NOTE: This is not a weak key dictionary, thus keeping a lot of stuff alive.
 TEST_RAW_ADDR_KEEP_ALIVE = {}
 
@@ -1346,8 +1339,6 @@
     """Returns a 'char *' that is valid as long as the rpython string object is alive.
     Two calls to to this function, given the same string parameter,
     are guaranteed to return the same pointer.
-
-    NOTE: may raise ValueError on some GCs, but not the default one.
     """
     assert isinstance(string, str)
     from rpython.rtyper.annlowlevel import llstr
@@ -1357,11 +1348,11 @@
 
     if we_are_translated():
         if rgc.must_split_gc_address_space():
-            raise ValueError("cannot return a pointer in the gcstring")
+            return _get_raw_address_buf_from_string(string)
         if rgc.can_move(string):
             string = rgc.move_out_of_nursery(string)
             if rgc.can_move(string):
-                raise ValueError("cannot make string immovable")
+                return _get_raw_address_buf_from_string(string)
 
         # string cannot move now! return the address
         lldata = llstr(string)
@@ -1374,6 +1365,48 @@
     else:
         global TEST_RAW_ADDR_KEEP_ALIVE
         if string in TEST_RAW_ADDR_KEEP_ALIVE:
-            return TEST_RAW_ADDR_KEEP_ALIVE[string].ptr
-        TEST_RAW_ADDR_KEEP_ALIVE[string] = rb = RawBytes(string)
-        return rb.ptr
+            return TEST_RAW_ADDR_KEEP_ALIVE[string]
+        result = str2charp(string, track_allocation=False)
+        TEST_RAW_ADDR_KEEP_ALIVE[string] = result
+        return result
+
+class _StrFinalizerQueue(rgc.FinalizerQueue):
+    Class = None              # to use GCREFs directly
+    print_debugging = False   # set to True from test_rffi
+    def finalizer_trigger(self):
+        from rpython.rtyper.annlowlevel import hlstr
+        from rpython.rtyper.lltypesystem import rstr
+        from rpython.rlib.debug import debug_print
+        from rpython.rlib import objectmodel
+        debug_print("HI THERE")
+        while True:
+            gcptr = self.next_dead()
+            if not gcptr:
+                break
+            ll_string = lltype.cast_opaque_ptr(lltype.Ptr(rstr.STR), gcptr)
+            string = hlstr(ll_string)
+            key = objectmodel.compute_unique_id(string)
+            ptr = self.raw_copies.get(key, lltype.nullptr(CCHARP.TO))
+            debug_print(ptr)
+            if ptr:
+                if self.print_debugging:
+                    debug_print("freeing [", ptr, "]")
+                free_charp(ptr, track_allocation=False)
+_fq_addr_from_string = _StrFinalizerQueue()
+_fq_addr_from_string.raw_copies = {}    # {GCREF: CCHARP}
+
+def _get_raw_address_buf_from_string(string):
+    # Slowish but ok because it's not supposed to be used from a
+    # regular PyPy.  It's only used with non-standard GCs like RevDB
+    from rpython.rtyper.annlowlevel import llstr
+    from rpython.rlib import objectmodel
+    key = objectmodel.compute_unique_id(string)
+    try:
+        ptr = _fq_addr_from_string.raw_copies[key]
+    except KeyError:
+        ptr = str2charp(string, track_allocation=False)
+        _fq_addr_from_string.raw_copies[key] = ptr
+        ll_string = llstr(string)
+        gcptr = lltype.cast_opaque_ptr(llmemory.GCREF, ll_string)
+        _fq_addr_from_string.register_finalizer(gcptr)
+    return ptr
diff --git a/rpython/rtyper/lltypesystem/test/test_rffi.py b/rpython/rtyper/lltypesystem/test/test_rffi.py
--- a/rpython/rtyper/lltypesystem/test/test_rffi.py
+++ b/rpython/rtyper/lltypesystem/test/test_rffi.py
@@ -814,6 +814,35 @@
     def test_generate_return_char_tests(self):
         py.test.skip("GenC does not handle char return values correctly")
 
+    def test__get_raw_address_buf_from_string(self):
+        from rpython.rlib import rgc
+        from rpython.rtyper.lltypesystem import rffi
+
+        def check_content(strings, rawptrs):
+            for i in range(len(strings)):
+                p = rawptrs[i]
+                expected = strings[i] + '\x00'
+                for j in range(len(expected)):
+                    assert p[j] == expected[j]
+
+        def f(n):
+            strings = [str(i) for i in range(n)]
+            rawptrs = [rffi._get_raw_address_buf_from_string(s)
+                       for s in strings]
+            check_content(strings, rawptrs)
+            rgc.collect(); rgc.collect(); rgc.collect()
+            check_content(strings, rawptrs)
+            del strings
+            rgc.collect(); rgc.collect(); rgc.collect()
+            return 42
+
+        rffi._StrFinalizerQueue.print_debugging = True
+        try:
+            xf = self.compile(f, [int], gcpolicy="incminimark")
+            assert xf(10000) == 42
+        finally:
+            rffi._StrFinalizerQueue.print_debugging = False
+
 def test_enforced_args():
     from rpython.annotator.model import s_None
     from rpython.rtyper.annlowlevel import MixLevelHelperAnnotator


More information about the pypy-commit mailing list