[pypy-commit] pypy gc-del-3: More reverts, and adapt the docs
arigo
pypy.commits at gmail.com
Wed May 4 11:19:42 EDT 2016
Author: Armin Rigo <arigo at tunes.org>
Branch: gc-del-3
Changeset: r84188:4a45bfe534bc
Date: 2016-05-04 17:19 +0200
http://bitbucket.org/pypy/pypy/changeset/4a45bfe534bc/
Log: More reverts, and adapt the docs
diff --git a/pypy/doc/discussion/finalizer-order.rst b/pypy/doc/discussion/finalizer-order.rst
--- a/pypy/doc/discussion/finalizer-order.rst
+++ b/pypy/doc/discussion/finalizer-order.rst
@@ -12,10 +12,15 @@
* RPython objects can have ``__del__()``. These are called
immediately by the GC when the last reference to the object goes
- away, like in CPython. However (like "lightweight finalizers" used
- to be), all ``__del__()`` methods must only contain simple enough
- code, and this is checked. We call this "destructors". They can't
- use operations that would resurrect the object, for example.
+ away, like in CPython. However, the long-term goal is that all
+ ``__del__()`` methods should only contain simple enough code. If
+ they do, we call them "destructors". They can't use operations that
+ would resurrect the object, for example. Use the decorator
+ ``@rgc.must_be_light_finalizer`` to ensure they are destructors.
+
+* RPython-level ``__del__()`` that are not passing the destructor test
+ are supported for backward compatibility, but deprecated. The rest
+ of this document assumes that ``__del__()`` are all destructors.
* For any more advanced usage --- in particular for any app-level
object with a __del__ --- we don't use the RPython-level
diff --git a/rpython/doc/rpython.rst b/rpython/doc/rpython.rst
--- a/rpython/doc/rpython.rst
+++ b/rpython/doc/rpython.rst
@@ -191,9 +191,9 @@
``__setitem__`` for slicing isn't supported. Additionally, using negative
indices for slicing is still not support, even when using ``__getslice__``.
- Note that from May 2016 the destructor ``__del__`` must only contain
- `simple operations`__; for any kind of more complex destructor, see
- ``rpython.rlib.rgc.register_finalizer()``.
+ Note that the destructor ``__del__`` should only contain `simple
+ operations`__; for any kind of more complex destructor, consider
+ using instead ``rpython.rlib.rgc.FinalizerQueue``.
.. __: garbage_collection.html
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
@@ -147,15 +147,15 @@
the four malloc_[fixed,var]size[_clear]() functions.
"""
size = self.fixed_size(typeid)
- needs_destructor = (bool(self.destructor_or_custom_trace(typeid))
- and not self.has_custom_trace(typeid))
- finalizer_is_light = (needs_destructor and
+ needs_finalizer = (bool(self.destructor_or_custom_trace(typeid))
+ and not self.has_custom_trace(typeid))
+ finalizer_is_light = (needs_finalizer and
not self.is_old_style_finalizer(typeid))
contains_weakptr = self.weakpointer_offset(typeid) >= 0
- assert not (needs_destructor and contains_weakptr)
+ assert not (needs_finalizer and contains_weakptr)
if self.is_varsize(typeid):
assert not contains_weakptr
- assert not needs_destructor
+ assert not needs_finalizer
itemsize = self.varsize_item_sizes(typeid)
offset_to_length = self.varsize_offset_to_length(typeid)
if self.malloc_zero_filled:
@@ -170,7 +170,7 @@
malloc_fixedsize = self.malloc_fixedsize_clear
else:
malloc_fixedsize = self.malloc_fixedsize
- ref = malloc_fixedsize(typeid, size, needs_destructor,
+ ref = malloc_fixedsize(typeid, size, needs_finalizer,
finalizer_is_light,
contains_weakptr)
# lots of cast and reverse-cast around...
diff --git a/rpython/memory/gc/incminimark.py b/rpython/memory/gc/incminimark.py
--- a/rpython/memory/gc/incminimark.py
+++ b/rpython/memory/gc/incminimark.py
@@ -608,7 +608,7 @@
def malloc_fixedsize(self, typeid, size,
- needs_destructor=False,
+ needs_finalizer=False,
is_finalizer_light=False,
contains_weakptr=False):
size_gc_header = self.gcheaderbuilder.size_gc_header
@@ -617,7 +617,7 @@
#
# If the object needs a finalizer, ask for a rawmalloc.
# The following check should be constant-folded.
- if needs_destructor and not is_finalizer_light:
+ if needs_finalizer and not is_finalizer_light:
# old-style finalizers only!
from rpython.rtyper.lltypesystem import rffi
ll_assert(not contains_weakptr,
@@ -657,7 +657,7 @@
#
# If it is a weakref or has a lightweight destructor, record it
# (checks constant-folded).
- if needs_destructor:
+ if needs_finalizer:
self.young_objects_with_destructors.append(obj)
if contains_weakptr:
self.young_objects_with_weakrefs.append(obj)
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
@@ -307,6 +307,7 @@
[s_gc, s_typeid16,
annmodel.SomeInteger(nonneg=True),
annmodel.SomeBool(),
+ annmodel.SomeBool(),
annmodel.SomeBool()], s_gcref,
inline = False)
self.malloc_varsize_ptr = getfn(
@@ -321,6 +322,7 @@
[s_gc, s_typeid16,
annmodel.SomeInteger(nonneg=True),
annmodel.SomeBool(),
+ annmodel.SomeBool(),
annmodel.SomeBool()], s_gcref,
inline = False)
self.malloc_varsize_ptr = getfn(
@@ -383,7 +385,7 @@
malloc_fast,
[s_gc, s_typeid16,
annmodel.SomeInteger(nonneg=True),
- s_False, s_False], s_gcref,
+ s_False, s_False, s_False], s_gcref,
inline = True)
else:
self.malloc_fast_ptr = None
@@ -792,10 +794,11 @@
info = self.layoutbuilder.get_info(type_id)
c_size = rmodel.inputconst(lltype.Signed, info.fixedsize)
fptrs = self.special_funcptr_for_type(TYPE)
- has_destructor = "destructor" in fptrs
- assert "finalizer" not in fptrs # removed
- assert "light_finalizer" not in fptrs # removed
- c_has_destructor = rmodel.inputconst(lltype.Bool, has_destructor)
+ has_finalizer = "destructor" in fptrs or "old_style_finalizer" in fptrs
+ has_light_finalizer = "destructor" in fptrs
+ c_has_finalizer = rmodel.inputconst(lltype.Bool, has_finalizer)
+ c_has_light_finalizer = rmodel.inputconst(lltype.Bool,
+ has_light_finalizer)
if flags.get('nonmovable'):
assert op.opname == 'malloc'
@@ -805,16 +808,16 @@
elif not op.opname.endswith('_varsize') and not flags.get('varsize'):
zero = flags.get('zero', False)
if (self.malloc_fast_ptr is not None and
- not c_has_destructor.value and
+ not c_has_finalizer.value and
(self.malloc_fast_is_clearing or not zero)):
malloc_ptr = self.malloc_fast_ptr
else:
malloc_ptr = self.malloc_fixedsize_ptr
args = [self.c_const_gc, c_type_id, c_size,
- c_has_destructor,
+ c_has_finalizer, c_has_light_finalizer,
rmodel.inputconst(lltype.Bool, False)]
else:
- assert not c_has_destructor.value
+ assert not c_has_finalizer.value
info_varsize = self.layoutbuilder.get_info_varsize(type_id)
v_length = op.args[-1]
c_ofstolength = rmodel.inputconst(lltype.Signed,
@@ -950,12 +953,13 @@
def gct_do_malloc_fixedsize(self, hop):
# used by the JIT (see rpython.jit.backend.llsupport.gc)
op = hop.spaceop
- [v_typeid, v_size, v_has_destructor, v_contains_weakptr] = op.args
+ [v_typeid, v_size,
+ v_has_finalizer, v_has_light_finalizer, v_contains_weakptr] = op.args
livevars = self.push_roots(hop)
hop.genop("direct_call",
[self.malloc_fixedsize_ptr, self.c_const_gc,
v_typeid, v_size,
- v_has_destructor,
+ v_has_finalizer, v_has_light_finalizer,
v_contains_weakptr],
resultvar=op.result)
self.pop_roots(hop, livevars)
@@ -1063,7 +1067,7 @@
c_false = rmodel.inputconst(lltype.Bool, False)
c_has_weakptr = rmodel.inputconst(lltype.Bool, True)
args = [self.c_const_gc, c_type_id, c_size,
- c_false, c_has_weakptr]
+ c_false, c_false, c_has_weakptr]
# push and pop the current live variables *including* the argument
# to the weakref_create operation, which must be kept alive and
@@ -1595,7 +1599,7 @@
def make_destructor_funcptr_for_type(self, TYPE):
if not self.has_destructor(TYPE):
- return None
+ return None, False
rtti = get_rtti(TYPE)
destrptr = rtti._obj.destructor_funcptr
DESTR_ARG = lltype.typeOf(destrptr).TO.ARGS[0]
diff --git a/rpython/memory/test/test_transformed_gc.py b/rpython/memory/test/test_transformed_gc.py
--- a/rpython/memory/test/test_transformed_gc.py
+++ b/rpython/memory/test/test_transformed_gc.py
@@ -323,6 +323,35 @@
res = run([5, 42]) #XXX pure lazyness here too
assert res == 6
+ def define_old_style_finalizer(cls):
+ class B(object):
+ pass
+ b = B()
+ b.nextid = 0
+ b.num_deleted = 0
+ class A(object):
+ def __init__(self):
+ self.id = b.nextid
+ b.nextid += 1
+ def __del__(self):
+ llop.gc__collect(lltype.Void)
+ b.num_deleted += 1
+ def f(x, y):
+ a = A()
+ i = 0
+ while i < x:
+ i += 1
+ a = A()
+ llop.gc__collect(lltype.Void)
+ llop.gc__collect(lltype.Void)
+ return b.num_deleted
+ return f
+
+ def test_old_style_finalizer(self):
+ run = self.runner("old_style_finalizer")
+ res = run([5, 42]) #XXX pure lazyness here too
+ assert res == 6
+
def define_finalizer(cls):
class B(object):
pass
@@ -846,7 +875,8 @@
if op.opname == 'do_malloc_fixedsize':
op.args = [Constant(type_id, llgroup.HALFWORD),
Constant(llmemory.sizeof(P), lltype.Signed),
- Constant(False, lltype.Bool), # has_destructor
+ Constant(False, lltype.Bool), # has_finalizer
+ Constant(False, lltype.Bool), # has_finalizer_light
Constant(False, lltype.Bool)] # contains_weakptr
break
else:
@@ -882,7 +912,8 @@
if op.opname == 'do_malloc_fixedsize':
op.args = [Constant(type_id, llgroup.HALFWORD),
Constant(llmemory.sizeof(P), lltype.Signed),
- Constant(False, lltype.Bool), # has_destructor
+ Constant(False, lltype.Bool), # has_finalizer
+ Constant(False, lltype.Bool), # has_finalizer_light
Constant(False, lltype.Bool)] # contains_weakptr
break
else:
More information about the pypy-commit
mailing list