[pypy-commit] pypy cpyext-gc-cycle: Implemented cpython-like GC list for cpyext

stevie_92 pypy.commits at gmail.com
Fri Jan 11 05:39:06 EST 2019


Author: Stefan Beyer <home at sbeyer.at>
Branch: cpyext-gc-cycle
Changeset: r95604:e5ba3fd47f96
Date: 2018-07-04 17:56 +0200
http://bitbucket.org/pypy/pypy/changeset/e5ba3fd47f96/

Log:	Implemented cpython-like GC list for cpyext Added some code for
	cpyext-only boehm GC support

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
@@ -751,6 +751,8 @@
 PyVarObjectFields = PyObjectFields + (("ob_size", Py_ssize_t), )
 PyVarObjectStruct = cts.gettype('PyVarObject')
 PyVarObject = cts.gettype('PyVarObject *')
+PyGC_Head = cts.gettype('PyGC_Head')
+PyGC_HeadPtr = cts.gettype('PyGC_Head *')
 
 Py_buffer = cts.gettype('Py_buffer')
 Py_bufferP = cts.gettype('Py_buffer *')
@@ -1173,6 +1175,9 @@
     state.C._PyPy_object_dealloc = rffi.llexternal(
         '_PyPy_object_dealloc', [PyObject], lltype.Void,
         compilation_info=eci, _nowrapper=True)
+    state.C._PyPy_InitPyObjList = rffi.llexternal(
+        '_PyPy_InitPyObjList', [], PyGC_HeadPtr,
+        compilation_info=eci, _nowrapper=True)
 
 
 def init_function(func):
@@ -1294,6 +1299,9 @@
                 ll2ctypes.lltype2ctypes(func.get_llhelper(space)),
                 ctypes.c_void_p)
 
+    # initialize the pyobj_list for the gc
+    space.fromcache(State).C._PyPy_InitPyObjList()
+
     # we need to call this *after* the init code above, because it might
     # indirectly call some functions which are attached to pypyAPI (e.g., we
     # if do tuple_attach of the prebuilt empty tuple, we need to call
@@ -1826,75 +1834,3 @@
         return result
 
     return generic_cpy_call
-
- at specialize.memo()
-def make_generic_cpy_call_gc(FT, expect_null):
-    from pypy.module.cpyext.pyobject import is_pyobj, make_ref, decref
-    from pypy.module.cpyext.pyobject import get_w_obj_and_decref
-    from pypy.module.cpyext.pyerrors import PyErr_Occurred
-    unrolling_arg_types = unrolling_iterable(enumerate(FT.ARGS))
-    RESULT_TYPE = FT.RESULT
-
-    # copied and modified from rffi.py
-    # We need tons of care to ensure that no GC operation and no
-    # exception checking occurs in call_external_function.
-    argnames = ', '.join(['a%d' % i for i in range(len(FT.ARGS))])
-    source = py.code.Source("""
-        def cpy_call_external(funcptr, %(argnames)s):
-            # NB. it is essential that no exception checking occurs here!
-            res = funcptr(%(argnames)s)
-            return res
-    """ % locals())
-    miniglobals = {'__name__':    __name__, # for module name propagation
-                   }
-    exec source.compile() in miniglobals
-    call_external_function = specialize.ll()(miniglobals['cpy_call_external'])
-    call_external_function._dont_inline_ = True
-    call_external_function._gctransformer_hint_close_stack_ = True
-    # don't inline, as a hack to guarantee that no GC pointer is alive
-    # anywhere in call_external_function
-
-    @specialize.ll()
-    def generic_cpy_call(func, *args):
-        boxed_args = ()
-        to_decref = ()
-        assert len(args) == len(FT.ARGS)
-        for i, ARG in unrolling_arg_types:
-            arg = args[i]
-            _pyobj = None
-            if is_PyObject(ARG):
-                assert is_pyobj(arg)
-
-            boxed_args += (arg,)
-            to_decref += (_pyobj,)
-
-        # see "Handling of the GIL" above
-        tid = rthread.get_ident()
-        tid_before = cpyext_glob_tid_ptr[0]
-        assert tid_before == 0 or tid_before == tid
-        cpyext_glob_tid_ptr[0] = tid
-
-        try:
-            # Call the function
-            result = call_external_function(func, *boxed_args)
-        finally:
-            assert cpyext_glob_tid_ptr[0] == tid
-            cpyext_glob_tid_ptr[0] = tid_before
-            for i, ARG in unrolling_arg_types:
-                # note that this loop is nicely unrolled statically by RPython
-                _pyobj = to_decref[i]
-                if _pyobj is not None:
-                    pyobj = rffi.cast(PyObject, _pyobj)
-                    rawrefcount.decref(pyobj)
-
-        if is_PyObject(RESULT_TYPE):
-            ret = None
-
-            # Check for exception consistency
-            # XXX best attempt, will miss preexisting error that is
-            # overwritten with a new error of the same type
-
-            return ret
-        return result
-
-    return generic_cpy_call
\ No newline at end of file
diff --git a/pypy/module/cpyext/include/object.h b/pypy/module/cpyext/include/object.h
--- a/pypy/module/cpyext/include/object.h
+++ b/pypy/module/cpyext/include/object.h
@@ -279,7 +279,7 @@
 	  ) & ~(SIZEOF_VOID_P - 1)		\
 	)
 
-        
+
 #define PyObject_INIT(op, typeobj) \
     ( Py_TYPE(op) = (typeobj), ((PyObject *)(op))->ob_refcnt = 1,\
       ((PyObject *)(op))->ob_pypy_link = 0, (op) )
@@ -309,22 +309,65 @@
 
 #define PyObject_GC_NewVar(type, typeobj, n) \
                 ( (type *) _PyObject_GC_NewVar((typeobj), (n)) )
- 
-/* A dummy PyGC_Head, just to please some tests. Don't use it! */
-typedef union _gc_head {
-    char dummy;
-} PyGC_Head;
 
-/* dummy GC macros */
-#define _PyGC_FINALIZED(o) 1
-#define PyType_IS_GC(tp) 1
+extern PyGC_Head *_pypy_rawrefcount_pyobj_list;
 
-/* TODO: implement like in cpython
-   (see https://github.com/python/cpython/blob/517da1e58f4c489d4b31579852cde5f7113da08e/Include/objimpl.h#L295) */
-#define PyObject_GC_Track(o)      do { } while(0)
-#define PyObject_GC_UnTrack(o)    do { } while(0)
-#define _PyObject_GC_TRACK(o)     do { } while(0)
-#define _PyObject_GC_UNTRACK(o)   do { } while(0)
+#define _Py_AS_GC(o) ((PyGC_Head *)(o)-1)
+#define _Py_FROM_GC(g) ((PyObject *)(((PyGC_Head *)g)+1))
+
+/* Bit 0 is set when tp_finalize is called */
+#define _PyGC_REFS_MASK_FINALIZED  (1 << 0)
+/* The (N-1) most significant bits contain the gc state / refcount */
+#define _PyGC_REFS_SHIFT           (1)
+#define _PyGC_REFS_MASK            (((size_t) -1) << _PyGC_REFS_SHIFT)
+
+#define _PyGCHead_REFS(g) ((g)->gc_refs >> _PyGC_REFS_SHIFT)
+#define _PyGCHead_SET_REFS(g, v) do { \
+    (g)->gc_refs = ((g)->gc_refs & ~_PyGC_REFS_MASK) \
+        | (((size_t)(v)) << _PyGC_REFS_SHIFT);             \
+    } while (0)
+#define _PyGCHead_DECREF(g) ((g)->gc_refs -= 1 << _PyGC_REFS_SHIFT)
+
+#define _PyGCHead_FINALIZED(g) (((g)->gc_refs & _PyGC_REFS_MASK_FINALIZED) != 0)
+#define _PyGCHead_SET_FINALIZED(g, v) do {  \
+    (g)->gc_refs = ((g)->gc_refs & ~_PyGC_REFS_MASK_FINALIZED) \
+        | (v != 0); \
+    } while (0)
+
+#define _PyGC_FINALIZED(o) _PyGCHead_FINALIZED(_Py_AS_GC(o))
+#define _PyGC_SET_FINALIZED(o, v) _PyGCHead_SET_FINALIZED(_Py_AS_GC(o), v)
+
+#define _PyGC_REFS(o) _PyGCHead_REFS(_Py_AS_GC(o))
+
+#define _PyGC_REFS_UNTRACKED                    (-2)
+#define _PyGC_REFS_REACHABLE                    (-3)
+#define _PyGC_REFS_TENTATIVELY_UNREACHABLE (-4)
+
+#define _PyGC_IS_TRACKED(o) (_PyGC_REFS(o) != _PyGC_REFS_UNTRACKED)
+
+#define PyType_IS_GC(t) PyType_HasFeature((t), Py_TPFLAGS_HAVE_GC)
+
+PyAPI_FUNC(void) PyObject_GC_Track(void *);
+PyAPI_FUNC(void) PyObject_GC_UnTrack(void *);
+
+#define _PyObject_GC_TRACK(o)     do { \
+    PyGC_Head *g = _Py_AS_GC(o); \
+    if (_PyGCHead_REFS(g) != _PyGC_REFS_UNTRACKED) \
+        Py_FatalError("GC object already tracked"); \
+    _PyGCHead_SET_REFS(g, _PyGC_REFS_REACHABLE); \
+    g->gc_next = _pypy_rawrefcount_pyobj_list; \
+    g->gc_prev = _pypy_rawrefcount_pyobj_list->gc_prev; \
+    ((PyGC_Head *)g->gc_prev)->gc_next = g; \
+    _pypy_rawrefcount_pyobj_list->gc_prev = g; \
+ } while(0)
+#define _PyObject_GC_UNTRACK(o)   do { \
+    PyGC_Head *g = _Py_AS_GC(o); \
+    assert(_PyGCHead_REFS(g) != _PyGC_REFS_UNTRACKED); \
+    _PyGCHead_SET_REFS(g, _PyGC_REFS_UNTRACKED); \
+    ((PyGC_Head *)g->gc_prev)->gc_next = g->gc_next; \
+    ((PyGC_Head *)g->gc_next)->gc_prev = g->gc_prev; \
+    g->gc_next = NULL; \
+ } while(0)
 
 /* Utility macro to help write tp_traverse functions.
  * To use this macro, the tp_traverse function must name its arguments
@@ -405,7 +448,7 @@
 #define _PyObject_GC_Del PyObject_GC_Del
 PyAPI_FUNC(void) _PyPy_subtype_dealloc(PyObject *);
 PyAPI_FUNC(void) _PyPy_object_dealloc(PyObject *);
-
+PyAPI_FUNC(PyGC_Head *) _PyPy_InitPyObjList();
 
 #ifdef __cplusplus
 }
diff --git a/pypy/module/cpyext/parse/cpyext_object.h b/pypy/module/cpyext/parse/cpyext_object.h
--- a/pypy/module/cpyext/parse/cpyext_object.h
+++ b/pypy/module/cpyext/parse/cpyext_object.h
@@ -321,3 +321,10 @@
     PyBufferProcs as_buffer;
     PyObject *ht_name, *ht_slots;
 } PyHeapTypeObject;
+
+
+typedef struct _gc_head {
+    void *gc_next;
+    void *gc_prev;
+    Py_ssize_t gc_refs;
+} PyGC_Head;
\ No newline at end of file
diff --git a/pypy/module/cpyext/src/object.c b/pypy/module/cpyext/src/object.c
--- a/pypy/module/cpyext/src/object.c
+++ b/pypy/module/cpyext/src/object.c
@@ -2,6 +2,12 @@
 
 #include "Python.h"
 
+/* Get an object's GC head */
+#define AS_GC(o) ((PyGC_Head *)(o)-1)
+
+/* Get the object given the GC head */
+#define FROM_GC(g) ((PyObject *)(((PyGC_Head *)g)+1))
+
 extern void _PyPy_Free(void *ptr);
 extern void *_PyPy_Malloc(Py_ssize_t size);
 
@@ -30,6 +36,17 @@
  */
 Py_ssize_t _pypy_rawrefcount_w_marker_deallocating = 0xDEADFFF;
 
+static PyGC_Head _internal_pyobj_list;
+PyGC_Head *_pypy_rawrefcount_pyobj_list = &_internal_pyobj_list;
+
+PyGC_Head *
+_PyPy_InitPyObjList()
+{
+    _pypy_rawrefcount_pyobj_list->gc_next = _pypy_rawrefcount_pyobj_list;
+    _pypy_rawrefcount_pyobj_list->gc_prev = _pypy_rawrefcount_pyobj_list;
+    return _pypy_rawrefcount_pyobj_list;
+}
+
 void
 _Py_Dealloc(PyObject *obj)
 {
@@ -57,9 +74,25 @@
 }
 
 void
+PyObject_GC_Track(void *obj)
+{
+    _PyObject_GC_TRACK(obj);
+}
+
+void
+PyObject_GC_UnTrack(void *obj)
+{
+    if (_PyGC_IS_TRACKED(obj))
+        _PyObject_GC_UNTRACK(obj);
+}
+
+void
 PyObject_GC_Del(void *obj)
 {
-    _PyPy_Free(obj);
+    PyGC_Head *g = AS_GC(obj);
+    if (_PyGC_IS_TRACKED(obj))
+        _PyObject_GC_UNTRACK(obj);
+    _PyPy_Free(g);
 }
 
 PyObject *
@@ -74,14 +107,51 @@
     return (PyObject*)_PyObject_NewVar(type, 0);
 }
 
+static PyObject *
+_generic_gc_alloc(PyTypeObject *type, Py_ssize_t nitems)
+{
+    Py_ssize_t size;
+    PyObject *pyobj;
+    PyGC_Head *g;
+    if (type->tp_flags & Py_TPFLAGS_HEAPTYPE)
+        Py_INCREF(type);
+
+    size = sizeof(PyGC_Head) + type->tp_basicsize;
+    if (type->tp_itemsize)
+        size += nitems * type->tp_itemsize;
+
+    g = (PyObject*)_PyPy_Malloc(size);
+    if (g == NULL)
+        return NULL;
+    g->gc_refs = 0;
+    _PyGCHead_SET_REFS(g, _PyGC_REFS_UNTRACKED);
+
+    pyobj = FROM_GC(g);
+    if (type->tp_itemsize)
+        ((PyVarObject*)pyobj)->ob_size = nitems;
+
+    pyobj->ob_refcnt = 1;
+    /* pyobj->ob_pypy_link should get assigned very quickly */
+    pyobj->ob_type = type;
+    return pyobj;
+}
+
+
 PyObject * _PyObject_GC_New(PyTypeObject *type)
 {
-    return _PyObject_New(type);
+    return (PyObject*)_PyObject_GC_NewVar(type, 0);
 }
 
 PyVarObject * _PyObject_GC_NewVar(PyTypeObject *type, Py_ssize_t nitems)
 {
-    return _PyObject_NewVar(type, nitems);
+    PyObject *py_obj = _generic_gc_alloc(type, nitems);
+    if (!py_obj)
+        return (PyVarObject*)PyErr_NoMemory();
+
+    if (type->tp_itemsize == 0)
+        return (PyVarObject*)PyObject_INIT(py_obj, type);
+    else
+        return PyObject_INIT_VAR((PyVarObject*)py_obj, type, nitems);
 }
 
 static PyObject *
@@ -141,4 +211,4 @@
 {
     obj->ob_size = size;
     return (PyVarObject*)PyObject_Init((PyObject*)obj, type);
-}
+}
\ No newline at end of file
diff --git a/pypy/module/cpyext/state.py b/pypy/module/cpyext/state.py
--- a/pypy/module/cpyext/state.py
+++ b/pypy/module/cpyext/state.py
@@ -59,6 +59,7 @@
     def setup_rawrefcount(self):
         space = self.space
         if not self.space.config.translating:
+            from pypy.module.cpyext.api import PyGC_HeadPtr
             def dealloc_trigger():
                 from pypy.module.cpyext.pyobject import PyObject, decref
                 print 'dealloc_trigger...'
@@ -73,7 +74,9 @@
             def tp_traverse(obj_addr, callback, args):
                 # TODO: implement
                 pass
-            rawrefcount.init(dealloc_trigger, tp_traverse)
+            pyobj_list = lltype.malloc(PyGC_HeadPtr.TO,
+                                       flavor='raw', immortal=True, zero=True)
+            rawrefcount.init(dealloc_trigger, tp_traverse, pyobj_list)
         else:
             if space.config.translation.gc == "boehm":
                 action = BoehmPyObjDeallocAction(space)
@@ -128,11 +131,13 @@
             if space.config.translation.gc != "boehm":
                 # This must be called in RPython, the untranslated version
                 # does something different. Sigh.
+                pypyobj_list = self.C._PyPy_InitPyObjList()
                 rawrefcount.init(
                     llhelper(rawrefcount.RAWREFCOUNT_DEALLOC_TRIGGER,
                     self.dealloc_trigger),
                     llhelper(rawrefcount.RAWREFCOUNT_TRAVERSE,
-                    self.tp_traverse))
+                    self.tp_traverse),
+                    pypyobj_list)
             self.builder.attach_all(space)
 
         setup_new_method_def(space)
diff --git a/rpython/memory/gc/incminimark.py b/rpython/memory/gc/incminimark.py
--- a/rpython/memory/gc/incminimark.py
+++ b/rpython/memory/gc/incminimark.py
@@ -2994,6 +2994,12 @@
                               ('c_ob_refcnt', lltype.Signed),
                               ('c_ob_pypy_link', lltype.Signed))
     PYOBJ_HDR_PTR = lltype.Ptr(PYOBJ_HDR)
+    PYOBJ_GC_HDR = lltype.Struct('PyGC_Head',
+                                 ('c_gc_next', rffi.VOIDP),
+                                 ('c_gc_prev', rffi.VOIDP),
+                                 ('c_gc_refs', lltype.Signed))
+    PYOBJ_GC_HDR_PTR = lltype.Ptr(PYOBJ_GC_HDR)
+
     RAWREFCOUNT_DEALLOC_TRIGGER = lltype.Ptr(lltype.FuncType([], lltype.Void))
     VISIT_FUNCTYPE = lltype.Ptr(lltype.FuncType([PYOBJ_HDR_PTR, rffi.VOIDP],
                                                 rffi.INT_real))
@@ -3004,8 +3010,11 @@
 
     def _pyobj(self, pyobjaddr):
             return llmemory.cast_adr_to_ptr(pyobjaddr, self.PYOBJ_HDR_PTR)
+    def _pygchdr(self, pygchdraddr):
+            return llmemory.cast_adr_to_ptr(pygchdraddr, self.PYOBJ_GC_HDR_PTR)
 
-    def rawrefcount_init(self, dealloc_trigger_callback, tp_traverse):
+    def rawrefcount_init(self, dealloc_trigger_callback, tp_traverse,
+                         pyobj_list):
         # see pypy/doc/discussion/rawrefcount.rst
         if not self.rrc_enabled:
             self.rrc_p_list_young = self.AddressStack()
@@ -3021,6 +3030,7 @@
             self.rrc_pyobjects_to_scan = self.AddressStack()
             self.rrc_more_pyobjects_to_scan = self.AddressStack()
             self.rrc_pyobjects_to_trace = self.AddressStack()
+            self.rrc_pyobj_list = self._pygchdr(pyobj_list)
             self.rrc_enabled = True
 
     def check_no_more_rawrefcount_state(self):
@@ -3220,6 +3230,8 @@
         assert not self.rrc_more_pyobjects_to_scan.non_empty()
         assert not self.rrc_pyobjects_to_trace.non_empty()
 
+        self._rrc_gc_print_list()
+
         # initially, scan all real pyobjects (not proxies) which are linked to objects
         #self.rrc_p_list_old.foreach(self._rrc_major_scan_non_rc_roots, None)
         self.rrc_o_list_old.foreach(self._rrc_major_scan_non_rc_roots, None)
@@ -3334,4 +3346,15 @@
         callback_ptr = llhelper(self.VISIT_FUNCTYPE,
                                 IncrementalMiniMarkGC._rrc_visit)
         self_ptr = rffi.cast(rffi.VOIDP, cast_nongc_instance_to_adr(self))
-        self.rrc_tp_traverse(pyobj, callback_ptr, self_ptr)
\ No newline at end of file
+        self.rrc_tp_traverse(pyobj, callback_ptr, self_ptr)
+
+    def _rrc_gc_list_init(self, pygclist):
+        pygclist.c_gc_next = rffi.cast(rffi.VOIDP, pygclist)
+        pygclist.c_gc_prev = rffi.cast(rffi.VOIDP, pygclist)
+
+    def _rrc_gc_print_list(self):
+        debug_print("gc_print_list start!")
+        curr = rffi.cast(self.PYOBJ_GC_HDR_PTR, self.rrc_pyobj_list.c_gc_next)
+        while curr != self.rrc_pyobj_list:
+            debug_print("gc_print_list: ", curr)
+            curr = rffi.cast(self.PYOBJ_GC_HDR_PTR, curr.c_gc_next)
diff --git a/rpython/memory/gc/test/test_rawrefcount.py b/rpython/memory/gc/test/test_rawrefcount.py
--- a/rpython/memory/gc/test/test_rawrefcount.py
+++ b/rpython/memory/gc/test/test_rawrefcount.py
@@ -5,7 +5,7 @@
 from rpython.rlib.rawrefcount import (REFCNT_FROM_PYPY, REFCNT_FROM_PYPY_LIGHT,
                                       REFCNT_MASK)
 from pypy.module.cpyext.api import (PyObject, PyTypeObject, PyTypeObjectPtr,
-                                    PyObjectFields, cpython_struct)
+                                    PyObjectFields, cpython_struct, PyGC_Head)
 from pypy.module.cpyext.complexobject import PyComplexObject
 from rpython.rtyper.lltypesystem import rffi
 from pypy.module.cpyext.typeobjectdefs import visitproc, traverseproc
@@ -54,8 +54,11 @@
             rc = REFCNT_FROM_PYPY
         self.trigger = []
         self.trigger2 = []
+        self.pyobj_list = lltype.malloc(PyGC_Head.TO, flavor='raw',
+                                        immortal=True)
         self.gc.rawrefcount_init(lambda: self.trigger.append(1),
-                                 lambda: self.trigger2.append(1))
+                                 lambda: self.trigger2.append(1),
+                                 self.pyobj_list)
         #
         if create_immortal:
             p1 = lltype.malloc(S, immortal=True)
diff --git a/rpython/memory/gctransform/framework.py b/rpython/memory/gctransform/framework.py
--- a/rpython/memory/gctransform/framework.py
+++ b/rpython/memory/gctransform/framework.py
@@ -476,7 +476,7 @@
             self.rawrefcount_init_ptr = getfn(
                 GCClass.rawrefcount_init,
                 [s_gc, SomePtr(GCClass.RAWREFCOUNT_DEALLOC_TRIGGER),
-                 SomePtr(GCClass.RAWREFCOUNT_TRAVERSE)],
+                 SomePtr(GCClass.RAWREFCOUNT_TRAVERSE), SomeAddress()],
                 annmodel.s_None)
             self.rawrefcount_create_link_pypy_ptr = getfn(
                 GCClass.rawrefcount_create_link_pypy,
@@ -1311,12 +1311,13 @@
         self.pop_roots(hop, livevars)
 
     def gct_gc_rawrefcount_init(self, hop):
-        [v_fnptr, v_fnptr2] = hop.spaceop.args
+        [v_fnptr, v_fnptr2, v_pyobj_list] = hop.spaceop.args
         assert v_fnptr.concretetype == self.GCClass.RAWREFCOUNT_DEALLOC_TRIGGER
         assert v_fnptr2.concretetype == self.GCClass.RAWREFCOUNT_TRAVERSE
+        # TODO add assert for v_pyobj_list
         hop.genop("direct_call",
                   [self.rawrefcount_init_ptr, self.c_const_gc, v_fnptr,
-                   v_fnptr2])
+                   v_fnptr2, v_pyobj_list])
 
     def gct_gc_rawrefcount_create_link_pypy(self, hop):
         [v_gcobj, v_pyobject] = hop.spaceop.args
diff --git a/rpython/rlib/rawrefcount.py b/rpython/rlib/rawrefcount.py
--- a/rpython/rlib/rawrefcount.py
+++ b/rpython/rlib/rawrefcount.py
@@ -81,12 +81,12 @@
 
 
 @not_rpython
-def init(dealloc_trigger_callback=None, tp_traverse=None):
+def init(dealloc_trigger_callback=None, tp_traverse=None, pyobj_list=None):
     """set up rawrefcount with the GC.  This is only used
     for tests; it should not be called at all during translation.
     """
     global _p_list, _o_list, _adr2pypy, _pypy2ob, _pypy2ob_rev
-    global _d_list, _dealloc_trigger_callback, _tp_traverse
+    global _d_list, _dealloc_trigger_callback, _tp_traverse, _pygclist
     _p_list = []
     _o_list = []
     _adr2pypy = [None]
@@ -96,6 +96,7 @@
     _d_marker = None
     _dealloc_trigger_callback = dealloc_trigger_callback
     _tp_traverse = tp_traverse
+    _pygclist = pyobj_list
 
 # def init_traverse(traverse_cpy_call):
 #     global _traverse_cpy_call
@@ -289,15 +290,18 @@
 class Entry(ExtRegistryEntry):
     _about_ = init
 
-    def compute_result_annotation(self, s_dealloc_callback, tp_traverse):
+    def compute_result_annotation(self, s_dealloc_callback, tp_traverse,
+                                  pyobj_list):
         from rpython.rtyper.llannotation import SomePtr
         assert isinstance(s_dealloc_callback, SomePtr)   # ll-ptr-to-function
         # add assert?
 
     def specialize_call(self, hop):
         hop.exception_cannot_occur()
-        v_dealloc_callback, v_tp_traverse = hop.inputargs(*hop.args_r)
-        hop.genop('gc_rawrefcount_init', [v_dealloc_callback, v_tp_traverse])
+        v_dealloc_callback, v_tp_traverse, v_pyobj_list = \
+            hop.inputargs(*hop.args_r)
+        hop.genop('gc_rawrefcount_init', [v_dealloc_callback, v_tp_traverse,
+                                          v_pyobj_list])
 
 
 class Entry(ExtRegistryEntry):
diff --git a/rpython/translator/c/src/mem.h b/rpython/translator/c/src/mem.h
--- a/rpython/translator/c/src/mem.h
+++ b/rpython/translator/c/src/mem.h
@@ -2,11 +2,32 @@
 /************************************************************/
 /***  C header subsection: operations on LowLevelTypes    ***/
 
-#include <string.h>
+#ifdef CPYEXT_BOEHM
+/* use boehm for cpyext -> redirect all calls to malloc
+    - use __libc_malloc / __libc_calloc for pypy
+    - cpyext modules will use redirected malloc
+*/
+#define REDIRECT_MALLOC=GC_malloc
+/* TODO: use own version of boehm, where before sweep new roots can be added */
+#include <gc/gc.h>
 
-/* used by rpython.rlib.rstack, but also by asmgcc */
-#define OP_STACK_CURRENT(r)  r = (Signed)&r
+static void (*real_malloc)(size_t) = NULL;
+static void (*real_calloc)(size_t,  size_t) = NULL;
 
+/* TODO: fix, does not work. but patch should be made here */
+#define OP_RAW_MALLOC(size, zero, result)  {    \
+        if (zero) {                             \
+            real_write = dlsym(RTLD_NEXT, "write");
+            real_write(fd, buf, count);
+            result = __libc_calloc(size, 1);    \
+        } else                                  \
+            result = __libc_malloc(size);       \
+        if (result != NULL) {                   \
+            COUNT_MALLOC;                       \
+        }                                       \
+    }
+
+#else
 
 #define OP_RAW_MALLOC(size, zero, result)  {    \
         if (zero)                               \
@@ -18,6 +39,13 @@
         }                                       \
     }
 
+#endif
+
+#include <string.h>
+
+/* used by rpython.rlib.rstack, but also by asmgcc */
+#define OP_STACK_CURRENT(r)  r = (Signed)&r
+
 #define OP_RAW_FREE(p, r) free(p); COUNT_FREE;
 
 #define OP_RAW_MEMCLEAR(p, size, r) memset((void*)p, 0, size)


More information about the pypy-commit mailing list