[pypy-commit] pypy stmgc-c7: Finalizers, step 1
arigo
noreply at buildbot.pypy.org
Fri Oct 17 16:16:33 CEST 2014
Author: Armin Rigo <arigo at 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
More information about the pypy-commit
mailing list