[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