[pypy-commit] pypy gc-disable: implement rgc.collect_step() through all the layers

antocuni pypy.commits at gmail.com
Wed May 30 12:43:41 EDT 2018


Author: Antonio Cuni <anto.cuni at gmail.com>
Branch: gc-disable
Changeset: r94712:868c42b150e9
Date: 2018-05-29 18:58 +0200
http://bitbucket.org/pypy/pypy/changeset/868c42b150e9/

Log:	implement rgc.collect_step() through all the layers

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
@@ -159,6 +159,9 @@
     def isenabled(self):
         return True
 
+    def collect_step(self):
+        return True
+
     def malloc(self, typeid, length=0, zero=False):
         """NOT_RPYTHON
         For testing.  The interface used by the gctransformer is
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
@@ -309,6 +309,8 @@
 
         self.collect_ptr = getfn(GCClass.collect.im_func,
             [s_gc, annmodel.SomeInteger()], annmodel.s_None)
+        self.collect_step_ptr = getfn(GCClass.collect_step.im_func, [s_gc],
+                                      annmodel.s_Bool)
         self.enable_ptr = getfn(GCClass.enable.im_func, [s_gc], annmodel.s_None)
         self.disable_ptr = getfn(GCClass.disable.im_func, [s_gc], annmodel.s_None)
         self.isenabled_ptr = getfn(GCClass.isenabled.im_func, [s_gc],
@@ -888,6 +890,13 @@
                   resultvar=op.result)
         self.pop_roots(hop, livevars)
 
+    def gct_gc__collect_step(self, hop):
+        op = hop.spaceop
+        livevars = self.push_roots(hop)
+        hop.genop("direct_call", [self.collect_step_ptr, self.c_const_gc],
+                  resultvar=op.result)
+        self.pop_roots(hop, livevars)
+
     def gct_gc__enable(self, hop):
         op = hop.spaceop
         hop.genop("direct_call", [self.enable_ptr, self.c_const_gc],
diff --git a/rpython/rlib/rgc.py b/rpython/rlib/rgc.py
--- a/rpython/rlib/rgc.py
+++ b/rpython/rlib/rgc.py
@@ -17,6 +17,14 @@
 disable = gc.disable
 isenabled = gc.isenabled
 
+def collect_step():
+    """
+    If the GC is incremental, run a single gc-collect-step. Return True when
+    the major collection is completed.
+    If the GC is not incremental, do nothing.
+    """
+    return True
+
 def set_max_heap_size(nbytes):
     """Limit the heap size to n bytes.
     """
@@ -153,6 +161,18 @@
         return hop.genop('gc__isenabled', hop.args_v, resulttype=hop.r_result)
 
 
+class CollectStepEntry(ExtRegistryEntry):
+    _about_ = collect_step
+
+    def compute_result_annotation(self):
+        from rpython.annotator import model as annmodel
+        return annmodel.s_Bool
+
+    def specialize_call(self, hop):
+        hop.exception_cannot_occur()
+        return hop.genop('gc__collect_step', hop.args_v, resulttype=hop.r_result)
+
+
 class SetMaxHeapSizeEntry(ExtRegistryEntry):
     _about_ = set_max_heap_size
 
diff --git a/rpython/rlib/test/test_rgc.py b/rpython/rlib/test/test_rgc.py
--- a/rpython/rlib/test/test_rgc.py
+++ b/rpython/rlib/test/test_rgc.py
@@ -56,6 +56,19 @@
     res = interpret(f, [])
     assert res
 
+def test_collect_step():
+    def f():
+        return rgc.collect_step()
+
+    assert f()
+    t, typer, graph = gengraph(f, [])
+    blockops = list(graph.iterblockops())
+    opnames = [op.opname for block, op in blockops
+               if op.opname.startswith('gc__')]
+    assert opnames == ['gc__collect_step']
+    res = interpret(f, [])
+    assert res
+
 
 def test_can_move():
     T0 = lltype.GcStruct('T')
diff --git a/rpython/rtyper/llinterp.py b/rpython/rtyper/llinterp.py
--- a/rpython/rtyper/llinterp.py
+++ b/rpython/rtyper/llinterp.py
@@ -819,6 +819,9 @@
     def op_gc__collect(self, *gen):
         self.heap.collect(*gen)
 
+    def op_gc__collect_step(self):
+        return self.heap.collect_step()
+
     def op_gc__enable(self):
         self.heap.enable()
 
diff --git a/rpython/rtyper/lltypesystem/llheap.py b/rpython/rtyper/lltypesystem/llheap.py
--- a/rpython/rtyper/lltypesystem/llheap.py
+++ b/rpython/rtyper/lltypesystem/llheap.py
@@ -5,7 +5,7 @@
 
 setfield = setattr
 from operator import setitem as setarrayitem
-from rpython.rlib.rgc import can_move, collect, enable, disable, isenabled, add_memory_pressure
+from rpython.rlib.rgc import can_move, collect, enable, disable, isenabled, add_memory_pressure, collect_step
 
 def setinterior(toplevelcontainer, inneraddr, INNERTYPE, newvalue,
                 offsets=None):
diff --git a/rpython/rtyper/lltypesystem/lloperation.py b/rpython/rtyper/lltypesystem/lloperation.py
--- a/rpython/rtyper/lltypesystem/lloperation.py
+++ b/rpython/rtyper/lltypesystem/lloperation.py
@@ -450,6 +450,7 @@
     # __________ GC operations __________
 
     'gc__collect':          LLOp(canmallocgc=True),
+    'gc__collect_step':     LLOp(canmallocgc=True),
     'gc__enable':           LLOp(),
     'gc__disable':          LLOp(),
     'gc__isenabled':        LLOp(),
diff --git a/rpython/translator/c/test/test_newgc.py b/rpython/translator/c/test/test_newgc.py
--- a/rpython/translator/c/test/test_newgc.py
+++ b/rpython/translator/c/test/test_newgc.py
@@ -1851,6 +1851,39 @@
         deleted = self.run("enable_disable", 1)
         assert deleted == 0
 
+    def define_collect_step(self):
+        class Counter(object):
+            val = 0
+        counter = Counter()
+        class X(object):
+            def __del__(self):
+                counter.val += 1
+        def f():
+            x1 = X()
+            rgc.collect() # make x1 old
+            assert not rgc.can_move(x1)
+            x1 = None
+            #
+            gc.disable()
+            n = 0
+            while True:
+                n += 1
+                if rgc.collect_step():
+                    break
+                if n == 100:
+                    print 'Endless loop!'
+                    assert False, 'this looks like an endless loop'
+                
+            if n < 4: # we expect at least 4 steps
+                print 'Too few steps! n =', n
+                assert False
+            return counter.val
+        return f
+
+    def test_collect_step(self):
+        deleted = self.run("collect_step")
+        assert deleted == 1
+
 
 # ____________________________________________________________________
 


More information about the pypy-commit mailing list