def clear_gcflag_extra(fromlist): pending = fromlist[:] while pending: gcref = pending.pop() if rgc.get_gcflag_extra(gcref): rgc.toggle_gcflag_extra(gcref) pending.extend(rgc.get_rpy_referents(gcref))
def do_get_referrers(w_arg): result_w = [] gcarg = rgc.cast_instance_to_gcref(w_arg) roots = [gcref for gcref in rgc.get_rpy_roots() if gcref] head = PathEntry(None, rgc.NULL_GCREF, roots) while True: head.remaining -= 1 if head.remaining >= 0: gcref = head.referents[head.remaining] if not rgc.get_gcflag_extra(gcref): # not visited so far if gcref == gcarg: w_obj = head.get_most_recent_w_obj() if w_obj is not None: result_w.append(w_obj) # found! rgc.toggle_gcflag_extra(gcref) # toggle twice rgc.toggle_gcflag_extra(gcref) head = PathEntry(head, gcref, rgc.get_rpy_referents(gcref)) else: # no more referents to visit head = head.prev if head is None: break # done. Clear flags carefully rgc.toggle_gcflag_extra(gcarg) rgc.clear_gcflag_extra(roots) rgc.clear_gcflag_extra([gcarg]) return result_w
def _list_w_obj_referents(gcref, result_w): # Get all W_Root reachable directly from gcref, and add them to # the list 'result_w'. pending = [] # = list of all objects whose gcflag was toggled i = 0 gcrefparent = gcref while True: for gcref in rgc.get_rpy_referents(gcrefparent): if rgc.get_gcflag_extra(gcref): continue rgc.toggle_gcflag_extra(gcref) pending.append(gcref) while i < len(pending): gcrefparent = pending[i] i += 1 w_obj = try_cast_gcref_to_w_root(gcrefparent) if w_obj is not None: result_w.append(w_obj) else: break # jump back to the start of the outermost loop else: break # done for gcref in pending: rgc.toggle_gcflag_extra(gcref) # reset the gcflag_extra's
def get_instances_array_gc(interp, w_class=None): space = interp.space from rpython.rlib import rgc result_w = [] roots = [gcref for gcref in rgc.get_rpy_roots() if gcref] pending = roots[:] while pending: gcref = pending.pop() if not rgc.get_gcflag_extra(gcref): rgc.toggle_gcflag_extra(gcref) w_obj = rgc.try_cast_gcref_to_instance(W_Object, gcref) if w_obj is not None and w_obj.has_class(): w_cls = w_obj.getclass(space) if w_cls is not None: # XXX: should not return SmallFloat64 on Spur64... if ((not w_cls.is_same_object(space.w_SmallInteger)) and (not (space.is_spur.is_set() and w_cls.is_same_object(space.w_Character))) and (w_class is None or w_cls.is_same_object(w_class))): result_w.append(w_obj) pending.extend(rgc.get_rpy_referents(gcref)) rgc.clear_gcflag_extra(roots) rgc.assert_no_more_gcflags() return result_w
def do_get_referrers(w_arg): result_w = [] gcarg = rgc.cast_instance_to_gcref(w_arg) roots = [gcref for gcref in rgc.get_rpy_roots() if gcref] head = PathEntry(None, rgc.NULL_GCREF, roots) while True: head.remaining -= 1 if head.remaining >= 0: gcref = head.referents[head.remaining] if not rgc.get_gcflag_extra(gcref): # not visited so far if gcref == gcarg: w_obj = head.get_most_recent_w_obj() if w_obj is not None: result_w.append(w_obj) # found! rgc.toggle_gcflag_extra(gcref) # toggle twice rgc.toggle_gcflag_extra(gcref) head = PathEntry(head, gcref, rgc.get_rpy_referents(gcref)) else: # no more referents to visit head = head.prev if head is None: break # done. Clear flags carefully rgc.toggle_gcflag_extra(gcarg) clear_gcflag_extra(roots) clear_gcflag_extra([gcarg]) return result_w
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 do_get_objects(): roots = [gcref for gcref in rgc.get_rpy_roots() if gcref] pending = roots[:] result_w = [] while pending: gcref = pending.pop() if not rgc.get_gcflag_extra(gcref): rgc.toggle_gcflag_extra(gcref) w_obj = try_cast_gcref_to_w_root(gcref) if w_obj is not None: result_w.append(w_obj) pending.extend(rgc.get_rpy_referents(gcref)) clear_gcflag_extra(roots) return result_w
def method_each_object(self, space, w_mod, block): match_w = [] roots = [gcref for gcref in rgc.get_rpy_roots() if gcref] pending = roots[:] while pending: gcref = pending.pop() if not rgc.get_gcflag_extra(gcref): rgc.toggle_gcflag_extra(gcref) w_obj = try_cast_gcref_to_w_baseobject(gcref) if w_obj is not None and space.is_kind_of(w_obj, w_mod): match_w.append(w_obj) pending.extend(rgc.get_rpy_referents(gcref)) clear_gcflag_extra(roots) for w_obj in match_w: space.invoke_block(block, [w_obj])
def getMonteObjects(): roots = [gcref for gcref in rgc.get_rpy_roots() if gcref] pending = roots[:] result_w = [] while pending: gcref = pending.pop() if not rgc.get_gcflag_extra(gcref): rgc.toggle_gcflag_extra(gcref) w_obj = rgc.try_cast_gcref_to_instance(Object, gcref) if w_obj is not None: result_w.append(w_obj) pending.extend(rgc.get_rpy_referents(gcref)) clear_gcflag_extra(roots) rgc.assert_no_more_gcflags() return result_w
def method_each_object(self, space, w_mod, block): if block is None: return space.send(self, "enum_for", [space.newsymbol("each_object"), w_mod], block) match_w = [] roots = [gcref for gcref in rgc.get_rpy_roots() if gcref] pending = roots[:] while pending: gcref = pending.pop() if not rgc.get_gcflag_extra(gcref): rgc.toggle_gcflag_extra(gcref) w_obj = try_cast_gcref_to_w_baseobject(gcref) if w_obj is not None and space.is_kind_of(w_obj, w_mod): match_w.append(w_obj) pending.extend(rgc.get_rpy_referents(gcref)) clear_gcflag_extra(roots) for w_obj in match_w: space.invoke_block(block, [w_obj]) return space.newint(len(match_w))
def clear_gcflag_extra(pending): while pending: gcref = pending.pop() if rgc.get_gcflag_extra(gcref): rgc.toggle_gcflag_extra(gcref) pending.extend(rgc.get_rpy_referents(gcref))