[pypy-commit] pypy default: Kill most of the fragile keepalive_until_here() logic. Replace it with a
arigo
noreply at buildbot.pypy.org
Wed Mar 4 15:32:43 CET 2015
Author: Armin Rigo <arigo at tunes.org>
Branch:
Changeset: r76242:1a44b21df005
Date: 2015-03-04 15:32 +0100
http://bitbucket.org/pypy/pypy/changeset/1a44b21df005/
Log: Kill most of the fragile keepalive_until_here() logic. Replace it
with a context manager API, declared on the W_CData objects
themselves.
diff --git a/pypy/module/_cffi_backend/cbuffer.py b/pypy/module/_cffi_backend/cbuffer.py
--- a/pypy/module/_cffi_backend/cbuffer.py
+++ b/pypy/module/_cffi_backend/cbuffer.py
@@ -81,4 +81,5 @@
if size < 0:
raise oefmt(space.w_TypeError,
"don't know the size pointed to by '%s'", ctype.name)
- return space.wrap(MiniBuffer(LLBuffer(w_cdata._cdata, size), w_cdata))
+ ptr = w_cdata.unsafe_escaping_ptr() # w_cdata kept alive by MiniBuffer()
+ return space.wrap(MiniBuffer(LLBuffer(ptr, size), w_cdata))
diff --git a/pypy/module/_cffi_backend/ccallback.py b/pypy/module/_cffi_backend/ccallback.py
--- a/pypy/module/_cffi_backend/ccallback.py
+++ b/pypy/module/_cffi_backend/ccallback.py
@@ -48,9 +48,12 @@
raise oefmt(space.w_NotImplementedError,
"%s: callback with unsupported argument or "
"return type or with '...'", self.getfunctype().name)
- res = clibffi.c_ffi_prep_closure(self.get_closure(), cif_descr.cif,
- invoke_callback,
- rffi.cast(rffi.VOIDP, self.unique_id))
+ with self as ptr:
+ closure_ptr = rffi.cast(clibffi.FFI_CLOSUREP, ptr)
+ unique_id = rffi.cast(rffi.VOIDP, self.unique_id)
+ res = clibffi.c_ffi_prep_closure(closure_ptr, cif_descr.cif,
+ invoke_callback,
+ unique_id)
if rffi.cast(lltype.Signed, res) != clibffi.FFI_OK:
raise OperationError(space.w_SystemError,
space.wrap("libffi failed to build this callback"))
@@ -62,12 +65,9 @@
from pypy.module.thread.os_thread import setup_threads
setup_threads(space)
- def get_closure(self):
- return rffi.cast(clibffi.FFI_CLOSUREP, self._cdata)
-
#@rgc.must_be_light_finalizer
def __del__(self):
- clibffi.closureHeap.free(self.get_closure())
+ clibffi.closureHeap.free(rffi.cast(clibffi.FFI_CLOSUREP, self._ptr))
if self.ll_error:
lltype.free(self.ll_error, flavor='raw')
@@ -106,7 +106,7 @@
fresult = self.getfunctype().ctitem
if fresult.size > 0:
misc._raw_memcopy(self.ll_error, ll_res, fresult.size)
- keepalive_until_here(self)
+ keepalive_until_here(self) # to keep self.ll_error alive
global_callback_mapping = rweakref.RWeakValueDictionary(int, W_CDataCallback)
diff --git a/pypy/module/_cffi_backend/cdataobj.py b/pypy/module/_cffi_backend/cdataobj.py
--- a/pypy/module/_cffi_backend/cdataobj.py
+++ b/pypy/module/_cffi_backend/cdataobj.py
@@ -14,21 +14,37 @@
class W_CData(W_Root):
- _attrs_ = ['space', '_cdata', 'ctype', '_lifeline_']
- _immutable_fields_ = ['_cdata', 'ctype']
- _cdata = lltype.nullptr(rffi.CCHARP.TO)
+ _attrs_ = ['space', '_ptr', 'ctype', '_lifeline_']
+ _immutable_fields_ = ['_ptr', 'ctype']
+ _ptr = lltype.nullptr(rffi.CCHARP.TO)
- def __init__(self, space, cdata, ctype):
+ def __init__(self, space, ptr, ctype):
from pypy.module._cffi_backend import ctypeobj
- assert lltype.typeOf(cdata) == rffi.CCHARP
+ assert lltype.typeOf(ptr) == rffi.CCHARP
assert isinstance(ctype, ctypeobj.W_CType)
self.space = space
- self._cdata = cdata # don't forget keepalive_until_here!
+ self._ptr = ptr # don't access directly! use "with cdata as ptr:"
self.ctype = ctype
+ def __enter__(self):
+ """Use 'with cdata as ptr:' to access the raw memory. It will
+ stay alive at least until the end of the 'with' block.
+ """
+ return self._ptr
+
+ def __exit__(self, *args):
+ keepalive_until_here(self)
+
+ def unsafe_escaping_ptr(self):
+ """Generally unsafe: escape the pointer to raw memory.
+ If 'self' is a subclass that frees the pointer in a destructor,
+ it may be freed under your feet at any time.
+ """
+ return self._ptr
+
def _repr_extra(self):
- extra = self.ctype.extra_repr(self._cdata)
- keepalive_until_here(self)
+ with self as ptr:
+ extra = self.ctype.extra_repr(ptr)
return extra
def _repr_extra_owning(self):
@@ -54,11 +70,13 @@
self.ctype.name, extra1, extra2))
def nonzero(self):
- return self.space.wrap(bool(self._cdata))
+ with self as ptr:
+ nonzero = bool(ptr)
+ return self.space.wrap(nonzero)
def int(self, space):
- w_result = self.ctype.cast_to_int(self._cdata)
- keepalive_until_here(self)
+ with self as ptr:
+ w_result = self.ctype.cast_to_int(ptr)
return w_result
def long(self, space):
@@ -69,8 +87,8 @@
return w_result
def float(self):
- w_result = self.ctype.float(self._cdata)
- keepalive_until_here(self)
+ with self as ptr:
+ w_result = self.ctype.float(ptr)
return w_result
def len(self):
@@ -88,20 +106,19 @@
def _cmp(self, w_other):
from pypy.module._cffi_backend.ctypeprim import W_CTypePrimitive
space = self.space
- cdata1 = self._cdata
- if isinstance(w_other, W_CData):
- cdata2 = w_other._cdata
- else:
+ if not isinstance(w_other, W_CData):
return space.w_NotImplemented
- if requires_ordering:
- if (isinstance(self.ctype, W_CTypePrimitive) or
- isinstance(w_other.ctype, W_CTypePrimitive)):
- raise OperationError(space.w_TypeError,
- space.wrap("cannot do comparison on a primitive cdata"))
- cdata1 = rffi.cast(lltype.Unsigned, cdata1)
- cdata2 = rffi.cast(lltype.Unsigned, cdata2)
- return space.newbool(op(cdata1, cdata2))
+ with self as ptr1, w_other as ptr2:
+ if requires_ordering:
+ if (isinstance(self.ctype, W_CTypePrimitive) or
+ isinstance(w_other.ctype, W_CTypePrimitive)):
+ raise OperationError(space.w_TypeError, space.wrap(
+ "cannot do comparison on a primitive cdata"))
+ ptr1 = rffi.cast(lltype.Unsigned, ptr1)
+ ptr2 = rffi.cast(lltype.Unsigned, ptr2)
+ result = op(ptr1, ptr2)
+ return space.newbool(result)
#
return func_with_new_name(_cmp, name)
@@ -113,7 +130,8 @@
ge = _make_comparison('ge')
def hash(self):
- h = rffi.cast(lltype.Signed, self._cdata)
+ ptr = self.unsafe_escaping_ptr()
+ h = rffi.cast(lltype.Signed, ptr)
# To hash pointers in dictionaries. Assumes that h shows some
# alignment (to 4, 8, maybe 16 bytes), so we use the following
# formula to avoid the trailing bits being always 0.
@@ -128,26 +146,27 @@
i = space.getindex_w(w_index, space.w_IndexError)
ctype = self.ctype._check_subscript_index(self, i)
w_o = self._do_getitem(ctype, i)
- keepalive_until_here(self)
return w_o
def _do_getitem(self, ctype, i):
ctitem = ctype.ctitem
- return ctitem.convert_to_object(
- rffi.ptradd(self._cdata, i * ctitem.size))
+ with self as ptr:
+ return ctitem.convert_to_object(
+ rffi.ptradd(ptr, i * ctitem.size))
def setitem(self, w_index, w_value):
space = self.space
if space.isinstance_w(w_index, space.w_slice):
- self._do_setslice(w_index, w_value)
+ with self as ptr:
+ self._do_setslice(w_index, w_value, ptr)
else:
i = space.getindex_w(w_index, space.w_IndexError)
ctype = self.ctype._check_subscript_index(self, i)
ctitem = ctype.ctitem
- ctitem.convert_from_object(
- rffi.ptradd(self._cdata, i * ctitem.size),
- w_value)
- keepalive_until_here(self)
+ with self as ptr:
+ ctitem.convert_from_object(
+ rffi.ptradd(ptr, i * ctitem.size),
+ w_value)
def _do_getslicearg(self, w_slice):
from pypy.module._cffi_backend.ctypeptr import W_CTypePointer
@@ -188,14 +207,15 @@
ctarray = newtype.new_array_type(space, ctptr, space.w_None)
ctptr.cache_array_type = ctarray
#
- p = rffi.ptradd(self._cdata, start * ctarray.ctitem.size)
- return W_CDataSliced(space, p, ctarray, length)
+ ptr = self.unsafe_escaping_ptr()
+ ptr = rffi.ptradd(ptr, start * ctarray.ctitem.size)
+ return W_CDataSliced(space, ptr, ctarray, length)
- def _do_setslice(self, w_slice, w_value):
+ def _do_setslice(self, w_slice, w_value, ptr):
ctptr, start, length = self._do_getslicearg(w_slice)
ctitem = ctptr.ctitem
ctitemsize = ctitem.size
- cdata = rffi.ptradd(self._cdata, start * ctitemsize)
+ target = rffi.ptradd(ptr, start * ctitemsize)
#
if isinstance(w_value, W_CData):
from pypy.module._cffi_backend import ctypearray
@@ -204,9 +224,8 @@
ctv.ctitem is ctitem and
w_value.get_array_length() == length):
# fast path: copying from exactly the correct type
- s = w_value._cdata
- rffi.c_memcpy(cdata, s, ctitemsize * length)
- keepalive_until_here(w_value)
+ with w_value as source:
+ rffi.c_memcpy(target, source, ctitemsize * length)
return
#
# A fast path for <char[]>[0:N] = "somestring".
@@ -221,7 +240,7 @@
raise oefmt(space.w_ValueError,
"need a string of length %d, got %d",
length, len(value))
- copy_string_to_raw(llstr(value), cdata, 0, length)
+ copy_string_to_raw(llstr(value), target, 0, length)
return
#
w_iter = space.iter(w_value)
@@ -233,8 +252,8 @@
raise
raise oefmt(space.w_ValueError,
"need %d values to unpack, got %d", length, i)
- ctitem.convert_from_object(cdata, w_item)
- cdata = rffi.ptradd(cdata, ctitemsize)
+ ctitem.convert_from_object(target, w_item)
+ target = rffi.ptradd(target, ctitemsize)
try:
space.next(w_iter)
except OperationError, e:
@@ -247,7 +266,8 @@
def _add_or_sub(self, w_other, sign):
space = self.space
i = sign * space.getindex_w(w_other, space.w_OverflowError)
- return self.ctype.add(self._cdata, i)
+ ptr = self.unsafe_escaping_ptr()
+ return self.ctype.add(ptr, i)
def add(self, w_other):
return self._add_or_sub(w_other, +1)
@@ -268,9 +288,11 @@
self.ctype.name, ct.name)
#
itemsize = ct.ctitem.size
- if itemsize <= 0: itemsize = 1
- diff = (rffi.cast(lltype.Signed, self._cdata) -
- rffi.cast(lltype.Signed, w_other._cdata)) // itemsize
+ if itemsize <= 0:
+ itemsize = 1
+ with self as ptr1, w_other as ptr2:
+ diff = (rffi.cast(lltype.Signed, ptr1) -
+ rffi.cast(lltype.Signed, ptr2)) // itemsize
return space.wrap(diff)
#
return self._add_or_sub(w_other, -1)
@@ -279,17 +301,19 @@
return self.ctype.getcfield(self.space.str_w(w_attr))
def getattr(self, w_attr):
- w_res = self.getcfield(w_attr).read(self._cdata)
- keepalive_until_here(self)
+ cfield = self.getcfield(w_attr)
+ with self as ptr:
+ w_res = cfield.read(ptr)
return w_res
def setattr(self, w_attr, w_value):
- self.getcfield(w_attr).write(self._cdata, w_value)
- keepalive_until_here(self)
+ cfield = self.getcfield(w_attr)
+ with self as ptr:
+ cfield.write(ptr, w_value)
def call(self, args_w):
- w_result = self.ctype.call(self._cdata, args_w)
- keepalive_until_here(self)
+ with self as ptr:
+ w_result = self.ctype.call(ptr, args_w)
return w_result
def iter(self):
@@ -311,21 +335,21 @@
@specialize.argtype(1)
def write_raw_signed_data(self, source):
- misc.write_raw_signed_data(self._cdata, source, self.ctype.size)
- keepalive_until_here(self)
+ with self as ptr:
+ misc.write_raw_signed_data(ptr, source, self.ctype.size)
@specialize.argtype(1)
def write_raw_unsigned_data(self, source):
- misc.write_raw_unsigned_data(self._cdata, source, self.ctype.size)
- keepalive_until_here(self)
+ with self as ptr:
+ misc.write_raw_unsigned_data(ptr, source, self.ctype.size)
def write_raw_float_data(self, source):
- misc.write_raw_float_data(self._cdata, source, self.ctype.size)
- keepalive_until_here(self)
+ with self as ptr:
+ misc.write_raw_float_data(ptr, source, self.ctype.size)
def convert_to_object(self):
- w_obj = self.ctype.convert_to_object(self._cdata)
- keepalive_until_here(self)
+ with self as ptr:
+ w_obj = self.ctype.convert_to_object(ptr)
return w_obj
def get_array_length(self):
@@ -353,7 +377,7 @@
@rgc.must_be_light_finalizer
def __del__(self):
- lltype.free(self._cdata, flavor='raw')
+ lltype.free(self._ptr, flavor='raw')
class W_CDataNewOwning(W_CDataMem):
diff --git a/pypy/module/_cffi_backend/ctypearray.py b/pypy/module/_cffi_backend/ctypearray.py
--- a/pypy/module/_cffi_backend/ctypearray.py
+++ b/pypy/module/_cffi_backend/ctypearray.py
@@ -8,7 +8,6 @@
from pypy.interpreter.typedef import TypeDef
from rpython.rtyper.lltypesystem import rffi
-from rpython.rlib.objectmodel import keepalive_until_here
from rpython.rlib.rarithmetic import ovfcheck
from pypy.module._cffi_backend import cdataobj
@@ -49,8 +48,8 @@
cdata = cdataobj.W_CDataNewOwning(space, datasize, self)
#
if not space.is_w(w_init, space.w_None):
- self.convert_from_object(cdata._cdata, w_init)
- keepalive_until_here(cdata)
+ with cdata as ptr:
+ self.convert_from_object(ptr, w_init)
return cdata
def _check_subscript_index(self, w_cdata, i):
@@ -119,8 +118,8 @@
self.ctitem = ctitem
self.cdata = cdata
length = cdata.get_array_length()
- self._next = cdata._cdata
- self._stop = rffi.ptradd(cdata._cdata, length * ctitem.size)
+ self._next = cdata.unsafe_escaping_ptr()
+ self._stop = rffi.ptradd(self._next, length * ctitem.size)
def iter_w(self):
return self.space.wrap(self)
diff --git a/pypy/module/_cffi_backend/ctypeenum.py b/pypy/module/_cffi_backend/ctypeenum.py
--- a/pypy/module/_cffi_backend/ctypeenum.py
+++ b/pypy/module/_cffi_backend/ctypeenum.py
@@ -2,8 +2,6 @@
Enums.
"""
-from rpython.rlib.objectmodel import keepalive_until_here
-
from pypy.module._cffi_backend import misc
from pypy.module._cffi_backend.ctypeprim import (W_CTypePrimitiveSigned,
W_CTypePrimitiveUnsigned)
@@ -47,8 +45,8 @@
return '%s: %s' % (value, s)
def string(self, cdataobj, maxlen):
- value = self._get_value(cdataobj._cdata)
- keepalive_until_here(cdataobj)
+ with cdataobj as ptr:
+ value = self._get_value(ptr)
try:
s = self.enumvalues2erators[value]
except KeyError:
diff --git a/pypy/module/_cffi_backend/ctypeobj.py b/pypy/module/_cffi_backend/ctypeobj.py
--- a/pypy/module/_cffi_backend/ctypeobj.py
+++ b/pypy/module/_cffi_backend/ctypeobj.py
@@ -177,8 +177,8 @@
raise oefmt(space.w_AttributeError,
"cdata '%s' has no attribute '%s'", self.name, attr)
- def copy_and_convert_to_object(self, cdata):
- return self.convert_to_object(cdata)
+ def copy_and_convert_to_object(self, source):
+ return self.convert_to_object(source)
# __________ app-level attributes __________
def dir(self):
diff --git a/pypy/module/_cffi_backend/ctypeprim.py b/pypy/module/_cffi_backend/ctypeprim.py
--- a/pypy/module/_cffi_backend/ctypeprim.py
+++ b/pypy/module/_cffi_backend/ctypeprim.py
@@ -5,7 +5,6 @@
import sys
from rpython.rlib.rarithmetic import r_uint, r_ulonglong, intmask
-from rpython.rlib.objectmodel import keepalive_until_here
from rpython.rlib import jit
from rpython.rtyper.lltypesystem import lltype, rffi
@@ -53,7 +52,8 @@
space = self.space
if (isinstance(w_ob, cdataobj.W_CData) and
isinstance(w_ob.ctype, ctypeptr.W_CTypePtrOrArray)):
- value = rffi.cast(lltype.Signed, w_ob._cdata)
+ ptr = w_ob.unsafe_escaping_ptr()
+ value = rffi.cast(lltype.Signed, ptr)
value = self._cast_result(value)
elif space.isinstance_w(w_ob, space.w_str):
value = self.cast_str(w_ob)
@@ -81,8 +81,8 @@
def string(self, cdataobj, maxlen):
if self.size == 1:
- s = cdataobj._cdata[0]
- keepalive_until_here(cdataobj)
+ with cdataobj as ptr:
+ s = ptr[0]
return self.space.wrap(s)
return W_CType.string(self, cdataobj, maxlen)
@@ -116,7 +116,8 @@
return s[0]
if (isinstance(w_ob, cdataobj.W_CData) and
isinstance(w_ob.ctype, W_CTypePrimitiveChar)):
- return w_ob._cdata[0]
+ with w_ob as ptr:
+ return ptr[0]
raise self._convert_error("string of length 1", w_ob)
def convert_from_object(self, cdata, w_ob):
@@ -137,8 +138,8 @@
return self.space.wrap(s)
def string(self, cdataobj, maxlen):
- w_res = self.convert_to_object(cdataobj._cdata)
- keepalive_until_here(cdataobj)
+ with cdataobj as ptr:
+ w_res = self.convert_to_object(ptr)
return w_res
def _convert_to_unichar(self, w_ob):
@@ -149,7 +150,8 @@
return s[0]
if (isinstance(w_ob, cdataobj.W_CData) and
isinstance(w_ob.ctype, W_CTypePrimitiveUniChar)):
- return rffi.cast(rffi.CWCHARP, w_ob._cdata)[0]
+ with w_ob as ptr:
+ return rffi.cast(rffi.CWCHARP, ptr)[0]
raise self._convert_error("unicode string of length 1", w_ob)
def convert_from_object(self, cdata, w_ob):
@@ -219,13 +221,15 @@
if self.size == rffi.sizeof(rffi.LONG):
from rpython.rlib.rrawarray import populate_list_from_raw_array
res = []
- buf = rffi.cast(rffi.LONGP, w_cdata._cdata)
length = w_cdata.get_array_length()
- populate_list_from_raw_array(res, buf, length)
+ with w_cdata as ptr:
+ buf = rffi.cast(rffi.LONGP, ptr)
+ populate_list_from_raw_array(res, buf, length)
return res
elif self.value_smaller_than_long:
res = [0] * w_cdata.get_array_length()
- misc.unpack_list_from_raw_array(res, w_cdata._cdata, self.size)
+ with w_cdata as ptr:
+ misc.unpack_list_from_raw_array(res, ptr, self.size)
return res
return None
@@ -308,8 +312,8 @@
def unpack_list_of_int_items(self, w_cdata):
if self.value_fits_long:
res = [0] * w_cdata.get_array_length()
- misc.unpack_unsigned_list_from_raw_array(res, w_cdata._cdata,
- self.size)
+ with w_cdata as ptr:
+ misc.unpack_unsigned_list_from_raw_array(res, ptr, self.size)
return res
return None
@@ -363,8 +367,8 @@
if not isinstance(self, W_CTypePrimitiveLongDouble):
w_cdata.write_raw_float_data(value)
else:
- self._to_longdouble_and_write(value, w_cdata._cdata)
- keepalive_until_here(w_cdata)
+ with w_cdata as ptr:
+ self._to_longdouble_and_write(value, ptr)
return w_cdata
def cast_to_int(self, cdata):
@@ -387,13 +391,15 @@
if self.size == rffi.sizeof(rffi.DOUBLE):
from rpython.rlib.rrawarray import populate_list_from_raw_array
res = []
- buf = rffi.cast(rffi.DOUBLEP, w_cdata._cdata)
length = w_cdata.get_array_length()
- populate_list_from_raw_array(res, buf, length)
+ with w_cdata as ptr:
+ buf = rffi.cast(rffi.DOUBLEP, ptr)
+ populate_list_from_raw_array(res, buf, length)
return res
elif self.size == rffi.sizeof(rffi.FLOAT):
res = [0.0] * w_cdata.get_array_length()
- misc.unpack_cfloat_list_from_raw_array(res, w_cdata._cdata)
+ with w_cdata as ptr:
+ misc.unpack_cfloat_list_from_raw_array(res, ptr)
return res
return None
@@ -423,8 +429,8 @@
def cast(self, w_ob):
if (isinstance(w_ob, cdataobj.W_CData) and
isinstance(w_ob.ctype, W_CTypePrimitiveLongDouble)):
- w_cdata = self.convert_to_object(w_ob._cdata)
- keepalive_until_here(w_ob)
+ with w_ob as ptr:
+ w_cdata = self.convert_to_object(ptr)
return w_cdata
else:
return W_CTypePrimitiveFloat.cast(self, w_ob)
@@ -451,16 +457,16 @@
def convert_to_object(self, cdata):
w_cdata = cdataobj.W_CDataMem(self.space, self.size, self)
- self._copy_longdouble(cdata, w_cdata._cdata)
- keepalive_until_here(w_cdata)
+ with w_cdata as ptr:
+ self._copy_longdouble(cdata, ptr)
return w_cdata
def convert_from_object(self, cdata, w_ob):
space = self.space
if (isinstance(w_ob, cdataobj.W_CData) and
isinstance(w_ob.ctype, W_CTypePrimitiveLongDouble)):
- self._copy_longdouble(w_ob._cdata, cdata)
- keepalive_until_here(w_ob)
+ with w_ob as ptr:
+ self._copy_longdouble(ptr, cdata)
else:
value = space.float_w(space.float(w_ob))
self._to_longdouble_and_write(value, cdata)
diff --git a/pypy/module/_cffi_backend/ctypeptr.py b/pypy/module/_cffi_backend/ctypeptr.py
--- a/pypy/module/_cffi_backend/ctypeptr.py
+++ b/pypy/module/_cffi_backend/ctypeptr.py
@@ -3,7 +3,6 @@
"""
from rpython.rlib import rposix
-from rpython.rlib.objectmodel import keepalive_until_here
from rpython.rlib.rarithmetic import ovfcheck
from rpython.rtyper.annlowlevel import llstr, llunicode
from rpython.rtyper.lltypesystem import lltype, rffi
@@ -49,7 +48,7 @@
space = self.space
if (isinstance(w_ob, cdataobj.W_CData) and
isinstance(w_ob.ctype, W_CTypePtrOrArray)):
- value = w_ob._cdata
+ value = w_ob.unsafe_escaping_ptr()
else:
value = misc.as_unsigned_long(space, w_ob, strict=False)
value = rffi.cast(rffi.CCHARP, value)
@@ -108,34 +107,33 @@
def string(self, cdataobj, maxlen):
space = self.space
if isinstance(self.ctitem, ctypeprim.W_CTypePrimitive):
- cdata = cdataobj._cdata
- if not cdata:
- raise oefmt(space.w_RuntimeError, "cannot use string() on %s",
- space.str_w(cdataobj.repr()))
- #
- from pypy.module._cffi_backend import ctypearray
- length = maxlen
- if length < 0 and isinstance(self, ctypearray.W_CTypeArray):
- length = cdataobj.get_array_length()
- #
- # pointer to a primitive type of size 1: builds and returns a str
- if self.ctitem.size == rffi.sizeof(lltype.Char):
- if length < 0:
- s = rffi.charp2str(cdata)
- else:
- s = rffi.charp2strn(cdata, length)
- keepalive_until_here(cdataobj)
- return space.wrap(s)
- #
- # pointer to a wchar_t: builds and returns a unicode
- if self.is_unichar_ptr_or_array():
- cdata = rffi.cast(rffi.CWCHARP, cdata)
- if length < 0:
- u = rffi.wcharp2unicode(cdata)
- else:
- u = rffi.wcharp2unicoden(cdata, length)
- keepalive_until_here(cdataobj)
- return space.wrap(u)
+ with cdataobj as ptr:
+ if not ptr:
+ raise oefmt(space.w_RuntimeError,
+ "cannot use string() on %s",
+ space.str_w(cdataobj.repr()))
+ #
+ from pypy.module._cffi_backend import ctypearray
+ length = maxlen
+ if length < 0 and isinstance(self, ctypearray.W_CTypeArray):
+ length = cdataobj.get_array_length()
+ #
+ # pointer to a primitive type of size 1: builds and returns a str
+ if self.ctitem.size == rffi.sizeof(lltype.Char):
+ if length < 0:
+ s = rffi.charp2str(ptr)
+ else:
+ s = rffi.charp2strn(ptr, length)
+ return space.wrap(s)
+ #
+ # pointer to a wchar_t: builds and returns a unicode
+ if self.is_unichar_ptr_or_array():
+ cdata = rffi.cast(rffi.CWCHARP, ptr)
+ if length < 0:
+ u = rffi.wcharp2unicode(cdata)
+ else:
+ u = rffi.wcharp2unicoden(cdata, length)
+ return space.wrap(u)
#
return W_CType.string(self, cdataobj, maxlen)
@@ -162,7 +160,7 @@
if not (self.can_cast_anything or other.can_cast_anything):
raise self._convert_error("compatible pointer", w_ob)
- rffi.cast(rffi.CCHARPP, cdata)[0] = w_ob._cdata
+ rffi.cast(rffi.CCHARPP, cdata)[0] = w_ob.unsafe_escaping_ptr()
def _alignof(self):
from pypy.module._cffi_backend import newtype
@@ -206,8 +204,8 @@
lltype.nullptr(rffi.CCHARP.TO), w_init, datasize)
#
cdatastruct = cdataobj.W_CDataNewOwning(space, datasize, ctitem)
- cdata = cdataobj.W_CDataPtrToStructOrUnion(space,
- cdatastruct._cdata,
+ ptr = cdatastruct.unsafe_escaping_ptr()
+ cdata = cdataobj.W_CDataPtrToStructOrUnion(space, ptr,
self, cdatastruct)
else:
if self.is_char_or_unichar_ptr_or_array():
@@ -215,8 +213,8 @@
cdata = cdataobj.W_CDataNewOwning(space, datasize, self)
#
if not space.is_w(w_init, space.w_None):
- ctitem.convert_from_object(cdata._cdata, w_init)
- keepalive_until_here(cdata)
+ with cdata as ptr:
+ ctitem.convert_from_object(ptr, w_init)
return cdata
def _check_subscript_index(self, w_cdata, i):
@@ -332,8 +330,9 @@
ctype2 = cdata.ctype
if (isinstance(ctype2, W_CTypeStructOrUnion) or
isinstance(ctype2, W_CTypePtrOrArray)):
- ptrdata = rffi.ptradd(cdata._cdata, offset)
- return cdataobj.W_CData(space, ptrdata, self)
+ ptr = cdata.unsafe_escaping_ptr()
+ ptr = rffi.ptradd(ptr, offset)
+ return cdataobj.W_CData(space, ptr, self)
else:
raise OperationError(space.w_TypeError,
space.wrap("expected a cdata struct/union/array/pointer"
diff --git a/pypy/module/_cffi_backend/ctypestruct.py b/pypy/module/_cffi_backend/ctypestruct.py
--- a/pypy/module/_cffi_backend/ctypestruct.py
+++ b/pypy/module/_cffi_backend/ctypestruct.py
@@ -7,7 +7,6 @@
from pypy.interpreter.typedef import TypeDef, interp_attrproperty
from rpython.rlib import jit
-from rpython.rlib.objectmodel import keepalive_until_here
from rpython.rlib.rarithmetic import r_uint, r_ulonglong, r_longlong, intmask
from rpython.rlib.rarithmetic import ovfcheck
from rpython.rtyper.lltypesystem import lltype, rffi
@@ -57,12 +56,12 @@
self.check_complete()
return cdataobj.W_CData(space, cdata, self)
- def copy_and_convert_to_object(self, cdata):
+ def copy_and_convert_to_object(self, source):
space = self.space
self.check_complete()
ob = cdataobj.W_CDataNewOwning(space, self.size, self)
- misc._raw_memcopy(cdata, ob._cdata, self.size)
- keepalive_until_here(ob)
+ with ob as target:
+ misc._raw_memcopy(source, target, self.size)
return ob
def typeoffsetof_field(self, fieldname, following):
@@ -80,8 +79,8 @@
def _copy_from_same(self, cdata, w_ob):
if isinstance(w_ob, cdataobj.W_CData):
if w_ob.ctype is self and self.size >= 0:
- misc._raw_memcopy(w_ob._cdata, cdata, self.size)
- keepalive_until_here(w_ob)
+ with w_ob as ptr:
+ misc._raw_memcopy(ptr, cdata, self.size)
return True
return False
diff --git a/pypy/module/_cffi_backend/ctypevoid.py b/pypy/module/_cffi_backend/ctypevoid.py
--- a/pypy/module/_cffi_backend/ctypevoid.py
+++ b/pypy/module/_cffi_backend/ctypevoid.py
@@ -13,5 +13,5 @@
def __init__(self, space):
W_CType.__init__(self, space, -1, "void", len("void"))
- def copy_and_convert_to_object(self, cdata):
+ def copy_and_convert_to_object(self, source):
return self.space.w_None
diff --git a/pypy/module/_cffi_backend/handle.py b/pypy/module/_cffi_backend/handle.py
--- a/pypy/module/_cffi_backend/handle.py
+++ b/pypy/module/_cffi_backend/handle.py
@@ -34,8 +34,9 @@
raise oefmt(space.w_TypeError,
"expected a 'cdata' object with a 'void *' out of "
"new_handle(), got '%s'", ctype.name)
- index = rffi.cast(lltype.Signed, w_cdata._cdata)
- original_cdataobj = get(space).fetch_handle(index - 1)
+ with w_cdata as ptr:
+ index = rffi.cast(lltype.Signed, ptr)
+ original_cdataobj = get(space).fetch_handle(index - 1)
#
if isinstance(original_cdataobj, cdataobj.W_CDataHandle):
return original_cdataobj.w_keepalive
diff --git a/pypy/module/_cffi_backend/misc.py b/pypy/module/_cffi_backend/misc.py
--- a/pypy/module/_cffi_backend/misc.py
+++ b/pypy/module/_cffi_backend/misc.py
@@ -3,7 +3,7 @@
from pypy.interpreter.error import OperationError
from rpython.rlib import jit
-from rpython.rlib.objectmodel import keepalive_until_here, specialize
+from rpython.rlib.objectmodel import specialize
from rpython.rlib.rarithmetic import r_uint, r_ulonglong
from rpython.rlib.unroll import unrolling_iterable
from rpython.rtyper.lltypesystem import lltype, llmemory, rffi
@@ -272,11 +272,11 @@
from pypy.module._cffi_backend.ctypeprim import W_CTypePrimitiveLongDouble
is_cdata = isinstance(w_ob, W_CData)
if is_cdata and isinstance(w_ob.ctype, W_CTypePrimitiveFloat):
- if isinstance(w_ob.ctype, W_CTypePrimitiveLongDouble):
- result = is_nonnull_longdouble(w_ob._cdata)
- else:
- result = is_nonnull_float(w_ob._cdata, w_ob.ctype.size)
- keepalive_until_here(w_ob)
+ with w_ob as ptr:
+ if isinstance(w_ob.ctype, W_CTypePrimitiveLongDouble):
+ result = is_nonnull_longdouble(ptr)
+ else:
+ result = is_nonnull_float(ptr, w_ob.ctype.size)
return result
#
if not is_cdata and space.lookup(w_ob, '__float__') is not None:
More information about the pypy-commit
mailing list