[pypy-commit] pypy default: hg merge issue2752

arigo pypy.commits at gmail.com
Sat Apr 14 15:57:55 EDT 2018


Author: Armin Rigo <arigo at tunes.org>
Branch: 
Changeset: r94330:91ffd8f1e3f5
Date: 2018-04-14 21:56 +0200
http://bitbucket.org/pypy/pypy/changeset/91ffd8f1e3f5/

Log:	hg merge issue2752

diff --git a/pypy/module/cpyext/test/test_bufferobject.py b/pypy/module/cpyext/test/test_bufferobject.py
--- a/pypy/module/cpyext/test/test_bufferobject.py
+++ b/pypy/module/cpyext/test/test_bufferobject.py
@@ -4,6 +4,7 @@
 from pypy.module.cpyext.api import PyObject
 
 class AppTestBufferObject(AppTestCpythonExtensionBase):
+
     def test_FromMemory(self):
         module = self.import_extension('foo', [
             ("get_FromMemory", "METH_NOARGS",
@@ -62,3 +63,61 @@
         a = array.array('c', 'text')
         b = buffer(a)
         assert module.roundtrip(b) == 'text'
+
+
+    def test_issue2752(self):
+        iterations = 10
+        if self.runappdirect:
+            iterations = 2000
+        module = self.import_extension('foo', [
+            ("test_mod", 'METH_VARARGS',
+            """
+                PyObject *obj;
+                Py_buffer bp;
+                if (!PyArg_ParseTuple(args, "O", &obj))
+                    return NULL;
+
+                if (PyObject_GetBuffer(obj, &bp, PyBUF_SIMPLE) == -1)
+                    return NULL;
+                
+                if (((unsigned char*)bp.buf)[0] != '0') {
+                    void * buf = (void*)bp.buf;
+                    unsigned char val[4];
+                    unsigned char * s = PyString_AsString(obj);
+                    memcpy(val, bp.buf, 4);
+                    PyBuffer_Release(&bp);
+                    if (PyObject_GetBuffer(obj, &bp, PyBUF_SIMPLE) == -1)
+                        return NULL;
+                    PyErr_Format(PyExc_ValueError,
+                            "mismatch: %p [%x %x %x %x...] now %p [%x %x %x %x...] as str '%s'",
+                            buf, val[0], val[1], val[2], val[3],
+                            (void *)bp.buf,
+                            ((unsigned char*)bp.buf)[0],
+                            ((unsigned char*)bp.buf)[1],
+                            ((unsigned char*)bp.buf)[2],
+                            ((unsigned char*)bp.buf)[3],
+                            s);
+                    PyBuffer_Release(&bp);
+                    return NULL;
+                }
+
+                PyBuffer_Release(&bp);
+                Py_RETURN_NONE;
+            """),
+            ])
+        bufsize = 4096
+        def getdata(bufsize):
+            data = b'01234567'
+            for x in range(18):
+                data += data
+                if len(data) >= bufsize:
+                    break
+            return data
+        for j in range(iterations):
+            block = getdata(bufsize)
+            assert block[:8] == '01234567'
+            try:
+                module.test_mod(block)
+            except ValueError as e:
+                print("%s at it=%d" % (e, j))
+                assert False
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
@@ -736,9 +736,14 @@
             shadow = self.nursery_objects_shadows.get(obj)
             ll_assert(shadow != llmemory.NULL,
                       "GCFLAG_HAS_SHADOW but no shadow found")
-            return shadow
+        else:
+            shadow = self._allocate_shadow(obj)
 
-        return self._allocate_shadow(obj, copy=True)
+        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
@@ -2644,8 +2649,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 +2671,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