Author: Matti Picus <matti.pi...@gmail.com> Branch: py3.5 Changeset: r94333:599b7470b778 Date: 2018-04-15 08:48 +0300 http://bitbucket.org/pypy/pypy/changeset/599b7470b778/
Log: merge default into py3.5 diff --git a/pypy/doc/whatsnew-head.rst b/pypy/doc/whatsnew-head.rst --- a/pypy/doc/whatsnew-head.rst +++ b/pypy/doc/whatsnew-head.rst @@ -6,3 +6,7 @@ .. startrev: f22145c34985 +.. branch: issue2752 + +Fix a rare GC bug that was introduced more than one year ago, but was +not diagnosed before issue #2752. 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 @@ -731,14 +731,16 @@ def move_out_of_nursery(self, obj): # called twice, it should return the same shadow object, - # and not creating another shadow object - if self.header(obj).tid & GCFLAG_HAS_SHADOW: - shadow = self.nursery_objects_shadows.get(obj) - ll_assert(shadow != llmemory.NULL, - "GCFLAG_HAS_SHADOW but no shadow found") - return shadow - - return self._allocate_shadow(obj, copy=True) + # and not creating another shadow object. As a safety feature, + # when called on a non-nursery object, do nothing. + if not self.is_in_nursery(obj): + return obj + shadow = self._find_shadow(obj) + if (self.header(obj).tid & GCFLAG_SHADOW_INITIALIZED) == 0: + self.header(obj).tid |= GCFLAG_SHADOW_INITIALIZED + totalsize = self.get_size(obj) + llmemory.raw_memcopy(obj, shadow, totalsize) + return shadow def collect(self, gen=2): """Do a minor (gen=0), start a major (gen=1), or do a full @@ -2074,13 +2076,12 @@ ll_assert(newobj != llmemory.NULL, "GCFLAG_HAS_SHADOW but no shadow found") newhdr = newobj - size_gc_header # - # Remove the flag GCFLAG_HAS_SHADOW, so that it doesn't get - # copied to the shadow itself. - self.header(obj).tid &= ~GCFLAG_HAS_SHADOW + # The flags GCFLAG_HAS_SHADOW and GCFLAG_SHADOW_INITIALIZED + # have no meaning in non-nursery objects. We don't need to + # remove them explicitly here before doing the copy. tid = self.header(obj).tid if (tid & GCFLAG_SHADOW_INITIALIZED) != 0: copy = False - self.header(obj).tid &= ~GCFLAG_SHADOW_INITIALIZED # totalsize = size_gc_header + self.get_size(obj) self.nursery_surviving_size += raw_malloc_usage(totalsize) @@ -2644,8 +2645,7 @@ # ---------- # id() and identityhash() support - @specialize.arg(2) - def _allocate_shadow(self, obj, copy=False): + def _allocate_shadow(self, obj): size_gc_header = self.gcheaderbuilder.size_gc_header size = self.get_size(obj) shadowhdr = self._malloc_out_of_nursery(size_gc_header + @@ -2667,12 +2667,6 @@ # self.header(obj).tid |= GCFLAG_HAS_SHADOW self.nursery_objects_shadows.setitem(obj, shadow) - - if copy: - self.header(obj).tid |= GCFLAG_SHADOW_INITIALIZED - totalsize = size_gc_header + self.get_size(obj) - llmemory.raw_memcopy(obj - size_gc_header, shadow, totalsize) - return shadow def _find_shadow(self, obj): diff --git a/rpython/memory/gc/test/test_direct.py b/rpython/memory/gc/test/test_direct.py --- a/rpython/memory/gc/test/test_direct.py +++ b/rpython/memory/gc/test/test_direct.py @@ -671,6 +671,25 @@ self.gc.debug_gc_step_until(incminimark.STATE_SCANNING) assert self.stackroots[1].x == 13 + def test_move_out_of_nursery(self): + obj0 = self.malloc(S) + obj0.x = 123 + adr1 = self.gc.move_out_of_nursery(llmemory.cast_ptr_to_adr(obj0)) + obj1 = llmemory.cast_adr_to_ptr(adr1, lltype.Ptr(S)) + assert obj1.x == 123 + # + import pytest + obj2 = self.malloc(S) + obj2.x = 456 + adr3 = self.gc._find_shadow(llmemory.cast_ptr_to_adr(obj2)) + obj3 = llmemory.cast_adr_to_ptr(adr3, lltype.Ptr(S)) + with pytest.raises(lltype.UninitializedMemoryAccess): + obj3.x # the shadow is not populated yet + adr4 = self.gc.move_out_of_nursery(llmemory.cast_ptr_to_adr(obj2)) + assert adr4 == adr3 + assert obj3.x == 456 # it is populated now + + class TestIncrementalMiniMarkGCFull(DirectGCTest): from rpython.memory.gc.incminimark import IncrementalMiniMarkGC as GCClass def test_malloc_fixedsize_no_cleanup(self): _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit