[pypy-commit] pypy gc-del-3: still progressing, slowly
arigo
pypy.commits at gmail.com
Tue May 3 03:26:04 EDT 2016
Author: Armin Rigo <arigo at tunes.org>
Branch: gc-del-3
Changeset: r84168:67a03224c02d
Date: 2016-05-03 09:26 +0200
http://bitbucket.org/pypy/pypy/changeset/67a03224c02d/
Log: still progressing, slowly
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
@@ -1,6 +1,7 @@
from rpython.rtyper.lltypesystem import lltype, llmemory, llarena, rffi
from rpython.rtyper.lltypesystem.lloperation import llop
from rpython.rlib.debug import ll_assert
+from rpython.rlib.objectmodel import we_are_translated
from rpython.memory.gcheader import GCHeaderBuilder
from rpython.memory.support import DEFAULT_CHUNK_SIZE
from rpython.memory.support import get_address_stack, get_address_deque
@@ -36,8 +37,26 @@
def setup(self):
# all runtime mutable values' setup should happen here
# and in its overriden versions! for the benefit of test_transformed_gc
- self.finalizer_lock_count = 0
- self.run_finalizers = self.AddressDeque()
+ self.finalizer_lock = False
+ if we_are_translated():
+ XXXXXX
+ else:
+ self._finalizer_queue_objects = [] # XXX FIX ME
+
+ def register_finalizer_index(self, fq, index):
+ while len(self._finalizer_queue_objects) <= index:
+ self._finalizer_queue_objects.append(None)
+ if self._finalizer_queue_objects[index] is None:
+ fq._reset()
+ self._finalizer_queue_objects[index] = fq
+ else:
+ assert self._finalizer_queue_objects[index] is fq
+
+ def add_finalizer_to_run(self, fq_index, obj):
+ if we_are_translated():
+ XXXXXX
+ else:
+ self._finalizer_queue_objects[fq_index]._queue.append(obj)
def post_setup(self):
# More stuff that needs to be initialized when the GC is already
@@ -60,6 +79,7 @@
def set_query_functions(self, is_varsize, has_gcptr_in_varsize,
is_gcarrayofgcptr,
+ finalizer_trigger,
destructor_or_custom_trace,
offsets_to_gc_pointers,
fixed_size, varsize_item_sizes,
@@ -73,6 +93,7 @@
fast_path_tracing,
has_gcptr,
cannot_pin):
+ self.finalizer_trigger = finalizer_trigger
self.destructor_or_custom_trace = destructor_or_custom_trace
self.is_varsize = is_varsize
self.has_gcptr_in_varsize = has_gcptr_in_varsize
@@ -320,9 +341,17 @@
callback2, attrname = _convert_callback_formats(callback) # :-/
setattr(self, attrname, arg)
self.root_walker.walk_roots(callback2, callback2, callback2)
- self.run_finalizers.foreach(callback, arg)
+ self.enum_pending_finalizers(callback, arg)
enumerate_all_roots._annspecialcase_ = 'specialize:arg(1)'
+ def enum_pending_finalizers(self, callback, arg):
+ if we_are_translated():
+ XXXXXX #. foreach(callback, arg)
+ for fq in self._finalizer_queue_objects:
+ for obj in fq._queue:
+ callback(obj, arg)
+ enum_pending_finalizers._annspecialcase_ = 'specialize:arg(1)'
+
def debug_check_consistency(self):
"""To use after a collection. If self.DEBUG is set, this
enumerates all roots and traces all objects to check if we didn't
@@ -362,17 +391,17 @@
pass
def execute_finalizers(self):
- self.finalizer_lock_count += 1
+ if self.finalizer_lock:
+ return # the outer invocation of execute_finalizers() will do it
+ self.finalizer_lock = True
try:
- while self.run_finalizers.non_empty():
- if self.finalizer_lock_count > 1:
- # the outer invocation of execute_finalizers() will do it
- break
- obj = self.run_finalizers.popleft()
- finalizer = self.getfinalizer(self.get_type_id(obj))
- finalizer(obj)
+ if we_are_translated():
+ XXXXXX
+ for i, fq in enumerate(self._finalizer_queue_objects):
+ if len(fq._queue) > 0:
+ self.finalizer_trigger(i)
finally:
- self.finalizer_lock_count -= 1
+ self.finalizer_lock = False
class MovingGCBase(GCBase):
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
@@ -2422,7 +2422,7 @@
#
# If we are in an inner collection caused by a call to a finalizer,
# the 'run_finalizers' objects also need to be kept alive.
- self.run_finalizers.foreach(self._collect_obj, None)
+ self.enum_pending_finalizers(self._collect_obj, None)
def enumerate_all_roots(self, callback, arg):
self.prebuilt_root_objects.foreach(callback, arg)
@@ -2676,8 +2676,9 @@
state = self._finalization_state(x)
ll_assert(state >= 2, "unexpected finalization state < 2")
if state == 2:
- # XXX use fq_nr here
- self.run_finalizers.append(x)
+ from rpython.rtyper.lltypesystem import rffi
+ fq_index = rffi.cast(lltype.Signed, fq_nr)
+ self.add_finalizer_to_run(fq_index, x)
# we must also fix the state from 2 to 3 here, otherwise
# we leave the GCFLAG_FINALIZATION_ORDERING bit behind
# which will confuse the next collection
diff --git a/rpython/memory/gctypelayout.py b/rpython/memory/gctypelayout.py
--- a/rpython/memory/gctypelayout.py
+++ b/rpython/memory/gctypelayout.py
@@ -83,6 +83,12 @@
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 q_finalizer_trigger(self, fq_index):
+ self.finalizer_trigger(fq_index)
+
def q_destructor_or_custom_trace(self, typeid):
return self.get(typeid).customfunc
@@ -136,6 +142,7 @@
self.q_is_varsize,
self.q_has_gcptr_in_varsize,
self.q_is_gcarrayofgcptr,
+ self.q_finalizer_trigger,
self.q_destructor_or_custom_trace,
self.q_offsets_to_gc_pointers,
self.q_fixed_size,
@@ -374,13 +381,17 @@
return result
def make_destructor_funcptr_for_type(self, TYPE):
- # must be overridden for proper finalizer support
+ # must be overridden for proper destructor support
return None
def make_custom_trace_funcptr_for_type(self, TYPE):
# must be overridden for proper custom tracer support
return None
+ def make_finalizer_trigger(self):
+ # must be overridden for proper finalizer support
+ return None
+
def initialize_gc_query_function(self, gc):
gcdata = GCData(self.type_info_group)
gcdata.set_query_functions(gc)
diff --git a/rpython/memory/gcwrapper.py b/rpython/memory/gcwrapper.py
--- a/rpython/memory/gcwrapper.py
+++ b/rpython/memory/gcwrapper.py
@@ -1,6 +1,6 @@
from rpython.translator.backendopt.finalizer import FinalizerAnalyzer
from rpython.rtyper.lltypesystem import lltype, llmemory, llheap
-from rpython.rtyper import llinterp
+from rpython.rtyper import llinterp, rclass
from rpython.rtyper.annlowlevel import llhelper
from rpython.memory import gctypelayout
from rpython.flowspace.model import Constant
@@ -16,12 +16,14 @@
chunk_size = 10,
translated_to_c = False,
**GC_PARAMS)
+ self.translator = translator
self.gc.set_root_walker(LLInterpRootWalker(self))
self.gc.DEBUG = True
self.llinterp = llinterp
self.prepare_graphs(flowgraphs)
self.gc.setup()
- self.finalizer_queues = {}
+ self.finalizer_queue_indexes = {}
+ self.finalizer_queues = []
self.has_write_barrier_from_array = hasattr(self.gc,
'write_barrier_from_array')
@@ -32,6 +34,7 @@
self.llinterp)
self.get_type_id = layoutbuilder.get_type_id
gcdata = layoutbuilder.initialize_gc_query_function(self.gc)
+ gcdata.init_finalizer_trigger(self.finalizer_trigger)
constants = collect_constants(flowgraphs)
for obj in constants:
@@ -189,18 +192,38 @@
def thread_run(self):
pass
+ def finalizer_trigger(self, fq_index):
+ fq = self.finalizer_queues[fq_index]
+ graph = self.translator._graphof(fq.finalizer_trigger.im_func)
+ try:
+ self.llinterp.eval_graph(graph, [None], recursive=True)
+ except llinterp.LLException:
+ raise RuntimeError(
+ "finalizer_trigger() raised an exception, shouldn't happen")
+
def get_finalizer_queue_index(self, fq_tag):
assert fq_tag.expr == 'FinalizerQueue TAG'
fq = fq_tag.default
- return self.finalizer_queues.setdefault(fq, len(self.finalizer_queues))
+ try:
+ index = self.finalizer_queue_indexes[fq]
+ except KeyError:
+ index = len(self.finalizer_queue_indexes)
+ assert index == len(self.finalizer_queues)
+ self.finalizer_queue_indexes[fq] = index
+ self.finalizer_queues.append(fq)
+ return (fq, index)
def gc_fq_next_dead(self, fq_tag):
- index = self.get_finalizer_queue_index(fq_tag)
- xxx
+ fq, _ = self.get_finalizer_queue_index(fq_tag)
+ addr = fq.next_dead()
+ if addr is None:
+ addr = llmemory.NULL
+ return llmemory.cast_adr_to_ptr(addr, rclass.OBJECTPTR)
def gc_fq_register(self, fq_tag, ptr):
- index = self.get_finalizer_queue_index(fq_tag)
+ fq, index = self.get_finalizer_queue_index(fq_tag)
ptr = lltype.cast_opaque_ptr(llmemory.GCREF, ptr)
+ self.gc.register_finalizer_index(fq, index)
self.gc.register_finalizer(index, ptr)
# ____________________________________________________________
diff --git a/rpython/rlib/rgc.py b/rpython/rlib/rgc.py
--- a/rpython/rlib/rgc.py
+++ b/rpython/rlib/rgc.py
@@ -390,7 +390,8 @@
from rpython.rtyper.lltypesystem.lloperation import llop
from rpython.rtyper.rclass import OBJECTPTR
from rpython.rtyper.annlowlevel import cast_base_ptr_to_instance
- ptr = llop.gc_fq_next_dead(OBJECTPTR, self._get_tag())
+ tag = FinalizerQueue._get_tag(self)
+ ptr = llop.gc_fq_next_dead(OBJECTPTR, tag)
return cast_base_ptr_to_instance(self.Class, ptr)
try:
return self._queue.popleft()
@@ -404,24 +405,27 @@
from rpython.rtyper.lltypesystem.lloperation import llop
from rpython.rtyper.rclass import OBJECTPTR
from rpython.rtyper.annlowlevel import cast_instance_to_base_ptr
+ tag = FinalizerQueue._get_tag(self)
ptr = cast_instance_to_base_ptr(obj)
- llop.gc_fq_register(lltype.Void, self._get_tag(), ptr)
+ llop.gc_fq_register(lltype.Void, tag, ptr)
return
else:
self._untranslated_register_finalizer(obj)
- @specialize.memo()
def _get_tag(self):
- return CDefinedIntSymbolic('FinalizerQueue TAG', default=self)
+ "NOT_RPYTHON: special-cased below"
+
+ def _reset(self):
+ import collections
+ self._weakrefs = set()
+ self._queue = collections.deque()
def _untranslated_register_finalizer(self, obj):
if hasattr(obj, '__enable_del_for_id'):
return # already called
if not hasattr(self, '_queue'):
- import collections
- self._weakrefs = set()
- self._queue = collections.deque()
+ self._reset()
# Fetch and check the type of 'obj'
objtyp = obj.__class__
@@ -483,6 +487,23 @@
_fq_patched_classes = set()
+class FqTagEntry(ExtRegistryEntry):
+ _about_ = FinalizerQueue._get_tag.im_func
+
+ def compute_result_annotation(self, s_fq):
+ assert s_fq.is_constant()
+ fq = s_fq.const
+ s_func = self.bookkeeper.immutablevalue(fq.finalizer_trigger)
+ self.bookkeeper.emulate_pbc_call(self.bookkeeper.position_key,
+ s_func, [])
+ if not hasattr(fq, '_fq_tag'):
+ fq._fq_tag = CDefinedIntSymbolic('FinalizerQueue TAG', default=fq)
+ return self.bookkeeper.immutablevalue(fq._fq_tag)
+
+ def specialize_call(self, hop):
+ hop.exception_cannot_occur()
+ return hop.inputconst(lltype.Signed, hop.s_result.const)
+
# ____________________________________________________________
More information about the pypy-commit
mailing list