------------------------------------------------------------------------
                           Usage and Status
------------------------------------------------------------------------

.. contents::
.. sectnum::

Status
======

A foreword of warning about the JIT of PyPy as of March 2007: single
functions doing integer arithmetic get great speed-ups; about anything
else will be a bit slower with the JIT than without.  We are working
on this - you can even expect quick progress, because it is mostly a
matter of adding a few careful hints in the source code of the Python
interpreter of PyPy.

By construction, the JIT is supposed to work correctly on absolutely any
kind of Python code: generators, nested scopes, ``exec`` statements,
``sys._getframe().f_back.f_back.f_locals``, etc. (the latter is an
example of expression that Psyco_ cannot emulate correctly).  However,
there are a couple of known issues for now (see Caveats_).


In more details
---------------

So far there is little point in trying the JIT on anything else than
integer arithmetic-intensive functions (unless you want to help find bugs).
For small examples, you can also look at the machine code it produces, but
if you do please keep in mind that the assembler will look fundamentally
different after we extend the range of PyPy that the JIT generator
processes.

* The produced machine code is kind of good, in the sense that the
  backends perform some reasonable register allocation.  The 386 backend
  computes the lifetime of values within blocks.  The PPC backend does
  not, but the fact that the processor has plenty of registers mitigates
  this problem to some extent.  The PPC backend has at least one known
  bug left.  An LLVM_ backend is started but blocked half-way on a hard
  problem that might not get solved any time soon.

* The *timeshifter*, which produces the JIT frontend, is able to handle
  rather incredibly tricky situations successfully.

* The remaining work is to continue the necessary adjustments of the
  PyPy interpreter source code so that the timeshifter can process more
  of it.  At the moment, the timeshifter sees the interpreter's main
  dispatch loop, integer arithmetic, and a bit of function call logic.
  This means that the produced JIT can remove the bytecode
  interpretation overhead and do a good job with integer arithmetic, but
  cannot optimize at all the manipulations of any other type of objects.

.. _LLVM: http://llvm.org/


How to compile a pypy-c with a JIT
==================================

Go to ``pypy/translator/goal/`` and run::

    ./translate.py --jit targetpypystandalone

Please read the Status_ section above first.

This will produce the C code for a version pypy-c that includes both a
regular interpreter and an automatically generated JIT compiler.  This
pypy-c uses its interpreter by default, and due to some overhead we
expect this interpreter to be a bit slower than the one found in a
pypy-c compiled without JIT.

In addition to ``--jit``, you can also pass the normal options to
``translate.py`` to compile different flavors of PyPy with a JIT.  See
the `compatibility matrix`_ for the combinations known to be working
right now.  (The combination of the JIT with the thunk or taint object
spaces probably works too, but we don't expect it to generate good code
before we drop a few extra hints in the source code of the object
spaces.)

.. _`compatibility matrix`: ../image/compat-matrix.png

Usage
=====

You can mark one or many code objects as candidates for being run by
the JIT as follows::

    >>>> def f(x): return x*5
    >>>> import pypyjit
    >>>> pypyjit.enable(f.func_code)
    >>>> f(7)
    # the JIT runs here
    35
    >>>> f(8)
    # machine code already generated, no more jitting occurs here
    40

A few examples of this kind can be found in `demo/jit/`_.  The script
`demo/jit/f1.py`_ shows a function that becomes seriously faster with
the JIT - only 10% to 20% slower than what ``gcc -O0`` produces from the
obvious equivalent C code, a result similar to Psyco.  Although the JIT
generation process is well-tested, we only have a few tests directly for
the final ``pypy-c``.  Try::

    pypy-c test_all.py module/pypyjit/test/test_pypy_c.py -A --nomagic

You can get a dump of the generated machine code by setting the
environment variable ``PYPYJITLOG`` to a file name before you start
pypy-c.  See `In more details`_ above.  To inspect this file, use the
following tool::

    python  pypy/jit/codegen/i386/viewcode.py  dumpfilename

The viewcode.py script is based on the Linux tool ``objdump`` to produce
a disassembly.  It should be easy to port to OS/X.  If you want to port
the tool to Windows, have a look at
http://codespeak.net/svn/psyco/dist/py-utils/xam.py : this is the tool
from which viewcode.py was derived in the first place, but
Windows-specific parts were omitted for lack of a Windows machine to try
them on.

Caveats
-------

When running JIT'ed code, the bytecode tracing hook is not invoked.  This
should be the only visible effect of the JIT, aside from the debug
prints and the speed/memory impact.  In practice, of course, it still
has also got rough edges.

One of them is that all compile-time errors are fatal for now, because
it is hard to recover from them.  Clearly, the compiler is not
*supposed* to fail, but it can occur because the memory runs out, a bug
hits, or for more subtle reasons.  For example, overflowing the stack is
likely to cause the JIT compiler to try to compile the app-level
handlers for the RuntimeError, and compiling takes up stack space too -
so the compiler, running on top of the already-full stack, might hit the
stack limit again before it has got a chance to generate code for the
app-level handlers.


.. _Psyco: http://psyco.sourceforge.net

.. include:: _ref.txt
