[pypy-svn] r64721 - in pypy/branch/pyjitpl5-simplify/pypy/jit: backend backend/llgraph backend/minimal backend/test backend/x86 backend/x86/test metainterp metainterp/test tl

antocuni at codespeak.net antocuni at codespeak.net
Mon Apr 27 12:00:09 CEST 2009


Author: antocuni
Date: Mon Apr 27 12:00:08 2009
New Revision: 64721

Modified:
   pypy/branch/pyjitpl5-simplify/pypy/jit/backend/llgraph/llimpl.py
   pypy/branch/pyjitpl5-simplify/pypy/jit/backend/llgraph/runner.py
   pypy/branch/pyjitpl5-simplify/pypy/jit/backend/minimal/runner.py
   pypy/branch/pyjitpl5-simplify/pypy/jit/backend/model.py
   pypy/branch/pyjitpl5-simplify/pypy/jit/backend/test/runner.py
   pypy/branch/pyjitpl5-simplify/pypy/jit/backend/test/test_random.py
   pypy/branch/pyjitpl5-simplify/pypy/jit/backend/x86/assembler.py
   pypy/branch/pyjitpl5-simplify/pypy/jit/backend/x86/runner.py
   pypy/branch/pyjitpl5-simplify/pypy/jit/backend/x86/test/test_regalloc.py
   pypy/branch/pyjitpl5-simplify/pypy/jit/backend/x86/test/test_runner.py
   pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/codewriter.py
   pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/compile.py
   pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/history.py
   pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/pyjitpl.py
   pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/simple_optimize.py
   pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_basic.py
   pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_loop.py
   pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_recursive.py
   pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/warmspot.py
   pypy/branch/pyjitpl5-simplify/pypy/jit/tl/pypyjit_child.py
   pypy/branch/pyjitpl5-simplify/pypy/jit/tl/pypyjit_demo.py
Log:
merge more of the pyjitpl5 branch back to pyjitpl5-simplify (the first part of
the branch was merged in r64647)

svn merge svn+ssh://codespeak.net/svn/pypy/branch/pyjitpl5/ -r64647:HEAD


    ------------------------------------------------------------------------
    r64649 | fijal | 2009-04-24 18:56:39 +0200 (Fri, 24 Apr 2009) | 2 lines
    Changed paths:
       M /pypy/branch/pyjitpl5/pypy/jit/backend/minimal/runner.py

    improve debugging

    ------------------------------------------------------------------------
    r64651 | fijal | 2009-04-24 20:34:55 +0200 (Fri, 24 Apr 2009) | 4 lines
    Changed paths:
       M /pypy/branch/pyjitpl5/pypy/jit/metainterp/compile.py

    disable this optimization. I have a vague feeling that those loops appear
    in random places in old_loops of optimize_bridge and in simple optimize we don't
    check it at all

    ------------------------------------------------------------------------
    r64652 | fijal | 2009-04-24 20:37:31 +0200 (Fri, 24 Apr 2009) | 2 lines
    Changed paths:
       M /pypy/branch/pyjitpl5/pypy/jit/metainterp/compile.py

    that was dumb, I need to think

    ------------------------------------------------------------------------
    r64653 | fijal | 2009-04-24 20:46:52 +0200 (Fri, 24 Apr 2009) | 4 lines
    Changed paths:
       M /pypy/branch/pyjitpl5/pypy/jit/metainterp/compile.py

    don't store pseudo-loops in possible compiled merge points. I must admit I have
    a bit no clue what I'm doing, except I'm pretty sure optimize_bridge should
    not randomly return pseudo loop. Also don't know how to write a test.

    ------------------------------------------------------------------------
    r64654 | fijal | 2009-04-24 20:52:07 +0200 (Fri, 24 Apr 2009) | 2 lines
    Changed paths:
       M /pypy/branch/pyjitpl5/pypy/jit/metainterp/compile.py

    don't add them here as well

    ------------------------------------------------------------------------
    r64655 | fijal | 2009-04-24 21:17:32 +0200 (Fri, 24 Apr 2009) | 7 lines
    Changed paths:
       M /pypy/branch/pyjitpl5/pypy/jit/metainterp/simple_optimize.py

    according to my limited knowledge this should yield true. We should not have
    more than one loop going from a single greenkey. It's obviously not true,
    because we store there both starts from the interpreter and some other
    stuff. Returning old_loops[0] makes no sense, so what should we return?

    I have no clue so far.

    ------------------------------------------------------------------------
    r64656 | fijal | 2009-04-24 21:18:45 +0200 (Fri, 24 Apr 2009) | 2 lines
    Changed paths:
       M /pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py

    make simple optimize the default

    ------------------------------------------------------------------------
    r64657 | fijal | 2009-04-24 21:25:18 +0200 (Fri, 24 Apr 2009) | 2 lines
    Changed paths:
       M /pypy/branch/pyjitpl5/pypy/jit/metainterp/simple_optimize.py

    I think this should also yield true

    ------------------------------------------------------------------------
    r64658 | fijal | 2009-04-24 21:25:47 +0200 (Fri, 24 Apr 2009) | 3 lines
    Changed paths:
       M /pypy/branch/pyjitpl5/pypy/jit/metainterp/compile.py

    attempt at making assertions pass, some tests fail thanks to different
    counts, let's see..

    ------------------------------------------------------------------------
    r64659 | fijal | 2009-04-24 21:38:53 +0200 (Fri, 24 Apr 2009) | 2 lines
    Changed paths:
       M /pypy/branch/pyjitpl5/pypy/jit/metainterp/compile.py

    oops

    ------------------------------------------------------------------------
    r64660 | benjamin | 2009-04-25 00:23:14 +0200 (Sat, 25 Apr 2009) | 1 line
    Changed paths:
       M /pypy/branch/pyjitpl5/pypy/jit/metainterp/compile.py
       M /pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py
       M /pypy/branch/pyjitpl5/pypy/jit/metainterp/simple_optimize.py

    revert r64651 through r64659 because fijal says he didn't know what he was doing :P
    ------------------------------------------------------------------------
    r64661 | fijal | 2009-04-25 02:28:22 +0200 (Sat, 25 Apr 2009) | 3 lines
    Changed paths:
       M /pypy/branch/pyjitpl5/pypy/interpreter/pyopcode.py
       M /pypy/branch/pyjitpl5/pypy/module/pypyjit/interp_jit.py

    Seems our jit is not too happy with pypy's python interpreter. Make it
    look like tests a bit more

    ------------------------------------------------------------------------
    r64662 | benjamin | 2009-04-25 02:55:49 +0200 (Sat, 25 Apr 2009) | 6 lines
    Changed paths:
       M /pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py
       M /pypy/branch/pyjitpl5/pypy/jit/backend/minimal/runner.py
       M /pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py
       M /pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py
       M /pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py
       M /pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py

    implement serialization of prebuilt AbstractValues for space in the binary

    At the moment, only simple ConstInt can be serialized

    I refactored out jitcode decoding from MIFrame

    ------------------------------------------------------------------------
    r64663 | benjamin | 2009-04-25 03:18:34 +0200 (Sat, 25 Apr 2009) | 1 line
    Changed paths:
       A /pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_history.py

    add a test for serializing ConstInt
    ------------------------------------------------------------------------
    r64668 | arigo | 2009-04-25 12:12:57 +0200 (Sat, 25 Apr 2009) | 8 lines
    Changed paths:
       M /pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py
       M /pypy/branch/pyjitpl5/pypy/jit/backend/minimal/runner.py
       M /pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py
       M /pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py
       M /pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py
       M /pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py
       D /pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_history.py

    Revert r64662 and r64663 by benjamin.  It seems completely useless to
    me (saving prebuilt ConstInts that are anyway globally shared so they
    cannot be so numerous), but I may be missing the point.

    Additionally, as Samuele puts it, the current goal should be to maximize
    debuggability.  That seems to make things worse in this respect.  Please
    go to a (sub-)branch for this kind of experiments...

    ------------------------------------------------------------------------
    r64670 | arigo | 2009-04-25 14:05:23 +0200 (Sat, 25 Apr 2009) | 3 lines
    Changed paths:
       M /pypy/branch/pyjitpl5/pypy/jit/backend/test/test_random.py

    Rename GuardBinaryOperation to GuardOperation
    (they are not binary at all).

    ------------------------------------------------------------------------
    r64671 | arigo | 2009-04-25 15:59:28 +0200 (Sat, 25 Apr 2009) | 3 lines
    Changed paths:
       M /pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py

    Avoid the 'make_new_vars' opcodes that only change the order
    of variables, without removing any.

    ------------------------------------------------------------------------
    r64673 | arigo | 2009-04-25 17:59:24 +0200 (Sat, 25 Apr 2009) | 2 lines
    Changed paths:
       M /pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py

    Re-add a line accidentally(?) deleted at r63642.

    ------------------------------------------------------------------------
    r64674 | arigo | 2009-04-25 18:05:47 +0200 (Sat, 25 Apr 2009) | 2 lines
    Changed paths:
       M /pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py

    Translation fix (this time without breaking the semantics, hopefully).

    ------------------------------------------------------------------------
    r64675 | arigo | 2009-04-25 18:14:43 +0200 (Sat, 25 Apr 2009) | 3 lines
    Changed paths:
       M /pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py
       M /pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py

    Revert r64577: I'm not completely sure I get it, but it seems
    related to the accident in r63642 (fixed in r64673).

    ------------------------------------------------------------------------
    r64676 | arigo | 2009-04-25 18:22:31 +0200 (Sat, 25 Apr 2009) | 2 lines
    Changed paths:
       M /pypy/branch/pyjitpl5/pypy/interpreter/pyopcode.py
       M /pypy/branch/pyjitpl5/pypy/module/pypyjit/interp_jit.py

    Revert r64661, as requested by fijal.

    ------------------------------------------------------------------------
    r64677 | arigo | 2009-04-25 18:35:39 +0200 (Sat, 25 Apr 2009) | 3 lines
    Changed paths:
       M /pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py

    * Set DEBUG=True for now.
    * execute() returns None.

    ------------------------------------------------------------------------
    r64679 | arigo | 2009-04-25 19:44:08 +0200 (Sat, 25 Apr 2009) | 3 lines
    Changed paths:
       M /pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py

    Save/restore the exception_box and exc_value_box too.
    This is clearly not looking safe...

    ------------------------------------------------------------------------
    r64681 | arigo | 2009-04-25 19:54:44 +0200 (Sat, 25 Apr 2009) | 2 lines
    Changed paths:
       M /pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py

    Oups

    ------------------------------------------------------------------------
    r64686 | arigo | 2009-04-26 14:17:49 +0200 (Sun, 26 Apr 2009) | 6 lines
    Changed paths:
       M /pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py
       M /pypy/branch/pyjitpl5/pypy/jit/backend/model.py
       M /pypy/branch/pyjitpl5/pypy/jit/backend/test/runner.py
       M /pypy/branch/pyjitpl5/pypy/jit/metainterp/compile.py
       M /pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py
       M /pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py
       M /pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py

    Experimental: replace _save_recursive_call() with the ReturnBoxes class.
    The idea is that the backend should not patch the real boxes in-place,
    but only the boxes in ReturnBoxes.  The front-end will then copy the
    boxes in place in a try:finally:, and restore their value afterwards.
    It's expected to be much safer than the previous hack.

    ------------------------------------------------------------------------
    r64687 | arigo | 2009-04-26 14:23:40 +0200 (Sun, 26 Apr 2009) | 2 lines
    Changed paths:
       M /pypy/branch/pyjitpl5/pypy/jit/backend/minimal/runner.py
       M /pypy/branch/pyjitpl5/pypy/jit/backend/test/runner.py

    Fix the minimal backend.

    ------------------------------------------------------------------------
    r64688 | arigo | 2009-04-26 14:40:09 +0200 (Sun, 26 Apr 2009) | 2 lines
    Changed paths:
       M /pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py
       M /pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/test/test_llgraph.py
       M /pypy/branch/pyjitpl5/pypy/jit/backend/minimal/runner.py
       M /pypy/branch/pyjitpl5/pypy/jit/backend/minimal/test/test_runner.py
       M /pypy/branch/pyjitpl5/pypy/jit/backend/model.py
       M /pypy/branch/pyjitpl5/pypy/jit/backend/test/runner.py
       M /pypy/branch/pyjitpl5/pypy/jit/metainterp/compile.py
       M /pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py

    Simplify the CPU interface a bit.

    ------------------------------------------------------------------------
    r64689 | arigo | 2009-04-26 15:04:24 +0200 (Sun, 26 Apr 2009) | 2 lines
    Changed paths:
       M /pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py
       M /pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/test/test_llgraph.py
       M /pypy/branch/pyjitpl5/pypy/jit/backend/minimal/runner.py
       M /pypy/branch/pyjitpl5/pypy/jit/backend/minimal/test/test_runner.py
       M /pypy/branch/pyjitpl5/pypy/jit/backend/model.py
       M /pypy/branch/pyjitpl5/pypy/jit/backend/test/runner.py
       M /pypy/branch/pyjitpl5/pypy/jit/metainterp/compile.py
       M /pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py
       M /pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py
       M /pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py

    Revert r64686-r64687-r64688; will do it differently.

    ------------------------------------------------------------------------
    r64691 | arigo | 2009-04-26 16:35:53 +0200 (Sun, 26 Apr 2009) | 7 lines
    Changed paths:
       M /pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py
       M /pypy/branch/pyjitpl5/pypy/jit/backend/model.py
       M /pypy/branch/pyjitpl5/pypy/jit/backend/test/runner.py
       M /pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py
       M /pypy/branch/pyjitpl5/pypy/jit/metainterp/compile.py
       M /pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py
       M /pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py
       M /pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_basic.py
       M /pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py

    Replace _save_recursive_call() with an interface change.  The idea is
    that the backend should not patch the real boxes in-place, but only
    expose the result via an interface, get_latest_value_xxx().  The
    front-end will then copy the values into the boxes in a try:finally:,
    and restore their value afterwards.  It's expected to be much safer than
    the previous hack.

    ------------------------------------------------------------------------
    r64692 | arigo | 2009-04-26 16:40:52 +0200 (Sun, 26 Apr 2009) | 2 lines
    Changed paths:
       M /pypy/branch/pyjitpl5/pypy/jit/backend/minimal/runner.py
       M /pypy/branch/pyjitpl5/pypy/jit/backend/test/runner.py

    Fix the minimal backend.

    ------------------------------------------------------------------------
    r64693 | arigo | 2009-04-26 17:00:26 +0200 (Sun, 26 Apr 2009) | 2 lines
    Changed paths:
       M /pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py

    Translation fix.

    ------------------------------------------------------------------------
    r64694 | arigo | 2009-04-26 17:01:00 +0200 (Sun, 26 Apr 2009) | 2 lines
    Changed paths:
       M /pypy/branch/pyjitpl5/pypy/jit/backend/test/test_random.py
       M /pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py
       M /pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_regalloc2.py
       M /pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_runner.py

    Fix the x86 backend for r64691.

    ------------------------------------------------------------------------
    r64695 | arigo | 2009-04-26 17:18:34 +0200 (Sun, 26 Apr 2009) | 2 lines
    Changed paths:
       M /pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py

    Minor clean-up.

    ------------------------------------------------------------------------
    r64696 | arigo | 2009-04-26 18:18:15 +0200 (Sun, 26 Apr 2009) | 2 lines
    Changed paths:
       M /pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py

    Debugging info.

    ------------------------------------------------------------------------
    r64697 | arigo | 2009-04-26 18:22:38 +0200 (Sun, 26 Apr 2009) | 2 lines
    Changed paths:
       M /pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit_child.py
       M /pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit_demo.py

    Updates.

    ------------------------------------------------------------------------
    r64698 | fijal | 2009-04-26 18:55:06 +0200 (Sun, 26 Apr 2009) | 2 lines
    Changed paths:
       M /pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py

    make simple_optimize the default

    ------------------------------------------------------------------------
    r64699 | fijal | 2009-04-26 18:55:48 +0200 (Sun, 26 Apr 2009) | 2 lines
    Changed paths:
       M /pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_basic.py

    Disable this checks

    ------------------------------------------------------------------------
    r64700 | fijal | 2009-04-26 18:57:58 +0200 (Sun, 26 Apr 2009) | 2 lines
    Changed paths:
       M /pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py
       M /pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_basic.py

    Revert

    ------------------------------------------------------------------------
    r64701 | arigo | 2009-04-26 18:59:22 +0200 (Sun, 26 Apr 2009) | 2 lines
    Changed paths:
       M /pypy/branch/pyjitpl5/pypy/jit/metainterp/simple_optimize.py

    Add an assert.

    ------------------------------------------------------------------------
    r64702 | fijal | 2009-04-26 19:02:43 +0200 (Sun, 26 Apr 2009) | 2 lines
    Changed paths:
       M /pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_loop.py

    a passing test that was lying down in my wc

    ------------------------------------------------------------------------
    r64705 | arigo | 2009-04-26 20:18:38 +0200 (Sun, 26 Apr 2009) | 2 lines
    Changed paths:
       M /pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_loop.py

    Probably an accidental checkin.

    ------------------------------------------------------------------------
    r64707 | arigo | 2009-04-26 20:26:08 +0200 (Sun, 26 Apr 2009) | 7 lines
    Changed paths:
       M /pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py
       M /pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py
       M /pypy/branch/pyjitpl5/pypy/jit/backend/model.py
       M /pypy/branch/pyjitpl5/pypy/jit/backend/test/runner.py
       M /pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py
       M /pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_recursive.py
       M /pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py

    Use a custom interface to set the initial values to
    cpu.execute_operations(), which is set_future_value_xxx(); this is
    similar to the custom interface to fetch the values returned by a FAIL
    operation, which is get_latest_value_xxx().

    This allows us to remove the call to changevalue_xxx() in warmspot.py.

    ------------------------------------------------------------------------
    r64708 | arigo | 2009-04-26 22:04:21 +0200 (Sun, 26 Apr 2009) | 2 lines
    Changed paths:
       M /pypy/branch/pyjitpl5/pypy/jit/backend/minimal/runner.py
       M /pypy/branch/pyjitpl5/pypy/jit/backend/test/runner.py
       M /pypy/branch/pyjitpl5/pypy/jit/backend/test/test_random.py
       M /pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py
       M /pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py
       M /pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_regalloc2.py
       M /pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_runner.py
       M /pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py
       M /pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py

    Fix the x86 and the minimal backends.

    ------------------------------------------------------------------------
    r64709 | arigo | 2009-04-26 22:26:04 +0200 (Sun, 26 Apr 2009) | 2 lines
    Changed paths:
       M /pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py
       M /pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_regalloc.py
       M /pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_runner.py

    Clean-ups.

    ------------------------------------------------------------------------
    r64710 | fijal | 2009-04-27 02:40:02 +0200 (Mon, 27 Apr 2009) | 2 lines
    Changed paths:
       M /pypy/branch/pyjitpl5/pypy/jit/backend/minimal/runner.py

    *ekhem*

    ------------------------------------------------------------------------
    r64719 | arigo | 2009-04-27 11:33:48 +0200 (Mon, 27 Apr 2009) | 3 lines
    Changed paths:
       M /pypy/branch/pyjitpl5/pypy/jit/metainterp/compile.py
       M /pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py
       M /pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py
       M /pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py

    Constant string comparison is nicely folded too; forgot about that.
    Simplifies result_type.

    ------------------------------------------------------------------------



Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/backend/llgraph/llimpl.py
==============================================================================
--- pypy/branch/pyjitpl5-simplify/pypy/jit/backend/llgraph/llimpl.py	(original)
+++ pypy/branch/pyjitpl5-simplify/pypy/jit/backend/llgraph/llimpl.py	Mon Apr 27 12:00:08 2009
@@ -809,26 +809,30 @@
         frame = Frame(memocast)
     return _to_opaque(frame)
 
+_future_values = []
+
 def frame_clear(frame, loop):
     frame = _from_opaque(frame)
     loop = _from_opaque(loop)
     frame.loop = loop
     frame.env = {}
+    for i in range(len(loop.inputargs)):
+        frame.env[loop.inputargs[i]] = _future_values[i]
 
-def frame_add_int(frame, value):
-    frame = _from_opaque(frame)
-    i = len(frame.env)
-    frame.env[frame.loop.inputargs[i]] = value
-
-def frame_add_ptr(frame, value):
-    frame = _from_opaque(frame)
-    i = len(frame.env)
-    frame.env[frame.loop.inputargs[i]] = value
-
-def frame_add_obj(frame, value):
-    frame = _from_opaque(frame)
-    i = len(frame.env)
-    frame.env[frame.loop.inputargs[i]] = value
+def set_future_value_int(index, value):
+    del _future_values[index:]
+    assert len(_future_values) == index
+    _future_values.append(value)
+
+def set_future_value_ptr(index, value):
+    del _future_values[index:]
+    assert len(_future_values) == index
+    _future_values.append(value)
+
+def set_future_value_obj(index, value):
+    del _future_values[index:]
+    assert len(_future_values) == index
+    _future_values.append(value)
 
 def frame_execute(frame):
     frame = _from_opaque(frame)
@@ -1199,9 +1203,9 @@
 
 setannotation(new_frame, s_Frame)
 setannotation(frame_clear, annmodel.s_None)
-setannotation(frame_add_int, annmodel.s_None)
-setannotation(frame_add_ptr, annmodel.s_None)
-setannotation(frame_add_obj, annmodel.s_None)
+setannotation(set_future_value_int, annmodel.s_None)
+setannotation(set_future_value_ptr, annmodel.s_None)
+setannotation(set_future_value_obj, annmodel.s_None)
 setannotation(frame_execute, annmodel.SomeInteger())
 setannotation(frame_int_getvalue, annmodel.SomeInteger())
 setannotation(frame_ptr_getvalue, annmodel.SomePtr(llmemory.GCREF))

Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/backend/llgraph/runner.py
==============================================================================
--- pypy/branch/pyjitpl5-simplify/pypy/jit/backend/llgraph/runner.py	(original)
+++ pypy/branch/pyjitpl5-simplify/pypy/jit/backend/llgraph/runner.py	Mon Apr 27 12:00:08 2009
@@ -82,6 +82,7 @@
         llimpl._llinterp = LLInterpreter(self.rtyper)
         if translate_support_code:
             self.mixlevelann = annmixlevel
+        self._future_values = []
 
     def compile_operations(self, loop):
         """In a real assembler backend, this should assemble the given
@@ -152,54 +153,44 @@
             llimpl.compile_add_fail(c, len(self.fail_ops))
             self.fail_ops.append(op)
 
-    def execute_operations(self, loop, valueboxes):
+    def execute_operations(self, loop):
         """Calls the assembler generated for the given loop.
         Returns the ResOperation that failed, of type rop.FAIL.
         """
         frame = llimpl.new_frame(self.memo_cast, self.is_oo)
         # setup the frame
         llimpl.frame_clear(frame, loop._compiled_version)
-        for box in valueboxes:
-            if isinstance(box, history.BoxInt):
-                llimpl.frame_add_int(frame, box.value)
-            elif isinstance(box, history.BoxPtr):
-                llimpl.frame_add_ptr(frame, box.value)
-            elif self.is_oo and isinstance(box, history.BoxObj):
-                llimpl.frame_add_obj(frame, box.value)
-            elif isinstance(box, history.ConstInt):
-                llimpl.frame_add_int(frame, box.value)
-            elif isinstance(box, history.ConstPtr):
-                llimpl.frame_add_ptr(frame, box.value)
-            elif self.is_oo and isinstance(box, history.ConstObj):
-                llimpl.frame_add_obj(frame, box.value)
-            else:
-                raise Exception("bad box in valueboxes: %r" % (box,))
         # run the loop
         fail_index = llimpl.frame_execute(frame)
-        # we hit a FAIL operation.  Fish for the values
-        # (in a real backend, this should be done by the FAIL operation
-        # itself, not here)
-        op = self.fail_ops[fail_index]
-        for i in range(len(op.args)):
-            box = op.args[i]
-            if isinstance(box, history.BoxInt):
-                value = llimpl.frame_int_getvalue(frame, i)
-                box.changevalue_int(value)
-            elif isinstance(box, history.BoxPtr):
-                value = llimpl.frame_ptr_getvalue(frame, i)
-                box.changevalue_ptr(value)
-            elif self.is_oo and isinstance(box, history.BoxObj):
-                value = llimpl.frame_ptr_getvalue(frame, i)
-                box.changevalue_obj(value)
-            elif isinstance(box, history.ConstInt):
-                pass
-            elif isinstance(box, history.ConstPtr):
-                pass
-            elif self.is_oo and isinstance(box, history.ConstObj):
-                pass
-            else:
-                raise Exception("bad box in 'fail': %r" % (box,))
-        return op
+        # we hit a FAIL operation.
+        self.latest_frame = frame
+        return self.fail_ops[fail_index]
+
+    def set_future_value_int(self, index, intvalue):
+        llimpl.set_future_value_int(index, intvalue)
+
+    def set_future_value_ptr(self, index, ptrvalue):
+        llimpl.set_future_value_ptr(index, ptrvalue)
+
+    def set_future_value_obj(self, index, objvalue):
+        llimpl.set_future_value_obj(index, objvalue)
+
+    def get_latest_value_int(self, index):
+        return llimpl.frame_int_getvalue(self.latest_frame, index)
+
+    def get_latest_value_ptr(self, index):
+        return llimpl.frame_ptr_getvalue(self.latest_frame, index)
+
+    def get_latest_value_obj(self, index):
+        return llimpl.frame_ptr_getvalue(self.latest_frame, index)
+
+    # ----------
+
+    def get_exception(self):
+        return self.cast_adr_to_int(llimpl.get_exception())
+
+    def get_exc_value(self):
+        return llimpl.get_exc_value()
 
     def clear_exception(self):
         llimpl.clear_exception()

Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/backend/minimal/runner.py
==============================================================================
--- pypy/branch/pyjitpl5-simplify/pypy/jit/backend/minimal/runner.py	(original)
+++ pypy/branch/pyjitpl5-simplify/pypy/jit/backend/minimal/runner.py	Mon Apr 27 12:00:08 2009
@@ -6,6 +6,7 @@
 from pypy.jit.metainterp import executor
 from pypy.jit.metainterp.resoperation import rop, opname
 
+DEBUG = False
 
 class CPU(object):
     is_oo = False    # XXX for now
@@ -19,6 +20,7 @@
             self.is_oo = False
         self.stats = stats
         self.translate_support_code = translate_support_code
+        self._future_values = []
         self.setup()
 
     def setup(self):
@@ -38,11 +40,12 @@
     def compile_operations(self, loop):
         pass
 
-    def execute_operations(self, loop, valueboxes):
-        #debug_print("execute_operations: starting", loop)
-        #for box in valueboxes:
-        #    debug_print("\t", box, "\t", box.get_())
-        valueboxes = [box.clonebox() for box in valueboxes]
+    def execute_operations(self, loop):
+        valueboxes = self._future_values
+        if DEBUG:
+            print "execute_operations: starting", loop
+            for box in valueboxes:
+                print "\t", box, "\t", box.get_()
         self.clear_exception()
         self._guard_failed = False
         while True:
@@ -60,20 +63,24 @@
                 op = operations[i]
                 i += 1
                 argboxes = []
-                #lst = [' %s ' % opname[op.opnum]]
+                if DEBUG:
+                    lst = [' %s ' % opname[op.opnum]]
                 for box in op.args:
                     if isinstance(box, Box):
                         box = env[box]
                     argboxes.append(box)
-                    #lst.append(str(box.get_()))
-                #debug_print(' '.join(lst))
+                    if DEBUG:
+                        lst.append(str(box.get_()))
+                if DEBUG:
+                    print ' '.join(lst)
                 if op.is_final():
                     break
                 if op.is_guard():
                     try:
                         resbox = self.execute_guard(op.opnum, argboxes)
                     except GuardFailed:
-                        #debug_print("\t*guard failed*")
+                        if DEBUG:
+                            print "\t*guard failed (%s)*" % op.getopname()
                         self._guard_failed = True
                         operations = op.suboperations
                         i = 0
@@ -85,7 +92,8 @@
                 if op.result is not None:
                     ll_assert(resbox is not None,
                               "execute_operations: unexpectedly got None")
-                    #debug_print('\t-->', resbox.get_())
+                    if DEBUG:
+                        print '\t-->', resbox.get_()
                     env[op.result] = resbox
                 else:
                     ll_assert(resbox is None,
@@ -98,19 +106,32 @@
             if op.opnum == rop.FAIL:
                 break
             ll_assert(False, "execute_operations: bad opnum")
-        #
-        #debug_print("execute_operations: leaving", loop)
-        for i in range(len(op.args)):
-            box = op.args[i]
-            if isinstance(box, BoxInt):
-                value = env[box].getint()
-                box.changevalue_int(value)
-            elif isinstance(box, BoxPtr):
-                value = env[box].getptr_base()
-                box.changevalue_ptr(value)
-            #debug_print("\t", box, "\t", box.get_())
+
+        if DEBUG:
+            print "execute_operations: leaving", loop
+            for box in op.args:
+                print "\t", env[box], "\t", env[box].get_()
+        self.latest_fail = op, env
         return op
 
+    def set_future_value_int(self, index, intvalue):
+        del self._future_values[index:]
+        assert len(self._future_values) == index
+        self._future_values.append(BoxInt(intvalue))
+
+    def set_future_value_ptr(self, index, ptrvalue):
+        del self._future_values[index:]
+        assert len(self._future_values) == index
+        self._future_values.append(BoxPtr(ptrvalue))
+
+    def get_latest_value_int(self, index):
+        op, env = self.latest_fail
+        return env[op.args[index]].getint()
+
+    def get_latest_value_ptr(self, index):
+        op, env = self.latest_fail
+        return env[op.args[index]].getptr_base()
+
     def execute_guard(self, opnum, argboxes):
         if opnum == rop.GUARD_TRUE:
             value = argboxes[0].getint()
@@ -363,12 +384,14 @@
         except Exception, e:
             from pypy.rpython.annlowlevel import cast_instance_to_base_ptr
             self.current_exc_inst = cast_instance_to_base_ptr(e)
-            #debug_print('\tcall raised!', self.current_exc_inst)
+            if DEBUG:
+                print '\tcall raised!', self.current_exc_inst
             box = calldescr.errbox
             if box:
                 box = box.clonebox()
-        #else:
-            #debug_print('\tcall did not raise')
+        else:
+            if DEBUG:
+                print '\tcall did not raise'
         return box
 
     # ----------

Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/backend/model.py
==============================================================================
--- pypy/branch/pyjitpl5-simplify/pypy/jit/backend/model.py	(original)
+++ pypy/branch/pyjitpl5-simplify/pypy/jit/backend/model.py	Mon Apr 27 12:00:08 2009
@@ -4,12 +4,40 @@
         """Assemble the given list of operations."""
         raise NotImplementedError
 
-    def execute_operations(self, loop, valueboxes):
+    def execute_operations(self, loop):
         """Calls the assembler generated for the given loop.
         Returns the ResOperation that failed, of type rop.FAIL.
+        Use set_future_value_xxx() before, and get_latest_value_xxx() after.
         """
         raise NotImplementedError
-    
+
+    def set_future_value_int(self, index, intvalue):
+        """Set the value for the index'th argument for the loop to run."""
+        raise NotImplementedError
+
+    def set_future_value_ptr(self, index, ptrvalue):
+        """Set the value for the index'th argument for the loop to run."""
+        raise NotImplementedError
+
+    def set_future_value_obj(self, index, objvalue):
+        """Set the value for the index'th argument for the loop to run."""
+        raise NotImplementedError
+
+    def get_latest_value_int(self, index):
+        """Returns the value for the index'th argument to the
+        lastest rop.FAIL.  Returns an int."""
+        raise NotImplementedError
+
+    def get_latest_value_ptr(self, index):
+        """Returns the value for the index'th argument to the
+        lastest rop.FAIL.  Returns a ptr."""
+        raise NotImplementedError
+
+    def get_latest_value_obj(self, index):
+        """Returns the value for the index'th argument to the
+        lastest rop.FAIL.  Returns an obj."""
+        raise NotImplementedError
+
     def get_exception(self):
         raise NotImplementedError
 

Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/backend/test/runner.py
==============================================================================
--- pypy/branch/pyjitpl5-simplify/pypy/jit/backend/test/runner.py	(original)
+++ pypy/branch/pyjitpl5-simplify/pypy/jit/backend/test/runner.py	Mon Apr 27 12:00:08 2009
@@ -1,7 +1,7 @@
 
 import sys
 from pypy.jit.metainterp.history import (BoxInt, Box, BoxPtr, TreeLoop,
-                                         ConstInt, ConstPtr)
+                                         ConstInt, ConstPtr, BoxObj)
 from pypy.jit.metainterp.resoperation import ResOperation, rop
 from pypy.rpython.lltypesystem import lltype, llmemory, rstr, rffi, rclass
 from pypy.jit.metainterp.executor import execute
@@ -23,14 +23,26 @@
     def execute_operation(self, opname, valueboxes, result_type, descr=None):
         loop = self.get_compiled_single_operation(opname, result_type,
                                                   valueboxes, descr)
-        boxes = [box for box in valueboxes if isinstance(box, Box)]
-        res = self.cpu.execute_operations(loop, boxes)
+        j = 0
+        for box in valueboxes:
+            if isinstance(box, BoxInt):
+                self.cpu.set_future_value_int(j, box.getint())
+                j += 1
+            elif isinstance(box, BoxPtr):
+                self.cpu.set_future_value_ptr(j, box.getptr_base())
+                j += 1
+            elif isinstance(box, BoxObj):
+                self.cpu.set_future_value_obj(j, box.getobj())
+                j += 1
+        res = self.cpu.execute_operations(loop)
         if res is loop.operations[-1]:
             self.guard_failed = False
         else:
             self.guard_failed = True
-        if result_type != 'void':
-            return res.args[0]
+        if result_type == 'int':
+            return BoxInt(self.cpu.get_latest_value_int(0))
+        elif result_type == 'ptr':
+            return BoxPtr(self.cpu.get_latest_value_ptr(0))
 
     def get_compiled_single_operation(self, opnum, result_type, valueboxes,
                                       descr):
@@ -155,7 +167,7 @@
 
     def test_ovf_operations(self):
         minint = -sys.maxint-1
-        boom = 666
+        boom = 'boom'
         for opnum, testcases in [
             (rop.INT_ADD_OVF, [(10, -2, 8),
                                (-1, minint, boom),
@@ -200,15 +212,21 @@
                 ]
             if opnum in (rop.INT_NEG_OVF, rop.INT_ABS_OVF):
                 del ops[0].args[1]
-            ops[1].suboperations = [ResOperation(rop.FAIL, [ConstInt(boom)],
+            ops[1].suboperations = [ResOperation(rop.FAIL, [],
                                                  None)]
             loop = TreeLoop('name')
             loop.operations = ops
             loop.inputargs = [v1, v2]
             self.cpu.compile_operations(loop)
             for x, y, z in testcases:
-                op = self.cpu.execute_operations(loop, [BoxInt(x), BoxInt(y)])
-                assert op.args[0].value == z
+                self.cpu.set_future_value_int(0, x)
+                self.cpu.set_future_value_int(1, y)
+                op = self.cpu.execute_operations(loop)
+                if z == boom:
+                    assert op is ops[1].suboperations[0]
+                else:
+                    assert op is ops[-1]
+                    assert self.cpu.get_latest_value_int(0) == z
             # ----------
             # the same thing but with the exception path reversed
 ##            v1 = BoxInt(testcases[0][0])

Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/backend/test/test_random.py
==============================================================================
--- pypy/branch/pyjitpl5-simplify/pypy/jit/backend/test/test_random.py	(original)
+++ pypy/branch/pyjitpl5-simplify/pypy/jit/backend/test/test_random.py	Mon Apr 27 12:00:08 2009
@@ -56,15 +56,18 @@
         print >>s, '            ]'
         print >>s, '    cpu = CPU(None, None)'
         print >>s, '    cpu.compile_operations(loop)'
-        print >>s, '    op = cpu.execute_operations(loop, [%s])' % (
-            ', '.join(['BoxInt(%d)' % v.value for v in self.loop.inputargs]))
+        for i, v in enumerate(self.loop.inputargs):
+            print >>s, '    cpu.set_future_value_int(%d, %d)' % (i, v.value)
+        print >>s, '    op = cpu.execute_operations(loop)'
         if self.should_fail_by is None:
-            for v in self.loop.operations[-1].args:
-                print >>s, '    assert %s.value == %d' % (names[v], v.value)
+            for i, v in enumerate(self.loop.operations[-1].args):
+                print >>s, '    assert cpu.get_latest_value_int(%d) == %d' % (
+                    i, v.value)
         else:
             print >>s, '    assert op is loop.operations[%d].suboperations[0]' % self.should_fail_by_num
-            for v in self.should_fail_by.args:
-                print >>s, '    assert %s.value == %d' % (names[v], v.value)
+            for i, v in enumerate(self.should_fail_by.args):
+                print >>s, '    assert cpu.get_latest_value_int(%d) == %d' % (
+                    i, v.value)
         self.names = names
         if demo_conftest.option.output:
             s.close()
@@ -111,7 +114,7 @@
             v_second = v
         self.put(builder, [v_first, v_second])
 
-class GuardBinaryOperation(AbstractOperation):
+class GuardOperation(AbstractOperation):
 
     def produce_into(self, builder, r):
         v = builder.get_bool_var(r)
@@ -158,8 +161,9 @@
 OPERATIONS.append(BinaryOperation(rop.INT_RSHIFT, LONG_BIT-1))
 OPERATIONS.append(BinaryOperation(rop.INT_LSHIFT, LONG_BIT-1))
 OPERATIONS.append(BinaryOperation(rop.UINT_RSHIFT, LONG_BIT-1))
-OPERATIONS.append(GuardBinaryOperation(rop.GUARD_TRUE))
-OPERATIONS.append(GuardBinaryOperation(rop.GUARD_FALSE))
+
+OPERATIONS.append(GuardOperation(rop.GUARD_TRUE))
+OPERATIONS.append(GuardOperation(rop.GUARD_FALSE))
 
 for _op in [rop.INT_NEG,
             rop.INT_INVERT,

Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/backend/x86/assembler.py
==============================================================================
--- pypy/branch/pyjitpl5-simplify/pypy/jit/backend/x86/assembler.py	(original)
+++ pypy/branch/pyjitpl5-simplify/pypy/jit/backend/x86/assembler.py	Mon Apr 27 12:00:08 2009
@@ -264,20 +264,17 @@
         self.make_sure_mc_exists()
         addr = self.mc.tell()
         self.mc.SUB(esp, imm(framesize * WORD))
-        self.mc.MOV(eax, arg_pos(0, framesize * WORD))
         for i in range(len(arglocs)):
             loc = arglocs[i]
             if not isinstance(loc, REG):
-                self.mc.MOV(ecx, mem(eax, i * WORD))
+                self.mc.MOV(ecx,
+                            addr_add(imm(self.fail_box_addr), imm(i*WORD)))
                 self.mc.MOV(loc, ecx)
         for i in range(len(arglocs)):
             loc = arglocs[i]
-            if isinstance(loc, REG) and loc is not eax:
-                self.mc.MOV(loc, mem(eax, i * WORD))
-        for i in range(len(arglocs)):
-            loc = arglocs[i]
-            if loc is eax:
-                self.mc.MOV(loc, mem(eax, i * WORD))
+            if isinstance(loc, REG):
+                self.mc.MOV(loc,
+                            addr_add(imm(self.fail_box_addr), imm(i*WORD)))
         self.mc.JMP(rel32(jumpaddr))
         self.mc.done()
         return addr
@@ -867,7 +864,7 @@
                 self.mc.PUSH(stack_pos(loc.position + extra_on_stack))
             extra_on_stack += 1
         if isinstance(op.args[0], Const):
-            x = rel32(self.cpu.get_box_value_as_int(op.args[0]))
+            x = rel32(op.args[0].getint())
         else:
             x = arglocs[0]
             if isinstance(x, MODRM):

Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/backend/x86/runner.py
==============================================================================
--- pypy/branch/pyjitpl5-simplify/pypy/jit/backend/x86/runner.py	(original)
+++ pypy/branch/pyjitpl5-simplify/pypy/jit/backend/x86/runner.py	Mon Apr 27 12:00:08 2009
@@ -11,7 +11,7 @@
 from pypy.jit.metainterp import history, codewriter
 from pypy.jit.metainterp.history import (ResOperation, Box, Const,
      ConstInt, ConstPtr, BoxInt, BoxPtr, ConstAddr, AbstractDescr)
-from pypy.jit.backend.x86.assembler import Assembler386, WORD
+from pypy.jit.backend.x86.assembler import Assembler386, WORD, MAX_FAIL_BOXES
 from pypy.jit.backend.x86 import symbolic
 from pypy.jit.metainterp.resoperation import rop, opname
 from pypy.jit.backend.x86.support import gc_malloc_fnaddr
@@ -69,8 +69,7 @@
     debug = True
     is_oo = False
 
-    BOOTSTRAP_TP = lltype.FuncType([lltype.Ptr(rffi.CArray(lltype.Signed))],
-                                   lltype.Signed)
+    BOOTSTRAP_TP = lltype.FuncType([], lltype.Signed)
 
     def __init__(self, rtyper, stats, translate_support_code=False,
                  mixlevelann=None):
@@ -92,7 +91,6 @@
             self.current_interpreter._store_exception = _store_exception
         TP = lltype.GcArray(llmemory.GCREF)
         self.keepalives = []
-        self.keepalives_index = 0
         self._bootstrap_cache = {}
         self._guard_list = []
         self._compiled_ops = {}
@@ -179,8 +177,8 @@
 #                 self.caught_exception = e
 #             return self.assembler.generic_return_addr
 
-    def set_meta_interp(self, metainterp):
-        self.metainterp = metainterp
+#    def set_meta_interp(self, metainterp):
+#        self.metainterp = metainterp
 
     def get_exception(self):
         self.assembler.make_sure_mc_exists()
@@ -231,28 +229,6 @@
             self._bootstrap_cache[key] = func
             return func
 
-    def get_box_value_as_int(self, box):
-        if isinstance(box, BoxInt):
-            return box.value
-        elif isinstance(box, ConstInt):
-            return box.value
-        elif isinstance(box, BoxPtr):
-            self.keepalives.append(box.value)
-            return self.cast_gcref_to_int(box.value)
-        elif isinstance(box, ConstPtr): 
-            self.keepalives.append(box.value)
-            return self.cast_gcref_to_int(box.value)
-        elif isinstance(box, ConstAddr):
-            return self.cast_adr_to_int(box.value)
-        else:
-            raise ValueError('get_box_value_as_int, wrong arg')
-
-    def set_value_of_box(self, box, index, fail_boxes):
-        if isinstance(box, BoxInt):
-            box.value = fail_boxes[index]
-        elif isinstance(box, BoxPtr):
-            box.value = self.cast_int_to_gcref(fail_boxes[index])
-
     def _new_box(self, ptr):
         if ptr:
             return BoxPtr(lltype.nullptr(llmemory.GCREF.TO))
@@ -260,21 +236,16 @@
     
     def _get_loop_for_call(self, argnum, calldescr, ptr):
         try:
-            loop = self.generated_mps[calldescr]
-            box = self._new_box(ptr)
-            loop.operations[0].result = box
-            loop.operations[-1].args[0] = box
-            loop.operations[1].suboperations[0].args[0] = box
-            return loop
+            return self.generated_mps[calldescr]
         except KeyError:
             pass
-        args = [BoxInt(0) for i in range(argnum + 1)]
+        args = [BoxInt() for i in range(argnum + 1)]
         result = self._new_box(ptr)
         operations = [
             ResOperation(rop.CALL, args, result, calldescr),
             ResOperation(rop.GUARD_NO_EXCEPTION, [], None),
             ResOperation(rop.FAIL, [result], None)]
-        operations[1].suboperations = [ResOperation(rop.FAIL, [result], None)]
+        operations[1].suboperations = [ResOperation(rop.FAIL, [], None)]
         loop = history.TreeLoop('call')
         loop.inputargs = args
         loop.operations = operations
@@ -282,36 +253,38 @@
         self.generated_mps[calldescr] = loop
         return loop
 
-    def execute_operations(self, loop, valueboxes):
+    def execute_operations(self, loop):
         func = self.get_bootstrap_code(loop)
-        # turn all the values into integers
-        TP = rffi.CArray(lltype.Signed)
-        oldindex = self.keepalives_index
-        values_as_int = lltype.malloc(TP, len(valueboxes), flavor='raw')
-        for i in range(len(valueboxes)):
-            box = valueboxes[i]
-            v = self.get_box_value_as_int(box)
-            values_as_int[i] = v
         # debug info
         #if self.debug and not we_are_translated():
         #    values_repr = ", ".join([str(values_as_int[i]) for i in
         #                             range(len(valueboxes))])
         #    llop.debug_print(lltype.Void, 'exec:', name, values_repr)
-        self.assembler.log_call(valueboxes)
-        self.keepalives_index = len(self.keepalives)
-        guard_index = self.execute_call(loop, func, values_as_int)
+        #self.assembler.log_call(valueboxes) --- XXX
+        guard_index = self.execute_call(loop, func)
         self._guard_index = guard_index # for tests
-        keepalive_until_here(valueboxes)
-        self.keepalives_index = oldindex
-        del self.keepalives[oldindex:]
         op = self._guard_list[guard_index]
         #print "Leaving at: %d" % self.assembler.fail_boxes[len(op.args)]
-        for i in range(len(op.args)):
-            box = op.args[i]
-            self.set_value_of_box(box, i, self.assembler.fail_boxes)
         return op
 
-    def execute_call(self, loop, func, values_as_int):
+    def set_future_value_int(self, index, intvalue):
+        assert index < MAX_FAIL_BOXES, "overflow!"
+        self.assembler.fail_boxes[index] = intvalue
+
+    def set_future_value_ptr(self, index, ptrvalue):
+        assert index < MAX_FAIL_BOXES, "overflow!"
+        self.keepalives.append(ptrvalue)
+        intvalue = self.cast_gcref_to_int(ptrvalue)
+        self.assembler.fail_boxes[index] = intvalue
+
+    def get_latest_value_int(self, index):
+        return self.assembler.fail_boxes[index]
+
+    def get_latest_value_ptr(self, index):
+        intvalue = self.assembler.fail_boxes[index]
+        return self.cast_int_to_gcref(intvalue)
+
+    def execute_call(self, loop, func):
         # help flow objspace
         prev_interpreter = None
         if not self.translate_support_code:
@@ -321,12 +294,12 @@
         try:
             self.caught_exception = None
             #print "Entering: %d" % rffi.cast(lltype.Signed, func)
-            res = func(values_as_int)
+            res = func()
+            del self.keepalives[:]
             self.reraise_caught_exception()
         finally:
             if not self.translate_support_code:
                 LLInterpreter.current_interpreter = prev_interpreter
-            lltype.free(values_as_int, flavor='raw')
         return res
 
     def reraise_caught_exception(self):
@@ -346,21 +319,21 @@
         self._guard_list.append(guard_op)
         return index
 
-    def convert_box_to_int(self, valuebox):
-        if isinstance(valuebox, ConstInt):
-            return valuebox.value
-        elif isinstance(valuebox, BoxInt):
-            return valuebox.value
-        elif isinstance(valuebox, BoxPtr):
-            x = self.cast_gcref_to_int(valuebox.value)
-            self.keepalives.append(valuebox.value)
-            return x
-        elif isinstance(valuebox, ConstPtr):
-            x = self.cast_gcref_to_int(valuebox.value)
-            self.keepalives.append(valuebox.value)
-            return x
-        else:
-            raise ValueError(valuebox.type)
+#    def convert_box_to_int(self, valuebox):
+#        if isinstance(valuebox, ConstInt):
+#            return valuebox.value
+#        elif isinstance(valuebox, BoxInt):
+#            return valuebox.value
+#        elif isinstance(valuebox, BoxPtr):
+#            x = self.cast_gcref_to_int(valuebox.value)
+#            self.keepalives.append(valuebox.value)
+#            return x
+#        elif isinstance(valuebox, ConstPtr):
+#            x = self.cast_gcref_to_int(valuebox.value)
+#            self.keepalives.append(valuebox.value)
+#            return x
+#        else:
+#            raise ValueError(valuebox.type)
 
 #     def getvaluebox(self, frameadr, guard_op, argindex):
 #         # XXX that's plain stupid, do we care about the return value???
@@ -565,10 +538,16 @@
         num_args, size, ptr = self.unpack_calldescr(calldescr)
         assert isinstance(calldescr, ConstDescr3)
         loop = self._get_loop_for_call(num_args, calldescr, ptr)
-        op = self.execute_operations(loop, args)
+        history.set_future_values(self, args)
+        self.execute_operations(loop)
+        # Note: if an exception is set, the rest of the code does a bit of
+        # nonsense but nothing wrong (the return value should be ignored)
         if size == 0:
             return None
-        return op.args[0]
+        elif ptr:
+            return BoxPtr(self.get_latest_value_ptr(0))
+        else:
+            return BoxInt(self.get_latest_value_int(0))
 
     def do_cast_ptr_to_int(self, args, descr=None):
         return BoxInt(self.cast_gcref_to_int(args[0].getptr_base()))

Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/backend/x86/test/test_regalloc.py
==============================================================================
--- pypy/branch/pyjitpl5-simplify/pypy/jit/backend/x86/test/test_regalloc.py	(original)
+++ pypy/branch/pyjitpl5-simplify/pypy/jit/backend/x86/test/test_regalloc.py	Mon Apr 27 12:00:08 2009
@@ -3,6 +3,7 @@
 """
 
 import py
+py.test.skip("Think about a nice way of doing stuff below")
 from pypy.jit.backend.x86.test.test_runner import FakeMetaInterp, FakeStats
 from pypy.jit.metainterp.history import ResOperation, BoxInt, ConstInt,\
      BoxPtr, ConstPtr
@@ -10,7 +11,6 @@
 from pypy.rpython.lltypesystem import lltype
 from pypy.jit.metainterp.resoperation import rop
 from pypy.rpython.lltypesystem import lltype, llmemory
-py.test.skip("Think about a nice way of doing stuff below")
 
 def test_simple_loop():
     meta_interp = FakeMetaInterp()

Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/backend/x86/test/test_runner.py
==============================================================================
--- pypy/branch/pyjitpl5-simplify/pypy/jit/backend/x86/test/test_runner.py	(original)
+++ pypy/branch/pyjitpl5-simplify/pypy/jit/backend/x86/test/test_runner.py	Mon Apr 27 12:00:08 2009
@@ -15,9 +15,6 @@
 class FakeStats(object):
     pass
 
-class FakeMetaInterp(object):
-    pass
-
 # ____________________________________________________________
 
 class TestX86(BaseBackendTest):
@@ -27,7 +24,6 @@
     
     def setup_class(cls):
         cls.cpu = CPU(rtyper=None, stats=FakeStats())
-        cls.cpu.set_meta_interp(FakeMetaInterp())
 
     def test_int_binary_ops(self):
         for op, args, res in [
@@ -69,7 +65,6 @@
 
     def test_execute_operations_in_env(self):
         cpu = self.cpu
-        cpu.set_meta_interp(FakeMetaInterp())
         x = BoxInt(123)
         y = BoxInt(456)
         z = BoxInt(579)
@@ -88,8 +83,11 @@
         operations[-1].jump_target = loop
         operations[-2].suboperations = [ResOperation(rop.FAIL, [t, z], None)]
         cpu.compile_operations(loop)
-        res = self.cpu.execute_operations(loop, [BoxInt(0), BoxInt(10)])
-        assert [arg.value for arg in res.args] == [0, 55]
+        self.cpu.set_future_value_int(0, 0)
+        self.cpu.set_future_value_int(1, 10)
+        res = self.cpu.execute_operations(loop)
+        assert self.cpu.get_latest_value_int(0) == 0
+        assert self.cpu.get_latest_value_int(1) == 55
 
     def test_misc_int_ops(self):
         for op, args, res in [
@@ -463,11 +461,13 @@
                     loop.operations = ops
                     loop.inputargs = [b]
                     self.cpu.compile_operations(loop)
-                    r = self.cpu.execute_operations(loop, [b])
+                    self.cpu.set_future_value_ptr(0, b.value)
+                    r = self.cpu.execute_operations(loop)
+                    result = self.cpu.get_latest_value_int(0)
                     if guard == rop.GUARD_FALSE:
-                        assert r.args[0].value == execute(self.cpu, op, [b]).value
+                        assert result == execute(self.cpu, op, [b]).value
                     else:
-                        assert r.args[0].value != execute(self.cpu, op, [b]).value
+                        assert result != execute(self.cpu, op, [b]).value
                     
 
     def test_stuff_followed_by_guard(self):
@@ -503,11 +503,14 @@
                     loop.operations = ops
                     loop.inputargs = [i for i in (a, b) if isinstance(i, Box)]
                     self.cpu.compile_operations(loop)
-                    r = self.cpu.execute_operations(loop, loop.inputargs)
+                    for i, box in enumerate(loop.inputargs):
+                        self.cpu.set_future_value_int(i, box.value)
+                    r = self.cpu.execute_operations(loop)
+                    result = self.cpu.get_latest_value_int(0)
                     if guard == rop.GUARD_FALSE:
-                        assert r.args[0].value == execute(self.cpu, op, (a, b)).value
+                        assert result == execute(self.cpu, op, (a, b)).value
                     else:
-                        assert r.args[0].value != execute(self.cpu, op, (a, b)).value
+                        assert result != execute(self.cpu, op, (a, b)).value
 
     def test_overflow_mc(self):
         from pypy.jit.backend.x86.assembler import MachineCodeBlockWrapper
@@ -530,8 +533,9 @@
             loop.operations = ops
             loop.inputargs = [base_v]
             self.cpu.compile_operations(loop)
-            op = self.cpu.execute_operations(loop, [base_v])
-            assert op.args[0].value == 1024
+            self.cpu.set_future_value_int(0, base_v.value)
+            op = self.cpu.execute_operations(loop)
+            assert self.cpu.get_latest_value_int(0) == 1024
         finally:
             MachineCodeBlockWrapper.MC_SIZE = orig_size
             self.cpu.assembler.mc = old_mc

Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/codewriter.py
==============================================================================
--- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/codewriter.py	(original)
+++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/codewriter.py	Mon Apr 27 12:00:08 2009
@@ -44,31 +44,32 @@
 
 class IndirectCallset(history.AbstractValue):
     def __init__(self, codewriter, graphs):
-        keys = []
-        values = []
+        self.keys = []
+        self.values = []
         for graph in graphs:
             fnptr = codewriter.rtyper.getcallable(graph)
             fnaddress = codewriter.ts.cast_fnptr_to_root(fnptr)
-            keys.append(fnaddress)
-            values.append(codewriter.get_jitcode(graph))
+            self.keys.append(fnaddress)
+            self.values.append(codewriter.get_jitcode(graph))
+        self.dict = None
 
-        def bytecode_for_address(fnaddress):
-            if we_are_translated():
-                if self.dict is None:
-                    # Build the dictionary at run-time.  This is needed
-                    # because the keys are function addresses, so they
-                    # can change from run to run.
-                    self.dict = {}
-                    for i in range(len(keys)):
-                        self.dict[keys[i]] = values[i]
-                return self.dict[fnaddress]
-            else:
+    def bytecode_for_address(self, fnaddress):
+        if we_are_translated():
+            if self.dict is None:
+                # Build the dictionary at run-time.  This is needed
+                # because the keys are function addresses, so they
+                # can change from run to run.
+                self.dict = {}
+                keys = self.keys
+                values = self.values
                 for i in range(len(keys)):
-                    if fnaddress == keys[i]:
-                        return values[i]
-                raise KeyError(fnaddress)
-        self.bytecode_for_address = bytecode_for_address
-        self.dict = None
+                    self.dict[keys[i]] = values[i]
+            return self.dict[fnaddress]
+        else:
+            for i in range(len(self.keys)):
+                if fnaddress == self.keys[i]:
+                    return self.values[i]
+            raise KeyError(fnaddress)
 
 class SwitchDict(history.AbstractValue):
     "Get a 'dict' attribute mapping integer values to bytecode positions."
@@ -256,6 +257,7 @@
         self.codewriter = codewriter
         self.cpu = codewriter.metainterp_sd.cpu
         self.portal = portal
+        self.block_start_order = {}
         graph, oosend_methdescr = graph_key
         self.bytecode = self.codewriter.get_jitcode(graph,
                                              oosend_methdescr=oosend_methdescr)
@@ -326,6 +328,7 @@
                     self.emit("return")
             elif len(block.inputargs) == 2:
                 # exception block, raising an exception from a function
+                assert self.force_block_args_order(block) == block.inputargs
                 self.emit("raise")
             else:
                 raise Exception("?")
@@ -338,7 +341,7 @@
         self.seen_blocks[block] = True
         self.free_vars = 0
         self.var_positions = {}
-        for arg in block.inputargs:
+        for arg in self.force_block_args_order(block):
             self.register_var(arg, verbose=False)
         self.emit(label(block))
         #self.make_prologue(block)
@@ -366,7 +369,7 @@
         if len(block.exits) == 1 or block.exitswitch == c_last_exception:
             link = block.exits[0]
             assert link.exitcase is None
-            self.emit(*self.insert_renaming(link.args))
+            self.emit(*self.insert_renaming(link))
             self.make_bytecode_block(link.target)
         elif (len(block.exits) == 2
               and block.exitswitch.concretetype == lltype.Bool):
@@ -377,8 +380,8 @@
                       tlabel(linkfalse),
                       self.var_position(block.exitswitch))
             self.minimize_variables(argument_only=True, exitswitch=False)
-            truerenaming = self.insert_renaming(linktrue.args)
-            falserenaming = self.insert_renaming(linkfalse.args)
+            truerenaming = self.insert_renaming(linktrue)
+            falserenaming = self.insert_renaming(linkfalse)
             # true path:
             self.emit(*truerenaming)
             self.make_bytecode_block(linktrue.target)
@@ -406,11 +409,11 @@
                 self.emit_list([self.const_position(link.llexitcase)
                                 for link in switches])
                 self.emit_list([tlabel(link) for link in switches])
-            renamings = [self.insert_renaming(link.args)
+            renamings = [self.insert_renaming(link)
                          for link in switches]
             if block.exits[-1].exitcase == 'default':
                 link = block.exits[-1]
-                self.emit(*self.insert_renaming(link.args))
+                self.emit(*self.insert_renaming(link))
                 self.make_bytecode_block(link.target)
             for renaming, link in zip(renamings, switches):
                 self.emit(label(link))
@@ -423,7 +426,8 @@
         handler = object()
         renamings = []
         for i, link in enumerate(exception_exits):
-            args_without_last_exc = [v for v in link.args
+            args = self.force_link_args_order(link)
+            args_without_last_exc = [v for v in args
                                        if (v is not link.last_exception and
                                            v is not link.last_exc_value)]
             if (link.exitcase is Exception and
@@ -432,8 +436,8 @@
                 # stop at the catch-and-reraise-every-exception branch, if any
                 exception_exits = exception_exits[:i]
                 break
-            renamings.append(self.insert_renaming(args_without_last_exc,
-                                                  force=True))
+            list = self.get_renaming_list(args_without_last_exc)
+            renamings.append(self.make_new_vars(list))
         self.pending_exception_handlers.append((handler, exception_exits,
                                                 renamings))
         self.emit("setup_exception_block",
@@ -471,15 +475,44 @@
         args = [v for v in args if v.concretetype is not lltype.Void]
         return [self.var_position(v) for v in args]
 
-    def insert_renaming(self, args, force=False):
-        list = self.get_renaming_list(args)
-        if not force and list == range(0, self.free_vars*2, 2):
-            return []     # no-op
+    def make_new_vars(self, list):
         if len(list) >= MAX_MAKE_NEW_VARS:
             return ["make_new_vars", len(list)] + list
         else:
             return ["make_new_vars_%d" % len(list)] + list
 
+    def force_block_args_order(self, block):
+        non_void = [v for v in block.inputargs
+                      if v.concretetype is not lltype.Void]
+        if block not in self.block_start_order:
+            self.block_start_order[block] = range(len(non_void))
+        return [non_void[i] for i in self.block_start_order[block]]
+
+    def force_link_args_order(self, link):
+        self.force_block_args_order(link.target)
+        non_void = [v for v in link.args
+                      if v.concretetype is not lltype.Void]
+        return [non_void[i] for i in self.block_start_order[link.target]]
+
+    def insert_renaming(self, link):
+        shortcut = False
+        list = self.get_renaming_list(link.args)
+        if link.target not in self.block_start_order:
+            if (sorted(list) == range(0, self.free_vars*2, 2)
+                and link.target.operations != ()):
+                nlist = [None] * len(list)
+                for index, n in enumerate(list):
+                    nlist[n/2] = index
+                self.block_start_order[link.target] = nlist
+                shortcut = True
+            else:
+                self.force_block_args_order(link.target)
+        list = [list[i] for i in self.block_start_order[link.target]]
+        if list == range(0, self.free_vars*2, 2):
+            return []     # no-op
+        assert not shortcut
+        return self.make_new_vars(list)
+
     def minimize_variables(self, argument_only=False, exitswitch=True):
         if self.dont_minimize_variables:
             assert not argument_only
@@ -496,12 +529,12 @@
         vars = seen.items()
         vars.sort()
         vars = [v1 for pos, v1 in vars]
+        renaming_list = self.get_renaming_list(vars)
         if argument_only:
             # only generate the list of vars as an arg in a complex operation
-            renaming_list = self.get_renaming_list(vars)
             self.emit(len(renaming_list), *renaming_list)
-        else:
-            self.emit(*self.insert_renaming(vars))
+        elif renaming_list != range(0, self.free_vars*2, 2):
+            self.emit(*self.make_new_vars(renaming_list))
         self.free_vars = 0
         self.var_positions.clear()
         for v1 in vars:

Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/compile.py
==============================================================================
--- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/compile.py	(original)
+++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/compile.py	Mon Apr 27 12:00:08 2009
@@ -6,7 +6,8 @@
 
 from pypy.jit.metainterp.resoperation import ResOperation, rop
 from pypy.jit.metainterp.history import TreeLoop, log, Box, History
-from pypy.jit.metainterp.history import AbstractDescr, BoxInt, BoxPtr
+from pypy.jit.metainterp.history import AbstractDescr, BoxInt, BoxPtr, BoxObj
+from pypy.jit.metainterp import history
 from pypy.jit.metainterp.specnode import NotSpecNode
 from pypy.rlib.debug import debug_print
 
@@ -58,7 +59,7 @@
     else:
         if target_loop is not None:
             show_loop(metainterp, target_loop)
-    if target_loop is not None and target_loop not in map_loop2descr:
+    if target_loop is not None and type(target_loop) is not TerminatingLoop:
         target_loop.check_consistency()
     return target_loop
 
@@ -71,7 +72,7 @@
                 errmsg += ': ' + str(error)
         else:
             errmsg = None
-        if loop is None or loop in map_loop2descr:
+        if loop is None or type(loop) is TerminatingLoop:
             extraloops = []
         else:
             extraloops = [loop]
@@ -122,50 +123,94 @@
 
 # ____________________________________________________________
 
-class DoneWithThisFrameDescr0(AbstractDescr):
+class DoneWithThisFrameDescrVoid(AbstractDescr):
     def handle_fail_op(self, metainterp_sd, fail_op):
-        raise metainterp_sd.DoneWithThisFrame(None)
+        assert metainterp_sd.result_type == 'void'
+        raise metainterp_sd.DoneWithThisFrameVoid()
 
-class DoneWithThisFrameDescr1(AbstractDescr):
+class DoneWithThisFrameDescrInt(AbstractDescr):
     def handle_fail_op(self, metainterp_sd, fail_op):
+        assert metainterp_sd.result_type == 'int'
         resultbox = fail_op.args[0]
-        raise metainterp_sd.DoneWithThisFrame(resultbox)
+        if isinstance(resultbox, BoxInt):
+            result = metainterp_sd.cpu.get_latest_value_int(0)
+        else:
+            assert isinstance(resultbox, history.Const)
+            result = resultbox.getint()
+        raise metainterp_sd.DoneWithThisFrameInt(result)
+
+class DoneWithThisFrameDescrPtr(AbstractDescr):
+    def handle_fail_op(self, metainterp_sd, fail_op):
+        assert metainterp_sd.result_type == 'ptr'
+        resultbox = fail_op.args[0]
+        if isinstance(resultbox, BoxPtr):
+            result = metainterp_sd.cpu.get_latest_value_ptr(0)
+        else:
+            assert isinstance(resultbox, history.Const)
+            result = resultbox.getptr_base()
+        raise metainterp_sd.DoneWithThisFramePtr(result)
+
+class DoneWithThisFrameDescrObj(AbstractDescr):
+    def handle_fail_op(self, metainterp_sd, fail_op):
+        assert metainterp_sd.result_type == 'obj'
+        resultbox = fail_op.args[0]
+        if isinstance(resultbox, BoxObj):
+            result = metainterp_sd.cpu.get_latest_value_obj(0)
+        else:
+            assert isinstance(resultbox, history.Const)
+            result = resultbox.getobj()
+        raise metainterp_sd.DoneWithThisFrameObj(result)
 
 class ExitFrameWithExceptionDescr(AbstractDescr):
     def handle_fail_op(self, metainterp_sd, fail_op):
         assert len(fail_op.args) == 1
         valuebox = fail_op.args[0]
-        raise metainterp_sd.ExitFrameWithException(valuebox)
-
-done_with_this_frame_descr_0 = DoneWithThisFrameDescr0()
-done_with_this_frame_descr_1 = DoneWithThisFrameDescr1()
+        if isinstance(valuebox, BoxPtr):
+            value = metainterp_sd.cpu.get_latest_value_ptr(0)
+        else:
+            assert isinstance(valuebox, history.Const)
+            value = valuebox.getptr_base()
+        raise metainterp_sd.ExitFrameWithException(value)
+
+done_with_this_frame_descr_void = DoneWithThisFrameDescrVoid()
+done_with_this_frame_descr_int = DoneWithThisFrameDescrInt()
+done_with_this_frame_descr_ptr = DoneWithThisFrameDescrPtr()
+done_with_this_frame_descr_obj = DoneWithThisFrameDescrObj()
 exit_frame_with_exception_descr = ExitFrameWithExceptionDescr()
-map_loop2descr = {}
+
+class TerminatingLoop(TreeLoop):
+    pass
 
 # pseudo-loops to make the life of optimize.py easier
-_loop = TreeLoop('done_with_this_frame_int')
+_loop = TerminatingLoop('done_with_this_frame_int')
 _loop.specnodes = [NotSpecNode()]
 _loop.inputargs = [BoxInt()]
+_loop.finishdescr = done_with_this_frame_descr_int
 loops_done_with_this_frame_int = [_loop]
-map_loop2descr[_loop] = done_with_this_frame_descr_1
 
-_loop = TreeLoop('done_with_this_frame_ptr')
+_loop = TerminatingLoop('done_with_this_frame_ptr')
 _loop.specnodes = [NotSpecNode()]
 _loop.inputargs = [BoxPtr()]
+_loop.finishdescr = done_with_this_frame_descr_ptr
 loops_done_with_this_frame_ptr = [_loop]
-map_loop2descr[_loop] = done_with_this_frame_descr_1
 
-_loop = TreeLoop('done_with_this_frame_void')
+_loop = TerminatingLoop('done_with_this_frame_obj')
+_loop.specnodes = [NotSpecNode()]
+_loop.inputargs = [BoxObj()]
+_loop.finishdescr = done_with_this_frame_descr_obj
+loops_done_with_this_frame_obj = [_loop]
+
+_loop = TerminatingLoop('done_with_this_frame_void')
 _loop.specnodes = []
 _loop.inputargs = []
+_loop.finishdescr = done_with_this_frame_descr_void
 loops_done_with_this_frame_void = [_loop]
-map_loop2descr[_loop] = done_with_this_frame_descr_0
 
-_loop = TreeLoop('exit_frame_with_exception')
+_loop = TerminatingLoop('exit_frame_with_exception')
 _loop.specnodes = [NotSpecNode()]
 _loop.inputargs = [BoxPtr()]
+_loop.finishdescr = exit_frame_with_exception_descr
 loops_exit_frame_with_exception = [_loop]
-map_loop2descr[_loop] = exit_frame_with_exception_descr
 del _loop
 
 
@@ -181,7 +226,49 @@
     def handle_fail_op(self, metainterp_sd, fail_op):
         from pypy.jit.metainterp.pyjitpl import MetaInterp
         metainterp = MetaInterp(metainterp_sd)
-        return metainterp.handle_guard_failure(fail_op, self)
+        patch = self.patch_boxes_temporarily(metainterp_sd, fail_op)
+        try:
+            return metainterp.handle_guard_failure(fail_op, self)
+        finally:
+            self.restore_patched_boxes(metainterp_sd, fail_op, patch)
+
+    def patch_boxes_temporarily(self, metainterp_sd, fail_op):
+        # A bit indirect: when we hit a rop.FAIL, the current values are
+        # stored somewhere in the CPU backend.  Below we fetch them and
+        # copy them into the real boxes, i.e. the 'fail_op.args'.  We
+        # are in a try:finally path at the end of which, in
+        # restore_patched_boxes(), we can safely undo exactly the
+        # changes done here.
+        cpu = metainterp_sd.cpu
+        patch = []
+        for i in range(len(fail_op.args)):
+            box = fail_op.args[i]
+            patch.append(box.clonebox())
+            if isinstance(box, BoxInt):
+                srcvalue = cpu.get_latest_value_int(i)
+                box.changevalue_int(srcvalue)
+            elif isinstance(box, BoxPtr):
+                srcvalue = cpu.get_latest_value_ptr(i)
+                box.changevalue_ptr(srcvalue)
+            elif cpu.is_oo and isinstance(box, BoxObj):
+                srcvalue = cpu.get_latest_value_obj(i)
+                box.changevalue_obj(srcvalue)
+            else:
+                assert False
+        return patch
+
+    def restore_patched_boxes(self, metainterp_sd, fail_op, patch):
+        for i in range(len(patch)-1, -1, -1):
+            srcbox = patch[i]
+            dstbox = fail_op.args[i]
+            if isinstance(srcbox, BoxInt):
+                srcbox.changevalue_int(dstbox.getint())
+            elif isinstance(srcbox, BoxPtr):
+                srcbox.changevalue_ptr(dstbox.getptr_base())
+            elif metainterp_sd.cpu.is_oo and isinstance(srcbox, BoxObj):
+                srcbox.changevalue_obj(dstbox.getobj())
+            else:
+                assert False
 
     def get_guard_op(self):
         guard_op = self.history.operations[self.history_guard_index]
@@ -270,13 +357,13 @@
 
 def prepare_last_operation(new_loop, target_loop):
     op = new_loop.operations[-1]
-    if target_loop not in map_loop2descr:
+    if not isinstance(target_loop, TerminatingLoop):
         # normal case
         op.jump_target = target_loop
     else:
-        # The target_loop is a pseudo-loop done_with_this_frame.  Replace
-        # the operation with the real operation we want, i.e. a FAIL.
-        descr = map_loop2descr[target_loop]
+        # The target_loop is a pseudo-loop, e.g. done_with_this_frame.
+        # Replace the operation with the real operation we want, i.e. a FAIL.
+        descr = target_loop.finishdescr
         new_op = ResOperation(rop.FAIL, op.args, None, descr=descr)
         new_loop.operations[-1] = new_op
 

Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/history.py
==============================================================================
--- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/history.py	(original)
+++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/history.py	Mon Apr 27 12:00:08 2009
@@ -202,6 +202,9 @@
     def get_(self):
         return self.value
 
+    def set_future_value(self, cpu, j):
+        cpu.set_future_value_int(j, self.value)
+
     def equals(self, other):
         return self.value == other.getint()
 
@@ -241,6 +244,9 @@
     def get_(self):
         return llmemory.cast_adr_to_int(self.value)
 
+    def set_future_value(self, cpu, j):
+        cpu.set_future_value_int(j, self.getint())
+
     def equals(self, other):
         return self.value == other.getaddr(self.cpu)
 
@@ -270,6 +276,9 @@
     def getaddr(self, cpu):
         return llmemory.cast_ptr_to_adr(self.value)
 
+    def set_future_value(self, cpu, j):
+        cpu.set_future_value_ptr(j, self.value)
+
     def equals(self, other):
         return self.value == other.getptr_base()
 
@@ -295,11 +304,14 @@
     def get_(self):
         return ootype.ooidentityhash(self.value) # XXX: check me
 
-    def getaddr(self, cpu):
-        # so far this is used only when calling
-        # CodeWriter.IndirectCallset.bytecode_for_address.  We don't need a
-        # real addr, but just a key for the dictionary
-        return self.value
+    def set_future_value(self, cpu, j):
+        cpu.set_future_value_obj(j, self.value)
+
+##    def getaddr(self, cpu):
+##        # so far this is used only when calling
+##        # CodeWriter.IndirectCallset.bytecode_for_address.  We don't need a
+##        # real addr, but just a key for the dictionary
+##        return self.value
 
     def equals(self, other):
         return self.value == other.getobj()
@@ -376,6 +388,9 @@
     def get_(self):
         return self.value
 
+    def set_future_value(self, cpu, j):
+        cpu.set_future_value_int(j, self.value)
+
     def _getrepr_(self):
         return self.value
 
@@ -404,6 +419,9 @@
     def get_(self):
         return lltype.cast_ptr_to_int(self.value)
 
+    def set_future_value(self, cpu, j):
+        cpu.set_future_value_ptr(j, self.value)
+
     _getrepr_ = repr_pointer
     changevalue_ptr = __init__
 
@@ -430,10 +448,17 @@
     def get_(self):
         return ootype.ooidentityhash(self.value) # XXX: check me
 
+    def set_future_value(self, cpu, j):
+        cpu.set_future_value_obj(j, self.value)
+
     _getrepr_ = repr_object
     changevalue_obj = __init__
 
 
+def set_future_values(cpu, boxes):
+    for j in range(len(boxes)):
+        boxes[j].set_future_value(cpu, j)
+
 # ____________________________________________________________
 
 # The TreeLoop class contains a loop or a generalized loop, i.e. a tree

Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/pyjitpl.py
==============================================================================
--- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/pyjitpl.py	(original)
+++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/pyjitpl.py	Mon Apr 27 12:00:08 2009
@@ -26,7 +26,8 @@
     for arg in args:
         assert isinstance(arg, (Box, Const))
 
-DEBUG = False
+# debug level: 0 off, 1 normal, 2 detailed
+DEBUG = 2
 
 def log(msg):
     if not we_are_translated():
@@ -120,6 +121,8 @@
 
 
 class MIFrame(object):
+    exception_box = None
+    exc_value_box = None
 
     def __init__(self, metainterp, jitcode):
         assert isinstance(jitcode, codewriter.JitCode)
@@ -466,7 +469,7 @@
         if not we_are_translated():
             self.metainterp._debug_history.append(['call',
                                                   varargs[0], varargs[1:]])
-        return self.execute(rop.CALL, varargs, descr=calldescr)
+        self.execute(rop.CALL, varargs, descr=calldescr)
 
     @arguments("descr", "varargs")
     def opimpl_residual_call_pure(self, calldescr, varargs):
@@ -527,7 +530,11 @@
     def opimpl_indirect_call(self, pc, indirectcallset, box, varargs):
         box = self.implement_guard_value(pc, box)
         cpu = self.metainterp.cpu
-        jitcode = indirectcallset.bytecode_for_address(box.getaddr(cpu))
+        if cpu.is_oo:
+            key = box.getobj()
+        else:
+            key = box.getaddr(cpu)
+        jitcode = indirectcallset.bytecode_for_address(key)
         f = self.metainterp.newframe(jitcode)
         f.setup_call(varargs)
         return True
@@ -707,6 +714,11 @@
             else:
                 box = consts[~num]
             self.env.append(box)
+        if DEBUG:
+            values = [box.get_() for box in self.env]
+            log('setup_resume_at_op  %s:%d %s %d' % (self.jitcode.name,
+                                                     self.pc, values,
+                                                     self.exception_target))
 
     def run_one_step(self):
         # Execute the frame forward.  This method contains a loop that leaves
@@ -804,6 +816,9 @@
         self.options = options
         self.globaldata = MetaInterpGlobalData()
 
+        RESULT = portal_graph.getreturnvar().concretetype
+        self.result_type = history.getkind(RESULT)
+
         self.opcode_implementations = []
         self.opcode_names = []
         self.opname_to_index = {}
@@ -861,32 +876,11 @@
 # ____________________________________________________________
 
 class MetaInterpGlobalData(object):
-
-    blackhole = False
-    
     def __init__(self):
-        self.metainterp_doing_call = None
         self._debug_history = []
         self.compiled_merge_points = r_dict(history.mp_eq, history.mp_hash)
                  # { greenkey: list-of-MergePoints }
 
-    def set_metainterp_doing_call(self, metainterp):
-        self.save_recursive_call()
-        self.metainterp_doing_call = metainterp
-
-    def unset_metainterp_doing_call(self, metainterp):
-        if self.metainterp_doing_call != metainterp:
-            metainterp._restore_recursive_call()
-        self.metainterp_doing_call = None
-
-    def save_recursive_call(self):
-        if self.metainterp_doing_call is not None:
-            self.metainterp_doing_call._save_recursive_call()
-            self.metainterp_doing_call = None
-
-    def assert_empty(self):
-        assert self.metainterp_doing_call is None
-
 # ____________________________________________________________
 
 class MetaInterp(object):
@@ -914,7 +908,18 @@
         else:
             if not isinstance(self.history, history.BlackHole):
                 self.compile_done_with_this_frame(resultbox)
-            raise self.staticdata.DoneWithThisFrame(resultbox)
+            sd = self.staticdata
+            if sd.result_type == 'void':
+                assert resultbox is None
+                raise sd.DoneWithThisFrameVoid()
+            elif sd.result_type == 'int':
+                raise sd.DoneWithThisFrameInt(resultbox.getint())
+            elif sd.result_type == 'ptr':
+                raise sd.DoneWithThisFramePtr(resultbox.getptr_base())
+            elif self.cpu.is_oo and sd.result_type == 'obj':
+                raise sd.DoneWithThisFrameObj(resultbox.getobj())
+            else:
+                assert False
 
     def finishframe_exception(self, exceptionbox, excvaluebox):
         if we_are_translated():   # detect and propagate AssertionErrors early
@@ -936,7 +941,7 @@
             self.framestack.pop()
         if not isinstance(self.history, history.BlackHole):
             self.compile_exit_frame_with_exception(excvaluebox)
-        raise self.staticdata.ExitFrameWithException(excvaluebox)
+        raise self.staticdata.ExitFrameWithException(excvaluebox.getptr_base())
 
     def create_empty_history(self):
         self.history = history.History(self.cpu)
@@ -951,9 +956,6 @@
 
     @specialize.arg(1)
     def execute_and_record(self, opnum, argboxes, descr=None):
-        # detect recursions when using rop.CALL
-        if opnum == rop.CALL:
-            self.staticdata.globaldata.set_metainterp_doing_call(self)
         # execute the operation first
         history.check_descr(descr)
         resbox = executor.execute(self.cpu, opnum, argboxes, descr)
@@ -969,68 +971,11 @@
                 resbox = resbox.nonconstbox()    # ensure it is a Box
         else:
             assert resbox is None or isinstance(resbox, Box)
-            if opnum == rop.CALL:
-                self.staticdata.globaldata.unset_metainterp_doing_call(self)
         # record the operation if not constant-folded away
         if not canfold:
             self.history.record(opnum, argboxes, resbox, descr)
         return resbox
 
-    def _save_recursive_call(self):
-        # A bit of a hack: we need to be safe against box.changevalue_xxx()
-        # called by cpu.execute_operations(), in case we are recursively
-        # in another MetaInterp.  Temporarily save away the content of the
-        # boxes.
-        log('recursive call to execute_operations()!')
-        saved_env = []
-        framestack = []
-        for f in self.framestack:
-            newenv = []
-            for box in f.env:
-                if isinstance(box, Box):
-                    saved_env.append(box.clonebox())
-                newenv.append(box)
-            framestack.append(newenv)
-        pseudoframe = instantiate(MIFrame)
-        pseudoframe.env = saved_env
-        pseudoframe._saved_framestack = framestack
-        self.framestack.append(pseudoframe)
-
-    def _restore_recursive_call(self):
-        log('recursion detected, restoring state')
-        if not we_are_translated():
-            assert not hasattr(self.framestack[-1], 'jitcode')
-            assert hasattr(self.framestack[-2], 'jitcode')
-        pseudoframe = self.framestack.pop()
-        saved_env = pseudoframe.env
-        i = 0
-        assert len(pseudoframe._saved_framestack) == len(self.framestack)
-        for j in range(len(self.framestack)):
-            f = self.framestack[j]
-            pseudoenv = pseudoframe._saved_framestack[j]
-            assert len(f.env) == len(pseudoenv)
-            for k in range(len(f.env)):
-                box = f.env[k]
-                if isinstance(box, BoxInt):
-                    assert isinstance(pseudoenv[k], BoxInt)
-                    box.changevalue_int(saved_env[i].getint())
-                    i += 1
-                elif isinstance(box, BoxPtr):
-                    assert isinstance(pseudoenv[k], BoxPtr)
-                    box.changevalue_ptr(saved_env[i].getptr_base())
-                    i += 1
-                elif isinstance(box, BoxObj):
-                    assert isinstance(pseudoenv[k], BoxObj)
-                    box.changevalue_obj(saved_env[i].getobj())
-                    i += 1
-                else:
-                    if isinstance(box, ConstInt):
-                        assert box.getint() == pseudoenv[k].getint()
-                    elif isinstance(box, ConstPtr):
-                        assert box.getptr_base() == pseudoenv[k].getptr_base()
-                    assert isinstance(box, Const)
-        assert i == len(saved_env)
-
     def _interpret(self):
         # Execute the frames forward until we raise a DoneWithThisFrame,
         # a ContinueRunningNormally, or a GenerateMergePoint exception.
@@ -1147,7 +1092,8 @@
         num_green_args = self.staticdata.num_green_args
         residual_args = self.get_residual_args(loop,
                                                gmp.argboxes[num_green_args:])
-        return (loop, residual_args)
+        history.set_future_values(self.cpu, residual_args)
+        return loop
 
     def prepare_resume_from_failure(self, opnum):
         if opnum == rop.GUARD_TRUE:     # a goto_if_not that jumps only now
@@ -1187,15 +1133,22 @@
 
     def compile_done_with_this_frame(self, exitbox):
         # temporarily put a JUMP to a pseudo-loop
-        if exitbox is not None:
-            exits = [exitbox]
-            if isinstance(exitbox, BoxInt) or isinstance(exitbox, ConstInt):
-                loops = compile.loops_done_with_this_frame_int
-            else:
-                loops = compile.loops_done_with_this_frame_ptr
-        else:
+        sd = self.staticdata
+        if sd.result_type == 'void':
+            assert exitbox is None
             exits = []
             loops = compile.loops_done_with_this_frame_void
+        elif sd.result_type == 'int':
+            exits = [exitbox]
+            loops = compile.loops_done_with_this_frame_int
+        elif sd.result_type == 'ptr':
+            exits = [exitbox]
+            loops = compile.loops_done_with_this_frame_ptr
+        elif sd.cpu.is_oo and sd.result_type == 'obj':
+            exits = [exitbox]
+            loops = compile.loops_done_with_this_frame_obj
+        else:
+            assert False
         self.history.record(rop.JUMP, exits, None)
         target_loop = compile.compile_new_bridge(self, loops, self.resumekey)
         assert target_loop is loops[0]
@@ -1276,14 +1229,14 @@
             if suboperations[-1].opnum != rop.FAIL:
                 must_compile = False
                 log("ignoring old version of the guard")
-            self.history = history.History(self.cpu)
-            extra = len(suboperations) - 1
-            assert extra >= 0
-            for i in range(extra):
-                self.history.operations.append(suboperations[i])
-            self.extra_rebuild_operations = extra
-        else:
-            self.staticdata.globaldata.blackhole = True
+            else:
+                self.history = history.History(self.cpu)
+                extra = len(suboperations) - 1
+                assert extra >= 0
+                for i in range(extra):
+                    self.history.operations.append(suboperations[i])
+                self.extra_rebuild_operations = extra
+        if not must_compile:
             self.history = history.BlackHole(self.cpu)
             # the BlackHole is invalid because it doesn't start with
             # guard_failure.key.guard_op.suboperations, but that's fine

Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/simple_optimize.py
==============================================================================
--- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/simple_optimize.py	(original)
+++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/simple_optimize.py	Mon Apr 27 12:00:08 2009
@@ -5,6 +5,7 @@
 
 def optimize_loop(options, old_loops, loop, cpu=None):
     if old_loops:
+        assert len(old_loops) == 1
         return old_loops[0]
     else:
         newoperations = []

Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_basic.py
==============================================================================
--- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_basic.py	(original)
+++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_basic.py	Mon Apr 27 12:00:08 2009
@@ -77,14 +77,16 @@
             cw.make_one_bytecode(graph_key, False, called_from)
         metainterp.staticdata.portal_code = maingraph
         metainterp.staticdata.state = FakeWarmRunnerDesc()
-        metainterp.staticdata.DoneWithThisFrame = DoneWithThisFrame
+        metainterp.staticdata.DoneWithThisFrameInt = DoneWithThisFrame
+        metainterp.staticdata.DoneWithThisFramePtr = DoneWithThisFrame
+        metainterp.staticdata.DoneWithThisFrameObj = DoneWithThisFrame
         self.metainterp = metainterp
         try:
             metainterp.compile_and_run_once(*args)
         except DoneWithThisFrame, e:
             #if conftest.option.view:
             #    metainterp.stats.view()
-            return e.args[0].value
+            return e.args[0]
         else:
             raise Exception("FAILED")
 

Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_loop.py
==============================================================================
--- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_loop.py	(original)
+++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_loop.py	Mon Apr 27 12:00:08 2009
@@ -213,6 +213,45 @@
         assert res == expected
         self.check_loop_count_at_most(19)
 
+    def test_interp_many_paths_2(self):
+        myjitdriver = JitDriver(greens = ['i'], reds = ['x', 'node'])
+        NODE = self._get_NODE()
+        bytecode = "xxxxxxxb"
+
+        def can_enter_jit(i, x, node):
+            myjitdriver.can_enter_jit(i=i, x=x, node=node)
+        
+        def f(node):
+            x = 0
+            i = 0
+            while i < len(bytecode):
+                myjitdriver.jit_merge_point(i=i, x=x, node=node)
+                op = bytecode[i]
+                if op == 'x':
+                    if not node:
+                        break
+                    if node.value < 100:   # a pseudo-random choice
+                        x += 1
+                    node = node.next
+                elif op == 'b':
+                    i = 0
+                    can_enter_jit(i, x, node)
+                    continue
+                i += 1
+            return x
+
+        node1 = self.nullptr(NODE)
+        for i in range(300):
+            prevnode = self.malloc(NODE)
+            prevnode.value = pow(47, i, 199)
+            prevnode.next = node1
+            node1 = prevnode
+
+        expected = f(node1)
+        res = self.meta_interp(f, [node1])
+        assert res == expected
+        self.check_loop_count_at_most(19)
+
     def test_nested_loops(self):
         myjitdriver = JitDriver(greens = ['i'], reds = ['x', 'y'])
         bytecode = "abc<de"

Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_recursive.py
==============================================================================
--- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_recursive.py	(original)
+++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_recursive.py	Mon Apr 27 12:00:08 2009
@@ -1,6 +1,7 @@
 import py
 from pypy.rlib.jit import JitDriver
 from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin
+from pypy.jit.metainterp.simple_optimize import Optimizer
 
 
 class RecursiveTests:
@@ -20,7 +21,7 @@
                 return f(n+1)
             else:
                 return 1
-        res = self.meta_interp(main, [20])
+        res = self.meta_interp(main, [20], optimizer=Optimizer)
         assert res == main(20)
 
     def test_recursion_three_times(self):
@@ -43,7 +44,7 @@
         print
         for i in range(1, 11):
             print '%3d %9d' % (i, f(i))
-        res = self.meta_interp(main, [10])
+        res = self.meta_interp(main, [10], optimizer=Optimizer)
         assert res == main(10)
         self.check_enter_count_at_most(10)
 

Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/warmspot.py
==============================================================================
--- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/warmspot.py	(original)
+++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/warmspot.py	Mon Apr 27 12:00:08 2009
@@ -189,8 +189,6 @@
 
         def maybe_enter_jit(*args):
             try:
-                if self.metainterp_sd.globaldata.blackhole:
-                    return
                 state.maybe_compile_and_run(*args)
             except JitException:
                 raise     # go through
@@ -206,11 +204,14 @@
         args = op.args[2:]
         ALLARGS = []
         self.green_args_spec = []
+        self.red_args_types = []
         for i, v in enumerate(args):
             TYPE = v.concretetype
             ALLARGS.append(TYPE)
             if i < len(self.jitdriver.greens):
                 self.green_args_spec.append(TYPE)
+            else:
+                self.red_args_types.append(history.getkind(TYPE))
         RESTYPE = graph.getreturnvar().concretetype
         (self.JIT_ENTER_FUNCTYPE,
          self.PTR_JIT_ENTER_FUNCTYPE) = self.ts.get_FuncType(ALLARGS, lltype.Void)
@@ -272,9 +273,9 @@
         #               except ContinueRunningNormally, e:
         #                   *args = *e.new_args
         #               except DoneWithThisFrame, e:
-        #                   return e.result
+        #                   return e.return
         #               except ExitFrameWithException, e:
-        #                   raise e.type, e.value
+        #                   raise Exception, e.value
         #
         #       def portal(*args):
         #           while 1:
@@ -290,17 +291,37 @@
         portal_ptr = self.ts.functionptr(PORTALFUNC, 'portal',
                                          graph = portalgraph)
 
-        class DoneWithThisFrame(JitException):
-            def __init__(self, resultbox):
-                self.resultbox = resultbox
+        class DoneWithThisFrameVoid(JitException):
             def __str__(self):
-                return 'DoneWithThisFrame(%s)' % (self.resultbox,)
+                return 'DoneWithThisFrameVoid()'
+
+        class DoneWithThisFrameInt(JitException):
+            def __init__(self, result):
+                assert lltype.typeOf(result) is lltype.Signed
+                self.result = result
+            def __str__(self):
+                return 'DoneWithThisFrameInt(%s)' % (self.result,)
+
+        class DoneWithThisFramePtr(JitException):
+            def __init__(self, result):
+                assert lltype.typeOf(result) == llmemory.GCREF
+                self.result = result
+            def __str__(self):
+                return 'DoneWithThisFramePtr(%s)' % (self.result,)
+
+        class DoneWithThisFrameObj(JitException):
+            def __init__(self, result):
+                assert ootype.typeOf(result) == ootype.Object
+                self.result = result
+            def __str__(self):
+                return 'DoneWithThisFrameObj(%s)' % (self.result,)
 
         class ExitFrameWithException(JitException):
-            def __init__(self, valuebox):
-                self.valuebox = valuebox
+            def __init__(self, value):
+                assert lltype.typeOf(value) == llmemory.GCREF
+                self.value = value
             def __str__(self):
-                return 'ExitFrameWithException(%s)' % (self.valuebox,)
+                return 'ExitFrameWithException(%s)' % (self.value,)
 
         class ContinueRunningNormally(JitException):
             def __init__(self, args):
@@ -310,42 +331,56 @@
                 return 'ContinueRunningNormally(%s)' % (
                     ', '.join(map(str, self.args)),)
 
-        self.DoneWithThisFrame = DoneWithThisFrame
+        self.DoneWithThisFrameVoid = DoneWithThisFrameVoid
+        self.DoneWithThisFrameInt = DoneWithThisFrameInt
+        self.DoneWithThisFramePtr = DoneWithThisFramePtr
+        self.DoneWithThisFrameObj = DoneWithThisFrameObj
         self.ExitFrameWithException = ExitFrameWithException
         self.ContinueRunningNormally = ContinueRunningNormally
-        self.metainterp_sd.DoneWithThisFrame = DoneWithThisFrame
+        self.metainterp_sd.DoneWithThisFrameVoid = DoneWithThisFrameVoid
+        self.metainterp_sd.DoneWithThisFrameInt = DoneWithThisFrameInt
+        self.metainterp_sd.DoneWithThisFramePtr = DoneWithThisFramePtr
+        self.metainterp_sd.DoneWithThisFrameObj = DoneWithThisFrameObj
         self.metainterp_sd.ExitFrameWithException = ExitFrameWithException
         self.metainterp_sd.ContinueRunningNormally = ContinueRunningNormally
         rtyper = self.translator.rtyper
         portalfunc_ARGS = unrolling_iterable(list(enumerate(PORTALFUNC.ARGS)))
         RESULT = PORTALFUNC.RESULT
+        result_kind = history.getkind(RESULT)
 
         unwrap_exc_value_box = self.metainterp_sd.ts.unwrap_exc_value_box
         def ll_portal_runner(*args):
             while 1:
                 try:
-                    try:
-                        return support.maybe_on_top_of_llinterp(rtyper,
-                                                          portal_ptr)(*args)
-                    except ContinueRunningNormally, e:
-                        args = ()
-                        for i, ARG in portalfunc_ARGS:
-                            v = unwrap(ARG, e.args[i])
-                            args = args + (v,)
-                    except DoneWithThisFrame, e:
-                        return unwrap(RESULT, e.resultbox)
-                    except ExitFrameWithException, e:
-                        value = unwrap_exc_value_box(e.valuebox)
-                        if not we_are_translated():
-                            if hasattr(value, 'typeptr'):
-                                raise LLException(value.typeptr, value)
-                            else:
-                                raise LLException(ootype.classof(value), value)
+                    return support.maybe_on_top_of_llinterp(rtyper,
+                                                      portal_ptr)(*args)
+                except ContinueRunningNormally, e:
+                    args = ()
+                    for i, ARG in portalfunc_ARGS:
+                        v = unwrap(ARG, e.args[i])
+                        args = args + (v,)
+                except DoneWithThisFrameVoid:
+                    assert result_kind == 'void'
+                    return
+                except DoneWithThisFrameInt, e:
+                    assert result_kind == 'int'
+                    return lltype.cast_primitive(RESULT, e.result)
+                except DoneWithThisFramePtr, e:
+                    assert result_kind == 'ptr'
+                    return lltype.cast_opaque_ptr(RESULT, e.result)
+                except DoneWithThisFrameObj, e:
+                    assert result_kind == 'obj'
+                    return ootype.cast_from_object(RESULT, e.result)
+                except ExitFrameWithException, e:
+                    value = unwrap_exc_value_box(e.valuebox)
+                    if not we_are_translated():
+                        if hasattr(value, 'typeptr'):
+                            raise LLException(value.typeptr, value)
                         else:
-                            value = cast_base_ptr_to_instance(Exception, value)
-                            raise Exception, value
-                finally:
-                    self.metainterp_sd.globaldata.blackhole = False
+                            raise LLException(ootype.classof(value), value)
+                    else:
+                        value = cast_base_ptr_to_instance(Exception, value)
+                        raise Exception, value
 
         ll_portal_runner._recursive_portal_call_ = True
 
@@ -416,7 +451,7 @@
     warmrunnerdesc.num_green_args = num_green_args
     green_args_spec = unrolling_iterable(warmrunnerdesc.green_args_spec)
     green_args_names = unrolling_iterable(jitdriver.greens)
-    red_args_index = unrolling_iterable(range(len(jitdriver.reds)))
+    red_args_types = unrolling_iterable(warmrunnerdesc.red_args_types)
     if num_green_args:
         MAX_HASH_TABLE_BITS = 28
     else:
@@ -444,24 +479,22 @@
                     return False
                 i = i + 1
             return True
-        def fill_boxes(self, *redargs):
-            boxes = self.bridge.inputargs
-            for j in red_args_index:
+        def set_future_values(self, cpu, *redargs):
+            j = 0
+            for typecode in red_args_types:
                 value = redargs[j]
-                box = boxes[j]
-                TYPE = lltype.typeOf(value)
-                if isinstance(TYPE, lltype.Ptr):
-                    assert isinstance(box, history.BoxPtr)
-                    box.changevalue_ptr(lltype.cast_opaque_ptr(llmemory.GCREF, value))
-                elif isinstance(TYPE, ootype.OOType):
-                    assert isinstance(box, history.BoxObj)
-                    box.changevalue_obj(ootype.cast_to_object(value))
-                elif TYPE == lltype.Signed:
-                    assert isinstance(box, history.BoxInt)
-                    box.changevalue_int(value)
+                if typecode == 'ptr':
+                    ptrvalue = lltype.cast_opaque_ptr(llmemory.GCREF, value)
+                    cpu.set_future_value_ptr(j, ptrvalue)
+                elif typecode == 'obj':
+                    objvalue = ootype.cast_to_object(value)
+                    cpu.set_future_value_obj(j, objvalue)
+                elif typecode == 'int':
+                    intvalue = lltype.cast_primitive(lltype.Signed, value)
+                    cpu.set_future_value_int(j, intvalue)
                 else:
-                    raise AssertionError("box is: %s" % (box,))
-            return boxes
+                    assert False
+                j = j + 1
 
     class WarmEnterState:
         def __init__(self):
@@ -508,29 +541,26 @@
                 #interp.debug_trace("jit_compile", *greenargs)
                 metainterp_sd = warmrunnerdesc.metainterp_sd
                 metainterp = MetaInterp(metainterp_sd)
-                loop, boxes = metainterp.compile_and_run_once(*args)
+                loop = metainterp.compile_and_run_once(*args)
             else:
                 # machine code was already compiled for these greenargs
                 # (or we have a hash collision)
                 assert isinstance(cell, MachineCodeEntryPoint)
                 if not cell.equalkey(*greenargs):
                     # hash collision
-                    loop, boxes = self.handle_hash_collision(cell, argshash,
-                                                             *args)
+                    loop = self.handle_hash_collision(cell, argshash, *args)
                     if loop is None:
                         return
                 else:
                     # get the assembler and fill in the boxes
+                    cpu = warmrunnerdesc.metainterp_sd.cpu
+                    cell.set_future_values(cpu, *args[num_green_args:])
                     loop = cell.bridge
-                    boxes = cell.fill_boxes(*args[num_green_args:])
             # ---------- execute assembler ----------
-            warmrunnerdesc.metainterp_sd.globaldata.save_recursive_call()
             while True:     # until interrupted by an exception
                 metainterp_sd = warmrunnerdesc.metainterp_sd
-                metainterp_sd.globaldata.assert_empty()
-                fail_op = metainterp_sd.cpu.execute_operations(loop, boxes)
-                loop, boxes = fail_op.descr.handle_fail_op(metainterp_sd,
-                                                           fail_op)
+                fail_op = metainterp_sd.cpu.execute_operations(loop)
+                loop = fail_op.descr.handle_fail_op(metainterp_sd, fail_op)
         maybe_compile_and_run._dont_inline_ = True
 
         def handle_hash_collision(self, cell, argshash, *args):
@@ -543,15 +573,16 @@
                     cell.next = next.next
                     next.next = self.cells[argshash]
                     self.cells[argshash] = next
-                    return (next.bridge,
-                            next.fill_boxes(*args[num_green_args:]))
+                    cpu = warmrunnerdesc.metainterp_sd.cpu
+                    next.set_future_values(cpu, *args[num_green_args:])
+                    return next.bridge
                 cell = next
                 next = cell.next
             # not found at all, do profiling
             n = next.counter + 1
             if n < self.threshold:
                 cell.next = Counter(n)
-                return (None, None)
+                return None
             metainterp_sd = warmrunnerdesc.metainterp_sd
             metainterp = MetaInterp(metainterp_sd)
             return metainterp.compile_and_run_once(*args)

Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/tl/pypyjit_child.py
==============================================================================
--- pypy/branch/pyjitpl5-simplify/pypy/jit/tl/pypyjit_child.py	(original)
+++ pypy/branch/pyjitpl5-simplify/pypy/jit/tl/pypyjit_child.py	Mon Apr 27 12:00:08 2009
@@ -1,6 +1,7 @@
 from pypy.conftest import option
 from pypy.rpython.lltypesystem import lltype
 from pypy.jit.metainterp import warmspot
+from pypy.jit.metainterp.simple_optimize import Optimizer
 from pypy.module.pypyjit.policy import PyPyJitPolicy
 
 # Current output: http://paste.pocoo.org/show/106540/
@@ -34,7 +35,9 @@
     interp.heap.malloc_nonmovable = returns_null     # XXX
 
     print 'warmspot.jittify_and_run() started...'
+    from pypy.jit.backend.llgraph.runner import LLtypeCPU
     policy = PyPyJitPolicy(interp.typer.annotator.translator)
     option.view = True
     warmspot.jittify_and_run(interp, graph, [], policy=policy,
-                             listops=True)
+                             listops=True, CPUClass=LLtypeCPU,
+                             optimizer=Optimizer)

Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/tl/pypyjit_demo.py
==============================================================================
--- pypy/branch/pyjitpl5-simplify/pypy/jit/tl/pypyjit_demo.py	(original)
+++ pypy/branch/pyjitpl5-simplify/pypy/jit/tl/pypyjit_demo.py	Mon Apr 27 12:00:08 2009
@@ -1,14 +1,10 @@
-def simple_loop():
-    print "simple loop"
-
-    i = 0
-    while i < 100:
-        i = i + 3
-    print i
-    assert i == 102
+def do():
+    import test.regrtest, sys
+    sys.argv = ['regrtest.py', 'test_builtin']
+    test.regrtest.main()
 
 try:
-    simple_loop()
+    do()
 except Exception, e:
     print '/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\'
     import sys



More information about the Pypy-commit mailing list