[pypy-commit] pypy lightweight-finalizers: chained objects unallowed
fijal
noreply at buildbot.pypy.org
Sun Oct 9 13:41:26 CEST 2011
Author: Maciej Fijalkowski <fijall at gmail.com>
Branch: lightweight-finalizers
Changeset: r47891:78904ead20ab
Date: 2011-10-09 13:41 +0200
http://bitbucket.org/pypy/pypy/changeset/78904ead20ab/
Log: chained objects unallowed
diff --git a/pypy/rpython/memory/gc/base.py b/pypy/rpython/memory/gc/base.py
--- a/pypy/rpython/memory/gc/base.py
+++ b/pypy/rpython/memory/gc/base.py
@@ -63,6 +63,7 @@
def set_query_functions(self, is_varsize, has_gcptr_in_varsize,
is_gcarrayofgcptr,
getfinalizer,
+ getlightfinalizer,
offsets_to_gc_pointers,
fixed_size, varsize_item_sizes,
varsize_offset_to_variable_part,
@@ -75,6 +76,7 @@
get_custom_trace,
fast_path_tracing):
self.getfinalizer = getfinalizer
+ self.getlightfinalizer = getlightfinalizer
self.is_varsize = is_varsize
self.has_gcptr_in_varsize = has_gcptr_in_varsize
self.is_gcarrayofgcptr = is_gcarrayofgcptr
@@ -140,6 +142,7 @@
size = self.fixed_size(typeid)
needs_finalizer = bool(self.getfinalizer(typeid))
+ finalizer_is_light = bool(self.getlightfinalizer(typeid))
contains_weakptr = self.weakpointer_offset(typeid) >= 0
assert not (needs_finalizer and contains_weakptr)
if self.is_varsize(typeid):
@@ -159,6 +162,7 @@
else:
malloc_fixedsize = self.malloc_fixedsize
ref = malloc_fixedsize(typeid, size, needs_finalizer,
+ finalizer_is_light,
contains_weakptr)
# lots of cast and reverse-cast around...
return llmemory.cast_ptr_to_adr(ref)
diff --git a/pypy/rpython/memory/gc/semispace.py b/pypy/rpython/memory/gc/semispace.py
--- a/pypy/rpython/memory/gc/semispace.py
+++ b/pypy/rpython/memory/gc/semispace.py
@@ -82,7 +82,7 @@
self.free = self.tospace
MovingGCBase.setup(self)
self.objects_with_finalizers = self.AddressDeque()
- self.objects_with_raw_mem = self.AddressStack()
+ self.objects_with_light_finalizers = self.AddressStack()
self.objects_with_weakrefs = self.AddressStack()
def _teardown(self):
@@ -94,7 +94,9 @@
# because the spaces are filled with zeroes in advance.
def malloc_fixedsize_clear(self, typeid16, size,
- has_finalizer=False, contains_weakptr=False):
+ has_finalizer=False,
+ has_light_finalizer=False,
+ contains_weakptr=False):
size_gc_header = self.gcheaderbuilder.size_gc_header
totalsize = size_gc_header + size
result = self.free
@@ -103,10 +105,10 @@
llarena.arena_reserve(result, totalsize)
self.init_gc_object(result, typeid16)
self.free = result + totalsize
- if has_finalizer:
+ if has_light_finalizer:
+ self.objects_with_light_finalizers.append(result + size_gc_header)
+ elif has_finalizer:
self.objects_with_finalizers.append(result + size_gc_header)
- if self.has_raw_mem_ptr(typeid16):
- self.objects_with_raw_mem.append(result + size_gc_header)
if contains_weakptr:
self.objects_with_weakrefs.append(result + size_gc_header)
return llmemory.cast_adr_to_ptr(result+size_gc_header, llmemory.GCREF)
@@ -266,10 +268,10 @@
if self.run_finalizers.non_empty():
self.update_run_finalizers()
scan = self.scan_copied(scan)
+ if self.objects_with_light_finalizers.non_empty():
+ self.deal_with_objects_with_light_finalizers()
if self.objects_with_finalizers.non_empty():
scan = self.deal_with_objects_with_finalizers(scan)
- if self.objects_with_raw_mem.non_empty():
- self.deal_with_objects_with_raw_mem()
if self.objects_with_weakrefs.non_empty():
self.invalidate_weakrefs()
self.update_objects_with_id()
@@ -476,6 +478,14 @@
# immortal objects always have GCFLAG_FORWARDED set;
# see get_forwarding_address().
+ def deal_with_objects_with_light_finalizers(self):
+ """ This is a much simpler version of dealing with finalizers
+ and an optimization - we can reasonably assume that those finalizers
+ don't do anything fancy and *just* call them. Among other things
+ they won't resurrect objects
+ """
+ xxx
+
def deal_with_objects_with_finalizers(self, scan):
# walk over list of objects with finalizers
# if it is not copied, add it to the list of to-be-called finalizers
@@ -528,17 +538,6 @@
self.objects_with_finalizers = new_with_finalizer
return scan
- def deal_with_objects_with_raw_mem(self):
- new_with_raw_mem = self.AddressStack()
- while self.objects_with_raw_mem.non_empty():
- addr = self.objects_with_raw_mem.pop()
- if self.surviving(addr):
- new_with_raw_mem.append(self.get_forwarding_address(addr))
- else:
- self._free_raw_mem_from(addr)
- self.objects_with_raw_mem = new_with_raw_mem
-
-
def _append_if_nonnull(pointer, stack):
stack.append(pointer.address[0])
_append_if_nonnull = staticmethod(_append_if_nonnull)
diff --git a/pypy/rpython/memory/gctransform/framework.py b/pypy/rpython/memory/gctransform/framework.py
--- a/pypy/rpython/memory/gctransform/framework.py
+++ b/pypy/rpython/memory/gctransform/framework.py
@@ -258,6 +258,7 @@
[s_gc, s_typeid16,
annmodel.SomeInteger(nonneg=True),
annmodel.SomeBool(),
+ annmodel.SomeBool(),
annmodel.SomeBool()], s_gcref,
inline = False)
if hasattr(GCClass, 'malloc_fixedsize'):
diff --git a/pypy/rpython/memory/gctypelayout.py b/pypy/rpython/memory/gctypelayout.py
--- a/pypy/rpython/memory/gctypelayout.py
+++ b/pypy/rpython/memory/gctypelayout.py
@@ -84,6 +84,13 @@
else:
return lltype.nullptr(GCData.FINALIZER_OR_CT_FUNC)
+ def q_light_finalizer(self, typeid):
+ typeinfo = self.get(typeid)
+ if typeinfo.infobits & T_HAS_LIGHTWEIGHT_FINALIZER:
+ return typeinfo.finalizer_or_customtrace
+ else:
+ return lltype.nullptr(GCData.FINALIZER_OR_CT_FUNC)
+
def q_offsets_to_gc_pointers(self, typeid):
return self.get(typeid).ofstoptrs
@@ -141,6 +148,7 @@
self.q_has_gcptr_in_varsize,
self.q_is_gcarrayofgcptr,
self.q_finalizer,
+ self.q_light_finalizer,
self.q_offsets_to_gc_pointers,
self.q_fixed_size,
self.q_varsize_item_sizes,
diff --git a/pypy/translator/backendopt/finalizer.py b/pypy/translator/backendopt/finalizer.py
--- a/pypy/translator/backendopt/finalizer.py
+++ b/pypy/translator/backendopt/finalizer.py
@@ -11,7 +11,7 @@
* anything that escapes self
* anything that can allocate
"""
- ok_operations = ['getfield', 'ptr_nonzero', 'free', 'same_as',
+ ok_operations = ['ptr_nonzero', 'free', 'same_as',
'direct_ptradd', 'force_cast', 'cast_primitive',
'cast_pointer']
@@ -25,4 +25,9 @@
if not isinstance(TP, lltype.Ptr) or TP.TO._gckind == 'raw':
# primitive type
return self.bottom_result()
+ if op.opname == 'getfield':
+ TP = op.result.concretetype
+ if not isinstance(TP, lltype.Ptr) or TP.TO._gckind == 'raw':
+ # primitive type
+ return self.bottom_result()
return self.top_result()
diff --git a/pypy/translator/backendopt/test/test_finalizer.py b/pypy/translator/backendopt/test/test_finalizer.py
--- a/pypy/translator/backendopt/test/test_finalizer.py
+++ b/pypy/translator/backendopt/test/test_finalizer.py
@@ -80,6 +80,24 @@
r = self.analyze(g, [], f, backendopt=True)
assert not r
+ def test_chain(self):
+ class B(object):
+ def __init__(self):
+ self.counter = 1
+
+ class A(object):
+ def __init__(self):
+ self.x = B()
+
+ def __del__(self):
+ self.x.counter += 1
+
+ def f():
+ A()
+
+ r = self.analyze(f, [], A.__del__.im_func)
+ assert r
+
def test_os_call(self):
py.test.skip("can allocate OSError, but also can raise, ignore for now")
import os
More information about the pypy-commit
mailing list