[pypy-commit] pypy gc-minimark-pinning: try to pass more stuff around nonmovingbuffer

fijal noreply at buildbot.pypy.org
Mon Apr 23 12:04:07 CEST 2012


Author: Maciej Fijalkowski <fijall at gmail.com>
Branch: gc-minimark-pinning
Changeset: r54663:d3ec07c4849c
Date: 2012-04-23 12:02 +0200
http://bitbucket.org/pypy/pypy/changeset/d3ec07c4849c/

Log:	try to pass more stuff around nonmovingbuffer

diff --git a/pypy/rlib/runicode.py b/pypy/rlib/runicode.py
--- a/pypy/rlib/runicode.py
+++ b/pypy/rlib/runicode.py
@@ -1481,8 +1481,7 @@
         if not final and is_dbcs_lead_byte(s[size-1]):
             size -= 1
 
-        dataptr = rffi.get_nonmovingbuffer(s)
-        try:
+        with rffi.scoped_nonmoving_unicodebuffer(s) as dataptr:
             # first get the size of the result
             usize = MultiByteToWideChar(CP_ACP, 0,
                                         dataptr, size,
@@ -1490,19 +1489,12 @@
             if usize == 0:
                 raise rwin32.lastWindowsError()
 
-            raw_buf, gc_buf = rffi.alloc_unicodebuffer(usize)
-            try:
+            with rffi.scoped_alloc_unicodebuffer(usize) as buf:
                 # do the conversion
                 if MultiByteToWideChar(CP_ACP, 0,
-                                       dataptr, size, raw_buf, usize) == 0:
+                                       dataptr, size, buf.raw, usize) == 0:
                     raise rwin32.lastWindowsError()
-
-                return (rffi.unicode_from_buffer(raw_buf, gc_buf, usize, usize),
-                        size)
-            finally:
-                rffi.keep_unicodebuffer_alive_until_here(raw_buf, gc_buf)
-        finally:
-            rffi.free_nonmovingbuffer(s, dataptr)
+                return buf.str(usize), size
 
     def unicode_encode_mbcs(p, size, errors, errorhandler=None):
         if size == 0:
diff --git a/pypy/rpython/lltypesystem/rffi.py b/pypy/rpython/lltypesystem/rffi.py
--- a/pypy/rpython/lltypesystem/rffi.py
+++ b/pypy/rpython/lltypesystem/rffi.py
@@ -713,24 +713,26 @@
         string is already nonmovable.  Must be followed by a
         free_nonmovingbuffer call.
         """
-        rgc.pin(data)
-        if rgc.can_move(data) or not we_are_translated():
-            count = len(data)
-            buf = lltype.malloc(TYPEP.TO, count, flavor='raw')
-            for i in range(count):
-                buf[i] = data[i]
-            return buf
-        else:
-            ll_s = llstrtype(data)
-            data_start = cast_ptr_to_adr(ll_s) + \
-                offsetof(STRTYPE, 'chars') + itemoffsetof(STRTYPE.chars, 0)
-            return cast(TYPEP, data_start)
+        pinned = False
+        if rgc.can_move(data):
+            if rgc.pin(data):
+                pinned = True
+            else:
+                count = len(data)
+                buf = lltype.malloc(TYPEP.TO, count, flavor='raw')
+                for i in range(count):
+                    buf[i] = data[i]
+                return buf, False, True
+        ll_s = llstrtype(data)
+        data_start = cast_ptr_to_adr(ll_s) + \
+                     offsetof(STRTYPE, 'chars') + itemoffsetof(STRTYPE.chars, 0)
+        return cast(TYPEP, data_start), pinned, False
     get_nonmovingbuffer._annenforceargs_ = [strtype]
 
     # (str, char*) -> None
     # Can't inline this because of the raw address manipulation.
     @jit.dont_look_inside
-    def free_nonmovingbuffer(data, buf):
+    def free_nonmovingbuffer(data, buf, pinned, is_raw):
         """
         Either free a non-moving buffer or keep the original storage alive.
         """
@@ -739,17 +741,12 @@
         # if 'buf' points inside 'data'.  This is only possible if we
         # followed the 2nd case in get_nonmovingbuffer(); in the first case,
         # 'buf' points to its own raw-malloced memory.
-        ll_data = llstrtype(data)
-        data_start = cast_ptr_to_adr(ll_data) + \
-            offsetof(STRTYPE, 'chars') + itemoffsetof(STRTYPE.chars, 0)
-        followed_2nd_path = (buf == cast(TYPEP, data_start))
         keepalive_until_here(data)
-        keepalive_until_here(ll_data)
-        if followed_2nd_path:
+        if pinned:
             rgc.unpin(data)
-        else:
+        elif is_raw:
             lltype.free(buf, flavor='raw')
-    free_nonmovingbuffer._annenforceargs_ = [strtype, None]
+    free_nonmovingbuffer._annenforceargs_ = [strtype, None, bool, bool]
 
     # int -> (char*, str)
     def alloc_buffer(count):
@@ -1070,20 +1067,22 @@
     def __init__(self, data):
         self.data = data
     def __enter__(self):
-        self.buf = get_nonmovingbuffer(self.data)
+        self.buf, self.pinned, self.is_raw = get_nonmovingbuffer(self.data)
         return self.buf
     def __exit__(self, *args):
-        free_nonmovingbuffer(self.data, self.buf)
+        free_nonmovingbuffer(self.data, self.buf, self.pinned, self.is_raw)
 
 
 class scoped_nonmoving_unicodebuffer:
     def __init__(self, data):
         self.data = data
     def __enter__(self):
-        self.buf = get_nonmoving_unicodebuffer(self.data)
+        self.buf, self.pinned, self.is_raw = get_nonmoving_unicodebuffer(
+            self.data)
         return self.buf
     def __exit__(self, *args):
-        free_nonmoving_unicodebuffer(self.data, self.buf)
+        free_nonmoving_unicodebuffer(self.data, self.buf, self.pinned,
+                                     self.is_raw)
 
 class scoped_alloc_buffer:
     def __init__(self, size):
diff --git a/pypy/rpython/lltypesystem/test/test_rffi.py b/pypy/rpython/lltypesystem/test/test_rffi.py
--- a/pypy/rpython/lltypesystem/test/test_rffi.py
+++ b/pypy/rpython/lltypesystem/test/test_rffi.py
@@ -513,7 +513,7 @@
     def test_nonmovingbuffer(self):
         d = 'some cool data that should not move'
         def f():
-            buf = get_nonmovingbuffer(d)
+            buf, is_pinned, is_raw = get_nonmovingbuffer(d)
             try:
                 counter = 0
                 for i in range(len(d)):
@@ -521,7 +521,7 @@
                         counter += 1
                 return counter
             finally:
-                free_nonmovingbuffer(d, buf)
+                free_nonmovingbuffer(d, buf, is_pinned_is_raw)
         assert f() == len(d)
         fn = self.compile(f, [], gcpolicy='ref')
         assert fn() == len(d)
@@ -531,13 +531,13 @@
         def f():
             counter = 0
             for n in range(32):
-                buf = get_nonmovingbuffer(d)
+                buf, is_pinned, is_raw = get_nonmovingbuffer(d)
                 try:
                     for i in range(len(d)):
                         if buf[i] == d[i]:
                             counter += 1
                 finally:
-                    free_nonmovingbuffer(d, buf)
+                    free_nonmovingbuffer(d, buf, is_pinned, is_raw)
             return counter
         fn = self.compile(f, [], gcpolicy='semispace')
         # The semispace gc uses raw_malloc for its internal data structs
diff --git a/pypy/rpython/module/ll_os.py b/pypy/rpython/module/ll_os.py
--- a/pypy/rpython/module/ll_os.py
+++ b/pypy/rpython/module/ll_os.py
@@ -910,15 +910,12 @@
 
         def os_write_llimpl(fd, data):
             count = len(data)
-            buf = rffi.get_nonmovingbuffer(data)
-            try:
+            with rffi.scoped_nonmovingbuffer(data) as buf:
                 written = rffi.cast(lltype.Signed, os_write(
                     rffi.cast(rffi.INT, fd),
                     buf, rffi.cast(rffi.SIZE_T, count)))
                 if written < 0:
                     raise OSError(rposix.get_errno(), "os_write failed")
-            finally:
-                rffi.free_nonmovingbuffer(data, buf)
             return written
 
         def os_write_oofakeimpl(fd, data):


More information about the pypy-commit mailing list