Author: Armin Rigo <ar...@tunes.org> Branch: stmgc-c7 Changeset: r73998:3159fb66123b Date: 2014-10-17 16:16 +0200 http://bitbucket.org/pypy/pypy/changeset/3159fb66123b/
Log: Finalizers, step 1 diff --git a/rpython/memory/gc/stmgc.py b/rpython/memory/gc/stmgc.py --- a/rpython/memory/gc/stmgc.py +++ b/rpython/memory/gc/stmgc.py @@ -73,13 +73,13 @@ needs_finalizer=False, is_finalizer_light=False, contains_weakptr=False): - # XXX finalizers are ignored for now - #ll_assert(not needs_finalizer, 'XXX needs_finalizer') - #ll_assert(not is_finalizer_light, 'XXX is_finalizer_light') if size < 16: size = 16 # minimum size (test usually constant-folded) if contains_weakptr: # check constant-folded return llop.stm_allocate_weakref(llmemory.GCREF, size, typeid16) + if needs_finalizer: + #is_finalizer_light XXX ignored now + return llop.stm_allocate_finalizer(llmemory.GCREF, size, typeid16) return llop.stm_allocate_tid(llmemory.GCREF, size, typeid16) def malloc_varsize_clear(self, typeid16, length, size, itemsize, diff --git a/rpython/memory/gctransform/framework.py b/rpython/memory/gctransform/framework.py --- a/rpython/memory/gctransform/framework.py +++ b/rpython/memory/gctransform/framework.py @@ -1257,8 +1257,6 @@ super(TransformerLayoutBuilder, self).__init__(GCClass, lltype2vtable) def has_finalizer(self, TYPE): - if self.translator.config.translation.stm: - return False # XXX no finalizer support for now rtti = get_rtti(TYPE) return rtti is not None and getattr(rtti._obj, 'destructor_funcptr', None) @@ -1275,22 +1273,24 @@ def make_finalizer_funcptr_for_type(self, TYPE): if not self.has_finalizer(TYPE): return None, False + stm = self.translator.config.translation.stm rtti = get_rtti(TYPE) destrptr = rtti._obj.destructor_funcptr DESTR_ARG = lltype.typeOf(destrptr).TO.ARGS[0] typename = TYPE.__name__ def ll_finalizer(addr): - v = llmemory.cast_adr_to_ptr(addr, DESTR_ARG) + if stm: + from rpython.rtyper.lltypesystem.lloperation import llop + v = llop.stm_really_force_cast_ptr(DESTR_ARG, addr) + else: + v = llmemory.cast_adr_to_ptr(addr, DESTR_ARG) ll_call_destructor(destrptr, v, typename) fptr = self.transformer.annotate_finalizer(ll_finalizer, [llmemory.Address], lltype.Void) try: g = destrptr._obj.graph - if self.translator.config.translation.stm: - light = False # XXX no working finalizers with STM so far - else: - analyzer = FinalizerAnalyzer(self.translator) - light = not analyzer.analyze_light_finalizer(g) + analyzer = FinalizerAnalyzer(self.translator) + light = not analyzer.analyze_light_finalizer(g) except lltype.DelayedPointer: light = False # XXX bah, too bad return fptr, light diff --git a/rpython/memory/gctransform/stmframework.py b/rpython/memory/gctransform/stmframework.py --- a/rpython/memory/gctransform/stmframework.py +++ b/rpython/memory/gctransform/stmframework.py @@ -1,7 +1,8 @@ from rpython.annotator import model as annmodel -from rpython.rtyper.lltypesystem import lltype, llmemory, rffi +from rpython.rtyper.lltypesystem import lltype, llmemory, rffi, llgroup from rpython.rtyper.lltypesystem.lloperation import llop -from rpython.memory.gctransform.framework import ( TYPE_ID, +from rpython.memory.gctransform.support import get_rtti +from rpython.memory.gctransform.framework import (TYPE_ID, BaseFrameworkGCTransformer, BaseRootWalker, sizeofaddr) from rpython.memory.gctypelayout import WEAKREF, WEAKREFPTR from rpython.rtyper import rmodel, llannotation @@ -66,6 +67,15 @@ [llannotation.SomeAddress(), llannotation.SomePtr(rffi.CArrayPtr(lltype.Unsigned))], annmodel.s_None)) + # + def pypy_stmcb_fetch_finalizer(typeid): + typeid = lltype.cast_primitive(llgroup.HALFWORD, typeid) + return llmemory.cast_ptr_to_adr(gc.getfinalizer(typeid)) + pypy_stmcb_fetch_finalizer.c_name = ( + "pypy_stmcb_fetch_finalizer") + self.autoregister_ptrs.append( + getfn(pypy_stmcb_fetch_finalizer, + [annmodel.s_Int], llannotation.SomeAddress())) def build_root_walker(self): return StmRootWalker(self) diff --git a/rpython/rtyper/lltypesystem/lloperation.py b/rpython/rtyper/lltypesystem/lloperation.py --- a/rpython/rtyper/lltypesystem/lloperation.py +++ b/rpython/rtyper/lltypesystem/lloperation.py @@ -417,6 +417,7 @@ 'stm_can_move': LLOp(), 'stm_allocate_tid': LLOp(sideeffects=False, canmallocgc=True), 'stm_allocate_weakref': LLOp(sideeffects=False, canmallocgc=True), + 'stm_allocate_finalizer': LLOp(sideeffects=False, canmallocgc=True), 'stm_get_from_obj': LLOp(sideeffects=False), 'stm_get_from_obj_const': LLOp(canfold=True), 'stm_set_into_obj': LLOp(), @@ -456,7 +457,8 @@ 'stm_expand_marker': LLOp(), 'stm_setup_expand_marker_for_pypy': LLOp(), - 'stm_count': LLOp(), + 'stm_count': LLOp(), + 'stm_really_force_cast_ptr': LLOp(), # __________ address operations __________ diff --git a/rpython/translator/c/genc.py b/rpython/translator/c/genc.py --- a/rpython/translator/c/genc.py +++ b/rpython/translator/c/genc.py @@ -766,15 +766,6 @@ print >> f print >> f, "#ifndef _PYPY_STRUCTDEF_H" print >> f, "#define _PYPY_STRUCTDEF_H" - if database.with_stm: - print >> f - print >> f, 'typedef TLPREFIX struct rpyobj_s {' - print >> f, '\tstruct object_s lib;' - print >> f, '\tuint32_t tid;' - print >> f, '} rpyobj_t;' - print >> f, 'typedef TLPREFIX char rpygcchar_t;' - else: - print >> f, 'typedef char rpygcchar_t;' print >> f for node in structdeflist: if hasattr(node, 'forward_decl'): @@ -798,7 +789,7 @@ if database.with_stm: print >> f print >> f, 'extern object_t *rpy_prebuilt[];' - print >> f + print >> f for node in database.globalcontainers(): for line in node.forward_declaration(): print >> f, line diff --git a/rpython/translator/c/src/g_prerequisite.h b/rpython/translator/c/src/g_prerequisite.h --- a/rpython/translator/c/src/g_prerequisite.h +++ b/rpython/translator/c/src/g_prerequisite.h @@ -25,8 +25,18 @@ #ifdef RPY_STM #define rpy_duck() asm("":::"memory") // work around an llvm bug :-/ + +typedef TLPREFIX struct rpyobj_s { + struct object_s lib; + uint32_t tid; +} rpyobj_t; +typedef TLPREFIX char rpygcchar_t; + #else + #define rpy_duck() /* nothing */ +typedef char rpygcchar_t; + #endif diff --git a/rpython/translator/stm/funcgen.py b/rpython/translator/stm/funcgen.py --- a/rpython/translator/stm/funcgen.py +++ b/rpython/translator/stm/funcgen.py @@ -89,6 +89,15 @@ return ('%s = (rpygcchar_t *)stm_allocate_weakref(%s); ' % (result, arg_size) + '((rpyobj_t *)%s)->tid = %s;' % (result, arg_type_id)) +def stm_allocate_finalizer(funcgen, op): + arg_size = funcgen.expr(op.args[0]) + arg_type_id = funcgen.expr(op.args[1]) + result = funcgen.expr(op.result) + # XXX NULL returns? + return ('%s = (rpygcchar_t *)stm_allocate_with_finalizer(%s); ' % ( + result, arg_size) + + '((rpyobj_t *)%s)->tid = %s;' % (result, arg_type_id)) + def stm_get_from_obj(funcgen, op): assert op.args[0].concretetype == llmemory.GCREF arg_obj = funcgen.expr(op.args[0]) @@ -254,3 +263,13 @@ def stm_count(funcgen, op): result = funcgen.expr(op.result) return '%s = _pypy_stm_count();' % (result,) + +def stm_really_force_cast_ptr(funcgen, op): + # pffff, try very very hard to cast a pointer in one address space + # to consider it as a pointer in another address space, without + # changing it in any way. It works if we cast via an integer + # (but not directly). + result = funcgen.expr(op.result) + arg = funcgen.expr(op.args[0]) + typename = cdecl(funcgen.lltypename(op.result), '') + return '%s = (%s)(uintptr_t)%s;' % (result, typename, arg) diff --git a/rpython/translator/stm/src_stm/extracode.h b/rpython/translator/stm/src_stm/extracode.h --- a/rpython/translator/stm/src_stm/extracode.h +++ b/rpython/translator/stm/src_stm/extracode.h @@ -1,3 +1,9 @@ + +static void _stm_call_finalizer(object_t *obj) +{ + void *funcptr = pypy_stmcb_fetch_finalizer(((rpyobj_t *)obj)->tid); + ((void(*)(object_t *))funcptr)(obj); +} void pypy_stm_setup_prebuilt(void) { @@ -23,6 +29,8 @@ for ( ; cur != end; cur++) { **cur = stm_setup_prebuilt(**cur); } + + stmcb_finalizer = &_stm_call_finalizer; } void pypy_stm_register_thread_local(void) diff --git a/rpython/translator/stm/src_stm/stmgcintf.c b/rpython/translator/stm/src_stm/stmgcintf.c --- a/rpython/translator/stm/src_stm/stmgcintf.c +++ b/rpython/translator/stm/src_stm/stmgcintf.c @@ -14,6 +14,7 @@ extern void pypy_stmcb_trace(void*, void(*)(void*)); extern void pypy_stmcb_trace_cards(void*, void(*)(void*), uintptr_t, uintptr_t); extern Signed pypy_stmcb_obj_supports_cards(void*); +extern void *pypy_stmcb_fetch_finalizer(long); inline ssize_t stmcb_size_rounded_up(struct object_s *obj) { ssize_t result = pypy_stmcb_size_rounded_up(obj); diff --git a/rpython/translator/stm/test/test_ztranslated.py b/rpython/translator/stm/test/test_ztranslated.py --- a/rpython/translator/stm/test/test_ztranslated.py +++ b/rpython/translator/stm/test/test_ztranslated.py @@ -510,3 +510,24 @@ assert ('starting some_extremely_longish_and_boring_function_name\n' 'File "<bla/br/project/foobaz.py", line 81,' ' in some_extremely_longish_a>\n') in data + + def test_finalizer(self): + class Counter: + num = 0 + g_counter = Counter() + class X: + def __del__(self): + g_counter.num += 1 + + def g(): + X() + + def main(argv): + g() + rgc.collect() + print 'destructors called:', g_counter.num + return 0 + + t, cbuilder = self.compile(main) + data = cbuilder.cmdexec('') + assert 'destructors called: 1\n' in data _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit