Commits

Armin Rigo  committed e5fb197

Fix the test by properly detecting the case during codewriting,
and raising NotImplementedError.

  • Participants
  • Parent commits 45f85f6

Comments (0)

Files changed (3)

File pypy/jit/codewriter/jtransform.py

                 pure = '_pure'
         else:
             pure = ''
+        self.check_field_access(v_inst.concretetype.TO)
         argname = getattr(v_inst.concretetype.TO, '_gckind', 'gc')
         descr = self.cpu.fielddescrof(v_inst.concretetype.TO,
                                       c_fieldname.value)
             return [SpaceOperation('-live-', [], None),
                     SpaceOperation('setfield_vable_%s' % kind,
                                    [v_inst, descr, v_value], None)]
+        self.check_field_access(v_inst.concretetype.TO)
         argname = getattr(v_inst.concretetype.TO, '_gckind', 'gc')
         descr = self.cpu.fielddescrof(v_inst.concretetype.TO,
                                       c_fieldname.value)
         return (op.args[1].value == 'typeptr' and
                 op.args[0].concretetype.TO._hints.get('typeptr'))
 
+    def check_field_access(self, STRUCT):
+        # check against a GcStruct with a nested GcStruct as a first argument
+        # but which is not an object at all; see metainterp/test/test_loop,
+        # test_regular_pointers_in_short_preamble.
+        if not isinstance(STRUCT, lltype.GcStruct):
+            return
+        if STRUCT._first_struct() == (None, None):
+            return
+        PARENT = STRUCT
+        while not PARENT._hints.get('typeptr'):
+            _, PARENT = PARENT._first_struct()
+            if PARENT is None:
+                raise NotImplementedError("%r is a GcStruct using nesting but "
+                                          "not inheriting from object" %
+                                          (STRUCT,))
+
     def get_vinfo(self, v_virtualizable):
         if self.callcontrol is None:      # for tests
             return None

File pypy/jit/codewriter/test/test_jtransform.py

         assert op1.opname == 'jit_force_quasi_immutable'
         assert op1.args[0] == v_x
         assert op1.args[1] == ('fielddescr', STRUCT, 'mutate_x')
+
+def test_no_gcstruct_nesting_outside_of_OBJECT():
+    PARENT = lltype.GcStruct('parent')
+    STRUCT = lltype.GcStruct('struct', ('parent', PARENT),
+                                       ('x', lltype.Signed))
+    v_x = varoftype(lltype.Ptr(STRUCT))
+    op = SpaceOperation('getfield', [v_x, Constant('x', lltype.Void)],
+                        varoftype(lltype.Signed))
+    tr = Transformer(None, None)
+    raises(NotImplementedError, tr.rewrite_operation, op)

File pypy/jit/metainterp/test/test_loop.py

         res = self.meta_interp(f, [200])        
 
     def test_regular_pointers_in_short_preamble(self):
-        # XXX do we really care about this case?  If not, we should
-        # at least detect it and complain during codewriter/jtransform
         from pypy.rpython.lltypesystem import lltype
         BASE = lltype.GcStruct('BASE')
         A = lltype.GcStruct('A', ('parent', BASE), ('val', lltype.Signed))
                 assert n>0 and m>0
                 i += j
             return sa
-        expected = f(20, 10, 1)
-        res = self.meta_interp(f, [20, 10, 1])
-        assert res == expected
+        # This is detected as invalid by the codewriter, for now
+        py.test.raises(NotImplementedError, self.meta_interp, f, [20, 10, 1])
 
     def test_unerased_pointers_in_short_preamble(self):
         from pypy.rlib.rerased import new_erasing_pair