Author: Maciej Fijalkowski <fij...@gmail.com>
Branch: optresult-unroll
Changeset: r79286:9e0692ce2a85
Date: 2015-08-28 18:32 +0200
http://bitbucket.org/pypy/pypy/changeset/9e0692ce2a85/

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
@@ -16,6 +16,7 @@
 
 from rpython.rlib.clibffi import FFI_DEFAULT_ABI
 from rpython.rlib.rarithmetic import ovfcheck, r_uint, r_ulonglong
+from rpython.rlib.objectmodel import Symbolic
 
 class LLTrace(object):
     has_been_freed = False
@@ -88,6 +89,10 @@
     def get_result_type(self):
         return getkind(self.RESULT)[0]
 
+class TypeIDSymbolic(Symbolic):
+    def __init__(self, STRUCT_OR_ARRAY):
+        self.STRUCT_OR_ARRAY = STRUCT_OR_ARRAY
+
 class SizeDescr(AbstractDescr):
     def __init__(self, S, vtable, runner):
         assert not isinstance(vtable, bool)
@@ -114,6 +119,10 @@
     def is_immutable(self):
         return heaptracker.is_immutable_struct(self.S)
 
+    def get_type_id(self):
+        assert isinstance(self.S, lltype.GcStruct)
+        return TypeIDSymbolic(self.S)     # integer-like symbolic
+
     def __repr__(self):
         return 'SizeDescr(%r)' % (self.S,)
 
@@ -222,6 +231,10 @@
         return intbounds.get_integer_max(
             not _is_signed_kind(self.A.OF), rffi.sizeof(self.A.OF))
 
+    def get_type_id(self):
+        assert isinstance(self.A, lltype.GcArray)
+        return TypeIDSymbolic(self.A)     # integer-like symbolic
+
 
 class InteriorFieldDescr(AbstractDescr):
     def __init__(self, A, fieldname, runner):
@@ -281,6 +294,7 @@
     supports_floats = True
     supports_longlong = r_uint is not r_ulonglong
     supports_singlefloats = True
+    supports_guard_gc_type = True
     translate_support_code = False
     is_llgraph = True
 
@@ -893,6 +907,16 @@
         self.execute_guard_nonnull(descr, arg)
         self.execute_guard_class(descr, arg, klass)
 
+    def execute_guard_gc_type(self, descr, arg, typeid):
+        assert isinstance(typeid, TypeIDSymbolic)
+        TYPE = arg._obj.container._TYPE
+        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_no_exception(self, descr):
         if self.last_exception is not None:
             self.fail_guard(descr)
diff --git a/rpython/jit/backend/llsupport/llmodel.py 
b/rpython/jit/backend/llsupport/llmodel.py
--- a/rpython/jit/backend/llsupport/llmodel.py
+++ b/rpython/jit/backend/llsupport/llmodel.py
@@ -40,6 +40,7 @@
         else:
             translator = None
         self.gc_ll_descr = get_ll_description(gcdescr, translator, rtyper)
+        self.supports_guard_gc_type = bool(translate_support_code)
         if translator and translator.config.translation.gcremovetypeptr:
             self.vtable_offset = None
         else:
diff --git a/rpython/jit/backend/model.py b/rpython/jit/backend/model.py
--- a/rpython/jit/backend/model.py
+++ b/rpython/jit/backend/model.py
@@ -15,6 +15,7 @@
     # longlongs are supported by the JIT, but stored as doubles.
     # Boxes and Consts are BoxFloats and ConstFloats.
     supports_singlefloats = False
+    supports_guard_gc_type = False
 
     propagate_exception_descr = 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
@@ -4832,3 +4832,51 @@
                                 assert a[i].a == a[i].b == val
                             else:
                                 assert a[i] == rffi.cast(OF, val)
+
+    def test_passing_guard_gc_type_struct(self):
+        if not self.cpu.supports_guard_gc_type:
+            py.test.skip("guard_gc_type not available")
+        t_box, _, descr = self.alloc_instance(self.T)
+        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:
+            py.test.skip("guard_gc_type not available")
+        a_box, A = self.alloc_array_of(rffi.SHORT, 342)
+        arraydescr = self.cpu.arraydescrof(A)
+        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:
+            py.test.skip("guard_gc_type not available")
+        t_box, _, tdescr = self.alloc_instance(self.T)
+        u_box, _, udescr = self.alloc_instance(self.U)
+        a_box, A = self.alloc_array_of(rffi.SHORT, 342)
+        adescr = self.cpu.arraydescrof(A)
+        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
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,10 +1734,10 @@
             self.mc.CMP(locs[0], locs[1])
         self.implement_guard(guard_token, 'NE')
 
-    def _cmp_guard_class(self, locs):
+    def _cmp_guard_class(self, loc_ptr, loc_classptr):
         offset = self.cpu.vtable_offset
         if offset is not None:
-            self.mc.CMP(mem(locs[0], offset), locs[1])
+            self.mc.CMP(mem(loc_ptr, offset), loc_classptr)
         else:
             # XXX hard-coded assumption: to go from an object to its class
             # we use the following algorithm:
@@ -1749,26 +1749,39 @@
             #   - multiply by 4 (on 32-bits only) and use it as an
             #     offset in type_info_group
             #   - add 16/32 bytes, to go past the TYPE_INFO structure
-            loc = locs[1]
-            assert isinstance(loc, ImmedLoc)
-            classptr = loc.value
+            assert isinstance(loc_classptr, ImmedLoc)
+            classptr = loc_classptr.value
             # here, we have to go back from 'classptr' to the value expected
-            # from reading the half-word in the object header.  Note that
-            # this half-word is at offset 0 on a little-endian machine;
-            # it would be at offset 2 or 4 on a big-endian machine.
+            # from reading the half-word in the object header.
             from rpython.memory.gctypelayout import GCData
             sizeof_ti = rffi.sizeof(GCData.TYPE_INFO)
             type_info_group = llop.gc_get_type_info_group(llmemory.Address)
             type_info_group = rffi.cast(lltype.Signed, type_info_group)
             expected_typeid = classptr - sizeof_ti - type_info_group
-            if IS_X86_32:
-                expected_typeid >>= 2
-                self.mc.CMP16(mem(locs[0], 0), ImmedLoc(expected_typeid))
-            elif IS_X86_64:
-                self.mc.CMP32_mi((locs[0].value, 0), expected_typeid)
+            self._cmp_guard_gc_type(loc_ptr, ImmedLoc(expected_typeid))
+
+    def _cmp_guard_gc_type(self, loc_ptr, loc_expected_typeid):
+        # Note that the typeid half-word is at offset 0 on a little-endian
+        # machine; it would be at offset 2 or 4 on a big-endian machine.
+        assert self.cpu.supports_guard_gc_type
+        if IS_X86_32:
+            self.mc.CMP16(mem(loc_ptr, 0), loc_expected_typeid)
+        else:
+            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(locs)
+        self._cmp_guard_class_or_gc_type(guard_op, locs)
         self.implement_guard(guard_token, 'NE')
 
     def genop_guard_guard_nonnull_class(self, ign_1, guard_op,
@@ -1777,7 +1790,7 @@
         # Patched below
         self.mc.J_il8(rx86.Conditions['B'], 0)
         jb_location = self.mc.get_relative_pos()
-        self._cmp_guard_class(locs)
+        self._cmp_guard_class_or_gc_type(guard_op, locs)
         # patch the JB above
         offset = self.mc.get_relative_pos() - jb_location
         assert 0 < offset <= 127
@@ -1785,6 +1798,9 @@
         #
         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 implement_guard_recovery(self, guard_opnum, faildescr, failargs,
                                  fail_locs, frame_depth):
         exc = (guard_opnum == rop.GUARD_EXCEPTION or
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
@@ -428,6 +428,8 @@
         self.perform_guard(op, [x, y], None)
 
     consider_guard_nonnull_class = consider_guard_class
+    consider_guard_gc_type = consider_guard_class
+    consider_guard_nonnull_gc_type = consider_guard_class
 
     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
@@ -656,6 +656,8 @@
     '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_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