Author: Armin Rigo <ar...@tunes.org> 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) +@specialize.arg(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 pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit