def entry_point(argv): ll_dealloc_trigger_callback = llhelper(FTYPE, dealloc_trigger) rawrefcount.init(ll_dealloc_trigger_callback) ob, p = make_p() if state.seen != []: print "OB COLLECTED REALLY TOO SOON" return 1 rgc.collect() if state.seen != []: print "OB COLLECTED TOO SOON" return 1 objectmodel.keepalive_until_here(p) p = None rgc.collect() if state.seen != [1]: print "OB NOT COLLECTED" return 1 if rawrefcount.next_dead(PyObject) != ob: print "NEXT_DEAD != OB" return 1 if rawrefcount.next_dead(PyObject) != lltype.nullptr(PyObjectS): print "NEXT_DEAD second time != NULL" return 1 if rawrefcount.to_obj(W_Root, ob) is not None: print "to_obj(dead) is not None?" return 1 rawrefcount.mark_deallocating(w_marker, ob) if rawrefcount.to_obj(W_Root, ob) is not w_marker: print "to_obj(marked-dead) is not w_marker" return 1 print "OK!" lltype.free(ob, flavor='raw') return 0
def test_mark_deallocating(self): ob = lltype.malloc(PyObjectS, flavor='raw', zero=True) w_marker = W_Root(42) rawrefcount.mark_deallocating(w_marker, ob) assert rawrefcount.to_obj(W_Root, ob) is w_marker rawrefcount._collect() assert rawrefcount.to_obj(W_Root, ob) is w_marker lltype.free(ob, flavor='raw')
def test_mark_deallocating(self): ob = lltype.malloc(PyObjectS, flavor='raw', zero=True) w_marker = W_Root(42) rawrefcount.mark_deallocating(w_marker, ob) assert rawrefcount.to_obj(W_Root, ob) is w_marker rawrefcount._collect() assert rawrefcount.to_obj(W_Root, ob) is w_marker lltype.free(ob, flavor='raw')
def test_create_link_pyobj(self): p = W_Root(42) ob = lltype.malloc(PyObjectS, flavor='raw', zero=True) assert rawrefcount.from_obj(PyObject, p) == lltype.nullptr(PyObjectS) assert rawrefcount.to_obj(W_Root, ob) == None rawrefcount.create_link_pyobj(p, ob) assert ob.c_ob_refcnt == 0 ob.c_ob_refcnt += REFCNT_FROM_PYPY assert rawrefcount.from_obj(PyObject, p) == lltype.nullptr(PyObjectS) assert rawrefcount.to_obj(W_Root, ob) == p lltype.free(ob, flavor='raw')
def test_create_link_pyobj(self): p = W_Root(42) ob = lltype.malloc(PyObjectS, flavor='raw', zero=True) assert rawrefcount.from_obj(PyObject, p) == lltype.nullptr(PyObjectS) assert rawrefcount.to_obj(W_Root, ob) == None rawrefcount.create_link_pyobj(p, ob) assert ob.c_ob_refcnt == 0 ob.c_ob_refcnt += REFCNT_FROM_PYPY assert rawrefcount.from_obj(PyObject, p) == lltype.nullptr(PyObjectS) assert rawrefcount.to_obj(W_Root, ob) == p lltype.free(ob, flavor='raw')
def main(argv): rawrefcount.create_link_pypy(w1, ob1) w = None ob = lltype.nullptr(PyObjectS) oblist = [] for op in argv[1:]: revdb.stop_point() w = W_Root(42) ob = lltype.malloc(PyObjectS, flavor='raw', zero=True) ob.c_ob_refcnt = rawrefcount.REFCNT_FROM_PYPY rawrefcount.create_link_pypy(w, ob) oblist.append(ob) del oblist[-1] # rgc.collect() assert rawrefcount.from_obj(PyObject, w) == ob assert rawrefcount.to_obj(W_Root, ob) == w while True: ob = rawrefcount.next_dead(PyObject) if not ob: break assert ob in oblist oblist.remove(ob) objectmodel.keepalive_until_here(w) revdb.stop_point() return 9
def make_p(): p = W_Root(42) ob = lltype.malloc(PyObjectS, flavor='raw', zero=True) rawrefcount.create_link_pypy(p, ob) ob.c_ob_refcnt += REFCNT_FROM_PYPY assert rawrefcount.from_obj(PyObject, p) == ob assert rawrefcount.to_obj(W_Root, ob) == p return ob, p
def make_p(): p = W_Root(42) ob = lltype.malloc(PyObjectS, flavor='raw', zero=True) rawrefcount.create_link_pypy(p, ob) ob.c_ob_refcnt += REFCNT_FROM_PYPY assert rawrefcount.from_obj(PyObject, p) == ob assert rawrefcount.to_obj(W_Root, ob) == p return ob, p
def entry_point(argv): ll_dealloc_trigger_callback = llhelper(FTYPE, dealloc_trigger) rawrefcount.init(ll_dealloc_trigger_callback) ob, p = make_p() if state.seen != []: print "OB COLLECTED REALLY TOO SOON" return 1 rgc.collect() if state.seen != []: print "OB COLLECTED TOO SOON" return 1 objectmodel.keepalive_until_here(p) p = None rgc.collect() if state.seen != [1]: print "OB NOT COLLECTED" return 1 if rawrefcount.next_dead(PyObject) != ob: print "NEXT_DEAD != OB" return 1 if ob.c_ob_refcnt != 1: print "next_dead().ob_refcnt != 1" return 1 if rawrefcount.next_dead(PyObject) != lltype.nullptr(PyObjectS): print "NEXT_DEAD second time != NULL" return 1 if rawrefcount.to_obj(W_Root, ob) is not None: print "to_obj(dead) is not None?" return 1 rawrefcount.mark_deallocating(w_marker, ob) if rawrefcount.to_obj(W_Root, ob) is not w_marker: print "to_obj(marked-dead) is not w_marker" return 1 print "OK!" lltype.free(ob, flavor='raw') return 0
def test_collect_p_keepalive_w_root(self): p = W_Root(42) ob = lltype.malloc(PyObjectS, flavor='raw', zero=True) rawrefcount.create_link_pypy(p, ob) ob.c_ob_refcnt += REFCNT_FROM_PYPY_LIGHT assert rawrefcount._p_list == [ob] wr_ob = weakref.ref(ob) del ob # p remains rawrefcount._collect() ob = wr_ob() assert ob is not None assert rawrefcount._p_list == [ob] assert rawrefcount.to_obj(W_Root, ob) == p assert rawrefcount.from_obj(PyObject, p) == ob lltype.free(ob, flavor='raw')
def test_collect_p_keepalive_w_root(self): p = W_Root(42) ob = lltype.malloc(PyObjectS, flavor='raw', zero=True) rawrefcount.create_link_pypy(p, ob) ob.c_ob_refcnt += REFCNT_FROM_PYPY_LIGHT assert rawrefcount._p_list == [ob] wr_ob = weakref.ref(ob) del ob # p remains rawrefcount._collect() ob = wr_ob() assert ob is not None assert rawrefcount._p_list == [ob] assert rawrefcount.to_obj(W_Root, ob) == p assert rawrefcount.from_obj(PyObject, p) == ob lltype.free(ob, flavor='raw')
def _type_realize(space, py_obj): """ Creates an interpreter type from a PyTypeObject structure. """ # missing: # unsupported: # tp_mro, tp_subclasses py_type = rffi.cast(PyTypeObjectPtr, py_obj) if not py_type.c_tp_base: # borrowed reference, but w_object is unlikely to disappear base = as_pyobj(space, space.w_object) py_type.c_tp_base = rffi.cast(PyTypeObjectPtr, base) finish_type_1(space, py_type) if py_type.c_ob_type: w_metatype = from_ref(space, rffi.cast(PyObject, py_type.c_ob_type)) else: # Somehow the tp_base type is created with no ob_type, notably # PyString_Type and PyBaseString_Type # While this is a hack, cpython does it as well. w_metatype = space.w_type w_obj = rawrefcount.to_obj(W_PyCTypeObject, py_obj) if w_obj is None: w_obj = space.allocate_instance(W_PyCTypeObject, w_metatype) track_reference(space, py_obj, w_obj) # __init__ wraps all slotdefs functions from py_type via add_operators w_obj.__init__(space, py_type) w_obj.ready() finish_type_2(space, py_type, w_obj) base = py_type.c_tp_base if base: # XXX refactor - parts of this are done in finish_type_2 -> inherit_slots if not py_type.c_tp_as_number: py_type.c_tp_as_number = base.c_tp_as_number py_type.c_tp_flags |= base.c_tp_flags & Py_TPFLAGS_CHECKTYPES py_type.c_tp_flags |= base.c_tp_flags & Py_TPFLAGS_HAVE_INPLACEOPS if not py_type.c_tp_as_sequence: py_type.c_tp_as_sequence = base.c_tp_as_sequence py_type.c_tp_flags |= base.c_tp_flags & Py_TPFLAGS_HAVE_INPLACEOPS if not py_type.c_tp_as_mapping: py_type.c_tp_as_mapping = base.c_tp_as_mapping #if not py_type.c_tp_as_buffer: py_type.c_tp_as_buffer = base.c_tp_as_buffer return w_obj
def test_collect_o_keepalive_w_root(self): p = W_Root(42) ob = lltype.malloc(PyObjectS, flavor="raw", zero=True) p.pyobj = ob rawrefcount.create_link_pyobj(p, ob) ob.c_ob_refcnt += REFCNT_FROM_PYPY assert rawrefcount._o_list == [ob] wr_ob = weakref.ref(ob) del ob # p remains rawrefcount._collect() ob = wr_ob() assert ob is not None assert rawrefcount._o_list == [ob] assert rawrefcount.to_obj(W_Root, ob) == p assert p.pyobj == ob lltype.free(ob, flavor="raw")
def test_collect_o_keepalive_pyobject(self): p = W_Root(42) ob = lltype.malloc(PyObjectS, flavor='raw', zero=True) p.pyobj = ob rawrefcount.create_link_pyobj(p, ob) ob.c_ob_refcnt += REFCNT_FROM_PYPY assert rawrefcount._o_list == [ob] wr_ob = weakref.ref(ob) wr_p = weakref.ref(p) ob.c_ob_refcnt += 1 # <= del p rawrefcount._collect() p = wr_p() assert p is None # was unlinked assert ob.c_ob_refcnt == 1 # != REFCNT_FROM_PYPY_OBJECT + 1 assert rawrefcount._o_list == [] assert rawrefcount.to_obj(W_Root, ob) == None lltype.free(ob, flavor='raw')
def test_collect_o_keepalive_pyobject(self): p = W_Root(42) ob = lltype.malloc(PyObjectS, flavor='raw', zero=True) p.pyobj = ob rawrefcount.create_link_pyobj(p, ob) ob.c_ob_refcnt += REFCNT_FROM_PYPY assert rawrefcount._o_list == [ob] wr_ob = weakref.ref(ob) wr_p = weakref.ref(p) ob.c_ob_refcnt += 1 # <= del p rawrefcount._collect() p = wr_p() assert p is None # was unlinked assert ob.c_ob_refcnt == 1 # != REFCNT_FROM_PYPY_OBJECT + 1 assert rawrefcount._o_list == [] assert rawrefcount.to_obj(W_Root, ob) == None lltype.free(ob, flavor='raw')
def test_collect_s_keepalive_pyobject(self): p = W_Root(42) ob = lltype.malloc(PyObjectS, flavor='raw', zero=True) p.pyobj = ob rawrefcount.create_link_pypy(p, ob) ob.c_ob_refcnt += REFCNT_FROM_PYPY assert rawrefcount._p_list == [ob] wr_ob = weakref.ref(ob) wr_p = weakref.ref(p) ob.c_ob_refcnt += 1 # <= del ob, p rawrefcount._collect() ob = wr_ob() p = wr_p() assert ob is not None and p is not None assert rawrefcount._p_list == [ob] assert rawrefcount.to_obj(W_Root, ob) == p lltype.free(ob, flavor='raw')
def test_collect_s_keepalive_pyobject(self): p = W_Root(42) ob = lltype.malloc(PyObjectS, flavor='raw', zero=True) p.pyobj = ob rawrefcount.create_link_pypy(p, ob) ob.c_ob_refcnt += REFCNT_FROM_PYPY assert rawrefcount._p_list == [ob] wr_ob = weakref.ref(ob) wr_p = weakref.ref(p) ob.c_ob_refcnt += 1 # <= del ob, p rawrefcount._collect() ob = wr_ob() p = wr_p() assert ob is not None and p is not None assert rawrefcount._p_list == [ob] assert rawrefcount.to_obj(W_Root, ob) == p lltype.free(ob, flavor='raw')
def from_ref(space, ref): """ Finds the interpreter object corresponding to the given reference. If the object is not yet realized (see bytesobject.py), creates it. """ assert is_pyobj(ref) if not ref: return None w_obj = rawrefcount.to_obj(W_Root, ref) if w_obj is not None: return w_obj # This reference is not yet a real interpreter object. # Realize it. ref_type = rffi.cast(PyObject, ref.c_ob_type) if ref_type == ref: # recursion! raise InvalidPointerException(str(ref)) w_type = from_ref(space, ref_type) assert isinstance(w_type, W_TypeObject) return get_typedescr(w_type.layout.typedef).realize(space, ref)
def from_ref(space, ref): """ Finds the interpreter object corresponding to the given reference. If the object is not yet realized (see bytesobject.py), creates it. """ assert is_pyobj(ref) if not ref: return None w_obj = rawrefcount.to_obj(W_Root, ref) if w_obj is not None: return w_obj # This reference is not yet a real interpreter object. # Realize it. ref_type = rffi.cast(PyObject, ref.c_ob_type) if ref_type == ref: # recursion! raise InvalidPointerException(str(ref)) w_type = from_ref(space, ref_type) assert isinstance(w_type, W_TypeObject) return get_typedescr(w_type.layout.typedef).realize(space, ref)
def from_ref(space, ref): """ Finds the interpreter object corresponding to the given reference. If the object is not yet realized (see bytesobject.py), creates it. """ assert is_pyobj(ref) if not ref: return None w_obj = rawrefcount.to_obj(W_Root, ref) if w_obj is not None: if w_obj is not w_marker_deallocating: return w_obj type_name = rffi.charp2str(cts.cast('char*', ref.c_ob_type.c_tp_name)) fatalerror( "*** Invalid usage of a dying CPython object ***\n" "\n" "cpyext, the emulation layer, detected that while it is calling\n" "an object's tp_dealloc, the C code calls back a function that\n" "tries to recreate the PyPy version of the object. Usually it\n" "means that tp_dealloc calls some general PyXxx() API. It is\n" "a dangerous and potentially buggy thing to do: even in CPython\n" "the PyXxx() function could, in theory, cause a reference to the\n" "object to be taken and stored somewhere, for an amount of time\n" "exceeding tp_dealloc itself. Afterwards, the object will be\n" "freed, making that reference point to garbage.\n" ">>> PyPy could contain some workaround to still work if\n" "you are lucky, but it is not done so far; better fix the bug in\n" "the CPython extension.\n" ">>> This object is of type '%s'" % (type_name, )) # This reference is not yet a real interpreter object. # Realize it. ref_type = rffi.cast(PyObject, ref.c_ob_type) if ref_type == ref: # recursion! raise InvalidPointerException(str(ref)) w_type = from_ref(space, ref_type) assert isinstance(w_type, W_TypeObject) return get_typedescr(w_type.layout.typedef).realize(space, ref)
def from_ref(space, ref): """ Finds the interpreter object corresponding to the given reference. If the object is not yet realized (see bytesobject.py), creates it. """ assert is_pyobj(ref) if not ref: return None w_obj = rawrefcount.to_obj(W_Root, ref) if w_obj is not None: if w_obj is not w_marker_deallocating: return w_obj fatalerror( "*** Invalid usage of a dying CPython object ***\n" "\n" "cpyext, the emulation layer, detected that while it is calling\n" "an object's tp_dealloc, the C code calls back a function that\n" "tries to recreate the PyPy version of the object. Usually it\n" "means that tp_dealloc calls some general PyXxx() API. It is\n" "a dangerous and potentially buggy thing to do: even in CPython\n" "the PyXxx() function could, in theory, cause a reference to the\n" "object to be taken and stored somewhere, for an amount of time\n" "exceeding tp_dealloc itself. Afterwards, the object will be\n" "freed, making that reference point to garbage.\n" ">>> PyPy could contain some workaround to still work if\n" "you are lucky, but it is not done so far; better fix the bug in\n" "the CPython extension.") # This reference is not yet a real interpreter object. # Realize it. ref_type = rffi.cast(PyObject, ref.c_ob_type) if ref_type == ref: # recursion! raise InvalidPointerException(str(ref)) w_type = from_ref(space, ref_type) assert isinstance(w_type, W_TypeObject) return get_typedescr(w_type.layout.typedef).realize(space, ref)
def pyobj_has_w_obj(pyobj): return rawrefcount.to_obj(W_Root, pyobj) is not None
def pyobj_has_w_obj(pyobj): return rawrefcount.to_obj(W_Root, pyobj) is not None
def pyobj_has_w_obj(pyobj): w_obj = rawrefcount.to_obj(W_Root, pyobj) return w_obj is not None and w_obj is not w_marker_deallocating
def pyobj_has_w_obj(pyobj): w_obj = rawrefcount.to_obj(W_Root, pyobj) return w_obj is not None and w_obj is not w_marker_deallocating