[pypy-commit] pypy py3.5: merge default into py3.5
mattip
pypy.commits at gmail.com
Sun Apr 15 02:00:49 EDT 2018
Author: Matti Picus <matti.picus at 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):
More information about the pypy-commit
mailing list