Author: Devin Jeanpierre <[email protected]>
Branch: cpyext-old-buffers
Changeset: r84753:5370a01c9140
Date: 2016-05-27 18:14 -0700
http://bitbucket.org/pypy/pypy/changeset/5370a01c9140/

Log:    Special-case buffer in typeobject.py instead of leaking for
        get_raw_address().

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
@@ -1,4 +1,4 @@
-from rpython.rlib.buffer import Buffer, StringBuffer, SubBuffer
+from rpython.rlib.buffer import StringBuffer, SubBuffer
 from rpython.rtyper.lltypesystem import rffi, lltype
 from pypy.interpreter.error import oefmt
 from pypy.module.cpyext.api import (
@@ -9,54 +9,6 @@
 from pypy.objspace.std.bufferobject import W_Buffer
 
 
-class LeakedBuffer(Buffer):
-    __slots__ = ['buf','ptr']
-    _immutable_ = True
-
-    def __init__(self, buffer):
-        if not buffer.readonly:
-            raise ValueError("Can only leak a copy of a readonly buffer.")
-        self.buf = buffer
-        self.readonly = True
-        self.ptr = rffi.cast(rffi.VOIDP, rffi.str2charp(self.buf.as_str()))
-
-    def getlength(self):
-        return self.buf.getlength()
-
-    def as_str(self):
-        return self.buf.as_str()
-
-    def as_str_and_offset_maybe(self):
-        return self.buf.as_str_and_offset_maybe()
-
-    def getitem(self, index):
-        return self.buf.getitem(index)
-
-    def getslice(self, start, stop, step, size):
-        return self.buf.getslice(start, stop, step, size)
-
-    def setitem(self, index, char):
-        return self.buf.setitem(index)
-
-    def setslice(self, start, string):
-        return self.buf.setslice(start, string)
-
-    def get_raw_address(self):
-        return self.ptr
-
-
-def leak_stringbuffer(buf):
-    if isinstance(buf, StringBuffer):
-        return LeakedBuffer(buf)
-    elif isinstance(buf, SubBuffer):
-        leaked = leak_stringbuffer(buf.buffer)
-        if leaked is None:
-            return leaked
-        return SubBuffer(leaked, buf.offset, buf.size)
-    else:
-        return None
-
-
 PyBufferObjectStruct = lltype.ForwardReference()
 PyBufferObject = lltype.Ptr(PyBufferObjectStruct)
 PyBufferObjectFields = PyObjectFields + (
@@ -91,19 +43,17 @@
     assert isinstance(w_obj, W_Buffer)
     buf = w_obj.buf
 
-    w_obj.buf = buf = leak_stringbuffer(buf) or buf
-    # Now, if it was backed by a StringBuffer, it is now a LeakedBuffer.
-    # We deliberately copy the string so that we can have a pointer to it,
-    # and we make it accessible in the buffer through get_raw_address(), so 
that
-    # we can reuse it elsewhere in the C API.
-
     if isinstance(buf, SubBuffer):
         py_buf.c_b_offset = buf.offset
         buf = buf.buffer
 
-    if isinstance(buf, LeakedBuffer):
+    # 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.
+
+    if isinstance(buf, StringBuffer):
         py_buf.c_b_base = lltype.nullptr(PyObject.TO)
-        py_buf.c_b_ptr = buf.get_raw_address()
+        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
diff --git a/pypy/module/cpyext/typeobject.py b/pypy/module/cpyext/typeobject.py
--- a/pypy/module/cpyext/typeobject.py
+++ b/pypy/module/cpyext/typeobject.py
@@ -453,7 +453,7 @@
 def bf_getreadbuffer(space, w_buf, segment, ref):
     if segment != 0:
         raise oefmt(space.w_SystemError,
-                    "accessing non-existent buffer segment")
+                    "accessing non-existent segment")
     buf = space.readbuf_w(w_buf)
     address = buf.get_raw_address()
     ref[0] = address
@@ -464,19 +464,17 @@
 def bf_getcharbuffer(space, w_buf, segment, ref):
     return bf_getreadbuffer(space, w_buf, segment, rffi.cast(rffi.VOIDPP, ref))
 
-
 @cpython_api([PyObject, Py_ssize_t, rffi.VOIDPP], lltype.Signed,
              header=None, error=-1)
 def bf_getwritebuffer(space, w_buf, segment, ref):
     if segment != 0:
         raise oefmt(space.w_SystemError,
-                    "accessing non-existent buffer segment")
+                    "accessing non-existent segment")
 
     buf = space.writebuf_w(w_buf)
     ref[0] = buf.get_raw_address()
     return len(buf)
 
-
 @cpython_api([PyObject, Py_ssize_t, rffi.VOIDPP], lltype.Signed,
              header=None, error=-1)
 def str_getreadbuffer(space, w_str, segment, ref):
@@ -490,12 +488,26 @@
     Py_DecRef(space, pyref)
     return space.len_w(w_str)
 
-
 @cpython_api([PyObject, Py_ssize_t, rffi.CCHARPP], lltype.Signed,
              header=None, error=-1)
 def str_getcharbuffer(space, w_buf, segment, ref):
     return str_getreadbuffer(space, w_buf, segment, rffi.cast(rffi.VOIDPP, 
ref))
 
+@cpython_api([PyObject, Py_ssize_t, rffi.VOIDPP], lltype.Signed,
+             header=None, error=-1)
+def buf_getreadbuffer(space, pyref, segment, ref):
+    from pypy.module.cpyext.bufferobject import PyBufferObject
+    if segment != 0:
+        raise oefmt(space.w_SystemError,
+                    "accessing non-existent buffer segment")
+    py_buf = rffi.cast(PyBufferObject, pyref)
+    ref[0] = py_buf.c_b_ptr
+    return py_buf.c_b_size
+
+@cpython_api([PyObject, Py_ssize_t, rffi.CCHARPP], lltype.Signed,
+             header=None, error=-1)
+def buf_getcharbuffer(space, w_buf, segment, ref):
+    return buf_getreadbuffer(space, w_buf, segment, rffi.cast(rffi.VOIDPP, 
ref))
 
 def setup_buffer_procs(space, w_type, pto):
     bufspec = w_type.layout.typedef.buffer
@@ -516,6 +528,17 @@
         c_buf.c_bf_getcharbuffer = llhelper(
             str_getcharbuffer.api_func.functype,
             str_getcharbuffer.api_func.get_wrapper(space))
+    elif space.is_w(w_type, space.w_buffer):
+        # Special case: we store a permanent address on the cpyext wrapper,
+        # so we'll reuse that.
+        # Note: we could instead store a permanent address on the buffer 
object,
+        # and use get_raw_address()
+        c_buf.c_bf_getreadbuffer = llhelper(
+            buf_getreadbuffer.api_func.functype,
+            buf_getreadbuffer.api_func.get_wrapper(space))
+        c_buf.c_bf_getcharbuffer = llhelper(
+            buf_getcharbuffer.api_func.functype,
+            buf_getcharbuffer.api_func.get_wrapper(space))
     else:
         # use get_raw_address()
         c_buf.c_bf_getreadbuffer = llhelper(bf_getreadbuffer.api_func.functype,
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to