[pypy-commit] pypy gc-del: Support the new finalizer interface in Boehm too.
arigo
noreply at buildbot.pypy.org
Wed Mar 27 15:52:34 CET 2013
Author: Armin Rigo <arigo at tunes.org>
Branch: gc-del
Changeset: r62833:9ef6bb8aa5c2
Date: 2013-03-27 15:50 +0100
http://bitbucket.org/pypy/pypy/changeset/9ef6bb8aa5c2/
Log: Support the new finalizer interface in Boehm too.
diff --git a/rpython/memory/gctransform/boehm.py b/rpython/memory/gctransform/boehm.py
--- a/rpython/memory/gctransform/boehm.py
+++ b/rpython/memory/gctransform/boehm.py
@@ -9,12 +9,12 @@
class BoehmGCTransformer(GCTransformer):
malloc_zero_filled = True
- FINALIZER_PTR = lltype.Ptr(lltype.FuncType([llmemory.Address], lltype.Void))
+ DESTRUCTOR_PTR = lltype.Ptr(lltype.FuncType([llmemory.Address], lltype.Void))
HDR = lltype.Struct("header", ("hash", lltype.Signed))
def __init__(self, translator, inline=False):
super(BoehmGCTransformer, self).__init__(translator, inline=inline)
- self.finalizer_funcptrs = {}
+ self.destructor_funcptrs = {}
atomic_mh = mallocHelpers()
atomic_mh.allocate = lambda size: llop.boehm_malloc_atomic(llmemory.Address, size)
@@ -66,10 +66,15 @@
v_raw = hop.genop("direct_call",
[funcptr, c_size],
resulttype=llmemory.Address)
- finalizer_ptr = self.finalizer_funcptr_for_type(TYPE)
- if finalizer_ptr:
- c_finalizer_ptr = Constant(finalizer_ptr, self.FINALIZER_PTR)
- hop.genop("boehm_register_finalizer", [v_raw, c_finalizer_ptr])
+ destructor_ptr = self.destructor_funcptr_for_type(TYPE)
+ if destructor_ptr:
+ from rpython.rtyper.annlowlevel import base_ptr_lltype
+ c_destructor_ptr = Constant(destructor_ptr, self.DESTRUCTOR_PTR)
+ v_llfn = hop.genop('cast_ptr_to_adr', [c_destructor_ptr],
+ resulttype=llmemory.Address)
+ v_self = hop.genop('cast_adr_to_ptr', [v_raw],
+ resulttype=base_ptr_lltype())
+ hop.genop("gc_register_finalizer", [v_self, v_llfn])
return v_raw
def gct_fv_gc_malloc_varsize(self, hop, flags, TYPE, v_length, c_const_size, c_item_size,
@@ -87,9 +92,9 @@
resulttype=llmemory.Address)
return v_raw
- def finalizer_funcptr_for_type(self, TYPE):
- if TYPE in self.finalizer_funcptrs:
- return self.finalizer_funcptrs[TYPE]
+ def destructor_funcptr_for_type(self, TYPE):
+ if TYPE in self.destructor_funcptrs:
+ return self.destructor_funcptrs[TYPE]
rtti = get_rtti(TYPE)
if rtti is not None and hasattr(rtti._obj, 'destructor_funcptr'):
@@ -102,16 +107,17 @@
if destrptr:
EXC_INSTANCE_TYPE = self.translator.rtyper.exceptiondata.lltype_of_exception_value
typename = TYPE.__name__
- def ll_finalizer(addr):
+ def ll_destructor(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)
+ fptr = self.annotate_finalizer(ll_destructor, [llmemory.Address],
+ lltype.Void)
else:
- fptr = lltype.nullptr(self.FINALIZER_PTR.TO)
+ fptr = lltype.nullptr(self.DESTRUCTOR_PTR.TO)
- self.finalizer_funcptrs[TYPE] = fptr
+ self.destructor_funcptrs[TYPE] = fptr
return fptr
def gct_weakref_create(self, hop):
diff --git a/rpython/memory/gctypelayout.py b/rpython/memory/gctypelayout.py
--- a/rpython/memory/gctypelayout.py
+++ b/rpython/memory/gctypelayout.py
@@ -148,7 +148,7 @@
finalizer = llmemory.cast_adr_to_ptr(finalizer, self.FINALIZER)
try:
finalizer(obj)
- except rgc.FinalizeLater:
+ except rgc._FinalizeLater:
return False
except Exception:
debug_print("WARNING: unhandled exception from finalizer",
@@ -166,7 +166,7 @@
llinterp.eval_graph(finalizer.ptr._obj.graph, [obj],
recursive=True)
except LLException, e:
- if ''.join(e.args[0].name) == 'FinalizeLater\x00':
+ if ''.join(e.args[0].name) == '_FinalizeLater\x00':
return False
raise RuntimeError(
"a finalizer raised an exception, shouldn't happen")
diff --git a/rpython/memory/test/test_gc.py b/rpython/memory/test/test_gc.py
--- a/rpython/memory/test/test_gc.py
+++ b/rpython/memory/test/test_gc.py
@@ -264,7 +264,7 @@
b.num_finalized += 1
debug_print("call to finalizer() number", b.num_finalized)
if (b.num_finalized % 3) == 0:
- raise rgc.FinalizeLater
+ raise rgc._FinalizeLater
def f(x):
a = A()
rgc.register_finalizer(a.finalizer)
diff --git a/rpython/rlib/rgc.py b/rpython/rlib/rgc.py
--- a/rpython/rlib/rgc.py
+++ b/rpython/rlib/rgc.py
@@ -6,6 +6,7 @@
from rpython.rlib import jit
from rpython.rlib.objectmodel import we_are_translated, enforceargs, specialize
+from rpython.rlib.objectmodel import CDefinedIntSymbolic
from rpython.rlib.nonconst import NonConstant
from rpython.rtyper.extregistry import ExtRegistryEntry
from rpython.rtyper.lltypesystem import lltype, llmemory
@@ -270,7 +271,7 @@
# ____________________________________________________________
-class FinalizeLater(Exception):
+class _FinalizeLater(Exception):
pass
_finalizer_queue = collections.deque()
@@ -286,6 +287,12 @@
progress_through_finalizer_queue()
delattr(g, '__disable_del')
+gc_supports_finalize_later = CDefinedIntSymbolic('GC_SUPPORTS_FINALIZE_LATER',
+ default=1)
+def finalize_later():
+ if gc_supports_finalize_later:
+ raise _FinalizeLater
+
def register_finalizer(method):
"NOT_RPYTHON"
# Cheat, cheat. When method() is called, its 'self' will actually be
@@ -336,7 +343,7 @@
obj, func = _finalizer_queue.popleft()
try:
func(obj)
- except FinalizeLater:
+ except _FinalizeLater:
_finalizer_queue.appendleft((obj, func))
break
except Exception, e:
diff --git a/rpython/rlib/test/test_rgc.py b/rpython/rlib/test/test_rgc.py
--- a/rpython/rlib/test/test_rgc.py
+++ b/rpython/rlib/test/test_rgc.py
@@ -258,7 +258,7 @@
def finalize(self):
if len(seen) < 3:
seen.append((self.x, self.y))
- raise rgc.FinalizeLater
+ raise rgc._FinalizeLater
seen.append(True)
p = Point(40, 2)
rgc.register_finalizer(p.finalize)
diff --git a/rpython/rtyper/llinterp.py b/rpython/rtyper/llinterp.py
--- a/rpython/rtyper/llinterp.py
+++ b/rpython/rtyper/llinterp.py
@@ -981,9 +981,6 @@
op_boehm_malloc = op_boehm_malloc_atomic = op_raw_malloc
- def op_boehm_register_finalizer(self, p, finalizer):
- pass
-
def op_boehm_disappearing_link(self, link, obj):
pass
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
@@ -413,7 +413,6 @@
'boehm_malloc': LLOp(),
'boehm_malloc_atomic': LLOp(),
- 'boehm_register_finalizer': LLOp(),
'boehm_disappearing_link': LLOp(),
'raw_malloc': LLOp(),
'raw_malloc_usage': LLOp(sideeffects=False),
diff --git a/rpython/translator/c/funcgen.py b/rpython/translator/c/funcgen.py
--- a/rpython/translator/c/funcgen.py
+++ b/rpython/translator/c/funcgen.py
@@ -600,10 +600,6 @@
return 'OP_BOEHM_ZERO_MALLOC(%s, %s, void*, 1, 0);' % (self.expr(op.args[0]),
self.expr(op.result))
- def OP_BOEHM_REGISTER_FINALIZER(self, op):
- return 'GC_REGISTER_FINALIZER(%s, (GC_finalization_proc)%s, NULL, NULL, NULL);' \
- % (self.expr(op.args[0]), self.expr(op.args[1]))
-
def OP_RAW_MALLOC(self, op):
eresult = self.expr(op.result)
esize = self.expr(op.args[0])
diff --git a/rpython/translator/c/src/mem.h b/rpython/translator/c/src/mem.h
--- a/rpython/translator/c/src/mem.h
+++ b/rpython/translator/c/src/mem.h
@@ -91,6 +91,10 @@
#endif /* RPY_ASSERT */
+
+#define GC_SUPPORTS_FINALIZE_LATER 1
+
+
/* for Boehm GC */
#ifdef PYPY_USING_BOEHM_GC
@@ -123,6 +127,10 @@
#define OP_GC__DISABLE_FINALIZERS(r) boehm_gc_finalizer_lock++
#define OP_GC__ENABLE_FINALIZERS(r) (boehm_gc_finalizer_lock--, \
boehm_gc_finalizer_notifier())
+#define OP_GC_REGISTER_FINALIZER(x, y, r) \
+ GC_REGISTER_FINALIZER(x, (GC_finalization_proc)y, NULL, NULL, NULL)
+#undef GC_SUPPORTS_FINALIZE_LATER
+#define GC_SUPPORTS_FINALIZE_LATER 0
#endif /* PYPY_USING_BOEHM_GC */
@@ -133,6 +141,9 @@
#define OP_BOEHM_DISAPPEARING_LINK(link, obj, r) /* nothing */
#define OP_GC__DISABLE_FINALIZERS(r) /* nothing */
#define OP_GC__ENABLE_FINALIZERS(r) /* nothing */
+#define OP_GC_REGISTER_FINALIZER(x, y, r) /* nothing */
+#undef GC_SUPPORTS_FINALIZE_LATER
+#define GC_SUPPORTS_FINALIZE_LATER 0
#endif
/************************************************************/
diff --git a/rpython/translator/c/test/test_boehm.py b/rpython/translator/c/test/test_boehm.py
--- a/rpython/translator/c/test/test_boehm.py
+++ b/rpython/translator/c/test/test_boehm.py
@@ -136,9 +136,9 @@
assert 0 < res1 <= 10
assert 0 < res2 <= 5
- def test_del_raises(self):
+ def test_finalizer_raises(self):
class A(object):
- def __del__(self):
+ def finalizer(self):
s.dels += 1
raise Exception
class State:
@@ -164,6 +164,35 @@
# it might be the test's fault though.
assert res > 0
+ def test_finalizer_raises(self):
+ class A(object):
+ def finalizer(self):
+ s.dels += 1
+ class State:
+ pass
+ s = State()
+ s.dels = 0
+ def g():
+ a = A()
+ rgc.register_finalizer(a.finalizer)
+ assert not rgc.gc_supports_finalize_later
+ def f():
+ s.dels = 0
+ for i in range(10):
+ g()
+ llop.gc__collect(lltype.Void)
+ return s.dels
+ fn = self.getcompiled(f)
+ # we can't demand that boehm has collected all of the objects,
+ # even with the gc__collect call. calling the compiled
+ # function twice seems to help, though.
+ res = 0
+ res += fn()
+ res += fn()
+ # if res is still 0, then we haven't tested anything so fail.
+ # it might be the test's fault though.
+ assert res > 0
+
def test_memory_error_varsize(self):
N = int(2**31-1)
A = lltype.GcArray(lltype.Char)
diff --git a/rpython/translator/c/test/test_newgc.py b/rpython/translator/c/test/test_newgc.py
--- a/rpython/translator/c/test/test_newgc.py
+++ b/rpython/translator/c/test/test_newgc.py
@@ -413,8 +413,9 @@
def finalizer(self):
b.num_deleted += 1
if b.num_deleted == 3:
- raise rgc.FinalizeLater
+ rgc.finalize_later()
def f():
+ assert rgc.gc_supports_finalize_later
A()
i = 0
while i < 5:
More information about the pypy-commit
mailing list