[pypy-commit] pypy cpyext-gc-cycle: Started implementation for gc.garbage, adapted interface
stevie_92
pypy.commits at gmail.com
Fri Mar 1 16:10:36 EST 2019
Author: Stefan Beyer <home at sbeyer.at>
Branch: cpyext-gc-cycle
Changeset: r96198:77d74e85609f
Date: 2019-03-01 22:09 +0100
http://bitbucket.org/pypy/pypy/changeset/77d74e85609f/
Log: Started implementation for gc.garbage, adapted interface
diff --git a/pypy/module/cpyext/state.py b/pypy/module/cpyext/state.py
--- a/pypy/module/cpyext/state.py
+++ b/pypy/module/cpyext/state.py
@@ -13,7 +13,6 @@
# context.
ExecutionContext.cpyext_operror = None
-
class State:
def __init__(self, space):
self.space = space
@@ -80,8 +79,6 @@
from pypy.interpreter.baseobjspace import W_Root
from pypy.module.cpyext.pyobject import PyObject, decref, \
incref, cts, finalize, from_ref
- w_list = space.getattr(space.builtin_modules['gc'],
- space.newtext('garbage'))
print 'dealloc_trigger...'
while True:
ob = rawrefcount.next_dead(PyObject)
@@ -116,17 +113,23 @@
if adr_int == llmemory.cast_adr_to_int(
llmemory.cast_ptr_to_adr(head)):
rawrefcount.cyclic_garbage_remove()
+ w_list = space.newlist([])
while True:
w_obj = rawrefcount.next_garbage_pypy(W_Root)
if not py_obj:
break
w_list.append(w_obj)
+ last_py_obj = lltype.nullptr(PyObject.TO)
while True:
- w_pyobj = rawrefcount.next_garbage_pyobj(PyObject)
- if not py_obj:
+ w_pyobj = rawrefcount.next_garbage_pyobj(PyObject,
+ last_py_obj)
+ if not w_pyobj:
break
w_obj = from_ref(space, w_pyobj)
w_list.append(w_obj)
+ last_py_obj = w_pyobj
+ space.setattr(space.builtin_modules['gc'],
+ space.newtext('garbage'), w_list)
print 'dealloc_trigger DONE'
return "RETRY"
def tp_traverse(pyobj_ptr, callback, args):
@@ -292,9 +295,6 @@
from pypy.module.cpyext.pyobject import (PyObject, incref, decref,
finalize, from_ref)
- w_list = space.getattr(space.builtin_modules['gc'],
- space.newtext('garbage'))
-
while True:
py_obj = rawrefcount.next_dead(PyObject)
if not py_obj:
@@ -321,17 +321,22 @@
if adr_int == llmemory.cast_adr_to_int(llmemory.cast_ptr_to_adr(head)):
rawrefcount.cyclic_garbage_remove()
+ w_list = space.newlist([])
while True:
w_obj = rawrefcount.next_garbage_pypy(W_Root)
if not py_obj:
break
w_list.append(w_obj)
+ last_py_obj = lltype.nullptr(PyObject.TO)
while True:
- w_pyobj = rawrefcount.next_garbage_pyobj(PyObject)
- if not py_obj:
+ w_pyobj = rawrefcount.next_garbage_pyobj(PyObject, last_py_obj)
+ if not w_pyobj:
break
w_obj = from_ref(space, w_pyobj)
w_list.append(w_obj)
+ last_py_obj = w_pyobj
+ space.setattr(space.builtin_modules['gc'], space.newtext('garbage'),
+ w_list)
class PyObjDeallocAction(executioncontext.AsyncAction):
"""An action that invokes _Py_Dealloc() on the dying PyObjects.
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
@@ -3063,6 +3063,16 @@
rrc_enabled = False
+ # The default state. Here cyclic garbage with legacy finalizers is marked.
+ RAWREFCOUNT_STATE_DEFAULT = 0
+
+ # The state in which cyclic garbage with legacy finalizers is traced.
+ # Do not mark objects during this state, because we remove the flag
+ # during tracing and we do not want to trace those objects again. Also
+ # during this phase no new objects can be marked, as we are only building
+ # the list of cyclic garbage.
+ RAWREFCOUNT_STATE_GARBAGE = 1
+
_ADDRARRAY = lltype.Array(llmemory.Address, hints={'nolength': True})
PYOBJ_HDR = lltype.Struct('GCHdr_PyObject',
('c_ob_refcnt', lltype.Signed),
@@ -3128,6 +3138,7 @@
self.rrc_pyobj_as_gc = pyobj_as_gc
self.rrc_finalizer_type = finalizer_type
self.rrc_enabled = True
+ self.rrc_state = self.RAWREFCOUNT_STATE_DEFAULT
def check_no_more_rawrefcount_state(self):
"NOT_RPYTHON: for tests"
@@ -3218,21 +3229,24 @@
next.c_gc_prev = gchdr
def rawrefcount_next_garbage_pypy(self):
+ if self.rrc_state == self.RAWREFCOUNT_STATE_DEFAULT:
+ self.rrc_state = self.RAWREFCOUNT_STATE_GARBAGE
+
# return the next pypy object which is only reachable from garbage
# pyobjects, probably need two more colors for this. one for marking
# so that they stay alive during sweep, one for marking, so they do not
# get returned here again
- return lltype.nullptr(llmemory.GCREF.TO)
-
- def rawrefcount_next_garbage_pyobj(self):
+ result = lltype.nullptr(llmemory.GCREF.TO)
+
+ if result == lltype.nullptr(llmemory.GCREF.TO):
+ self.rrc_state = self.RAWREFCOUNT_STATE_DEFAULT
+ return result
+
+ def rawrefcount_next_garbage_pyobj(self, curr_pyobj):
# implement st objects in this list still remain in the set of
# all pyobjs, because references could still change and cause them
# to live again. also keep in mind, that state will create references
# to pyobjs in this list and might increment the refcount.
-
- # use create_link_pyobj on the result to create gc objects for pyobjects
- #p = W_Root(42)
- #p.pyobj = ob
return llmemory.NULL
diff --git a/rpython/memory/gc/test/test_rawrefcount.py b/rpython/memory/gc/test/test_rawrefcount.py
--- a/rpython/memory/gc/test/test_rawrefcount.py
+++ b/rpython/memory/gc/test/test_rawrefcount.py
@@ -627,12 +627,16 @@
self.gc.rawrefcount_cyclic_garbage_remove()
next_dead = self.gc.rawrefcount_cyclic_garbage_head()
- next = self.gc.rawrefcount_next_garbage_pypy()
- while next <> lltype.nullptr(llmemory.GCREF.TO):
- garbage_pypy.append(next)
- next = self.gc.rawrefcount_next_garbage_pyobj()
+ next_garbage = self.gc.rawrefcount_next_garbage_pypy()
+ while next_garbage <> lltype.nullptr(llmemory.GCREF.TO):
+ garbage_pypy.append(next_garbage)
+ next_garbage = self.gc.rawrefcount_next_garbage_pypy()
+ last_pyobj = llmemory.NULL
+ next = self.gc.rawrefcount_next_garbage_pyobj(last_pyobj)
while next <> llmemory.NULL:
garbage_pyobj.append(next)
+ next = self.gc.rawrefcount_next_garbage_pyobj(last_pyobj)
+ last_pyobj = next
# do a collection to find cyclic isolates and clean them, if there are
# no finalizers
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
@@ -522,7 +522,7 @@
GCClass.rawrefcount_next_garbage_pypy, [s_gc],
s_gcref, inline = True)
self.rawrefcount_next_garbage_pyobj_ptr = getfn(
- GCClass.rawrefcount_next_garbage_pyobj, [s_gc],
+ GCClass.rawrefcount_next_garbage_pyobj, [s_gc, SomeAddress()],
SomeAddress(), inline = True)
if GCClass.can_usually_pin_objects:
@@ -1439,9 +1439,12 @@
resultvar=hop.spaceop.result)
def gct_gc_rawrefcount_next_garbage_pyobj(self, hop):
+ [v_pyobject] = hop.spaceop.args
+ assert v_pyobject.concretetype == llmemory.Address
assert hop.spaceop.result.concretetype == llmemory.Address
hop.genop("direct_call",
- [self.rawrefcount_next_garbage_pyobj_ptr, self.c_const_gc],
+ [self.rawrefcount_next_garbage_pyobj_ptr, self.c_const_gc,
+ v_pyobject],
resultvar=hop.spaceop.result)
def _set_into_gc_array_part(self, op):
diff --git a/rpython/rlib/rawrefcount.py b/rpython/rlib/rawrefcount.py
--- a/rpython/rlib/rawrefcount.py
+++ b/rpython/rlib/rawrefcount.py
@@ -147,10 +147,10 @@
@not_rpython
def next_garbage_pypy(Class):
- return lltype.nullptr(llmemory.GCREF.TO)
+ return None
@not_rpython
-def next_garbage_pyobj(OB_PTR_TYPE):
+def next_garbage_pyobj(OB_PTR_TYPE, curr_pyobj):
return lltype.nullptr(OB_PTR_TYPE.TO)
@not_rpython
@@ -375,8 +375,7 @@
return _spec_p(hop, v_p)
class Entry(ExtRegistryEntry):
- _about_ = (next_dead, cyclic_garbage_head, next_cyclic_isolate,
- next_garbage_pyobj)
+ _about_ = (next_dead, cyclic_garbage_head, next_cyclic_isolate)
def compute_result_annotation(self, s_OB_PTR_TYPE):
from rpython.rtyper.llannotation import lltype_to_annotation
@@ -390,13 +389,28 @@
name = 'gc_rawrefcount_cyclic_garbage_head'
elif self.instance is next_cyclic_isolate:
name = 'gc_rawrefcount_next_cyclic_isolate'
- elif self.instance is next_garbage_pyobj:
- name = 'gc_rawrefcount_next_garbage_pyobj'
hop.exception_cannot_occur()
v_ob = hop.genop(name, [], resulttype = llmemory.Address)
return _spec_ob(hop, v_ob)
class Entry(ExtRegistryEntry):
+ _about_ = next_garbage_pyobj
+
+ def compute_result_annotation(self, s_OB_PTR_TYPE, s_ob):
+ from rpython.rtyper.llannotation import lltype_to_annotation, SomePtr
+ assert s_OB_PTR_TYPE.is_constant()
+ assert isinstance(s_ob, SomePtr)
+ return lltype_to_annotation(s_OB_PTR_TYPE.const)
+
+ def specialize_call(self, hop):
+ hop.exception_cannot_occur()
+ v_ob = hop.inputarg(hop.args_r[1], arg=1)
+ v_ob_res = hop.genop('gc_rawrefcount_next_garbage_pyobj',
+ [_unspec_ob(hop, v_ob)],
+ resulttype = llmemory.Address)
+ return _spec_ob(hop, v_ob_res)
+
+class Entry(ExtRegistryEntry):
_about_ = next_garbage_pypy
def compute_result_annotation(self, s_Class):
More information about the pypy-commit
mailing list