def get_rpy_referents(space, w_obj): """Return a list of all the referents, as reported by the GC. This is likely to contain a lot of GcRefs.""" gcref = unwrap(space, w_obj) lst = rgc.get_rpy_referents(gcref) if lst is None: raise missing_operation(space) return space.newlist([wrap(space, gcref) for gcref in lst])
def test_get_referents(): class X(object): __slots__ = ['stuff'] x1 = X() x1.stuff = X() x2 = X() lst = rgc.get_rpy_referents(rgc.cast_instance_to_gcref(x1)) lst2 = [rgc.try_cast_gcref_to_instance(X, x) for x in lst] assert x1.stuff in lst2 assert x2 not in lst2
def fn(): s = lltype.malloc(S) s.u = lltype.malloc(U) gcref1 = lltype.cast_opaque_ptr(llmemory.GCREF, s) gcref2 = lltype.cast_opaque_ptr(llmemory.GCREF, s.u) lst = rgc.get_rpy_referents(gcref1) assert gcref2 in lst assert gcref1 not in lst s.u.x = 42 return 0
def _list_w_obj_referents(gcref, result_w): # Get all W_Root reachable directly from gcref, and add them to # the list 'result_w'. The logic here is not robust against gc # moves, and may return the same object several times. seen = {} # map {current_addr: obj} pending = [gcref] i = 0 while i < len(pending): gcrefparent = pending[i] i += 1 for gcref in rgc.get_rpy_referents(gcrefparent): key = rgc.cast_gcref_to_int(gcref) if gcref == seen.get(key, rgc.NULL_GCREF): continue # already in 'seen' seen[key] = gcref w_obj = try_cast_gcref_to_w_root(gcref) if w_obj is not None: result_w.append(w_obj) else: pending.append(gcref)