Author: Armin Rigo <[email protected]>
Branch: cpyext-gc-support
Changeset: r80423:33558aa4c963
Date: 2015-10-24 16:13 +0200
http://bitbucket.org/pypy/pypy/changeset/33558aa4c963/

Log:    hack hack hack hack hack buffer objects

diff --git a/pypy/module/cpyext/api.py b/pypy/module/cpyext/api.py
--- a/pypy/module/cpyext/api.py
+++ b/pypy/module/cpyext/api.py
@@ -870,7 +870,17 @@
 
     space.fromcache(State).install_dll(eci)
 
-    rawrefcount.init(lambda ob: _Py_Dealloc(space, ob))
+    def dealloc_trigger():
+        print 'dealloc_trigger...'
+        while True:
+            ob = rawrefcount.next_dead(PyObject)
+            if not ob:
+                break
+            print ob
+            _Py_Dealloc(space, ob)
+        print 'dealloc_trigger DONE'
+        return "RETRY"
+    rawrefcount.init(dealloc_trigger)
 
     # populate static data
     to_fill = []
diff --git a/pypy/module/cpyext/bufferobject.py 
b/pypy/module/cpyext/bufferobject.py
--- a/pypy/module/cpyext/bufferobject.py
+++ b/pypy/module/cpyext/bufferobject.py
@@ -4,7 +4,9 @@
 from pypy.module.cpyext.api import (
     cpython_api, Py_ssize_t, cpython_struct, bootstrap_function,
     PyObjectFields, PyObject)
-from pypy.module.cpyext.pyobject import make_typedescr, Py_DecRef
+from pypy.module.cpyext.pyobject import (
+    setup_class_for_cpyext, RRC_PERMANENT, get_pyobj_and_xincref, xdecref)
+from pypy.module.cpyext import support
 from pypy.module.array.interp_array import ArrayBuffer
 from pypy.objspace.std.bufferobject import W_Buffer
 
@@ -18,6 +20,7 @@
     ("b_offset", Py_ssize_t),
     ("b_readonly", rffi.INT),
     ("b_hash", rffi.LONG),
+    ("_b_data_pypy", rffi.CArray(lltype.Char)),
     )
 
 cpython_struct("PyBufferObject", PyBufferObjectFields, PyBufferObjectStruct)
@@ -25,61 +28,67 @@
 @bootstrap_function
 def init_bufferobject(space):
     "Type description of PyBufferObject"
-    make_typedescr(space.w_buffer.instancetypedef,
-                   basestruct=PyBufferObject.TO,
-                   attach=buffer_attach,
-                   dealloc=buffer_dealloc,
-                   realize=buffer_realize)
+    setup_class_for_cpyext(
+        W_Buffer,
+        basestruct=PyBufferObjectStruct,
 
-def buffer_attach(space, py_obj, w_obj):
+        # --from a W_Buffer, we call this function to create and fill a
+        #   new PyBufferObject --
+        alloc_pyobj=buffer_alloc_pyobj,
+
+        # --deallocator--
+        dealloc=buffer_dealloc,
+        )
+
+def buffer_alloc_pyobj(space, w_obj):
     """
-    Fills a newly allocated PyBufferObject with the given (str) buffer object.
+    Fills a newly allocated PyBufferObject with the given W_Buffer object.
     """
-    py_buf = rffi.cast(PyBufferObject, py_obj)
-    py_buf.c_b_offset = 0
-    rffi.setintfield(py_buf, 'c_b_readonly', 1)
-    rffi.setintfield(py_buf, 'c_b_hash', -1)
 
     assert isinstance(w_obj, W_Buffer)
     buf = w_obj.buf
 
+    # If buf already allocated a fixed buffer, use it, and keep a
+    # reference to buf.
+    # Otherwise, b_base stays NULL, and the b_ptr points inside the
+    # allocated object.
+
+    try:
+        ptr = buf.get_raw_address()
+    except ValueError:
+        srcstring = buf.as_str()
+        size = len(srcstring)
+        w_base = None
+        ptr = lltype.nullptr(rffi.VOIDP.TO)
+    else:
+        srcstring = ''
+        if isinstance(buf, ArrayBuffer):
+            w_base = buf.array
+        else:
+            w_base = w_obj
+        size = buf.getlength()
+        ptr = rffi.cast(rffi.VOIDP, ptr)
+
+    py_buf = lltype.malloc(PyBufferObjectStruct, len(srcstring), flavor='raw',
+                           track_allocation=False)
+    py_buf.c_b_base = get_pyobj_and_xincref(space, w_base)
+
+    if w_base is None:
+        ptr = py_buf._b_data_pypy
+        rffi.str2rawmem(srcstring, ptr, 0, size)
+        ptr = rffi.cast(rffi.VOIDP, ptr)
+    py_buf.c_b_ptr = ptr
+    py_buf.c_b_size = size
     if isinstance(buf, SubBuffer):
         py_buf.c_b_offset = buf.offset
-        buf = buf.buffer
+    else:
+        py_buf.c_b_offset = 0
+    rffi.setintfield(py_buf, 'c_b_readonly', 1)
+    rffi.setintfield(py_buf, 'c_b_hash', -1)
 
-    # If buf already allocated a fixed buffer, use it, and keep a
-    # reference to buf.
-    # Otherwise, b_base stays NULL, and we own the b_ptr.
+    return py_buf, RRC_PERMANENT
 
