Author: Maciej Fijalkowski <fij...@gmail.com>
Branch: optresult-unroll
Changeset: r79417:798a1f163fda
Date: 2015-09-04 13:28 +0200
http://bitbucket.org/pypy/pypy/changeset/798a1f163fda/

Log:    merge

diff --git a/rpython/jit/backend/llsupport/descr.py 
b/rpython/jit/backend/llsupport/descr.py
--- a/rpython/jit/backend/llsupport/descr.py
+++ b/rpython/jit/backend/llsupport/descr.py
@@ -64,7 +64,7 @@
         return heaptracker.adr2int(llmemory.cast_ptr_to_adr(self.vtable))
 
     def get_type_id(self):
-        assert self.tid != 0
+        assert self.tid
         return self.tid
 
 def get_size_descr(gccache, STRUCT, 
vtable=lltype.nullptr(rclass.OBJECT_VTABLE)):
@@ -293,7 +293,7 @@
         assert False
 
     def get_type_id(self):
-        assert self.tid != 0
+        assert self.tid
         return self.tid
 
     def repr_of_descr(self):
diff --git a/rpython/jit/backend/llsupport/gc.py 
b/rpython/jit/backend/llsupport/gc.py
--- a/rpython/jit/backend/llsupport/gc.py
+++ b/rpython/jit/backend/llsupport/gc.py
@@ -24,6 +24,7 @@
 class MovableObjectTracker(object):
 
     ptr_array_type = lltype.GcArray(llmemory.GCREF)
+    ptr_array_gcref = lltype.nullptr(llmemory.GCREF.TO)
 
     def __init__(self, cpu, const_pointers):
         size = len(const_pointers)
@@ -438,6 +439,7 @@
             self._make_gcrootmap()
             self._setup_gcclass()
             self._setup_tid()
+            self._setup_guard_is_object()
         self._setup_write_barrier()
         self._setup_str()
         self._make_functions(really_not_translated)
@@ -662,6 +664,54 @@
     def get_malloc_slowpath_array_addr(self):
         return self.get_malloc_fn_addr('malloc_array')
 
+    def get_typeid_from_classptr_if_gcremovetypeptr(self, classptr):
+        """Returns the typeid corresponding from a vtable pointer 'classptr'.
+        This function only works if cpu.vtable_offset is None, i.e. in
+        a translation with --gcremovetypeptr.
+         """
+        from rpython.memory.gctypelayout import GCData
+        assert self.gcdescr.config.translation.gcremovetypeptr
+
+        # hard-coded assumption: to go from an object to its class
+        # we would use the following algorithm:
+        #   - read the typeid from mem(locs[0]), i.e. at offset 0;
+        #     this is a complete word (N=4 bytes on 32-bit, N=8 on
+        #     64-bits)
+        #   - keep the lower half of what is read there (i.e.
+        #     truncate to an unsigned 'N / 2' bytes value)
+        #   - 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
+        # here, we have to go back from 'classptr' back to the typeid,
+        # so we do (part of) these computations in reverse.
+
+        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 WORD == 4:
+            expected_typeid >>= 2
+        return expected_typeid
+
+    def _setup_guard_is_object(self):
+        from rpython.memory.gctypelayout import GCData, T_IS_RPYTHON_INSTANCE
+        self._infobits_offset, _ = symbolic.get_field_token(GCData.TYPE_INFO,
+                                                            'infobits', True)
+        self._T_IS_RPYTHON_INSTANCE = T_IS_RPYTHON_INSTANCE
+
+    def get_translated_info_for_guard_is_object(self):
+        type_info_group = llop.gc_get_type_info_group(llmemory.Address)
+        type_info_group = rffi.cast(lltype.Signed, type_info_group)
+        infobits_offset = rffi.cast(lltype.Signed, self._infobits_offset)
+        if WORD == 4:
+            shift_by = 2
+        elif WORD == 8:
+            shift_by = 0
+        return (type_info_group + infobits_offset,
+                shift_by,
+                self._T_IS_RPYTHON_INSTANCE)
+
+
 # ____________________________________________________________
 
 def get_ll_description(gcdescr, translator=None, rtyper=None):
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
@@ -25,6 +25,12 @@
 
     HAS_CODEMAP = False
 
+    done_with_this_frame_descr_int      = None   # overridden by pyjitpl.py
+    done_with_this_frame_descr_float    = None
+    done_with_this_frame_descr_ref      = None
+    done_with_this_frame_descr_void     = None
+    exit_frame_with_exception_descr_ref = None
+
     def __init__(self, rtyper, stats, opts, translate_support_code=False,
                  gcdescr=None):
         assert type(opts) is not bool
diff --git a/rpython/jit/backend/llsupport/test/test_zrpy_gc_direct.py 
b/rpython/jit/backend/llsupport/test/test_zrpy_gc_direct.py
new file mode 100644
--- /dev/null
+++ b/rpython/jit/backend/llsupport/test/test_zrpy_gc_direct.py
@@ -0,0 +1,132 @@
+from rpython.jit.backend.detect_cpu import getcpuclass
+from rpython.jit.tool.oparser import parse
+from rpython.jit.metainterp.history import JitCellToken, NoStats
+from rpython.jit.metainterp.history import BasicFinalDescr, BasicFailDescr
+from rpython.jit.metainterp.gc import get_description
+from rpython.annotator.listdef import s_list_of_strings
+from rpython.rtyper.lltypesystem import lltype, llmemory, rffi
+from rpython.rtyper.rclass import getclassrepr, getinstancerepr
+from rpython.translator.unsimplify import call_initial_function
+from rpython.translator.translator import TranslationContext
+from rpython.translator.c import genc
+
+
+def run_guards_translated(gcremovetypeptr):
+    class A(object):
+        pass
+    class B(A):
+        pass
+    class C(B):
+        pass
+    def main(argv):
+        A(); B(); C()
+        return 0
+
+    t = TranslationContext()
+    t.config.translation.gc = "minimark"
+    t.config.translation.gcremovetypeptr = gcremovetypeptr
+    ann = t.buildannotator()
+    ann.build_types(main, [s_list_of_strings], main_entry_point=True)
+    rtyper = t.buildrtyper()
+    rtyper.specialize()
+
+    classdef = ann.bookkeeper.getuniqueclassdef(B)
+    rclass = getclassrepr(rtyper, classdef)
+    rinstance = getinstancerepr(rtyper, classdef)
+    LLB = rinstance.lowleveltype.TO
+    vtable_B = rclass.getvtable()
+    adr_vtable_B = llmemory.cast_ptr_to_adr(vtable_B)
+    vtable_B = llmemory.cast_adr_to_int(adr_vtable_B, mode="symbolic")
+
+    CPU = getcpuclass()
+    cpu = CPU(rtyper, NoStats(),
+              translate_support_code=True,
+              gcdescr=get_description(t.config))
+    execute_token = cpu.make_execute_token(llmemory.GCREF)
+    finaldescr = BasicFinalDescr()
+    faildescr = BasicFailDescr()
+
+    descr_B = cpu.sizeof(LLB, vtable_B)
+    typeid_B = descr_B.get_type_id()
+
+    loop1 = parse("""
+    [p0]
+    guard_class(p0, ConstInt(vtable_B), descr=faildescr) []
+    finish(descr=finaldescr)
+    """, namespace={'finaldescr': finaldescr,
+                    'faildescr': faildescr,
+                    'vtable_B': vtable_B})
+
+    loop2 = parse("""
+    [p0]
+    guard_gc_type(p0, ConstInt(typeid_B), descr=faildescr) []
+    finish(descr=finaldescr)
+    """, namespace={'finaldescr': finaldescr,
+                    'faildescr': faildescr,
+                    'typeid_B': typeid_B})
+
+    loop3 = parse("""
+    [p0]
+    guard_is_object(p0, descr=faildescr) []
+    finish(descr=finaldescr)
+    """, namespace={'finaldescr': finaldescr,
+                    'faildescr': faildescr})
+
+    def g():
+        cpu.setup_once()
+        token1 = JitCellToken()
+        token2 = JitCellToken()
+        token3 = JitCellToken()
+        cpu.compile_loop(loop1.inputargs, loop1.operations, token1)
+        cpu.compile_loop(loop2.inputargs, loop2.operations, token2)
+        cpu.compile_loop(loop3.inputargs, loop3.operations, token3)
+
+        for token, p0 in [
+                (token1, rffi.cast(llmemory.GCREF, A())),
+                (token1, rffi.cast(llmemory.GCREF, B())),
+                (token1, rffi.cast(llmemory.GCREF, C())),
+
+                (token2, rffi.cast(llmemory.GCREF, A())),
+                (token2, rffi.cast(llmemory.GCREF, B())),
+                (token2, rffi.cast(llmemory.GCREF, C())),
+                (token2, rffi.cast(llmemory.GCREF, [42, 43])),
+
+                (token3, rffi.cast(llmemory.GCREF, A())),
+                (token3, rffi.cast(llmemory.GCREF, B())),
+                (token3, rffi.cast(llmemory.GCREF, [44, 45])),
+                ]:
+            frame = execute_token(token, p0)
+            descr = cpu.get_latest_descr(frame)
+            if descr is finaldescr:
+                print 'match'
+            elif descr is faildescr:
+                print 'fail'
+            else:
+                print '???'
+
+    call_initial_function(t, g)
+
+    cbuilder = genc.CStandaloneBuilder(t, main, t.config)
+    cbuilder.generate_source(defines=cbuilder.DEBUG_DEFINES)
+    cbuilder.compile()
+    
+    data = cbuilder.cmdexec('')
+    assert data == ('fail\n'
+                    'match\n'
+                    'fail\n'
+
+                    'fail\n'
+                    'match\n'
+                    'fail\n'
+                    'fail\n'
+
+                    'match\n'
+                    'match\n'
+                    'fail\n')
+
+
+def test_guards_translated_with_gctypeptr():
+    run_guards_translated(gcremovetypeptr=False)
+
+def test_guards_translated_without_gctypeptr():
+    run_guards_translated(gcremovetypeptr=True)
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
@@ -1741,25 +1741,10 @@
         if offset is not None:
             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:
-            #   - read the typeid from mem(locs[0]), i.e. at offset 0;
-            #     this is a complete word (N=4 bytes on 32-bit, N=8 on
-            #     64-bits)
-            #   - keep the lower half of what is read there (i.e.
-            #     truncate to an unsigned 'N / 2' bytes value)
-            #   - 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
             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.
-            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
+            expected_typeid = (self.cpu.gc_ll_descr
+                    .get_typeid_from_classptr_if_gcremovetypeptr(classptr))
             self._cmp_guard_gc_type(loc_ptr, ImmedLoc(expected_typeid))
 
     def _cmp_guard_gc_type(self, loc_ptr, loc_expected_typeid):
@@ -1795,6 +1780,23 @@
         self._cmp_guard_gc_type(locs[0], locs[1])
         self.implement_guard(guard_token, 'NE')
 
+    def genop_guard_guard_is_object(self, ign_1, guard_op,
+                                    guard_token, locs, ign_2):
+        assert self.cpu.supports_guard_gc_type
+        [loc_object, loc_typeid] = locs
+        # idea: read the typeid, fetch the field 'infobits' from the big
+        # typeinfo table, and check the flag 'T_IS_RPYTHON_INSTANCE'.
+        base_type_info, shift_by, IS_OBJECT_FLAG = (
+            self.cpu.gc_ll_descr.get_translated_info_for_guard_is_object())
+        if IS_X86_32:
+            self.mc.MOVZX16(loc_typeid, mem(loc_object, 0))
+        else:
+            self.mc.MOV32(loc_typeid, mem(loc_object, 0))
+        loc_infobits = addr_add(imm(base_type_info), loc_typeid, 
scale=shift_by)
+        self.mc.TEST(loc_infobits, imm(IS_OBJECT_FLAG))
+        #
+        self.implement_guard(guard_token, 'Z')
+
     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
@@ -431,10 +431,14 @@
     consider_guard_gc_type = consider_guard_class
 
     def consider_guard_is_object(self, op):
-        xxx
+        x = self.make_sure_var_in_reg(op.getarg(0))
+        tmp_box = TempVar()
+        y = self.rm.force_allocate_reg(tmp_box)
+        self.rm.possibly_free_var(tmp_box)
+        self.perform_guard(op, [x, y], None)
 
     def consider_guard_subclass(self, op):
-        xxx
+        assert 0 # xxx
 
     def _consider_binop_part(self, op, symm=False):
         x = op.getarg(0)
@@ -798,6 +802,7 @@
 
     def _consider_real_call(self, op):
         effectinfo = op.getdescr().get_extra_info()
+        assert effectinfo is not None
         oopspecindex = effectinfo.oopspecindex
         if oopspecindex != EffectInfo.OS_NONE:
             if IS_X86_32:
diff --git a/rpython/jit/backend/x86/rx86.py b/rpython/jit/backend/x86/rx86.py
--- a/rpython/jit/backend/x86/rx86.py
+++ b/rpython/jit/backend/x86/rx86.py
@@ -674,6 +674,9 @@
     TEST8_bi = insn(rex_nw, '\xF6', orbyte(0<<3), stack_bp(1), immediate(2, 
'b'))
     TEST8_ji = insn(rex_nw, '\xF6', orbyte(0<<3), abs_(1), immediate(2, 'b'))
     TEST_rr = insn(rex_w, '\x85', register(2,8), register(1), '\xC0')
+    TEST_ai = insn(rex_w, '\xF7', orbyte(0<<3), 
mem_reg_plus_scaled_reg_plus_const(1), immediate(2))
+    TEST_mi = insn(rex_w, '\xF7', orbyte(0<<3), mem_reg_plus_const(1), 
immediate(2))
+    TEST_ji = insn(rex_w, '\xF7', orbyte(0<<3), abs_(1), immediate(2))
 
     BTS_mr = insn(rex_w, '\x0F\xAB', register(2,8), mem_reg_plus_const(1))
     BTS_jr = insn(rex_w, '\x0F\xAB', register(2,8), abs_(1))
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to