def __init__(self, cfunc, callback): self.cfunc = cfunc self.callback = callback pointer = rffi.cast(rffi.VOIDP, clibffi.closureHeap.alloc()) if cfunc.notready: cfunc.prepare_cif() cfunc.notready = False Mem.__init__(self, cfunc, pointer) closure_ptr = rffi.cast(clibffi.FFI_CLOSUREP, self.pointer) # hide the object gcref = rgc.cast_instance_to_gcref(self) raw = rgc.hide_nonmovable_gcref(gcref) unique_id = rffi.cast(rffi.VOIDP, raw) res = clibffi.c_ffi_prep_closure(closure_ptr, cfunc.cif.cif, invoke_callback, unique_id) if rffi.cast(lltype.Signed, res) != clibffi.FFI_OK: raise unwind(LError(u"libffi failed to build this callback")) if closure_ptr.c_user_data != unique_id: raise unwind(LError(u"ffi_prep_closure(): bad user_data")) # The function might be called in separate thread, # so allocate GIL here, just in case. rgil.allocate()
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 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 test_get_memory_usage(): class X(object): pass x1 = X() n = rgc.get_rpy_memory_usage(rgc.cast_instance_to_gcref(x1)) assert n >= 8 and n <= 64
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) gcref1 = lltype.cast_opaque_ptr(llmemory.GCREF, s) check(gcref1, False) f = Foo() gcref3 = rgc.cast_instance_to_gcref(f) check(gcref3, True) return 0
def _newp_handle(space, w_ctype, w_x): # Allocate a handle as a nonmovable W_CDataHandle instance, which # we can cast to a plain CCHARP. As long as the object is not freed, # we can cast the CCHARP back to a W_CDataHandle with reveal_gcref(). new_cdataobj = objectmodel.instantiate(cdataobj.W_CDataHandle, nonmovable=True) gcref = rgc.cast_instance_to_gcref(new_cdataobj) _cdata = rgc.hide_nonmovable_gcref(gcref) _cdata = rffi.cast(rffi.CCHARP, _cdata) cdataobj.W_CDataHandle.__init__(new_cdataobj, space, _cdata, w_ctype, w_x) return new_cdataobj
def get_referents(space, args_w): """Return a list of objects directly referred to by any of the arguments. """ if not rgc.has_gcflag_extra(): raise missing_operation(space) result_w = [] for w_obj in args_w: gcref = rgc.cast_instance_to_gcref(w_obj) _list_w_obj_referents(gcref, result_w) rgc.assert_no_more_gcflags() return space.newlist(result_w)
def fn(): foo = Foo() gcref1 = rgc.cast_instance_to_gcref(foo) assert rgc.try_cast_gcref_to_instance(Foo, gcref1) is foo assert rgc.try_cast_gcref_to_instance(FooBar, gcref1) is None assert rgc.try_cast_gcref_to_instance(Biz, gcref1) is None foobar = FooBar() gcref2 = rgc.cast_instance_to_gcref(foobar) assert rgc.try_cast_gcref_to_instance(Foo, gcref2) is foobar assert rgc.try_cast_gcref_to_instance(FooBar, gcref2) is foobar assert rgc.try_cast_gcref_to_instance(Biz, gcref2) is None s = lltype.malloc(S) gcref3 = lltype.cast_opaque_ptr(llmemory.GCREF, s) assert rgc.try_cast_gcref_to_instance(Foo, gcref3) is None assert rgc.try_cast_gcref_to_instance(FooBar, gcref3) is None assert rgc.try_cast_gcref_to_instance(Biz, gcref3) is None return 0
def _newp_handle(space, w_ctype, w_x): # Allocate a handle as a nonmovable W_CDataHandle instance, which # we can cast to a plain CCHARP. As long as the object is not freed, # we can cast the CCHARP back to a W_CDataHandle with reveal_gcref(). new_cdataobj = objectmodel.instantiate(cdataobj.W_CDataHandle, nonmovable=True) gcref = rgc.cast_instance_to_gcref(new_cdataobj) _cdata = rgc.hide_nonmovable_gcref(gcref) _cdata = rffi.cast(rffi.CCHARP, _cdata) cdataobj.W_CDataHandle.__init__(new_cdataobj, space, _cdata, w_ctype, w_x) return new_cdataobj
def get_referents(space, args_w): """Return a list of objects directly referred to by any of the arguments. """ if not rgc.has_gcflag_extra(): raise missing_operation(space) result_w = [] for w_obj in args_w: gcref = rgc.cast_instance_to_gcref(w_obj) _list_w_obj_referents(gcref, result_w) rgc.assert_no_more_gcflags() return space.newlist(result_w)
def get_referrers(space, args_w): """Return the list of objects that directly refer to any of objs.""" if not rgc.has_gcflag_extra(): raise missing_operation(space) # xxx uses a lot of memory to make the list of all W_Root objects, # but it's simpler this way and more correct than the previous # version of this code (issue #2612). It is potentially very slow # because each of the n calls to _list_w_obj_referents() could take # O(n) time as well, in theory, but I hope in practice the whole # thing takes much less than O(n^2). We could re-add an algorithm # that visits most objects only once, if needed... all_objects_w = rgc.do_get_objects(try_cast_gcref_to_w_root) result_w = [] for w_obj in all_objects_w: refs_w = [] gcref = rgc.cast_instance_to_gcref(w_obj) _list_w_obj_referents(gcref, refs_w) for w_arg in args_w: if w_arg in refs_w: result_w.append(w_obj) rgc.assert_no_more_gcflags() return space.newlist(result_w)
def hide_object(PTR, obj): gcref = rgc.cast_instance_to_gcref(obj) raw = rgc.hide_nonmovable_gcref(gcref) return rffi.cast(PTR, raw)
def test_get_memory_usage(): class X(object): pass x1 = X() n = rgc.get_rpy_memory_usage(rgc.cast_instance_to_gcref(x1)) assert n >= 8 and n <= 64
def hide_object(self): gcref = rgc.cast_instance_to_gcref(self) raw = rgc.hide_nonmovable_gcref(gcref) return rffi.cast(rffi.VOIDP, raw)
def hide_object(self): gcref = rgc.cast_instance_to_gcref(self) raw = rgc.hide_nonmovable_gcref(gcref) return rffi.cast(rffi.VOIDP, raw)
def unwrap(space, w_obj): if isinstance(w_obj, W_GcRef): gcref = w_obj.gcref else: gcref = rgc.cast_instance_to_gcref(w_obj) return gcref
def unwrap(space, w_obj): if isinstance(w_obj, W_GcRef): gcref = w_obj.gcref else: gcref = rgc.cast_instance_to_gcref(w_obj) return gcref