-    ZZZ
-    if isinstance(buf, StringBuffer):
-        py_buf.c_b_base = lltype.nullptr(PyObject.TO)
-        py_buf.c_b_ptr = rffi.cast(rffi.VOIDP, rffi.str2charp(buf.value))
-        py_buf.c_b_size = buf.getlength()
-    elif isinstance(buf, ArrayBuffer):
-        w_base = buf.array
-        py_buf.c_b_base = make_ref(space, w_base)
-        py_buf.c_b_ptr = rffi.cast(rffi.VOIDP, buf.array._charbuf_start())
-        py_buf.c_b_size = buf.getlength()
-    else:
-        raise OperationError(space.w_NotImplementedError, space.wrap(
-            "buffer flavor not supported"))
 
-
-def buffer_realize(space, py_obj):
-    """
-    Creates the buffer in the PyPy interpreter from a cpyext representation.
-    """
-    raise OperationError(space.w_NotImplementedError, space.wrap(
-        "Don't know how to realize a buffer"))
-
-
-@cpython_api([PyObject], lltype.Void, external=False)
-def buffer_dealloc(space, py_obj):
-    py_buf = rffi.cast(PyBufferObject, py_obj)
-    if py_buf.c_b_base:
-        Py_DecRef(space, py_buf.c_b_base)
-    else:
-        rffi.free_charp(rffi.cast(rffi.CCHARP, py_buf.c_b_ptr))
-    from pypy.module.cpyext.object import PyObject_dealloc
-    PyObject_dealloc(space, py_obj)
+def buffer_dealloc(space, py_buf):
+    xdecref(space, py_buf.c_b_base)
+    lltype.free(py_buf, flavor='raw', track_allocation=False)
diff --git a/pypy/module/cpyext/include/bufferobject.h 
b/pypy/module/cpyext/include/bufferobject.h
--- a/pypy/module/cpyext/include/bufferobject.h
+++ b/pypy/module/cpyext/include/bufferobject.h
@@ -17,6 +17,7 @@
        Py_ssize_t b_offset;
        int b_readonly;
        long b_hash;
+       char _b_data_pypy[1];
 } PyBufferObject;
 
 
diff --git a/pypy/module/cpyext/object.py b/pypy/module/cpyext/object.py
--- a/pypy/module/cpyext/object.py
+++ b/pypy/module/cpyext/object.py
@@ -55,7 +55,7 @@
 
 @cpython_api([rffi.VOIDP], lltype.Void)
 def PyObject_Del(space, obj):
-    lltype.free(obj, flavor='raw')
+    lltype.free(obj, flavor='raw', track_allocation=False)
 
 @cpython_api([PyObject], lltype.Void)
 def PyObject_dealloc(space, obj):
diff --git a/pypy/module/cpyext/test/test_bufferobject.py 
b/pypy/module/cpyext/test/test_bufferobject.py
--- a/pypy/module/cpyext/test/test_bufferobject.py
+++ b/pypy/module/cpyext/test/test_bufferobject.py
@@ -61,4 +61,4 @@
         a = array.array('c', 'text')
         b = buffer(a)
         assert module.roundtrip(b) == 'text'
-        
+        del a
diff --git a/pypy/module/cpyext/test/test_cpyext.py 
b/pypy/module/cpyext/test/test_cpyext.py
--- a/pypy/module/cpyext/test/test_cpyext.py
+++ b/pypy/module/cpyext/test/test_cpyext.py
@@ -374,6 +374,7 @@
     def teardown_method(self, func):
         for name in self.imported_module_names:
             self.unimport_module(name)
+        self.check_and_print_leaks()
         return #ZZZ
         self.cleanup_references(self.space)
         # XXX: find out how to disable check_and_print_leaks() if the
diff --git a/rpython/rlib/rawrefcount.py b/rpython/rlib/rawrefcount.py
--- a/rpython/rlib/rawrefcount.py
+++ b/rpython/rlib/rawrefcount.py
@@ -146,7 +146,9 @@
         attach(ob, wr, _o_list)
 
     if _d_list:
-        _dealloc_trigger_callback()
+        res = _dealloc_trigger_callback()
+        if res == "RETRY":
+            _collect(track_allocation=track_allocation)
 
 _keepalive_forever = set()
 def _dont_free_any_more():
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
@@ -803,6 +803,12 @@
         return length
     str2chararray._annenforceargs_ = [strtype, None, int]
 
+    # s[start:start+length] -> already-existing char[],
+    # all characters including zeros
+    def str2rawmem(s, array, start, length):
+        ll_s = llstrtype(s)
+        copy_string_to_raw(ll_s, array, start, length)
+
     # char* -> str
     # doesn't free char*
     def charp2str(cp):
@@ -953,19 +959,19 @@
     return (str2charp, free_charp, charp2str,
             get_nonmovingbuffer, free_nonmovingbuffer,
             alloc_buffer, str_from_buffer, keep_buffer_alive_until_here,
-            charp2strn, charpsize2str, str2chararray,
+            charp2strn, charpsize2str, str2chararray, str2rawmem,
             )
 
 (str2charp, free_charp, charp2str,
  get_nonmovingbuffer, free_nonmovingbuffer,
  alloc_buffer, str_from_buffer, keep_buffer_alive_until_here,
- charp2strn, charpsize2str, str2chararray,
+ charp2strn, charpsize2str, str2chararray, str2rawmem,
  ) = make_string_mappings(str)
 
 (unicode2wcharp, free_wcharp, wcharp2unicode,
  get_nonmoving_unicodebuffer, free_nonmoving_unicodebuffer,
  alloc_unicodebuffer, unicode_from_buffer, keep_unicodebuffer_alive_until_here,
- wcharp2unicoden, wcharpsize2unicode, unicode2wchararray,
+ wcharp2unicoden, wcharpsize2unicode, unicode2wchararray, unicode2rawmem,
  ) = make_string_mappings(unicode)
 
 # char**
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to