def dynamic_deallocation_funcptr_for_type(self, TYPE): if TYPE in self.dynamic_deallocator_funcptrs: return self.dynamic_deallocator_funcptrs[TYPE] #print_call_chain(self) rtti = get_rtti(TYPE) if rtti is None: p = self.static_deallocation_funcptr_for_type(TYPE) self.dynamic_deallocator_funcptrs[TYPE] = p return p queryptr = rtti._obj.query_funcptr if queryptr._obj in self.queryptr2dynamic_deallocator_funcptr: return self.queryptr2dynamic_deallocator_funcptr[queryptr._obj] RTTI_PTR = lltype.Ptr(lltype.RuntimeTypeInfo) QUERY_ARG_TYPE = lltype.typeOf(queryptr).TO.ARGS[0] gc_header_offset = self.gcheaderbuilder.size_gc_header HDRPTR = lltype.Ptr(self.HDR) def ll_dealloc(addr): # bump refcount to 1 gcheader = llmemory.cast_adr_to_ptr(addr - gc_header_offset, HDRPTR) gcheader.refcount = 1 v = llmemory.cast_adr_to_ptr(addr, QUERY_ARG_TYPE) rtti = queryptr(v) gcheader.refcount = 0 llop.gc_call_rtti_destructor(lltype.Void, rtti, addr) fptr = self.annotate_helper(ll_dealloc, [llmemory.Address], lltype.Void) self.dynamic_deallocator_funcptrs[TYPE] = fptr self.queryptr2dynamic_deallocator_funcptr[queryptr._obj] = fptr return fptr
def finalizer_funcptr_for_type(self, TYPE): if TYPE in self.finalizer_funcptrs: return self.finalizer_funcptrs[TYPE] rtti = get_rtti(TYPE) if rtti is not None and hasattr(rtti._obj, 'destructor_funcptr'): destrptr = rtti._obj.destructor_funcptr DESTR_ARG = lltype.typeOf(destrptr).TO.ARGS[0] else: destrptr = None DESTR_ARG = None if destrptr: EXC_INSTANCE_TYPE = self.translator.rtyper.exceptiondata.lltype_of_exception_value typename = TYPE.__name__ revdb = self.translator.config.translation.reverse_debugger def ll_finalizer(gcref): exc_instance = llop.gc_fetch_exception(EXC_INSTANCE_TYPE) if revdb: llop.revdb_call_destructor(lltype.Void, gcref) v = lltype.cast_opaque_ptr(DESTR_ARG, gcref) ll_call_destructor(destrptr, v, typename) llop.gc_restore_exception(lltype.Void, exc_instance) fptr = self.annotate_finalizer(ll_finalizer, [llmemory.GCREF], lltype.Void) else: fptr = lltype.nullptr(self.FINALIZER_PTR.TO) self.finalizer_funcptrs[TYPE] = fptr return fptr
def finalizer_funcptr_for_type(self, TYPE): if TYPE in self.finalizer_funcptrs: return self.finalizer_funcptrs[TYPE] rtti = get_rtti(TYPE) if rtti is not None and hasattr(rtti._obj, 'destructor_funcptr'): destrptr = rtti._obj.destructor_funcptr DESTR_ARG = lltype.typeOf(destrptr).TO.ARGS[0] else: destrptr = None DESTR_ARG = None if destrptr: EXC_INSTANCE_TYPE = self.translator.rtyper.exceptiondata.lltype_of_exception_value typename = TYPE.__name__ def ll_finalizer(addr): exc_instance = llop.gc_fetch_exception(EXC_INSTANCE_TYPE) v = llmemory.cast_adr_to_ptr(addr, DESTR_ARG) ll_call_destructor(destrptr, v, typename) llop.gc_restore_exception(lltype.Void, exc_instance) fptr = self.annotate_finalizer(ll_finalizer, [llmemory.Address], lltype.Void) else: fptr = lltype.nullptr(self.FINALIZER_PTR.TO) self.finalizer_funcptrs[TYPE] = fptr return fptr
def make_custom_trace_funcptr_for_type(self, TYPE): from rpython.memory.gctransform.support import get_rtti rtti = get_rtti(TYPE) if rtti is not None and hasattr(rtti._obj, 'custom_trace_funcptr'): return rtti._obj.custom_trace_funcptr else: return None
def make_finalizer_funcptr_for_type(self, TYPE): from rpython.memory.gctransform.support import get_rtti rtti = get_rtti(TYPE) if rtti is not None and hasattr(rtti._obj, 'destructor_funcptr'): destrptr = rtti._obj.destructor_funcptr DESTR_ARG = lltype.typeOf(destrptr).TO.ARGS[0] destrgraph = destrptr._obj.graph else: return None, False t = self.llinterp.typer.annotator.translator light = not FinalizerAnalyzer(t).analyze_light_finalizer(destrgraph) def ll_finalizer(addr): try: v = llmemory.cast_adr_to_ptr(addr, DESTR_ARG) self.llinterp.eval_graph(destrgraph, [v], recursive=True) except llinterp.LLException: raise RuntimeError( "a finalizer raised an exception, shouldn't happen") return llhelper(gctypelayout.GCData.FINALIZER, ll_finalizer), light
def static_deallocation_funcptr_for_type(self, TYPE): if TYPE in self.static_deallocator_funcptrs: return self.static_deallocator_funcptrs[TYPE] #print_call_chain(self) rtti = get_rtti(TYPE) if rtti is not None and hasattr(rtti._obj, 'destructor_funcptr'): destrptr = rtti._obj.destructor_funcptr DESTR_ARG = lltype.typeOf(destrptr).TO.ARGS[0] else: destrptr = None DESTR_ARG = None if destrptr is None and not find_gc_ptrs_in_type(TYPE): p = self.no_pointer_dealloc_ptr.value self.static_deallocator_funcptrs[TYPE] = p return p if destrptr is not None: body = '\n'.join(_static_deallocator_body_for_type('v', TYPE, 3)) src = """ def ll_deallocator(addr): exc_instance = llop.gc_fetch_exception(EXC_INSTANCE_TYPE) try: v = cast_adr_to_ptr(addr, PTR_TYPE) gcheader = cast_adr_to_ptr(addr - gc_header_offset, HDRPTR) # refcount is at zero, temporarily bump it to 1: gcheader.refcount = 1 destr_v = cast_pointer(DESTR_ARG, v) ll_call_destructor(destrptr, destr_v, %r) refcount = gcheader.refcount - 1 gcheader.refcount = refcount if refcount == 0: %s llop.%s_free(lltype.Void, addr) except: pass llop.gc_restore_exception(lltype.Void, exc_instance) pop_alive(exc_instance) # XXX layering of exceptiontransform versus gcpolicy """ % (TYPE.__name__, body, TYPE._gckind) else: call_del = None body = '\n'.join(_static_deallocator_body_for_type('v', TYPE)) src = ( 'def ll_deallocator(addr):\n v = cast_adr_to_ptr(addr, PTR_TYPE)\n' + body + '\n llop.%s_free(lltype.Void, addr)\n' % (TYPE._gckind, )) d = { 'pop_alive': LLTransformerOp(self.pop_alive), 'llop': llop, 'lltype': lltype, 'destrptr': destrptr, 'gc_header_offset': self.gcheaderbuilder.size_gc_header, 'cast_adr_to_ptr': llmemory.cast_adr_to_ptr, 'cast_pointer': lltype.cast_pointer, 'PTR_TYPE': lltype.Ptr(TYPE), 'DESTR_ARG': DESTR_ARG, 'EXC_INSTANCE_TYPE': self.translator.rtyper.exceptiondata.lltype_of_exception_value, 'll_call_destructor': ll_call_destructor, 'HDRPTR': lltype.Ptr(self.HDR) } exec src in d this = d['ll_deallocator'] fptr = self.annotate_finalizer(this, [llmemory.Address], lltype.Void) self.static_deallocator_funcptrs[TYPE] = fptr for p in find_gc_ptrs_in_type(TYPE): self.static_deallocation_funcptr_for_type(p.TO) return fptr
def static_deallocation_funcptr_for_type(self, TYPE): if TYPE in self.static_deallocator_funcptrs: return self.static_deallocator_funcptrs[TYPE] #print_call_chain(self) rtti = get_rtti(TYPE) if rtti is not None and hasattr(rtti._obj, 'destructor_funcptr'): destrptr = rtti._obj.destructor_funcptr DESTR_ARG = lltype.typeOf(destrptr).TO.ARGS[0] else: destrptr = None DESTR_ARG = None if destrptr is None and not find_gc_ptrs_in_type(TYPE): p = self.no_pointer_dealloc_ptr.value self.static_deallocator_funcptrs[TYPE] = p return p if destrptr is not None: body = '\n'.join(_static_deallocator_body_for_type('v', TYPE, 3)) src = """ def ll_deallocator(addr): exc_instance = llop.gc_fetch_exception(EXC_INSTANCE_TYPE) try: v = cast_adr_to_ptr(addr, PTR_TYPE) gcheader = cast_adr_to_ptr(addr - gc_header_offset, HDRPTR) # refcount is at zero, temporarily bump it to 1: gcheader.refcount = 1 destr_v = cast_pointer(DESTR_ARG, v) ll_call_destructor(destrptr, destr_v, %r) refcount = gcheader.refcount - 1 gcheader.refcount = refcount if refcount == 0: %s llop.%s_free(lltype.Void, addr) except: pass llop.gc_restore_exception(lltype.Void, exc_instance) pop_alive(exc_instance) # XXX layering of exceptiontransform versus gcpolicy """ % (TYPE.__name__, body, TYPE._gckind) else: call_del = None body = '\n'.join(_static_deallocator_body_for_type('v', TYPE)) src = ('def ll_deallocator(addr):\n v = cast_adr_to_ptr(addr, PTR_TYPE)\n' + body + '\n llop.%s_free(lltype.Void, addr)\n' % (TYPE._gckind,)) d = {'pop_alive': LLTransformerOp(self.pop_alive), 'llop': llop, 'lltype': lltype, 'destrptr': destrptr, 'gc_header_offset': self.gcheaderbuilder.size_gc_header, 'cast_adr_to_ptr': llmemory.cast_adr_to_ptr, 'cast_pointer': lltype.cast_pointer, 'PTR_TYPE': lltype.Ptr(TYPE), 'DESTR_ARG': DESTR_ARG, 'EXC_INSTANCE_TYPE': self.translator.rtyper.exceptiondata.lltype_of_exception_value, 'll_call_destructor': ll_call_destructor, 'HDRPTR':lltype.Ptr(self.HDR)} exec src in d this = d['ll_deallocator'] fptr = self.annotate_finalizer(this, [llmemory.Address], lltype.Void) self.static_deallocator_funcptrs[TYPE] = fptr for p in find_gc_ptrs_in_type(TYPE): self.static_deallocation_funcptr_for_type(p.TO) return fptr