Armin Rigo committed 2859ce7

Test and fix. It's relatively hard to hit the case on PyPy, but
if we managed to, it would be a potential obscure GC-related crash.

Comments (0)

Files changed (3)


                           [ConstInt(kind), ConstInt(itemsize), v_length],
                           v_result, descr=arraydescr)
-        self.write_barrier_applied[v_result] = None
+        # don't record v_result into self.write_barrier_applied:
+        # it can be a large, young array with card marking, and then
+        # the GC relies on the write barrier being called
         return True
     def gen_malloc_nursery_varsize_frame(self, sizebox, v_result):


+    def test_initialization_store_potentially_large_array(self):
+        # the write barrier cannot be omitted, because we might get
+        # an array with cards and the GC assumes that the write
+        # barrier is always called, even on young (but large) arrays
+        self.check_rewrite("""
+            [i0, p1, i2]
+            p0 = new_array(i0, descr=bdescr)
+            setarrayitem_gc(p0, i2, p1, descr=bdescr)
+            jump()
+        """, """
+            [i0, p1, i2]
+            p0 = call_malloc_nursery_varsize(0, 1, i0, descr=bdescr)
+            setfield_gc(p0, i0, descr=blendescr)
+            cond_call_gc_wb_array(p0, i2, descr=wbdescr)
+            setarrayitem_gc(p0, i2, p1, descr=bdescr)
+            jump()
+        """)
     def test_non_initialization_store(self):


                 if op.args[0] in mallocvars:
                     mallocvars[op.result] = True
             elif op.opname in ("setfield", "setarrayitem", "setinteriorfield"):
+                # note that 'mallocvars' only tracks fixed-size mallocs,
+                # so no risk that they use card marking
                 TYPE = op.args[-1].concretetype
                 if (op.args[0] in mallocvars and
                     isinstance(TYPE, lltype.Ptr) and