Author: Armin Rigo <[email protected]>
Branch: gc-del-3
Changeset: r84184:70f42e6f2872
Date: 2016-05-04 10:00 +0200
http://bitbucket.org/pypy/pypy/changeset/70f42e6f2872/
Log: in-progress: "test_transformed_gc -k Inc" seems happy
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
@@ -7,6 +7,7 @@
from rpython.memory.support import get_address_stack, get_address_deque
from rpython.memory.support import AddressDict, null_address_dict
from rpython.rtyper.lltypesystem.llmemory import NULL, raw_malloc_usage
+from rpython.rtyper.annlowlevel import cast_adr_to_nongc_instance
TYPEID_MAP = lltype.GcStruct('TYPEID_MAP', ('count', lltype.Signed),
('size', lltype.Signed),
@@ -40,8 +41,8 @@
self.finalizer_lock = False
def mark_finalizer_to_run(self, fq_index, obj):
- fdeque = self.get_run_finalizer_queue(self.AddressDeque, fq_index)
- fdeque.append(obj)
+ handlers = self.finalizer_handlers()
+ self._adr2deque(handlers[fq_index].deque).append(obj)
def post_setup(self):
# More stuff that needs to be initialized when the GC is already
@@ -64,8 +65,7 @@
def set_query_functions(self, is_varsize, has_gcptr_in_varsize,
is_gcarrayofgcptr,
- finalizer_trigger,
- get_run_finalizer_queue,
+ finalizer_handlers,
destructor_or_custom_trace,
offsets_to_gc_pointers,
fixed_size, varsize_item_sizes,
@@ -79,8 +79,7 @@
fast_path_tracing,
has_gcptr,
cannot_pin):
- self.finalizer_trigger = finalizer_trigger
- self.get_run_finalizer_queue = get_run_finalizer_queue
+ self.finalizer_handlers = finalizer_handlers
self.destructor_or_custom_trace = destructor_or_custom_trace
self.is_varsize = is_varsize
self.has_gcptr_in_varsize = has_gcptr_in_varsize
@@ -332,12 +331,10 @@
enumerate_all_roots._annspecialcase_ = 'specialize:arg(1)'
def enum_pending_finalizers(self, callback, arg):
+ handlers = self.finalizer_handlers()
i = 0
- while True:
- fdeque = self.get_run_finalizer_queue(self.AddressDeque, i)
- if fdeque is None:
- break
- fdeque.foreach(callback, arg)
+ while i < len(handlers):
+ self._adr2deque(handlers[i].deque).foreach(callback, arg)
i += 1
enum_pending_finalizers._annspecialcase_ = 'specialize:arg(1)'
@@ -379,23 +376,25 @@
def debug_check_object(self, obj):
pass
+ def _adr2deque(self, adr):
+ return cast_adr_to_nongc_instance(self.AddressDeque, adr)
+
def execute_finalizers(self):
if self.finalizer_lock:
return # the outer invocation of execute_finalizers() will do it
self.finalizer_lock = True
try:
+ handlers = self.finalizer_handlers()
i = 0
- while True:
- fdeque = self.get_run_finalizer_queue(self.AddressDeque, i)
- if fdeque is None:
- break
- if fdeque.non_empty():
- self.finalizer_trigger(i)
+ while i < len(handlers):
+ if self._adr2deque(handlers[i].deque).non_empty():
+ handlers[i].trigger()
i += 1
finally:
self.finalizer_lock = False
def finalizer_next_dead(self, fq_index):
+ xxxxxxxxxxxx
fdeque = self.get_run_finalizer_queue(self.AddressDeque, fq_index)
if fdeque.non_empty():
obj = fdeque.popleft()
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
@@ -1568,8 +1568,8 @@
def register_finalizer(self, fq_index, gcobj):
from rpython.rtyper.lltypesystem import rffi
obj = llmemory.cast_ptr_to_adr(gcobj)
+ fq_index = rffi.cast(llmemory.Address, fq_index)
self.probably_young_objects_with_finalizers.append(obj)
- fq_index = rffi.cast(llmemory.Address, fq_index)
self.probably_young_objects_with_finalizers.append(fq_index)
# ----------
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
@@ -9,8 +9,10 @@
from rpython.memory import gctypelayout
from rpython.memory.gctransform.log import log
from rpython.memory.gctransform.support import get_rtti, ll_call_destructor
+from rpython.memory.gctransform.support import ll_report_finalizer_error
from rpython.memory.gctransform.transform import GCTransformer
from rpython.memory.gctypelayout import ll_weakref_deref, WEAKREF, WEAKREFPTR
+from rpython.memory.gctypelayout import FIN_TRIGGER_FUNC, FIN_HANDLER_ARRAY
from rpython.tool.sourcetools import func_with_new_name
from rpython.translator.backendopt import graphanalyze
from rpython.translator.backendopt.finalizer import FinalizerAnalyzer
@@ -181,9 +183,11 @@
gcdata.max_type_id = 13 # patched in finish()
gcdata.typeids_z = a_random_address # patched in finish()
gcdata.typeids_list = a_random_address # patched in finish()
+ gcdata.finalizer_handlers = a_random_address # patched in finish()
self.gcdata = gcdata
self.malloc_fnptr_cache = {}
self.finalizer_queue_indexes = {}
+ self.finalizer_handlers = []
gcdata.gc = GCClass(translator.config.translation, **GC_PARAMS)
root_walker = self.build_root_walker()
@@ -218,6 +222,7 @@
data_classdef.generalize_attr('max_type_id', annmodel.SomeInteger())
data_classdef.generalize_attr('typeids_z', SomeAddress())
data_classdef.generalize_attr('typeids_list', SomeAddress())
+ data_classdef.generalize_attr('finalizer_handlers', SomeAddress())
annhelper = annlowlevel.MixLevelHelperAnnotator(self.translator.rtyper)
@@ -256,7 +261,6 @@
self.layoutbuilder.encode_type_shapes_now()
self.create_custom_trace_funcs(gcdata.gc, translator.rtyper)
- self.create_finalizer_trigger(gcdata)
annhelper.finish() # at this point, annotate all mix-level helpers
annhelper.backend_optimize()
@@ -603,11 +607,6 @@
"the custom trace hook %r for %r can cause "
"the GC to be called!" % (func, TP))
- def create_finalizer_trigger(self, gcdata):
- def ll_finalizer_trigger(fq_index):
- pass #xxxxxxxxxxxxx
- gcdata.init_finalizer_trigger(ll_finalizer_trigger)
-
def consider_constant(self, TYPE, value):
self.layoutbuilder.consider_constant(TYPE, value, self.gcdata.gc)
@@ -692,8 +691,15 @@
ll_instance.inst_typeids_list=
llmemory.cast_ptr_to_adr(ll_typeids_list)
newgcdependencies.append(ll_typeids_list)
#
- # update this field too
- ll_instance.inst_run_finalizer_queues =
self.gcdata.run_finalizer_queues
+ handlers = self.finalizer_handlers
+ ll_handlers = lltype.malloc(FIN_HANDLER_ARRAY, len(handlers),
+ immortal=True)
+ for i in range(len(handlers)):
+ ll_handlers[i].deque = handlers[i][0]
+ ll_handlers[i].trigger = handlers[i][1]
+ ll_instance.inst_finalizer_handlers = llmemory.cast_ptr_to_adr(
+ ll_handlers)
+ newgcdependencies.append(ll_handlers)
#
return newgcdependencies
@@ -1515,8 +1521,34 @@
try:
index = self.finalizer_queue_indexes[fq]
except KeyError:
- index = self.gcdata.register_next_finalizer_queue(
- self.gcdata.gc.AddressDeque)
+ index = len(self.finalizer_queue_indexes)
+ assert index == len(self.finalizer_handlers)
+ deque = self.gcdata.gc.AddressDeque()
+ #
+ def ll_finalizer_trigger():
+ try:
+ fq.finalizer_trigger()
+ except Exception as e:
+ ll_report_finalizer_error(e)
+ ll_trigger = self.annotate_finalizer(ll_finalizer_trigger, [],
+ lltype.Void)
+ def ll_next_dead():
+ if deque.non_empty():
+ return deque.popleft()
+ else:
+ return llmemory.NULL
+ ll_next_dead = self.annotate_finalizer(ll_next_dead, [],
+ llmemory.Address)
+ c_ll_next_dead = rmodel.inputconst(lltype.typeOf(ll_next_dead),
+ ll_next_dead)
+ #
+ s_deque =
self.translator.annotator.bookkeeper.immutablevalue(deque)
+ r_deque = self.translator.rtyper.getrepr(s_deque)
+ ll_deque = r_deque.convert_const(deque)
+ adr_deque = llmemory.cast_ptr_to_adr(ll_deque)
+ #
+ self.finalizer_handlers.append((adr_deque, ll_trigger,
+ c_ll_next_dead))
self.finalizer_queue_indexes[fq] = index
return index
@@ -1530,7 +1562,12 @@
c_index, v_ptr])
def gct_gc_fq_next_dead(self, hop):
- xxxx
+ index = self.get_finalizer_queue_index(hop)
+ c_ll_next_dead = self.finalizer_handlers[index][2]
+ v_adr = hop.genop("direct_call", [c_ll_next_dead],
+ resulttype=llmemory.Address)
+ hop.genop("cast_adr_to_ptr", [v_adr],
+ resultvar = hop.spaceop.result)
class TransformerLayoutBuilder(gctypelayout.TypeLayoutBuilder):
diff --git a/rpython/memory/gctransform/support.py
b/rpython/memory/gctransform/support.py
--- a/rpython/memory/gctransform/support.py
+++ b/rpython/memory/gctransform/support.py
@@ -89,3 +89,11 @@
write(2, " ignoring it\n")
except:
pass
+
+def ll_report_finalizer_error(e):
+ try:
+ write(2, "triggering finalizers raised an exception ")
+ write(2, str(e))
+ write(2, " ignoring it\n")
+ except:
+ pass
diff --git a/rpython/memory/gctypelayout.py b/rpython/memory/gctypelayout.py
--- a/rpython/memory/gctypelayout.py
+++ b/rpython/memory/gctypelayout.py
@@ -4,9 +4,6 @@
from rpython.rlib.debug import ll_assert
from rpython.rlib.rarithmetic import intmask
from rpython.tool.identity_dict import identity_dict
-from rpython.memory.support import make_list_of_nongc_instances
-from rpython.memory.support import list_set_nongc_instance
-from rpython.memory.support import list_get_nongc_instance
class GCData(object):
@@ -50,7 +47,6 @@
assert isinstance(type_info_group, llgroup.group)
self.type_info_group = type_info_group
self.type_info_group_ptr = type_info_group._as_ptr()
- self.run_finalizer_queues = make_list_of_nongc_instances(1)
def get(self, typeid):
res = llop.get_group_member(GCData.TYPE_INFO_PTR,
@@ -87,30 +83,9 @@
ANY = (T_HAS_GCPTR | T_IS_WEAKREF)
return (typeinfo.infobits & ANY) != 0 or bool(typeinfo.customfunc)
- def init_finalizer_trigger(self, finalizer_trigger):
- self._finalizer_trigger = finalizer_trigger
-
- def register_next_finalizer_queue(self, AddressDeque):
- "NOT_RPYTHON"
- # 'self.run_finalizer_queues' has got no length, but is NULL-terminated
- prevlength = self.run_finalizer_queues._obj.getlength()
- array = make_list_of_nongc_instances(prevlength + 1)
- for i in range(prevlength):
- array[i] = self.run_finalizer_queues[i]
- self.run_finalizer_queues = array
- #
- fq_index = prevlength - 1
- assert fq_index >= 0
- list_set_nongc_instance(self.run_finalizer_queues, fq_index,
- AddressDeque())
- return fq_index
-
- def q_finalizer_trigger(self, fq_index):
- self._finalizer_trigger(fq_index)
-
- def q_get_run_finalizer_queue(self, AddressDeque, fq_index):
- return list_get_nongc_instance(AddressDeque,
- self.run_finalizer_queues, fq_index)
+ def q_finalizer_handlers(self):
+ adr = self.finalizer_handlers # set from framework.py or gcwrapper.py
+ return llmemory.cast_adr_to_ptr(adr, lltype.Ptr(FIN_HANDLER_ARRAY))
def q_destructor_or_custom_trace(self, typeid):
return self.get(typeid).customfunc
@@ -165,8 +140,7 @@
self.q_is_varsize,
self.q_has_gcptr_in_varsize,
self.q_is_gcarrayofgcptr,
- self.q_finalizer_trigger,
- self.q_get_run_finalizer_queue,
+ self.q_finalizer_handlers,
self.q_destructor_or_custom_trace,
self.q_offsets_to_gc_pointers,
self.q_fixed_size,
@@ -568,3 +542,9 @@
link = lltype.malloc(WEAKREF, immortal=True)
link.weakptr = llmemory.cast_ptr_to_adr(targetptr)
return link
+
+########## finalizers ##########
+
+FIN_TRIGGER_FUNC = lltype.FuncType([], lltype.Void)
+FIN_HANDLER_ARRAY = lltype.Array(('deque', llmemory.Address),
+ ('trigger', lltype.Ptr(FIN_TRIGGER_FUNC)))
diff --git a/rpython/memory/support.py b/rpython/memory/support.py
--- a/rpython/memory/support.py
+++ b/rpython/memory/support.py
@@ -396,17 +396,3 @@
def _null_value_checker(key, value, arg):
if value:
arg.setitem(key, value)
-
-# ____________________________________________________________
-
-NONGCARRAY = lltype.Array(NONGCOBJECTPTR, hints={'nolength': True})
-
-def make_list_of_nongc_instances(count):
- return lltype.malloc(NONGCARRAY, count, flavor='raw', zero=True,
- track_allocation=False)
-
-def list_get_nongc_instance(Class, array, index):
- return cast_base_ptr_to_nongc_instance(Class, array[index])
-
-def list_set_nongc_instance(array, index, instance):
- array[index] = cast_nongc_instance_to_base_ptr(instance)
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
@@ -50,6 +50,8 @@
taggedpointers = False
def setup_class(cls):
+ if cls is not TestIncrementalMiniMarkGC:
+ py.test.skip("FOO")
cls.marker = lltype.malloc(rffi.CArray(lltype.Signed), 1,
flavor='raw', zero=True)
funcs0 = []
diff --git a/rpython/rtyper/annlowlevel.py b/rpython/rtyper/annlowlevel.py
--- a/rpython/rtyper/annlowlevel.py
+++ b/rpython/rtyper/annlowlevel.py
@@ -526,6 +526,12 @@
ptr = lltype.cast_opaque_ptr(OBJECTPTR, ptr)
return cast_base_ptr_to_instance(Class, ptr)
[email protected](0)
+def cast_adr_to_nongc_instance(Class, ptr):
+ from rpython.rtyper.rclass import NONGCOBJECTPTR
+ ptr = llmemory.cast_adr_to_ptr(ptr, NONGCOBJECTPTR)
+ return cast_base_ptr_to_nongc_instance(Class, ptr)
+
class CastBasePtrToInstanceEntry(extregistry.ExtRegistryEntry):
_about_ = cast_base_ptr_to_instance
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit