Author: Armin Rigo <[email protected]>
Branch: stmgc-c7
Changeset: r70218:09a81b58e77a
Date: 2014-03-23 17:58 +0100
http://bitbucket.org/pypy/pypy/changeset/09a81b58e77a/

Log:    hg merge default

diff --git a/pypy/module/pypyjit/test_pypy_c/test_containers.py 
b/pypy/module/pypyjit/test_pypy_c/test_containers.py
--- a/pypy/module/pypyjit/test_pypy_c/test_containers.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_containers.py
@@ -70,14 +70,14 @@
             p13 = new(descr=...)
             p15 = new_array(8, descr=<ArrayX .*>)
             setfield_gc(p13, p15, descr=<FieldP dicttable.entries .*>)
-            i17 = call(ConstClass(ll_dict_lookup_trampoline), p13, p10, i12, 
descr=<Calli . rri EF=4>)
+            i17 = call(ConstClass(ll_dict_lookup_trampoline), p13, p10, i12, 
descr=<Calli . rri EF=4 OS=4>)
             setfield_gc(p13, 16, descr=<FieldS dicttable.resize_counter .*>)
             guard_no_exception(descr=...)
             p20 = new_with_vtable(ConstClass(W_IntObject))
             call(ConstClass(_ll_dict_setitem_lookup_done_trampoline), p13, 
p10, p20, i12, i17, descr=<Callv 0 rrrii EF=4>)
             setfield_gc(p20, i5, descr=<FieldS .*W_IntObject.inst_intval .*>)
             guard_no_exception(descr=...)
-            i23 = call(ConstClass(ll_dict_lookup_trampoline), p13, p10, i12, 
descr=<Calli . rri EF=4>)
+            i23 = call(ConstClass(ll_dict_lookup_trampoline), p13, p10, i12, 
descr=<Calli . rri EF=4 OS=4>)
             guard_no_exception(descr=...)
             i26 = int_and(i23, .*)
             i27 = int_is_true(i26)
diff --git a/pypy/module/pypyjit/test_pypy_c/test_instance.py 
b/pypy/module/pypyjit/test_pypy_c/test_instance.py
--- a/pypy/module/pypyjit/test_pypy_c/test_instance.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_instance.py
@@ -141,15 +141,16 @@
             i = 0
             b = B(1)
             while i < 100:
-                b.x
-                v = b.x # ID: loadattr
+                v = b.x # ID: loadattr1
+                v = b.x # ID: loadattr2
                 i += v
             return i
 
         log = self.run(main, [], threshold=80)
         loop, = log.loops_by_filename(self.filepath)
-        assert loop.match_by_id('loadattr',
+        assert loop.match_by_id('loadattr1',
         '''
+        guard_not_invalidated(descr=...)
         i19 = call(ConstClass(ll_dict_lookup), _, _, _, descr=...)
         guard_no_exception(descr=...)
         i21 = int_and(i19, _)
@@ -161,6 +162,7 @@
         i29 = int_is_true(i28)
         guard_true(i29, descr=...)
         ''')
+        assert loop.match_by_id('loadattr2', "")   # completely folded away
 
     def test_python_contains(self):
         def main():
diff --git a/rpython/jit/backend/arm/opassembler.py 
b/rpython/jit/backend/arm/opassembler.py
--- a/rpython/jit/backend/arm/opassembler.py
+++ b/rpython/jit/backend/arm/opassembler.py
@@ -584,7 +584,10 @@
     emit_op_getfield_gc_pure = emit_op_getfield_gc
 
     def emit_op_increment_debug_counter(self, op, arglocs, regalloc, fcond):
-        # XXX implement me
+        base_loc, value_loc = arglocs
+        self.mc.LDR_ri(value_loc.value, base_loc.value, 0, cond=fcond)
+        self.mc.ADD_ri(value_loc.value, value_loc.value, 1, cond=fcond)
+        self.mc.STR_ri(value_loc.value, base_loc.value, 0, cond=fcond)
         return fcond
 
     def emit_op_getinteriorfield_gc(self, op, arglocs, regalloc, fcond):
diff --git a/rpython/jit/backend/arm/regalloc.py 
b/rpython/jit/backend/arm/regalloc.py
--- a/rpython/jit/backend/arm/regalloc.py
+++ b/rpython/jit/backend/arm/regalloc.py
@@ -850,8 +850,12 @@
     prepare_op_getfield_gc_pure = prepare_op_getfield_gc
 
     def prepare_op_increment_debug_counter(self, op, fcond):
-        # XXX implement me
-        return []
+        boxes = op.getarglist()
+        a0, = boxes
+        base_loc = self.make_sure_var_in_reg(a0, boxes)
+        value_loc = self.get_scratch_reg(INT, boxes)
+        self.free_temp_vars()
+        return [base_loc, value_loc]
 
     def prepare_op_getinteriorfield_gc(self, op, fcond):
         t = unpack_interiorfielddescr(op.getdescr())
diff --git a/rpython/jit/backend/llsupport/test/test_rewrite.py 
b/rpython/jit/backend/llsupport/test/test_rewrite.py
--- a/rpython/jit/backend/llsupport/test/test_rewrite.py
+++ b/rpython/jit/backend/llsupport/test/test_rewrite.py
@@ -556,7 +556,7 @@
             p1 = int_add(p0, %(strdescr.basesize + 16 * strdescr.itemsize)d)
             setfield_gc(p1, %(unicodedescr.tid)d, descr=tiddescr)
             setfield_gc(p1, 10, descr=unicodelendescr)
-            p2 = call_malloc_nursery_varsize(2, 4, i2, \
+            p2 = call_malloc_nursery_varsize(2, %(unicodedescr.itemsize)d, i2,\
                                 descr=unicodedescr)
             setfield_gc(p2, i2, descr=unicodelendescr)
             p3 = call_malloc_nursery_varsize(1, 1, i2, \
diff --git a/rpython/jit/backend/x86/arch.py b/rpython/jit/backend/x86/arch.py
--- a/rpython/jit/backend/x86/arch.py
+++ b/rpython/jit/backend/x86/arch.py
@@ -15,14 +15,14 @@
 #
 #        +--------------------+    <== aligned to 16 bytes
 #        |   return address   |
-#        +--------------------+
-#        |   STM resume buf   |    (16 extra bytes, only with STM)
-#        +--------------------+
-#        |    saved regs      |
-#        +--------------------+
-#        |   scratch          |
-#        |      space         |
-#        +--------------------+    <== aligned to 16 bytes
+#        +--------------------+               ------------------------.
+#        | resume buf (if STM)|                  STM_FRAME_FIXED_SIZE |
+#        +--------------------+           ----------------------.     |
+#        |    saved regs      |                FRAME_FIXED_SIZE |     |
+#        +--------------------+       --------------------.     |     |
+#        |   scratch          |          PASS_ON_MY_FRAME |     |     |
+#        |      space         |                           |     |     |
+#        +--------------------+    <== aligned to 16 -----' ----' ----'
 #             STACK TOP
 
 # All the rest of the data is in a GC-managed variable-size "frame".
@@ -33,16 +33,17 @@
 # start of every frame: the saved value of some registers
 
 if WORD == 4:
-    # ebp + ebx + esi + edi + 14 extra words + return address = 19 words
+    # ebp + ebx + esi + edi + 15 extra words = 19 words
     FRAME_FIXED_SIZE = 19
-    PASS_ON_MY_FRAME = 14
+    PASS_ON_MY_FRAME = 15
     JITFRAME_FIXED_SIZE = 6 + 8 * 2 # 6 GPR + 8 XMM * 2 WORDS/float
 else:
-    # rbp + rbx + r12 + r13 + r14 + r15 + 12 extra words + return address = 19
+    # rbp + rbx + r12 + r13 + r14 + r15 + 13 extra words = 19
     FRAME_FIXED_SIZE = 19
-    PASS_ON_MY_FRAME = 12
+    PASS_ON_MY_FRAME = 13
     JITFRAME_FIXED_SIZE = 28 # 13 GPR + 15 XMM
 
 assert PASS_ON_MY_FRAME >= 12       # asmgcc needs at least JIT_USE_WORDS + 3
 
 STM_RESUME_BUF = 16 / WORD
+STM_FRAME_FIXED_SIZE = FRAME_FIXED_SIZE + STM_RESUME_BUF
diff --git a/rpython/jit/codewriter/effectinfo.py 
b/rpython/jit/codewriter/effectinfo.py
--- a/rpython/jit/codewriter/effectinfo.py
+++ b/rpython/jit/codewriter/effectinfo.py
@@ -106,8 +106,10 @@
                 needs_inevitable=False):
         key = (frozenset_or_none(readonly_descrs_fields),
                frozenset_or_none(readonly_descrs_arrays),
+               frozenset_or_none(readonly_descrs_interiorfields),
                frozenset_or_none(write_descrs_fields),
                frozenset_or_none(write_descrs_arrays),
+               frozenset_or_none(write_descrs_interiorfields),
                extraeffect,
                oopspecindex,
                can_invalidate,
@@ -231,6 +233,18 @@
             descr = cpu.interiorfielddescrof(T, fieldname)
             descrs_interiorfields.append(descr)
 
+        # a read or a write to an interiorfield, inside an array of
+        # structs, is additionally recorded as a read or write of
+        # the array itself
+        extraef = set()
+        for tup in effects:
+            if tup[0] == "interiorfield" or tup[0] == "readinteriorfield":
+                T = deref(tup[1])
+                if isinstance(T, lltype.Array) and consider_array(T):
+                    extraef.add((tup[0].replace("interiorfield", "array"),
+                                 tup[1]))
+        effects |= extraef
+
         for tup in effects:
             if tup[0] == "struct":
                 add_struct(write_descrs_fields, tup)
diff --git a/rpython/jit/codewriter/jtransform.py 
b/rpython/jit/codewriter/jtransform.py
--- a/rpython/jit/codewriter/jtransform.py
+++ b/rpython/jit/codewriter/jtransform.py
@@ -1868,8 +1868,7 @@
     def _handle_dict_lookup_call(self, op, oopspec_name, args):
         extradescr1 = self.cpu.fielddescrof(op.args[1].concretetype.TO,
                                             'entries')
-        extradescr2 = self.cpu.interiorfielddescrof(
-            op.args[1].concretetype.TO.entries.TO, 'key')
+        extradescr2 = 
self.cpu.arraydescrof(op.args[1].concretetype.TO.entries.TO)
         return self._handle_oopspec_call(op, args, EffectInfo.OS_DICT_LOOKUP,
                                          extradescr=[extradescr1, extradescr2])
 
diff --git a/rpython/jit/codewriter/test/test_flatten.py 
b/rpython/jit/codewriter/test/test_flatten.py
--- a/rpython/jit/codewriter/test/test_flatten.py
+++ b/rpython/jit/codewriter/test/test_flatten.py
@@ -73,7 +73,7 @@
     def guess_call_kind(self, op):
         return 'residual'
     def getcalldescr(self, op, oopspecindex=EffectInfo.OS_NONE,
-                     extraeffect=None):
+                     extraeffect=None, extradescr=None):
         try:
             name = op.args[0].value._obj._name
             if 'cannot_raise' in name or name.startswith('cast_'):
diff --git a/rpython/jit/codewriter/test/test_longlong.py 
b/rpython/jit/codewriter/test/test_longlong.py
--- a/rpython/jit/codewriter/test/test_longlong.py
+++ b/rpython/jit/codewriter/test/test_longlong.py
@@ -17,7 +17,7 @@
 class FakeBuiltinCallControl:
     def guess_call_kind(self, op):
         return 'builtin'
-    def getcalldescr(self, op, oopspecindex=None, extraeffect=None):
+    def getcalldescr(self, op, oopspecindex=None, extraeffect=None, 
extradescr=None):
         assert oopspecindex is not None    # in this test
         return 'calldescr-%d' % oopspecindex
     def calldescr_canraise(self, calldescr):
diff --git a/rpython/jit/metainterp/logger.py b/rpython/jit/metainterp/logger.py
--- a/rpython/jit/metainterp/logger.py
+++ b/rpython/jit/metainterp/logger.py
@@ -82,6 +82,9 @@
     def _make_log_operations(self):
         return LogOperations(self.metainterp_sd, self.guard_number)
 
+    def repr_of_resop(self, op):
+        return LogOperations(self.metainterp_sd, 
self.guard_number).repr_of_resop(op)
+
 
 class LogOperations(object):
     """
diff --git a/rpython/jit/metainterp/optimizeopt/heap.py 
b/rpython/jit/metainterp/optimizeopt/heap.py
--- a/rpython/jit/metainterp/optimizeopt/heap.py
+++ b/rpython/jit/metainterp/optimizeopt/heap.py
@@ -177,7 +177,7 @@
         self.cached_arrayitems = {}
         # cached dict items: {dict descr: {(optval, index): box-or-const}}
         self.cached_dict_reads = {}
-        # cache of corresponding array descrs
+        # cache of corresponding {array descrs: dict 'entries' field descr}
         self.corresponding_array_descrs = {}
         #
         self._lazy_setfields_and_arrayitems = []
@@ -309,12 +309,11 @@
         descrs = op.getdescr().get_extra_info().extradescrs
         assert descrs        # translation hint
         descr1 = descrs[0]
-        descr2 = descrs[1]
-        if descr1 in self.cached_dict_reads:
+        try:
             d = self.cached_dict_reads[descr1]
-        else:
+        except KeyError:
             d = self.cached_dict_reads[descr1] = args_dict()
-            self.corresponding_array_descrs[descr2] = descr1
+            self.corresponding_array_descrs[descrs[1]] = descr1
         args = self.optimizer.make_args_key(op)
         try:
             res_v = d[args]
@@ -348,9 +347,8 @@
             self.force_lazy_setfield(fielddescr, can_cache=False)
         for arraydescr in effectinfo.write_descrs_arrays:
             self.force_lazy_setarrayitem(arraydescr, can_cache=False)
-        for descr in effectinfo.write_descrs_interiorfields:
-            if descr in self.corresponding_array_descrs:
-                dictdescr = self.corresponding_array_descrs.pop(descr)
+            if arraydescr in self.corresponding_array_descrs:
+                dictdescr = self.corresponding_array_descrs.pop(arraydescr)
                 try:
                     del self.cached_dict_reads[dictdescr]
                 except KeyError:
diff --git a/rpython/jit/metainterp/optimizeopt/rewrite.py 
b/rpython/jit/metainterp/optimizeopt/rewrite.py
--- a/rpython/jit/metainterp/optimizeopt/rewrite.py
+++ b/rpython/jit/metainterp/optimizeopt/rewrite.py
@@ -242,8 +242,9 @@
             box = value.box
             assert isinstance(box, Const)
             if not box.same_constant(constbox):
-                raise InvalidLoop('A GUARD_{VALUE,TRUE,FALSE} was proven to' +
-                                  'always fail')
+                r = self.optimizer.metainterp_sd.logger_ops.repr_of_resop(op)
+                raise InvalidLoop('A GUARD_{VALUE,TRUE,FALSE} (%s) was proven '
+                                  'to always fail' % r)
             return
         if emit_operation:
             self.emit_operation(op)
@@ -255,7 +256,9 @@
         if value.is_null():
             return
         elif value.is_nonnull():
-            raise InvalidLoop('A GUARD_ISNULL was proven to always fail')
+            r = self.optimizer.metainterp_sd.logger_ops.repr_of_resop(op)
+            raise InvalidLoop('A GUARD_ISNULL (%s) was proven to always fail'
+                              % r)
         self.emit_operation(op)
         value.make_constant(self.optimizer.cpu.ts.CONST_NULL)
 
@@ -264,7 +267,9 @@
         if value.is_nonnull():
             return
         elif value.is_null():
-            raise InvalidLoop('A GUARD_NONNULL was proven to always fail')
+            r = self.optimizer.metainterp_sd.logger_ops.repr_of_resop(op)
+            raise InvalidLoop('A GUARD_NONNULL (%s) was proven to always fail'
+                              % r)
         self.emit_operation(op)
         value.make_nonnull(op)
 
@@ -292,7 +297,8 @@
                 assert previous_classbox is not None
                 assert expected_classbox is not None
                 if not previous_classbox.same_constant(expected_classbox):
-                    raise InvalidLoop('A GUARD_VALUE was proven to always 
fail')
+                    r = 
self.optimizer.metainterp_sd.logger_ops.repr_of_resop(op)
+                    raise InvalidLoop('A GUARD_VALUE (%s) was proven to always 
fail' % r)
             op = old_guard_op.copy_and_change(rop.GUARD_VALUE,
                                       args = [old_guard_op.getarg(0), 
op.getarg(1)])
             self.optimizer.replaces_guard[op] = old_guard_op
@@ -333,7 +339,9 @@
         if realclassbox is not None:
             if realclassbox.same_constant(expectedclassbox):
                 return
-            raise InvalidLoop('A GUARD_CLASS was proven to always fail')
+            r = self.optimizer.metainterp_sd.logger_ops.repr_of_resop(op)
+            raise InvalidLoop('A GUARD_CLASS (%s) was proven to always fail'
+                              % r)
         if value.last_guard:
             # there already has been a guard_nonnull or guard_class or
             # guard_nonnull_class on this value.
@@ -356,8 +364,9 @@
     def optimize_GUARD_NONNULL_CLASS(self, op):
         value = self.getvalue(op.getarg(0))
         if value.is_null():
-            raise InvalidLoop('A GUARD_NONNULL_CLASS was proven to always ' +
-                              'fail')
+            r = self.optimizer.metainterp_sd.logger_ops.repr_of_resop(op)
+            raise InvalidLoop('A GUARD_NONNULL_CLASS (%s) was proven to '
+                              'always fail' % r)
         self.optimize_GUARD_CLASS(op)
 
     def optimize_CALL_LOOPINVARIANT(self, op):
diff --git a/rpython/jit/metainterp/optimizeopt/test/test_util.py 
b/rpython/jit/metainterp/optimizeopt/test/test_util.py
--- a/rpython/jit/metainterp/optimizeopt/test/test_util.py
+++ b/rpython/jit/metainterp/optimizeopt/test/test_util.py
@@ -319,6 +319,9 @@
         def log_loop(*args):
             pass
 
+    class logger_ops:
+        repr_of_resop = repr
+
     class warmrunnerdesc:
         class memory_manager:
             retrace_limit = 5
diff --git a/rpython/jit/metainterp/optimizeopt/util.py 
b/rpython/jit/metainterp/optimizeopt/util.py
--- a/rpython/jit/metainterp/optimizeopt/util.py
+++ b/rpython/jit/metainterp/optimizeopt/util.py
@@ -139,7 +139,13 @@
         txt1 = str(op1)
         txt2 = str(op2)
         while txt1 or txt2:
-            print '%s| %s' % (txt1[:width].ljust(width), txt2[:width])
+            part1 = txt1[:width]
+            part2 = txt2[:width]
+            if part1 == part2:
+                sep = '| '
+            else:
+                sep = '<>'
+            print '%s%s%s' % (part1.ljust(width), sep, part2)
             txt1 = txt1[width:]
             txt2 = txt2[width:]
     print '-' * totwidth
diff --git a/rpython/jit/metainterp/test/test_dict.py 
b/rpython/jit/metainterp/test/test_dict.py
--- a/rpython/jit/metainterp/test/test_dict.py
+++ b/rpython/jit/metainterp/test/test_dict.py
@@ -294,6 +294,54 @@
         assert res == f(10)
         self.check_simple_loop(call=3)
 
+    def test_dict_eq_can_release_gil(self):
+        from rpython.rtyper.lltypesystem import lltype, rffi
+        if type(self.newdict()) is not dict:
+            py.test.skip("this is an r_dict test")
+        T = rffi.CArrayPtr(rffi.TIME_T)
+        external = rffi.llexternal("time", [T], rffi.TIME_T, releasegil=True)
+        myjitdriver = JitDriver(greens = [], reds = ['total', 'dct'])
+        def key(x):
+            return x % 2
+        def eq(x, y):
+            external(lltype.nullptr(T.TO))
+            return (x % 2) == (y % 2)
+
+        def f(n):
+            dct = objectmodel.r_dict(eq, key)
+            total = n
+            x = 44444
+            y = 55555
+            z = 66666
+            while total:
+                myjitdriver.jit_merge_point(total=total, dct=dct)
+                dct[total] = total
+                x = dct[total]
+                y = dct[total]
+                z = dct[total]
+                total -= 1
+            return len(dct) + x + y + z
+
+        res = self.meta_interp(f, [10], listops=True)
+        assert res == 2 + 1 + 1 + 1
+        self.check_simple_loop(call_may_force=4,    # ll_dict_lookup_trampoline
+                               call=1) # ll_dict_setitem_lookup_done_trampoline
+
+    def test_bug42(self):
+        myjitdriver = JitDriver(greens = [], reds = 'auto')
+        def f(n):
+            mdict = {0: None, 1: None, 2: None, 3: None, 4: None,
+                     5: None, 6: None, 7: None, 8: None, 9: None}
+            while n > 0:
+                myjitdriver.jit_merge_point()
+                n -= 1
+                if n in mdict:
+                    del mdict[n]
+                    if n in mdict:
+                        raise Exception
+        self.meta_interp(f, [10])
+        self.check_simple_loop(call_may_force=0, call=3)
+
 
 class TestLLtype(DictTests, LLJitMixin):
     pass
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to