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