Author: Maciej Fijalkowski <fij...@gmail.com>
Branch: optresult-unroll
Changeset: r79393:0cd368883dd1
Date: 2015-09-03 18:17 +0200
http://bitbucket.org/pypy/pypy/changeset/0cd368883dd1/

Log:    merge

diff --git a/rpython/jit/backend/llgraph/runner.py 
b/rpython/jit/backend/llgraph/runner.py
--- a/rpython/jit/backend/llgraph/runner.py
+++ b/rpython/jit/backend/llgraph/runner.py
@@ -913,9 +913,25 @@
         if TYPE != typeid.STRUCT_OR_ARRAY:
             self.fail_guard(descr)
 
-    def execute_guard_nonnull_gc_type(self, descr, arg, typeid):
-        self.execute_guard_nonnull(descr, arg)
-        self.execute_guard_gc_type(descr, arg, typeid)
+    def execute_guard_is_object(self, descr, arg):
+        TYPE = arg._obj.container._TYPE
+        while TYPE is not rclass.OBJECT:
+            if not isinstance(TYPE, lltype.GcStruct):   # or TYPE is None
+                self.fail_guard(descr)
+                return
+            _, TYPE = TYPE._first_struct()
+
+    def execute_guard_subclass(self, descr, arg, klass):
+        value = lltype.cast_opaque_ptr(rclass.OBJECTPTR, arg)
+        expected_class = llmemory.cast_adr_to_ptr(
+            llmemory.cast_int_to_adr(klass),
+            rclass.CLASSTYPE)
+        if (expected_class.subclassrange_min
+                <= value.typeptr.subclassrange_min
+                <= expected_class.subclassrange_max):
+            pass
+        else:
+            self.fail_guard(descr)
 
     def execute_guard_no_exception(self, descr):
         if self.last_exception is not None:
diff --git a/rpython/jit/backend/test/runner_test.py 
b/rpython/jit/backend/test/runner_test.py
--- a/rpython/jit/backend/test/runner_test.py
+++ b/rpython/jit/backend/test/runner_test.py
@@ -4840,9 +4840,6 @@
         c_typeid = ConstInt(descr.get_type_id())
         self.execute_operation(rop.GUARD_GC_TYPE, [t_box, c_typeid], 'void')
         assert not self.guard_failed
-        self.execute_operation(rop.GUARD_NONNULL_GC_TYPE, [t_box, c_typeid],
-                               'void')
-        assert not self.guard_failed
 
     def test_passing_guard_gc_type_array(self):
         if not self.cpu.supports_guard_gc_type:
@@ -4852,9 +4849,6 @@
         c_typeid = ConstInt(arraydescr.get_type_id())
         self.execute_operation(rop.GUARD_GC_TYPE, [a_box, c_typeid], 'void')
         assert not self.guard_failed
-        self.execute_operation(rop.GUARD_NONNULL_GC_TYPE, [a_box, c_typeid],
-                               'void')
-        assert not self.guard_failed
 
     def test_failing_guard_gc_type(self):
         if not self.cpu.supports_guard_gc_type:
@@ -4866,17 +4860,78 @@
         c_ttypeid = ConstInt(tdescr.get_type_id())
         c_utypeid = ConstInt(udescr.get_type_id())
         c_atypeid = ConstInt(adescr.get_type_id())
-        null_box = self.null_instance()
         for opname, args in [(rop.GUARD_GC_TYPE, [t_box, c_utypeid]),
                              (rop.GUARD_GC_TYPE, [u_box, c_ttypeid]),
                              (rop.GUARD_GC_TYPE, [a_box, c_utypeid]),
                              (rop.GUARD_GC_TYPE, [t_box, c_atypeid]),
-                             (rop.GUARD_NONNULL_GC_TYPE, [t_box, c_utypeid]),
-                             (rop.GUARD_NONNULL_GC_TYPE, [u_box, c_ttypeid]),
-                             (rop.GUARD_NONNULL_GC_TYPE, [a_box, c_ttypeid]),
-                             (rop.GUARD_NONNULL_GC_TYPE, [u_box, c_atypeid]),
-                             (rop.GUARD_NONNULL_GC_TYPE, [null_box, 
c_ttypeid]),
-                             (rop.GUARD_NONNULL_GC_TYPE, [null_box, 
c_atypeid]),
                              ]:
             assert self.execute_operation(opname, args, 'void') == None
             assert self.guard_failed
+
+    def test_guard_is_object(self):
+        if not self.cpu.supports_guard_gc_type:
+            py.test.skip("guard_gc_type not available")
+        t_box, _, _ = self.alloc_instance(self.T)
+        self.execute_operation(rop.GUARD_IS_OBJECT, [t_box], 'void')
+        #
+        assert not self.guard_failed
+        a_box, _ = self.alloc_array_of(rffi.SHORT, 342)
+        self.execute_operation(rop.GUARD_IS_OBJECT, [a_box], 'void')
+        assert self.guard_failed
+        #
+        S = lltype.GcStruct('S')
+        s = lltype.malloc(S, immortal=True, zero=True)
+        s_box = InputArgRef(lltype.cast_opaque_ptr(llmemory.GCREF, s))
+        self.execute_operation(rop.GUARD_IS_OBJECT, [s_box], 'void')
+        assert self.guard_failed
+
+    def test_guard_subclass(self):
+        if not self.cpu.supports_guard_gc_type:
+            py.test.skip("guard_gc_type not available")
+
+        xtp = lltype.malloc(rclass.OBJECT_VTABLE, immortal=True)
+        xtp.subclassrange_min = 1
+        xtp.subclassrange_max = 3
+        X = lltype.GcStruct('X', ('parent', rclass.OBJECT),
+                            hints={'vtable':  xtp._obj})
+        xptr = lltype.malloc(X)
+        xptr.parent.typeptr = xtp
+        x_box = InputArgRef(lltype.cast_opaque_ptr(llmemory.GCREF, xptr))
+        X_box = ConstInt(heaptracker.adr2int(llmemory.cast_ptr_to_adr(xtp)))
+
+        ytp = lltype.malloc(rclass.OBJECT_VTABLE, immortal=True)
+        ytp.subclassrange_min = 2
+        ytp.subclassrange_max = 2
+        assert rclass.ll_issubclass(ytp, xtp)
+        Y = lltype.GcStruct('Y', ('parent', X),
+                            hints={'vtable':  ytp._obj})
+        yptr = lltype.malloc(Y)
+        yptr.parent.parent.typeptr = ytp
+        y_box = InputArgRef(lltype.cast_opaque_ptr(llmemory.GCREF, yptr))
+        Y_box = ConstInt(heaptracker.adr2int(llmemory.cast_ptr_to_adr(ytp)))
+
+        ztp = lltype.malloc(rclass.OBJECT_VTABLE, immortal=True)
+        ztp.subclassrange_min = 4
+        ztp.subclassrange_max = 5
+        assert not rclass.ll_issubclass(ztp, xtp)
+        assert not rclass.ll_issubclass(xtp, ztp)
+        Z = lltype.GcStruct('Z', ('parent', rclass.OBJECT),
+                            hints={'vtable':  ztp._obj})
+        zptr = lltype.malloc(Z)
+        zptr.parent.typeptr = ztp
+        z_box = InputArgRef(lltype.cast_opaque_ptr(llmemory.GCREF, zptr))
+        Z_box = ConstInt(heaptracker.adr2int(llmemory.cast_ptr_to_adr(ztp)))
+
+        for num, arg, klass, is_subclass in [
+                (1, x_box, X_box, True),
+                (2, x_box, Y_box, False),
+                (3, x_box, Z_box, False),
+                (4, y_box, X_box, True),
+                (5, y_box, Y_box, True),
+                (6, y_box, Z_box, False),
+                (7, z_box, X_box, False),
+                (8, z_box, Y_box, False),
+                (9, z_box, Z_box, True),
+                ]:
+            self.execute_operation(rop.GUARD_SUBCLASS, [arg, klass], 'void')
+            assert self.guard_failed == (not is_subclass)
diff --git a/rpython/jit/backend/x86/assembler.py 
b/rpython/jit/backend/x86/assembler.py
--- a/rpython/jit/backend/x86/assembler.py
+++ b/rpython/jit/backend/x86/assembler.py
@@ -1734,7 +1734,9 @@
             self.mc.CMP(locs[0], locs[1])
         self.implement_guard(guard_token, 'NE')
 
-    def _cmp_guard_class(self, loc_ptr, loc_classptr):
+    def _cmp_guard_class(self, locs):
+        loc_ptr = locs[0]
+        loc_classptr = locs[1]
         offset = self.cpu.vtable_offset
         if offset is not None:
             self.mc.CMP(mem(loc_ptr, offset), loc_classptr)
@@ -1770,18 +1772,8 @@
             assert isinstance(loc_expected_typeid, ImmedLoc)
             self.mc.CMP32_mi((loc_ptr.value, 0), loc_expected_typeid.value)
 
-    def _cmp_guard_class_or_gc_type(self, guard_op, locs):
-        if (  guard_op.getopnum() == rop.GUARD_CLASS or
-              guard_op.getopnum() == rop.GUARD_NONNULL_CLASS):
-            self._cmp_guard_class(locs[0], locs[1])
-        elif (guard_op.getopnum() == rop.GUARD_GC_TYPE or
-              guard_op.getopnum() == rop.GUARD_NONNULL_GC_TYPE):
-            self._cmp_guard_gc_type(locs[0], locs[1])
-        else:
-            assert 0
-
     def genop_guard_guard_class(self, ign_1, guard_op, guard_token, locs, 
ign_2):
-        self._cmp_guard_class_or_gc_type(guard_op, locs)
+        self._cmp_guard_class(locs)
         self.implement_guard(guard_token, 'NE')
 
     def genop_guard_guard_nonnull_class(self, ign_1, guard_op,
@@ -1790,7 +1782,7 @@
         # Patched below
         self.mc.J_il8(rx86.Conditions['B'], 0)
         jb_location = self.mc.get_relative_pos()
-        self._cmp_guard_class_or_gc_type(guard_op, locs)
+        self._cmp_guard_class(locs)
         # patch the JB above
         offset = self.mc.get_relative_pos() - jb_location
         assert 0 < offset <= 127
@@ -1798,8 +1790,10 @@
         #
         self.implement_guard(guard_token, 'NE')
 
-    genop_guard_guard_gc_type = genop_guard_guard_class
-    genop_guard_guard_nonnull_gc_type = genop_guard_guard_nonnull_class
+    def genop_guard_guard_gc_type(self, ign_1, guard_op,
+                                  guard_token, locs, ign_2):
+        self._cmp_guard_gc_type(locs[0], locs[1])
+        self.implement_guard(guard_token, 'NE')
 
     def implement_guard_recovery(self, guard_opnum, faildescr, failargs,
                                  fail_locs, frame_depth):
diff --git a/rpython/jit/backend/x86/regalloc.py 
b/rpython/jit/backend/x86/regalloc.py
--- a/rpython/jit/backend/x86/regalloc.py
+++ b/rpython/jit/backend/x86/regalloc.py
@@ -429,7 +429,12 @@
 
     consider_guard_nonnull_class = consider_guard_class
     consider_guard_gc_type = consider_guard_class
-    consider_guard_nonnull_gc_type = consider_guard_class
+
+    def consider_guard_is_object(self, op):
+        xxx
+
+    def consider_guard_subclass(self, op):
+        xxx
 
     def _consider_binop_part(self, op, symm=False):
         x = op.getarg(0)
diff --git a/rpython/jit/metainterp/resoperation.py 
b/rpython/jit/metainterp/resoperation.py
--- a/rpython/jit/metainterp/resoperation.py
+++ b/rpython/jit/metainterp/resoperation.py
@@ -661,8 +661,9 @@
     'GUARD_NONNULL/1d/n',
     'GUARD_ISNULL/1d/n',
     'GUARD_NONNULL_CLASS/2d/n',
-    'GUARD_GC_TYPE/2d/n',
-    'GUARD_NONNULL_GC_TYPE/2d/n',
+    'GUARD_GC_TYPE/2d/n',       # only if supports_guard_gc_type
+    'GUARD_IS_OBJECT/1d/n',     # only if supports_guard_gc_type
+    'GUARD_SUBCLASS/2d/n',      # only if supports_guard_gc_type
     '_GUARD_FOLDABLE_LAST',
     'GUARD_NO_EXCEPTION/0d/n',   # may be called with an exception currently 
set
     'GUARD_EXCEPTION/1d/r',     # may be called with an exception currently set
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to