[pypy-commit] pypy default: Extend FinalizerQueue to be able to handle low-level GCREF pointers
arigo
pypy.commits at gmail.com
Tue Mar 20 02:38:38 EDT 2018
Author: Armin Rigo <arigo at tunes.org>
Branch:
Changeset: r94019:c4654fc5b220
Date: 2018-03-20 07:37 +0100
http://bitbucket.org/pypy/pypy/changeset/c4654fc5b220/
Log: Extend FinalizerQueue to be able to handle low-level GCREF pointers
directly, instead of high-level instances of some class
diff --git a/rpython/rlib/rgc.py b/rpython/rlib/rgc.py
--- a/rpython/rlib/rgc.py
+++ b/rpython/rlib/rgc.py
@@ -385,6 +385,7 @@
#
# Class:
# the class (or base class) of finalized objects
+ # --or-- None to handle low-level GCREFs directly
#
# def finalizer_trigger(self):
# called to notify that new items have been put in the queue
@@ -397,11 +398,13 @@
def next_dead(self):
if we_are_translated():
from rpython.rtyper.lltypesystem.lloperation import llop
- from rpython.rtyper.rclass import OBJECTPTR
- from rpython.rtyper.annlowlevel import cast_base_ptr_to_instance
+ from rpython.rtyper.lltypesystem.llmemory import GCREF
+ from rpython.rtyper.annlowlevel import cast_gcref_to_instance
tag = FinalizerQueue._get_tag(self)
- ptr = llop.gc_fq_next_dead(OBJECTPTR, tag)
- return cast_base_ptr_to_instance(self.Class, ptr)
+ ptr = llop.gc_fq_next_dead(GCREF, tag)
+ if self.Class is not None:
+ ptr = cast_gcref_to_instance(self.Class, ptr)
+ return ptr
try:
return self._queue.popleft()
except (AttributeError, IndexError):
@@ -410,14 +413,18 @@
@specialize.arg(0)
@jit.dont_look_inside
def register_finalizer(self, obj):
- assert isinstance(obj, self.Class)
+ from rpython.rtyper.lltypesystem.llmemory import GCREF
+ if self.Class is None:
+ assert lltype.typeOf(obj) == GCREF
+ else:
+ assert isinstance(obj, self.Class)
if we_are_translated():
from rpython.rtyper.lltypesystem.lloperation import llop
- from rpython.rtyper.rclass import OBJECTPTR
- from rpython.rtyper.annlowlevel import cast_instance_to_base_ptr
+ from rpython.rtyper.annlowlevel import cast_instance_to_gcref
tag = FinalizerQueue._get_tag(self)
- ptr = cast_instance_to_base_ptr(obj)
- llop.gc_fq_register(lltype.Void, tag, ptr)
+ if self.Class is not None:
+ obj = cast_instance_to_gcref(obj)
+ llop.gc_fq_register(lltype.Void, tag, obj)
return
else:
self._untranslated_register_finalizer(obj)
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
@@ -599,3 +599,94 @@
e = py.test.raises(TyperError, gengraph, f, [])
assert str(e.value).startswith('the RPython-level __del__() method in')
+
+ def test_translated_boehm(self):
+ self._test_translated(use_gc="boehm", llcase=False)
+
+ def test_translated_boehm_ll(self):
+ self._test_translated(use_gc="boehm", llcase=True)
+
+ def test_translated_incminimark(self):
+ self._test_translated(use_gc="incminimark", llcase=False)
+
+ def test_translated_incminimark_ll(self):
+ self._test_translated(use_gc="incminimark", llcase=True)
+
+ def _test_translated(self, use_gc, llcase):
+ import subprocess
+ from rpython.rlib import objectmodel
+ from rpython.translator.interactive import Translation
+ #
+ class Seen:
+ count = 0
+ class MySimpleFQ(rgc.FinalizerQueue):
+ if not llcase:
+ Class = T_Root
+ else:
+ Class = None
+ def finalizer_trigger(self):
+ seen.count += 1
+ seen = Seen()
+ fq = MySimpleFQ()
+ if not llcase:
+ EMPTY = None
+ llbuilder = T_Int
+ else:
+ from rpython.rtyper.annlowlevel import llstr
+ EMPTY = lltype.nullptr(llmemory.GCREF.TO)
+ def llbuilder(n):
+ return lltype.cast_opaque_ptr(llmemory.GCREF, llstr(str(n)))
+
+ def subfunc():
+ w0 = llbuilder(40); fq.register_finalizer(w0)
+ w1 = llbuilder(41); fq.register_finalizer(w1)
+ w2 = llbuilder(42); fq.register_finalizer(w2)
+ w3 = llbuilder(43); fq.register_finalizer(w3)
+ w4 = llbuilder(44); fq.register_finalizer(w4)
+ w5 = llbuilder(45); fq.register_finalizer(w5)
+ w6 = llbuilder(46); fq.register_finalizer(w6)
+ w7 = llbuilder(47); fq.register_finalizer(w7)
+ w8 = llbuilder(48); fq.register_finalizer(w8)
+ w9 = llbuilder(49); fq.register_finalizer(w9)
+ gc.collect()
+ assert seen.count == 0
+ assert fq.next_dead() is EMPTY
+ objectmodel.keepalive_until_here(w0)
+ objectmodel.keepalive_until_here(w1)
+ objectmodel.keepalive_until_here(w2)
+ objectmodel.keepalive_until_here(w3)
+ objectmodel.keepalive_until_here(w4)
+ objectmodel.keepalive_until_here(w5)
+ objectmodel.keepalive_until_here(w6)
+ objectmodel.keepalive_until_here(w7)
+ objectmodel.keepalive_until_here(w8)
+ objectmodel.keepalive_until_here(w9)
+
+ def main(argv):
+ assert fq.next_dead() is EMPTY
+ subfunc()
+ gc.collect(); gc.collect(); gc.collect()
+ assert seen.count > 0
+ n = fq.next_dead()
+ while True:
+ if not llcase:
+ assert type(n) is T_Int and 40 <= n.x <= 49
+ else:
+ from rpython.rtyper.lltypesystem.rstr import STR
+ assert lltype.typeOf(n) is llmemory.GCREF
+ p = lltype.cast_opaque_ptr(lltype.Ptr(STR), n)
+ assert len(p.chars) == 2
+ assert p.chars[0] == "4"
+ assert "0" <= p.chars[1] <= "9"
+ n = fq.next_dead()
+ if n is EMPTY:
+ break
+ print "OK!"
+ return 0
+ #
+ t = Translation(main, gc=use_gc)
+ t.disable(['backendopt'])
+ t.set_backend_extra_options(c_debug_defines=True)
+ exename = t.compile()
+ data = subprocess.check_output([str(exename), '.', '.', '.'])
+ assert data.strip().endswith('OK!')
More information about the pypy-commit
mailing list