[pypy-commit] pypy py3.5: hg merge default

arigo pypy.commits at gmail.com
Wed Oct 12 15:27:34 EDT 2016


Author: Armin Rigo <arigo at tunes.org>
Branch: py3.5
Changeset: r87737:c3484752b4b2
Date: 2016-10-12 11:58 +0200
http://bitbucket.org/pypy/pypy/changeset/c3484752b4b2/

Log:	hg merge default

diff --git a/pypy/doc/contributor.rst b/pypy/doc/contributor.rst
--- a/pypy/doc/contributor.rst
+++ b/pypy/doc/contributor.rst
@@ -1,10 +1,3 @@
-Contributors to PyPy
-====================
-
-Here is a list of developers who have committed to the PyPy source
-code base, ordered by number of commits (which is certainly not a very
-appropriate measure but it's something)::
-
   Armin Rigo
   Maciej Fijalkowski
   Carl Friedrich Bolz
@@ -14,15 +7,15 @@
   Matti Picus
   Alex Gaynor
   Philip Jenvey
+  Ronan Lamy
   Brian Kearns
-  Ronan Lamy
   Michael Hudson
+  Richard Plangger
   Manuel Jacob
   David Schneider
   Holger Krekel
   Christian Tismer
   Hakan Ardo
-  Richard Plangger
   Benjamin Peterson
   Anders Chrigstrom
   Eric van Riet Paap
@@ -38,8 +31,8 @@
   Niklaus Haldimann
   Camillo Bruni
   Laura Creighton
+  Romain Guillebert
   Toon Verwaest
-  Romain Guillebert
   Leonardo Santagada
   Seo Sanghyeon
   Ronny Pfannschmidt
@@ -59,10 +52,12 @@
   Ludovic Aubry
   Jacob Hallen
   Jason Creighton
+  Mark Young
   Alex Martelli
   Michal Bendowski
   stian
   Jan de Mooij
+  Spenser Bauman
   Tyler Wade
   Vincent Legoll
   Michael Foord
@@ -71,19 +66,20 @@
   Valentino Volonghi
   Tomek Meka
   Patrick Maupin
+  Devin Jeanpierre
   Bob Ippolito
   Bruno Gola
   David Malcolm
   Jean-Paul Calderone
-  Mark Young
+  Stefano Rivera
   Timo Paulssen
+  Edd Barrett
   Squeaky
-  Devin Jeanpierre
   Marius Gedminas
   Alexandre Fayolle
   Simon Burton
-  Stefano Rivera
   Martin Matusiak
+  Nicolas Truessel
   Konstantin Lopuhin
   Wenzhu Man
   John Witulski
@@ -93,13 +89,11 @@
   Dario Bertini
   Mark Pearse
   Simon Cross
-  Edd Barrett
   Andreas Stührk
   Tobias Pape
   Jean-Philippe St. Pierre
   Guido van Rossum
   Pavel Vinogradov
-  Spenser Bauman
   Jeremy Thurgood
   Paweł Piotr Przeradowski
   Paul deGrandis
@@ -111,7 +105,6 @@
   tav
   Taavi Burns
   Georg Brandl
-  Nicolas Truessel
   Bert Freudenberg
   Stian Andreassen
   Wanja Saatkamp
@@ -126,12 +119,12 @@
   Preston Timmons
   David Ripton
   Jeff Terrace
+  Tim Felgentreff
   Dusty Phillips
   Lukas Renggli
   Guenter Jantzen
   William Leslie
   Ned Batchelder
-  Tim Felgentreff
   Anton Gulenko
   Amit Regmi
   Ben Young
@@ -159,6 +152,7 @@
   Victor Stinner
   Andrews Medina
   Stuart Williams
+  Daniel Patrick
   Jasper Schulz
   Christian Hudon
   Toby Watson
@@ -283,6 +277,7 @@
   Daniel Neuhäuser
   Ben Mather
   Niclas Olofsson
+  "Aaron Gallagher
   halgari
   Boglarka Vezer
   Chris Pressey
@@ -311,8 +306,10 @@
   jiaaro
   Mads Kiilerich
   opassembler.py
+  JohnDoe
   Antony Lee
   Jason Madden
+  reubano at gmail.com
   Yaroslav Fedevych
   Jim Hunziker
   Markus Unterwaditzer
@@ -331,6 +328,7 @@
   Michael Chermside
   Anna Ravencroft
   pizi
+  remarkablerocket
   Andrey Churin
   Dan Crosta
   Eli Stevens
@@ -339,3 +337,4 @@
   Roman Podoliaka
   Dan Loewenherz
   werat
+  hgattic
diff --git a/pypy/doc/index-of-whatsnew.rst b/pypy/doc/index-of-whatsnew.rst
--- a/pypy/doc/index-of-whatsnew.rst
+++ b/pypy/doc/index-of-whatsnew.rst
@@ -27,7 +27,12 @@
    whatsnew-2.0.0-beta1.rst
    whatsnew-1.9.rst
 
+CPython 3.3 compatible versions
+-------------------------------
 
+.. toctree::
+
+   whatsnew-pypy3-5.5.0.rst
 
 CPython 3.2 compatible versions
 -------------------------------
diff --git a/pypy/doc/release-pypy3.3-v5.5.0.rst b/pypy/doc/release-pypy3.3-v5.5.0.rst
new file mode 100644
--- /dev/null
+++ b/pypy/doc/release-pypy3.3-v5.5.0.rst
@@ -0,0 +1,68 @@
+============
+PyPy3 v5.5.0
+============
+
+We're pleased to announce the release of PyPy3 v5.5.0. Coming four months 
+after PyPy3.3 v5.2, it improves compatibility with Python 3.3 (3.3.5). We 
+strongly recommend updating from previous PyPy3 versions.
+
+We would like to thank all of the people who donated_ to the `py3k proposal`_
+for supporting the work that went into this release.
+
+You can download the PyPy3.3 v5.5.0 release here:
+
+    http://pypy.org/download.html#python-3-3-5-compatible-pypy3-3-v5-5
+
+Highlights
+==========
+
+* Improved Python 3.3.5 support.
+
+  - os.get_terminal_size(), time.monotonic(), str.casefold()
+
+  - faulthandler module
+
+  - There are still some `missing features`_ such as a
+    `PEP 393-like space efficient string representation`_ and `known issues`_
+    including performance regressions (e.g. issue `#2305`_). The focus for this
+    release has been updating to 3.3 compatibility. Windows is also not yet
+    supported.
+
+* `ensurepip`_ is also included (it's only included in CPython 3 >= 3.4).
+
+What is PyPy?
+==============
+
+PyPy is a very compliant Python interpreter, almost a drop-in replacement for
+CPython 2.7.10 and 3.3.5. It's fast due to its integrated tracing JIT
+compiler.
+
+We also welcome developers of other `dynamic languages`_ to see what RPython
+can do for them.
+
+This release supports:
+
+  * **x86** machines on most common operating systems except Windows
+    (Linux 32/64, Mac OS X 64, OpenBSD, FreeBSD),
+
+  * newer **ARM** hardware (ARMv6 or ARMv7, with VFPv3) running Linux,
+
+  * big- and little-endian variants of **PPC64** running Linux,
+
+  * **s390x** running Linux
+
+Please try it out and let us know what you think. We welcome feedback, we know
+you are using PyPy, please tell us about it!
+
+Cheers
+
+The PyPy Team
+
+.. _donated: http://morepypy.blogspot.com/2012/01/py3k-and-numpy-first-stage-thanks-to.html
+.. _`py3k proposal`: http://pypy.org/py3donate.html
+.. _`PEP 393-like space efficient string representation`: https://bitbucket.org/pypy/pypy/issues/2309/optimized-unicode-representation
+.. _`missing features`: https://bitbucket.org/pypy/pypy/issues?status=new&status=open&component=PyPy3+%28running+Python+3.x%29&kind=enhancement
+.. _`known issues`: https://bitbucket.org/pypy/pypy/issues?status=new&status=open&component=PyPy3%20%28running%20Python%203.x%29
+.. _`#2305`: https://bitbucket.org/pypy/pypy/issues/2305
+.. _`ensurepip`: https://docs.python.org/3/library/ensurepip.html#module-ensurepip
+.. _`dynamic languages`: http://pypyjs.org
diff --git a/pypy/doc/whatsnew-pypy3-5.5.0.rst b/pypy/doc/whatsnew-pypy3-5.5.0.rst
new file mode 100644
--- /dev/null
+++ b/pypy/doc/whatsnew-pypy3-5.5.0.rst
@@ -0,0 +1,59 @@
+=========================
+What's new in PyPy3 5.5.0
+=========================
+
+.. this is the revision after 5.2.0 was branched
+.. startrev: 2dd24a7eb90b
+
+.. pull request #454
+
+Update fallback code in time to match CPython.
+
+.. d93d0a6c41f9
+
+Add str.casefold().
+
+.. f1c0e13019d5
+
+Update Unicode character database to version 6.1.0.
+
+.. pull request #461
+
+Make win_perf_counter expose the clock info.
+Add a couple more fallbacks.
+Make time.monotonic conditionally available depending on platform.
+
+.. issue 2346
+
+Make hash(-1) return -2, like it does on CPython.
+
+.. pull request #469
+
+Fix the mappingproxy type to behave as in CPython.
+
+.. branch: py3k-kwonly-builtin
+
+Implement keyword-only arguments for built-in functions. Fix functions in the 
+posix module to have keyword-only arguments wherever CPython has them, instead
+of regular keyword arguments.
+
+.. pull request #475
+
+Add os.get_terminal_size().
+
+.. memoryview stuff
+
+Implement slicing of memoryview objects and improve their compatibility with
+CPython.
+
+.. bdd0b2244dd3
+
+Set up ImportError attributes properly in _imp.load_dynamic().
+
+.. 494a05343a22
+
+Allow __len__ to return any index-like.
+
+.. branch: py3k-faulthandler
+
+Replace stub faulthandler module with a working implementation.
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
@@ -31,6 +31,7 @@
 from rpython.rtyper import rclass
 from rpython.jit.backend.arm import callbuilder
 from rpython.rlib.rarithmetic import r_uint
+from rpython.rlib.rjitlog import rjitlog as jl
 
 
 class ArmGuardToken(GuardToken):
@@ -1012,6 +1013,8 @@
         mc = InstrBuilder(self.cpu.cpuinfo.arch_version)
         mc.B(target)
         mc.copy_to_raw_memory(oldadr)
+        #
+        jl.redirect_assembler(oldlooptoken, newlooptoken, newlooptoken.number)
 
     def emit_op_guard_not_forced(self, op, arglocs, regalloc, fcond):
         ofs = self.cpu.get_ofs_of_frame_field('jf_descr')
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
@@ -1067,6 +1067,7 @@
 
     def prepare_op_guard_not_forced_2(self, op, fcond):
         self.rm.before_call(op.getfailargs(), save_all_regs=True)
+        self.vfprm.before_call(op.getfailargs(), save_all_regs=True)
         fail_locs = self._prepare_guard(op)
         self.assembler.store_force_descr(op, fail_locs[1:], fail_locs[0].value)
         self.possibly_free_vars(op.getfailargs())
diff --git a/rpython/jit/backend/ppc/opassembler.py b/rpython/jit/backend/ppc/opassembler.py
--- a/rpython/jit/backend/ppc/opassembler.py
+++ b/rpython/jit/backend/ppc/opassembler.py
@@ -29,6 +29,7 @@
 from rpython.jit.codewriter.effectinfo import EffectInfo
 from rpython.jit.backend.ppc import callbuilder
 from rpython.rlib.rarithmetic import r_uint
+from rpython.rlib.rjitlog import rjitlog as jl
 
 class IntOpAssembler(object):
         
@@ -1321,6 +1322,7 @@
         mc = PPCBuilder()
         mc.b_abs(target)
         mc.copy_to_raw_memory(oldadr)
+        jl.redirect_assembler(oldlooptoken, newlooptoken, newlooptoken.number)
 
 
 class OpAssembler(IntOpAssembler, GuardOpAssembler,
diff --git a/rpython/jit/backend/ppc/regalloc.py b/rpython/jit/backend/ppc/regalloc.py
--- a/rpython/jit/backend/ppc/regalloc.py
+++ b/rpython/jit/backend/ppc/regalloc.py
@@ -965,6 +965,7 @@
 
     def prepare_guard_not_forced_2(self, op):
         self.rm.before_call(op.getfailargs(), save_all_regs=True)
+        self.fprm.before_call(op.getfailargs(), save_all_regs=True)
         arglocs = self._prepare_guard(op)
         return arglocs
 
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
@@ -2647,6 +2647,32 @@
         deadframe2 = self.cpu.force(frame)
         assert self.cpu.get_int_value(deadframe2, 0) == 30
 
+    def test_guard_not_forced_2_float(self):
+        cpu = self.cpu
+        if not cpu.supports_floats:
+            py.test.skip("requires floats")
+        faildescr = BasicFailDescr(1)
+        finaldescr = BasicFinalDescr(0)
+        loop = parse("""
+        [f0]
+        f1 = float_add(f0, 2.5)
+        p2 = force_token()
+        guard_not_forced_2(descr=faildescr) [f1]
+        finish(p2, descr=finaldescr)
+        """, namespace=locals())
+        looptoken = JitCellToken()
+        self.cpu.compile_loop(loop.inputargs, loop.operations, looptoken)
+        deadframe = self.cpu.execute_token(looptoken, 20.25)
+        fail = self.cpu.get_latest_descr(deadframe)
+        assert fail.identifier == 0
+        frame = self.cpu.get_ref_value(deadframe, 0)
+        # actually, we should get the same pointer in 'frame' and 'deadframe'
+        # but it is not the case on LLGraph
+        if not getattr(self.cpu, 'is_llgraph', False):
+            assert frame == deadframe
+        deadframe2 = self.cpu.force(frame)
+        assert self.cpu.get_float_value(deadframe2, 0) == 22.75
+
     def test_call_to_c_function(self):
         from rpython.rlib.libffi import CDLL, types, ArgChain, FUNCFLAG_CDECL
         from rpython.rtyper.lltypesystem.ll2ctypes import libc_name
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
@@ -466,6 +466,7 @@
                       operations, looptoken, log):
         '''adds the following attributes to looptoken:
                _ll_function_addr    (address of the generated func, as an int)
+               _ll_raw_start        (jitlog: address of the first byte to asm memory)
                _ll_loop_code       (debug: addr of the start of the ResOps)
                _x86_fullsize        (debug: full size including failure)
         '''
@@ -539,10 +540,11 @@
             looptoken._x86_fullsize = full_size
             looptoken._x86_ops_offset = ops_offset
         looptoken._ll_function_addr = rawstart + functionpos
+        looptoken._ll_raw_start = rawstart
 
-        if logger:
-            log = logger.log_trace(jl.MARK_TRACE_ASM, None, self.mc)
-            log.write(inputargs, operations, ops_offset=ops_offset)
+        if log and logger:
+            l = logger.log_trace(jl.MARK_TRACE_ASM, None, self.mc)
+            l.write(inputargs, operations, ops_offset=ops_offset)
 
             # legacy
             if logger.logger_ops:
@@ -594,6 +596,7 @@
         fullsize = self.mc.get_relative_pos()
         #
         rawstart = self.materialize_loop(original_loop_token)
+        original_loop_token._ll_raw_start = rawstart
         self.patch_gcref_table(original_loop_token, rawstart)
         self.patch_stack_checks(frame_depth_no_fixed_size + JITFRAME_FIXED_SIZE,
                                 rawstart)
@@ -1065,7 +1068,8 @@
             assert mc.get_relative_pos() <= 13
         mc.copy_to_raw_memory(oldadr)
         # log the redirection of the call_assembler_* operation
-        jl.redirect_assembler(oldlooptoken, newlooptoken, target)
+        asm_adr = newlooptoken._ll_raw_start
+        jl.redirect_assembler(oldlooptoken, newlooptoken, asm_adr)
 
     def dump(self, text):
         if not self.verbose:
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
@@ -1428,6 +1428,7 @@
 
     def consider_guard_not_forced_2(self, op):
         self.rm.before_call(op.getfailargs(), save_all_regs=True)
+        self.xrm.before_call(op.getfailargs(), save_all_regs=True)
         fail_locs = [self.loc(v) for v in op.getfailargs()]
         self.assembler.store_force_descr(op, fail_locs,
                                          self.fm.get_frame_depth())
diff --git a/rpython/jit/backend/zarch/opassembler.py b/rpython/jit/backend/zarch/opassembler.py
--- a/rpython/jit/backend/zarch/opassembler.py
+++ b/rpython/jit/backend/zarch/opassembler.py
@@ -9,6 +9,7 @@
 from rpython.jit.metainterp.history import (ConstInt)
 from rpython.jit.backend.zarch.codebuilder import ZARCHGuardToken, InstrBuilder
 from rpython.jit.backend.llsupport import symbolic, jitframe
+from rpython.rlib.rjitlog import rjitlog as jl
 import rpython.jit.backend.zarch.conditions as c
 import rpython.jit.backend.zarch.registers as r
 import rpython.jit.backend.zarch.locations as l
@@ -1155,6 +1156,8 @@
         mc.load_imm(r.SCRATCH, target)
         mc.BCR(c.ANY, r.SCRATCH)
         mc.copy_to_raw_memory(oldadr)
+        #
+        jl.redirect_assembler(oldlooptoken, newlooptoken, newlooptoken.number)
 
 
 class MiscOpAssembler(object):
diff --git a/rpython/jit/backend/zarch/regalloc.py b/rpython/jit/backend/zarch/regalloc.py
--- a/rpython/jit/backend/zarch/regalloc.py
+++ b/rpython/jit/backend/zarch/regalloc.py
@@ -1138,6 +1138,7 @@
 
     def prepare_guard_not_forced_2(self, op):
         self.rm.before_call(op.getfailargs(), save_all_regs=True)
+        self.fprm.before_call(op.getfailargs(), save_all_regs=True)
         arglocs = self._prepare_guard(op)
         return arglocs
 
diff --git a/rpython/jit/metainterp/compile.py b/rpython/jit/metainterp/compile.py
--- a/rpython/jit/metainterp/compile.py
+++ b/rpython/jit/metainterp/compile.py
@@ -7,6 +7,7 @@
 from rpython.rlib import rstack
 from rpython.rlib.jit import JitDebugInfo, Counters, dont_look_inside
 from rpython.rlib.rjitlog import rjitlog as jl
+from rpython.rlib.objectmodel import compute_unique_id
 from rpython.conftest import option
 
 from rpython.jit.metainterp.resoperation import ResOperation, rop,\
@@ -1121,6 +1122,10 @@
     version of the code may end up replacing it.
     """
     jitcell_token = make_jitcell_token(jitdriver_sd)
+    #
+    # record the target of a temporary callback to the interpreter
+    jl.tmp_callback(jitcell_token)
+    #
     nb_red_args = jitdriver_sd.num_red_args
     assert len(redargtypes) == nb_red_args
     inputargs = []
@@ -1156,6 +1161,7 @@
     operations[1].setfailargs([])
     operations = get_deep_immutable_oplist(operations)
     cpu.compile_loop(inputargs, operations, jitcell_token, log=False)
+
     if memory_manager is not None:    # for tests
         memory_manager.keep_loop_alive(jitcell_token)
     return jitcell_token
diff --git a/rpython/jit/metainterp/optimizeopt/info.py b/rpython/jit/metainterp/optimizeopt/info.py
--- a/rpython/jit/metainterp/optimizeopt/info.py
+++ b/rpython/jit/metainterp/optimizeopt/info.py
@@ -132,7 +132,6 @@
 
     def force_box(self, op, optforce):
         if self.is_virtual():
-            optforce.forget_numberings()
             #
             if self._is_immutable_and_filled_with_constants(optforce.optimizer):
                 constptr = optforce.optimizer.constant_fold(op)
diff --git a/rpython/jit/metainterp/optimizeopt/optimizer.py b/rpython/jit/metainterp/optimizeopt/optimizer.py
--- a/rpython/jit/metainterp/optimizeopt/optimizer.py
+++ b/rpython/jit/metainterp/optimizeopt/optimizer.py
@@ -249,9 +249,6 @@
     def produce_potential_short_preamble_ops(self, potential_ops):
         pass
 
-    def forget_numberings(self):
-        self.optimizer.forget_numberings()
-
     def _can_optimize_call_pure(self, op):
         arg_consts = []
         for i in range(op.numargs()):
@@ -350,10 +347,6 @@
         for opt in self.optimizations:
             opt.produce_potential_short_preamble_ops(sb)
 
-    def forget_numberings(self):
-        self.metainterp_sd.profiler.count(jitprof.Counters.OPT_FORCINGS)
-        self.resumedata_memo.forget_numberings()
-
     def getinfo(self, op):
         if op.type == 'r':
             return self.getptrinfo(op)
@@ -865,92 +858,6 @@
             return opinfo is not None and opinfo.is_virtual()
         return False
 
-    def pure_reverse(self, op):
-        import sys
-        if self.optpure is None:
-            return
-        optpure = self.optpure
-        if op.getopnum() == rop.INT_ADD:
-            arg0 = op.getarg(0)
-            arg1 = op.getarg(1)
-            optpure.pure_from_args(rop.INT_ADD, [arg1, arg0], op)
-            # Synthesize the reverse op for optimize_default to reuse
-            optpure.pure_from_args(rop.INT_SUB, [op, arg1], arg0)
-            optpure.pure_from_args(rop.INT_SUB, [op, arg0], arg1)
-            if isinstance(arg0, ConstInt):
-                # invert the constant
-                i0 = arg0.getint()
-                if i0 == -sys.maxint - 1:
-                    return
-                inv_arg0 = ConstInt(-i0)
-            elif isinstance(arg1, ConstInt):
-                # commutative
-                i0 = arg1.getint()
-                if i0 == -sys.maxint - 1:
-                    return
-                inv_arg0 = ConstInt(-i0)
-                arg1 = arg0
-            else:
-                return
-            optpure.pure_from_args(rop.INT_SUB, [arg1, inv_arg0], op)
-            optpure.pure_from_args(rop.INT_SUB, [arg1, op], inv_arg0)
-            optpure.pure_from_args(rop.INT_ADD, [op, inv_arg0], arg1)
-            optpure.pure_from_args(rop.INT_ADD, [inv_arg0, op], arg1)
-
-        elif op.getopnum() == rop.INT_SUB:
-            arg0 = op.getarg(0)
-            arg1 = op.getarg(1)
-            optpure.pure_from_args(rop.INT_ADD, [op, arg1], arg0)
-            optpure.pure_from_args(rop.INT_SUB, [arg0, op], arg1)
-            if isinstance(arg1, ConstInt):
-                # invert the constant
-                i1 = arg1.getint()
-                if i1 == -sys.maxint - 1:
-                    return
-                inv_arg1 = ConstInt(-i1)
-                optpure.pure_from_args(rop.INT_ADD, [arg0, inv_arg1], op)
-                optpure.pure_from_args(rop.INT_ADD, [inv_arg1, arg0], op)
-                optpure.pure_from_args(rop.INT_SUB, [op, inv_arg1], arg0)
-                optpure.pure_from_args(rop.INT_SUB, [op, arg0], inv_arg1)
-        elif op.getopnum() == rop.FLOAT_MUL:
-            optpure.pure_from_args(rop.FLOAT_MUL,
-                                   [op.getarg(1), op.getarg(0)], op)
-        elif op.getopnum() == rop.FLOAT_NEG:
-            optpure.pure_from_args(rop.FLOAT_NEG, [op], op.getarg(0))
-        elif op.getopnum() == rop.CAST_INT_TO_PTR:
-            optpure.pure_from_args(rop.CAST_PTR_TO_INT, [op], op.getarg(0))
-        elif op.getopnum() == rop.CAST_PTR_TO_INT:
-            optpure.pure_from_args(rop.CAST_INT_TO_PTR, [op], op.getarg(0))
-
-    #def optimize_GUARD_NO_OVERFLOW(self, op):
-    #    # otherwise the default optimizer will clear fields, which is unwanted
-    #    # in this case
-    #    self.emit(op)
-    # FIXME: Is this still needed?
-
-    def optimize_DEBUG_MERGE_POINT(self, op):
-        self.emit(op)
-
-    def optimize_JIT_DEBUG(self, op):
-        self.emit(op)
-
-    def optimize_STRGETITEM(self, op):
-        indexb = self.getintbound(op.getarg(1))
-        if indexb.is_constant():
-            pass
-            #raise Exception("implement me")
-            #arrayvalue = self.getvalue(op.getarg(0))
-            #arrayvalue.make_len_gt(MODE_STR, op.getdescr(), indexvalue.box.getint())
-        self.optimize_default(op)
-
-    def optimize_UNICODEGETITEM(self, op):
-        indexb = self.getintbound(op.getarg(1))
-        if indexb.is_constant():
-            #arrayvalue = self.getvalue(op.getarg(0))
-            #arrayvalue.make_len_gt(MODE_UNICODE, op.getdescr(), indexvalue.box.getint())
-            pass
-        self.optimize_default(op)
-
     # These are typically removed already by OptRewrite, but it can be
     # dissabled and unrolling emits some SAME_AS ops to setup the
     # optimizier state. These needs to always be optimized out.
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
@@ -143,7 +143,21 @@
             return self.emit(op)
 
     def postprocess_INT_SUB(self, op):
-        self.optimizer.pure_reverse(op)
+        import sys
+        arg0 = op.getarg(0)
+        arg1 = op.getarg(1)
+        self.optimizer.pure_from_args(rop.INT_ADD, [op, arg1], arg0)
+        self.optimizer.pure_from_args(rop.INT_SUB, [arg0, op], arg1)
+        if isinstance(arg1, ConstInt):
+            # invert the constant
+            i1 = arg1.getint()
+            if i1 == -sys.maxint - 1:
+                return
+            inv_arg1 = ConstInt(-i1)
+            self.optimizer.pure_from_args(rop.INT_ADD, [arg0, inv_arg1], op)
+            self.optimizer.pure_from_args(rop.INT_ADD, [inv_arg1, arg0], op)
+            self.optimizer.pure_from_args(rop.INT_SUB, [op, inv_arg1], arg0)
+            self.optimizer.pure_from_args(rop.INT_SUB, [op, arg0], inv_arg1)
 
     def optimize_INT_ADD(self, op):
         if self.is_raw_ptr(op.getarg(0)) or self.is_raw_ptr(op.getarg(1)):
@@ -162,7 +176,32 @@
             return self.emit(op)
 
     def postprocess_INT_ADD(self, op):
-        self.optimizer.pure_reverse(op)
+        import sys
+        arg0 = op.getarg(0)
+        arg1 = op.getarg(1)
+        self.optimizer.pure_from_args(rop.INT_ADD, [arg1, arg0], op)
+        # Synthesize the reverse op for optimize_default to reuse
+        self.optimizer.pure_from_args(rop.INT_SUB, [op, arg1], arg0)
+        self.optimizer.pure_from_args(rop.INT_SUB, [op, arg0], arg1)
+        if isinstance(arg0, ConstInt):
+            # invert the constant
+            i0 = arg0.getint()
+            if i0 == -sys.maxint - 1:
+                return
+            inv_arg0 = ConstInt(-i0)
+        elif isinstance(arg1, ConstInt):
+            # commutative
+            i0 = arg1.getint()
+            if i0 == -sys.maxint - 1:
+                return
+            inv_arg0 = ConstInt(-i0)
+            arg1 = arg0
+        else:
+            return
+        self.optimizer.pure_from_args(rop.INT_SUB, [arg1, inv_arg0], op)
+        self.optimizer.pure_from_args(rop.INT_SUB, [arg1, op], inv_arg0)
+        self.optimizer.pure_from_args(rop.INT_ADD, [op, inv_arg0], arg1)
+        self.optimizer.pure_from_args(rop.INT_ADD, [inv_arg0, op], arg1)
 
     def optimize_INT_MUL(self, op):
         arg1 = self.get_box_replacement(op.getarg(0))
@@ -250,7 +289,8 @@
         return self.emit(op)
 
     def postprocess_FLOAT_MUL(self, op):
-        self.optimizer.pure_reverse(op)
+        self.optimizer.pure_from_args(rop.FLOAT_MUL,
+                                      [op.getarg(1), op.getarg(0)], op)
 
     def optimize_FLOAT_TRUEDIV(self, op):
         arg1 = op.getarg(0)
@@ -277,7 +317,7 @@
         return self.emit(op)
 
     def postprocess_FLOAT_NEG(self, op):
-        self.optimizer.pure_reverse(op)
+        self.optimizer.pure_from_args(rop.FLOAT_NEG, [op], op.getarg(0))
 
     def optimize_guard(self, op, constbox):
         box = op.getarg(0)
@@ -799,11 +839,11 @@
             return True
 
     def optimize_CAST_PTR_TO_INT(self, op):
-        self.optimizer.pure_reverse(op)
+        self.optimizer.pure_from_args(rop.CAST_INT_TO_PTR, [op], op.getarg(0))
         return self.emit(op)
 
     def optimize_CAST_INT_TO_PTR(self, op):
-        self.optimizer.pure_reverse(op)
+        self.optimizer.pure_from_args(rop.CAST_PTR_TO_INT, [op], op.getarg(0))
         return self.emit(op)
 
     def optimize_SAME_AS_I(self, op):
diff --git a/rpython/jit/metainterp/optimizeopt/vstring.py b/rpython/jit/metainterp/optimizeopt/vstring.py
--- a/rpython/jit/metainterp/optimizeopt/vstring.py
+++ b/rpython/jit/metainterp/optimizeopt/vstring.py
@@ -79,7 +79,6 @@
     def force_box(self, op, optforce):
         if not self.is_virtual():
             return op
-        optforce.forget_numberings()
         if self.mode is mode_string:
             s = self.get_constant_string_spec(optforce, mode_string)
             if s is not None:
diff --git a/rpython/jit/metainterp/resume.py b/rpython/jit/metainterp/resume.py
--- a/rpython/jit/metainterp/resume.py
+++ b/rpython/jit/metainterp/resume.py
@@ -167,13 +167,18 @@
         self.liveboxes = {}
         self.current = [0] * size
         self._pos = 0
-        self.n = 0
-        self.v = 0
+        self.num_boxes = 0
+        self.num_virtuals = 0
 
-    def append(self, item):
+    def append_short(self, item):
         self.current[self._pos] = item
         self._pos += 1
 
+    def append_int(self, item):
+        short = rffi.cast(rffi.SHORT, item)
+        assert rffi.cast(lltype.Signed, short) == item
+        return self.append_short(short)
+
 class ResumeDataLoopMemo(object):
 
     def __init__(self, metainterp_sd):
@@ -182,7 +187,6 @@
         self.consts = []
         self.large_ints = {}
         self.refs = self.cpu.ts.new_ref_dict_2()
-        self.numberings = {}
         self.cached_boxes = {}
         self.cached_virtuals = {}
 
@@ -228,8 +232,8 @@
     def _number_boxes(self, iter, arr, optimizer, state):
         """ Number boxes from one snapshot
         """
-        n = state.n
-        v = state.v
+        num_boxes = state.num_boxes
+        num_virtuals = state.num_virtuals
         liveboxes = state.liveboxes
         for item in arr:
             box = iter.get(rffi.cast(lltype.Signed, item))
@@ -248,15 +252,15 @@
                     info = optimizer.getrawptrinfo(box, create=False)
                     is_virtual = (info is not None and info.is_virtual()) 
                 if is_virtual:
-                    tagged = tag(v, TAGVIRTUAL)
-                    v += 1
+                    tagged = tag(num_virtuals, TAGVIRTUAL)
+                    num_virtuals += 1
                 else:
-                    tagged = tag(n, TAGBOX)
-                    n += 1
+                    tagged = tag(num_boxes, TAGBOX)
+                    num_boxes += 1
                 liveboxes[box] = tagged
-            state.append(tagged)
-        state.n = n
-        state.v = v
+            state.append_short(tagged)
+        state.num_boxes = num_boxes
+        state.num_virtuals = num_virtuals
 
     def number(self, optimizer, position, trace):
         snapshot_iter = trace.get_snapshot_iter(position)
@@ -264,29 +268,25 @@
 
         arr = snapshot_iter.vable_array
 
-        state.append(rffi.cast(rffi.SHORT, len(arr)))
+        state.append_int(len(arr))
         self._number_boxes(snapshot_iter, arr, optimizer, state)
 
         arr = snapshot_iter.vref_array
         n = len(arr)
         assert not (n & 1)
-        state.append(rffi.cast(rffi.SHORT, n >> 1))
+        state.append_int(n >> 1)
 
         self._number_boxes(snapshot_iter, arr, optimizer, state)
 
         for snapshot in snapshot_iter.framestack:
             jitcode_index, pc = snapshot_iter.unpack_jitcode_pc(snapshot)
-            state.append(rffi.cast(rffi.SHORT, jitcode_index))
-            state.append(rffi.cast(rffi.SHORT, pc))
+            state.append_int(jitcode_index)
+            state.append_int(pc)
             self._number_boxes(snapshot_iter, snapshot.box_array, optimizer, state)
 
         numb = resumecode.create_numbering(state.current)
-        return numb, state.liveboxes, state.v
-        
-    def forget_numberings(self):
-        # XXX ideally clear only the affected numberings
-        self.numberings.clear()
-        self.clear_box_virtual_numbers()
+        return numb, state.liveboxes, state.num_virtuals
+
 
     # caching for virtuals and boxes inside them
 
@@ -426,14 +426,14 @@
         resume_position = self.guard_op.rd_resume_position
         assert resume_position >= 0
         # count stack depth
-        numb, liveboxes_from_env, v = self.memo.number(optimizer,
+        numb, liveboxes_from_env, num_virtuals = self.memo.number(optimizer,
             resume_position, self.optimizer.trace)
         self.liveboxes_from_env = liveboxes_from_env
         self.liveboxes = {}
         storage.rd_numb = numb
         
         # collect liveboxes and virtuals
-        n = len(liveboxes_from_env) - v
+        n = len(liveboxes_from_env) - num_virtuals
         liveboxes = [None] * n
         self.vfieldboxes = {}
         for box, tagged in liveboxes_from_env.iteritems():
@@ -464,7 +464,7 @@
             assert info is not None and info.is_virtual()
             info.visitor_walk_recursive(fieldbox, self, optimizer)
 
-        self._number_virtuals(liveboxes, optimizer, v)
+        self._number_virtuals(liveboxes, optimizer, num_virtuals)
         self._add_pending_fields(optimizer, pending_setfields)
 
         storage.rd_consts = self.memo.consts
@@ -526,7 +526,7 @@
 
         if self._invalidation_needed(len(liveboxes), nholes):
             memo.clear_box_virtual_numbers()
-        
+
     def _invalidation_needed(self, nliveboxes, nholes):
         memo = self.memo
         # xxx heuristic a bit out of thin air
diff --git a/rpython/memory/gctransform/framework.py b/rpython/memory/gctransform/framework.py
--- a/rpython/memory/gctransform/framework.py
+++ b/rpython/memory/gctransform/framework.py
@@ -679,7 +679,7 @@
         #
         return newgcdependencies
 
-    def get_finish_tables(self):
+    def enum_type_info_members(self):
         # We must first make sure that the type_info_group's members
         # are all followed.  Do it repeatedly while new members show up.
         # Once it is really done, do finish_tables().
@@ -688,6 +688,15 @@
             curtotal = len(self.layoutbuilder.type_info_group.members)
             yield self.layoutbuilder.type_info_group.members[seen:curtotal]
             seen = curtotal
+
+    def get_finish_helpers(self):
+        for dep in self.enum_type_info_members():
+            yield dep
+        yield self.finish_helpers()
+
+    def get_finish_tables(self):
+        for dep in self.enum_type_info_members():
+            yield dep
         yield self.finish_tables()
 
     def write_typeid_list(self):
diff --git a/rpython/memory/gctransform/transform.py b/rpython/memory/gctransform/transform.py
--- a/rpython/memory/gctransform/transform.py
+++ b/rpython/memory/gctransform/transform.py
@@ -286,6 +286,9 @@
         newgcdependencies = self.ll_finalizers_ptrs
         return newgcdependencies
 
+    def get_finish_helpers(self):
+        return self.finish_helpers
+
     def finish_tables(self):
         pass
 
diff --git a/rpython/rlib/rjitlog/rjitlog.py b/rpython/rlib/rjitlog/rjitlog.py
--- a/rpython/rlib/rjitlog/rjitlog.py
+++ b/rpython/rlib/rjitlog/rjitlog.py
@@ -212,7 +212,7 @@
         return method
     return decor
 
-JITLOG_VERSION = 3
+JITLOG_VERSION = 4
 JITLOG_VERSION_16BIT_LE = struct.pack("<H", JITLOG_VERSION)
 
 marks = [
@@ -245,6 +245,7 @@
     ('ABORT_TRACE',),
     ('SOURCE_CODE',),
     ('REDIRECT_ASSEMBLER',),
+    ('TMP_CALLBACK',),
 ]
 
 start = 0x11
@@ -254,12 +255,13 @@
 
 if __name__ == "__main__":
     print("# generated constants from rpython/rlib/jitlog.py")
-    print 'MARK_JITLOG_START = struct.pack("b", "%s")' % hex(0x10)
+    print('import struct')
+    print('MARK_JITLOG_START = struct.pack("b", %s)' % hex(0x10))
     for mark, in marks:
         nmr = globals()['MARK_' + mark]
         h = hex(ord(nmr))
-        print '%s = struct.pack("b", "%s")' % ('MARK_' + mark, h)
-    print 'MARK_JITLOG_END = struct.pack("b", "%s")' % hex(start)
+        print '%s = struct.pack("b", %s)' % ('MARK_' + mark, h)
+    print 'MARK_JITLOG_END = struct.pack("b", %s)' % hex(start)
     for key,value in locals().items():
         if key.startswith("MP_"):
             print '%s = (%s,"%s")' % (key, hex(value[0]), value[1])
@@ -310,16 +312,22 @@
     content = ''.join(list)
     jitlog_write_marked(content, len(content))
 
-def redirect_assembler(oldtoken, newtoken, target):
+def redirect_assembler(oldtoken, newtoken, asm_adr):
     if not jitlog_enabled():
         return
     descr_nmr = compute_unique_id(oldtoken)
     new_descr_nmr = compute_unique_id(newtoken)
     list = [MARK_REDIRECT_ASSEMBLER, encode_le_addr(descr_nmr),
-            encode_le_addr(new_descr_nmr), encode_le_addr(target)]
+            encode_le_addr(new_descr_nmr), encode_le_addr(asm_adr)]
     content = ''.join(list)
     jitlog_write_marked(content, len(content))
 
+def tmp_callback(looptoken):
+    mark_tmp_callback = ''.join([
+        MARK_TMP_CALLBACK,
+        encode_le_addr(compute_unique_id(looptoken)),
+        encode_le_64bit(looptoken.number)])
+    jitlog_write_marked(mark_tmp_callback, len(mark_tmp_callback))
 
 class JitLogger(object):
     def __init__(self, cpu=None):
@@ -343,6 +351,10 @@
     def finish(self):
         jitlog_teardown()
 
+    def next_id(self):
+        self.trace_id += 1
+        return self.trace_id
+
     def start_new_trace(self, metainterp_sd, faildescr=None, entry_bridge=False, jd_name=""):
         # even if the logger is not enabled, increment the trace id
         self.trace_id += 1
diff --git a/rpython/translator/c/database.py b/rpython/translator/c/database.py
--- a/rpython/translator/c/database.py
+++ b/rpython/translator/c/database.py
@@ -275,7 +275,7 @@
         finish_callbacks = []
         if self.gctransformer:
             finish_callbacks.append(('GC transformer: finished helpers',
-                                     self.gctransformer.finish_helpers))
+                                     self.gctransformer.get_finish_helpers()))
             finish_callbacks.append(('GC transformer: finished tables',
                                      self.gctransformer.get_finish_tables()))
 


More information about the pypy-commit mailing list