Author: Armin Rigo <[email protected]>
Branch: cpyext-gc-support
Changeset: r80393:8e2b3183d88b
Date: 2015-10-22 15:58 +0200
http://bitbucket.org/pypy/pypy/changeset/8e2b3183d88b/
Log: in-progress
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
@@ -215,11 +215,7 @@
return True
def get_llhelper(self, space):
- llh = getattr(self, '_llhelper', None)
- if llh is None:
- llh = llhelper(self.functype, self.get_wrapper(space))
- self._llhelper = llh
- return llh
+ return llhelper(self.functype, self.get_wrapper(space))
@specialize.memo()
def get_wrapper(self, space):
@@ -232,6 +228,7 @@
wrapper.c_name = cpyext_namespace.uniquename(self.c_name)
return wrapper
+
def cpython_api(argtypes, restype, error=_NOT_SPECIFIED, external=True,
gil=None, result_borrowed=False):
"""
@@ -402,11 +399,11 @@
# These are C symbols which cpyext will export, but which are defined in .c
# files somewhere in the implementation of cpyext (rather than being defined in
# RPython).
-SYMBOLS_C = [
+SYMBOLS_C = set([
'Py_FatalError', 'PyOS_snprintf', 'PyOS_vsnprintf', 'PyArg_Parse',
'PyArg_ParseTuple', 'PyArg_UnpackTuple', 'PyArg_ParseTupleAndKeywords',
'PyArg_VaParse', 'PyArg_VaParseTupleAndKeywords', '_PyArg_NoKeywords',
- 'PyString_FromFormat', 'PyString_FromFormatV',
+ 'PyString_FromFormat', 'PyString_FromFormatV', '_PyString_Resize',
'PyModule_AddObject', 'PyModule_AddIntConstant',
'PyModule_AddStringConstant',
'Py_BuildValue', 'Py_VaBuildValue', 'PyTuple_Pack',
'_PyArg_Parse_SizeT', '_PyArg_ParseTuple_SizeT',
@@ -454,7 +451,7 @@
'Py_FrozenFlag', 'Py_TabcheckFlag', 'Py_UnicodeFlag',
'Py_IgnoreEnvironmentFlag',
'Py_DivisionWarningFlag', 'Py_DontWriteBytecodeFlag',
'Py_NoUserSiteDirectory',
'_Py_QnewFlag', 'Py_Py3kWarningFlag', 'Py_HashRandomizationFlag',
'_Py_PackageContext',
-]
+])
TYPES = {}
GLOBALS = { # this needs to include all prebuilt pto, otherwise segfaults occur
'_Py_NoneStruct#': ('PyObject*', 'space.w_None'),
@@ -803,7 +800,7 @@
from pypy.module.cpyext.pyobject import setup_prebuilt_pyobj, _Py_Dealloc
from rpython.rlib import rawrefcount
- export_symbols = list(FUNCTIONS) + SYMBOLS_C + list(GLOBALS)
+ export_symbols = sorted(FUNCTIONS) + sorted(SYMBOLS_C) + sorted(GLOBALS)
from rpython.translator.c.database import LowLevelDatabase
db = LowLevelDatabase()
@@ -1100,7 +1097,7 @@
"NOT_RPYTHON"
from pypy.module.cpyext.pyobject import make_ref
- export_symbols = list(FUNCTIONS) + SYMBOLS_C + list(GLOBALS)
+ export_symbols = sorted(FUNCTIONS) + sorted(SYMBOLS_C) + sorted(GLOBALS)
from rpython.translator.c.database import LowLevelDatabase
db = LowLevelDatabase()
diff --git a/pypy/module/cpyext/include/intobject.h
b/pypy/module/cpyext/include/intobject.h
--- a/pypy/module/cpyext/include/intobject.h
+++ b/pypy/module/cpyext/include/intobject.h
@@ -13,6 +13,7 @@
long ob_ival;
} PyIntObject;
+
/* Macro, trading safety for speed */
#define PyInt_AS_LONG(op) (((PyIntObject *)(op))->ob_ival)
diff --git a/pypy/module/cpyext/include/stringobject.h
b/pypy/module/cpyext/include/stringobject.h
--- a/pypy/module/cpyext/include/stringobject.h
+++ b/pypy/module/cpyext/include/stringobject.h
@@ -7,15 +7,19 @@
extern "C" {
#endif
-#define PyString_GET_SIZE(op) PyString_Size(op)
-#define PyString_AS_STRING(op) PyString_AsString(op)
+/* Macro, trading safety for speed */
+#define PyString_GET_SIZE(op) Py_SIZE(op)
+#define PyString_AS_STRING(op) ( \
+ ((PyStringObject *)(op))->ob_sval_pypy[((PyStringObject *)(op))->ob_size] \
+ == 0 ? ((PyStringObject *)(op))->ob_sval_pypy : PyString_AsString(op))
+
typedef struct {
- PyObject_HEAD
- char* buffer;
- Py_ssize_t size;
+ PyObject_VAR_HEAD
+ char ob_sval_pypy[1];
} PyStringObject;
+PyAPI_FUNC(int) _PyString_Resize(PyObject **pv, Py_ssize_t newsize);
PyAPI_FUNC(PyObject *) PyString_FromFormatV(const char *format, va_list vargs);
PyAPI_FUNC(PyObject *) PyString_FromFormat(const char *format, ...);
diff --git a/pypy/module/cpyext/include/tupleobject.h
b/pypy/module/cpyext/include/tupleobject.h
--- a/pypy/module/cpyext/include/tupleobject.h
+++ b/pypy/module/cpyext/include/tupleobject.h
@@ -12,6 +12,7 @@
PyObject *ob_item[1];
} PyTupleObject;
+
/* defined in varargswrapper.c */
PyAPI_FUNC(PyObject *) PyTuple_Pack(Py_ssize_t, ...);
diff --git a/pypy/module/cpyext/intobject.py b/pypy/module/cpyext/intobject.py
--- a/pypy/module/cpyext/intobject.py
+++ b/pypy/module/cpyext/intobject.py
@@ -45,9 +45,9 @@
# --and then we call this function to initialize the W_IntObject--
fill_pypy=int_fill_pypy,
- # --in this case, and if PyInt_CheckExact() returns True, then
- # the link can be light, i.e. the original PyIntObject might
- # be freed with free() by the GC--
+ # --if PyInt_CheckExact() returns True, then such a link can
+ # be light, i.e. the original PyIntObject is freed with free()
+ # by the GC if there is no more reference to the PyIntObject--
alloc_pypy_light_if=PyInt_CheckExact,
)
diff --git a/pypy/module/cpyext/pyobject.py b/pypy/module/cpyext/pyobject.py
--- a/pypy/module/cpyext/pyobject.py
+++ b/pypy/module/cpyext/pyobject.py
@@ -116,6 +116,15 @@
assert 'cpyext_create_pypy' not in typedef.__dict__
typedef.cpyext_create_pypy = cpyext_create_pypy
+ if tp_basestruct._arrayfld is None:
+ typedef.cpyext_basicsize = rffi.sizeof(tp_basestruct)
+ typedef.cpyext_itemsize = 0
+ else:
+ typedef.cpyext_basicsize = rffi.offsetof(tp_basestruct,
+ tp_basestruct._arrayfld)
+ ARRAY = getattr(tp_basestruct, tp_basestruct._arrayfld)
+ typedef.cpyext_itemsize = rffi.sizeof(ARRAY.OF)
+
if tp_dealloc:
@cpython_api([PyObject], lltype.Void,
external=False, error=CANNOT_FAIL)
@@ -178,6 +187,8 @@
W_ObjectObject.typedef.cpyext_create_pypy)
TypeDef.cpyext_get_dealloc = staticmethod(
W_ObjectObject.typedef.cpyext_get_dealloc)
+ TypeDef.cpyext_basicsize = W_ObjectObject.typedef.cpyext_basicsize
+ TypeDef.cpyext_itemsize = W_ObjectObject.typedef.cpyext_itemsize
def _default_dealloc(space, py_obj):
lltype.free(py_obj, flavor='raw', track_allocation=False)
diff --git a/pypy/module/cpyext/src/stringobject.c
b/pypy/module/cpyext/src/stringobject.c
--- a/pypy/module/cpyext/src/stringobject.c
+++ b/pypy/module/cpyext/src/stringobject.c
@@ -248,3 +248,21 @@
va_end(vargs);
return ret;
}
+
+int
+_PyString_Resize(PyObject **pv, Py_ssize_t newsize)
+{
+ /* XXX always create a new string so far */
+ PyObject *v = *pv;
+ Py_ssize_t size = PyString_GET_SIZE(v);
+ PyObject *newv = PyString_FromStringAndSize(NULL, newsize);
+ if (newv == NULL) {
+ Py_DECREF(v);
+ return -1;
+ }
+ memcpy(PyString_AS_STRING(newv), PyString_AS_STRING(v),
+ size < newsize ? size : newsize);
+ Py_DECREF(v);
+ *pv = newv;
+ return 0;
+}
diff --git a/pypy/module/cpyext/stringobject.py
b/pypy/module/cpyext/stringobject.py
--- a/pypy/module/cpyext/stringobject.py
+++ b/pypy/module/cpyext/stringobject.py
@@ -1,12 +1,14 @@
from pypy.interpreter.error import OperationError
from rpython.rtyper.lltypesystem import rffi, lltype
from pypy.module.cpyext.api import (
- cpython_api, cpython_struct, bootstrap_function, build_type_checkers,
- PyObjectFields, Py_ssize_t, CONST_STRING, CANNOT_FAIL)
+ cpython_api, cpython_struct, bootstrap_function, build_type_checkers3,
+ PyVarObjectFields, Py_ssize_t, CONST_STRING, CANNOT_FAIL)
from pypy.module.cpyext.pyerrors import PyErr_BadArgument
from pypy.module.cpyext.pyobject import (
- PyObject, PyObjectP, Py_DecRef, make_ref, from_ref, track_reference,
- make_typedescr, get_typedescr)
+ PyObject, PyObjectP, Py_DecRef, get_pyobj_and_incref, from_pyobj,
+ setup_class_for_cpyext, RRC_PERMANENT_LIGHT, new_pyobj)
+from pypy.objspace.std.bytesobject import W_BytesObject, W_AbstractBytesObject
+from pypy.module.cpyext import support
##
## Implementation of PyStringObject
@@ -16,7 +18,8 @@
## -----------
##
## PyString_AsString() must return a (non-movable) pointer to the underlying
-## buffer, whereas pypy strings are movable. C code may temporarily store
+## buffer, whereas pypy strings are movable (and also, they are not
+## null-terminated at all). The C code may temporarily store
## this address and use it, as long as it owns a reference to the PyObject.
## There is no "release" function to specify that the pointer is not needed
## any more.
@@ -52,162 +55,135 @@
PyStringObjectStruct = lltype.ForwardReference()
PyStringObject = lltype.Ptr(PyStringObjectStruct)
-PyStringObjectFields = PyObjectFields + \
- (("buffer", rffi.CCHARP), ("size", Py_ssize_t))
+PyStringObjectFields = PyVarObjectFields + \
+ (("ob_sval_pypy", rffi.CArray(lltype.Char)),)
cpython_struct("PyStringObject", PyStringObjectFields, PyStringObjectStruct)
+PyString_Check, PyString_CheckExact, _PyString_Type = (
+ build_type_checkers3("String", "w_str"))
+
+
@bootstrap_function
def init_stringobject(space):
"Type description of PyStringObject"
- make_typedescr(space.w_str.instancetypedef,
- basestruct=PyStringObject.TO,
- attach=string_attach,
- dealloc=string_dealloc,
- realize=string_realize)
+ setup_class_for_cpyext(
+ W_AbstractBytesObject,
+ basestruct=PyStringObjectStruct,
-PyString_Check, PyString_CheckExact = build_type_checkers("String", "w_str")
+ # --from a W_BytesObject, we call this function to allocate
+ # a PyStringObject, initially without any data--
+ alloc_pyobj=string_alloc_pyobj,
-def new_empty_str(space, length):
+ # --reverse direction: from a PyStringObject, we make a W_BytesObject
+ # by instantiating a custom subclass of W_BytesObject--
+ realize_subclass_of=W_BytesObject,
+
+ # --and then we call this function to initialize the W_BytesObject--
+ fill_pypy=string_fill_pypy,
+
+ # --in this case, and if PyString_CheckExact() returns True, then
+ # the link can be light, i.e. the original PyStringObject might
+ # be freed with free() by the GC--
+ alloc_pypy_light_if=PyString_CheckExact,
+ )
+
+def _string_fill_pyobj(s, ob):
+ rffi.str2chararray(s, ob.c_ob_sval_pypy, len(s))
+ ob.c_ob_sval_pypy[len(s)] = '\x00'
+
+def string_alloc_pyobj(space, w_obj):
"""
- Allocatse a PyStringObject and its buffer, but without a corresponding
- interpreter object. The buffer may be mutated, until string_realize() is
- called.
+ Makes a PyTupleObject from a W_AbstractBytesObject.
"""
- typedescr = get_typedescr(space.w_str.instancetypedef)
- py_obj = typedescr.allocate(space, space.w_str)
- py_str = rffi.cast(PyStringObject, py_obj)
+ assert isinstance(w_obj, W_AbstractBytesObject)
+ size = w_obj.string_length()
+ ob = lltype.malloc(PyStringObjectStruct, size + 1, flavor='raw',
+ track_allocation=False)
+ ob.c_ob_size = size
+ if size > 8:
+ ob.c_ob_sval_pypy[size] = '*' # not filled yet
+ else:
+ _string_fill_pyobj(w_obj.str_w(space), ob)
+ return ob, RRC_PERMANENT_LIGHT
- buflen = length + 1
- py_str.c_size = length
- py_str.c_buffer = lltype.malloc(rffi.CCHARP.TO, buflen,
- flavor='raw', zero=True)
- return py_str
-
-def string_attach(space, py_obj, w_obj):
- """
- Fills a newly allocated PyStringObject with the given string object. The
- buffer must not be modified.
- """
- py_str = rffi.cast(PyStringObject, py_obj)
- py_str.c_size = len(space.str_w(w_obj))
- py_str.c_buffer = lltype.nullptr(rffi.CCHARP.TO)
-
-def string_realize(space, py_obj):
+def string_fill_pypy(space, w_obj, py_obj):
"""
Creates the string in the interpreter. The PyStringObject buffer must not
be modified after this call.
"""
py_str = rffi.cast(PyStringObject, py_obj)
- s = rffi.charpsize2str(py_str.c_buffer, py_str.c_size)
- w_obj = space.wrap(s)
- track_reference(space, py_obj, w_obj)
- return w_obj
-
-@cpython_api([PyObject], lltype.Void, external=False)
-def string_dealloc(space, py_obj):
- """Frees allocated PyStringObject resources.
- """
- py_str = rffi.cast(PyStringObject, py_obj)
- if py_str.c_buffer:
- lltype.free(py_str.c_buffer, flavor="raw")
- from pypy.module.cpyext.object import PyObject_dealloc
- PyObject_dealloc(space, py_obj)
+ s = rffi.charpsize2str(rffi.cast(rffi.CCHARP, py_str.c_ob_sval_pypy),
+ py_str.c_ob_size)
+ W_BytesObject.__init__(w_obj, s)
#_______________________________________________________________________
+def new_empty_str(space, length):
+ """
+ Allocates an uninitialized PyStringObject. The string may be mutated
+ as long as it has a refcount of 1; notably, until string_fill_pypy() is
+ called.
+ """
+ py_str = new_pyobj(PyStringObjectStruct, _PyString_Type(space), length + 1)
+ py_str.c_ob_size = length
+ py_str.c_ob_sval_pypy[length] = '\x00'
+ return py_str
+
@cpython_api([CONST_STRING, Py_ssize_t], PyObject)
def PyString_FromStringAndSize(space, char_p, length):
+ # XXX move to C
+ py_str = new_empty_str(space, length)
if char_p:
- s = rffi.charpsize2str(char_p, length)
- return make_ref(space, space.wrap(s))
- else:
- return rffi.cast(PyObject, new_empty_str(space, length))
+ support.memcpy_fn(py_str.c_ob_sval_pypy, char_p, length)
+ return rffi.cast(PyObject, py_str)
@cpython_api([CONST_STRING], PyObject)
def PyString_FromString(space, char_p):
+ # is it better to make an RPython object and lazily copy data to
+ # the C string, or make a purely C PyStringObject and then usually
+ # copy the string again to RPython? no clue... ideally, we should
+ # measure and adapt dynamically
s = rffi.charp2str(char_p)
return space.wrap(s)
@cpython_api([PyObject], rffi.CCHARP, error=0)
def PyString_AsString(space, ref):
- if from_ref(space, rffi.cast(PyObject, ref.c_ob_type)) is space.w_str:
- pass # typecheck returned "ok" without forcing 'ref' at all
- elif not PyString_Check(space, ref): # otherwise, use the alternate way
+ if not PyString_Check(space, ref):
raise OperationError(space.w_TypeError, space.wrap(
"PyString_AsString only support strings"))
ref_str = rffi.cast(PyStringObject, ref)
- if not ref_str.c_buffer:
+ last_char = ref_str.c_ob_sval_pypy[ref_str.ob_size]
+ if last_char != '\x00':
+ assert last_char == '*'
# copy string buffer
- w_str = from_ref(space, ref)
- s = space.str_w(w_str)
- ref_str.c_buffer = rffi.str2charp(s)
- return ref_str.c_buffer
+ w_str = from_pyobj(space, ref)
+ _string_fill_pyobj(w_str.str_w(space), ref_str)
+ return rffi.cast(rffi.CCHARP, ref_str.c_ob_sval_pypy)
@cpython_api([PyObject, rffi.CCHARPP, rffi.CArrayPtr(Py_ssize_t)],
rffi.INT_real, error=-1)
def PyString_AsStringAndSize(space, ref, buffer, length):
- if not PyString_Check(space, ref):
- raise OperationError(space.w_TypeError, space.wrap(
- "PyString_AsStringAndSize only support strings"))
+ buffer[0] = Pystring_AsString(space, ref)
ref_str = rffi.cast(PyStringObject, ref)
- if not ref_str.c_buffer:
- # copy string buffer
- w_str = from_ref(space, ref)
- s = space.str_w(w_str)
- ref_str.c_buffer = rffi.str2charp(s)
- buffer[0] = ref_str.c_buffer
if length:
- length[0] = ref_str.c_size
+ length[0] = ref_str.c_ob_size
else:
i = 0
- while ref_str.c_buffer[i] != '\0':
+ while ref_str.c_ob_sval_pypy[i] != '\0':
i += 1
- if i != ref_str.c_size:
+ if i != ref_str.c_ob_size:
raise OperationError(space.w_TypeError, space.wrap(
"expected string without null bytes"))
return 0
@cpython_api([PyObject], Py_ssize_t, error=-1)
def PyString_Size(space, ref):
- if from_ref(space, rffi.cast(PyObject, ref.c_ob_type)) is space.w_str:
+ if PyString_Check(space, ref):
ref = rffi.cast(PyStringObject, ref)
- return ref.c_size
+ return ref.c_ob_size
else:
- w_obj = from_ref(space, ref)
+ w_obj = from_pyobj(space, ref)
return space.len_w(w_obj)
-@cpython_api([PyObjectP, Py_ssize_t], rffi.INT_real, error=-1)
-def _PyString_Resize(space, ref, newsize):
- """A way to resize a string object even though it is "immutable". Only use
this to
- build up a brand new string object; don't use this if the string may
already be
- known in other parts of the code. It is an error to call this function if
the
- refcount on the input string object is not one. Pass the address of an
existing
- string object as an lvalue (it may be written into), and the new size
desired.
- On success, *string holds the resized string object and 0 is returned;
- the address in *string may differ from its input value. If the
reallocation
- fails, the original string object at *string is deallocated, *string is
- set to NULL, a memory exception is set, and -1 is returned.
- """
- # XXX always create a new string so far
- py_str = rffi.cast(PyStringObject, ref[0])
- if not py_str.c_buffer:
- raise OperationError(space.w_SystemError, space.wrap(
- "_PyString_Resize called on already created string"))
- try:
- py_newstr = new_empty_str(space, newsize)
- except MemoryError:
- Py_DecRef(space, ref[0])
- ref[0] = lltype.nullptr(PyObject.TO)
- raise
- to_cp = newsize
- oldsize = py_str.c_size
- if oldsize < newsize:
- to_cp = oldsize
- for i in range(to_cp):
- py_newstr.c_buffer[i] = py_str.c_buffer[i]
- Py_DecRef(space, ref[0])
- ref[0] = rffi.cast(PyObject, py_newstr)
- return 0
-
@cpython_api([PyObject, PyObject], rffi.INT, error=CANNOT_FAIL)
def _PyString_Eq(space, w_str1, w_str2):
return space.eq_w(w_str1, w_str2)
@@ -228,10 +204,10 @@
Py_DecRef(space, ref[0])
ref[0] = lltype.nullptr(PyObject.TO)
return
- w_str = from_ref(space, ref[0])
+ w_str = from_pyobj(space, ref[0])
w_newstr = space.add(w_str, w_newpart)
Py_DecRef(space, ref[0])
- ref[0] = make_ref(space, w_newstr)
+ ref[0] = get_pyobj_and_incref(space, w_newstr)
@cpython_api([PyObjectP, PyObject], lltype.Void)
def PyString_ConcatAndDel(space, ref, newpart):
diff --git a/pypy/module/cpyext/support.py b/pypy/module/cpyext/support.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/cpyext/support.py
@@ -0,0 +1,8 @@
+from rpython.rtyper.lltypesystem import lltype, rffi
+
+memcpy_fn = rffi.llexternal('memcpy', [rffi.CCHARP, rffi.CCHARP,
+ rffi.SIZE_T], lltype.Void,
+ sandboxsafe=True)
+memset_fn = rffi.llexternal('memset', [rffi.CCHARP, rffi.INT,
+ rffi.SIZE_T], lltype.Void,
+ sandboxsafe=True)
diff --git a/pypy/module/cpyext/test/test_stringobject.py
b/pypy/module/cpyext/test/test_stringobject.py
--- a/pypy/module/cpyext/test/test_stringobject.py
+++ b/pypy/module/cpyext/test/test_stringobject.py
@@ -30,6 +30,8 @@
}
if(s->ob_type->tp_basicsize != sizeof(void*)*4)
result = 0;
+ if(s->ob_type->tp_itemsize != sizeof(char))
+ result = 0;
Py_DECREF(s);
return PyBool_FromLong(result);
"""),
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
@@ -4,7 +4,6 @@
from rpython.rlib.objectmodel import specialize, instantiate
from rpython.rlib.objectmodel import keepalive_until_here
from rpython.rlib.rstring import rsplit
-from rpython.rtyper.annlowlevel import llhelper
from rpython.rtyper.lltypesystem import rffi, lltype
from pypy.interpreter.baseobjspace import W_Root, DescrMismatch
@@ -132,8 +131,7 @@
if get_slot:
slot_func_helper = get_slot()
elif slot_func:
- slot_func_helper = llhelper(slot_func.api_func.functype,
- slot_func.api_func.get_wrapper(space))
+ slot_func_helper = slot_func.api_func.get_llhelper(space)
if slot_func_helper is None:
if WARN_ABOUT_MISSING_SLOT_FUNCTIONS:
@@ -226,8 +224,7 @@
def setup_new_method_def(space):
ptr = get_new_method_def(space)
ptr.c_ml_meth = rffi.cast(PyCFunction_typedef,
- llhelper(tp_new_wrapper.api_func.functype,
- tp_new_wrapper.api_func.get_wrapper(space)))
+ tp_new_wrapper.api_func.get_llhelper(space))
def add_tp_new_wrapper(space, dict_w, pto):
if "__new__" in dict_w:
@@ -294,8 +291,7 @@
def subtype_dealloc(space, obj):
pto = obj.c_ob_type
base = pto
- this_func_ptr = llhelper(subtype_dealloc.api_func.functype,
- subtype_dealloc.api_func.get_wrapper(space))
+ this_func_ptr = subtype_dealloc.api_func.get_llhelper(space)
while base.c_tp_dealloc == this_func_ptr:
base = base.c_tp_base
assert base
@@ -354,22 +350,17 @@
def setup_string_buffer_procs(space, pto):
c_buf = lltype.malloc(PyBufferProcs, flavor='raw', zero=True)
lltype.render_immortal(c_buf)
- c_buf.c_bf_getsegcount = llhelper(str_segcount.api_func.functype,
- str_segcount.api_func.get_wrapper(space))
- c_buf.c_bf_getreadbuffer = llhelper(str_getreadbuffer.api_func.functype,
- str_getreadbuffer.api_func.get_wrapper(space))
- c_buf.c_bf_getcharbuffer = llhelper(str_getcharbuffer.api_func.functype,
- str_getcharbuffer.api_func.get_wrapper(space))
+ c_buf.c_bf_getsegcount = str_segcount.api_func.get_llhelper(space)
+ c_buf.c_bf_getreadbuffer = str_getreadbuffer.api_func.get_llhelper(space)
+ c_buf.c_bf_getcharbuffer = str_getcharbuffer.api_func.get_llhelper(space)
pto.c_tp_as_buffer = c_buf
pto.c_tp_flags |= Py_TPFLAGS_HAVE_GETCHARBUFFER
def setup_buffer_buffer_procs(space, pto):
c_buf = lltype.malloc(PyBufferProcs, flavor='raw', zero=True)
lltype.render_immortal(c_buf)
- c_buf.c_bf_getsegcount = llhelper(str_segcount.api_func.functype,
- str_segcount.api_func.get_wrapper(space))
- c_buf.c_bf_getreadbuffer = llhelper(buf_getreadbuffer.api_func.functype,
- buf_getreadbuffer.api_func.get_wrapper(space))
+ c_buf.c_bf_getsegcount = str_segcount.api_func.get_llhelper(space)
+ c_buf.c_bf_getreadbuffer = buf_getreadbuffer.api_func.get_llhelper(space)
pto.c_tp_as_buffer = c_buf
@cpython_api([PyObject], lltype.Void, external=False)
@@ -436,10 +427,8 @@
if space.is_w(w_type, space.w_buffer):
setup_buffer_buffer_procs(space, pto)
- pto.c_tp_free = llhelper(PyObject_Del.api_func.functype,
- PyObject_Del.api_func.get_wrapper(space))
- pto.c_tp_alloc = llhelper(PyType_GenericAlloc.api_func.functype,
- PyType_GenericAlloc.api_func.get_wrapper(space))
+ pto.c_tp_free = PyObject_Del.api_func.get_llhelper(space)
+ pto.c_tp_alloc = PyType_GenericAlloc.api_func.get_llhelper(space)
if pto.c_tp_flags & Py_TPFLAGS_HEAPTYPE:
w_typename = space.getattr(w_type, space.wrap('__name__'))
heaptype = rffi.cast(PyHeapTypeObject, pto)
@@ -450,8 +439,10 @@
# leak the name, but only for types in PyPy that correspond to
# non-heap types in CPython
pto.c_tp_name = rffi.str2charp(w_type.name, track_allocation=False)
- pto.c_tp_basicsize = -1 # hopefully this makes malloc bail out
- pto.c_tp_itemsize = 0
+
+ typedef = w_type.instancetypedef
+ pto.c_tp_basicsize = typedef.cpyext_basicsize
+ pto.c_tp_itemsize = typedef.cpyext_itemsize
if space.is_w(w_type, space.w_object):
pto.c_tp_new = rffi.cast(newfunc, 1) # XXX temp
# uninitialized fields:
@@ -466,8 +457,6 @@
finish_type_2(space, pto, w_type)
- #pto.c_tp_basicsize = rffi.sizeof(typedescr.basestruct) ZZZ
- pto.c_tp_basicsize = rffi.sizeof(PyObject.TO) # ZZZ
if pto.c_tp_base:
if pto.c_tp_base.c_tp_basicsize > pto.c_tp_basicsize:
pto.c_tp_basicsize = pto.c_tp_base.c_tp_basicsize
@@ -594,9 +583,7 @@
if not pto.c_tp_setattro:
from pypy.module.cpyext.object import PyObject_GenericSetAttr
- pto.c_tp_setattro = llhelper(
- PyObject_GenericSetAttr.api_func.functype,
- PyObject_GenericSetAttr.api_func.get_wrapper(space))
+ pto.c_tp_setattro =
PyObject_GenericSetAttr.api_func.get_llhelper(space)
w_dict = w_type.getdict(space)
old = pto.c_tp_dict
diff --git a/pypy/objspace/std/bytesobject.py b/pypy/objspace/std/bytesobject.py
--- a/pypy/objspace/std/bytesobject.py
+++ b/pypy/objspace/std/bytesobject.py
@@ -478,6 +478,9 @@
def _len(self):
return len(self._value)
+ def string_length(self): # for cpyext
+ return self._len()
+
_val = str_w
@staticmethod
diff --git a/pypy/objspace/std/strbufobject.py
b/pypy/objspace/std/strbufobject.py
--- a/pypy/objspace/std/strbufobject.py
+++ b/pypy/objspace/std/strbufobject.py
@@ -43,6 +43,9 @@
def readbuf_w(self, space):
return StringBuffer(self.force())
+ def string_length(self): # for cpyext
+ return self.length
+
def descr_len(self, space):
return space.wrap(self.length)
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit