Commits

Michael Pavone  committed db2f8a9 Draft Merge

Merge

  • Participants
  • Parent commits f23c258, 66eb9aa

Comments (0)

Files changed (13)

File pypy/jit/metainterp/heapcache.py

                                 if frombox not in self.new_boxes:
                                     del cache[frombox]
                     return
+            else:
+                # Only invalidate things that are either escaped or arguments
+                for descr, boxes in self.heap_cache.iteritems():
+                    for box in boxes.keys():
+                        if not self.is_unescaped(box) or box in argboxes:
+                            del boxes[box]
+                for descr, indices in self.heap_array_cache.iteritems():
+                    for boxes in indices.itervalues():
+                        for box in boxes.keys():
+                            if not self.is_unescaped(box) or box in argboxes:
+                                del boxes[box]
+                return
 
         self.heap_cache.clear()
         self.heap_array_cache.clear()

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

 from pypy.jit.codewriter.policy import JitPolicy
 from pypy.jit.codewriter import codewriter, longlong
 from pypy.rlib.rfloat import isnan
+from pypy.translator.backendopt.all import backend_optimizations
+
 
 def _get_jitcodes(testself, CPUClass, func, values, type_system,
                   supports_longlong=False, translationoptions={}, **kwds):
     policy = JitPolicy()
     policy.set_supports_floats(True)
     policy.set_supports_longlong(supports_longlong)
-    cw.find_all_graphs(policy)
+    graphs = cw.find_all_graphs(policy)
+    if kwds.get("backendopt"):
+        backend_optimizations(rtyper.annotator.translator, graphs=graphs)
     #
     testself.warmrunnerstate = FakeWarmRunnerState()
     testself.warmrunnerstate.cpu = cpu

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

 index2 = ConstInt(1)
 
 
-class FakeEffektinfo(object):
+class FakeEffectinfo(object):
     EF_ELIDABLE_CANNOT_RAISE           = 0 #elidable function (and cannot raise)
     EF_LOOPINVARIANT                   = 1 #special: call it only once per loop
     EF_CANNOT_RAISE                    = 2 #a function which cannot raise
         self.oopspecindex = oopspecindex
 
     def get_extra_info(self):
-        return FakeEffektinfo(self.extraeffect, self.oopspecindex)
+        return FakeEffectinfo(self.extraeffect, self.oopspecindex)
 
 class TestHeapCache(object):
     def test_known_class_box(self):
         assert h.getarrayitem(box1, index2, descr1) is box4
 
         h.invalidate_caches(
-            rop.CALL, FakeCallDescr(FakeEffektinfo.EF_ELIDABLE_CANNOT_RAISE), [])
+            rop.CALL, FakeCallDescr(FakeEffectinfo.EF_ELIDABLE_CANNOT_RAISE), [])
         assert h.getfield(box1, descr1) is box2
         assert h.getarrayitem(box1, index1, descr1) is box2
         assert h.getarrayitem(box1, index2, descr1) is box4
         assert h.getarrayitem(box1, index2, descr1) is box4
 
         h.invalidate_caches(
-            rop.CALL_LOOPINVARIANT, FakeCallDescr(FakeEffektinfo.EF_LOOPINVARIANT), [])
+            rop.CALL_LOOPINVARIANT, FakeCallDescr(FakeEffectinfo.EF_LOOPINVARIANT), [])
 
         h.invalidate_caches(
-            rop.CALL, FakeCallDescr(FakeEffektinfo.EF_RANDOM_EFFECTS), [])
+            rop.CALL, FakeCallDescr(FakeEffectinfo.EF_RANDOM_EFFECTS), [])
         assert h.getfield(box1, descr1) is None
         assert h.getarrayitem(box1, index1, descr1) is None
         assert h.getarrayitem(box1, index2, descr1) is None
         # Just need the destination box for this call
         h.invalidate_caches(
             rop.CALL,
-            FakeCallDescr(FakeEffektinfo.EF_CANNOT_RAISE, FakeEffektinfo.OS_ARRAYCOPY),
+            FakeCallDescr(FakeEffectinfo.EF_CANNOT_RAISE, FakeEffectinfo.OS_ARRAYCOPY),
             [None, None, box2, None, None]
         )
         assert h.getarrayitem(box1, index1, descr1) is box2
         h.invalidate_caches(
             rop.CALL,
-            FakeCallDescr(FakeEffektinfo.EF_CANNOT_RAISE, FakeEffektinfo.OS_ARRAYCOPY),
+            FakeCallDescr(FakeEffectinfo.EF_CANNOT_RAISE, FakeEffectinfo.OS_ARRAYCOPY),
             [None, None, box3, None, None]
         )
         assert h.getarrayitem(box1, index1, descr1) is None
         assert h.getarrayitem(box4, index1, descr1) is box2
         h.invalidate_caches(
             rop.CALL,
-            FakeCallDescr(FakeEffektinfo.EF_CANNOT_RAISE, FakeEffektinfo.OS_ARRAYCOPY),
+            FakeCallDescr(FakeEffectinfo.EF_CANNOT_RAISE, FakeEffectinfo.OS_ARRAYCOPY),
             [None, None, box2, None, None]
         )
         assert h.getarrayitem(box4, index1, descr1) is None
         assert h.is_unescaped(box1)
         assert h.is_unescaped(box2)
         h.invalidate_caches(
-            rop.CALL, FakeCallDescr(FakeEffektinfo.EF_RANDOM_EFFECTS), [box1]
+            rop.CALL, FakeCallDescr(FakeEffectinfo.EF_RANDOM_EFFECTS), [box1]
         )
         assert not h.is_unescaped(box1)
         assert not h.is_unescaped(box2)
+
+    def test_call_doesnt_invalidate_unescaped_boxes(self):
+        h = HeapCache()
+        h.new(box1)
+        assert h.is_unescaped(box1)
+        h.setfield(box1, box2, descr1)
+        h.invalidate_caches(rop.CALL,
+            FakeCallDescr(FakeEffectinfo.EF_CAN_RAISE),
+            []
+        )
+        assert h.getfield(box1, descr1) is box2
+
+    def test_call_doesnt_invalidate_unescaped_array_boxes(self):
+        h = HeapCache()
+        h.new_array(box1, lengthbox1)
+        assert h.is_unescaped(box1)
+        h.setarrayitem(box1, index1, box3, descr1)
+        h.invalidate_caches(rop.CALL,
+            FakeCallDescr(FakeEffectinfo.EF_CAN_RAISE),
+            []
+        )
+        assert h.getarrayitem(box1, index1, descr1) is box3

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

 import py
 from pypy.rlib.objectmodel import newlist_hint
-from pypy.rlib.jit import JitDriver
+from pypy.rlib.jit import JitDriver, promote
 from pypy.jit.metainterp.test.support import LLJitMixin, OOJitMixin
 
 
         self.check_loops(setarrayitem_gc=0, call=0)
 
     def test_vlist_with_default_read(self):
-        jitdriver = JitDriver(greens = [], reds = ['n'])
+        jitdriver = JitDriver(greens=[], reds=['n'])
         def f(n):
             l = [1] * 20
             while n > 0:
                 n -= 1
             return l[0]
 
-        res = self.meta_interp(f, [10], listops=True)
+        res = self.meta_interp(f, [10], listops=True, backendopt=True)
         assert res == f(10)
         self.check_resops(setarrayitem_gc=0, call=0, getarrayitem_gc=0)
 
         r = self.interp_operations(f, [-1])
         assert r == 0
 
+    def test_list_mul_nonzero(self):
+        driver = JitDriver(greens=[], reds=['i', 'n'])
+
+        def f(n):
+            i = 0
+            while i < n:
+                driver.jit_merge_point(i=i, n=n)
+                x = promote(n)
+                l = [-1] * x
+                i -= l[2]
+            return i
+        res = self.meta_interp(f, [5])
+        assert res == 5
+        self.check_resops(call=0)
+
+
 class TestOOtype(ListTests, OOJitMixin):
     pass
 

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

         res = self.interp_operations(fn, [7])
         assert res == 7 + 7 + 1
         self.check_operations_history(setarrayitem_gc=2,
-                setfield_gc=2)
+                setfield_gc=0)
 
     def test_virtualizable_with_array_heap_cache(self):
         myjitdriver = jit.JitDriver(greens = [], reds = ['n', 'x', 'i', 'frame'],
             a1 = [0] * n
             g.a = a1
             return len(a1) + res
-        res = self.interp_operations(fn, [7])
+        res = self.interp_operations(fn, [7], backendopt=True)
         assert res == 7 * 3
         self.check_operations_history(arraylen_gc=1)
 
             x = [0] * n
             x[2] = 21
             return len(a[:n]) + x[2]
-        res = self.interp_operations(fn, [3])
+        res = self.interp_operations(fn, [3], backendopt=True)
         assert res == 24
         self.check_operations_history(getarrayitem_gc=0)
 

File pypy/module/_codecs/interp_codecs.py

         self.codec_search_cache = {}
         self.codec_error_registry = {}
         self.codec_need_encodings = True
-        self.decode_error_handler = self.make_errorhandler(space, True)
-        self.encode_error_handler = self.make_errorhandler(space, False)
+        self.decode_error_handler = self.make_decode_errorhandler(space)
+        self.encode_error_handler = self.make_encode_errorhandler(space)
 
         self.unicodedata_handler = None
 
-    def make_errorhandler(self, space, decode):
-        def unicode_call_errorhandler(errors,  encoding, reason, input,
-                                      startpos, endpos):
+    def _make_errorhandler(self, space, decode):
+        def call_errorhandler(errors, encoding, reason, input, startpos,
+                              endpos):
+            """Generic wrapper for calling into error handlers.
 
+            Returns (unicode_or_none, str_or_none, newpos) as error
+            handlers may return unicode or on Python 3, bytes.
+            """
             w_errorhandler = lookup_error(space, errors)
             if decode:
                 w_cls = space.w_UnicodeDecodeError
                     "position %d from error handler out of bounds", newpos)
             replace = space.unicode_w(w_replace)
             return replace, newpos
-        return unicode_call_errorhandler
+        return call_errorhandler
+
+    def make_decode_errorhandler(self, space):
+        return self._make_errorhandler(space, True)
+
+    def make_encode_errorhandler(self, space):
+        errorhandler = self._make_errorhandler(space, False)
+        def encode_call_errorhandler(errors, encoding, reason, input, startpos,
+                                     endpos):
+            replace, newpos = errorhandler(errors, encoding, reason, input,
+                                           startpos, endpos)
+            return replace, None, newpos
+        return encode_call_errorhandler
 
     def get_unicodedata_handler(self, space):
         if self.unicodedata_handler:

File pypy/module/_codecs/test/test_codecs.py

 
 
 class AppTestCodecs:
-    spaceconfig = dict(usemodules=('unicodedata', 'struct'))
+    spaceconfig = dict(usemodules=('binascii', 'struct', 'unicodedata'))
 
     def test_register_noncallable(self):
         import _codecs

File pypy/module/_multibytecodec/c_codecs.py

             replace = "?"
     else:
         assert errorcb
-        ret, end = errorcb(errors, namecb, reason,
-                           unicodedata, start, end)
-        codec = pypy_cjk_enc_getcodec(encodebuf)
-        replace = encode(codec, ret, "strict", errorcb, namecb)
+        retu, rets, end = errorcb(errors, namecb, reason,
+                                  unicodedata, start, end)
+        if rets is not None:
+            # py3k only
+            replace = rets
+        else:
+            codec = pypy_cjk_enc_getcodec(encodebuf)
+            replace = encode(codec, retu, "strict", errorcb, namecb)
     inbuf = rffi.get_nonmovingbuffer(replace)
     try:
         r = pypy_cjk_enc_replace_on_error(encodebuf, inbuf, len(replace), end)

File pypy/module/_multibytecodec/test/test_app_codecs.py

         repl = u"\u2014"
         s = u"\uDDA1".encode("gbk", "test.multi_bad_handler")
         assert s == '\xA1\xAA'
+
+    def test_encode_custom_error_handler_type(self):
+        import codecs
+        import sys
+        codecs.register_error("test.test_encode_custom_error_handler_type",
+                              lambda e: ('\xc3', e.end))
+        raises(TypeError, u"\uDDA1".encode, "gbk",
+               "test.test_encode_custom_error_handler_type")

File pypy/module/_multibytecodec/test/test_c_codecs.py

     c = getcodec('iso2022_jp')
     s = encode(c, u'\u83ca\u5730\u6642\u592b')
     assert s == '\x1b$B5FCO;~IW\x1b(B' and type(s) is str
+
+def test_encode_custom_error_handler_bytes():
+    c = getcodec("hz")
+    def errorhandler(errors, enc, msg, t, startingpos, endingpos):
+        return None, '\xc3', endingpos
+    s = encode(c, u'abc\u1234def', 'foo', errorhandler)
+    assert '\xc3' in s

File pypy/rlib/jit.py

             def trampoline(%(arguments)s):
                 return func(%(arguments)s)
             if hasattr(func, "oopspec"):
-                # XXX: This seems like it should be here, but it causes errors.
-                # trampoline.oopspec = func.oopspec
+                trampoline.oopspec = func.oopspec
                 del func.oopspec
             trampoline.__name__ = func.__name__ + "_trampoline"
             trampoline._annspecialcase_ = "specialize:call_location"
                 else:
                     return trampoline(%(arguments)s)
             f.__name__ = func.__name__ + "_look_inside_iff"
+            f._always_inline = True
         """ % {"arguments": ", ".join(args)}).compile() in d
         return d["f"]
     return inner

File pypy/rlib/runicode.py

 def default_unicode_error_encode(errors, encoding, msg, u,
                                  startingpos, endingpos):
     if errors == 'replace':
-        return u'?', endingpos
+        return u'?', None, endingpos
     if errors == 'ignore':
-        return u'', endingpos
+        return u'', None, endingpos
     raise UnicodeEncodeError(encoding, u, startingpos, endingpos, msg)
 
 # ____________________________________________________________
                             _encodeUCS4(result, ch3)
                             continue
                     if not allow_surrogates:
-                        r, pos = errorhandler(errors, 'utf-8',
-                                              'surrogates not allowed',
-                                              s, pos-1, pos)
-                        for ch in r:
+                        ru, rs, pos = errorhandler(errors, 'utf-8',
+                                                   'surrogates not allowed',
+                                                   s, pos-1, pos)
+                        if rs is not None:
+                            # py3k only
+                            result.append(rs)
+                            continue
+                        for ch in ru:
                             if ord(ch) < 0x80:
                                 result.append(chr(ord(ch)))
                             else:
             collend = pos+1
             while collend < len(p) and ord(p[collend]) >= limit:
                 collend += 1
-            r, pos = errorhandler(errors, encoding, reason, p,
-                                  collstart, collend)
-            for ch in r:
+            ru, rs, pos = errorhandler(errors, encoding, reason, p,
+                                       collstart, collend)
+            if rs is not None:
+                # py3k only
+                result.append(rs)
+                continue
+            for ch in ru:
                 if ord(ch) < limit:
                     result.append(chr(ord(ch)))
                 else:
 
         c = mapping.get(ch, '')
         if len(c) == 0:
-            res, pos = errorhandler(errors, "charmap",
-                                    "character maps to <undefined>",
-                                    s, pos, pos + 1)
-            for ch2 in res:
+            ru, rs, pos = errorhandler(errors, "charmap",
+                                       "character maps to <undefined>",
+                                       s, pos, pos + 1)
+            if rs is not None:
+                # py3k only
+                result.append(rs)
+                continue
+            for ch2 in ru:
                 c2 = mapping.get(ch2, '')
                 if len(c2) == 0:
                     errorhandler(
                 pass
             collend += 1
         msg = "invalid decimal Unicode string"
-        r, pos = errorhandler(errors, 'decimal',
-                              msg, s, collstart, collend)
-        for char in r:
+        ru, rs, pos = errorhandler(errors, 'decimal',
+                                   msg, s, collstart, collend)
+        if rs is not None:
+            # py3k only
+            errorhandler('strict', 'decimal', msg, s, collstart, collend)
+        for char in ru:
             ch = ord(char)
             if unicodedb.isspace(ch):
                 result.append(' ')

File pypy/rlib/test/test_runicode.py

             assert t is s
             assert start == startingpos
             assert stop == endingpos
-            return "42424242", stop
+            return u"42424242", None, stop
         encoder = self.getencoder(encoding)
         result = encoder(s, len(s), "foo!", errorhandler)
         assert called[0]
         assert "42424242" in result
 
+        # ensure bytes results passthru
+        def errorhandler_bytes(errors, enc, msg, t, startingpos,
+                               endingpos):
+            return None, '\xc3', endingpos
+        result = encoder(s, len(s), "foo!", errorhandler_bytes)
+        assert '\xc3' in result
+
     def checkdecodeerror(self, s, encoding, start, stop,
                          addstuff=True, msg=None):
         called = [0]