Author: Stefan Beyer <h...@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 - -@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) _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit