Author: Stefan Beyer <h...@sbeyer.at> Branch: cpyext-gc-cycle Changeset: r95605:878ff32d88a1 Date: 2018-07-05 13:01 +0200 http://bitbucket.org/pypy/pypy/changeset/878ff32d88a1/
Log: Removed extra flags in cpython refcount Fixed tests in test_rawrefcount and test_cpyext Removed references from rawrefcount to cpyext Added some comments 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 @@ -1787,10 +1787,10 @@ preexist_error = PyErr_Occurred(space) try: - print "start cpyext_call" + #print "start cpyext_call" # Call the function result = call_external_function(func, *boxed_args) - print "end cpyext_call" + #print "end cpyext_call" finally: assert cpyext_glob_tid_ptr[0] == tid cpyext_glob_tid_ptr[0] = tid_before diff --git a/pypy/module/cpyext/include/boolobject.h b/pypy/module/cpyext/include/boolobject.h --- a/pypy/module/cpyext/include/boolobject.h +++ b/pypy/module/cpyext/include/boolobject.h @@ -13,8 +13,8 @@ #define Py_True ((PyObject *) &_Py_TrueStruct) /* Macros for returning Py_True or Py_False, respectively */ -#define Py_RETURN_TRUE do { Py_INCREF(Py_True); return Py_True; } while(0) -#define Py_RETURN_FALSE do { Py_INCREF(Py_False); return Py_False; } while(0) +#define Py_RETURN_TRUE return Py_INCREF(Py_True), Py_True +#define Py_RETURN_FALSE return Py_INCREF(Py_False), Py_False #ifdef __cplusplus } 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 @@ -2,7 +2,6 @@ #define Py_OBJECT_H #include <stdio.h> -#include <math.h> #ifdef __cplusplus extern "C" { @@ -13,12 +12,7 @@ #define PY_SSIZE_T_MAX ((Py_ssize_t)(((size_t)-1)>>1)) #define PY_SSIZE_T_MIN (-PY_SSIZE_T_MAX-1) -#define PY_REFCNT_FROM_PYPY (4L << ((long)(log(PY_SSIZE_T_MAX) / log(2) - 2))) -#define PY_REFCNT_OVERFLOW (1L << ((long)(log(PY_SSIZE_T_MAX) / log(2) - 4) - 1L)) -#define PY_REFCNT_MASK ((PY_REFCNT_OVERFLOW << 1L) - 1L) -#define Py_RETURN_NONE return (((((PyObject *)(Py_None))->ob_refcnt & PY_REFCNT_OVERFLOW) == 0) ? \ - ((PyObject *)(Py_None))->ob_refcnt++ : Py_IncRef((PyObject *)(Py_None))), Py_None - +#define Py_RETURN_NONE return Py_INCREF(Py_None), Py_None /* CPython has this for backwards compatibility with really old extensions, and now @@ -40,20 +34,14 @@ #define Py_XDECREF(ob) (Py_DecRef((PyObject *)(ob))) #else /* Fast version */ -#define Py_INCREF(ob) do { \ - if (!(((PyObject *)(ob))->ob_refcnt & PY_REFCNT_OVERFLOW)) \ - ((PyObject *)(ob))->ob_refcnt++; \ - else \ - Py_IncRef((PyObject *)(ob)); \ - } while (0) -#define Py_DECREF(ob) do { \ - if ((((PyObject *)(ob))->ob_refcnt & PY_REFCNT_OVERFLOW)) \ - Py_DecRef((PyObject *)(ob)); \ - else if (--((PyObject *)(ob))->ob_refcnt & PY_REFCNT_MASK) \ - ; \ - else \ - _Py_Dealloc((PyObject *)(ob)); \ - } while (0) +#define Py_INCREF(ob) (((PyObject *)(ob))->ob_refcnt++) +#define Py_DECREF(op) \ + do { \ + if (--((PyObject *)(op))->ob_refcnt != 0) \ + ; \ + else \ + _Py_Dealloc((PyObject *)(op)); \ + } while (0) #define Py_XINCREF(op) do { if ((op) == NULL) ; else Py_INCREF(op); } while (0) #define Py_XDECREF(op) do { if ((op) == NULL) ; else Py_DECREF(op); } while (0) @@ -73,8 +61,7 @@ } \ } while (0) -#define Py_REFCNT(ob) ((((PyObject *)(ob))->ob_refcnt & PY_REFCNT_OVERFLOW == 0) ? \ - (((PyObject*)(ob))->ob_refcnt & PY_REFCNT_MASK) : _Py_RefCnt_Overflow(ob)) +#define Py_REFCNT(ob) (((PyObject*)(ob))->ob_refcnt) #define Py_TYPE(ob) (((PyObject*)(ob))->ob_type) #define Py_SIZE(ob) (((PyVarObject*)(ob))->ob_size) diff --git a/pypy/module/cpyext/object.py b/pypy/module/cpyext/object.py --- a/pypy/module/cpyext/object.py +++ b/pypy/module/cpyext/object.py @@ -11,7 +11,6 @@ from pypy.module.cpyext.pyerrors import PyErr_NoMemory, PyErr_BadInternalCall from pypy.objspace.std.typeobject import W_TypeObject from pypy.interpreter.error import OperationError, oefmt -from rpython.rlib.rawrefcount import REFCNT_MASK import pypy.module.__builtin__.operation as operation @@ -51,7 +50,7 @@ def _dealloc(space, obj): # This frees an object after its refcount dropped to zero, so we # assert that it is really zero here. - assert obj.c_ob_refcnt & REFCNT_MASK == 0 + assert obj.c_ob_refcnt == 0 pto = obj.c_ob_type obj_voidp = rffi.cast(rffi.VOIDP, obj) generic_cpy_call(space, pto.c_tp_free, obj_voidp) 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 @@ -17,11 +17,8 @@ from rpython.rlib.objectmodel import keepalive_until_here from rpython.rtyper.annlowlevel import llhelper, cast_instance_to_base_ptr from rpython.rlib import rawrefcount, jit -from rpython.rlib.debug import ll_assert, fatalerror, debug_print -from rpython.rlib.rawrefcount import (REFCNT_MASK, REFCNT_FROM_PYPY, - REFCNT_OVERFLOW) -from pypy.module.cpyext.api import slot_function -from pypy.module.cpyext.typeobjectdefs import visitproc +from rpython.rlib.debug import ll_assert, fatalerror + #________________________________________________________ # type description @@ -344,7 +341,7 @@ pyobj = as_pyobj(space, w_obj, w_userdata, immortal=immortal) if pyobj: # != NULL assert pyobj.c_ob_refcnt >= rawrefcount.REFCNT_FROM_PYPY - rawrefcount.incref(pyobj) + pyobj.c_ob_refcnt += 1 keepalive_until_here(w_obj) return pyobj @@ -378,7 +375,7 @@ pyobj = rffi.cast(PyObject, pyobj) w_obj = from_ref(space, pyobj) if pyobj: - rawrefcount.decref(pyobj) + pyobj.c_ob_refcnt -= 1 assert pyobj.c_ob_refcnt >= rawrefcount.REFCNT_FROM_PYPY keepalive_until_here(w_obj) return w_obj @@ -389,7 +386,7 @@ assert is_pyobj(pyobj) pyobj = rffi.cast(PyObject, pyobj) assert pyobj.c_ob_refcnt >= 1 - rawrefcount.incref(pyobj) + pyobj.c_ob_refcnt += 1 @specialize.ll() def decref(space, pyobj): @@ -397,9 +394,11 @@ assert is_pyobj(pyobj) pyobj = rffi.cast(PyObject, pyobj) if pyobj: - rawrefcount.decref(pyobj) - rc = pyobj.c_ob_refcnt - if rc & REFCNT_MASK == 0: + assert pyobj.c_ob_refcnt > 0 + assert (pyobj.c_ob_pypy_link == 0 or + pyobj.c_ob_refcnt > rawrefcount.REFCNT_FROM_PYPY) + pyobj.c_ob_refcnt -= 1 + if pyobj.c_ob_refcnt == 0: state = space.fromcache(State) generic_cpy_call(space, state.C._Py_Dealloc, pyobj) #else: @@ -407,32 +406,6 @@ # if w_obj is not None: # assert pyobj.c_ob_refcnt >= rawrefcount.REFCNT_FROM_PYPY -@cpython_api([PyObject], lltype.Void) -def Py_IncRef(space, obj): - incref(space, obj) - -@cpython_api([PyObject], lltype.Void) -def Py_DecRef(space, obj): - decref(space, obj) - -@cpython_api([PyObject], lltype.SignedLongLong, error=CANNOT_FAIL) -def _Py_RefCnt_Overflow(space, obj): - return refcnt_overflow(space, obj) - -@specialize.ll() -def refcnt_overflow(space, obj): - if is_pyobj(obj): - pyobj = rffi.cast(PyObject, obj) - else: - pyobj = as_pyobj(space, obj, None) - if pyobj: - if pyobj.c_ob_refcnt & REFCNT_MASK == REFCNT_OVERFLOW: - return REFCNT_OVERFLOW - else: - return (pyobj.c_ob_refcnt & REFCNT_MASK) + \ - rawrefcount.overflow_get(pyobj) - return 0 - @init_function def write_w_marker_deallocating(space): if we_are_translated(): 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 @@ -11,7 +11,6 @@ extern void _PyPy_Free(void *ptr); extern void *_PyPy_Malloc(Py_ssize_t size); -/* void Py_IncRef(PyObject *o) { @@ -23,7 +22,6 @@ { Py_XDECREF(o); } -*/ /* * The actual value of this variable will be the address of 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 @@ -74,8 +74,12 @@ def tp_traverse(obj_addr, callback, args): # TODO: implement pass + # Warning: This list ist different than the list actually used + # by the extension modules (see _PyPy_InitPyObjList). pyobj_list = lltype.malloc(PyGC_HeadPtr.TO, flavor='raw', immortal=True, zero=True) + pyobj_list.c_gc_next = rffi.cast(rffi.VOIDP, pyobj_list); + pyobj_list.c_gc_next = rffi.cast(rffi.VOIDP, pyobj_list); rawrefcount.init(dealloc_trigger, tp_traverse, pyobj_list) else: if space.config.translation.gc == "boehm": diff --git a/pypy/module/cpyext/test/test_bytesobject.py b/pypy/module/cpyext/test/test_bytesobject.py --- a/pypy/module/cpyext/test/test_bytesobject.py +++ b/pypy/module/cpyext/test/test_bytesobject.py @@ -9,12 +9,11 @@ PyString_ConcatAndDel, PyString_Format, PyString_InternFromString, PyString_AsEncodedObject, PyString_AsDecodedObject, _PyString_Eq, _PyString_Join) -from pypy.module.cpyext.api import ( - PyObjectP, PyObject, Py_ssize_tP, generic_cpy_call) -from pypy.module.cpyext.pyobject import ( - Py_DecRef, Py_IncRef, _Py_RefCnt_Overflow, from_ref, make_ref, decref) +from pypy.module.cpyext.api import PyObjectP, PyObject, Py_ssize_tP, \ + generic_cpy_call +from pypy.module.cpyext.pyobject import decref, from_ref, make_ref from pypy.module.cpyext.buffer import PyObject_AsCharBuffer -from rpython.rlib import rawrefcount +from pypy.module.cpyext.api import PyTypeObjectPtr class AppTestBytesObject(AppTestCpythonExtensionBase): @@ -512,9 +511,9 @@ ref = make_ref(space, space.wrap('abc')) ptr = lltype.malloc(PyObjectP.TO, 1, flavor='raw') ptr[0] = ref - prev_refcnt = ref.c_ob_refcnt & rawrefcount.REFCNT_MASK + prev_refcnt = ref.c_ob_refcnt PyString_Concat(space, ptr, space.wrap('def')) - assert ref.c_ob_refcnt & rawrefcount.REFCNT_MASK == prev_refcnt - 1 + assert ref.c_ob_refcnt == prev_refcnt - 1 assert space.str_w(from_ref(space, ptr[0])) == 'abcdef' with pytest.raises(OperationError): PyString_Concat(space, ptr, space.w_None) @@ -550,9 +549,9 @@ w_text = space.wrap("text") ref = make_ref(space, w_text) - prev_refcnt = ref.c_ob_refcnt & rawrefcount.REFCNT_MASK + prev_refcnt = ref.c_ob_refcnt assert PyObject_AsCharBuffer(space, ref, bufp, lenp) == 0 - assert ref.c_ob_refcnt & rawrefcount.REFCNT_MASK == prev_refcnt + assert ref.c_ob_refcnt == prev_refcnt assert lenp[0] == 4 assert rffi.charp2str(bufp[0]) == 'text' lltype.free(bufp, flavor='raw') @@ -611,53 +610,3 @@ w_seq = space.wrap(['a', 'b']) w_joined = _PyString_Join(space, w_sep, w_seq) assert space.unwrap(w_joined) == 'a<sep>b' - - def test_refcnt_overflow(self, space): - ref1 = make_ref(space, space.wrap('foo')) - ref1.c_ob_refcnt = rawrefcount.REFCNT_OVERFLOW - 1 - - Py_IncRef(space, ref1) - assert ref1.c_ob_refcnt & rawrefcount.REFCNT_MASK \ - == rawrefcount.REFCNT_OVERFLOW - assert _Py_RefCnt_Overflow(space, ref1) \ - == rawrefcount.REFCNT_OVERFLOW - - Py_IncRef(space, ref1) - assert ref1.c_ob_refcnt & rawrefcount.REFCNT_MASK \ - == rawrefcount.REFCNT_OVERFLOW + 1 - assert _Py_RefCnt_Overflow(space, ref1) \ - == rawrefcount.REFCNT_OVERFLOW + 1 - - Py_IncRef(space, ref1) - assert ref1.c_ob_refcnt & rawrefcount.REFCNT_MASK \ - == rawrefcount.REFCNT_OVERFLOW + 1 - assert _Py_RefCnt_Overflow(space, ref1) \ - == rawrefcount.REFCNT_OVERFLOW + 2 - - Py_IncRef(space, ref1) - assert ref1.c_ob_refcnt & rawrefcount.REFCNT_MASK \ - == rawrefcount.REFCNT_OVERFLOW + 1 - assert _Py_RefCnt_Overflow(space, ref1) \ - == rawrefcount.REFCNT_OVERFLOW + 3 - - Py_DecRef(space, ref1) - assert ref1.c_ob_refcnt & rawrefcount.REFCNT_MASK \ - == rawrefcount.REFCNT_OVERFLOW + 1 - assert _Py_RefCnt_Overflow(space, ref1) \ - == rawrefcount.REFCNT_OVERFLOW + 2 - - Py_DecRef(space, ref1) - assert ref1.c_ob_refcnt & rawrefcount.REFCNT_MASK \ - == rawrefcount.REFCNT_OVERFLOW + 1 - assert _Py_RefCnt_Overflow(space, ref1) \ - == rawrefcount.REFCNT_OVERFLOW + 1 - - Py_DecRef(space, ref1) - assert ref1.c_ob_refcnt & rawrefcount.REFCNT_MASK \ - == rawrefcount.REFCNT_OVERFLOW - assert _Py_RefCnt_Overflow(space, ref1) \ - == rawrefcount.REFCNT_OVERFLOW - - Py_DecRef(space, ref1) - assert ref1.c_ob_refcnt & rawrefcount.REFCNT_MASK \ - == rawrefcount.REFCNT_OVERFLOW - 1 diff --git a/pypy/module/cpyext/test/test_cpyext.py b/pypy/module/cpyext/test/test_cpyext.py --- a/pypy/module/cpyext/test/test_cpyext.py +++ b/pypy/module/cpyext/test/test_cpyext.py @@ -756,7 +756,7 @@ module = self.import_module(name='foo', init=init, body=body) # uncaught interplevel exceptions are turned into SystemError - expected = "ZeroDivisionError('integer division or modulo by zero',)" + expected = "ZeroDivisionError('integer division by zero',)" exc = raises(SystemError, module.crash1) assert exc.value[0] == expected 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 @@ -3107,10 +3107,11 @@ self.singleaddr) def _rrc_minor_trace(self, pyobject, singleaddr): - from rpython.rlib.rawrefcount import REFCNT_MASK + from rpython.rlib.rawrefcount import REFCNT_FROM_PYPY + from rpython.rlib.rawrefcount import REFCNT_FROM_PYPY_LIGHT # rc = self._pyobj(pyobject).c_ob_refcnt - if rc & REFCNT_MASK == 0: + if rc == REFCNT_FROM_PYPY or rc == REFCNT_FROM_PYPY_LIGHT: pass # the corresponding object may die else: # force the corresponding object to be alive @@ -3169,12 +3170,11 @@ def _rrc_free(self, pyobject): from rpython.rlib.rawrefcount import REFCNT_FROM_PYPY from rpython.rlib.rawrefcount import REFCNT_FROM_PYPY_LIGHT - from rpython.rlib.rawrefcount import REFCNT_MASK # rc = self._pyobj(pyobject).c_ob_refcnt if rc >= REFCNT_FROM_PYPY_LIGHT: rc -= REFCNT_FROM_PYPY_LIGHT - if rc & REFCNT_MASK == 0: + if rc == 0: lltype.free(self._pyobj(pyobject), flavor='raw') else: # can only occur if LIGHT is used in create_link_pyobj() @@ -3186,7 +3186,7 @@ "refcount underflow from REFCNT_FROM_PYPY_LIGHT?") rc -= REFCNT_FROM_PYPY self._pyobj(pyobject).c_ob_pypy_link = 0 - if rc & REFCNT_MASK == 0: + if rc == 0: self.rrc_dealloc_pending.append(pyobject) # an object with refcnt == 0 cannot stay around waiting # for its deallocator to be called. Some code (lxml) @@ -3212,10 +3212,11 @@ debug_stop("gc-rrc-trace") def _rrc_major_trace(self, pyobject, ignore): - from rpython.rlib.rawrefcount import REFCNT_MASK + from rpython.rlib.rawrefcount import REFCNT_FROM_PYPY + from rpython.rlib.rawrefcount import REFCNT_FROM_PYPY_LIGHT # rc = self._pyobj(pyobject).c_ob_refcnt - if rc & REFCNT_MASK == 0: + if rc == REFCNT_FROM_PYPY or rc == REFCNT_FROM_PYPY_LIGHT: pass # the corresponding object may die else: # force the corresponding object to be alive @@ -3263,11 +3264,11 @@ self.rrc_more_pyobjects_to_scan = self.AddressStack() def _rrc_mark_cpyobj(self, pyobj): - from rpython.rlib.rawrefcount import REFCNT_VISITED # if the pyobj is not marked, remember it and if there is a linked pypy # object also remember it - if pyobj.c_ob_refcnt & REFCNT_VISITED != REFCNT_VISITED: - pyobj.c_ob_refcnt |= REFCNT_VISITED + visited = True # TODO: check if visited (via 'cast' to PyGC_Head) + if not visited: + # TODO: mark visited pyobject = llmemory.cast_ptr_to_adr(pyobj) self.rrc_more_pyobjects_to_scan.append(pyobject) intobj = pyobj.c_ob_pypy_link @@ -3278,7 +3279,6 @@ self.objects_to_trace.append(obj) def _rrc_major_scan_non_rc_roots(self, pyobject, ignore): - from rpython.rlib.rawrefcount import REFCNT_VISITED # check in the object header of the linked pypy object, if it is marked # or not pyobj = self._pyobj(pyobject) @@ -3286,9 +3286,10 @@ obj = llmemory.cast_int_to_adr(intobj) hdr = self.header(obj) if hdr.tid & GCFLAG_VISITED: - if pyobj.c_ob_refcnt & REFCNT_VISITED != REFCNT_VISITED: + visited = True # TODO: check if visited + if not visited: # process the pyobject now - pyobj.c_ob_refcnt |= REFCNT_VISITED + # TODO: mark visited self.rrc_pyobjects_to_trace.append(pyobject) else: # save the pyobject for later, in case its linked object becomes 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 @@ -2,17 +2,15 @@ from rpython.rtyper.lltypesystem import lltype, llmemory from rpython.memory.gc.incminimark import IncrementalMiniMarkGC from rpython.memory.gc.test.test_direct import BaseDirectGCTest -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, PyGC_Head) -from pypy.module.cpyext.complexobject import PyComplexObject +from rpython.rlib.rawrefcount import REFCNT_FROM_PYPY +from rpython.rlib.rawrefcount import REFCNT_FROM_PYPY_LIGHT from rpython.rtyper.lltypesystem import rffi -from pypy.module.cpyext.typeobjectdefs import visitproc, traverseproc from rpython.rtyper.annlowlevel import llhelper -from rpython.rtyper.tool import rffi_platform +#from pypy.module.cpyext.api import (PyTypeObject) +#from pypy.module.cpyext.typeobjectdefs import visitproc, traverseproc PYOBJ_HDR = IncrementalMiniMarkGC.PYOBJ_HDR PYOBJ_HDR_PTR = IncrementalMiniMarkGC.PYOBJ_HDR_PTR +PYOBJ_GC_HDR_PTR = IncrementalMiniMarkGC.PYOBJ_GC_HDR_PTR S = lltype.GcForwardReference() S.become(lltype.GcStruct('S', @@ -22,14 +20,14 @@ T = lltype.Ptr(lltype.ForwardReference()) T.TO.become(lltype.Struct('test', - ('base', PyObject.TO), + ('base', PYOBJ_HDR_PTR.TO), ('next', T), ('prev', T), ('value', lltype.Signed))) -TRAVERSE_FUNCTYPE = rffi.CCallback([PyObject, visitproc, rffi.VOIDP], - rffi.INT_real) -t1 = lltype.malloc(PyTypeObject, flavor='raw', immortal=True) +#TRAVERSE_FUNCTYPE = rffi.CCallback([PYOBJ_HDR_PTR, visitproc, rffi.VOIDP], +# rffi.INT_real) +#t1 = lltype.malloc(PyTypeObject, flavor='raw', immortal=True) class TestRawRefCount(BaseDirectGCTest): @@ -54,11 +52,13 @@ rc = REFCNT_FROM_PYPY self.trigger = [] self.trigger2 = [] - self.pyobj_list = lltype.malloc(PyGC_Head.TO, flavor='raw', + self.pyobj_list = lltype.malloc(PYOBJ_GC_HDR_PTR.TO, flavor='raw', immortal=True) + self.pyobj_list.c_gc_next = rffi.cast(rffi.VOIDP, self.pyobj_list); + self.pyobj_list.c_gc_next = rffi.cast(rffi.VOIDP, self.pyobj_list); self.gc.rawrefcount_init(lambda: self.trigger.append(1), lambda: self.trigger2.append(1), - self.pyobj_list) + llmemory.cast_ptr_to_adr(self.pyobj_list)) # if create_immortal: p1 = lltype.malloc(S, immortal=True) @@ -78,10 +78,10 @@ self._collect(major=False) p1 = self.stackroots.pop() p1ref = lltype.cast_opaque_ptr(llmemory.GCREF, p1) - r1 = lltype.malloc(PyObject.TO, flavor='raw', immortal=create_immortal) + r1 = lltype.malloc(PYOBJ_HDR_PTR.TO, flavor='raw', immortal=create_immortal) r1.c_ob_refcnt = rc r1.c_ob_pypy_link = 0 - r1.c_ob_type = lltype.nullptr(PyTypeObject) + #r1.c_ob_type = lltype.nullptr(PyTypeObject) r1addr = llmemory.cast_ptr_to_adr(r1) if is_pyobj: assert not is_light @@ -104,40 +104,13 @@ return p1 return p1, p1ref, r1, r1addr, check_alive - def _rawrefcount_cycle_obj(self): - - def test_tp_traverse(obj, visit, args): - test = rffi.cast(T, obj) - vret = 0 - if llmemory.cast_ptr_to_adr(test.next).ptr is not None: - next = rffi.cast(PyObject, test.next) - vret = visit(next, args) - if vret != 0: - return vret - if llmemory.cast_ptr_to_adr(test.prev).ptr is not None: - next = rffi.cast(PyObject, test.prev) - vret = visit(next, args) - if vret != 0: - return vret - return vret - - func_ptr = llhelper(TRAVERSE_FUNCTYPE, test_tp_traverse) - rffi_func_ptr = rffi.cast(traverseproc, func_ptr) - t1.c_tp_traverse = rffi_func_ptr - - r1 = lltype.malloc(T.TO, flavor='raw', immortal=True) - r1.base.c_ob_pypy_link = 0 - r1.base.c_ob_type = t1 - r1.base.c_ob_refcnt = 1 - return r1 - def test_rawrefcount_objects_basic(self, old=False): p1, p1ref, r1, r1addr, check_alive = ( self._rawrefcount_pair(42, is_light=True, create_old=old)) p2 = self.malloc(S) p2.x = 84 p2ref = lltype.cast_opaque_ptr(llmemory.GCREF, p2) - r2 = lltype.malloc(PyObject.TO, flavor='raw') + r2 = lltype.malloc(PYOBJ_HDR_PTR.TO, flavor='raw') r2.c_ob_refcnt = 1 r2.c_ob_pypy_link = 0 r2addr = llmemory.cast_ptr_to_adr(r2) @@ -340,6 +313,33 @@ self._collect(major=True) check_alive(0) + # def _rawrefcount_cycle_obj(self): + # + # def test_tp_traverse(obj, visit, args): + # test = rffi.cast(T, obj) + # vret = 0 + # if llmemory.cast_ptr_to_adr(test.next).ptr is not None: + # next = rffi.cast(PYOBJ_HDR_PTR, test.next) + # vret = visit(next, args) + # if vret != 0: + # return vret + # if llmemory.cast_ptr_to_adr(test.prev).ptr is not None: + # next = rffi.cast(PYOBJ_HDR_PTR, test.prev) + # vret = visit(next, args) + # if vret != 0: + # return vret + # return vret + # + # func_ptr = llhelper(TRAVERSE_FUNCTYPE, test_tp_traverse) + # rffi_func_ptr = rffi.cast(traverseproc, func_ptr) + # t1.c_tp_traverse = rffi_func_ptr + # + # r1 = lltype.malloc(T.TO, flavor='raw', immortal=True) + # r1.base.c_ob_pypy_link = 0 + # r1.base.c_ob_type = t1 + # r1.base.c_ob_refcnt = 1 + # return r1 + # # def test_cycle_self_reference_free(self): # self.gc.rawrefcount_init(lambda: self.trigger.append(1)) # r1 = self._rawrefcount_cycle_obj() diff --git a/rpython/rlib/rawrefcount.py b/rpython/rlib/rawrefcount.py --- a/rpython/rlib/rawrefcount.py +++ b/rpython/rlib/rawrefcount.py @@ -4,22 +4,16 @@ # This is meant for pypy's cpyext module, but is a generally # useful interface over our GC. XXX "pypy" should be removed here # -import sys, weakref, py, math +import sys, weakref, py from rpython.rtyper.lltypesystem import lltype, llmemory, rffi from rpython.rlib.objectmodel import we_are_translated, specialize, not_rpython from rpython.rtyper.extregistry import ExtRegistryEntry from rpython.translator.tool.cbuild import ExternalCompilationInfo -from rpython.rlib import rgc, objectmodel +from rpython.rlib import rgc -MAX_BIT = int(math.log(sys.maxint, 2)) - -# Flags -REFCNT_FROM_PYPY = 1 << MAX_BIT - 2 # Reference from a pypy object -REFCNT_FROM_PYPY_LIGHT = (1 << MAX_BIT - 1) + REFCNT_FROM_PYPY # Light reference from a pypy object -REFCNT_VISITED = 1 << MAX_BIT - 3 # Object visited during marking -REFCNT_OVERFLOW = 1 << MAX_BIT - 4 # Overflow bit for reference count -REFCNT_MASK = (REFCNT_OVERFLOW << 1) - 1 # Mask for reference count (including overflow bit) +REFCNT_FROM_PYPY = sys.maxint // 4 + 1 +REFCNT_FROM_PYPY_LIGHT = REFCNT_FROM_PYPY + (sys.maxint // 2 + 1) PYOBJ_HDR = lltype.Struct('GCHdr_PyObject', ('c_ob_refcnt', lltype.Signed), @@ -39,46 +33,6 @@ _adr2pypy.append(p) return res -def incref(pyobj): - if pyobj.c_ob_refcnt & REFCNT_OVERFLOW == 0: - pyobj.c_ob_refcnt += 1 - else: - if pyobj.c_ob_refcnt & REFCNT_MASK == REFCNT_OVERFLOW: - pyobj.c_ob_refcnt += 1 - overflow_new(pyobj) - else: - overflow_add(pyobj) - -def decref(pyobj): - if pyobj.c_ob_refcnt & REFCNT_OVERFLOW == 0: - pyobj.c_ob_refcnt -= 1 - else: - if pyobj.c_ob_refcnt & REFCNT_MASK == REFCNT_OVERFLOW: - pyobj.c_ob_refcnt -= 1 - elif overflow_sub(pyobj): - pyobj.c_ob_refcnt -= 1 - -_refcount_overflow = dict() - -def overflow_new(obj): - _refcount_overflow[objectmodel.current_object_addr_as_int(obj)] = 0 - -def overflow_add(obj): - _refcount_overflow[objectmodel.current_object_addr_as_int(obj)] += 1 - -def overflow_sub(obj): - addr = objectmodel.current_object_addr_as_int(obj) - c = _refcount_overflow[addr] - if c > 0: - _refcount_overflow[addr] = c - 1 - return False - else: - _refcount_overflow.pop(addr) - return True - -def overflow_get(obj): - return _refcount_overflow[objectmodel.current_object_addr_as_int(obj)] - @not_rpython def init(dealloc_trigger_callback=None, tp_traverse=None, pyobj_list=None): @@ -189,8 +143,7 @@ wr_p_list = [] new_p_list = [] for ob in reversed(_p_list): - if ob.c_ob_refcnt & REFCNT_MASK > 0 \ - or ob.c_ob_refcnt & REFCNT_FROM_PYPY == 0: + if ob.c_ob_refcnt not in (REFCNT_FROM_PYPY, REFCNT_FROM_PYPY_LIGHT): new_p_list.append(ob) else: p = detach(ob, wr_p_list) @@ -223,8 +176,7 @@ if ob.c_ob_refcnt >= REFCNT_FROM_PYPY_LIGHT: ob.c_ob_refcnt -= REFCNT_FROM_PYPY_LIGHT ob.c_ob_pypy_link = 0 - if ob.c_ob_refcnt & REFCNT_MASK == 0 \ - and ob.c_ob_refcnt < REFCNT_FROM_PYPY: + if ob.c_ob_refcnt == 0: lltype.free(ob, flavor='raw', track_allocation=track_allocation) else: @@ -232,9 +184,8 @@ assert ob.c_ob_refcnt < int(REFCNT_FROM_PYPY_LIGHT * 0.99) ob.c_ob_refcnt -= REFCNT_FROM_PYPY ob.c_ob_pypy_link = 0 - if ob.c_ob_refcnt & REFCNT_MASK == 0 \ - and ob.c_ob_refcnt < REFCNT_FROM_PYPY: - ob.c_ob_refcnt += 1 + if ob.c_ob_refcnt == 0: + ob.c_ob_refcnt = 1 _d_list.append(ob) return None diff --git a/rpython/rtyper/rclass.py b/rpython/rtyper/rclass.py --- a/rpython/rtyper/rclass.py +++ b/rpython/rtyper/rclass.py @@ -915,6 +915,10 @@ lst.append(str(g)) g = seen.get(g) lst.append('') + # TODO: remove code (see below) to make this check pass + # pypy/module/cpyext/api.py: + # print "start cpyext_call" + # print "end cpyext_call" raise TyperError("the RPython-level __del__() method " "in %r calls:%s" % (graph, '\n\t'.join(lst[::-1]))) _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit