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

Reply via email to