Author: Armin Rigo <[email protected]>
Branch: gc-del
Changeset: r62758:ff9d7eba9314
Date: 2013-03-25 21:37 +0100
http://bitbucket.org/pypy/pypy/changeset/ff9d7eba9314/
Log: test_gc and test_transformed_gc pass now (with MiniMark only!)
diff --git a/rpython/memory/gc/base.py b/rpython/memory/gc/base.py
--- a/rpython/memory/gc/base.py
+++ b/rpython/memory/gc/base.py
@@ -331,13 +331,6 @@
def debug_check_object(self, obj):
pass
- def register_finalizer(self, gcobj, llfn):
- llobj = llmemory.cast_ptr_to_adr(gcobj)
- self._register_finalizer(llobj, llfn)
-
- def _register_finalizer(self, obj, llfn):
- raise NotImplementedError # must be overridden
-
def execute_finalizers(self):
if self.running_finalizers:
return # the outer invocation of execute_finalizers() will do it
diff --git a/rpython/memory/gc/minimark.py b/rpython/memory/gc/minimark.py
--- a/rpython/memory/gc/minimark.py
+++ b/rpython/memory/gc/minimark.py
@@ -973,7 +973,7 @@
"the card marker bits are not cleared")
i -= 1
- def _register_finalizer(self, obj, llfn):
+ def register_finalizer(self, obj, llfn):
if self.header(obj).tid & (
GCFLAG_HAS_FINALIZER | # obj has already a finalizer
GCFLAG_NO_HEAP_PTRS): # immortal object anyway, and we don't
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
@@ -431,6 +431,12 @@
annmodel.SomeInteger(nonneg=True)],
annmodel.s_None)
+ self.register_finalizer_ptr = getfn(GCClass.register_finalizer.im_func,
+ [s_gc,
+ annmodel.SomeAddress(),
+ annmodel.SomeAddress()],
+ annmodel.s_None)
+
self.write_barrier_ptr = None
self.write_barrier_from_array_ptr = None
if GCClass.needs_write_barrier:
@@ -1194,8 +1200,14 @@
def pop_roots(self, hop, livevars):
raise NotImplementedError
- def gct_gc_register_finalizer(self, op):
- xxx
+ def gct_gc_register_finalizer(self, hop):
+ v_obj, v_func = hop.spaceop.args
+ v_obj_addr = hop.genop("cast_ptr_to_adr", [v_obj],
+ resulttype = llmemory.Address)
+ hop.genop("direct_call", [self.register_finalizer_ptr,
+ self.c_const_gc,
+ v_obj_addr, v_func],
+ resultvar = hop.spaceop.result)
class TransformerLayoutBuilder(gctypelayout.TypeLayoutBuilder):
diff --git a/rpython/memory/gctypelayout.py b/rpython/memory/gctypelayout.py
--- a/rpython/memory/gctypelayout.py
+++ b/rpython/memory/gctypelayout.py
@@ -1,10 +1,10 @@
from rpython.rtyper.lltypesystem import lltype, llmemory, llarena, llgroup
from rpython.rtyper.lltypesystem import rclass
from rpython.rtyper.lltypesystem.lloperation import llop
-from rpython.rlib.debug import ll_assert, debug_print
+from rpython.rlib.debug import ll_assert, debug_print, llinterpcall
from rpython.rlib.rarithmetic import intmask
from rpython.rlib import rgc
-from rpython.rlib.objectmodel import we_are_translated
+from rpython.rlib.objectmodel import we_are_translated, running_on_llinterp
from rpython.tool.identity_dict import identity_dict
@@ -140,14 +140,36 @@
return infobits & T_ANY_SLOW_FLAG == 0
def q_call_finalizer(self, finalizer, obj):
+ if not we_are_translated():
+ return GCData.p_call_finalizer(finalizer, obj)
+ if running_on_llinterp:
+ return llinterpcall(lltype.Bool, GCData.p_call_finalizer,
+ finalizer, obj)
finalizer = llmemory.cast_adr_to_ptr(finalizer, self.FINALIZER)
try:
finalizer(obj)
except rgc.FinalizeLater:
return False
except Exception:
- debug_print("exception from finalizer", finalizer, "of", obj)
- llop.debug_fatalerror(lltype.Void, "exception from finalizer!")
+ debug_print("WARNING: unhandled exception from finalizer",
+ finalizer, "of", obj)
+ return True
+
+ @staticmethod
+ def p_call_finalizer(finalizer, obj):
+ "NOT_RPYTHON"
+ from rpython.rtyper.llinterp import LLInterpreter, LLException
+ FUNC = lltype.typeOf(finalizer.ptr).TO
+ obj = llmemory.cast_adr_to_ptr(obj, FUNC.ARGS[0])
+ llinterp = LLInterpreter.current_interpreter
+ try:
+ llinterp.eval_graph(finalizer.ptr._obj.graph, [obj],
+ recursive=True)
+ except LLException, e:
+ if ''.join(e.args[0].name) == 'FinalizeLater\x00':
+ return False
+ raise RuntimeError(
+ "a finalizer raised an exception, shouldn't happen")
return True
@@ -404,11 +426,8 @@
# must be overridden for proper custom tracer support
return None
- def initialize_gc_query_function(self, gc, call_finalizer=None):
- gcdata = GCData(self.type_info_group)
- if call_finalizer is not None:
- gcdata.q_call_finalizer = call_finalizer # for tests
- gcdata.set_query_functions(gc)
+ def initialize_gc_query_function(self, gc):
+ GCData(self.type_info_group).set_query_functions(gc)
def consider_constant(self, TYPE, value, gc):
if value is not lltype.top_container(value):
diff --git a/rpython/memory/gcwrapper.py b/rpython/memory/gcwrapper.py
--- a/rpython/memory/gcwrapper.py
+++ b/rpython/memory/gcwrapper.py
@@ -29,8 +29,7 @@
lltype2vtable,
self.llinterp)
self.get_type_id = layoutbuilder.get_type_id
- layoutbuilder.initialize_gc_query_function(
- self.gc, layoutbuilder._call_finalizer)
+ layoutbuilder.initialize_gc_query_function(self.gc)
constants = collect_constants(flowgraphs)
for obj in constants:
@@ -169,7 +168,8 @@
return (hdr.tid & self.gc.gcflag_extra) != 0
def register_finalizer(self, llptr, llfn):
- self.gc.register_finalizer(llptr, llfn)
+ llobj = llmemory.cast_ptr_to_adr(llptr)
+ self.gc.register_finalizer(llobj, llfn)
# ____________________________________________________________
@@ -239,19 +239,6 @@
else:
return None
- def _call_finalizer(self, finalizer, obj):
- FUNC = lltype.typeOf(finalizer.ptr).TO
- obj = llmemory.cast_adr_to_ptr(obj, FUNC.ARGS[0])
- try:
- self.llinterp.eval_graph(finalizer.ptr._obj.graph, [obj],
- recursive=True)
- except llinterp.LLException, e:
- if ''.join(e.args[0].name) == 'FinalizeLater\x00':
- return False
- raise RuntimeError(
- "a finalizer raised an exception, shouldn't happen")
- return True
-
def collect_constants(graphs):
constants = {}
diff --git a/rpython/memory/test/snippet.py b/rpython/memory/test/snippet.py
--- a/rpython/memory/test/snippet.py
+++ b/rpython/memory/test/snippet.py
@@ -140,12 +140,13 @@
class B:
count = 0
class A:
- def __del__(self):
+ def finalizer(self):
self.b.count += 1
def g():
b = B()
a = A()
a.b = b
+ rgc.register_finalizer(a.finalizer)
i = 0
lst = [None]
while i < MAX:
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
@@ -373,8 +373,6 @@
count = 0
a = A()
class B(object):
- def __init__(self, ref):
- rgc.register_finalizer(self.finalizer)
def finalizer(self):
# when the finalizer is called, the weakref to myself is
# still valid in RPython
@@ -383,7 +381,8 @@
b = B()
ref = weakref.ref(b)
b.ref = ref
- return b
+ rgc.register_finalizer(b.finalizer)
+ return ref
def f():
ref = g()
llop.gc__collect(lltype.Void)
@@ -412,14 +411,12 @@
res = self.interpret(f, [])
assert res
- def test_cycle_with_weakref_and_del(self):
+ def test_cycle_with_weakref_and_finalizer(self):
import weakref
class A(object):
count = 0
a = A()
class B(object):
- def __init__(self, ref):
- rgc.register_finalizer(self.finalizer)
def finalizer(self):
# when the finalizer is called, the weakref to c should be dead
if self.ref() is None:
@@ -433,6 +430,7 @@
c.b = B()
ref = weakref.ref(c)
c.b.ref = ref
+ rgc.register_finalizer(c.b.finalizer)
return ref
def f():
ref = g()
@@ -448,13 +446,12 @@
class A(object):
pass
class B(object):
- def __init__(self, ref):
- rgc.register_finalizer(self.finalizer)
def finalizer(self):
self.wref().x += 1
def g(a):
b = B()
b.wref = weakref.ref(a)
+ rgc.register_finalizer(b.finalizer)
# the only way to reach this weakref is via B, which is an
# object with finalizer (but the weakref itself points to
# a, which does not go away but will move during the next
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit