Author: Armin Rigo <ar...@tunes.org> 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 pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit