Commits

Tobias Pape committed 3480901 Merge

merge

Comments (0)

Files changed (70)

py/_code/source.py

                 trysource = self[start:end]
                 if trysource.isparseable():
                     return start, end
+                if end == start + 100:   # XXX otherwise, it takes forever
+                    break                # XXX
         if end is None:
             raise IndexError("no valid source range around line %d " % (lineno,))
         return start, end

pypy/doc/whatsnew-head.rst

 .. branch: kill-faking
 .. branch: improved_ebnfparse_error
 .. branch: task-decorator
+.. branch: fix-e4fa0b2
+.. branch: win32-fixes
+.. branch: fix-version-tool
 
 .. branch: release-2.0-beta1
 

pypy/interpreter/app_main.py

     def pypy_find_stdlib(s):
         from os.path import abspath, join, dirname as dn
         thisfile = abspath(__file__)
-        root = dn(dn(dn(dn(thisfile))))
+        root = dn(dn(dn(thisfile)))
         return [join(root, 'lib-python', '2.7'),
                 join(root, 'lib_pypy')]
     
     def pypy_resolvedirof(s):
         # we ignore the issue of symlinks; for tests, the executable is always
-        # translator/goal/app_main.py anyway
+        # interpreter/app_main.py anyway
         import os
         return os.path.abspath(os.path.join(s, '..'))
 

pypy/interpreter/test2/test_app_main.py

             assert line.rstrip() == 'Not at all. They could be carried.'
             print 'A five ounce bird could not carry a one pound coconut.'
             """)
-        py_py = os.path.join(pypydir, 'bin', 'py.py')
+        py_py = os.path.join(pypydir, 'bin', 'pyinteractive.py')
         child = self._spawn(sys.executable, [py_py, '-S', path])
         child.expect('Are you suggesting coconuts migrate?', timeout=120)
         child.sendline('Not at all. They could be carried.')
         assert data == p + os.sep + '\n'
 
     def test_getfilesystemencoding(self):
-        py.test.skip("this has been failing since forever, but it's not tested nightly because buildbot uses python2.6 :-(")
+        py.test.skip("encoding is only set if stdout.isatty(), test is flawed")
         if sys.version_info < (2, 7):
             skip("test requires Python >= 2.7")
         p = getscript_in_dir("""
 
     def test_setup_bootstrap_path(self):
         import sys
-        import os
         old_sys_path = sys.path[:]
         sys.path.append(self.goal_dir)
         try:
         sys.path.append(self.goal_dir)
         try:
             import app_main
-            pypy_c = os.path.join(self.trunkdir, 'pypy', 'translator', 'goal', 'pypy-c')
+            pypy_c = os.path.join(self.trunkdir, 'pypy', 'goal', 'pypy-c')
             app_main.setup_bootstrap_path(pypy_c)
             newpath = sys.path[:]
             # we get at least lib_pypy 
         sys.path.append(self.goal_dir)
         try:
             import app_main
-            pypy_c = os.path.join(self.trunkdir, 'pypy', 'translator', 'goal', 'pypy-c')
+            pypy_c = os.path.join(self.trunkdir, 'pypy', 'goal', 'pypy-c')
             app_main.entry_point(pypy_c, [self.foo_py])
             # assert it did not crash
         finally:

pypy/interpreter/test2/test_targetpypy.py

-
-import py
 from pypy.goal.targetpypystandalone import get_entry_point
 from pypy.config.pypyoption import get_pypy_config
 
     def test_run(self):
         config = get_pypy_config(translating=False)
         entry_point = get_entry_point(config)[0]
-        space = self.space
-        py.test.skip("not working so far")
         entry_point(['pypy-c' , '-S', '-c', 'print 3'])

pypy/module/_ffi/test/test_funcptr.py

         libm = CDLL(self.libm_name)
         pow_addr = libm.getaddressindll('pow')
         fff = sys.maxint*2-1
-        if sys.platform == 'win32':
+        if sys.platform == 'win32' or sys.platform == 'darwin':
             fff = sys.maxint*2+1
         assert pow_addr == self.pow_addr & fff
 

pypy/module/_file/test/test_file.py

         assert f.subclass_closed
 
     def test_readline_unbuffered_should_read_one_line_only(self):
-        import posix
+        import os
 
         with self.file(self.temppath, 'w') as f:
             f.write('foo\nbar\n')
         with self.file(self.temppath, 'r', 0) as f:
             s = f.readline()
             assert s == 'foo\n'
-            s = posix.read(f.fileno(), 10)
+            s = os.read(f.fileno(), 10)
             assert s == 'bar\n'
 
 def test_flush_at_exit():

pypy/module/_file/test/test_file_extra.py

                                   repr(unicode(self.temptestfile)))
         f.close()
 
+    @py.test.mark.skipif("os.name != 'posix'")
     def test_EAGAIN(self):
         import _socket, posix
         s1, s2 = _socket.socketpair()

pypy/module/_io/test/test_fileio.py

 import os
 
 class AppTestFileIO:
-    spaceconfig = dict(usemodules=['_io'])
+    spaceconfig = dict(usemodules=['_io'] + (['fcntl'] if os.name != 'nt' else []))
 
     def setup_class(cls):
         tmpfile = udir.join('tmpfile')

pypy/module/cpyext/test/test_cpyext.py

         kwds["libraries"] = [api_library]
         # '%s' undefined; assuming extern returning int
         kwds["compile_extra"] = ["/we4013"]
+    elif sys.platform == 'darwin':
+        kwds["link_files"] = [str(api_library + '.dylib')]
     else:
         kwds["link_files"] = [str(api_library + '.so')]
         if sys.platform.startswith('linux'):

pypy/module/rctime/test/test_rctime.py

             assert rctime.mktime(rctime.localtime(-1)) == -1
 
         res = rctime.mktime((2000, 1, 1, 0, 0, 0, -1, -1, -1))
-        assert rctime.ctime(res) == 'Sat Jan  1 00:00:00 2000'
+        if os.name == 'nt':
+            assert rctime.ctime(res) == 'Sat Jan 01 00:00:00 2000'
+        else:
+            assert rctime.ctime(res) == 'Sat Jan  1 00:00:00 2000'
 
     def test_asctime(self):
         import time as rctime
 
     def test_strftime(self):
         import time as rctime
-        import os
+        import os, sys
 
         t = rctime.time()
         tt = rctime.gmtime(t)
         # input to [w]strftime is not kosher.
         if os.name == 'nt':
             raises(ValueError, rctime.strftime, '%f')
+        elif sys.platform == 'darwin':
+            # darwin strips % of unknown format codes
+            # http://bugs.python.org/issue9811
+            assert rctime.strftime('%f') == 'f'
         else:
             assert rctime.strftime('%f') == '%f'
 

pypy/module/signal/__init__.py

     }
 
     def buildloaders(cls):
-        from pypy.module.signal import interp_signal
-        for name in interp_signal.signal_names:
-            signum = getattr(interp_signal, name)
+        from rpython.rlib import rsignal
+
+        for name in rsignal.signal_names:
+            signum = getattr(rsignal, name)
             if signum is not None:
                 Module.interpleveldefs[name] = 'space.wrap(%d)' % (signum,)
         super(Module, cls).buildloaders()

pypy/module/signal/interp_signal.py

 from __future__ import with_statement
+
+import signal as cpy_signal
+import sys
+
 from pypy.interpreter.error import OperationError, exception_from_errno
-from pypy.interpreter.executioncontext import AsyncAction, AbstractActionFlag
-from pypy.interpreter.executioncontext import PeriodicAsyncAction
+from pypy.interpreter.executioncontext import (AsyncAction, AbstractActionFlag,
+    PeriodicAsyncAction)
 from pypy.interpreter.gateway import unwrap_spec
-import signal as cpy_signal
-from rpython.rtyper.lltypesystem import lltype, rffi
-from rpython.rtyper.tool import rffi_platform
-from rpython.translator.tool.cbuild import ExternalCompilationInfo
-from rpython.conftest import cdir
-import py
-import sys
+
 from rpython.rlib import jit, rposix
 from rpython.rlib.rarithmetic import intmask
 from rpython.rlib.rsignal import *
+from rpython.rtyper.lltypesystem import lltype, rffi
+
 
 WIN32 = sys.platform == 'win32'
 
+
 class SignalActionFlag(AbstractActionFlag):
     # This class uses the C-level pypysig_counter variable as the tick
     # counter.  The C-level signal handler will reset it to -1 whenever
-    # a signal is received.
+    # a signal is received.  This causes CheckSignalAction.perform() to
+    # be called.
 
     def get_ticker(self):
         p = pypysig_getaddr_occurred()
     def __init__(self, space):
         AsyncAction.__init__(self, space)
         self.handlers_w = {}
-        if space.config.objspace.usemodules.thread:
-            # need a helper action in case signals arrive in a non-main thread
-            self.pending_signals = {}
-            self.reissue_signal_action = ReissueSignalAction(space)
-        else:
-            self.reissue_signal_action = None
+        self.emulated_sigint = False
 
     @jit.dont_look_inside
     def perform(self, executioncontext, frame):
-        while True:
-            n = pypysig_poll()
-            if n < 0:
-                break
-            self.perform_signal(executioncontext, n)
-
-    @jit.dont_look_inside
-    def perform_signal(self, executioncontext, n):
-        if self.reissue_signal_action is None:
-            # no threads: we can report the signal immediately
-            self.report_signal(n)
+        if self.space.config.objspace.usemodules.thread:
+            main_ec = self.space.threadlocals.getmainthreadvalue()
+            in_main = executioncontext is main_ec
         else:
-            main_ec = self.space.threadlocals.getmainthreadvalue()
-            if executioncontext is main_ec:
-                # running in the main thread: we can report the
-                # signal immediately
-                self.report_signal(n)
-            else:
-                # running in another thread: we need to hack a bit
-                self.pending_signals[n] = None
-                self.reissue_signal_action.fire_after_thread_switch()
+            in_main = True
+        # If we are in the main thread, poll and report the signals now.
+        if in_main:
+            if self.emulated_sigint:
+                self.emulated_sigint = False
+                self._report_signal(cpy_signal.SIGINT)
+            while True:
+                n = pypysig_poll()
+                if n < 0:
+                    break
+                self._report_signal(n)
+        else:
+            # Otherwise, don't call pypysig_poll() at all.  Instead,
+            # arrange for perform() to be called again after a thread
+            # switch.  It might be called again and again, until we
+            # land in the main thread.
+            self.fire_after_thread_switch()
 
     @jit.dont_look_inside
     def set_interrupt(self):
         "Simulates the effect of a SIGINT signal arriving"
         ec = self.space.getexecutioncontext()
-        self.perform_signal(ec, cpy_signal.SIGINT)
+        self.emulated_sigint = True
+        self.perform(ec, None)
 
-    @jit.dont_look_inside
-    def report_signal(self, n):
+    def _report_signal(self, n):
         try:
             w_handler = self.handlers_w[n]
         except KeyError:
         w_frame = space.wrap(ec.gettopframe_nohidden())
         space.call_function(w_handler, space.wrap(n), w_frame)
 
-    @jit.dont_look_inside
-    def report_pending_signals(self):
-        # XXX this logic isn't so complicated but I have no clue how
-        # to test it :-(
-        pending_signals = self.pending_signals.keys()
-        self.pending_signals.clear()
-        try:
-            while pending_signals:
-                self.report_signal(pending_signals.pop())
-        finally:
-            # in case of exception, put the undelivered signals back
-            # into the dict instead of silently swallowing them
-            if pending_signals:
-                for n in pending_signals:
-                    self.pending_signals[n] = None
-                self.reissue_signal_action.fire()
-
-
-class ReissueSignalAction(AsyncAction):
-    """A special action to help deliver signals to the main thread.  If
-    a non-main thread caught a signal, this action fires after every
-    thread switch until we land in the main thread.
-    """
-
-    def perform(self, executioncontext, frame):
-        main_ec = self.space.threadlocals.getmainthreadvalue()
-        if executioncontext is main_ec:
-            # now running in the main thread: we can really report the signals
-            self.space.check_signal_action.report_pending_signals()
-        else:
-            # still running in some other thread: try again later
-            self.fire_after_thread_switch()
-
 
 @unwrap_spec(signum=int)
 def getsignal(space, signum):
         return action.handlers_w[signum]
     return space.wrap(SIG_DFL)
 
+
 def default_int_handler(space, w_signum, w_frame):
     """
     default_int_handler(...)
     raise OperationError(space.w_KeyboardInterrupt,
                          space.w_None)
 
+
 @jit.dont_look_inside
 @unwrap_spec(timeout=int)
 def alarm(space, timeout):
     return space.wrap(c_alarm(timeout))
 
+
 @jit.dont_look_inside
 def pause(space):
     c_pause()
     return space.w_None
 
+
 def check_signum_exists(space, signum):
     if signum in signal_values:
         return
     raise OperationError(space.w_ValueError,
                          space.wrap("invalid signal value"))
 
+
 def check_signum_in_range(space, signum):
     if 1 <= signum < NSIG:
         return
     A signal handler function is called with two arguments:
     the first is the signal number, the second is the interrupted stack frame.
     """
-    ec      = space.getexecutioncontext()
+    ec = space.getexecutioncontext()
     main_ec = space.threadlocals.getmainthreadvalue()
 
     old_handler = getsignal(space, signum)
     action.handlers_w[signum] = w_handler
     return old_handler
 
+
 @jit.dont_look_inside
 @unwrap_spec(fd=int)
 def set_wakeup_fd(space, fd):
     """Sets the fd to be written to (with '\0') when a signal
     comes in.  Returns the old fd.  A library can use this to
     wakeup select or poll.  The previous fd is returned.
-    
+
     The fd must be non-blocking.
     """
     if space.config.objspace.usemodules.thread:
     old_fd = pypysig_set_wakeup_fd(fd)
     return space.wrap(intmask(old_fd))
 
+
 @jit.dont_look_inside
 @unwrap_spec(signum=int, flag=int)
 def siginterrupt(space, signum, flag):
     rffi.setintfield(timeval, 'c_tv_sec', int(d))
     rffi.setintfield(timeval, 'c_tv_usec', int((d - int(d)) * 1000000))
 
+
 def double_from_timeval(tv):
     return rffi.getintfield(tv, 'c_tv_sec') + (
         rffi.getintfield(tv, 'c_tv_usec') / 1000000.0)
 
+
 def itimer_retval(space, val):
     w_value = space.wrap(double_from_timeval(val.c_it_value))
     w_interval = space.wrap(double_from_timeval(val.c_it_interval))
     return space.newtuple([w_value, w_interval])
 
+
 class Cache:
     def __init__(self, space):
         self.w_itimererror = space.new_exception_class("signal.ItimerError",
                                                        space.w_IOError)
 
+
 def get_itimer_error(space):
     return space.fromcache(Cache).w_itimererror
 
+
 @jit.dont_look_inside
 @unwrap_spec(which=int, first=float, interval=float)
 def setitimer(space, which, first, interval=0):
     """setitimer(which, seconds[, interval])
-    
     Sets given itimer (one of ITIMER_REAL, ITIMER_VIRTUAL
+
     or ITIMER_PROF) to fire after value seconds and after
     that every interval seconds.
     The itimer can be cleared by setting seconds to zero.
-    
+
     Returns old values as a tuple: (delay, interval).
     """
     with lltype.scoped_alloc(itimervalP.TO, 1) as new:
             if ret != 0:
                 raise exception_from_errno(space, get_itimer_error(space))
 
+            return itimer_retval(space, old[0])
 
-            return itimer_retval(space, old[0])
 
 @jit.dont_look_inside
 @unwrap_spec(which=int)
 def getitimer(space, which):
     """getitimer(which)
-    
+
     Returns current value of given itimer.
     """
     with lltype.scoped_alloc(itimervalP.TO, 1) as old:

pypy/module/signal/test/test_signal.py

 
 class AppTestSignal:
     spaceconfig = {
-        "usemodules": ['signal', 'rctime'],
+        "usemodules": ['signal', 'rctime'] + (['fcntl'] if os.name != 'nt' else []),
     }
 
     def setup_class(cls):
         if sys.platform == 'win32':
             raises(ValueError, signal, 42, lambda *args: None)
             raises(ValueError, signal, 7, lambda *args: None)
+        elif sys.platform == 'darwin':
+            raises(ValueError, signal, 42, lambda *args: None)
         else:
             signal(42, lambda *args: None)
             signal(42, SIG_DFL)

pypy/module/sys/version.py

 
 import pypy
 pypydir = os.path.dirname(os.path.abspath(pypy.__file__))
+pypyroot = os.path.dirname(pypydir)
 del pypy
-from pypy.tool.version import get_repo_version_info
+from rpython.tool.version import get_repo_version_info
 
 import time as t
 gmtime = t.gmtime()
         CPYTHON_VERSION[0],
         CPYTHON_VERSION[1],
         CPYTHON_VERSION[2],
-        get_repo_version_info()[2],
+        get_repo_version_info(root=pypyroot)[1],
         date,
         time,
         ver,
     return space.wrap(('PyPy', '', ''))
 
 def get_repo_info(space):
-    info = get_repo_version_info()
+    info = get_repo_version_info(root=pypyroot)
     if info:
-        project, repo_tag, repo_version = info
-        return space.newtuple([space.wrap(project),
+        repo_tag, repo_version = info
+        return space.newtuple([space.wrap('PyPy'),
                                space.wrap(repo_tag),
                                space.wrap(repo_version)])
     else:

pypy/module/sys/vm.py

 def exc_info_with_tb(space):
     operror = space.getexecutioncontext().sys_exc_info()
     if operror is None:
-        return space.newtuple([space.w_None,space.w_None,space.w_None])
+        return space.newtuple([space.w_None, space.w_None, space.w_None])
     else:
         return space.newtuple([operror.w_type, operror.get_w_value(space),
                                space.wrap(operror.get_traceback())])

pypy/module/thread/os_local.py

         local = wref()
         if local is not None:
             del local.dicts[ec]
-        local.last_dict = None
-        local.last_ec = None
+            local.last_dict = None
+            local.last_ec = None

pypy/module/thread/test/test_thread.py

         import signal
 
         def f():
-            time.sleep(0.5)
-            thread.interrupt_main()
+            for x in range(50):
+                if waiting:
+                    thread.interrupt_main()
+                    return
+                print 'tock...', x  # <-force the GIL to be released, as
+                time.sleep(0.01)    #   time.sleep doesn't do non-translated
 
         def busy_wait():
-            for x in range(1000):
+            waiting.append(None)
+            for x in range(100):
                 print 'tick...', x  # <-force the GIL to be released, as
                 time.sleep(0.01)    #   time.sleep doesn't do non-translated
+            waiting.pop()
 
         # This is normally called by app_main.py
         signal.signal(signal.SIGINT, signal.default_int_handler)
 
-        thread.start_new_thread(f, ())
-        raises(KeyboardInterrupt, busy_wait)
+        for i in range(100):
+            waiting = []
+            thread.start_new_thread(f, ())
+            raises(KeyboardInterrupt, busy_wait)

pypy/module/unicodedata/interp_ucd.py

 from rpython.rlib.objectmodel import we_are_translated
 from rpython.rlib.runicode import MAXUNICODE
 from rpython.rlib.unicodedata import unicodedb_5_2_0, unicodedb_3_2_0
-from rpython.rlib.runicode import code_to_unichr, ORD
+from rpython.rlib.runicode import code_to_unichr, ord_accepts_surrogate
 import sys
 
 
 # handling: on narrow unicode builds, a surrogate pair is considered as one
 # unicode code point.
 
-# The functions below are subtly different from the ones in runicode.py.
-# When PyPy implements Python 3 they should be merged.
 
 if MAXUNICODE > 0xFFFF:
     # Target is wide build
         if not we_are_translated() and sys.maxunicode == 0xFFFF:
             # Host CPython is narrow build, accept surrogates
             try:
-                return ORD(space.unicode_w(w_unichr))
+                return ord_accepts_surrogate(space.unicode_w(w_unichr))
             except ValueError:
                 raise OperationError(space.w_TypeError, space.wrap(
                     'need a single Unicode character as parameter'))
         else:
             # Accept surrogates
             try:
-                return ORD(space.unicode_w(w_unichr))
+                return ord_accepts_surrogate(space.unicode_w(w_unichr))
             except ValueError:
                 raise OperationError(space.w_TypeError, space.wrap(
                     'need a single Unicode character as parameter'))

pypy/tool/jitlogparser/parser.py

     _lineset = None
     is_bytecode = False
     inline_level = None
+    bytecode_name = None
 
     # factory method
     TraceForOpcode = TraceForOpcode
             return ",".join([str(len(v)) for v in stack])
 
         def append_to_res(bc):
-            if not stack:
-                stack.append([])
-            else:
-                if bc.inline_level is not None and bc.inline_level + 1 != len(stack):
-                    if bc.inline_level < len(stack):
+            if bc.inline_level is not None:
+                if bc.inline_level == len(stack) - 1:
+                    pass
+                elif bc.inline_level > len(stack) - 1:
+                    stack.append([])
+                else:
+                    while bc.inline_level + 1 < len(stack):
                         last = stack.pop()
                         stack[-1].append(cls(last, getpath(stack), storage))
-                    else:
-                        stack.append([])
             stack[-1].append(bc)
 
         so_far = []
         stack = []
+        nothing_yet = True
         for op in operations:
             if op.name == 'debug_merge_point':
                 if so_far:
-                    append_to_res(cls.TraceForOpcode(so_far, storage, loopname))
+                    opc = cls.TraceForOpcode(so_far, storage, loopname)
+                    if nothing_yet:
+                        nothing_yet = False
+                        for i in xrange(opc.inline_level + 1):
+                            stack.append([])
+                    append_to_res(opc)
                     if limit:
                         break
                     so_far = []

pypy/tool/jitlogparser/test/test_parser.py

     f = Function.from_operations(loop.operations, LoopStorage())
     assert f.chunks[-1].filename == 'x.py'
     assert f.filename is None
+
+def test_parse_2_levels_up():
+    loop = parse("""
+    []
+    debug_merge_point(0, 0, 'one')
+    debug_merge_point(1, 0, 'two')
+    debug_merge_point(2, 0, 'three')
+    debug_merge_point(0, 0, 'one')    
+    """)
+    f = Function.from_operations(loop.operations, LoopStorage())
+    assert len(f.chunks) == 3
+
+def test_parse_from_inside():
+    loop = parse("""
+    []
+    debug_merge_point(1, 0, 'two')
+    debug_merge_point(2, 0, 'three')
+    debug_merge_point(0, 0, 'one')    
+    """)
+    f = Function.from_operations(loop.operations, LoopStorage())
+    assert len(f.chunks) == 2
+    

pypy/tool/release/package.py

 #!/usr/bin/env python
 """ A sample script that packages PyPy, provided that it's already built.
-It uses 'pypy/translator/goal/pypy-c' and parts of the rest of the working
+It uses 'pypy/goal/pypy-c' and parts of the rest of the working
 copy.  Usage:
 
     package.py root-pypy-dir [name-of-archive] [name-of-pypy-c] [destination-for-tarball] [pypy-c-path]
 import sys
 import os
 #Add toplevel repository dir to sys.path
-sys.path.insert(0,os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(__file__)))))
+sys.path.insert(0,os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))))
 import py
 import fnmatch
 from rpython.tool.udir import udir

pypy/tool/release/test/test_package.py

         basename = 'pypy-c'
         rename_pypy_c = 'pypy'
         exe_name_in_archive = 'bin/pypy'
-    pypy_c = py.path.local(pypydir).join('..', basename)
+    pypy_c = py.path.local(pypydir).join('goal', basename)
     if not pypy_c.check():
         os.system("echo faked_pypy_c> %s" % (pypy_c,))
         pypy_c.chmod(0755)

pypy/tool/rundictbenchmarks.py

 # this file runs some benchmarks with a pypy-c that is assumed to be
 # built using the MeasuringDictImplementation.
 
-# it should be run with pypy/translator/goal as the cwd, and you'll
+# it should be run with pypy/goal as the cwd, and you'll
 # need to hack a copy of rst2html for yourself (svn docutils
 # required).
 

pypy/tool/test/test_version.py

-import os, sys
-import py
-from pypy.tool.version import get_repo_version_info, _get_hg_archive_version
-
-def test_hg_archival_version(tmpdir):
-    def version_for(name, **kw):
-        path = tmpdir.join(name)
-        path.write('\n'.join('%s: %s' % x for x in kw.items()))
-        return _get_hg_archive_version(str(path))
-
-    assert version_for('release',
-                       tag='release-123',
-                       node='000',
-                      ) == ('PyPy', 'release-123', '000')
-    assert version_for('somebranch',
-                       node='000',
-                       branch='something',
-                      ) == ('PyPy', 'something', '000')
-
-
-def test_get_repo_version_info():
-    assert get_repo_version_info(None)
-    assert get_repo_version_info(os.devnull) == ('PyPy', '?', '?')
-    assert get_repo_version_info(sys.executable) == ('PyPy', '?', '?')

pypy/tool/version.py

-import py
-import os
-from subprocess import Popen, PIPE
-import pypy
-pypydir = os.path.dirname(os.path.abspath(pypy.__file__))
-pypyroot = os.path.dirname(pypydir)
-default_retval = 'PyPy', '?', '?'
-
-def maywarn(err, repo_type='Mercurial'):
-    if not err:
-        return
-
-    from rpython.tool.ansi_print import ansi_log
-    log = py.log.Producer("version")
-    py.log.setconsumer("version", ansi_log)
-    log.WARNING('Errors getting %s information: %s' % (repo_type, err))
-
-def get_repo_version_info(hgexe=None):
-    '''Obtain version information by invoking the 'hg' or 'git' commands.'''
-
-    # Try to see if we can get info from Git if hgexe is not specified.
-    if not hgexe:
-        if os.path.isdir(os.path.join(pypyroot, '.git')):
-            return _get_git_version()
-
-    # Fallback to trying Mercurial.
-    if hgexe is None:
-        hgexe = py.path.local.sysfind('hg')
-
-    if os.path.isfile(os.path.join(pypyroot, '.hg_archival.txt')):
-        return _get_hg_archive_version(os.path.join(pypyroot, '.hg_archival.txt'))
-    elif not os.path.isdir(os.path.join(pypyroot, '.hg')):
-        maywarn('Not running from a Mercurial repository!')
-        return default_retval
-    elif not hgexe:
-        maywarn('Cannot find Mercurial command!')
-        return default_retval
-    else:
-        return _get_hg_version(hgexe)
-
-
-def _get_hg_version(hgexe):
-    env = dict(os.environ)
-    # get Mercurial into scripting mode
-    env['HGPLAIN'] = '1'
-    # disable user configuration, extensions, etc.
-    env['HGRCPATH'] = os.devnull
-
-    try:
-        p = Popen([str(hgexe), 'version', '-q'],
-                  stdout=PIPE, stderr=PIPE, env=env)
-    except OSError, e:
-        maywarn(e)
-        return default_retval
-
-    if not p.stdout.read().startswith('Mercurial Distributed SCM'):
-        maywarn('command does not identify itself as Mercurial')
-        return default_retval
-
-    p = Popen([str(hgexe), 'id', '-i', pypyroot],
-              stdout=PIPE, stderr=PIPE, env=env)
-    hgid = p.stdout.read().strip()
-    maywarn(p.stderr.read())
-    if p.wait() != 0:
-        hgid = '?'
-
-    p = Popen([str(hgexe), 'id', '-t', pypyroot],
-              stdout=PIPE, stderr=PIPE, env=env)
-    hgtags = [t for t in p.stdout.read().strip().split() if t != 'tip']
-    maywarn(p.stderr.read())
-    if p.wait() != 0:
-        hgtags = ['?']
-
-    if hgtags:
-        return 'PyPy', hgtags[0], hgid
-    else:
-        # use the branch instead
-        p = Popen([str(hgexe), 'id', '-b', pypyroot],
-                  stdout=PIPE, stderr=PIPE, env=env)
-        hgbranch = p.stdout.read().strip()
-        maywarn(p.stderr.read())
-
-        return 'PyPy', hgbranch, hgid
-
-
-def _get_hg_archive_version(path):
-    fp = open(path)
-    try:
-        data = dict(x.split(': ', 1) for x in fp.read().splitlines())
-    finally:
-        fp.close()
-    if 'tag' in data:
-        return 'PyPy', data['tag'], data['node']
-    else:
-        return 'PyPy', data['branch'], data['node']
-
-
-def _get_git_version():
-    #XXX: this function is a untested hack,
-    #     so the git mirror tav made will work
-    gitexe = py.path.local.sysfind('git')
-    if not gitexe:
-        return default_retval
-
-    try:
-        p = Popen(
-            [str(gitexe), 'rev-parse', 'HEAD'],
-            stdout=PIPE, stderr=PIPE, cwd=pypyroot
-            )
-    except OSError, e:
-        maywarn(e, 'Git')
-        return default_retval
-    if p.wait() != 0:
-        maywarn(p.stderr.read(), 'Git')
-        return default_retval
-    revision_id = p.stdout.read().strip()[:12]
-    p = Popen(
-        [str(gitexe), 'describe', '--tags', '--exact-match'],
-        stdout=PIPE, stderr=PIPE, cwd=pypyroot
-        )
-    if p.wait() != 0:
-        p = Popen(
-            [str(gitexe), 'branch'], stdout=PIPE, stderr=PIPE,
-            cwd=pypyroot
-            )
-        if p.wait() != 0:
-            maywarn(p.stderr.read(), 'Git')
-            return 'PyPy', '?', revision_id
-        branch = '?'
-        for line in p.stdout.read().strip().split('\n'):
-            if line.startswith('* '):
-                branch = line[1:].strip()
-                if branch == '(no branch)':
-                    branch = '?'
-                break
-        return 'PyPy', branch, revision_id
-    return 'PyPy', p.stdout.read().strip(), revision_id
-
-
-if __name__ == '__main__':
-    print get_repo_version_info()

rpython/annotator/builtin.py

         s_item = s_ImpossibleValue
     else:
         nonneg = False # so far
-        if step > 0:
+        if step > 0 or s_step.nonneg:
             nonneg = s_start.nonneg
         elif step < 0:
             nonneg = s_stop.nonneg or (s_stop.is_constant() and

rpython/annotator/test/test_annrpython.py

         assert isinstance(s, annmodel.SomeInteger)
         assert s.nonneg
 
+    def test_range_nonneg_variablestep(self):
+        def get_step(n):
+            if n == 1:
+                return 2
+            else:
+                return 3
+        def fun(n, k):
+            step = get_step(n)
+            for i in range(0, n, step):
+                if k == 17:
+                    return i
+            return 0
+        a = self.RPythonAnnotator()
+        s = a.build_types(fun, [int, int])
+        assert isinstance(s, annmodel.SomeInteger)
+        assert s.nonneg
+
     def test_reverse_range_nonneg(self):
         def fun(n, k):
             for i in range(n-1, -1, -1):
         a = self.RPythonAnnotator()
         s = a.build_types(f, [str])
         assert isinstance(s, annmodel.SomeString)
+        assert s.no_nul
 
         def f(x):
             return u'a'.replace(x, u'b')

rpython/annotator/unaryop.py

         return getbookkeeper().newlist(s_item)
 
     def method_replace(str, s1, s2):
-        return str.basestringclass()
+        return str.basestringclass(no_nul=str.no_nul and s2.no_nul)
 
     def getslice(str, s_start, s_stop):
         check_negative_slice(s_start, s_stop)

rpython/jit/backend/llgraph/llimpl.py

-"""
-The non-RPythonic part of the llgraph backend.
-This contains all the code that is directly run
-when executing on top of the llinterpreter.
-"""
-
-import weakref
-from rpython.flowspace.model import Variable, Constant
-from rpython.annotator import model as annmodel
-from rpython.jit.metainterp.history import REF, INT, FLOAT
-from rpython.jit.metainterp import history
-from rpython.jit.codewriter import heaptracker
-from rpython.rtyper.lltypesystem import lltype, llmemory, rclass, rstr, rffi
-from rpython.rtyper.ootypesystem import ootype
-from rpython.rtyper.module.support import LLSupport, OOSupport
-from rpython.rtyper.llinterp import LLException
-from rpython.rtyper.extregistry import ExtRegistryEntry
-
-from rpython.jit.metainterp import resoperation
-from rpython.jit.metainterp.resoperation import rop
-from rpython.jit.backend.llgraph import symbolic
-from rpython.jit.codewriter import longlong
-from rpython.jit.codewriter.effectinfo import EffectInfo
-
-from rpython.rlib.objectmodel import ComputedIntSymbolic, we_are_translated
-from rpython.rlib.rarithmetic import ovfcheck
-from rpython.rlib.rarithmetic import r_longlong, r_ulonglong, r_uint
-from rpython.rlib.rtimer import read_timestamp
-
-import py
-from rpython.tool.ansi_print import ansi_log
-log = py.log.Producer('runner')
-py.log.setconsumer('runner', ansi_log)
-
-IS_32_BIT = r_ulonglong is not r_uint
-
-
-def _from_opaque(opq):
-    return opq._obj.externalobj
-
-_TO_OPAQUE = {}
-
-def _to_opaque(value):
-    try:
-        return value._the_opaque_pointer
-    except AttributeError:
-        op = lltype.opaqueptr(_TO_OPAQUE[value.__class__], 'opaque',
-                              externalobj=value)
-        value._the_opaque_pointer = op
-        return op
-
-def _normalize(value):
-    if isinstance(value, lltype._ptr):
-        value = lltype.top_container(value._obj)
-    return value
-
-def from_opaque_string(s):
-    if isinstance(s, str):
-        return s
-    elif isinstance(s, ootype._string):
-        return OOSupport.from_rstr(s)
-    else:
-        return LLSupport.from_rstr(s)
-
-FLOAT_ARRAY_TP = lltype.Ptr(lltype.Array(lltype.Float, hints={"nolength": True}))
-def maybe_uncast(TP, array):
-    if array._TYPE.TO.OF != lltype.Float:
-        # array._TYPE.TO._hints.get("uncast_on_llgraph"):
-        array = rffi.cast(TP, array)
-    return array
-
-# a list of argtypes of all operations - couldn't find any and it's
-# very useful.  Note however that the table is half-broken here and
-# there, in ways that are sometimes a bit hard to fix; that's why
-# it is not "official".
-TYPES = {
-    'int_add'         : (('int', 'int'), 'int'),
-    'int_sub'         : (('int', 'int'), 'int'),
-    'int_mul'         : (('int', 'int'), 'int'),
-    'int_floordiv'    : (('int', 'int'), 'int'),
-    'int_mod'         : (('int', 'int'), 'int'),
-    'int_and'         : (('int', 'int'), 'int'),
-    'int_or'          : (('int', 'int'), 'int'),
-    'int_xor'         : (('int', 'int'), 'int'),
-    'int_lshift'      : (('int', 'int'), 'int'),
-    'int_rshift'      : (('int', 'int'), 'int'),
-    'int_lt'          : (('int', 'int'), 'bool'),
-    'int_gt'          : (('int', 'int'), 'bool'),
-    'int_ge'          : (('int', 'int'), 'bool'),
-    'int_le'          : (('int', 'int'), 'bool'),
-    'int_eq'          : (('int', 'int'), 'bool'),
-    'int_ne'          : (('int', 'int'), 'bool'),
-    'int_is_true'     : (('int',), 'bool'),
-    'int_is_zero'     : (('int',), 'bool'),
-    'int_neg'         : (('int',), 'int'),
-    'int_invert'      : (('int',), 'int'),
-    'int_add_ovf'     : (('int', 'int'), 'int'),
-    'int_sub_ovf'     : (('int', 'int'), 'int'),
-    'int_mul_ovf'     : (('int', 'int'), 'int'),
-    'int_force_ge_zero':(('int',), 'int'),
-    'uint_add'        : (('int', 'int'), 'int'),
-    'uint_sub'        : (('int', 'int'), 'int'),
-    'uint_mul'        : (('int', 'int'), 'int'),
-    'uint_lt'         : (('int', 'int'), 'bool'),
-    'uint_le'         : (('int', 'int'), 'bool'),
-    'uint_eq'         : (('int', 'int'), 'bool'),
-    'uint_ne'         : (('int', 'int'), 'bool'),
-    'uint_gt'         : (('int', 'int'), 'bool'),
-    'uint_ge'         : (('int', 'int'), 'bool'),
-    'uint_xor'        : (('int', 'int'), 'int'),
-    'uint_rshift'     : (('int', 'int'), 'int'),
-    'uint_floordiv'   : (('int', 'int'), 'int'),
-    'float_add'       : (('float', 'float'), 'float'),
-    'float_sub'       : (('float', 'float'), 'float'),
-    'float_mul'       : (('float', 'float'), 'float'),
-    'float_truediv'   : (('float', 'float'), 'float'),
-    'float_lt'        : (('float', 'float'), 'bool'),
-    'float_le'        : (('float', 'float'), 'bool'),
-    'float_eq'        : (('float', 'float'), 'bool'),
-    'float_ne'        : (('float', 'float'), 'bool'),
-    'float_gt'        : (('float', 'float'), 'bool'),
-    'float_ge'        : (('float', 'float'), 'bool'),
-    'float_neg'       : (('float',), 'float'),
-    'float_abs'       : (('float',), 'float'),
-    'cast_float_to_int':(('float',), 'int'),
-    'cast_int_to_float':(('int',), 'float'),
-    'same_as'         : (('int',), 'int'),      # could also be ptr=>ptr
-    'new_with_vtable' : (('ref',), 'ref'),
-    'new'             : ((), 'ref'),
-    'new_array'       : (('int',), 'ref'),
-    'oois'            : (('ref', 'ref'), 'bool'),
-    'ooisnot'         : (('ref', 'ref'), 'bool'),
-    'instanceof'      : (('ref',), 'bool'),
-    'subclassof'      : (('ref', 'ref'), 'bool'),
-    'runtimenew'      : (('ref',), 'ref'),
-    'setfield_gc'     : (('ref', 'intorptr'), None),
-    'getfield_gc'     : (('ref',), 'intorptr'),
-    'getfield_gc_pure': (('ref',), 'intorptr'),
-    'setfield_raw'    : (('ref', 'intorptr'), None),
-    'getfield_raw'    : (('ref',), 'intorptr'),
-    'getfield_raw_pure': (('ref',), 'intorptr'),
-    'setarrayitem_gc' : (('ref', 'int', 'intorptr'), None),
-    'getarrayitem_gc' : (('ref', 'int'), 'intorptr'),
-    'getarrayitem_gc_pure' : (('ref', 'int'), 'intorptr'),
-    'setarrayitem_raw' : (('ref', 'int', 'intorptr'), None),
-    'getarrayitem_raw' : (('ref', 'int'), 'intorptr'),
-    'getarrayitem_raw_pure' : (('ref', 'int'), 'intorptr'),
-    'arraylen_gc'     : (('ref',), 'int'),
-    'call'            : (('ref', 'varargs'), 'intorptr'),
-    'call_assembler'  : (('varargs',), 'intorptr'),
-    'cond_call_gc_wb' : (('ptr', 'ptr'), None),
-    'cond_call_gc_wb_array': (('ptr', 'int', 'ptr'), None),
-    'oosend'          : (('varargs',), 'intorptr'),
-    'oosend_pure'     : (('varargs',), 'intorptr'),
-    'guard_true'      : (('bool',), None),
-    'guard_false'     : (('bool',), None),
-    'guard_value'     : (('int', 'int'), None),
-    'guard_class'     : (('ref', 'ref'), None),
-    'guard_no_exception'   : ((), None),
-    'guard_exception'      : (('ref',), 'ref'),
-    'guard_no_overflow'    : ((), None),
-    'guard_overflow'       : ((), None),
-    'guard_nonnull'        : (('ref',), None),
-    'guard_isnull'        : (('ref',), None),
-    'guard_nonnull_class' : (('ref', 'ref'), None),
-    'newstr'          : (('int',), 'ref'),
-    'strlen'          : (('ref',), 'int'),
-    'strgetitem'      : (('ref', 'int'), 'int'),
-    'strsetitem'      : (('ref', 'int', 'int'), None),
-    'newunicode'      : (('int',), 'ref'),
-    'unicodelen'      : (('ref',), 'int'),
-    'unicodegetitem'  : (('ref', 'int'), 'int'),
-    'unicodesetitem'  : (('ref', 'int', 'int'), 'int'),
-    'cast_ptr_to_int' : (('ref',), 'int'),
-    'cast_int_to_ptr' : (('int',), 'ref'),
-    'debug_merge_point': (('ref', 'int', 'int'), None),
-    'force_token'     : ((), 'int'),
-    'call_may_force'  : (('int', 'varargs'), 'intorptr'),
-    'guard_not_forced': ((), None),
-}
-
-# ____________________________________________________________
-
-class CompiledLoop(object):
-    has_been_freed = False
-    invalid = False
-
-    def __init__(self):
-        self.inputargs = []
-        self.operations = []
-
-    def getargtypes(self):
-        return [v.concretetype for v in self.inputargs]
-
-    def __repr__(self):
-        lines = []
-        self.as_text(lines, 1)
-        return 'CompiledLoop %s:\n%s' % (self.inputargs, '\n'.join(lines))
-
-    def as_text(self, lines, indent):
-        for op in self.operations:
-            lines.append('\t'*indent + repr(op))
-
-class Operation(object):
-    result = None
-    descr = None
-    jump_target = None
-    fail_args = None
-
-    def __init__(self, opnum):
-        self.opnum = opnum
-        self.args = []
-
-    def __repr__(self):
-        if self.result is not None:
-            sres = repr0(self.result) + ' = '
-        else:
-            sres = ''
-        return '{%s%s(%s)}' % (sres, self.getopname(),
-                               ', '.join(map(repr0, self.args)))
-
-    def getopname(self):
-        try:
-            return resoperation.opname[self.opnum]
-        except KeyError:
-            return '<%d>' % self.opnum
-
-    def is_guard(self):
-        return rop._GUARD_FIRST <= self.opnum <= rop._GUARD_LAST
-
-    def is_final(self):
-        return rop._FINAL_FIRST <= self.opnum <= rop._FINAL_LAST
-
-def repr0(x):
-    if isinstance(x, list):
-        return '[' + ', '.join(repr0(y) for y in x) + ']'
-    elif isinstance(x, Constant):
-        return '(' + repr0(x.value) + ')'
-    elif isinstance(x, lltype._ptr):
-        x = llmemory.cast_ptr_to_adr(x)
-        if x.ptr:
-            try:
-                container = x.ptr._obj._normalizedcontainer()
-                return '* %s' % (container._TYPE._short_name(),)
-            except AttributeError:
-                return repr(x)
-        else:
-            return 'NULL'
-    else:
-        return repr(x)
-
-def repr_list(lst, types):
-    res_l = []
-    if types and types[-1] == 'varargs':
-        types = types[:-1] + ('int',) * (len(lst) - len(types) + 1)
-    assert len(types) == len(lst)
-    for elem, tp in zip(lst, types):
-        if isinstance(elem, Constant):
-            res_l.append('(%s)' % repr1(elem, tp))
-        else:
-            res_l.append(repr1(elem, tp))
-    return '[%s]' % (', '.join(res_l))
-
-def repr1(x, tp):
-    if tp == "intorptr":
-        TYPE = lltype.typeOf(x)
-        if isinstance(TYPE, lltype.Ptr) and TYPE.TO._gckind == 'gc':
-            tp = "ref"
-        else:
-            tp = "int"
-    if tp == 'int':
-        return str(x)
-    elif tp == 'void':
-        return '---'
-    elif tp == 'ref':
-        if not x:
-            return '(* None)'
-        if isinstance(x, int):
-            # XXX normalize?
-            ptr = str(llmemory.cast_int_to_adr(x))
-        elif isinstance(ootype.typeOf(x), ootype.OOType):
-            return repr(x)
-        else:
-            if getattr(x, '_fake', None):
-                return repr(x)
-            if lltype.typeOf(x) == llmemory.GCREF:
-                TP = lltype.Ptr(lltype.typeOf(x._obj.container))
-                ptr = lltype.cast_opaque_ptr(TP, x)
-            else:
-                ptr = x
-        try:
-            container = ptr._obj._normalizedcontainer()
-            return '(* %s)' % (container._TYPE._short_name(),)
-        except AttributeError:
-            return '(%r)' % (ptr,)
-    elif tp == 'bool':
-        assert x == 0 or x == 1
-        return str(bool(x))
-    #elif tp == 'fieldname':
-    #    return str(symbolic.TokenToField[x...][1])
-    elif tp == 'float':
-        return str(x)
-    else:
-        raise NotImplementedError("tp = %s" % tp)
-
-_variables = []
-
-def compile_start():
-    del _variables[:]
-    return _to_opaque(CompiledLoop())
-
-def mark_as_free(loop):
-    loop = _from_opaque(loop)
-    assert not loop.has_been_freed
-    loop.has_been_freed = True
-
-def compile_start_int_var(loop):
-    return compile_start_ref_var(loop, lltype.Signed)
-
-def compile_start_float_var(loop):
-    return compile_start_ref_var(loop, longlong.FLOATSTORAGE)
-
-def compile_start_ref_var(loop, TYPE):
-    loop = _from_opaque(loop)
-    assert not loop.operations
-    v = Variable()
-    v.concretetype = TYPE
-    loop.inputargs.append(v)
-    r = len(_variables)
-    _variables.append(v)
-    return r
-
-def compile_started_vars(clt):
-    if not hasattr(clt, '_debug_argtypes'):    # only when compiling the loop
-        argtypes = [v.concretetype for v in _variables]
-        try:
-            clt._debug_argtypes = argtypes
-        except AttributeError:    # when 'clt' is actually a translated
-            pass                  # GcStruct
-
-def compile_add(loop, opnum):
-    loop = _from_opaque(loop)
-    loop.operations.append(Operation(opnum))
-
-def compile_add_descr(loop, ofs, type, arg_types, extrainfo, width):
-    from rpython.jit.backend.llgraph.runner import Descr
-    loop = _from_opaque(loop)
-    op = loop.operations[-1]
-    assert isinstance(type, str) and len(type) == 1
-    op.descr = Descr(ofs, type, arg_types=arg_types, extrainfo=extrainfo, width=width)
-
-def compile_add_descr_arg(loop, ofs, type, arg_types):
-    from rpython.jit.backend.llgraph.runner import Descr
-    loop = _from_opaque(loop)
-    op = loop.operations[-1]
-    assert isinstance(type, str) and len(type) == 1
-    op.args.append(Descr(ofs, type, arg_types=arg_types))
-
-def compile_add_loop_token(loop, descr):
-    if we_are_translated():
-        raise ValueError("CALL_ASSEMBLER not supported")
-    loop = _from_opaque(loop)
-    op = loop.operations[-1]
-    op.descr = weakref.ref(descr)
-
-TARGET_TOKENS = weakref.WeakKeyDictionary()
-
-def compile_add_target_token(loop, descr, clt):
-    # here, 'clt' is the compiled_loop_token of the original loop that
-    # we are compiling
-    loop = _from_opaque(loop)
-    op = loop.operations[-1]
-    descrobj = _normalize(descr)
-    TARGET_TOKENS[descrobj] = loop, len(loop.operations), op.args, clt
-
-def compile_add_var(loop, intvar):
-    loop = _from_opaque(loop)
-    op = loop.operations[-1]
-    op.args.append(_variables[intvar])
-
-def compile_add_int_const(loop, value):
-    compile_add_ref_const(loop, value, lltype.Signed)
-
-def compile_add_float_const(loop, value):
-    compile_add_ref_const(loop, value, longlong.FLOATSTORAGE)
-
-def compile_add_ref_const(loop, value, TYPE):
-    loop = _from_opaque(loop)
-    const = Constant(value)
-    const.concretetype = TYPE
-    op = loop.operations[-1]
-    op.args.append(const)
-
-def compile_add_int_result(loop):
-    return compile_add_ref_result(loop, lltype.Signed)
-
-def compile_add_float_result(loop):
-    return compile_add_ref_result(loop, longlong.FLOATSTORAGE)
-
-def compile_add_ref_result(loop, TYPE):
-    loop = _from_opaque(loop)
-    v = Variable()
-    v.concretetype = TYPE
-    op = loop.operations[-1]
-    op.result = v
-    r = len(_variables)
-    _variables.append(v)
-    return r
-
-def compile_add_jump_target(loop, targettoken, source_clt):
-    loop = _from_opaque(loop)
-    descrobj = _normalize(targettoken)
-    (loop_target, target_opindex, target_inputargs, target_clt
-        ) = TARGET_TOKENS[descrobj]
-    #
-    try:
-        assert source_clt._debug_argtypes == target_clt._debug_argtypes
-    except AttributeError:   # when translated
-        pass
-    #
-    op = loop.operations[-1]
-    op.jump_target = loop_target
-    op.jump_target_opindex = target_opindex
-    op.jump_target_inputargs = target_inputargs
-    assert op.opnum == rop.JUMP
-    assert [v.concretetype for v in op.args] == (
-           [v.concretetype for v in target_inputargs])
-    #
-    if loop_target == loop:
-        log.info("compiling new loop")
-    else:
-        log.info("compiling new bridge")
-
-def compile_add_guard_jump_target(loop, loop_target):
-    loop = _from_opaque(loop)
-    loop_target = _from_opaque(loop_target)
-    op = loop.operations[-1]
-    assert op.is_guard()
-    op.jump_target = loop_target
-
-def compile_add_fail(loop, fail_index):
-    loop = _from_opaque(loop)
-    index = len(loop.operations)-1
-    op = loop.operations[index]
-    op.fail_index = fail_index
-    return index
-
-def compile_add_fail_arg(loop, intvar):
-    loop = _from_opaque(loop)
-    op = loop.operations[-1]
-    if op.fail_args is None:
-        op.fail_args = []
-    if intvar == -1:
-        op.fail_args.append(None)
-    else:
-        op.fail_args.append(_variables[intvar])
-
-def compile_redirect_fail(old_loop, old_index, new_loop):
-    old_loop = _from_opaque(old_loop)
-    new_loop = _from_opaque(new_loop)
-    guard_op = old_loop.operations[old_index]
-    assert guard_op.is_guard()
-    guard_op.jump_target = new_loop
-    # check that the bridge's inputargs are of the correct number and
-    # kind for the guard
-    if guard_op.fail_args is not None:
-        argkinds = [v.concretetype for v in guard_op.fail_args if v]
-    else:
-        argkinds = []
-    assert argkinds == [v.concretetype for v in new_loop.inputargs]
-
-# ------------------------------
-
-class Frame(object):
-    OPHANDLERS = [None] * (rop._LAST+1)
-
-    def __init__(self, cpu):
-        self.verbose = False
-        self.cpu = cpu
-        self.opindex = 1
-        self._forced = False
-        self._may_force = -1
-
-    def getenv(self, v):
-        from rpython.jit.backend.llgraph.runner import Descr
-        if isinstance(v, Constant):
-            return v.value
-        elif isinstance(v, Descr):
-            return v
-        else:
-            return self.env[v]
-
-    def _populate_fail_args(self, op, skip=None):
-        fail_args = []
-        if op.fail_args:
-            for fail_arg in op.fail_args:
-                if fail_arg is None:
-                    fail_args.append(None)
-                elif fail_arg is skip:
-                    fail_args.append(fail_arg.concretetype._defl())
-                else:
-                    fail_args.append(self.getenv(fail_arg))
-        self.fail_args = fail_args
-        self.fail_index = op.fail_index
-
-    def execute(self):
-        """Execute all operations in a loop,
-        possibly following to other loops as well.
-        """
-        global _last_exception
-        assert _last_exception is None, "exception left behind"
-        verbose = True
-        self.opindex = 0
-        while True:
-            assert not self.loop.has_been_freed
-            op = self.loop.operations[self.opindex]
-            args = [self.getenv(v) for v in op.args]
-            if not op.is_final():
-                try:
-                    result = self.execute_operation(op.opnum, args, op.descr,
-                                                    verbose)
-                except GuardFailed:
-                    assert op.is_guard()
-                    _stats.exec_conditional_jumps += 1
-                    if op.jump_target is not None:
-                        # a patched guard, pointing to further code
-                        if op.fail_args:
-                            args = [self.getenv(v) for v in op.fail_args if v]
-                        else:
-                            args = []
-                        assert len(op.jump_target.inputargs) == len(args)
-                        self.env = dict(zip(op.jump_target.inputargs, args))
-                        self.loop = op.jump_target
-                        self.opindex = 0
-                        continue
-                    else:
-                        self._populate_fail_args(op)
-                        # a non-patched guard
-                        if self.verbose:
-                            log.trace('failed: %s' % (
-                                ', '.join(map(str, fail_args)),))
-                        return op.fail_index
-                #verbose = self.verbose
-                assert (result is None) == (op.result is None)
-                if op.result is not None:
-                    RESTYPE = op.result.concretetype
-                    if RESTYPE is lltype.Signed:
-                        x = self.as_int(result)
-                    elif RESTYPE is llmemory.GCREF:
-                        x = self.as_ptr(result)
-                    elif RESTYPE is ootype.Object:
-                        x = self.as_object(result)
-                    elif RESTYPE is longlong.FLOATSTORAGE:
-                        x = self.as_floatstorage(result)
-                    else:
-                        raise Exception("op.result.concretetype is %r"
-                                        % (RESTYPE,))
-                    self.env[op.result] = x
-                self.opindex += 1
-                continue
-            if op.opnum == rop.JUMP:
-                inputargs = op.jump_target_inputargs
-                assert len(inputargs) == len(args)
-                self.env = dict(zip(inputargs, args))
-                self.loop = op.jump_target
-                self.opindex = op.jump_target_opindex
-                _stats.exec_jumps += 1
-            elif op.opnum == rop.FINISH:
-                if self.verbose:
-                    log.trace('finished: %s' % (
-                        ', '.join(map(str, args)),))
-                self.fail_args = args
-                return op.fail_index
-
-            else:
-                assert 0, "unknown final operation %d" % (op.opnum,)
-
-    def execute_operation(self, opnum, values, descr, verbose):
-        """Execute a single operation.
-        """
-        ophandler = self.OPHANDLERS[opnum]
-        if ophandler is None:
-            self._define_impl(opnum)
-            ophandler = self.OPHANDLERS[opnum]
-            assert ophandler is not None, "missing impl for op %d" % opnum
-        opname = resoperation.opname[opnum].lower()
-        exec_counters = _stats.exec_counters
-        exec_counters[opname] = exec_counters.get(opname, 0) + 1
-        for i in range(len(values)):
-            if isinstance(values[i], ComputedIntSymbolic):
-                values[i] = values[i].compute_fn()
-        res = NotImplemented
-        try:
-            res = ophandler(self, descr, *values)
-        finally:
-            if 0:     # if verbose:
-                argtypes, restype = TYPES[opname]
-                if res is None:
-                    resdata = ''
-                elif res is NotImplemented:
-                    resdata = '*fail*'
-                else:
-                    resdata = '-> ' + repr1(res, restype)
-                # fish the types
-                log.cpu('\t%s %s %s' % (opname, repr_list(values, argtypes),
-                                        resdata))
-        return res
-
-    def as_int(self, x):
-        return cast_to_int(x)
-
-    def as_ptr(self, x):
-        return cast_to_ptr(x)
-
-    def as_object(self, x):
-        return ootype.cast_to_object(x)
-
-    def as_floatstorage(self, x):
-        return cast_to_floatstorage(x)
-
-    def log_progress(self):
-        count = sum(_stats.exec_counters.values())
-        count_jumps = _stats.exec_jumps
-        log.trace('ran %d operations, %d jumps' % (count, count_jumps))
-
-    # ----------
-
-    @classmethod
-    def _define_impl(cls, opnum):
-        opname = resoperation.opname[opnum]
-        try:
-            op = getattr(cls, 'op_' + opname.lower())   # op_guard_true etc.
-        except AttributeError:
-            try:
-                impl = globals()['do_' + opname.lower()]  # do_arraylen_gc etc.
-                def op(self, descr, *args):
-                    if descr is None:
-                        return impl(*args)
-                    else:
-                        return impl(descr, *args)
-            except KeyError:
-                op = cls._make_impl_from_blackhole_interp(opname)
-        cls.OPHANDLERS[opnum] = op
-
-    @classmethod
-    def _make_impl_from_blackhole_interp(cls, opname):
-        from rpython.jit.metainterp.blackhole import BlackholeInterpreter
-        name = 'bhimpl_' + opname.lower()
-        func = BlackholeInterpreter.__dict__[name]
-        for argtype in func.argtypes:
-            assert argtype in ('i', 'r', 'f')
-        #
-        def _op_default_implementation(self, descr, *args):
-            # for all operations implemented in the blackhole interpreter
-            return func(*args)
-        #
-        return _op_default_implementation
-
-    def op_label(self, _, *args):
-        op = self.loop.operations[self.opindex]
-        assert op.opnum == rop.LABEL
-        assert len(op.args) == len(args)
-        newenv = {}
-        for v, value in zip(op.args, args):
-            newenv[v] = value
-        self.env = newenv
-
-    def op_debug_merge_point(self, _, *args):
-        from rpython.jit.metainterp.warmspot import get_stats
-        try:
-            stats = get_stats()
-        except AttributeError:
-            pass
-        else:
-            stats.add_merge_point_location(args[1:])
-        pass
-
-    def op_guard_true(self, _, value):
-        if not value:
-            raise GuardFailed
-
-    def op_guard_false(self, _, value):
-        if value:
-            raise GuardFailed
-
-    op_guard_nonnull = op_guard_true
-    op_guard_isnull  = op_guard_false
-
-    def op_guard_class(self, _, value, expected_class):
-        value = lltype.cast_opaque_ptr(rclass.OBJECTPTR, value)
-        expected_class = llmemory.cast_adr_to_ptr(
-            llmemory.cast_int_to_adr(expected_class),
-            rclass.CLASSTYPE)
-        if value.typeptr != expected_class:
-            raise GuardFailed
-
-    def op_guard_nonnull_class(self, _, value, expected_class):
-        if not value:
-            raise GuardFailed
-        self.op_guard_class(_, value, expected_class)
-
-    def op_guard_value(self, _, value, expected_value):
-        if value != expected_value:
-            raise GuardFailed
-
-    def op_guard_no_exception(self, _):
-        if _last_exception:
-            raise GuardFailed
-
-    def _check_exception(self, expected_exception):
-        global _last_exception
-        expected_exception = self._cast_exception(expected_exception)
-        assert expected_exception
-        exc = _last_exception
-        if exc:
-            got = exc.args[0]
-            # exact match!
-            if got != expected_exception:
-                return False
-            return True
-        else:
-            return False
-
-    def _cast_exception(self, exception):
-        return llmemory.cast_adr_to_ptr(
-            llmemory.cast_int_to_adr(exception),
-            rclass.CLASSTYPE)
-
-    def _issubclass(self, cls1, cls2):
-        return rclass.ll_issubclass(cls1, cls2)
-
-    def op_guard_exception(self, _, expected_exception):
-        global _last_exception
-        if not self._check_exception(expected_exception):
-            raise GuardFailed
-        res = _last_exception[1]
-        _last_exception = None
-        return res
-
-    def op_guard_no_overflow(self, _):
-        flag = self.overflow_flag
-        del self.overflow_flag
-        if flag:
-            raise GuardFailed
-
-    def op_guard_overflow(self, _):
-        flag = self.overflow_flag
-        del self.overflow_flag
-        if not flag:
-            raise GuardFailed
-
-    def op_int_add_ovf(self, _, x, y):
-        try:
-            z = ovfcheck(x + y)
-        except OverflowError:
-            ovf = True
-            z = 0
-        else:
-            ovf = False
-        self.overflow_flag = ovf
-        return z
-
-    def op_int_sub_ovf(self, _, x, y):
-        try:
-            z = ovfcheck(x - y)
-        except OverflowError:
-            ovf = True
-            z = 0
-        else:
-            ovf = False
-        self.overflow_flag = ovf
-        return z
-
-    def op_int_mul_ovf(self, _, x, y):
-        try:
-            z = ovfcheck(x * y)
-        except OverflowError:
-            ovf = True
-            z = 0
-        else:
-            ovf = False
-        self.overflow_flag = ovf
-        return z
-
-    def op_keepalive(self, _, x):
-        pass
-
-    # ----------
-    # delegating to the builtins do_xxx() (done automatically for simple cases)
-
-    def op_getarrayitem_gc(self, arraydescr, array, index):
-        if arraydescr.typeinfo == REF:
-            return do_getarrayitem_gc_ptr(array, index)
-        elif arraydescr.typeinfo == INT:
-            return do_getarrayitem_gc_int(array, index)
-        elif arraydescr.typeinfo == FLOAT:
-            return do_getarrayitem_gc_float(array, index)
-        else:
-            raise NotImplementedError
-
-    op_getarrayitem_gc_pure = op_getarrayitem_gc
-
-    def op_getarrayitem_raw(self, arraydescr, array, index):
-        if arraydescr.typeinfo == REF:
-            raise NotImplementedError("getarrayitem_raw -> gcref")
-        elif arraydescr.typeinfo == INT:
-            return do_getarrayitem_raw_int(array, index, arraydescr.ofs)
-        elif arraydescr.typeinfo == FLOAT:
-            return do_getarrayitem_raw_float(array, index)
-        else:
-            raise NotImplementedError
-
-    op_getarrayitem_raw_pure = op_getarrayitem_raw
-
-    def op_getfield_gc(self, fielddescr, struct):
-        if fielddescr.typeinfo == REF:
-            return do_getfield_gc_ptr(struct, fielddescr.ofs)
-        elif fielddescr.typeinfo == INT:
-            return do_getfield_gc_int(struct, fielddescr.ofs)
-        elif fielddescr.typeinfo == FLOAT:
-            return do_getfield_gc_float(struct, fielddescr.ofs)
-        else:
-            raise NotImplementedError
-
-    op_getfield_gc_pure = op_getfield_gc
-
-    def op_getfield_raw(self, fielddescr, struct):
-        if fielddescr.typeinfo == REF:
-            return do_getfield_raw_ptr(struct, fielddescr.ofs)
-        elif fielddescr.typeinfo == INT:
-            return do_getfield_raw_int(struct, fielddescr.ofs)
-        elif fielddescr.typeinfo == FLOAT:
-            return do_getfield_raw_float(struct, fielddescr.ofs)
-        else:
-            raise NotImplementedError
-
-    op_getfield_raw_pure = op_getfield_raw
-
-    def op_raw_store(self, arraydescr, addr, offset, value):
-        if arraydescr.typeinfo == REF:
-            raise AssertionError("cannot store GC pointer in raw storage")
-        elif arraydescr.typeinfo == INT:
-            do_raw_store_int(addr, offset, arraydescr.ofs, value)
-        elif arraydescr.typeinfo == FLOAT:
-            do_raw_store_float(addr, offset, value)
-        else:
-            raise NotImplementedError
-
-    def op_raw_load(self, arraydescr, addr, offset):
-        if arraydescr.typeinfo == REF: 
-            raise AssertionError("cannot store GC pointer in raw storage")
-        elif arraydescr.typeinfo == INT:
-            return do_raw_load_int(addr, offset, arraydescr.ofs)
-        elif arraydescr.typeinfo == FLOAT:
-            return do_raw_load_float(addr, offset)
-        else:
-            raise NotImplementedError
-
-    def op_new(self, size):
-        return do_new(size.ofs)
-
-    def op_new_with_vtable(self, descr, vtable):
-        assert descr is None
-        descr = heaptracker.vtable2descr(self.cpu, vtable)
-        result = do_new(descr.ofs)
-        value = lltype.cast_opaque_ptr(rclass.OBJECTPTR, result)
-        value.typeptr = cast_from_int(rclass.CLASSTYPE, vtable)
-        return result
-
-    def op_setarrayitem_gc(self, arraydescr, array, index, newvalue):
-        if arraydescr.typeinfo == REF:
-            do_setarrayitem_gc_ptr(array, index, newvalue)
-        elif arraydescr.typeinfo == INT:
-            do_setarrayitem_gc_int(array, index, newvalue)
-        elif arraydescr.typeinfo == FLOAT:
-            do_setarrayitem_gc_float(array, index, newvalue)
-        else:
-            raise NotImplementedError
-
-    def op_setarrayitem_raw(self, arraydescr, array, index, newvalue):
-        if arraydescr.typeinfo == REF:
-            raise NotImplementedError("setarrayitem_raw <- gcref")
-        elif arraydescr.typeinfo == INT:
-            do_setarrayitem_raw_int(array, index, newvalue, arraydescr.ofs)
-        elif arraydescr.typeinfo == FLOAT:
-            do_setarrayitem_raw_float(array, index, newvalue)
-        else:
-            raise NotImplementedError
-
-    def op_getinteriorfield_gc(self, descr, array, index):
-        if descr.typeinfo == REF:
-            return do_getinteriorfield_gc_ptr(array, index, descr.ofs)
-        elif descr.typeinfo == INT:
-            return do_getinteriorfield_gc_int(array, index, descr.ofs)
-        elif descr.typeinfo == FLOAT:
-            return do_getinteriorfield_gc_float(array, index, descr.ofs)
-        else:
-            raise NotImplementedError
-
-    def op_getinteriorfield_raw(self, descr, array, index):
-        if descr.typeinfo == REF:
-            return do_getinteriorfield_raw_ptr(array, index, descr.width, descr.ofs)
-        elif descr.typeinfo == INT:
-            return do_getinteriorfield_raw_int(array, index, descr.width, descr.ofs)
-        elif descr.typeinfo == FLOAT:
-            return do_getinteriorfield_raw_float(array, index, descr.width, descr.ofs)
-        else:
-            raise NotImplementedError
-
-    def op_setinteriorfield_gc(self, descr, array, index, newvalue):
-        if descr.typeinfo == REF:
-            return do_setinteriorfield_gc_ptr(array, index, descr.ofs,
-                                              newvalue)
-        elif descr.typeinfo == INT:
-            return do_setinteriorfield_gc_int(array, index, descr.ofs,
-                                              newvalue)
-        elif descr.typeinfo == FLOAT:
-            return do_setinteriorfield_gc_float(array, index, descr.ofs,
-                                                newvalue)
-        else:
-            raise NotImplementedError
-
-    def op_setinteriorfield_raw(self, descr, array, index, newvalue):
-        if descr.typeinfo == REF:
-            return do_setinteriorfield_raw_ptr(array, index, newvalue, descr.width, descr.ofs)
-        elif descr.typeinfo == INT:
-            return do_setinteriorfield_raw_int(array, index, newvalue, descr.width, descr.ofs)
-        elif descr.typeinfo == FLOAT:
-            return do_setinteriorfield_raw_float(array, index, newvalue, descr.width, descr.ofs)
-        else:
-            raise NotImplementedError
-
-    def op_setfield_gc(self, fielddescr, struct, newvalue):
-        if fielddescr.typeinfo == REF:
-            do_setfield_gc_ptr(struct, fielddescr.ofs, newvalue)
-        elif fielddescr.typeinfo == INT:
-            do_setfield_gc_int(struct, fielddescr.ofs, newvalue)
-        elif fielddescr.typeinfo == FLOAT:
-            do_setfield_gc_float(struct, fielddescr.ofs, newvalue)
-        else:
-            raise NotImplementedError
-
-    def op_setfield_raw(self, fielddescr, struct, newvalue):
-        if fielddescr.typeinfo == REF:
-            do_setfield_raw_ptr(struct, fielddescr.ofs, newvalue)
-        elif fielddescr.typeinfo == INT:
-            do_setfield_raw_int(struct, fielddescr.ofs, newvalue)
-        elif fielddescr.typeinfo == FLOAT:
-            do_setfield_raw_float(struct, fielddescr.ofs, newvalue)
-        else:
-            raise NotImplementedError
-
-    def op_call(self, calldescr, func, *args):
-        effectinfo = calldescr.get_extra_info()
-        if effectinfo is not None and hasattr(effectinfo, 'oopspecindex'):
-            oopspecindex = effectinfo.oopspecindex
-            if oopspecindex == EffectInfo.OS_MATH_SQRT:
-                return do_math_sqrt(args[0])
-        return self._do_call(calldescr, func, args, call_with_llptr=False)
-
-    def op_call_release_gil(self, calldescr, func, *args):
-        return self._do_call(calldescr, func, args, call_with_llptr=True)
-
-    def _do_call(self, calldescr, func, args, call_with_llptr):
-        global _last_exception
-        assert _last_exception is None, "exception left behind"
-        assert _call_args_i == _call_args_r == _call_args_f == []
-        args_in_order = []
-        for x in args:
-            T = lltype.typeOf(x)
-            if T is lltype.Signed:
-                args_in_order.append('i')