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