Author: Armin Rigo <[email protected]>
Branch: cpyext-gc-support
Changeset: r80287:15ef951bf126
Date: 2015-10-16 19:41 +0200
http://bitbucket.org/pypy/pypy/changeset/15ef951bf126/
Log: Second half of the test
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
@@ -2170,9 +2170,13 @@
# finalizers/weak references are rare and short which means that
# they do not need a separate state and do not need to be
# made incremental.
+ # For now, the same applies to rawrefcount'ed objects.
if (not self.objects_to_trace.non_empty() and
not self.more_objects_to_trace.non_empty()):
#
+ if self.rrc_enabled:
+ self.rrc_major_collection_trace()
+ #
if self.objects_with_finalizers.non_empty():
self.deal_with_objects_with_finalizers()
elif self.old_objects_with_weakrefs.non_empty():
@@ -2207,6 +2211,10 @@
self.old_objects_pointing_to_pinned = \
new_old_objects_pointing_to_pinned
self.updated_old_objects_pointing_to_pinned = True
+ #
+ if self.rrc_enabled:
+ self.rrc_major_collection_free()
+ #
self.gc_state = STATE_SWEEPING
#END MARKING
elif self.gc_state == STATE_SWEEPING:
@@ -2760,7 +2768,7 @@
self.rrc_p_list_old = self.AddressStack()
self.rrc_o_list_young = self.AddressStack()
self.rrc_o_list_old = self.AddressStack()
- self.rrc_dict = self.AddressDict()
+ self.rrc_p_dict = self.AddressDict()
p = lltype.malloc(self._ADDRARRAY, 1, flavor='raw',
track_allocation=False)
self.rrc_singleaddr = llmemory.cast_ptr_to_adr(p)
@@ -2775,11 +2783,11 @@
self.rrc_p_list_old.append(pyobject)
objint = llmemory.cast_adr_to_int(obj, mode="symbolic")
self._pyobj(pyobject).ob_pypy_link = objint
- self.rrc_dict.setitem(obj, pyobject)
+ self.rrc_p_dict.setitem(obj, pyobject)
def rawrefcount_from_obj(self, gcobj):
obj = llmemory.cast_ptr_to_adr(gcobj)
- return self.rrc_dict.get(obj)
+ return self.rrc_p_dict.get(obj)
def rawrefcount_to_obj(self, pyobject):
obj = llmemory.cast_int_to_adr(self._pyobj(pyobject).ob_pypy_link)
@@ -2808,10 +2816,7 @@
while lst.non_empty():
self._rrc_minor_free(lst.pop(), self.rrc_p_list_old)
- def _rrc_minor_free(self, pyobject, add_into_list):
- from rpython.rlib.rawrefcount import REFCNT_FROM_PYPY
- from rpython.rlib.rawrefcount import REFCNT_FROM_PYPY_DIRECT
- #
+ def _rrc_minor_free(self, pyobject, surviving_list):
intobj = self._pyobj(pyobject).ob_pypy_link
obj = llmemory.cast_int_to_adr(intobj)
if self.is_in_nursery(obj):
@@ -2820,7 +2825,7 @@
obj = self.get_forwarding_address(obj)
intobj = llmemory.cast_adr_to_int(obj, mode="symbolic")
self._pyobj(pyobject).ob_pypy_link = intobj
- self.rrc_dict.setitem(obj, pyobject)
+ self.rrc_p_dict.setitem(obj, pyobject)
surviving = True
else:
surviving = False
@@ -2833,16 +2838,65 @@
surviving = False
#
if surviving:
- add_into_list.append(obj)
+ surviving_list.append(pyobject)
else:
- rc = self._pyobj(pyobject).ob_refcnt
- if rc == self.REFCNT_FROM_PYPY_DIRECT:
- llmemory.raw_free(pyobject)
+ self._rrc_free(pyobject)
+
+ def _rrc_free(self, pyobject):
+ from rpython.rlib.rawrefcount import REFCNT_FROM_PYPY
+ from rpython.rlib.rawrefcount import REFCNT_FROM_PYPY_DIRECT
+ #
+ rc = self._pyobj(pyobject).ob_refcnt
+ if rc == REFCNT_FROM_PYPY_DIRECT:
+ lltype.free(self._pyobj(pyobject), flavor='raw')
+ else:
+ if rc > REFCNT_FROM_PYPY_DIRECT:
+ rc -= REFCNT_FROM_PYPY_DIRECT
else:
- if rc > self.REFCNT_FROM_PYPY_DIRECT:
- rc -= self.REFCNT_FROM_PYPY_DIRECT
- else:
- rc -= self.REFCNT_FROM_PYPY
- if rc == 0:
- xxx # _Py_Dealloc(pyobject)
- self._pyobj(pyobject).ob_refcnt = rc
+ rc -= REFCNT_FROM_PYPY
+ if rc == 0:
+ xxx # _Py_Dealloc(pyobject)
+ self._pyobj(pyobject).ob_refcnt = rc
+ _rrc_free._always_inline_ = True
+
+ def rrc_major_collection_trace(self):
+ self.rrc_p_list_old.foreach(self._rrc_major_trace, None)
+
+ def _rrc_major_trace(self, pyobject, ignore):
+ from rpython.rlib.rawrefcount import REFCNT_FROM_PYPY
+ from rpython.rlib.rawrefcount import REFCNT_FROM_PYPY_DIRECT
+ #
+ rc = self._pyobj(pyobject).ob_refcnt
+ if rc == REFCNT_FROM_PYPY or rc == REFCNT_FROM_PYPY_DIRECT:
+ pass # the corresponding object may die
+ else:
+ # force the corresponding object to be alive
+ intobj = self._pyobj(pyobject).ob_pypy_link
+ obj = llmemory.cast_int_to_adr(intobj)
+ self.objects_to_trace.append(obj)
+ self.visit_all_objects()
+
+ def rrc_major_collection_free(self):
+ new_p_list = self.AddressStack()
+ if self.rrc_p_dict.length() > self.rrc_p_list_old.length() * 2 + 30:
+ new_p_dict = self.AddressDict()
+ else:
+ new_p_dict = self.null_address_dict()
+ while self.rrc_p_list_old.non_empty():
+ self._rrc_major_free(self.rrc_p_list_old.pop(), new_p_list,
+ new_p_dict)
+ self.rrc_p_list_old.delete()
+ self.rrc_p_list_old = new_p_list
+ if new_p_dict:
+ self.rrc_p_dict.delete()
+ self.rrc_p_dict = new_p_dict
+
+ def _rrc_major_free(self, pyobject, surviving_list, surviving_dict):
+ intobj = self._pyobj(pyobject).ob_pypy_link
+ obj = llmemory.cast_int_to_adr(intobj)
+ if self.header(obj).tid & GCFLAG_VISITED:
+ surviving_list.append(pyobject)
+ if surviving_dict:
+ surviving_dict.setitem(obj, pyobject)
+ else:
+ self._rrc_free(pyobject)
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
@@ -1,3 +1,4 @@
+import py
from rpython.rtyper.lltypesystem import lltype, llmemory
from rpython.memory.gc.incminimark import IncrementalMiniMarkGC
from rpython.memory.gc.test.test_direct import BaseDirectGCTest
@@ -61,16 +62,24 @@
lltype.free(r2, flavor='raw')
def test_rawrefcount_objects_collection_survives_from_raw(self):
- for do_collect in [self.gc.minor_collection, self.gc.collect] * 2:
- p1, p1ref, r1, r1addr = self._rawrefcount_pair(42, is_direct=True)
- assert r1.ob_refcnt == REFCNT_FROM_PYPY_DIRECT
- r1.ob_refcnt += 1
- do_collect()
- assert r1.ob_refcnt == REFCNT_FROM_PYPY_DIRECT + 1
+ def check_alive(extra_refcount):
+ assert r1.ob_refcnt == REFCNT_FROM_PYPY_DIRECT + extra_refcount
assert r1.ob_pypy_link != 0
p1ref = self.gc.rawrefcount_to_obj(r1addr)
assert lltype.cast_opaque_ptr(lltype.Ptr(S), p1ref).x == 42
assert self.gc.rawrefcount_from_obj(p1ref) == r1addr
+ p1, p1ref, r1, r1addr = self._rawrefcount_pair(42, is_direct=True)
+ assert r1.ob_refcnt == REFCNT_FROM_PYPY_DIRECT
+ r1.ob_refcnt += 1
+ self.gc.minor_collection()
+ check_alive(+1)
+ self.gc.collect()
+ check_alive(+1)
+ r1.ob_refcnt -= 1
+ self.gc.minor_collection()
+ check_alive(0)
+ self.gc.collect()
+ py.test.raises(RuntimeError, "r1.ob_refcnt") # dead
def test_rawrefcount_objects_collection_survives_from_obj(self):
for do_collect in [self.gc.minor_collection, self.gc.collect] * 2:
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit