def test_del_basic(): for gcpolicy in ["ref"]: #, "framework"]: S = lltype.GcStruct('S', ('x', lltype.Signed)) TRASH = lltype.GcStruct('TRASH', ('x', lltype.Signed)) lltype.attachRuntimeTypeInfo(S) GLOBAL = lltype.Struct('GLOBAL', ('x', lltype.Signed)) glob = lltype.malloc(GLOBAL, immortal=True) def destructor(s): glob.x = s.x + 1 def type_info_S(s): return lltype.getRuntimeTypeInfo(S) def g(n): s = lltype.malloc(S) s.x = n # now 's' should go away def entrypoint(n): g(n) # llop.gc__collect(lltype.Void) return glob.x t = TranslationContext() t.buildannotator().build_types(entrypoint, [int]) rtyper = t.buildrtyper() destrptr = rtyper.annotate_helper_fn(destructor, [lltype.Ptr(S)]) rtyper.attachRuntimeTypeInfoFunc(S, type_info_S, destrptr=destrptr) rtyper.specialize() fn = compile_func(entrypoint, None, t, gcpolicy=gcpolicy) res = fn(123) assert res == 124
def define_custom_trace(cls): from pypy.rpython.annlowlevel import llhelper from pypy.rpython.lltypesystem import llmemory # S = lltype.GcStruct('S', ('x', llmemory.Address), rtti=True) T = lltype.GcStruct('T', ('z', lltype.Signed)) offset_of_x = llmemory.offsetof(S, 'x') def customtrace(obj, prev): if not prev: return obj + offset_of_x else: return llmemory.NULL CUSTOMTRACEFUNC = lltype.FuncType([llmemory.Address, llmemory.Address], llmemory.Address) customtraceptr = llhelper(lltype.Ptr(CUSTOMTRACEFUNC), customtrace) lltype.attachRuntimeTypeInfo(S, customtraceptr=customtraceptr) # def setup(): s1 = lltype.malloc(S) tx = lltype.malloc(T) tx.z = 4243 s1.x = llmemory.cast_ptr_to_adr(tx) return s1 def f(): s1 = setup() llop.gc__collect(lltype.Void) return llmemory.cast_adr_to_ptr(s1.x, lltype.Ptr(T)).z return f
def test_del_basic(): for gcpolicy in ["ref"]: #, "framework"]: S = lltype.GcStruct('S', ('x', lltype.Signed)) TRASH = lltype.GcStruct('TRASH', ('x', lltype.Signed)) lltype.attachRuntimeTypeInfo(S) GLOBAL = lltype.Struct('GLOBAL', ('x', lltype.Signed)) glob = lltype.malloc(GLOBAL, immortal=True) def destructor(s): glob.x = s.x + 1 def type_info_S(s): return lltype.getRuntimeTypeInfo(S) def g(n): s = lltype.malloc(S) s.x = n # now 's' should go away def entrypoint(n): g(n) # llop.gc__collect(lltype.Void) return glob.x t = TranslationContext() t.buildannotator().build_types(entrypoint, [int]) rtyper = t.buildrtyper() destrptr = rtyper.annotate_helper_fn(destructor, [lltype.Ptr(S)]) rtyper.attachRuntimeTypeInfoFunc(S, type_info_S, destrptr=destrptr) rtyper.specialize() fn = compile_func(entrypoint, None, t, gcpolicy=gcpolicy) res = fn(123) assert res == 124
def define_custom_trace(cls): from pypy.rpython.annlowlevel import llhelper from pypy.rpython.lltypesystem import llmemory # S = lltype.GcStruct('S', ('x', llmemory.Address), rtti=True) T = lltype.GcStruct('T', ('z', lltype.Signed)) offset_of_x = llmemory.offsetof(S, 'x') def customtrace(obj, prev): if not prev: return obj + offset_of_x else: return llmemory.NULL CUSTOMTRACEFUNC = lltype.FuncType([llmemory.Address, llmemory.Address], llmemory.Address) customtraceptr = llhelper(lltype.Ptr(CUSTOMTRACEFUNC), customtrace) lltype.attachRuntimeTypeInfo(S, customtraceptr=customtraceptr) # def setup(): s1 = lltype.malloc(S) tx = lltype.malloc(T) tx.z = 4243 s1.x = llmemory.cast_ptr_to_adr(tx) return s1 def f(): s1 = setup() llop.gc__collect(lltype.Void) return llmemory.cast_adr_to_ptr(s1.x, lltype.Ptr(T)).z return f
def get_shadowstackref(gctransformer): if hasattr(gctransformer, '_SHADOWSTACKREF'): return gctransformer._SHADOWSTACKREF SHADOWSTACKREFPTR = lltype.Ptr(lltype.GcForwardReference()) SHADOWSTACKREF = lltype.GcStruct('ShadowStackRef', ('base', llmemory.Address), ('top', llmemory.Address), ('context', llmemory.Address), #('fullstack', lltype.Bool), rtti=True) SHADOWSTACKREFPTR.TO.become(SHADOWSTACKREF) gc = gctransformer.gcdata.gc root_iterator = get_root_iterator(gctransformer) def customtrace(obj, prev): obj = llmemory.cast_adr_to_ptr(obj, SHADOWSTACKREFPTR) if not prev: root_iterator.setcontext(obj.context) prev = obj.top return root_iterator.nextleft(gc, obj.base, prev) CUSTOMTRACEFUNC = lltype.FuncType([llmemory.Address, llmemory.Address], llmemory.Address) customtraceptr = llhelper(lltype.Ptr(CUSTOMTRACEFUNC), customtrace) lltype.attachRuntimeTypeInfo(SHADOWSTACKREF, customtraceptr=customtraceptr) gctransformer._SHADOWSTACKREF = SHADOWSTACKREF return SHADOWSTACKREF
def define_custom_trace(cls): from pypy.rpython.annlowlevel import llhelper from pypy.rpython.lltypesystem import llmemory # S = lltype.GcStruct('S', ('x', llmemory.Address), rtti=True) offset_of_x = llmemory.offsetof(S, 'x') def customtrace(obj, prev): if not prev: return obj + offset_of_x else: return llmemory.NULL CUSTOMTRACEFUNC = lltype.FuncType([llmemory.Address, llmemory.Address], llmemory.Address) customtraceptr = llhelper(lltype.Ptr(CUSTOMTRACEFUNC), customtrace) lltype.attachRuntimeTypeInfo(S, customtraceptr=customtraceptr) # def setup(): s = lltype.nullptr(S) for i in range(10000): t = lltype.malloc(S) t.x = llmemory.cast_ptr_to_adr(s) s = t return s def measure_length(s): res = 0 while s: res += 1 s = llmemory.cast_adr_to_ptr(s.x, lltype.Ptr(S)) return res def f(n): s1 = setup() llop.gc__collect(lltype.Void) return measure_length(s1) return f
def _setup_repr(self, llfields=None, hints=None, adtmeths=None): # NOTE: don't store mutable objects like the dicts below on 'self' # before they are fully built, to avoid strange bugs in case # of recursion where other code would uses these # partially-initialized dicts. self.rclass = getclassrepr(self.rtyper, self.classdef) fields = {} allinstancefields = {} if self.classdef is None: fields['__class__'] = 'typeptr', get_type_repr(self.rtyper) else: # instance attributes if llfields is None: llfields = [] attrs = self.classdef.attrs.items() attrs.sort() for name, attrdef in attrs: if not attrdef.readonly: r = self.rtyper.getrepr(attrdef.s_value) mangled_name = 'inst_' + name fields[name] = mangled_name, r llfields.append((mangled_name, r.lowleveltype)) # # hash() support if self.rtyper.needs_hash_support(self.classdef): from pypy.rpython import rint fields['_hash_cache_'] = 'hash_cache', rint.signed_repr llfields.append(('hash_cache', Signed)) self.rbase = getinstancerepr(self.rtyper, self.classdef.basedef, self.gcflavor) self.rbase.setup() # # PyObject wrapper support if self.has_wrapper and '_wrapper_' not in self.rbase.allinstancefields: fields['_wrapper_'] = 'wrapper', pyobj_repr llfields.append(('wrapper', Ptr(PyObject))) MkStruct = lltype.STRUCT_BY_FLAVOR[LLFLAVOR[self.gcflavor]] if adtmeths is None: adtmeths = {} if hints is None: hints = {} if '_immutable_' in self.classdef.classdesc.classdict: hints = hints.copy() hints['immutable'] = True object_type = MkStruct(self.classdef.name, ('super', self.rbase.object_type), hints=hints, adtmeths=adtmeths, *llfields) self.object_type.become(object_type) allinstancefields.update(self.rbase.allinstancefields) allinstancefields.update(fields) self.fields = fields self.allinstancefields = allinstancefields if self.gcflavor in RTTIFLAVORS: attachRuntimeTypeInfo(self.object_type)
def test_caching_dynamic_deallocator(): S = lltype.GcStruct("S", ('x', lltype.Signed), rtti=True) S1 = lltype.GcStruct("S1", ('s', S), ('y', lltype.Signed), rtti=True) T = lltype.GcStruct("T", ('x', lltype.Signed), rtti=True) def f_S(s): s.x = 1 def f_S1(s1): s1.s.x = 1 s1.y = 2 def f_T(s): s.x = 1 def type_info_S(p): return lltype.getRuntimeTypeInfo(S) def type_info_T(p): return lltype.getRuntimeTypeInfo(T) qp = lltype.functionptr(lltype.FuncType([lltype.Ptr(S)], lltype.Ptr( lltype.RuntimeTypeInfo)), "type_info_S", _callable=type_info_S) dp = lltype.functionptr(lltype.FuncType([lltype.Ptr(S)], lltype.Void), "destructor_funcptr", _callable=f_S) pinf = lltype.attachRuntimeTypeInfo(S, qp, destrptr=dp) dp = lltype.functionptr(lltype.FuncType([lltype.Ptr(S)], lltype.Void), "destructor_funcptr", _callable=f_S1) pinf = lltype.attachRuntimeTypeInfo(S1, qp, destrptr=dp) qp = lltype.functionptr(lltype.FuncType([lltype.Ptr(T)], lltype.Ptr( lltype.RuntimeTypeInfo)), "type_info_S", _callable=type_info_T) dp = lltype.functionptr(lltype.FuncType([lltype.Ptr(T)], lltype.Void), "destructor_funcptr", _callable=f_T) pinf = lltype.attachRuntimeTypeInfo(T, qp, destrptr=dp) def f(): pass t = TranslationContext() t.buildannotator().build_types(f, []) t.buildrtyper().specialize() transformer = RefcountingGCTransformer(t) p_S = transformer.dynamic_deallocation_funcptr_for_type(S) p_S1 = transformer.dynamic_deallocation_funcptr_for_type(S1) p_T = transformer.dynamic_deallocation_funcptr_for_type(T) assert p_S is not p_T assert p_S is p_S1
def _setup_repr(self, llfields=None, hints=None, adtmeths=None): # NOTE: don't store mutable objects like the dicts below on 'self' # before they are fully built, to avoid strange bugs in case # of recursion where other code would uses these # partially-initialized dicts. self.rclass = getclassrepr(self.rtyper, self.classdef) fields = {} allinstancefields = {} if self.classdef is None: fields['__class__'] = 'typeptr', get_type_repr(self.rtyper) else: # instance attributes if llfields is None: llfields = [] attrs = self.classdef.attrs.items() attrs.sort() for name, attrdef in attrs: if not attrdef.readonly: r = self.rtyper.getrepr(attrdef.s_value) mangled_name = 'inst_' + name fields[name] = mangled_name, r llfields.append((mangled_name, r.lowleveltype)) # # hash() support if self.rtyper.needs_hash_support(self.classdef): from pypy.rpython import rint fields['_hash_cache_'] = 'hash_cache', rint.signed_repr llfields.append(('hash_cache', Signed)) self.rbase = getinstancerepr(self.rtyper, self.classdef.basedef, self.gcflavor) self.rbase.setup() MkStruct = lltype.STRUCT_BY_FLAVOR[LLFLAVOR[self.gcflavor]] if adtmeths is None: adtmeths = {} if hints is None: hints = {} if '_immutable_' in self.classdef.classdesc.classdict: hints = hints.copy() hints['immutable'] = True object_type = MkStruct(self.classdef.name, ('super', self.rbase.object_type), hints=hints, adtmeths=adtmeths, *llfields) self.object_type.become(object_type) allinstancefields.update(self.rbase.allinstancefields) allinstancefields.update(fields) self.fields = fields self.allinstancefields = allinstancefields if self.gcflavor == 'gc': attachRuntimeTypeInfo(self.object_type)
def attachRuntimeTypeInfoFunc(self, GCSTRUCT, func, ARG_GCSTRUCT=None, destrptr=None): self.call_all_setups() # compute ForwardReferences now if ARG_GCSTRUCT is None: ARG_GCSTRUCT = GCSTRUCT args_s = [annmodel.SomePtr(Ptr(ARG_GCSTRUCT))] graph = self.annotate_helper(func, args_s) s = self.annotator.binding(graph.getreturnvar()) if (not isinstance(s, annmodel.SomePtr) or s.ll_ptrtype != Ptr(RuntimeTypeInfo)): raise TyperError("runtime type info function %r returns %r, " "excepted Ptr(RuntimeTypeInfo)" % (func, s)) funcptr = self.getcallable(graph) attachRuntimeTypeInfo(GCSTRUCT, funcptr, destrptr)
def test_caching_dynamic_deallocator(): S = lltype.GcStruct("S", ('x', lltype.Signed)) S1 = lltype.GcStruct("S1", ('s', S), ('y', lltype.Signed)) T = lltype.GcStruct("T", ('x', lltype.Signed)) def f_S(s): s.x = 1 def f_S1(s1): s1.s.x = 1 s1.y = 2 def f_T(s): s.x = 1 def type_info_S(p): return lltype.getRuntimeTypeInfo(S) def type_info_T(p): return lltype.getRuntimeTypeInfo(T) qp = lltype.functionptr(lltype.FuncType([lltype.Ptr(S)], lltype.Ptr(lltype.RuntimeTypeInfo)), "type_info_S", _callable=type_info_S) dp = lltype.functionptr(lltype.FuncType([lltype.Ptr(S)], lltype.Void), "destructor_funcptr", _callable=f_S) pinf = lltype.attachRuntimeTypeInfo(S, qp, destrptr=dp) dp = lltype.functionptr(lltype.FuncType([lltype.Ptr(S)], lltype.Void), "destructor_funcptr", _callable=f_S1) pinf = lltype.attachRuntimeTypeInfo(S1, qp, destrptr=dp) qp = lltype.functionptr(lltype.FuncType([lltype.Ptr(T)], lltype.Ptr(lltype.RuntimeTypeInfo)), "type_info_S", _callable=type_info_T) dp = lltype.functionptr(lltype.FuncType([lltype.Ptr(T)], lltype.Void), "destructor_funcptr", _callable=f_T) pinf = lltype.attachRuntimeTypeInfo(T, qp, destrptr=dp) def f(): pass t = TranslationContext() t.buildannotator().build_types(f, []) t.buildrtyper().specialize() transformer = RefcountingGCTransformer(t) p_S = transformer.dynamic_deallocation_funcptr_for_type(S) p_S1 = transformer.dynamic_deallocation_funcptr_for_type(S1) p_T = transformer.dynamic_deallocation_funcptr_for_type(T) assert p_S is not p_T assert p_S is p_S1
def test_malloc_new_with_destructor(): vtable = lltype.malloc(rclass.OBJECT_VTABLE, immortal=True) S = lltype.GcStruct("S", ("parent", rclass.OBJECT), rtti=True) DESTRUCTOR = lltype.FuncType([lltype.Ptr(S)], lltype.Void) destructor = lltype.functionptr(DESTRUCTOR, "destructor") lltype.attachRuntimeTypeInfo(S, destrptr=destructor) heaptracker.set_testing_vtable_for_gcstruct(S, vtable, "S") v = varoftype(lltype.Ptr(S)) op = SpaceOperation("malloc", [Constant(S, lltype.Void), Constant({"flavor": "gc"}, lltype.Void)], v) tr = Transformer(FakeCPU(), FakeResidualCallControl()) oplist = tr.rewrite_operation(op) op0, op1 = oplist assert op0.opname == "residual_call_r_r" assert op0.args[0].value == "alloc_with_del" # pseudo-function as a str assert list(op0.args[2]) == [] assert op1.opname == "-live-" assert op1.args == []
def get_shadowstackref(gctransformer): if hasattr(gctransformer, '_SHADOWSTACKREF'): return gctransformer._SHADOWSTACKREF SHADOWSTACKREFPTR = lltype.Ptr(lltype.GcForwardReference()) SHADOWSTACKREF = lltype.GcStruct( 'ShadowStackRef', ('base', llmemory.Address), ('top', llmemory.Address), ('context', llmemory.Address), #('fullstack', lltype.Bool), rtti=True) SHADOWSTACKREFPTR.TO.become(SHADOWSTACKREF) translator = gctransformer.translator if hasattr(translator, '_jit2gc'): gc = gctransformer.gcdata.gc root_iterator = translator._jit2gc['root_iterator'] def customtrace(obj, prev): obj = llmemory.cast_adr_to_ptr(obj, SHADOWSTACKREFPTR) if not prev: root_iterator.context = obj.context next = obj.base else: next = prev + sizeofaddr return root_iterator.next(gc, next, obj.top) else: def customtrace(obj, prev): # a simple but not JIT-ready version if not prev: next = llmemory.cast_adr_to_ptr(obj, SHADOWSTACKREFPTR).base else: next = prev + sizeofaddr if next == llmemory.cast_adr_to_ptr(obj, SHADOWSTACKREFPTR).top: next = llmemory.NULL return next CUSTOMTRACEFUNC = lltype.FuncType([llmemory.Address, llmemory.Address], llmemory.Address) customtraceptr = llhelper(lltype.Ptr(CUSTOMTRACEFUNC), customtrace) lltype.attachRuntimeTypeInfo(SHADOWSTACKREF, customtraceptr=customtraceptr) gctransformer._SHADOWSTACKREF = SHADOWSTACKREF return SHADOWSTACKREF
def attachRuntimeTypeInfoFunc(self, GCSTRUCT, func, ARG_GCSTRUCT=None, destrptr=None): self.call_all_setups() # compute ForwardReferences now if ARG_GCSTRUCT is None: ARG_GCSTRUCT = GCSTRUCT args_s = [annmodel.SomePtr(Ptr(ARG_GCSTRUCT))] graph = self.annotate_helper(func, args_s) s = self.annotator.binding(graph.getreturnvar()) if (not isinstance(s, annmodel.SomePtr) or s.ll_ptrtype != Ptr(RuntimeTypeInfo)): raise TyperError("runtime type info function %r returns %r, " "excepted Ptr(RuntimeTypeInfo)" % (func, s)) funcptr = self.getcallable(graph) attachRuntimeTypeInfo(GCSTRUCT, funcptr, destrptr, None)
def _setup_repr(self, llfields=None, hints=None, adtmeths=None): # NOTE: don't store mutable objects like the dicts below on 'self' # before they are fully built, to avoid strange bugs in case # of recursion where other code would uses these # partially-initialized dicts. self.rclass = getclassrepr(self.rtyper, self.classdef) fields = {} allinstancefields = {} if self.classdef is None: fields['__class__'] = 'typeptr', get_type_repr(self.rtyper) else: # instance attributes if llfields is None: llfields = [] attrs = self.classdef.attrs.items() attrs.sort() for name, attrdef in attrs: if not attrdef.readonly: r = self.rtyper.getrepr(attrdef.s_value) mangled_name = 'inst_' + name fields[name] = mangled_name, r llfields.append((mangled_name, r.lowleveltype)) self.rbase = getinstancerepr(self.rtyper, self.classdef.basedef, self.gcflavor) self.rbase.setup() MkStruct = lltype.STRUCT_BY_FLAVOR[LLFLAVOR[self.gcflavor]] if adtmeths is None: adtmeths = {} if hints is None: hints = {} hints = self._check_for_immutable_hints(hints) object_type = MkStruct(self.classdef.name, ('super', self.rbase.object_type), hints=hints, adtmeths=adtmeths, *llfields) self.object_type.become(object_type) allinstancefields.update(self.rbase.allinstancefields) allinstancefields.update(fields) self.fields = fields self.allinstancefields = allinstancefields if self.gcflavor == 'gc': attachRuntimeTypeInfo(self.object_type)
def get_shadowstackref(gctransformer): if hasattr(gctransformer, '_SHADOWSTACKREF'): return gctransformer._SHADOWSTACKREF SHADOWSTACKREFPTR = lltype.Ptr(lltype.GcForwardReference()) SHADOWSTACKREF = lltype.GcStruct('ShadowStackRef', ('base', llmemory.Address), ('top', llmemory.Address), ('context', llmemory.Address), #('fullstack', lltype.Bool), rtti=True) SHADOWSTACKREFPTR.TO.become(SHADOWSTACKREF) translator = gctransformer.translator if hasattr(translator, '_jit2gc'): gc = gctransformer.gcdata.gc root_iterator = translator._jit2gc['root_iterator'] def customtrace(obj, prev): obj = llmemory.cast_adr_to_ptr(obj, SHADOWSTACKREFPTR) if not prev: root_iterator.context = obj.context next = obj.base else: next = prev + sizeofaddr return root_iterator.next(gc, next, obj.top) else: def customtrace(obj, prev): # a simple but not JIT-ready version if not prev: next = llmemory.cast_adr_to_ptr(obj, SHADOWSTACKREFPTR).base else: next = prev + sizeofaddr if next == llmemory.cast_adr_to_ptr(obj, SHADOWSTACKREFPTR).top: next = llmemory.NULL return next CUSTOMTRACEFUNC = lltype.FuncType([llmemory.Address, llmemory.Address], llmemory.Address) customtraceptr = llhelper(lltype.Ptr(CUSTOMTRACEFUNC), customtrace) lltype.attachRuntimeTypeInfo(SHADOWSTACKREF, customtraceptr=customtraceptr) gctransformer._SHADOWSTACKREF = SHADOWSTACKREF return SHADOWSTACKREF
def test_malloc_new_with_destructor(): vtable = lltype.malloc(rclass.OBJECT_VTABLE, immortal=True) S = lltype.GcStruct('S', ('parent', rclass.OBJECT), rtti=True) DESTRUCTOR = lltype.FuncType([lltype.Ptr(S)], lltype.Void) destructor = lltype.functionptr(DESTRUCTOR, 'destructor') lltype.attachRuntimeTypeInfo(S, destrptr=destructor) heaptracker.set_testing_vtable_for_gcstruct(S, vtable, 'S') v = varoftype(lltype.Ptr(S)) op = SpaceOperation( 'malloc', [Constant(S, lltype.Void), Constant({'flavor': 'gc'}, lltype.Void)], v) tr = Transformer(FakeCPU(), FakeResidualCallControl()) oplist = tr.rewrite_operation(op) op0, op1 = oplist assert op0.opname == 'residual_call_r_r' assert op0.args[0].value == 'alloc_with_del' # pseudo-function as a str assert list(op0.args[2]) == [] assert op1.opname == '-live-' assert op1.args == []
def test_custom_trace(self): from pypy.rpython.annlowlevel import llhelper from pypy.rpython.lltypesystem import llmemory from pypy.rpython.lltypesystem.llarena import ArenaError # S = lltype.GcStruct('S', ('x', llmemory.Address), ('y', llmemory.Address), rtti=True) T = lltype.GcStruct('T', ('z', lltype.Signed)) offset_of_x = llmemory.offsetof(S, 'x') def customtrace(obj, prev): if not prev: return obj + offset_of_x else: return llmemory.NULL CUSTOMTRACEFUNC = lltype.FuncType([llmemory.Address, llmemory.Address], llmemory.Address) customtraceptr = llhelper(lltype.Ptr(CUSTOMTRACEFUNC), customtrace) lltype.attachRuntimeTypeInfo(S, customtraceptr=customtraceptr) # for attrname in ['x', 'y']: def setup(): s1 = lltype.malloc(S) tx = lltype.malloc(T) tx.z = 42 ty = lltype.malloc(T) s1.x = llmemory.cast_ptr_to_adr(tx) s1.y = llmemory.cast_ptr_to_adr(ty) return s1 def f(): s1 = setup() llop.gc__collect(lltype.Void) return llmemory.cast_adr_to_ptr(getattr(s1, attrname), lltype.Ptr(T)) if attrname == 'x': res = self.interpret(f, []) assert res.z == 42 else: py.test.raises((RuntimeError, ArenaError), self.interpret, f, [])
def test_custom_trace(self): from pypy.rpython.annlowlevel import llhelper from pypy.rpython.lltypesystem import llmemory from pypy.rpython.lltypesystem.llarena import ArenaError # S = lltype.GcStruct('S', ('x', llmemory.Address), ('y', llmemory.Address), rtti=True) T = lltype.GcStruct('T', ('z', lltype.Signed)) offset_of_x = llmemory.offsetof(S, 'x') def customtrace(obj, prev): if not prev: return obj + offset_of_x else: return llmemory.NULL CUSTOMTRACEFUNC = lltype.FuncType([llmemory.Address, llmemory.Address], llmemory.Address) customtraceptr = llhelper(lltype.Ptr(CUSTOMTRACEFUNC), customtrace) lltype.attachRuntimeTypeInfo(S, customtraceptr=customtraceptr) # for attrname in ['x', 'y']: def setup(): s1 = lltype.malloc(S) tx = lltype.malloc(T) tx.z = 42 ty = lltype.malloc(T) s1.x = llmemory.cast_ptr_to_adr(tx) s1.y = llmemory.cast_ptr_to_adr(ty) return s1 def f(): s1 = setup() llop.gc__collect(lltype.Void) return llmemory.cast_adr_to_ptr(getattr(s1, attrname), lltype.Ptr(T)) if attrname == 'x': res = self.interpret(f, []) assert res.z == 42 else: py.test.raises((RuntimeError, ArenaError), self.interpret, f, [])
def test_deallocator_with_destructor(): S = lltype.GcStruct("S", ('x', lltype.Signed)) def f(s): s.x = 1 def type_info_S(p): return lltype.getRuntimeTypeInfo(S) qp = lltype.functionptr(lltype.FuncType([lltype.Ptr(S)], lltype.Ptr(lltype.RuntimeTypeInfo)), "type_info_S", _callable=type_info_S) dp = lltype.functionptr(lltype.FuncType([lltype.Ptr(S)], lltype.Void), "destructor_funcptr", _callable=f) pinf = lltype.attachRuntimeTypeInfo(S, qp, destrptr=dp) graph, t = make_deallocator(S)
def test_deallocator_with_destructor(): S = lltype.GcStruct("S", ('x', lltype.Signed)) def f(s): s.x = 1 def type_info_S(p): return lltype.getRuntimeTypeInfo(S) qp = lltype.functionptr(lltype.FuncType([lltype.Ptr(S)], lltype.Ptr(lltype.RuntimeTypeInfo)), "type_info_S", _callable=type_info_S) dp = lltype.functionptr(lltype.FuncType([lltype.Ptr(S)], lltype.Void), "destructor_funcptr", _callable=f) pinf = lltype.attachRuntimeTypeInfo(S, qp, destrptr=dp) graph, t = make_deallocator(S)
def test_boehm_finalizer_nomix___del___and_pyobj(): S = lltype.GcStruct("S", ('x', lltype.Signed), ('y', lltype.Ptr(lltype.PyObject))) def f(s): s.x = 1 def type_info_S(p): return lltype.getRuntimeTypeInfo(S) qp = lltype.functionptr(lltype.FuncType([lltype.Ptr(S)], lltype.Ptr(lltype.RuntimeTypeInfo)), "type_info_S", _callable=type_info_S) dp = lltype.functionptr(lltype.FuncType([lltype.Ptr(S)], lltype.Void), "destructor_funcptr", _callable=f) pinf = lltype.attachRuntimeTypeInfo(S, qp, destrptr=dp) py.test.raises(Exception, "make_boehm_finalizer(S)")
def test_boehm_finalizer___del__(): S = lltype.GcStruct("S", ('x', lltype.Signed)) def f(s): s.x = 1 def type_info_S(p): return lltype.getRuntimeTypeInfo(S) qp = lltype.functionptr(lltype.FuncType([lltype.Ptr(S)], lltype.Ptr(lltype.RuntimeTypeInfo)), "type_info_S", _callable=type_info_S) dp = lltype.functionptr(lltype.FuncType([lltype.Ptr(S)], lltype.Void), "destructor_funcptr", _callable=f) pinf = lltype.attachRuntimeTypeInfo(S, qp, destrptr=dp) f, t = make_boehm_finalizer(S) assert f is not None
def test_boehm_finalizer_nomix___del___and_pyobj(): S = lltype.GcStruct("S", ('x', lltype.Signed), ('y', lltype.Ptr(lltype.PyObject))) def f(s): s.x = 1 def type_info_S(p): return lltype.getRuntimeTypeInfo(S) qp = lltype.functionptr(lltype.FuncType([lltype.Ptr(S)], lltype.Ptr( lltype.RuntimeTypeInfo)), "type_info_S", _callable=type_info_S) dp = lltype.functionptr(lltype.FuncType([lltype.Ptr(S)], lltype.Void), "destructor_funcptr", _callable=f) pinf = lltype.attachRuntimeTypeInfo(S, qp, destrptr=dp) py.test.raises(Exception, "make_boehm_finalizer(S)")
def test_boehm_finalizer___del__(): S = lltype.GcStruct("S", ('x', lltype.Signed)) def f(s): s.x = 1 def type_info_S(p): return lltype.getRuntimeTypeInfo(S) qp = lltype.functionptr(lltype.FuncType([lltype.Ptr(S)], lltype.Ptr( lltype.RuntimeTypeInfo)), "type_info_S", _callable=type_info_S) dp = lltype.functionptr(lltype.FuncType([lltype.Ptr(S)], lltype.Void), "destructor_funcptr", _callable=f) pinf = lltype.attachRuntimeTypeInfo(S, qp, destrptr=dp) f, t = make_boehm_finalizer(S) assert f is not None
def customtrace(obj, prev): stackletrootwalker = get_stackletrootwalker() return stackletrootwalker.next(obj, prev) SUSPSTACK = lltype.GcStruct('SuspStack', ('handle', _c.handle), ('anchor', llmemory.Address), rtti=True) NULL_SUSPSTACK = lltype.nullptr(SUSPSTACK) CUSTOMTRACEFUNC = lltype.FuncType([llmemory.Address, llmemory.Address], llmemory.Address) customtraceptr = llhelper(lltype.Ptr(CUSTOMTRACEFUNC), customtrace) lltype.attachRuntimeTypeInfo(SUSPSTACK, customtraceptr=customtraceptr) ASM_FRAMEDATA_HEAD_PTR = lltype.Ptr(lltype.ForwardReference()) ASM_FRAMEDATA_HEAD_PTR.TO.become(lltype.Struct('ASM_FRAMEDATA_HEAD', ('prev', ASM_FRAMEDATA_HEAD_PTR), ('next', ASM_FRAMEDATA_HEAD_PTR) )) alternateanchor = lltype.malloc(ASM_FRAMEDATA_HEAD_PTR.TO, immortal=True) alternateanchor.prev = alternateanchor alternateanchor.next = alternateanchor FUNCNOARG_P = lltype.Ptr(lltype.FuncType([], _c.handle)) pypy_asm_stackwalk2 = rffi.llexternal('pypy_asm_stackwalk', [FUNCNOARG_P, ASM_FRAMEDATA_HEAD_PTR],
get_stackletrootwalker._annspecialcase_ = 'specialize:memo' def customtrace(obj, prev): stackletrootwalker = get_stackletrootwalker() return stackletrootwalker.next(obj, prev) SUSPSTACK = lltype.GcStruct('SuspStack', ('handle', _c.handle), ('anchor', llmemory.Address), rtti=True) NULL_SUSPSTACK = lltype.nullptr(SUSPSTACK) CUSTOMTRACEFUNC = lltype.FuncType([llmemory.Address, llmemory.Address], llmemory.Address) customtraceptr = llhelper(lltype.Ptr(CUSTOMTRACEFUNC), customtrace) lltype.attachRuntimeTypeInfo(SUSPSTACK, customtraceptr=customtraceptr) ASM_FRAMEDATA_HEAD_PTR = lltype.Ptr(lltype.ForwardReference()) ASM_FRAMEDATA_HEAD_PTR.TO.become( lltype.Struct('ASM_FRAMEDATA_HEAD', ('prev', ASM_FRAMEDATA_HEAD_PTR), ('next', ASM_FRAMEDATA_HEAD_PTR))) alternateanchor = lltype.malloc(ASM_FRAMEDATA_HEAD_PTR.TO, immortal=True) alternateanchor.prev = alternateanchor alternateanchor.next = alternateanchor FUNCNOARG_P = lltype.Ptr(lltype.FuncType([], _c.handle)) pypy_asm_stackwalk2 = rffi.llexternal('pypy_asm_stackwalk', [FUNCNOARG_P, ASM_FRAMEDATA_HEAD_PTR], _c.handle, sandboxsafe=True, _nowrapper=True)