[pypy-svn] r79770 - in pypy/branch/jitypes2: . ctypes_configure lib-python lib-python/modified-2.5.2/distutils lib-python/modified-2.5.2/distutils/tests lib-python/modified-2.5.2/test lib_pypy lib_pypy/_ctypes lib_pypy/pypy_test pypy pypy/annotation pypy/annotation/test pypy/config pypy/config/test pypy/doc pypy/doc/config pypy/doc/statistic pypy/interpreter pypy/interpreter/test pypy/jit pypy/jit/backend pypy/jit/backend/llgraph pypy/jit/backend/llsupport pypy/jit/backend/llsupport/test pypy/jit/backend/test pypy/jit/backend/x86 pypy/jit/backend/x86/test pypy/jit/codewriter pypy/jit/codewriter/test pypy/jit/metainterp pypy/jit/metainterp/optimizeopt pypy/jit/metainterp/test pypy/jit/tl pypy/jit/tl/spli pypy/jit/tool pypy/jit/tool/test pypy/module/__pypy__ pypy/module/__pypy__/test pypy/module/_minimal_curses pypy/module/_pickle_support pypy/module/array/benchmark pypy/module/array/test pypy/module/binascii pypy/module/binascii/test pypy/module/cpyext pypy/module/cpyext/include pypy/module/cpyext/src pypy/module/cpyext/test pypy/module/fcntl/test pypy/module/imp pypy/module/itertools pypy/module/posix pypy/module/posix/test pypy/module/pyexpat pypy/module/pyexpat/test pypy/module/pypyjit pypy/module/pypyjit/test pypy/module/sys pypy/module/test_lib_pypy/ctypes_tests pypy/objspace/std pypy/rlib pypy/rlib/rsre pypy/rlib/rsre/test pypy/rlib/test pypy/rpython pypy/rpython/lltypesystem pypy/rpython/memory/gc pypy/rpython/memory/gc/test pypy/rpython/memory/gctransform pypy/rpython/module pypy/rpython/ootypesystem pypy/rpython/test pypy/rpython/tool pypy/tool pypy/translator pypy/translator/c pypy/translator/c/gcc pypy/translator/c/src pypy/translator/c/test pypy/translator/goal pypy/translator/goal/test2 pypy/translator/platform pypy/translator/tool site-packages

antocuni at codespeak.net antocuni at codespeak.net
Fri Dec 3 11:04:39 CET 2010


Author: antocuni
Date: Fri Dec  3 11:04:29 2010
New Revision: 79770

Added:
   pypy/branch/jitypes2/lib-python/modified-2.5.2/test/seq_tests.py
      - copied unchanged from r79768, pypy/trunk/lib-python/modified-2.5.2/test/seq_tests.py
   pypy/branch/jitypes2/lib_pypy/pypy_test/hack___pypy__.py
      - copied unchanged from r79768, pypy/trunk/lib_pypy/pypy_test/hack___pypy__.py
   pypy/branch/jitypes2/pypy/config/support.py
      - copied unchanged from r79768, pypy/trunk/pypy/config/support.py
   pypy/branch/jitypes2/pypy/config/test/test_support.py
      - copied unchanged from r79768, pypy/trunk/pypy/config/test/test_support.py
   pypy/branch/jitypes2/pypy/doc/config/objspace.usemodules.binascii.txt
      - copied unchanged from r79768, pypy/trunk/pypy/doc/config/objspace.usemodules.binascii.txt
   pypy/branch/jitypes2/pypy/jit/backend/llsupport/asmmemmgr.py
      - copied unchanged from r79768, pypy/trunk/pypy/jit/backend/llsupport/asmmemmgr.py
   pypy/branch/jitypes2/pypy/jit/backend/llsupport/test/test_asmmemmgr.py
      - copied unchanged from r79768, pypy/trunk/pypy/jit/backend/llsupport/test/test_asmmemmgr.py
   pypy/branch/jitypes2/pypy/jit/backend/x86/codebuf.py
      - copied unchanged from r79768, pypy/trunk/pypy/jit/backend/x86/codebuf.py
   pypy/branch/jitypes2/pypy/jit/metainterp/memmgr.py
      - copied unchanged from r79768, pypy/trunk/pypy/jit/metainterp/memmgr.py
   pypy/branch/jitypes2/pypy/jit/metainterp/test/test_memmgr.py
      - copied unchanged from r79768, pypy/trunk/pypy/jit/metainterp/test/test_memmgr.py
   pypy/branch/jitypes2/pypy/jit/tool/cpython.vmrss
      - copied unchanged from r79768, pypy/trunk/pypy/jit/tool/cpython.vmrss
   pypy/branch/jitypes2/pypy/jit/tool/test/test_log2gnumeric.py
      - copied unchanged from r79768, pypy/trunk/pypy/jit/tool/test/test_log2gnumeric.py
   pypy/branch/jitypes2/pypy/module/__pypy__/interp_debug.py
      - copied unchanged from r79768, pypy/trunk/pypy/module/__pypy__/interp_debug.py
   pypy/branch/jitypes2/pypy/module/__pypy__/test/test_debug.py
      - copied unchanged from r79768, pypy/trunk/pypy/module/__pypy__/test/test_debug.py
   pypy/branch/jitypes2/pypy/module/binascii/   (props changed)
      - copied from r79768, pypy/trunk/pypy/module/binascii/
   pypy/branch/jitypes2/pypy/module/cpyext/include/structseq.h
      - copied unchanged from r79768, pypy/trunk/pypy/module/cpyext/include/structseq.h
   pypy/branch/jitypes2/pypy/module/cpyext/src/structseq.c
      - copied unchanged from r79768, pypy/trunk/pypy/module/cpyext/src/structseq.c
   pypy/branch/jitypes2/pypy/module/cpyext/test/test_structseq.py
      - copied unchanged from r79768, pypy/trunk/pypy/module/cpyext/test/test_structseq.py
   pypy/branch/jitypes2/pypy/rpython/memory/gc/env.py
      - copied unchanged from r79768, pypy/trunk/pypy/rpython/memory/gc/env.py
   pypy/branch/jitypes2/pypy/rpython/memory/gc/test/test_env.py
      - copied unchanged from r79768, pypy/trunk/pypy/rpython/memory/gc/test/test_env.py
   pypy/branch/jitypes2/pypy/rpython/memory/gc/test/test_inspector.py
      - copied unchanged from r79768, pypy/trunk/pypy/rpython/memory/gc/test/test_inspector.py
   pypy/branch/jitypes2/pypy/tool/debug_print.py
      - copied unchanged from r79768, pypy/trunk/pypy/tool/debug_print.py
   pypy/branch/jitypes2/pypy/translator/platform/freebsd.py
      - copied unchanged from r79768, pypy/trunk/pypy/translator/platform/freebsd.py
Removed:
   pypy/branch/jitypes2/pypy/doc/config/translation.jit_debug.txt
   pypy/branch/jitypes2/pypy/translator/platform/freebsd7.py
Modified:
   pypy/branch/jitypes2/   (props changed)
   pypy/branch/jitypes2/ctypes_configure/configure.py
   pypy/branch/jitypes2/lib-python/conftest.py
   pypy/branch/jitypes2/lib-python/modified-2.5.2/distutils/msvccompiler.py
   pypy/branch/jitypes2/lib-python/modified-2.5.2/distutils/tests/test_msvccompiler.py
   pypy/branch/jitypes2/lib_pypy/_ctypes/array.py
   pypy/branch/jitypes2/lib_pypy/_ctypes/basics.py
   pypy/branch/jitypes2/lib_pypy/_ctypes/builtin.py
   pypy/branch/jitypes2/lib_pypy/_ctypes/function.py
   pypy/branch/jitypes2/lib_pypy/_ctypes/pointer.py
   pypy/branch/jitypes2/lib_pypy/_ctypes/primitive.py
   pypy/branch/jitypes2/lib_pypy/_ctypes/structure.py
   pypy/branch/jitypes2/lib_pypy/_hashlib.py
   pypy/branch/jitypes2/lib_pypy/_locale.py
   pypy/branch/jitypes2/lib_pypy/_marshal.py
   pypy/branch/jitypes2/lib_pypy/_minimal_curses.py
   pypy/branch/jitypes2/lib_pypy/_pypy_interact.py
   pypy/branch/jitypes2/lib_pypy/binascii.py
   pypy/branch/jitypes2/lib_pypy/cPickle.py
   pypy/branch/jitypes2/lib_pypy/cmath.py
   pypy/branch/jitypes2/lib_pypy/ctypes_support.py
   pypy/branch/jitypes2/lib_pypy/grp.py
   pypy/branch/jitypes2/lib_pypy/hashlib.py
   pypy/branch/jitypes2/lib_pypy/itertools.py
   pypy/branch/jitypes2/lib_pypy/msvcrt.py
   pypy/branch/jitypes2/lib_pypy/pwd.py
   pypy/branch/jitypes2/lib_pypy/pyexpat.py
   pypy/branch/jitypes2/lib_pypy/pypy_test/test_hashlib.py
   pypy/branch/jitypes2/lib_pypy/pypy_test/test_structseq.py
   pypy/branch/jitypes2/lib_pypy/readline.py
   pypy/branch/jitypes2/lib_pypy/resource.py
   pypy/branch/jitypes2/lib_pypy/syslog.py
   pypy/branch/jitypes2/pypy/   (props changed)
   pypy/branch/jitypes2/pypy/annotation/annrpython.py
   pypy/branch/jitypes2/pypy/annotation/bookkeeper.py
   pypy/branch/jitypes2/pypy/annotation/description.py
   pypy/branch/jitypes2/pypy/annotation/listdef.py
   pypy/branch/jitypes2/pypy/annotation/model.py
   pypy/branch/jitypes2/pypy/annotation/specialize.py
   pypy/branch/jitypes2/pypy/annotation/test/test_annrpython.py
   pypy/branch/jitypes2/pypy/annotation/unaryop.py
   pypy/branch/jitypes2/pypy/config/pypyoption.py
   pypy/branch/jitypes2/pypy/config/translationoption.py
   pypy/branch/jitypes2/pypy/conftest.py
   pypy/branch/jitypes2/pypy/doc/cpython_differences.txt
   pypy/branch/jitypes2/pypy/doc/faq.txt
   pypy/branch/jitypes2/pypy/doc/index.txt
   pypy/branch/jitypes2/pypy/doc/release-1.4.0.txt
   pypy/branch/jitypes2/pypy/doc/sprint-reports.txt
   pypy/branch/jitypes2/pypy/doc/statistic/release_dates.dat
   pypy/branch/jitypes2/pypy/doc/statistic/sprint_dates.dat
   pypy/branch/jitypes2/pypy/interpreter/baseobjspace.py
   pypy/branch/jitypes2/pypy/interpreter/function.py
   pypy/branch/jitypes2/pypy/interpreter/gateway.py
   pypy/branch/jitypes2/pypy/interpreter/generator.py
   pypy/branch/jitypes2/pypy/interpreter/pycode.py
   pypy/branch/jitypes2/pypy/interpreter/test/test_gateway.py
   pypy/branch/jitypes2/pypy/jit/backend/detect_cpu.py
   pypy/branch/jitypes2/pypy/jit/backend/llgraph/llimpl.py
   pypy/branch/jitypes2/pypy/jit/backend/llgraph/runner.py
   pypy/branch/jitypes2/pypy/jit/backend/llsupport/gc.py
   pypy/branch/jitypes2/pypy/jit/backend/llsupport/llmodel.py
   pypy/branch/jitypes2/pypy/jit/backend/llsupport/test/test_gc.py
   pypy/branch/jitypes2/pypy/jit/backend/model.py
   pypy/branch/jitypes2/pypy/jit/backend/test/runner_test.py
   pypy/branch/jitypes2/pypy/jit/backend/test/test_random.py
   pypy/branch/jitypes2/pypy/jit/backend/x86/assembler.py
   pypy/branch/jitypes2/pypy/jit/backend/x86/regalloc.py
   pypy/branch/jitypes2/pypy/jit/backend/x86/regloc.py
   pypy/branch/jitypes2/pypy/jit/backend/x86/runner.py
   pypy/branch/jitypes2/pypy/jit/backend/x86/rx86.py
   pypy/branch/jitypes2/pypy/jit/backend/x86/support.py
   pypy/branch/jitypes2/pypy/jit/backend/x86/test/test_assembler.py
   pypy/branch/jitypes2/pypy/jit/backend/x86/test/test_gc_integration.py
   pypy/branch/jitypes2/pypy/jit/backend/x86/test/test_regalloc.py
   pypy/branch/jitypes2/pypy/jit/backend/x86/test/test_regalloc2.py
   pypy/branch/jitypes2/pypy/jit/backend/x86/test/test_regloc.py
   pypy/branch/jitypes2/pypy/jit/backend/x86/test/test_runner.py
   pypy/branch/jitypes2/pypy/jit/backend/x86/test/test_rx86.py
   pypy/branch/jitypes2/pypy/jit/backend/x86/test/test_zll_random.py
   pypy/branch/jitypes2/pypy/jit/backend/x86/test/test_zmath.py
   pypy/branch/jitypes2/pypy/jit/backend/x86/valgrind.py
   pypy/branch/jitypes2/pypy/jit/codewriter/call.py
   pypy/branch/jitypes2/pypy/jit/codewriter/jtransform.py
   pypy/branch/jitypes2/pypy/jit/codewriter/support.py
   pypy/branch/jitypes2/pypy/jit/codewriter/test/test_codewriter.py
   pypy/branch/jitypes2/pypy/jit/codewriter/test/test_list.py
   pypy/branch/jitypes2/pypy/jit/codewriter/test/test_void_list.py
   pypy/branch/jitypes2/pypy/jit/conftest.py
   pypy/branch/jitypes2/pypy/jit/metainterp/compile.py
   pypy/branch/jitypes2/pypy/jit/metainterp/history.py
   pypy/branch/jitypes2/pypy/jit/metainterp/jitprof.py
   pypy/branch/jitypes2/pypy/jit/metainterp/optimizeopt/optimizer.py   (props changed)
   pypy/branch/jitypes2/pypy/jit/metainterp/pyjitpl.py
   pypy/branch/jitypes2/pypy/jit/metainterp/test/test_basic.py
   pypy/branch/jitypes2/pypy/jit/metainterp/test/test_compile.py
   pypy/branch/jitypes2/pypy/jit/metainterp/test/test_list.py
   pypy/branch/jitypes2/pypy/jit/metainterp/test/test_logger.py
   pypy/branch/jitypes2/pypy/jit/metainterp/test/test_optimizeopt.py
   pypy/branch/jitypes2/pypy/jit/metainterp/test/test_pyjitpl.py
   pypy/branch/jitypes2/pypy/jit/metainterp/test/test_recursive.py
   pypy/branch/jitypes2/pypy/jit/metainterp/test/test_virtualizable.py
   pypy/branch/jitypes2/pypy/jit/metainterp/test/test_warmspot.py
   pypy/branch/jitypes2/pypy/jit/metainterp/test/test_warmstate.py
   pypy/branch/jitypes2/pypy/jit/metainterp/warmspot.py
   pypy/branch/jitypes2/pypy/jit/metainterp/warmstate.py
   pypy/branch/jitypes2/pypy/jit/tl/spli/interpreter.py
   pypy/branch/jitypes2/pypy/jit/tl/tl.py
   pypy/branch/jitypes2/pypy/jit/tool/jitoutput.py
   pypy/branch/jitypes2/pypy/jit/tool/log-template.gnumeric
   pypy/branch/jitypes2/pypy/jit/tool/log2gnumeric.py
   pypy/branch/jitypes2/pypy/jit/tool/test/test_jitoutput.py
   pypy/branch/jitypes2/pypy/module/__pypy__/__init__.py
   pypy/branch/jitypes2/pypy/module/__pypy__/interp_magic.py
   pypy/branch/jitypes2/pypy/module/__pypy__/test/test_special.py
   pypy/branch/jitypes2/pypy/module/_minimal_curses/__init__.py
   pypy/branch/jitypes2/pypy/module/_pickle_support/maker.py
   pypy/branch/jitypes2/pypy/module/array/benchmark/Makefile   (props changed)
   pypy/branch/jitypes2/pypy/module/array/benchmark/intimg.c   (props changed)
   pypy/branch/jitypes2/pypy/module/array/benchmark/intimgtst.c   (props changed)
   pypy/branch/jitypes2/pypy/module/array/benchmark/intimgtst.py   (props changed)
   pypy/branch/jitypes2/pypy/module/array/benchmark/loop.c   (props changed)
   pypy/branch/jitypes2/pypy/module/array/benchmark/sum.c   (props changed)
   pypy/branch/jitypes2/pypy/module/array/benchmark/sumtst.c   (props changed)
   pypy/branch/jitypes2/pypy/module/array/benchmark/sumtst.py   (props changed)
   pypy/branch/jitypes2/pypy/module/array/test/test_array_old.py   (props changed)
   pypy/branch/jitypes2/pypy/module/binascii/test/   (props changed)
   pypy/branch/jitypes2/pypy/module/cpyext/api.py
   pypy/branch/jitypes2/pypy/module/cpyext/cdatetime.py
   pypy/branch/jitypes2/pypy/module/cpyext/include/tupleobject.h
   pypy/branch/jitypes2/pypy/module/cpyext/sequence.py
   pypy/branch/jitypes2/pypy/module/cpyext/slotdefs.py
   pypy/branch/jitypes2/pypy/module/cpyext/state.py
   pypy/branch/jitypes2/pypy/module/cpyext/stubs.py
   pypy/branch/jitypes2/pypy/module/cpyext/test/test_arraymodule.py
   pypy/branch/jitypes2/pypy/module/cpyext/test/test_cpyext.py
   pypy/branch/jitypes2/pypy/module/cpyext/test/test_datetime.py
   pypy/branch/jitypes2/pypy/module/cpyext/test/test_sequence.py
   pypy/branch/jitypes2/pypy/module/cpyext/test/test_tupleobject.py
   pypy/branch/jitypes2/pypy/module/cpyext/test/test_typeobject.py
   pypy/branch/jitypes2/pypy/module/cpyext/tupleobject.py
   pypy/branch/jitypes2/pypy/module/cpyext/typeobject.py
   pypy/branch/jitypes2/pypy/module/fcntl/test/test_fcntl.py
   pypy/branch/jitypes2/pypy/module/imp/importing.py
   pypy/branch/jitypes2/pypy/module/itertools/interp_itertools.py
   pypy/branch/jitypes2/pypy/module/posix/__init__.py
   pypy/branch/jitypes2/pypy/module/posix/interp_posix.py
   pypy/branch/jitypes2/pypy/module/posix/test/test_posix2.py
   pypy/branch/jitypes2/pypy/module/pyexpat/interp_pyexpat.py
   pypy/branch/jitypes2/pypy/module/pyexpat/test/test_parser.py
   pypy/branch/jitypes2/pypy/module/pypyjit/policy.py
   pypy/branch/jitypes2/pypy/module/pypyjit/test/test_policy.py
   pypy/branch/jitypes2/pypy/module/pypyjit/test/test_pypy_c.py
   pypy/branch/jitypes2/pypy/module/sys/__init__.py
   pypy/branch/jitypes2/pypy/module/test_lib_pypy/ctypes_tests/test_guess_argtypes.py
   pypy/branch/jitypes2/pypy/module/test_lib_pypy/ctypes_tests/test_keepalive.py
   pypy/branch/jitypes2/pypy/objspace/std/mapdict.py
   pypy/branch/jitypes2/pypy/objspace/std/objspace.py
   pypy/branch/jitypes2/pypy/rlib/debug.py
   pypy/branch/jitypes2/pypy/rlib/jit.py
   pypy/branch/jitypes2/pypy/rlib/libffi.py
   pypy/branch/jitypes2/pypy/rlib/rarithmetic.py
   pypy/branch/jitypes2/pypy/rlib/rdynload.py
   pypy/branch/jitypes2/pypy/rlib/rerased.py   (contents, props changed)
   pypy/branch/jitypes2/pypy/rlib/rsre/rsre_core.py
   pypy/branch/jitypes2/pypy/rlib/rsre/test/test_zjit.py
   pypy/branch/jitypes2/pypy/rlib/test/test_debug.py
   pypy/branch/jitypes2/pypy/rlib/test/test_libffi.py
   pypy/branch/jitypes2/pypy/rlib/test/test_rerased.py   (props changed)
   pypy/branch/jitypes2/pypy/rpython/extfunc.py
   pypy/branch/jitypes2/pypy/rpython/lltypesystem/ll2ctypes.py
   pypy/branch/jitypes2/pypy/rpython/lltypesystem/llmemory.py
   pypy/branch/jitypes2/pypy/rpython/lltypesystem/rbuiltin.py
   pypy/branch/jitypes2/pypy/rpython/lltypesystem/rclass.py
   pypy/branch/jitypes2/pypy/rpython/lltypesystem/rdict.py
   pypy/branch/jitypes2/pypy/rpython/lltypesystem/rpbc.py
   pypy/branch/jitypes2/pypy/rpython/memory/gc/base.py
   pypy/branch/jitypes2/pypy/rpython/memory/gc/generation.py
   pypy/branch/jitypes2/pypy/rpython/memory/gc/inspector.py
   pypy/branch/jitypes2/pypy/rpython/memory/gc/markcompact.py
   pypy/branch/jitypes2/pypy/rpython/memory/gc/minimark.py
   pypy/branch/jitypes2/pypy/rpython/memory/gc/semispace.py
   pypy/branch/jitypes2/pypy/rpython/memory/gc/test/test_direct.py
   pypy/branch/jitypes2/pypy/rpython/memory/gctransform/asmgcroot.py
   pypy/branch/jitypes2/pypy/rpython/memory/gctransform/boehm.py
   pypy/branch/jitypes2/pypy/rpython/memory/gctransform/framework.py
   pypy/branch/jitypes2/pypy/rpython/memory/gctransform/refcounting.py
   pypy/branch/jitypes2/pypy/rpython/memory/gctransform/support.py
   pypy/branch/jitypes2/pypy/rpython/module/ll_os.py
   pypy/branch/jitypes2/pypy/rpython/module/ll_time.py
   pypy/branch/jitypes2/pypy/rpython/ootypesystem/rpbc.py
   pypy/branch/jitypes2/pypy/rpython/rlist.py
   pypy/branch/jitypes2/pypy/rpython/rpbc.py
   pypy/branch/jitypes2/pypy/rpython/test/test_rclass.py
   pypy/branch/jitypes2/pypy/rpython/test/test_rint.py
   pypy/branch/jitypes2/pypy/rpython/test/test_rlist.py
   pypy/branch/jitypes2/pypy/rpython/tool/rffi_platform.py
   pypy/branch/jitypes2/pypy/tool/ansi_print.py
   pypy/branch/jitypes2/pypy/tool/logparser.py
   pypy/branch/jitypes2/pypy/translator/c/funcgen.py
   pypy/branch/jitypes2/pypy/translator/c/gcc/trackgcroot.py
   pypy/branch/jitypes2/pypy/translator/c/src/debug_alloc.h
   pypy/branch/jitypes2/pypy/translator/c/src/debug_print.h
   pypy/branch/jitypes2/pypy/translator/c/src/mem.h
   pypy/branch/jitypes2/pypy/translator/c/test/test_newgc.py
   pypy/branch/jitypes2/pypy/translator/c/test/test_standalone.py
   pypy/branch/jitypes2/pypy/translator/driver.py
   pypy/branch/jitypes2/pypy/translator/goal/app_main.py
   pypy/branch/jitypes2/pypy/translator/goal/test2/test_app_main.py
   pypy/branch/jitypes2/pypy/translator/platform/__init__.py
   pypy/branch/jitypes2/pypy/translator/platform/darwin.py
   pypy/branch/jitypes2/pypy/translator/tool/cbuild.py
   pypy/branch/jitypes2/pypy/translator/tool/reftracker.py
   pypy/branch/jitypes2/site-packages/   (props changed)
Log:
merge from trunk: svn merge http://codespeak.net/svn/pypy/trunk -r79389:HEAD

in particular, this merges the _ctypes changes that amaury did on the
fast-forward branch and then merged on trunk



Modified: pypy/branch/jitypes2/ctypes_configure/configure.py
==============================================================================
--- pypy/branch/jitypes2/ctypes_configure/configure.py	(original)
+++ pypy/branch/jitypes2/ctypes_configure/configure.py	Fri Dec  3 11:04:29 2010
@@ -559,6 +559,7 @@
 C_HEADER = """
 #include <stdio.h>
 #include <stddef.h>   /* for offsetof() */
+#include <stdint.h>   /* FreeBSD: for uint64_t */
 
 void dump(char* key, int value) {
     printf("%s: %d\\n", key, value);

Modified: pypy/branch/jitypes2/lib-python/conftest.py
==============================================================================
--- pypy/branch/jitypes2/lib-python/conftest.py	(original)
+++ pypy/branch/jitypes2/lib-python/conftest.py	Fri Dec  3 11:04:29 2010
@@ -139,7 +139,7 @@
     RegrTest('test_augassign.py', core=True),
     RegrTest('test_base64.py'),
     RegrTest('test_bastion.py'),
-    RegrTest('test_binascii.py'),
+    RegrTest('test_binascii.py', usemodules='binascii'),
 
     RegrTest('test_binhex.py'),
 

Modified: pypy/branch/jitypes2/lib-python/modified-2.5.2/distutils/msvccompiler.py
==============================================================================
--- pypy/branch/jitypes2/lib-python/modified-2.5.2/distutils/msvccompiler.py	(original)
+++ pypy/branch/jitypes2/lib-python/modified-2.5.2/distutils/msvccompiler.py	Fri Dec  3 11:04:29 2010
@@ -25,17 +25,20 @@
 from distutils import log
 from distutils.util import get_platform
 
-import _winreg
-
-RegOpenKeyEx = _winreg.OpenKeyEx
-RegEnumKey = _winreg.EnumKey
-RegEnumValue = _winreg.EnumValue
-RegError = _winreg.error
-
-HKEYS = (_winreg.HKEY_USERS,
-         _winreg.HKEY_CURRENT_USER,
-         _winreg.HKEY_LOCAL_MACHINE,
-         _winreg.HKEY_CLASSES_ROOT)
+try:
+    import _winreg
+except ImportError:
+    pass
+else:
+    RegOpenKeyEx = _winreg.OpenKeyEx
+    RegEnumKey = _winreg.EnumKey
+    RegEnumValue = _winreg.EnumValue
+    RegError = _winreg.error
+
+    HKEYS = (_winreg.HKEY_USERS,
+             _winreg.HKEY_CURRENT_USER,
+             _winreg.HKEY_LOCAL_MACHINE,
+             _winreg.HKEY_CLASSES_ROOT)
 
 VS_BASE = r"Software\Microsoft\VisualStudio\%0.1f"
 VSEXPRESS_BASE = r"Software\Microsoft\VCExpress\%0.1f"

Modified: pypy/branch/jitypes2/lib-python/modified-2.5.2/distutils/tests/test_msvccompiler.py
==============================================================================
--- pypy/branch/jitypes2/lib-python/modified-2.5.2/distutils/tests/test_msvccompiler.py	(original)
+++ pypy/branch/jitypes2/lib-python/modified-2.5.2/distutils/tests/test_msvccompiler.py	Fri Dec  3 11:04:29 2010
@@ -11,11 +11,15 @@
         else:
             self.fail("could not find a suitable manifest")
 
+class MsvcCompilerSimplerTestCase(unittest.TestCase):
+    def test_import_module(self):
+        from distutils.msvccompiler import MSVCCompiler
+
 def test_suite():
     if sys.platform == 'win32':
         return unittest.makeSuite(MsvcCompilerTestCase)
     else:
-        return unittest.TestSuite([])
+        return unittest.makeSuite(MsvcCompilerSimplerTestCase)
 
 if __name__ == "__main__":
     unittest.main(defaultTest="test_suite")

Modified: pypy/branch/jitypes2/lib_pypy/_ctypes/array.py
==============================================================================
--- pypy/branch/jitypes2/lib_pypy/_ctypes/array.py	(original)
+++ pypy/branch/jitypes2/lib_pypy/_ctypes/array.py	Fri Dec  3 11:04:29 2010
@@ -99,6 +99,9 @@
                 if len(value) > self._length_:
                     raise ValueError("Invalid length")
                 value = self(*value)
+            elif not isinstance(value, self):
+                raise TypeError("expected string or Unicode object, %s found"
+                                % (value.__class__.__name__,))
         else:
             if isinstance(value, tuple):
                 if len(value) > self._length_:
@@ -107,22 +110,43 @@
         return _CDataMeta.from_param(self, value)
 
 def array_get_slice_params(self, index):
-    if index.step is not None:
-        raise TypeError("3 arg slices not supported (for no reason)")
-    start = index.start or 0
-    stop = index.stop or self._length_
-    return start, stop
+    if hasattr(self, '_length_'):
+        start, stop, step = index.indices(self._length_)
+    else:
+        step = index.step
+        if step is None:
+            step = 1
+        start = index.start
+        stop = index.stop
+        if start is None:
+            if step > 0:
+                start = 0
+            else:
+                raise ValueError("slice start is required for step < 0")
+        if stop is None:
+            raise ValueError("slice stop is required")
+
+    return start, stop, step
 
 def array_slice_setitem(self, index, value):
-    start, stop = self._get_slice_params(index)
-    if stop - start != len(value):
+    start, stop, step = self._get_slice_params(index)
+
+    if ((step < 0 and stop >= start) or
+        (step > 0 and start >= stop)):
+        slicelength = 0
+    elif step < 0:
+        slicelength = (stop - start + 1) / step + 1
+    else:
+        slicelength = (stop - start - 1) / step + 1;
+
+    if slicelength != len(value):
         raise ValueError("Can only assign slices of the same length")
-    for i in range(start, stop):
-        self[i] = value[i - start]
+    for i, j in enumerate(range(start, stop, step)):
+        self[j] = value[i]
 
 def array_slice_getitem(self, index):
-    start, stop = self._get_slice_params(index)
-    l = [self[i] for i in range(start, stop)]
+    start, stop, step = self._get_slice_params(index)
+    l = [self[i] for i in range(start, stop, step)]
     letter = getattr(self._type_, '_type_', None)
     if letter == 'c':
         return "".join(l)
@@ -135,7 +159,8 @@
     _ffiargshape = 'P'
 
     def __init__(self, *args):
-        self._buffer = self._ffiarray(self._length_, autofree=True)
+        if not hasattr(self, '_buffer'):
+            self._buffer = self._ffiarray(self._length_, autofree=True)
         for i, arg in enumerate(args):
             self[i] = arg
 
@@ -162,9 +187,10 @@
             self._slice_setitem(index, value)
             return
         index = self._fix_index(index)
-        if ensure_objects(value) is not None:
-            store_reference(self, index, value._objects)
-        arg = self._type_._CData_value(value)
+        cobj = self._type_.from_param(value)
+        if ensure_objects(cobj) is not None:
+            store_reference(self, index, cobj._objects)
+        arg = cobj._get_buffer_value()
         if self._type_._fficompositesize is None:
             self._buffer[index] = arg
             # something more sophisticated, cannot set field directly
@@ -183,7 +209,7 @@
         return self._length_
 
     def _get_buffer_for_param(self):
-        return CArgObject(self._buffer.byptr())
+        return CArgObject(self, self._buffer.byptr())
 
     def _get_buffer_value(self):
         return self._buffer.buffer

Modified: pypy/branch/jitypes2/lib_pypy/_ctypes/basics.py
==============================================================================
--- pypy/branch/jitypes2/lib_pypy/_ctypes/basics.py	(original)
+++ pypy/branch/jitypes2/lib_pypy/_ctypes/basics.py	Fri Dec  3 11:04:29 2010
@@ -46,21 +46,6 @@
         else:
             return self.from_param(as_parameter)
 
-    def _CData_input(self, value):
-        """Used when data enters into ctypes from user code.  'value' is
-        some user-specified Python object, which is converted into a _rawffi
-        array of length 1 containing the same value according to the
-        type 'self'.
-        """
-        cobj = self.from_param(value)
-        return cobj, cobj._get_buffer_for_param()
-
-    def _CData_value(self, value):
-        cobj = self.from_param(value)
-        # we don't care here if this stuff will live afterwards, as we're
-        # interested only in value anyway
-        return cobj._get_buffer_value()
-
     def _CData_output(self, resbuffer, base=None, index=-1):
         #assert isinstance(resbuffer, _rawffi.ArrayInstance)
         """Used when data exits ctypes and goes into user code.
@@ -92,13 +77,23 @@
     """ simple wrapper around buffer, just for the case of freeing
     it afterwards
     """
-    def __init__(self, buffer):
+    def __init__(self, obj, buffer):
+        self._obj = obj
         self._buffer = buffer
 
     def __del__(self):
         self._buffer.free()
         self._buffer = None
 
+    def __repr__(self):
+        return '<CArgObject %r>' % (self._obj,)
+
+    def __eq__(self, other):
+        return self._obj == other
+
+    def __ne__(self, other):
+        return self._obj != other
+
 class _CData(object):
     """ The most basic object for all ctypes types
     """
@@ -128,7 +123,7 @@
         return buffer(self._buffer)
 
     def _get_b_base(self):
-        return self._objects
+        return self._base
     _b_base_ = property(_get_b_base)
     _b_needsfree_ = False
 

Modified: pypy/branch/jitypes2/lib_pypy/_ctypes/builtin.py
==============================================================================
--- pypy/branch/jitypes2/lib_pypy/_ctypes/builtin.py	(original)
+++ pypy/branch/jitypes2/lib_pypy/_ctypes/builtin.py	Fri Dec  3 11:04:29 2010
@@ -11,7 +11,8 @@
 def _string_at(addr, lgt):
     # address here can be almost anything
     import ctypes
-    arg = ctypes.c_void_p._CData_value(addr)
+    cobj = ctypes.c_void_p.from_param(addr)
+    arg = cobj._get_buffer_value()
     return _rawffi.charp2rawstring(arg, lgt)
 
 def set_conversion_mode(encoding, errors):
@@ -22,7 +23,8 @@
 
 def _wstring_at(addr, lgt):
     import ctypes
-    arg = ctypes.c_void_p._CData_value(addr)
+    cobj = ctypes.c_void_p.from_param(addr)
+    arg = cobj._get_buffer_value()
     # XXX purely applevel
     if lgt == -1:
         lgt = sys.maxint

Modified: pypy/branch/jitypes2/lib_pypy/_ctypes/function.py
==============================================================================
--- pypy/branch/jitypes2/lib_pypy/_ctypes/function.py	(original)
+++ pypy/branch/jitypes2/lib_pypy/_ctypes/function.py	Fri Dec  3 11:04:29 2010
@@ -36,6 +36,7 @@
 
     _argtypes_ = None
     _restype_ = None
+    _errcheck_ = None
     _flags_ = 0
     _ffiargshape = 'P'
     _ffishape = 'P'
@@ -54,7 +55,15 @@
         return self._argtypes_
     def _setargtypes(self, argtypes):
         self._ptr = None
-        self._argtypes_ = argtypes    
+        if argtypes is None:
+            self._argtypes_ = None
+        else:
+            for i, argtype in enumerate(argtypes):
+                if not hasattr(argtype, 'from_param'):
+                    raise TypeError(
+                        "item %d in _argtypes_ has no from_param method" % (
+                            i + 1,))
+            self._argtypes_ = argtypes
     argtypes = property(_getargtypes, _setargtypes)
 
     def _getrestype(self):
@@ -73,9 +82,24 @@
         del self._restype_
     restype = property(_getrestype, _setrestype, _delrestype)
 
+    def _geterrcheck(self):
+        return getattr(self, '_errcheck_', None)
+    def _seterrcheck(self, errcheck):
+        if not callable(errcheck):
+            raise TypeError("The errcheck attribute must be callable")
+        self._errcheck_ = errcheck
+    def _delerrcheck(self):
+        try:
+            del self._errcheck_
+        except AttributeError:
+            pass
+    errcheck = property(_geterrcheck, _seterrcheck, _delerrcheck)
+
     def _ffishapes(self, args, restype):
         argtypes = [arg._ffiargshape for arg in args]
         if restype is not None:
+            if not isinstance(restype, _CDataMeta):
+                raise TypeError("invalid result type for callback function")
             restype = restype._ffiargshape
         else:
             restype = 'O' # void
@@ -143,6 +167,7 @@
     def __call__(self, *args):
         if self.callable is not None:
             assert False, 'TODO1'
+            args = args[:len(self._argtypes_)]
             try:
                 res = self.callable(*args)
             except:
@@ -166,19 +191,30 @@
             thisarg = None
             
         if argtypes is None:
-            assert False, 'TODO3'
-            argtypes = self._guess_argtypes(args)
-
-        # XXX
-        argtypes, argsandobjs = self._wrap_args(argtypes, args)
-        newargs = self._unwrap_args(argtypes, argsandobjs)
+            argtypes = []
+        args = self._convert_args(argtypes, args)
+        argtypes = [type(arg) for arg in args]
+        newargs = self._unwrap_args(argtypes, args)
 
-        
         restype = self._restype_
         funcptr = self._getfuncptr(argtypes, restype, thisarg)
-        return funcptr(*newargs)
-        #resbuffer = funcptr(*[arg._buffer for _, arg in argsandobjs])
-        #return self._build_result(restype, resbuffer, argtypes, argsandobjs)
+        result = funcptr(*newargs)
+        ## resbuffer = funcptr(*[arg._get_buffer_for_param()._buffer
+        ##                       for arg in args])
+        ## result = self._build_result(restype, resbuffer, argtypes, args)
+
+        # The 'errcheck' protocol
+        if self._errcheck_:
+            v = self._errcheck_(result, self, args)
+            # If the errcheck funtion failed, let it throw
+            # If the errcheck function returned callargs unchanged,
+            # continue normal processing.
+            # If the errcheck function returned something else,
+            # use that as result.
+            if v is not args:
+                result = v
+
+        return result
 
     # XXX: maybe move this to _ffi
     from _ffi import types
@@ -212,6 +248,7 @@
             print 'unknown shape %s' % shape
             assert False, 'TODO5'
 
+
     def _getfuncptr(self, argtypes, restype, thisarg=None):
         if self._ptr is not None and argtypes is self._argtypes_:
             return self._ptr
@@ -258,31 +295,33 @@
             raise
 
     @staticmethod
-    def _guess_argtypes(args):
+    def _conv_param(argtype, arg, index):
         from ctypes import c_char_p, c_wchar_p, c_void_p, c_int
-        res = []
-        for arg in args:
-            if hasattr(arg, '_as_parameter_'):
-                arg = arg._as_parameter_
-            if isinstance(arg, str):
-                res.append(c_char_p)
-            elif isinstance(arg, unicode):
-                res.append(c_wchar_p)
-            elif isinstance(arg, _CData):
-                res.append(type(arg))
-            elif arg is None:
-                res.append(c_void_p)
-            #elif arg == 0:
-            #    res.append(c_void_p)
-            elif isinstance(arg, (int, long)):
-                res.append(c_int)
-            else:
-                raise TypeError("Don't know how to handle %s" % (arg,))
-        return res
+        if argtype is not None:
+            arg = argtype.from_param(arg)
+        if hasattr(arg, '_as_parameter_'):
+            arg = arg._as_parameter_
+
+        if isinstance(arg, _CData):
+            # The usual case when argtype is defined
+            cobj = arg
+        elif isinstance(arg, str):
+            cobj = c_char_p(arg)
+        elif isinstance(arg, unicode):
+            cobj = c_wchar_p(arg)
+        elif arg is None:
+            cobj = c_void_p()
+        elif isinstance(arg, (int, long)):
+            cobj = c_int(arg)
+        else:
+            raise TypeError("Don't know how to handle %s" % (arg,))
+
+        return cobj
 
-    def _wrap_args(self, argtypes, args):
+    def _convert_args(self, argtypes, args):
         wrapped_args = []
         consumed = 0
+
         for i, argtype in enumerate(argtypes):
             defaultvalue = None
             if i > 0 and self._paramflags is not None:
@@ -309,7 +348,7 @@
                     val = defaultvalue
                     if val is None:
                         val = 0
-                    wrapped = argtype._CData_input(val)
+                    wrapped = self._conv_param(argtype, val, consumed)
                     wrapped_args.append(wrapped)
                     continue
                 else:
@@ -324,28 +363,27 @@
                 raise TypeError("Not enough arguments")
 
             try:
-                wrapped = argtype._CData_input(arg)
-            except (UnicodeError, TypeError), e:
+                wrapped = self._conv_param(argtype, arg, consumed)
+            except (UnicodeError, TypeError, ValueError), e:
                 raise ArgumentError(str(e))
             wrapped_args.append(wrapped)
             consumed += 1
 
         if len(wrapped_args) < len(args):
             extra = args[len(wrapped_args):]
-            extra_types = self._guess_argtypes(extra)
-            for arg, argtype in zip(extra, extra_types):
+            argtypes = list(argtypes)
+            for i, arg in enumerate(extra):
                 try:
-                    wrapped = argtype._CData_input(arg)
-                except (UnicodeError, TypeError), e:
+                    wrapped = self._conv_param(None, arg, i)
+                except (UnicodeError, TypeError, ValueError), e:
                     raise ArgumentError(str(e))
                 wrapped_args.append(wrapped)
-            argtypes = list(argtypes) + extra_types
-        return argtypes, wrapped_args
+        return wrapped_args
 
-    def _unwrap_args(self, argtypes, argsandobjs):
-        assert len(argtypes) == len(argsandobjs)
+    def _unwrap_args(self, argtypes, args):
+        assert len(argtypes) == len(args)
         newargs = []
-        for argtype, (_, arg) in zip(argtypes, argsandobjs):
+        for argtype, arg in zip(argtypes, args):
             value = arg.value
             if isinstance(value, basestring) and len(value) == 1:
                 # XXX: who should do this conversion? Maybe _ffi?
@@ -364,7 +402,7 @@
         if self._com_index:
             if resbuffer[0] & 0x80000000:
                 raise get_com_error(resbuffer[0],
-                                    self._com_iid, argsandobjs[0][0])
+                                    self._com_iid, argsandobjs[0])
             else:
                 retval = int(resbuffer[0])
         elif restype is not None:
@@ -383,8 +421,8 @@
 
         results = []
         if self._paramflags:
-            for argtype, (obj, _), paramflag in zip(argtypes[1:], argsandobjs[1:],
-                                                    self._paramflags):
+            for argtype, obj, paramflag in zip(argtypes[1:], argsandobjs[1:],
+                                               self._paramflags):
                 if len(paramflag) == 2:
                     idlflag, name = paramflag
                 elif len(paramflag) == 3:

Modified: pypy/branch/jitypes2/lib_pypy/_ctypes/pointer.py
==============================================================================
--- pypy/branch/jitypes2/lib_pypy/_ctypes/pointer.py	(original)
+++ pypy/branch/jitypes2/lib_pypy/_ctypes/pointer.py	Fri Dec  3 11:04:29 2010
@@ -1,7 +1,8 @@
 
 import _rawffi
 from _ctypes.basics import _CData, _CDataMeta, cdata_from_address
-from _ctypes.basics import sizeof, byref, keepalive_key
+from _ctypes.basics import keepalive_key, store_reference, ensure_objects
+from _ctypes.basics import sizeof, byref
 from _ctypes.array import Array, array_get_slice_params, array_slice_getitem,\
      array_slice_setitem
 
@@ -55,7 +56,8 @@
     def set_type(self, TP):
         ffiarray = _rawffi.Array('P')
         def __init__(self, value=None):
-            self._buffer = ffiarray(1, autofree=True)
+            if not hasattr(self, '_buffer'):
+                self._buffer = ffiarray(1, autofree=True)
             if value is not None:
                 self.contents = value
         self._ffiarray = ffiarray
@@ -99,7 +101,10 @@
         return self._type_._CData_output(self._subarray(index), self, index)
 
     def __setitem__(self, index, value):
-        self._subarray(index)[0] = self._type_._CData_value(value)
+        cobj = self._type_.from_param(value)
+        if ensure_objects(cobj) is not None:
+            store_reference(self, index, cobj._objects)
+        self._subarray(index)[0] = cobj._get_buffer_value()
 
     def __nonzero__(self):
         return self._buffer[0] != 0
@@ -110,29 +115,32 @@
     if not (isinstance(tp, _CDataMeta) and tp._is_pointer_like()):
         raise TypeError("cast() argument 2 must be a pointer type, not %s"
                         % (tp,))
-    if isinstance(obj, Array):
-        ptr = tp.__new__(tp)
-        ptr._buffer = tp._ffiarray(1, autofree=True)
-        ptr._buffer[0] = obj._buffer
-        return ptr
     if isinstance(obj, (int, long)):
         result = tp()
         result._buffer[0] = obj
         return result
-    if obj is None:
+    elif obj is None:
         result = tp()
         return result
-    if not (isinstance(obj, _CData) and type(obj)._is_pointer_like()):
+    elif isinstance(obj, Array):
+        ptr = tp.__new__(tp)
+        ptr._buffer = tp._ffiarray(1, autofree=True)
+        ptr._buffer[0] = obj._buffer
+        result = ptr
+    elif not (isinstance(obj, _CData) and type(obj)._is_pointer_like()):
         raise TypeError("cast() argument 1 must be a pointer, not %s"
                         % (type(obj),))
-    result = tp()
+    else:
+        result = tp()
+        result._buffer[0] = obj._buffer[0]
 
     # The casted objects '_objects' member:
-    # It must certainly contain the source objects one.
+    # From now on, both objects will use the same dictionary
+    # It must certainly contain the source objects
     # It must contain the source object itself.
     if obj._ensure_objects() is not None:
-        result._objects = {keepalive_key(0): obj._objects,
-                           keepalive_key(1): obj}
+        result._objects = obj._objects
+        if isinstance(obj._objects, dict):
+            result._objects[id(obj)] =  obj
 
-    result._buffer[0] = obj._buffer[0]
     return result

Modified: pypy/branch/jitypes2/lib_pypy/_ctypes/primitive.py
==============================================================================
--- pypy/branch/jitypes2/lib_pypy/_ctypes/primitive.py	(original)
+++ pypy/branch/jitypes2/lib_pypy/_ctypes/primitive.py	Fri Dec  3 11:04:29 2010
@@ -132,8 +132,8 @@
                                              ConvMode.errors)
                     #self._objects = value
                     array = _rawffi.Array('c')(len(value)+1, value)
+                    self._objects = CArgObject(value, array)
                     value = array.buffer
-                    self._objects = {'0': CArgObject(array)}
                 elif value is None:
                     value = 0
                 self._buffer[0] = value
@@ -155,8 +155,8 @@
                                              ConvMode.errors)
                     #self._objects = value
                     array = _rawffi.Array('u')(len(value)+1, value)
+                    self._objects = CArgObject(value, array)
                     value = array.buffer
-                    self._objects = {'0': CArgObject(array)}
                 elif value is None:
                     value = 0
                 self._buffer[0] = value
@@ -174,8 +174,8 @@
             def _setvalue(self, value):
                 if isinstance(value, str):
                     array = _rawffi.Array('c')(len(value)+1, value)
+                    self._objects = CArgObject(value, array)
                     value = array.buffer
-                    self._objects = {'0': CArgObject(array)}
                 elif value is None:
                     value = 0
                 self._buffer[0] = value
@@ -271,7 +271,9 @@
 
     def _CData_output(self, resbuffer, base=None, index=-1):
         output = super(SimpleType, self)._CData_output(resbuffer, base, index)
-        return output.value
+        if self.__bases__[0] is _SimpleCData:
+            return output.value
+        return output
     
     def _sizeofinstances(self):
         return _rawffi.sizeof(self._type_)
@@ -287,7 +289,8 @@
     _type_ = 'i'
 
     def __init__(self, value=DEFAULT_VALUE):
-        self._buffer = self._ffiarray(1, autofree=True)
+        if not hasattr(self, '_buffer'):
+            self._buffer = self._ffiarray(1, autofree=True)
         if value is not DEFAULT_VALUE:
             self.value = value
 
@@ -312,7 +315,11 @@
         return self.value
 
     def __repr__(self):
-        return "%s(%r)" % (type(self).__name__, self.value)
+        if type(self).__bases__[0] is _SimpleCData:
+            return "%s(%r)" % (type(self).__name__, self.value)
+        else:
+            return "<%s object at 0x%x>" % (type(self).__name__,
+                                            id(self))
 
     def __nonzero__(self):
         return self._buffer[0] not in (0, '\x00')

Modified: pypy/branch/jitypes2/lib_pypy/_ctypes/structure.py
==============================================================================
--- pypy/branch/jitypes2/lib_pypy/_ctypes/structure.py	(original)
+++ pypy/branch/jitypes2/lib_pypy/_ctypes/structure.py	Fri Dec  3 11:04:29 2010
@@ -34,9 +34,11 @@
         if not isinstance(tp, _CDataMeta):
             raise TypeError("Expected CData subclass, got %s" % (tp,))
     import ctypes
-    all_fields = _fields_[:]
-    for cls in inspect.getmro(superclass):
-        all_fields += getattr(cls, '_fields_', [])
+    all_fields = []
+    for cls in reversed(inspect.getmro(superclass)):
+        # The first field comes from the most base class
+        all_fields.extend(getattr(cls, '_fields_', []))
+    all_fields.extend(_fields_)
     names = [name for name, ctype in all_fields]
     rawfields = [(name, ctype._ffishape)
                  for name, ctype in all_fields]
@@ -168,7 +170,7 @@
 
     def __init__(self, *args, **kwds):
         if len(args) > len(self._names):
-            raise TypeError("too many arguments")
+            raise TypeError("too many initializers")
         for name, arg in zip(self._names, args):
             if name in kwds:
                 raise TypeError("duplicate value for argument %r" % (

Modified: pypy/branch/jitypes2/lib_pypy/_hashlib.py
==============================================================================
--- pypy/branch/jitypes2/lib_pypy/_hashlib.py	(original)
+++ pypy/branch/jitypes2/lib_pypy/_hashlib.py	Fri Dec  3 11:04:29 2010
@@ -148,21 +148,29 @@
     return hash(ctx, name)
 
 # shortcut functions
+try: from __pypy__ import builtinify
+except ImportError: builtinify = lambda f: f
+
+ at builtinify
 def openssl_md5(string=''):
     return new('md5', string)
 
+ at builtinify
 def openssl_sha1(string=''):
     return new('sha1', string)
 
+ at builtinify
 def openssl_sha224(string=''):
     return new('sha224', string)
 
+ at builtinify
 def openssl_sha256(string=''):
     return new('sha256', string)
 
+ at builtinify
 def openssl_sha384(string=''):
     return new('sha384', string)
 
+ at builtinify
 def openssl_sha512(string=''):
     return new('sha512', string)
-

Modified: pypy/branch/jitypes2/lib_pypy/_locale.py
==============================================================================
--- pypy/branch/jitypes2/lib_pypy/_locale.py	(original)
+++ pypy/branch/jitypes2/lib_pypy/_locale.py	Fri Dec  3 11:04:29 2010
@@ -11,6 +11,9 @@
 # load the platform-specific cache made by running locale.ctc.py
 from ctypes_config_cache._locale_cache import *
 
+try: from __pypy__ import builtinify
+except ImportError: builtinify = lambda f: f
+
 
 # Ubuntu Gusty i386 structure
 class lconv(Structure):
@@ -158,6 +161,7 @@
     ul = ''.join(ul)
     string.letters = ul
 
+ at builtinify
 def setlocale(category, locale=None):
     "(integer,string=None) -> string. Activates/queries locale processing."
     if locale:
@@ -182,6 +186,7 @@
         groups.append(0)
     return groups
 
+ at builtinify
 def localeconv():
     "() -> dict. Returns numeric and monetary locale-specific parameters."
 
@@ -215,6 +220,7 @@
     }
     return result
 
+ at builtinify
 def strcoll(s1, s2):
     "string,string -> int. Compares two strings according to the locale."
 
@@ -233,6 +239,7 @@
     # Collate the strings.
     return _wcscoll(s1, s2)
 
+ at builtinify
 def strxfrm(s):
     "string -> string. Returns a string that behaves for cmp locale-aware."
 
@@ -246,6 +253,7 @@
         _strxfrm(buf, s, n2)
     return buf.value
 
+ at builtinify
 def getdefaultlocale():
     # TODO: Port code from CPython for Windows and Mac OS
     raise NotImplementedError()
@@ -267,26 +275,31 @@
         raise ValueError("unsupported langinfo constant")
 
 if HAS_LIBINTL:
+    @builtinify
     def gettext(msg):
         """gettext(msg) -> string
         Return translation of msg."""
         return _gettext(msg)
 
+    @builtinify
     def dgettext(domain, msg):
         """dgettext(domain, msg) -> string
         Return translation of msg in domain."""
         return _dgettext(domain, msg)
 
+    @builtinify
     def dcgettext(domain, msg, category):
         """dcgettext(domain, msg, category) -> string
         Return translation of msg in domain and category."""
         return _dcgettext(domain, msg, category)
 
+    @builtinify
     def textdomain(domain):
         """textdomain(domain) -> string
         Set the C library's textdomain to domain, returning the new domain."""
         return _textdomain(domain)
 
+    @builtinify
     def bindtextdomain(domain, dir):
         """bindtextdomain(domain, dir) -> string
         Bind the C library's domain to dir."""
@@ -297,6 +310,7 @@
         return dirname
 
     if HAS_BIND_TEXTDOMAIN_CODESET:
+        @builtinify
         def bind_textdomain_codeset(domain, codeset):
             """bind_textdomain_codeset(domain, codeset) -> string
             Bind the C library's domain to codeset."""

Modified: pypy/branch/jitypes2/lib_pypy/_marshal.py
==============================================================================
--- pypy/branch/jitypes2/lib_pypy/_marshal.py	(original)
+++ pypy/branch/jitypes2/lib_pypy/_marshal.py	Fri Dec  3 11:04:29 2010
@@ -6,6 +6,10 @@
 import types
 from _codecs import utf_8_decode, utf_8_encode
 
+try: from __pypy__ import builtinify
+except ImportError: builtinify = lambda f: f
+
+
 TYPE_NULL     = '0'
 TYPE_NONE     = 'N'
 TYPE_FALSE    = 'F'
@@ -645,15 +649,18 @@
 
 version = 1
 
+ at builtinify
 def dump(x, f, version=version):
     # XXX 'version' is ignored, we always dump in a version-0-compatible format
     m = _Marshaller(f.write)
     m.dump(x)
 
+ at builtinify
 def load(f):
     um = _Unmarshaller(f.read)
     return um.load()
 
+ at builtinify
 def dumps(x, version=version):
     # XXX 'version' is ignored, we always dump in a version-0-compatible format
     buffer = []
@@ -661,6 +668,7 @@
     m.dump(x)
     return ''.join(buffer)
 
+ at builtinify
 def loads(s):
     um = _FastUnmarshaller(s)
     return um.load()

Modified: pypy/branch/jitypes2/lib_pypy/_minimal_curses.py
==============================================================================
--- pypy/branch/jitypes2/lib_pypy/_minimal_curses.py	(original)
+++ pypy/branch/jitypes2/lib_pypy/_minimal_curses.py	Fri Dec  3 11:04:29 2010
@@ -35,18 +35,24 @@
 
 # ____________________________________________________________
 
+try: from __pypy__ import builtinify
+except ImportError: builtinify = lambda f: f
+
+ at builtinify
 def setupterm(termstr, fd):
     err = ctypes.c_int(0)
     result = clib.setupterm(termstr, fd, ctypes.byref(err))
     if result == ERR:
         raise error("setupterm() failed (err=%d)" % err.value)
 
+ at builtinify
 def tigetstr(cap):
     result = clib.tigetstr(cap)
     if ctypes.cast(result, ctypes.c_void_p).value == ERR:
         return None
     return ctypes.cast(result, ctypes.c_char_p).value
 
+ at builtinify
 def tparm(str, i1=0, i2=0, i3=0, i4=0, i5=0, i6=0, i7=0, i8=0, i9=0):
     result = clib.tparm(str, i1, i2, i3, i4, i5, i6, i7, i8, i9)
     if result is None:

Modified: pypy/branch/jitypes2/lib_pypy/_pypy_interact.py
==============================================================================
--- pypy/branch/jitypes2/lib_pypy/_pypy_interact.py	(original)
+++ pypy/branch/jitypes2/lib_pypy/_pypy_interact.py	Fri Dec  3 11:04:29 2010
@@ -4,6 +4,13 @@
 
 
 def interactive_console(mainmodule=None):
+    # set sys.{ps1,ps2} just before invoking the interactive interpreter. This
+    # mimics what CPython does in pythonrun.c
+    if not hasattr(sys, 'ps1'):
+        sys.ps1 = '>>>> '
+    if not hasattr(sys, 'ps2'):
+        sys.ps2 = '.... '
+    #
     try:
         from _pypy_irc_topic import some_topic
         text = "And now for something completely different: ``%s''" % (
@@ -15,6 +22,7 @@
         print text
     except ImportError:
         pass
+    #
     try:
         from pyrepl.simple_interact import check
         if not check():

Modified: pypy/branch/jitypes2/lib_pypy/binascii.py
==============================================================================
--- pypy/branch/jitypes2/lib_pypy/binascii.py	(original)
+++ pypy/branch/jitypes2/lib_pypy/binascii.py	Fri Dec  3 11:04:29 2010
@@ -1,3 +1,9 @@
+"""A pure Python implementation of binascii.
+
+Rather slow and buggy in corner cases.
+PyPy provides an RPython version too.
+"""
+
 class Error(Exception):
     pass
 
@@ -277,7 +283,7 @@
         if (c > '~' or
             c == '=' or
             (header and c == '_') or
-            (c == '.' and linelen == 0 and (inp == len(data) or
+            (c == '.' and linelen == 0 and (inp+1 == len(data) or
                                             data[inp+1] == '\n' or
                                             data[inp+1] == '\r')) or
             (not istext and (c == '\r' or c == '\n')) or

Modified: pypy/branch/jitypes2/lib_pypy/cPickle.py
==============================================================================
--- pypy/branch/jitypes2/lib_pypy/cPickle.py	(original)
+++ pypy/branch/jitypes2/lib_pypy/cPickle.py	Fri Dec  3 11:04:29 2010
@@ -5,6 +5,10 @@
 from pickle import *
 from pickle import __doc__, __version__, format_version, compatible_formats
 
+try: from __pypy__ import builtinify
+except ImportError: builtinify = lambda f: f
+
+
 BadPickleGet = KeyError
 UnpickleableError = PicklingError
 
@@ -31,9 +35,11 @@
     def getvalue(self):
         return self.__f and self.__f.getvalue()
 
+ at builtinify
 def dump(obj, file, protocol=None):
     Pickler(file, protocol).dump(obj)
 
+ at builtinify
 def dumps(obj, protocol=None):
     file = StringIO()
     Pickler(file, protocol).dump(obj)

Modified: pypy/branch/jitypes2/lib_pypy/cmath.py
==============================================================================
--- pypy/branch/jitypes2/lib_pypy/cmath.py	(original)
+++ pypy/branch/jitypes2/lib_pypy/cmath.py	Fri Dec  3 11:04:29 2010
@@ -7,7 +7,10 @@
 
 import math
 from math import e, pi
-        
+
+try: from __pypy__ import builtinify
+except ImportError: builtinify = lambda f: f
+
 
 # constants
 _one = complex(1., 0.)
@@ -24,6 +27,7 @@
     return complex(real, imag)
 
 
+ at builtinify
 def acos(x):
     """acos(x)
 
@@ -32,6 +36,7 @@
     return -(_prodi(log((x+(_i*sqrt((_one-(x*x))))))))
 
 
+ at builtinify
 def acosh(x):
     """acosh(x)
 
@@ -41,6 +46,7 @@
     return z+z
 
 
+ at builtinify
 def asin(x):
     """asin(x)
 
@@ -52,6 +58,7 @@
     return -(_prodi(log((sqrt_1_minus_x_sq+_prodi(x)))))
 
 
+ at builtinify
 def asinh(x):
     """asinh(x)
 
@@ -61,6 +68,7 @@
     return z+z
 
 
+ at builtinify
 def atan(x):
     """atan(x)
     
@@ -69,6 +77,7 @@
     return _halfi*log(((_i+x)/(_i-x)))
 
 
+ at builtinify
 def atanh(x):
     """atanh(x)
 
@@ -77,6 +86,7 @@
     return _half*log((_one+x)/(_one-x))
 
 
+ at builtinify
 def cos(x):
     """cos(x)
 
@@ -88,6 +98,7 @@
     return complex(real, imag)
 
 
+ at builtinify
 def cosh(x):
     """cosh(x)
     
@@ -99,6 +110,7 @@
     return complex(real, imag)
 
 
+ at builtinify
 def exp(x):
     """exp(x)
     
@@ -111,6 +123,7 @@
     return complex(real, imag)
 
 
+ at builtinify
 def log(x, base=None):
     """log(x)
 
@@ -125,6 +138,7 @@
     return complex(real, imag)
 
 
+ at builtinify
 def log10(x):
     """log10(x)
 
@@ -137,6 +151,7 @@
     return complex(real, imag)
 
 
+ at builtinify
 def sin(x):
     """sin(x)
 
@@ -148,6 +163,7 @@
     return complex(real, imag)
 
 
+ at builtinify
 def sinh(x):
     """sinh(x)
 
@@ -159,6 +175,7 @@
     return complex(real, imag)
 
 
+ at builtinify
 def sqrt(x):
     """sqrt(x)
 
@@ -184,6 +201,7 @@
 _sqrt_half = sqrt(_half)
 
 
+ at builtinify
 def tan(x):
     """tan(x)
 
@@ -204,6 +222,7 @@
     return complex(real, imag)
 
 
+ at builtinify
 def tanh(x):
     """tanh(x)
 

Modified: pypy/branch/jitypes2/lib_pypy/ctypes_support.py
==============================================================================
--- pypy/branch/jitypes2/lib_pypy/ctypes_support.py	(original)
+++ pypy/branch/jitypes2/lib_pypy/ctypes_support.py	Fri Dec  3 11:04:29 2010
@@ -25,7 +25,7 @@
     def _where_is_errno():
         return standard_c_lib.__errno_location()
 
-elif sys.platform == 'darwin':
+elif sys.platform in ('darwin', 'freebsd7', 'freebsd8', 'freebsd9'):
     standard_c_lib.__error.restype = ctypes.POINTER(ctypes.c_int)
     def _where_is_errno():
         return standard_c_lib.__error()

Modified: pypy/branch/jitypes2/lib_pypy/grp.py
==============================================================================
--- pypy/branch/jitypes2/lib_pypy/grp.py	(original)
+++ pypy/branch/jitypes2/lib_pypy/grp.py	Fri Dec  3 11:04:29 2010
@@ -9,6 +9,10 @@
 from ctypes import Structure, c_char_p, c_int, POINTER
 from ctypes_support import standard_c_lib as libc
 
+try: from __pypy__ import builtinify
+except ImportError: builtinify = lambda f: f
+
+
 gid_t = c_int
 
 class GroupStruct(Structure):
@@ -64,6 +68,7 @@
     return Group(res.contents.gr_name, res.contents.gr_passwd,
                  res.contents.gr_gid, mem)
 
+ at builtinify
 def getgrgid(gid):
     res = libc.getgrgid(gid)
     if not res:
@@ -71,6 +76,7 @@
         raise KeyError(gid)
     return _group_from_gstruct(res)
 
+ at builtinify
 def getgrnam(name):
     if not isinstance(name, str):
         raise TypeError("expected string")
@@ -79,6 +85,7 @@
         raise KeyError(name)
     return _group_from_gstruct(res)
 
+ at builtinify
 def getgrall():
     libc.setgrent()
     lst = []

Modified: pypy/branch/jitypes2/lib_pypy/hashlib.py
==============================================================================
--- pypy/branch/jitypes2/lib_pypy/hashlib.py	(original)
+++ pypy/branch/jitypes2/lib_pypy/hashlib.py	Fri Dec  3 11:04:29 2010
@@ -50,53 +50,30 @@
     'a4337bc45a8fc544c03f52dc550cd6e1e87021bc896588bd79e901e2'
 
 """
+import sys
 try:
     import _hashlib
 except ImportError:
     _hashlib = None
 
-def __get_builtin_constructor(name):
-    if name in ('SHA1', 'sha1'):
-        import sha
-        return sha.new
-    elif name in ('MD5', 'md5'):
-        import md5
-        return md5.new
-    elif name in ('SHA256', 'sha256'):
-        import _sha256
-        return _sha256.sha256
-    elif name in ('SHA224', 'sha224'):
-        import _sha256
-        return _sha256.sha224
-    elif name in ('SHA512', 'sha512'):
-        import _sha512
-        return _sha512.sha512
-    elif name in ('SHA384', 'sha384'):
-        import _sha512
-        return _sha512.sha384
-    raise ValueError, "unsupported hash type"
-
 def __hash_new(name, string=''):
     """new(name, string='') - Return a new hashing object using the named algorithm;
     optionally initialized with a string.
     """
     try:
-        if _hashlib:
-            return _hashlib.new(name, string)
-    except ValueError:
-        # If the _hashlib module (OpenSSL) doesn't support the named
-        # hash, try using our builtin implementations.
-        # This allows for SHA224/256 and SHA384/512 support even though
-        # the OpenSSL library prior to 0.9.8 doesn't provide them.
-        pass
-
-    return __get_builtin_constructor(name)(string)
+        new = __byname[name]
+    except KeyError:
+        raise ValueError("unsupported hash type")
+    return new(string)
 
 new = __hash_new
 
-def _setfuncs():
-    # use the wrapper of the C implementation
+# ____________________________________________________________
+
+__byname = {}
 
+def __use_openssl_funcs():
+    # use the wrapper of the C implementation
     sslprefix = 'openssl_'
     for opensslfuncname, func in vars(_hashlib).items():
         if not opensslfuncname.startswith(sslprefix):
@@ -106,23 +83,41 @@
             # try them all, some may not work due to the OpenSSL
             # version not supporting that algorithm.
             func() 
-            # Use the C function directly (very fast)
-            globals()[funcname] = func 
+            # Use the C function directly (very fast, but with ctypes overhead)
+            __byname[funcname] = func
         except ValueError:
-            try:
-                # Use the builtin implementation directly (fast)
-                globals()[funcname] = __get_builtin_constructor(funcname) 
-            except ValueError:
-                # this one has no builtin implementation, don't define it
-                pass
+            pass
+
+def __use_builtin_funcs():
+    # look up the built-in versions (written in Python or RPython),
+    # and use the fastest one:
+    #  1. the one in RPython
+    #  2. the one from openssl (slower due to ctypes calling overhead)
+    #  3. the one in pure Python
+    if 'sha1' not in __byname or 'sha' in sys.builtin_module_names:
+        import sha
+        __byname['sha1'] = sha.new
+    if 'md5' not in __byname or 'md5' in sys.builtin_module_names:
+        import md5
+        __byname['md5'] = md5.new
+    if 'sha256' not in __byname:
+        import _sha256
+        __byname['sha256'] = _sha256.sha256
+    if 'sha224' not in __byname:
+        import _sha256
+        __byname['sha224'] = _sha256.sha224
+    if 'sha512' not in __byname:
+        import _sha512
+        __byname['sha512'] = _sha512.sha512
+    if 'sha384' not in __byname:
+        import _sha512
+        __byname['sha384'] = _sha512.sha384
+
+def __export_funcs():
+    for key, value in __byname.items():
+        globals()[key] = __byname[key.upper()] = value
 
 if _hashlib:
-    _setfuncs()
-else:
-    # lookup the C function to use directly for the named constructors
-    md5 = __get_builtin_constructor('md5')
-    sha1 = __get_builtin_constructor('sha1')
-    sha224 = __get_builtin_constructor('sha224')
-    sha256 = __get_builtin_constructor('sha256')
-    sha384 = __get_builtin_constructor('sha384')
-    sha512 = __get_builtin_constructor('sha512')
+    __use_openssl_funcs()
+__use_builtin_funcs()
+__export_funcs()

Modified: pypy/branch/jitypes2/lib_pypy/itertools.py
==============================================================================
--- pypy/branch/jitypes2/lib_pypy/itertools.py	(original)
+++ pypy/branch/jitypes2/lib_pypy/itertools.py	Fri Dec  3 11:04:29 2010
@@ -27,6 +27,9 @@
            'ifilterfalse', 'imap', 'islice', 'izip', 'repeat', 'starmap',
            'takewhile', 'tee']
 
+try: from __pypy__ import builtinify
+except ImportError: builtinify = lambda f: f
+
 
 class chain(object):
     """Make an iterator that returns elements from the first iterable
@@ -565,7 +568,8 @@
     def __iter__(self):
         return self
 
-    
+
+ at builtinify
 def tee(iterable, n=2):
     """Return n independent iterators from a single iterable.
     Note : once tee() has made a split, the original iterable

Modified: pypy/branch/jitypes2/lib_pypy/msvcrt.py
==============================================================================
--- pypy/branch/jitypes2/lib_pypy/msvcrt.py	(original)
+++ pypy/branch/jitypes2/lib_pypy/msvcrt.py	Fri Dec  3 11:04:29 2010
@@ -17,6 +17,10 @@
 except AttributeError: # we are not on windows
     raise ImportError
 
+try: from __pypy__ import builtinify
+except ImportError: builtinify = lambda f: f
+
+
 open_osfhandle.argtypes = [ctypes.c_int, ctypes.c_int]
 open_osfhandle.restype = ctypes.c_int
 
@@ -34,6 +38,7 @@
 _locking.argtypes = [ctypes.c_int, ctypes.c_int, ctypes.c_int]
 _locking.restype = ctypes.c_int
 
+ at builtinify
 def locking(fd, mode, nbytes):
     '''lock or unlock a number of bytes in a file.'''
     rv = _locking(fd, mode, nbytes)

Modified: pypy/branch/jitypes2/lib_pypy/pwd.py
==============================================================================
--- pypy/branch/jitypes2/lib_pypy/pwd.py	(original)
+++ pypy/branch/jitypes2/lib_pypy/pwd.py	Fri Dec  3 11:04:29 2010
@@ -17,6 +17,10 @@
 from ctypes_support import standard_c_lib as libc
 from ctypes import Structure, POINTER, c_int, c_char_p
 
+try: from __pypy__ import builtinify
+except ImportError: builtinify = lambda f: f
+
+
 uid_t = c_int
 gid_t = c_int
 
@@ -79,10 +83,12 @@
 _endpwent.argtypes = None
 _endpwent.restype = None
 
+ at builtinify
 def mkpwent(pw):
     pw = pw.contents
     return struct_passwd(pw)
 
+ at builtinify
 def getpwuid(uid):
     """
     getpwuid(uid) -> (pw_name,pw_passwd,pw_uid,
@@ -95,6 +101,7 @@
         raise KeyError("getpwuid(): uid not found: %s" % uid)
     return mkpwent(pw)
 
+ at builtinify
 def getpwnam(name):
     """
     getpwnam(name) -> (pw_name,pw_passwd,pw_uid,
@@ -109,9 +116,10 @@
         raise KeyError("getpwname(): name not found: %s" % name)
     return mkpwent(pw)
 
+ at builtinify
 def getpwall():
     """
-    "getpwall() -> list_of_entries
+    getpwall() -> list_of_entries
     Return a list of all available password database entries, in arbitrary order.
     See pwd.__doc__ for more on password database entries.
     """

Modified: pypy/branch/jitypes2/lib_pypy/pyexpat.py
==============================================================================
--- pypy/branch/jitypes2/lib_pypy/pyexpat.py	(original)
+++ pypy/branch/jitypes2/lib_pypy/pyexpat.py	Fri Dec  3 11:04:29 2010
@@ -7,6 +7,9 @@
 # load the platform-specific cache made by running pyexpat.ctc.py
 from ctypes_config_cache._pyexpat_cache import *
 
+try: from __pypy__ import builtinify
+except ImportError: builtinify = lambda f: f
+
 
 lib = ctypes.CDLL(ctypes.util.find_library('expat'))
 
@@ -425,9 +428,11 @@
         new_parser._set_unknown_encoding_handler()
         return new_parser
 
+ at builtinify
 def ErrorString(errno):
     return XML_ErrorString(errno)[:200]
 
+ at builtinify
 def ParserCreate(encoding=None, namespace_separator=None, intern=None):
     if (not isinstance(encoding, str) and
         not encoding is None):

Modified: pypy/branch/jitypes2/lib_pypy/pypy_test/test_hashlib.py
==============================================================================
--- pypy/branch/jitypes2/lib_pypy/pypy_test/test_hashlib.py	(original)
+++ pypy/branch/jitypes2/lib_pypy/pypy_test/test_hashlib.py	Fri Dec  3 11:04:29 2010
@@ -2,10 +2,20 @@
 from ..ctypes_config_cache import rebuild
 rebuild.rebuild_one('hashlib.ctc.py')
 
+from . import hack___pypy__
 from .. import hashlib, _hashlib
 
 def test_unicode():
-    assert isinstance(hashlib.new('sha1', u'xxx'), _hashlib.hash)
+    assert isinstance(hashlib.new('sha256', u'xxx'), _hashlib.hash)
+
+pure_python_version = {
+    'md5': 'md5.new',
+    'sha1': 'sha.new',
+    'sha224': '_sha256.sha224',
+    'sha256': '_sha256.sha256',
+    'sha384': '_sha512.sha384',
+    'sha512': '_sha512.sha512',
+    }
 
 def test_attributes():
     for name, expected_size in {'md5': 16,
@@ -30,7 +40,9 @@
         assert hexdigest == h.hexdigest()
 
         # also test the pure Python implementation
-        h = hashlib.__get_builtin_constructor(name)('')
+        modname, constructor = pure_python_version[name].split('.')
+        builder = getattr(__import__(modname), constructor)
+        h = builder('')
         assert h.digest_size == expected_size
         assert h.digestsize == expected_size
         #

Modified: pypy/branch/jitypes2/lib_pypy/pypy_test/test_structseq.py
==============================================================================
--- pypy/branch/jitypes2/lib_pypy/pypy_test/test_structseq.py	(original)
+++ pypy/branch/jitypes2/lib_pypy/pypy_test/test_structseq.py	Fri Dec  3 11:04:29 2010
@@ -1,6 +1,6 @@
 from __future__ import absolute_import
 import py
-from .._structseq import *
+from .._structseq import structseqfield, structseqtype
 
 
 class mydata:

Modified: pypy/branch/jitypes2/lib_pypy/readline.py
==============================================================================
--- pypy/branch/jitypes2/lib_pypy/readline.py	(original)
+++ pypy/branch/jitypes2/lib_pypy/readline.py	Fri Dec  3 11:04:29 2010
@@ -6,8 +6,4 @@
 are only stubs at the moment.
 """
 
-# Note that PyPy contains also a built-in module 'readline' which will hide
-# this one if compiled in.  However the built-in module is incomplete;
-# don't use it.
-
 from pyrepl.readline import *

Modified: pypy/branch/jitypes2/lib_pypy/resource.py
==============================================================================
--- pypy/branch/jitypes2/lib_pypy/resource.py	(original)
+++ pypy/branch/jitypes2/lib_pypy/resource.py	Fri Dec  3 11:04:29 2010
@@ -11,6 +11,10 @@
 from errno import EINVAL, EPERM
 import _structseq
 
+try: from __pypy__ import builtinify
+except ImportError: builtinify = lambda f: f
+
+
 class error(Exception):
     pass
 
@@ -77,6 +81,7 @@
     ru_nvcsw = _structseq.structseqfield(14)
     ru_nivcsw = _structseq.structseqfield(15)
 
+ at builtinify
 def rlimit_check_bounds(rlim_cur, rlim_max):
     if rlim_cur > rlim_t_max:
         raise ValueError("%d does not fit into rlim_t" % rlim_cur)
@@ -89,6 +94,7 @@
         ("rlim_max", rlim_t),
     )
 
+ at builtinify
 def getrusage(who):
     ru = _struct_rusage()
     ret = _getrusage(who, byref(ru))
@@ -116,6 +122,7 @@
         ru.ru_nivcsw,
         ))
 
+ at builtinify
 def getrlimit(resource):
     if not(0 <= resource < RLIM_NLIMITS):
         return ValueError("invalid resource specified")
@@ -127,6 +134,7 @@
         raise error(errno)
     return (rlim.rlim_cur, rlim.rlim_max)
 
+ at builtinify
 def setrlimit(resource, rlim):
     if not(0 <= resource < RLIM_NLIMITS):
         return ValueError("invalid resource specified")
@@ -143,6 +151,7 @@
         else:
             raise error(errno)
 
+ at builtinify
 def getpagesize():
     pagesize = 0
     if _getpagesize:

Modified: pypy/branch/jitypes2/lib_pypy/syslog.py
==============================================================================
--- pypy/branch/jitypes2/lib_pypy/syslog.py	(original)
+++ pypy/branch/jitypes2/lib_pypy/syslog.py	Fri Dec  3 11:04:29 2010
@@ -15,6 +15,10 @@
 from ctypes_support import standard_c_lib as libc
 from ctypes import c_int, c_char_p
 
+try: from __pypy__ import builtinify
+except ImportError: builtinify = lambda f: f
+
+
 # Real prototype is:
 # void syslog(int priority, const char *format, ...);
 # But we also need format ("%s") and one format argument (message)
@@ -34,9 +38,11 @@
 _setlogmask.argtypes = (c_int,)
 _setlogmask.restype = c_int
 
+ at builtinify
 def openlog(ident, option, facility):
     _openlog(ident, option, facility)
 
+ at builtinify
 def syslog(arg1, arg2=None):
     if arg2 is not None:
         priority, message = arg1, arg2
@@ -44,15 +50,19 @@
         priority, message = LOG_INFO, arg1
     _syslog(priority, "%s", message)
 
+ at builtinify
 def closelog():
     _closelog()
 
+ at builtinify
 def setlogmask(mask):
     return _setlogmask(mask)
 
+ at builtinify
 def LOG_MASK(pri):
     return (1 << pri)
 
+ at builtinify
 def LOG_UPTO(pri):
     return (1 << (pri + 1)) - 1
 

Modified: pypy/branch/jitypes2/pypy/annotation/annrpython.py
==============================================================================
--- pypy/branch/jitypes2/pypy/annotation/annrpython.py	(original)
+++ pypy/branch/jitypes2/pypy/annotation/annrpython.py	Fri Dec  3 11:04:29 2010
@@ -145,7 +145,7 @@
         classdef.add_source_for_attribute(attr, classdef.classdesc)
         self.bookkeeper
         assert isinstance(s_result, annmodel.SomePBC)
-        olddesc = s_result.descriptions.iterkeys().next()
+        olddesc = s_result.any_description()
         desc = olddesc.bind_self(classdef)
         args = self.bookkeeper.build_args("simple_call", args_s[:])
         desc.consider_call_site(self.bookkeeper, desc.getcallfamily(), [desc],

Modified: pypy/branch/jitypes2/pypy/annotation/bookkeeper.py
==============================================================================
--- pypy/branch/jitypes2/pypy/annotation/bookkeeper.py	(original)
+++ pypy/branch/jitypes2/pypy/annotation/bookkeeper.py	Fri Dec  3 11:04:29 2010
@@ -262,7 +262,7 @@
                                             args_s, s_result)
 
     def consider_call_site_for_pbc(self, s_callable, opname, args_s, s_result):
-        descs = s_callable.descriptions.keys()
+        descs = list(s_callable.descriptions)
         if not descs:
             return
         family = descs[0].getcallfamily()
@@ -590,7 +590,7 @@
         assert s_attr.is_constant()
         attr = s_attr.const
 
-        descs = pbc.descriptions.keys()
+        descs = list(pbc.descriptions)
         if not descs:
             return s_ImpossibleValue
 
@@ -633,7 +633,7 @@
         """Analyse a call to a SomePBC() with the given args (list of
         annotations).
         """
-        descs = pbc.descriptions.keys()
+        descs = list(pbc.descriptions)
         if not descs:
             return s_ImpossibleValue
         first = descs[0]

Modified: pypy/branch/jitypes2/pypy/annotation/description.py
==============================================================================
--- pypy/branch/jitypes2/pypy/annotation/description.py	(original)
+++ pypy/branch/jitypes2/pypy/annotation/description.py	Fri Dec  3 11:04:29 2010
@@ -636,6 +636,24 @@
                     return self
         return None
 
+    def maybe_return_immutable_list(self, attr, s_result):
+        # hack: 'x.lst' where lst is listed in _immutable_fields_ as 'lst[*]'
+        # should really return an immutable list as a result.  Implemented
+        # by changing the result's annotation (but not, of course, doing an
+        # actual copy in the rtyper).  Tested in pypy.rpython.test.test_rlist,
+        # test_immutable_list_out_of_instance.
+        search = '%s[*]' % (attr,)
+        cdesc = self
+        while cdesc is not None:
+            if '_immutable_fields_' in cdesc.classdict:
+                if search in cdesc.classdict['_immutable_fields_'].value:
+                    s_result.listdef.never_resize()
+                    s_copy = s_result.listdef.offspring()
+                    s_copy.listdef.mark_as_immutable()
+                    return s_copy
+            cdesc = cdesc.basedesc
+        return s_result     # common case
+
     def consider_call_site(bookkeeper, family, descs, args, s_result):
         from pypy.annotation.model import SomeInstance, SomePBC, s_None
         if len(descs) == 1:
@@ -654,7 +672,7 @@
             if isinstance(s_init, SomePBC):
                 assert len(s_init.descriptions) == 1, (
                     "unexpected dynamic __init__?")
-                initfuncdesc = s_init.descriptions.keys()[0]
+                initfuncdesc, = s_init.descriptions
                 if isinstance(initfuncdesc, FunctionDesc):
                     initmethdesc = bookkeeper.getmethoddesc(initfuncdesc,
                                                             classdef,
@@ -782,8 +800,8 @@
                                                         desc.selfclassdef,
                                                         desc.name,
                                                         commonflags)
-                del descs[desc]
-                descs[newdesc] = None
+                descs.remove(desc)
+                descs.add(newdesc)
 
         # --- case 1 ---
         groups = {}
@@ -798,7 +816,7 @@
                     for desc2 in group:
                         cdef2 = desc2.selfclassdef
                         if cdef1 is not cdef2 and cdef1.issubclass(cdef2):
-                            del descs[desc1]
+                            descs.remove(desc1)
                             break
     simplify_desc_set = staticmethod(simplify_desc_set)
 

Modified: pypy/branch/jitypes2/pypy/annotation/listdef.py
==============================================================================
--- pypy/branch/jitypes2/pypy/annotation/listdef.py	(original)
+++ pypy/branch/jitypes2/pypy/annotation/listdef.py	Fri Dec  3 11:04:29 2010
@@ -6,11 +6,16 @@
 class TooLateForChange(Exception):
     pass
 
+class ListChangeUnallowed(Exception):
+    pass
+
 class ListItem(object):
     mutated = False    # True for lists mutated after creation
     resized = False    # True for lists resized after creation
     range_step = None  # the step -- only for lists only created by a range()
     dont_change_any_more = False   # set to True when too late for changes
+    immutable = False  # for getattr out of _immutable_fields_ = ['attr[*]']
+    must_not_resize = False   # make_sure_not_resized()
 
     # what to do if range_step is different in merge.
     # - if one is a list (range_step is None), unify to a list.
@@ -26,7 +31,6 @@
         self.bookkeeper = bookkeeper
         self.itemof = {}  # set of all ListDefs using this ListItem
         self.read_locations = {}
-        self.dont_resize = False
         if bookkeeper is None:
             self.dont_change_any_more = True
 
@@ -34,12 +38,15 @@
         if not self.mutated:
             if self.dont_change_any_more:
                 raise TooLateForChange
+            self.immutable = False
             self.mutated = True
 
     def resize(self):
         if not self.resized:
-            if self.dont_change_any_more or self.dont_resize:
+            if self.dont_change_any_more:
                 raise TooLateForChange
+            if self.must_not_resize:
+                raise ListChangeUnallowed("resizing list")
             self.resized = True
 
     def setrangestep(self, step):
@@ -63,11 +70,13 @@
                     # things more general
                     self, other = other, self
 
-            if other.dont_resize:
-                if self.resized:                    
-                    raise TooLateForChange()
-                self.dont_resize = True
-            if other.mutated: self.mutate()
+            self.immutable &= other.immutable
+            if other.must_not_resize:
+                if self.resized:
+                    raise ListChangeUnallowed("list merge with a resized")
+                self.must_not_resize = True
+            if other.mutated:
+                self.mutate()
             if other.resized:
                 self.resize()
             if other.range_step != self.range_step:
@@ -176,9 +185,11 @@
         self.listitem.generalize(s_value)
 
     def __repr__(self):
-        return '<[%r]%s%s>' % (self.listitem.s_value,
+        return '<[%r]%s%s%s%s>' % (self.listitem.s_value,
                                self.listitem.mutated and 'm' or '',
-                               self.listitem.resized and 'r' or '')
+                               self.listitem.resized and 'r' or '',
+                               self.listitem.immutable and 'I' or '',
+                               self.listitem.must_not_resize and '!R' or '')
 
     def mutate(self):
         self.listitem.mutate()
@@ -189,13 +200,20 @@
 
     def never_resize(self):
         if self.listitem.resized:
-            raise TooLateForChange()
-        self.listitem.dont_resize = True
+            raise ListChangeUnallowed("list already resized")
+        self.listitem.must_not_resize = True
 
-    def never_mutate(self):
-        if self.listitem.resized or self.listitem.mutated:
-            raise TooLateForChange()
-        self.listitem.dont_change_any_more = True
+    def mark_as_immutable(self):
+        # Sets the 'immutable' flag.  Note that unlike "never resized",
+        # the immutable flag is only a hint.  It is cleared again e.g.
+        # when we merge with a "normal" list that doesn't have it.  It
+        # is thus expected to live only shortly, mostly for the case
+        # of writing 'x.list[n]'.
+        self.never_resize()
+        if not self.listitem.mutated:
+            self.listitem.immutable = True
+        #else: it's fine, don't set immutable=True at all (see
+        #      test_can_merge_immutable_list_with_regular_list)
 
 MOST_GENERAL_LISTDEF = ListDef(None, SomeObject())
 

Modified: pypy/branch/jitypes2/pypy/annotation/model.py
==============================================================================
--- pypy/branch/jitypes2/pypy/annotation/model.py	(original)
+++ pypy/branch/jitypes2/pypy/annotation/model.py	Fri Dec  3 11:04:29 2010
@@ -356,8 +356,8 @@
     immutable = True
 
     def __init__(self, descriptions, can_be_None=False, subset_of=None):
-        # descriptions is a set of Desc instances.
-        descriptions = dict.fromkeys(descriptions)
+        # descriptions is a set of Desc instances
+        descriptions = set(descriptions)
         self.descriptions = descriptions
         self.can_be_None = can_be_None
         self.subset_of = subset_of
@@ -379,6 +379,9 @@
                 if desc.pyobj is not None:
                     self.const = desc.pyobj
 
+    def any_description(self):
+        return iter(self.descriptions).next()
+
     def getKind(self):
         "Return the common Desc class of all descriptions in this PBC."
         kinds = {}

Modified: pypy/branch/jitypes2/pypy/annotation/specialize.py
==============================================================================
--- pypy/branch/jitypes2/pypy/annotation/specialize.py	(original)
+++ pypy/branch/jitypes2/pypy/annotation/specialize.py	Fri Dec  3 11:04:29 2010
@@ -345,7 +345,8 @@
             key.append(s.const)
         elif isinstance(s, SomePBC) and len(s.descriptions) == 1:
             # for test_specialize_arg_bound_method
-            key.append(s.descriptions.keys()[0])
+            desc, = s.descriptions
+            key.append(desc)
         else:
             raise Exception("specialize:arg(%d): argument not constant: %r"
                             % (i, s))

Modified: pypy/branch/jitypes2/pypy/annotation/test/test_annrpython.py
==============================================================================
--- pypy/branch/jitypes2/pypy/annotation/test/test_annrpython.py	(original)
+++ pypy/branch/jitypes2/pypy/annotation/test/test_annrpython.py	Fri Dec  3 11:04:29 2010
@@ -10,7 +10,7 @@
 from pypy.translator.translator import graphof as tgraphof
 from pypy.annotation import policy
 from pypy.annotation import specialize
-from pypy.annotation.listdef import ListDef, TooLateForChange
+from pypy.annotation.listdef import ListDef, ListChangeUnallowed
 from pypy.annotation.dictdef import DictDef
 from pypy.objspace.flow.model import *
 from pypy.rlib.rarithmetic import r_uint, base_int, r_longlong, r_ulonglong
@@ -1010,7 +1010,7 @@
         bookkeeper = a.bookkeeper
 
         def getmdesc(bmeth):
-            return bookkeeper.immutablevalue(bmeth).descriptions.keys()[0]
+            return bookkeeper.immutablevalue(bmeth).any_description()
 
         mdescA_m = getmdesc(A().m)
         mdescC_m = getmdesc(C().m)
@@ -2862,7 +2862,7 @@
         assert s.items[0].flags == {'access_directly': True}
         assert isinstance(s.items[1], annmodel.SomePBC)
         assert len(s.items[1].descriptions) == 1
-        assert s.items[1].descriptions.keys()[0].flags == {'access_directly':
+        assert s.items[1].any_description().flags == {'access_directly':
                                                            True}
         assert isinstance(s.items[2], annmodel.SomeInstance)
         assert s.items[2].flags == {'access_directly': True}
@@ -3206,7 +3206,7 @@
             l.append(4)
 
         a = self.RPythonAnnotator()
-        py.test.raises(TooLateForChange, a.build_types, g, [])
+        py.test.raises(ListChangeUnallowed, a.build_types, g, [])
         assert called
 
     def test_listitem_no_mutating2(self):
@@ -3229,7 +3229,7 @@
 
         a = self.RPythonAnnotator()
         a.translator.config.translation.list_comprehension_operations = True
-        py.test.raises(TooLateForChange, a.build_types, fn, [int])
+        py.test.raises(ListChangeUnallowed, a.build_types, fn, [int])
 
     def test_listitem_never_resize(self):
         from pypy.rlib.debug import check_annotation
@@ -3243,7 +3243,7 @@
             check_annotation(l, checker)
 
         a = self.RPythonAnnotator()
-        py.test.raises(TooLateForChange, a.build_types, f, [])
+        py.test.raises(ListChangeUnallowed, a.build_types, f, [])
 
 
     def test_len_of_empty_list(self):
@@ -3357,6 +3357,87 @@
         # not a constant: both __enter__ and __exit__ have been annotated
         assert not s.is_constant()
 
+    def test_make_sure_not_resized(self):
+        from pypy.rlib.debug import make_sure_not_resized
+
+        def pycode(consts):
+            make_sure_not_resized(consts)
+        def build1():
+            return pycode(consts=[1])
+        def build2():
+            return pycode(consts=[0])
+        def fn():
+            build1()
+            build2()
+
+        a = self.RPythonAnnotator()
+        a.translator.config.translation.list_comprehension_operations = True
+        a.build_types(fn, [])
+        # assert did not raise ListChangeUnallowed
+
+    def test_return_immutable_list(self):
+        class A:
+            _immutable_fields_ = 'lst[*]'
+        def f(n):
+            a = A()
+            l1 = [n, 0]
+            l1[1] = n+1
+            a.lst = l1
+            return a.lst
+
+        a = self.RPythonAnnotator()
+        s = a.build_types(f, [int])
+        assert s.listdef.listitem.immutable
+
+    def test_immutable_list_is_actually_resized(self):
+        class A:
+            _immutable_fields_ = 'lst[*]'
+        def f(n):
+            a = A()
+            l1 = [n]
+            l1.append(n+1)
+            a.lst = l1
+            return a.lst
+
+        a = self.RPythonAnnotator()
+        py.test.raises(ListChangeUnallowed, a.build_types, f, [int])
+
+    def test_can_merge_immutable_list_with_regular_list(self):
+        class A:
+            _immutable_fields_ = 'lst[*]'
+        def foo(lst):
+            pass
+
+        def f(n):
+            a = A()
+            l1 = [n, 0]
+            l1[1] = n+1
+            a.lst = l1
+            if n > 0:
+                foo(a.lst)
+            else:
+                lst = [0]
+                lst[0] = n
+                foo(lst)
+
+        a = self.RPythonAnnotator()
+        a.build_types(f, [int])
+
+        def f(n):
+            a = A()
+            l1 = [n, 0]
+            l1[1] = n+1
+            a.lst = l1
+            if n > 0:
+                lst = [0]
+                lst[0] = n
+                foo(lst)
+            else:
+                foo(a.lst)
+
+        a = self.RPythonAnnotator()
+        a.build_types(f, [int])
+
 
 def g(n):
     return [0,1,2,n]

Modified: pypy/branch/jitypes2/pypy/annotation/unaryop.py
==============================================================================
--- pypy/branch/jitypes2/pypy/annotation/unaryop.py	(original)
+++ pypy/branch/jitypes2/pypy/annotation/unaryop.py	Fri Dec  3 11:04:29 2010
@@ -615,6 +615,9 @@
                     if basedef.classdesc.all_enforced_attrs is not None:
                         if attr in basedef.classdesc.all_enforced_attrs:
                             raise HarmlesslyBlocked("get enforced attr")
+            elif isinstance(s_result, SomeList):
+                s_result = ins.classdef.classdesc.maybe_return_immutable_list(
+                    attr, s_result)
             return s_result
         return SomeObject()
     getattr.can_only_throw = []

Modified: pypy/branch/jitypes2/pypy/config/pypyoption.py
==============================================================================
--- pypy/branch/jitypes2/pypy/config/pypyoption.py	(original)
+++ pypy/branch/jitypes2/pypy/config/pypyoption.py	Fri Dec  3 11:04:29 2010
@@ -31,7 +31,7 @@
      "crypt", "signal", "_rawffi", "termios", "zlib",
      "struct", "md5", "sha", "bz2", "_minimal_curses", "cStringIO",
      "thread", "itertools", "pyexpat", "_ssl", "cpyext", "array",
-     "_bisect", "_ffi"]
+     "_bisect", "binascii", "_ffi"]
 ))
 
 translation_modules = default_modules.copy()
@@ -161,7 +161,6 @@
                suggests=[("objspace.allworkingmodules", False)]),
 
     BoolOption("geninterp", "specify whether geninterp should be used",
-               cmdline=None,
                default=True),
 
     BoolOption("logbytecodes",

Modified: pypy/branch/jitypes2/pypy/config/translationoption.py
==============================================================================
--- pypy/branch/jitypes2/pypy/config/translationoption.py	(original)
+++ pypy/branch/jitypes2/pypy/config/translationoption.py	Fri Dec  3 11:04:29 2010
@@ -3,6 +3,7 @@
 from pypy.config.config import OptionDescription, BoolOption, IntOption, ArbitraryOption, FloatOption
 from pypy.config.config import ChoiceOption, StrOption, to_optparse, Config
 from pypy.config.config import ConfigError
+from pypy.config.support import detect_number_of_processors
 
 DEFL_INLINE_THRESHOLD = 32.4    # just enough to inline add__Int_Int()
 # and just small enough to prevend inlining of some rlist functions.
@@ -113,10 +114,6 @@
     ChoiceOption("jit_backend", "choose the backend for the JIT",
                  ["auto", "x86", "x86-without-sse2", "llvm"],
                  default="auto", cmdline="--jit-backend"),
-    ChoiceOption("jit_debug", "the amount of debugging dumps made by the JIT",
-                 ["off", "profile", "steps", "detailed"],
-                 default="off",
-                 cmdline="--jit-debug"),
     ChoiceOption("jit_profiler", "integrate profiler support into the JIT",
                  ["off", "oprofile"],
                  default="off"),
@@ -171,7 +168,7 @@
                default=False, negation=False),
     IntOption("make_jobs", "Specify -j argument to make for compilation"
               " (C backend only)",
-              cmdline="--make-jobs", default=1),
+              cmdline="--make-jobs", default=detect_number_of_processors()),
 
     # Flags of the TranslationContext:
     BoolOption("simplifying", "Simplify flow graphs", default=True),

Modified: pypy/branch/jitypes2/pypy/conftest.py
==============================================================================
--- pypy/branch/jitypes2/pypy/conftest.py	(original)
+++ pypy/branch/jitypes2/pypy/conftest.py	Fri Dec  3 11:04:29 2010
@@ -336,13 +336,15 @@
         self.runtest_finish()
 
     def runtest_open(self):
-        leakfinder.start_tracking_allocations()
+        if not getattr(self.obj, 'dont_track_allocations', False):
+            leakfinder.start_tracking_allocations()
 
     def runtest_perform(self):
         super(PyPyTestFunction, self).runtest()
 
     def runtest_close(self):
-        if leakfinder.TRACK_ALLOCATIONS:
+        if (not getattr(self.obj, 'dont_track_allocations', False)
+            and leakfinder.TRACK_ALLOCATIONS):
             self._pypytest_leaks = leakfinder.stop_tracking_allocations(False)
         else:            # stop_tracking_allocations() already called
             self._pypytest_leaks = None

Modified: pypy/branch/jitypes2/pypy/doc/cpython_differences.txt
==============================================================================
--- pypy/branch/jitypes2/pypy/doc/cpython_differences.txt	(original)
+++ pypy/branch/jitypes2/pypy/doc/cpython_differences.txt	Fri Dec  3 11:04:29 2010
@@ -20,16 +20,21 @@
 
     __builtin__
     `__pypy__`_
+    _ast
+    _bisect
     _codecs
     _lsprof
     `_minimal_curses`_
     _random
     `_rawffi`_
+    _ssl
     _socket
     _sre
     _weakref
+    array
     bz2
     cStringIO
+    `cpyext`_
     crypt
     errno
     exceptions
@@ -72,7 +77,7 @@
 
 * Supported by being rewritten in pure Python (possibly using ``ctypes``):
   see the `lib_pypy/`_ directory.  Examples of modules that we
-  support this way: ``ctypes``, ``array``, ``cPickle``,
+  support this way: ``ctypes``, ``cPickle``,
   ``cStringIO``, ``cmath``, ``dbm`` (?), ``datetime``, ``binascii``...  
   Note that some modules are both in there and in the list above;
   by default, the built-in module is used (but can be disabled
@@ -80,11 +85,13 @@
 
 The extension modules (i.e. modules written in C, in the standard CPython)
 that are neither mentioned above nor in `lib_pypy/`_ are not available in PyPy.
+(You may have a chance to use them anyway with `cpyext`_.)
 
 .. the nonstandard modules are listed below...
 .. _`__pypy__`: __pypy__-module.html
 .. _`_rawffi`: ctypes-implementation.html
 .. _`_minimal_curses`: config/objspace.usemodules._minimal_curses.html
+.. _`cpyext`: http://morepypy.blogspot.com/2010/04/using-cpython-extension-modules-with.html
 .. _Stackless: stackless.html
 
 
@@ -129,12 +136,10 @@
 .. __: http://morepypy.blogspot.com/2008/02/python-finalizers-semantics-part-1.html
 .. __: http://morepypy.blogspot.com/2008/02/python-finalizers-semantics-part-2.html
 
-The built-in function ``id()`` returns numbers that are not addresses
-for most of PyPy's garbage collectors.
-This is most visible in the default repr: a typical PyPy object can
-pretend to be located ``at 0x00000009``.  This is just its ``id()``, not
-its real address (because an object can move around in some GCs). Calling
-``id`` a lot can lead to performance problem.
+Using the default GC called ``minimark``, the built-in function ``id()``
+works like it does in CPython.  With other GCs it returns numbers that
+are not real addresses (because an object can move around several times)
+and calling it a lot can lead to performance problem.
 
 Note that if you have a long chain of objects, each with a reference to
 the next one, and each with a __del__, PyPy's GC will perform badly.  On

Modified: pypy/branch/jitypes2/pypy/doc/faq.txt
==============================================================================
--- pypy/branch/jitypes2/pypy/doc/faq.txt	(original)
+++ pypy/branch/jitypes2/pypy/doc/faq.txt	Fri Dec  3 11:04:29 2010
@@ -47,7 +47,7 @@
 
 There is also an experimental support for CPython extension modules, so
 they'll run without change (from current observation, rather with little
-change) on trunk. It has been a part of 1.3 release, but support is still
+change) on trunk. It has been a part of 1.4 release, but support is still
 in alpha phase.
 
 .. _`extension modules`: cpython_differences.html#extension-modules

Modified: pypy/branch/jitypes2/pypy/doc/index.txt
==============================================================================
--- pypy/branch/jitypes2/pypy/doc/index.txt	(original)
+++ pypy/branch/jitypes2/pypy/doc/index.txt	Fri Dec  3 11:04:29 2010
@@ -8,7 +8,7 @@
 Getting into PyPy ... 
 =============================================
 
-* `Release 1.3`_: the latest official release
+* `Release 1.4`_: the latest official release
 
 * `PyPy Blog`_: news and status info about PyPy 
 
@@ -56,4 +56,4 @@
 .. _`Documentation`: docindex.html 
 .. _`Getting Started`: getting-started.html
 .. _papers: extradoc.html
-.. _`Release 1.3`: http://pypy.org/download.html
+.. _`Release 1.4`: http://pypy.org/download.html

Modified: pypy/branch/jitypes2/pypy/doc/release-1.4.0.txt
==============================================================================
--- pypy/branch/jitypes2/pypy/doc/release-1.4.0.txt	(original)
+++ pypy/branch/jitypes2/pypy/doc/release-1.4.0.txt	Fri Dec  3 11:04:29 2010
@@ -2,27 +2,58 @@
 PyPy 1.4: Ouroboros in practice
 ===============================
 
-Hello.
-
 We're pleased to announce the 1.4 release of PyPy. This is a major breakthrough
 in our long journey, as PyPy 1.4 is the first PyPy release that can translate
-itself faster than CPython. Starting today, we plan to start using PyPy for our
-own development.
+itself faster than CPython.  Starting today, we are using PyPy more for
+our every-day development.  So may you :) You can download it here:
+
+    http://pypy.org/download.html
+
+What is PyPy
+============
+
+PyPy is a very compliant Python interpreter, almost a drop-in replacement
+for CPython. It's fast (`pypy 1.4 and cpython 2.6`_ comparison)
 
-Among other features, this release includes numerous performance improvements
+Among its new features, this release includes numerous performance improvements
 (which made fast self-hosting possible), a 64-bit JIT backend, as well
 as serious stabilization. As of now, we can consider the 32-bit and 64-bit
-linux versions of PyPy stable enoughto run in production.
+linux versions of PyPy stable enough to run `in production`_.
+
+Numerous speed achievements are described on `our blog`_. Normalized speed
+charts comparing `pypy 1.4 and pypy 1.3`_ as well as `pypy 1.4 and cpython 2.6`_
+are available on benchmark website. For the impatient: yes, we got a lot faster!
 
 More highlights
 ===============
 
-* Virtualenv support: now PyPy is fully compatible with virtualenv_: note that
+* PyPy's built-in Just-in-Time compiler is fully transparent and
+  automatically generated; it now also has very reasonable memory
+  requirements.  The total memory used by a very complex and
+  long-running process (translating PyPy itself) is within 1.5x to
+  at most 2x the memory needed by CPython, for a speed-up of 2x.
+
+* More compact instances.  All instances are as compact as if
+  they had ``__slots__``.  This can give programs a big gain in
+  memory.  (In the example of translation above, we already have
+  carefully placed ``__slots__``, so there is no extra win.)
+
+* `Virtualenv support`_: now PyPy is fully compatible with virtualenv_: note that
   to use it, you need a recent version of virtualenv (>= 1.5).
 
 * Faster (and JITted) regular expressions - huge boost in speeding up
-  sre module.
+  the `re` module.
 
-* Faster (and JITted) calls to functions like map().
+* Other speed improvements, like JITted calls to functions like map().
 
 .. _virtualenv: http://pypi.python.org/pypi/virtualenv
+.. _`Virtualenv support`: http://morepypy.blogspot.com/2010/08/using-virtualenv-with-pypy.html
+.. _`in production`: http://morepypy.blogspot.com/2010/11/running-large-radio-telescope-software.html
+.. _`our blog`: http://morepypy.blogspot.com
+.. _`pypy 1.4 and pypy 1.3`: http://speed.pypy.org/comparison/?exe=1%2B41,1%2B172&ben=1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20&env=1&hor=false&bas=1%2B41&chart=normal+bars
+.. _`pypy 1.4 and cpython 2.6`: http://speed.pypy.org/comparison/?exe=2%2B35,1%2B172&ben=1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20&env=1&hor=false&bas=2%2B35&chart=normal+bars
+
+Cheers,
+
+Carl Friedrich Bolz, Antonio Cuni, Maciej Fijalkowski,
+Amaury Forgeot d'Arc, Armin Rigo and the PyPy team

Modified: pypy/branch/jitypes2/pypy/doc/sprint-reports.txt
==============================================================================
--- pypy/branch/jitypes2/pypy/doc/sprint-reports.txt	(original)
+++ pypy/branch/jitypes2/pypy/doc/sprint-reports.txt	Fri Dec  3 11:04:29 2010
@@ -30,6 +30,17 @@
   * `Düsseldorf (October 2006)`_
   * `Leysin (January 2007)`_
   * `Hildesheim (Feb 2007)`_ (also `EU report writing sprint`_)
+  * `Göteborg (November 2007)`_
+  * `Leysin (January 2008)`_
+  * `Berlin (May 2008)`_
+  * `Vilnius after EuroPython (July 2008)`_
+  * `Düsseldorf (August 2008)`_
+  * `Wroclaw (February 2009)`_
+  * `Leysin (April 2009)`_
+  * `Göteborg (August 2009)`_
+  * `Düsseldorf (November 2009)`_
+  * `CERN (July 2010)`_
+  * `Düsseldorf (October 2010)`_
 
     .. _Hildesheim (Feb 2003): http://codespeak.net/pypy/extradoc/sprintinfo/HildesheimReport.html
     .. _Gothenburg (May 2003): http://codespeak.net/pypy/extradoc/sprintinfo/gothenburg-2003-sprintreport.txt
@@ -55,3 +66,15 @@
     .. _Hildesheim (Feb 2007): http://codespeak.net/pypy/extradoc/sprintinfo/trillke-2007/sprint-report.txt
     .. _`EU report writing sprint`: http://codespeak.net/pypy/extradoc/sprintinfo/trillke-2007/eu-report-sprint-report.txt
     .. _`PyCon/Dallas (Feb 2006)`: http://codespeak.net/pypy/extradoc/sprintinfo/pycon06/sprint-report.txt
+    .. _`Göteborg (November 2007)`: http://morepypy.blogspot.com/2007_11_01_archive.html
+    .. _`Leysin (January 2008)`: http://morepypy.blogspot.com/2008/01/leysin-winter-sport-sprint-started.html
+    .. _`Berlin (May 2008)`: http://morepypy.blogspot.com/2008_05_01_archive.html
+    .. _`Vilnius after EuroPython (July 2008)`: http://morepypy.blogspot.com/2008/07/europython-2008-pypy-talks-and-sprint.html
+    .. _`Düsseldorf (August 2008)`: http://morepypy.blogspot.com/2008_10_01_archive.html
+    .. _`Wroclaw (February 2009)`: http://morepypy.blogspot.com/2009/02/wroclaw-2009-sprint-progress-report.html
+    .. _`Leysin (April 2009)`: http://morepypy.blogspot.com/2009/04/leysin-sprint-report.html
+    .. _`Göteborg (August 2009)`: http://morepypy.blogspot.com/2009/08/gothenburg-jit-sprint-report.html
+    .. _`Düsseldorf (November 2009)`: http://morepypy.blogspot.com/2009/11/dusseldorf-sprint-report.html
+    .. _`CERN (July 2010)`: http://morepypy.blogspot.com/2010/07/cern-sprint-report-wrapping-c-libraries.html
+    .. _`Düsseldorf (October 2010)`: http://morepypy.blogspot.com/2010/10/dusseldorf-sprint-report-2010.html
+

Modified: pypy/branch/jitypes2/pypy/doc/statistic/release_dates.dat
==============================================================================
--- pypy/branch/jitypes2/pypy/doc/statistic/release_dates.dat	(original)
+++ pypy/branch/jitypes2/pypy/doc/statistic/release_dates.dat	Fri Dec  3 11:04:29 2010
@@ -7,3 +7,7 @@
 2006-06-25,"PyPy 0.9"
 2007-02-17,"PyPy 0.99"
 2007-03-27,"PyPy 1.0"
+2009-04-28,"PyPy 1.1"
+2010-03-12,"PyPy 1.2"
+2010-06-26,"PyPy 1.3"
+2010-11-26,"PyPy 1.4"

Modified: pypy/branch/jitypes2/pypy/doc/statistic/sprint_dates.dat
==============================================================================
--- pypy/branch/jitypes2/pypy/doc/statistic/sprint_dates.dat	(original)
+++ pypy/branch/jitypes2/pypy/doc/statistic/sprint_dates.dat	Fri Dec  3 11:04:29 2010
@@ -1,26 +1,39 @@
 PyPy sprints
 location, begin, end
 "Hildesheim",2003-02-17,2003-02-23
-"Gothenburg",2003-05-24,2003-05-31
-"LovainLaNeuve",2003-06-21,2003-06-24
+"Göteborg",2003-05-24,2003-05-31
+"Louvain-la-Neuve",2003-06-21,2003-06-24
 "Berlin",2003-09-29,2003-10-04
 "Amsterdam",2003-12-14,2003-12-21
-"Europython/Gothenburg",2004-06-01,2004-06-07
+"Europython/Göteborg",2004-06-01,2004-06-07
 "Vilnius",2004-11-15,2004-11-23
 "Leysin",2005-01-22,2005-01-29
 "PyCon/Washington",2005-03-19,2005-03-22
-"Europython/Gothenburg",2005-07-01,2005-07-07
+"Europython/Göteborg",2005-07-01,2005-07-07
 "Hildesheim",2005-07-25,2005-07-31
 "Heidelberg",2005-08-22,2005-08-29
 "Paris",2005-10-10,2005-10-16
-"Gothenburg",2005-12-05,2005-12-11
+"Göteborg",2005-12-05,2005-12-11
 "Mallorca",2006-01-23,2006-01-29
 "Pycon/Dallas",2006-02-27,2006-03-02
 "Louvain-la-Neuve",2006-03-06,2006-03-10
 "Japan",2006-04-23,2006-04-29
-"Duesseldorf",2006-06-02,2006-06-09
+"Düsseldorf",2006-06-02,2006-06-09
 "Europython/Genf",2006-07-06,2006-07-09
 "Limerick",2006-08-21,2006-08-27
-"Duesseldorf",2006-10-30,2006-11-05
+"Düsseldorf",2006-10-30,2006-11-05
 "Leysin",2007-01-08,2007-01-14
 "Hildesheim",2007-03-01,2007-03-05
+"Hildesheim",2007-03-18,2007-03-23
+"Bern",2007-10-22,2007-10-26
+"Göteborg",2007-11-19,2007-11-25
+"Leysin",2008-01-12,2008-01-19
+"Berlin",2008-05-17,2008-05-22
+"EuroPython/Vilnius",2008-07-10,2008-07-12
+"Düsseldorf",2008-08-05,2008-08-13
+"Wroclaw",2009-02-07,2009-02-14
+"Leysin",2009-04-14,2009-04-21
+"Göteborg",2009-08-18,2009-08-25
+"Düsseldorf",2009-11-06,2009-11-13
+"CERN",2010-07-05,2010-07-09
+"Düsseldorf",2010-10-25,2010-10-31

Modified: pypy/branch/jitypes2/pypy/interpreter/baseobjspace.py
==============================================================================
--- pypy/branch/jitypes2/pypy/interpreter/baseobjspace.py	(original)
+++ pypy/branch/jitypes2/pypy/interpreter/baseobjspace.py	Fri Dec  3 11:04:29 2010
@@ -147,7 +147,7 @@
 
     __already_enqueued_for_destruction = False
 
-    def _enqueue_for_destruction(self, space):
+    def _enqueue_for_destruction(self, space, call_user_del=True):
         """Put the object in the destructor queue of the space.
         At a later, safe point in time, UserDelAction will use
         space.userdel() to call the object's app-level __del__ method.
@@ -160,7 +160,8 @@
                 return
             self.__already_enqueued_for_destruction = True
         self.clear_all_weakrefs()
-        space.user_del_action.register_dying_object(self)
+        if call_user_del:
+            space.user_del_action.register_dying_object(self)
 
     def _call_builtin_destructor(self):
         pass     # method overridden in typedef.py

Modified: pypy/branch/jitypes2/pypy/interpreter/function.py
==============================================================================
--- pypy/branch/jitypes2/pypy/interpreter/function.py	(original)
+++ pypy/branch/jitypes2/pypy/interpreter/function.py	Fri Dec  3 11:04:29 2010
@@ -612,11 +612,9 @@
         self.w_func_dict = func.w_func_dict
         self.w_module = func.w_module
 
-    def descr_builtinfunction__new__(space, w_subtype, w_func):
-        func = space.interp_w(Function, w_func)
-        bltin = space.allocate_instance(BuiltinFunction, w_subtype)
-        BuiltinFunction.__init__(bltin, func)
-        return space.wrap(bltin)
+    def descr_builtinfunction__new__(space, w_subtype):
+        raise OperationError(space.w_TypeError,
+                     space.wrap("cannot create 'builtin_function' instances"))
 
     def descr_function_repr(self):
         return self.space.wrap('<built-in function %s>' % (self.name,))

Modified: pypy/branch/jitypes2/pypy/interpreter/gateway.py
==============================================================================
--- pypy/branch/jitypes2/pypy/interpreter/gateway.py	(original)
+++ pypy/branch/jitypes2/pypy/interpreter/gateway.py	Fri Dec  3 11:04:29 2010
@@ -1083,7 +1083,7 @@
             # these decorators are known to return the same function
             # object, we may ignore them
             assert '\n' in source
-            source = source[source.find('\n') + 1:]
+            source = source[source.find('\n') + 1:].lstrip()
         assert source.startswith("def "), "can only transform functions" 
         source = source[4:]
     p = source.find('(')

Modified: pypy/branch/jitypes2/pypy/interpreter/generator.py
==============================================================================
--- pypy/branch/jitypes2/pypy/interpreter/generator.py	(original)
+++ pypy/branch/jitypes2/pypy/interpreter/generator.py	Fri Dec  3 11:04:29 2010
@@ -10,7 +10,7 @@
     
     def __init__(self, frame):
         self.space = frame.space
-        self.frame = frame
+        self.frame = frame     # turned into None when frame_finished_execution
         self.running = False
 
     def descr__reduce__(self, space):
@@ -19,9 +19,13 @@
         mod      = space.interp_w(MixedModule, w_mod)
         new_inst = mod.get('generator_new')
         w        = space.wrap
+        if self.frame:
+            w_frame = w(self.frame)
+        else:
+            w_frame = space.w_None
 
         tup = [
-            w(self.frame),
+            w_frame,
             w(self.running),
             ]
 
@@ -41,7 +45,8 @@
         if self.running:
             raise OperationError(space.w_ValueError,
                                  space.wrap('generator already executing'))
-        if self.frame.frame_finished_execution:
+        frame = self.frame
+        if frame is None:
             # xxx a bit ad-hoc, but we don't want to go inside
             # execute_generator_frame() if the frame is actually finished
             if operr is None:
@@ -49,7 +54,7 @@
             raise operr
         # XXX it's not clear that last_instr should be promoted at all
         # but as long as it is necessary for call_assembler, let's do it early
-        last_instr = jit.hint(self.frame.last_instr, promote=True)
+        last_instr = jit.hint(frame.last_instr, promote=True)
         if last_instr == -1:
             if w_arg and not space.is_w(w_arg, space.w_None):
                 msg = "can't send non-None value to a just-started generator"
@@ -60,18 +65,19 @@
         self.running = True
         try:
             try:
-                w_result = self.frame.execute_generator_frame(w_arg, operr)
+                w_result = frame.execute_generator_frame(w_arg, operr)
             except OperationError:
                 # errors finish a frame
-                self.frame.frame_finished_execution = True
+                self.frame = None
                 raise
             # if the frame is now marked as finished, it was RETURNed from
-            if self.frame.frame_finished_execution:
+            if frame.frame_finished_execution:
+                self.frame = None
                 raise OperationError(space.w_StopIteration, space.w_None) 
             else:
                 return w_result     # YIELDed
         finally:
-            self.frame.f_backref = jit.vref_None
+            frame.f_backref = jit.vref_None
             self.running = False
 
     def descr_throw(self, w_type, w_val=None, w_tb=None):
@@ -115,7 +121,7 @@
             raise OperationError(space.w_RuntimeError, space.wrap(msg))
 
     def descr_gi_frame(space, self):
-        if not self.frame.frame_finished_execution:
+        if self.frame is not None and not self.frame.frame_finished_execution:
             return self.frame
         else:
             return space.w_None
@@ -125,15 +131,17 @@
         applevel __del__, which is called at a safe point after the
         interp-level __del__ enqueued the object for destruction
         """
-        # Only bother raising an exception if the frame is still not
-        # finished and finally or except blocks are present.
-        if not self.frame.frame_finished_execution:
+        self.descr_close()
+
+    def __del__(self):
+        # Only bother enqueuing self to raise an exception if the frame is
+        # still not finished and finally or except blocks are present.
+        must_call_close = False
+        if self.frame is not None:
             block = self.frame.lastblock
             while block is not None:
                 if not isinstance(block, LoopBlock):
-                    self.descr_close()
-                    return
+                    must_call_close = True
+                    break
                 block = block.previous
-
-    def __del__(self):
-        self._enqueue_for_destruction(self.space)
+        self._enqueue_for_destruction(self.space, must_call_close)

Modified: pypy/branch/jitypes2/pypy/interpreter/pycode.py
==============================================================================
--- pypy/branch/jitypes2/pypy/interpreter/pycode.py	(original)
+++ pypy/branch/jitypes2/pypy/interpreter/pycode.py	Fri Dec  3 11:04:29 2010
@@ -15,7 +15,7 @@
     CO_OPTIMIZED, CO_NEWLOCALS, CO_VARARGS, CO_VARKEYWORDS, CO_NESTED,
     CO_GENERATOR, CO_CONTAINSGLOBALS)
 from pypy.rlib.rarithmetic import intmask
-from pypy.rlib.debug import make_sure_not_resized, make_sure_not_modified
+from pypy.rlib.debug import make_sure_not_resized
 from pypy.rlib import jit
 from pypy.rlib.objectmodel import compute_hash
 from pypy.tool.stdlib_opcode import opcodedesc, HAVE_ARGUMENT
@@ -69,7 +69,7 @@
         self.co_stacksize = stacksize
         self.co_flags = flags
         self.co_code = code
-        self.co_consts_w = make_sure_not_modified(consts)
+        self.co_consts_w = consts
         self.co_names_w = [space.new_interned_str(aname) for aname in names]
         self.co_varnames = varnames
         self.co_freevars = freevars
@@ -269,7 +269,7 @@
         dis.dis(co)
 
     def fget_co_consts(space, self):
-        return space.newtuple(self.co_consts_w[:])
+        return space.newtuple(self.co_consts_w)
     
     def fget_co_names(space, self):
         return space.newtuple(self.co_names_w)
@@ -383,7 +383,7 @@
             w(self.co_stacksize), 
             w(self.co_flags),
             w(self.co_code), 
-            space.newtuple(self.co_consts_w[:]), 
+            space.newtuple(self.co_consts_w), 
             space.newtuple(self.co_names_w), 
             space.newtuple([w(v) for v in self.co_varnames]), 
             w(self.co_filename),

Modified: pypy/branch/jitypes2/pypy/interpreter/test/test_gateway.py
==============================================================================
--- pypy/branch/jitypes2/pypy/interpreter/test/test_gateway.py	(original)
+++ pypy/branch/jitypes2/pypy/interpreter/test/test_gateway.py	Fri Dec  3 11:04:29 2010
@@ -578,6 +578,11 @@
         w_res = space.call_args(w_g, args)
         assert space.eq_w(w_res, space.wrap((-1, 0)))
 
+class AppTestPyTestMark:
+    @py.test.mark.unlikely_to_exist
+    def test_anything(self):
+        pass
+
 
 class TestPassThroughArguments:
     

Modified: pypy/branch/jitypes2/pypy/jit/backend/detect_cpu.py
==============================================================================
--- pypy/branch/jitypes2/pypy/jit/backend/detect_cpu.py	(original)
+++ pypy/branch/jitypes2/pypy/jit/backend/detect_cpu.py	Fri Dec  3 11:04:29 2010
@@ -31,7 +31,8 @@
                 'i86pc': 'x86',    # Solaris/Intel
                 'x86':   'x86',    # Apple
                 'Power Macintosh': 'ppc',
-                'x86_64': 'x86', 
+                'x86_64': 'x86',
+                'amd64': 'x86'     # freebsd
                 }[mach]
     except KeyError:
         return mach

Modified: pypy/branch/jitypes2/pypy/jit/backend/llgraph/llimpl.py
==============================================================================
--- pypy/branch/jitypes2/pypy/jit/backend/llgraph/llimpl.py	(original)
+++ pypy/branch/jitypes2/pypy/jit/backend/llgraph/llimpl.py	Fri Dec  3 11:04:29 2010
@@ -4,6 +4,7 @@
 when executing on top of the llinterpreter.
 """
 
+import weakref
 from pypy.objspace.flow.model import Variable, Constant
 from pypy.annotation import model as annmodel
 from pypy.jit.metainterp.history import (ConstInt, ConstPtr,
@@ -161,6 +162,8 @@
 # ____________________________________________________________
 
 class CompiledLoop(object):
+    has_been_freed = False
+
     def __init__(self):
         self.inputargs = []
         self.operations = []
@@ -285,6 +288,11 @@
     del _variables[:]
     return _to_opaque(CompiledLoop())
 
+def mark_as_free(loop):
+    loop = _from_opaque(loop)
+    assert not loop.has_been_freed
+    loop.has_been_freed = True
+
 def compile_start_int_var(loop):
     return compile_start_ref_var(loop, lltype.Signed)
 
@@ -317,7 +325,7 @@
         raise ValueError("CALL_ASSEMBLER not supported")
     loop = _from_opaque(loop)
     op = loop.operations[-1]
-    op.descr = descr
+    op.descr = weakref.ref(descr)
 
 def compile_add_var(loop, intvar):
     loop = _from_opaque(loop)
@@ -429,6 +437,7 @@
         verbose = True
         self.opindex = 0
         while True:
+            assert not self.loop.has_been_freed
             op = self.loop.operations[self.opindex]
             args = [self.getenv(v) for v in op.args]
             if not op.is_final():
@@ -440,7 +449,10 @@
                     _stats.exec_conditional_jumps += 1
                     if op.jump_target is not None:
                         # a patched guard, pointing to further code
-                        args = [self.getenv(v) for v in op.fail_args if v]
+                        if op.fail_args:
+                            args = [self.getenv(v) for v in op.fail_args if v]
+                        else:
+                            args = []
                         assert len(op.jump_target.inputargs) == len(args)
                         self.env = dict(zip(op.jump_target.inputargs, args))
                         self.loop = op.jump_target
@@ -571,7 +583,12 @@
     def op_debug_merge_point(self, _, value, recdepth):
         from pypy.jit.metainterp.warmspot import get_stats
         loc = ConstPtr(value)._get_str()
-        get_stats().add_merge_point_location(loc)
+        try:
+            stats = get_stats()
+        except AttributeError:
+            pass
+        else:
+            stats.add_merge_point_location(loc)
 
     def op_guard_true(self, _, value):
         if not value:
@@ -839,14 +856,22 @@
         finally:
             self._may_force = -1
 
-    def op_call_assembler(self, loop_token, *args):
+    def op_call_assembler(self, wref_loop_token, *args):
+        if we_are_translated():
+            raise ValueError("CALL_ASSEMBLER not supported")
+        return self._do_call_assembler(wref_loop_token, *args)
+
+    def _do_call_assembler(self, wref_loop_token, *args):
         global _last_exception
+        loop_token = wref_loop_token()
+        assert loop_token, "CALL_ASSEMBLER to a target that already died"
+        ctl = loop_token.compiled_loop_token
+        if hasattr(ctl, 'redirected'):
+            return self._do_call_assembler(ctl.redirected, *args)
         assert not self._forced
-        loop_token = self.cpu._redirected_call_assembler.get(loop_token,
-                                                             loop_token)
         self._may_force = self.opindex
         try:
-            inpargs = _from_opaque(loop_token._llgraph_compiled_version).inputargs
+            inpargs = _from_opaque(ctl.compiled_version).inputargs
             for i, inparg in enumerate(inpargs):
                 TYPE = inparg.concretetype
                 if TYPE is lltype.Signed:
@@ -1539,10 +1564,13 @@
         do_setfield_gc_int(vable, fielddescr.ofs, 0)
 
 def redirect_call_assembler(cpu, oldlooptoken, newlooptoken):
-    OLD = _from_opaque(oldlooptoken._llgraph_compiled_version).getargtypes()
-    NEW = _from_opaque(newlooptoken._llgraph_compiled_version).getargtypes()
+    oldclt = oldlooptoken.compiled_loop_token
+    newclt = newlooptoken.compiled_loop_token
+    OLD = _from_opaque(oldclt.compiled_version).getargtypes()
+    NEW = _from_opaque(newclt.compiled_version).getargtypes()
     assert OLD == NEW
-    cpu._redirected_call_assembler[oldlooptoken] = newlooptoken
+    assert not hasattr(oldclt, 'redirected')
+    oldclt.redirected = weakref.ref(newlooptoken)
 
 # ____________________________________________________________
 
@@ -1609,6 +1637,7 @@
 setannotation(compile_add_fail, annmodel.SomeInteger())
 setannotation(compile_add_fail_arg, annmodel.s_None)
 setannotation(compile_redirect_fail, annmodel.s_None)
+setannotation(mark_as_free, annmodel.s_None)
 
 setannotation(new_frame, s_Frame)
 setannotation(frame_clear, annmodel.s_None)

Modified: pypy/branch/jitypes2/pypy/jit/backend/llgraph/runner.py
==============================================================================
--- pypy/branch/jitypes2/pypy/jit/backend/llgraph/runner.py	(original)
+++ pypy/branch/jitypes2/pypy/jit/backend/llgraph/runner.py	Fri Dec  3 11:04:29 2010
@@ -102,7 +102,6 @@
         llimpl._llinterp = LLInterpreter(self.rtyper)
         self._future_values = []
         self._descrs = {}
-        self._redirected_call_assembler = {}
 
     def _freeze_(self):
         assert self.translate_support_code
@@ -118,22 +117,34 @@
             self._descrs[key] = descr
             return descr
 
-    def compile_bridge(self, faildescr, inputargs, operations, log=True):
+    def compile_bridge(self, faildescr, inputargs, operations,
+                       original_loop_token, log=True):
         c = llimpl.compile_start()
+        clt = original_loop_token.compiled_loop_token
+        clt.loop_and_bridges.append(c)
+        clt.compiling_a_bridge()
         self._compile_loop_or_bridge(c, inputargs, operations)
         old, oldindex = faildescr._compiled_fail
         llimpl.compile_redirect_fail(old, oldindex, c)
 
-    def compile_loop(self, inputargs, operations, loopdescr, log=True):
+    def compile_loop(self, inputargs, operations, looptoken, log=True):
         """In a real assembler backend, this should assemble the given
         list of operations.  Here we just generate a similar CompiledLoop
         instance.  The code here is RPython, whereas the code in llimpl
         is not.
         """
         c = llimpl.compile_start()
-        loopdescr._llgraph_compiled_version = c
+        clt = model.CompiledLoopToken(self, looptoken.number)
+        clt.loop_and_bridges = [c]
+        clt.compiled_version = c
+        looptoken.compiled_loop_token = clt
         self._compile_loop_or_bridge(c, inputargs, operations)
 
+    def free_loop_and_bridges(self, compiled_loop_token):
+        for c in compiled_loop_token.loop_and_bridges:
+            llimpl.mark_as_free(c)
+        model.AbstractCPU.free_loop_and_bridges(self, compiled_loop_token)
+
     def _compile_loop_or_bridge(self, c, inputargs, operations):
         var2index = {}
         for box in inputargs:
@@ -207,7 +218,7 @@
         if op.getopnum() == rop.JUMP:
             targettoken = op.getdescr()
             assert isinstance(targettoken, history.LoopToken)
-            compiled_version = targettoken._llgraph_compiled_version
+            compiled_version = targettoken.compiled_loop_token.compiled_version
             llimpl.compile_add_jump_target(c, compiled_version)
         elif op.getopnum() == rop.FINISH:
             faildescr = op.getdescr()
@@ -217,7 +228,7 @@
             assert False, "unknown operation"
 
     def _execute_token(self, loop_token):
-        compiled_version = loop_token._llgraph_compiled_version
+        compiled_version = loop_token.compiled_loop_token.compiled_version
         frame = llimpl.new_frame(self.is_oo, self)
         # setup the frame
         llimpl.frame_clear(frame, compiled_version)

Modified: pypy/branch/jitypes2/pypy/jit/backend/llsupport/gc.py
==============================================================================
--- pypy/branch/jitypes2/pypy/jit/backend/llsupport/gc.py	(original)
+++ pypy/branch/jitypes2/pypy/jit/backend/llsupport/gc.py	Fri Dec  3 11:04:29 2010
@@ -15,6 +15,7 @@
 from pypy.jit.backend.llsupport.descr import GcCache, get_field_descr
 from pypy.jit.backend.llsupport.descr import GcPtrFieldDescr
 from pypy.jit.backend.llsupport.descr import get_call_descr
+from pypy.rpython.memory.gctransform import asmgcroot
 
 # ____________________________________________________________
 
@@ -35,6 +36,8 @@
         return False
     def has_write_barrier_class(self):
         return None
+    def freeing_block(self, start, stop):
+        pass
 
 # ____________________________________________________________
 
@@ -218,50 +221,120 @@
     LOC_EBP_PLUS  = 2
     LOC_EBP_MINUS = 3
 
-    GCMAP_ARRAY = rffi.CArray(llmemory.Address)
-    CALLSHAPE_ARRAY = rffi.CArray(rffi.UCHAR)
+    GCMAP_ARRAY = rffi.CArray(lltype.Signed)
+    CALLSHAPE_ARRAY_PTR = rffi.CArrayPtr(rffi.UCHAR)
 
     def __init__(self):
+        # '_gcmap' is an array of length '_gcmap_maxlength' of addresses.
+        # '_gcmap_curlength' tells how full the array really is.
+        # The addresses are actually grouped in pairs:
+        #     (addr-after-the-CALL-in-assembler, addr-of-the-call-shape).
+        # '_gcmap_deadentries' counts pairs marked dead (2nd item is NULL).
+        # '_gcmap_sorted' is True only if we know the array is sorted.
         self._gcmap = lltype.nullptr(self.GCMAP_ARRAY)
         self._gcmap_curlength = 0
         self._gcmap_maxlength = 0
+        self._gcmap_deadentries = 0
+        self._gcmap_sorted = True
 
     def initialize(self):
         # hack hack hack.  Remove these lines and see MissingRTypeAttribute
         # when the rtyper tries to annotate these methods only when GC-ing...
         self.gcmapstart()
         self.gcmapend()
+        self.gcmarksorted()
 
     def gcmapstart(self):
-        return llmemory.cast_ptr_to_adr(self._gcmap)
+        return rffi.cast(llmemory.Address, self._gcmap)
 
     def gcmapend(self):
         addr = self.gcmapstart()
         if self._gcmap_curlength:
-            addr += llmemory.sizeof(llmemory.Address)*self._gcmap_curlength
+            addr += rffi.sizeof(lltype.Signed) * self._gcmap_curlength
+            if not we_are_translated() and type(addr) is long:
+                from pypy.rpython.lltypesystem import ll2ctypes
+                addr = ll2ctypes._lladdress(addr)       # XXX workaround
         return addr
 
+    def gcmarksorted(self):
+        # Called by the GC when it is about to sort [gcmapstart():gcmapend()].
+        # Returns the previous sortedness flag -- i.e. returns True if it
+        # is already sorted, False if sorting is needed.
+        sorted = self._gcmap_sorted
+        self._gcmap_sorted = True
+        return sorted
+
     def put(self, retaddr, callshapeaddr):
         """'retaddr' is the address just after the CALL.
-        'callshapeaddr' is the address returned by encode_callshape()."""
+        'callshapeaddr' is the address of the raw 'shape' marker.
+        Both addresses are actually integers here."""
         index = self._gcmap_curlength
         if index + 2 > self._gcmap_maxlength:
-            self._enlarge_gcmap()
+            index = self._enlarge_gcmap()
         self._gcmap[index] = retaddr
         self._gcmap[index+1] = callshapeaddr
         self._gcmap_curlength = index + 2
+        self._gcmap_sorted = False
 
+    @rgc.no_collect
     def _enlarge_gcmap(self):
-        newlength = 250 + self._gcmap_maxlength * 2
-        newgcmap = lltype.malloc(self.GCMAP_ARRAY, newlength, flavor='raw',
-                                 track_allocation=False)
         oldgcmap = self._gcmap
-        for i in range(self._gcmap_curlength):
-            newgcmap[i] = oldgcmap[i]
-        self._gcmap = newgcmap
-        self._gcmap_maxlength = newlength
-        if oldgcmap:
-            lltype.free(oldgcmap, flavor='raw', track_allocation=False)
+        if self._gcmap_deadentries * 3 * 2 > self._gcmap_maxlength:
+            # More than 1/3rd of the entries are dead.  Don't actually
+            # enlarge the gcmap table, but just clean up the dead entries.
+            newgcmap = oldgcmap
+        else:
+            # Normal path: enlarge the array.
+            newlength = 250 + (self._gcmap_maxlength // 3) * 4
+            newgcmap = lltype.malloc(self.GCMAP_ARRAY, newlength, flavor='raw',
+                                     track_allocation=False)
+            self._gcmap_maxlength = newlength
+        #
+        j = 0
+        i = 0
+        end = self._gcmap_curlength
+        while i < end:
+            if oldgcmap[i + 1]:
+                newgcmap[j] = oldgcmap[i]
+                newgcmap[j + 1] = oldgcmap[i + 1]
+                j += 2
+            i += 2
+        self._gcmap_curlength = j
+        self._gcmap_deadentries = 0
+        if oldgcmap != newgcmap:
+            self._gcmap = newgcmap
+            if oldgcmap:
+                lltype.free(oldgcmap, flavor='raw', track_allocation=False)
+        return j
+
+    @rgc.no_collect
+    def freeing_block(self, start, stop):
+        # if [start:stop] is a raw block of assembler, then look up the
+        # corresponding gcroot markers, and mark them as freed now in
+        # self._gcmap by setting the 2nd address of every entry to NULL.
+        gcmapstart = self.gcmapstart()
+        gcmapend   = self.gcmapend()
+        if gcmapstart == gcmapend:
+            return
+        if not self.gcmarksorted():
+            asmgcroot.sort_gcmap(gcmapstart, gcmapend)
+        # A note about gcmarksorted(): the deletion we do here keeps the
+        # array sorted.  This avoids needing too many sort_gcmap()s.
+        # Indeed, freeing_block() is typically called many times in a row,
+        # so it will call sort_gcmap() at most the first time.
+        startaddr = rffi.cast(llmemory.Address, start)
+        stopaddr  = rffi.cast(llmemory.Address, stop)
+        item = asmgcroot.binary_search(gcmapstart, gcmapend, startaddr)
+        # 'item' points to one of the entries.  Because the whole array
+        # is sorted, we know that it points either to the first entry we
+        # want to kill, or to the previous entry.
+        if item.address[0] < startaddr:
+            item += asmgcroot.arrayitemsize    # go forward one entry
+            assert item == gcmapend or item.address[0] >= startaddr
+        while item != gcmapend and item.address[0] < stopaddr:
+            item.address[1] = llmemory.NULL
+            self._gcmap_deadentries += 1
+            item += asmgcroot.arrayitemsize
 
     def get_basic_shape(self, is_64_bit=False):
         # XXX: Should this code even really know about stack frame layout of
@@ -304,17 +377,15 @@
         assert reg_index > 0
         shape.append(chr(self.LOC_REG | (reg_index << 2)))
 
-    def compress_callshape(self, shape):
+    def compress_callshape(self, shape, datablockwrapper):
         # Similar to compress_callshape() in trackgcroot.py.
-        # XXX so far, we always allocate a new small array (we could regroup
-        # them inside bigger arrays) and we never try to share them.
+        # Returns an address to raw memory (as an integer).
         length = len(shape)
-        compressed = lltype.malloc(self.CALLSHAPE_ARRAY, length,
-                                   flavor='raw',
-                                   track_allocation=False)   # memory leak
+        rawaddr = datablockwrapper.malloc_aligned(length, 1)
+        p = rffi.cast(self.CALLSHAPE_ARRAY_PTR, rawaddr)
         for i in range(length):
-            compressed[length-1-i] = rffi.cast(rffi.UCHAR, shape[i])
-        return llmemory.cast_ptr_to_adr(compressed)
+            p[length-1-i] = rffi.cast(rffi.UCHAR, shape[i])
+        return rawaddr
 
 
 class WriteBarrierDescr(AbstractDescr):
@@ -379,6 +450,7 @@
             'layoutbuilder': self.layoutbuilder,
             'gcmapstart': lambda: gcrootmap.gcmapstart(),
             'gcmapend': lambda: gcrootmap.gcmapend(),
+            'gcmarksorted': lambda: gcrootmap.gcmarksorted(),
             }
         self.GCClass = self.layoutbuilder.GCClass
         self.moving_gc = self.GCClass.moving_gc
@@ -641,6 +713,9 @@
     def has_write_barrier_class(self):
         return WriteBarrierDescr
 
+    def freeing_block(self, start, stop):
+        self.gcrootmap.freeing_block(start, stop)
+
 # ____________________________________________________________
 
 def get_ll_description(gcdescr, translator=None, rtyper=None):

Modified: pypy/branch/jitypes2/pypy/jit/backend/llsupport/llmodel.py
==============================================================================
--- pypy/branch/jitypes2/pypy/jit/backend/llsupport/llmodel.py	(original)
+++ pypy/branch/jitypes2/pypy/jit/backend/llsupport/llmodel.py	Fri Dec  3 11:04:29 2010
@@ -18,6 +18,7 @@
 from pypy.jit.backend.llsupport.descr import BaseIntCallDescr, GcPtrCallDescr
 from pypy.jit.backend.llsupport.descr import FloatCallDescr, VoidCallDescr
 from pypy.jit.backend.llsupport.ffisupport import get_call_descr_dynamic
+from pypy.jit.backend.llsupport.asmmemmgr import AsmMemoryManager
 from pypy.rpython.annlowlevel import cast_instance_to_base_ptr
 
 
@@ -52,6 +53,7 @@
         else:
             self._setup_exception_handling_untranslated()
         self.saved_exc_value = lltype.nullptr(llmemory.GCREF.TO)
+        self.asmmemmgr = AsmMemoryManager()
         self.setup()
         if translate_support_code:
             self._setup_on_leave_jitted_translated()
@@ -177,6 +179,15 @@
         self.saved_exc_value = lltype.nullptr(llmemory.GCREF.TO)
         return exc
 
+    def free_loop_and_bridges(self, compiled_loop_token):
+        AbstractCPU.free_loop_and_bridges(self, compiled_loop_token)
+        blocks = compiled_loop_token.asmmemmgr_blocks
+        if blocks is not None:
+            compiled_loop_token.asmmemmgr_blocks = None
+            for rawstart, rawstop in blocks:
+                self.gc_ll_descr.freeing_block(rawstart, rawstop)
+                self.asmmemmgr.free(rawstart, rawstop)
+
     # ------------------- helpers and descriptions --------------------
 
     @staticmethod

Modified: pypy/branch/jitypes2/pypy/jit/backend/llsupport/test/test_gc.py
==============================================================================
--- pypy/branch/jitypes2/pypy/jit/backend/llsupport/test/test_gc.py	(original)
+++ pypy/branch/jitypes2/pypy/jit/backend/llsupport/test/test_gc.py	Fri Dec  3 11:04:29 2010
@@ -9,6 +9,7 @@
 from pypy.jit.tool.oparser import parse
 from pypy.rpython.lltypesystem.rclass import OBJECT, OBJECT_VTABLE
 from pypy.jit.metainterp.test.test_optimizeopt import equaloplists
+from pypy.rpython.memory.gctransform import asmgcroot
 
 def test_boehm():
     gc_ll_descr = GcLLDescr_boehm(None, None, None)
@@ -62,58 +63,169 @@
     for i in range(len(allocs)):
         assert addrs[i].address[0] == llmemory.cast_ptr_to_adr(allocs[i])
 
-def test_GcRootMap_asmgcc():
-    def frame_pos(n):
-        return -4*(4+n)
-    gcrootmap = GcRootMap_asmgcc()
-    num1 = frame_pos(-5)
-    num1a = num1|2
-    num2 = frame_pos(55)
-    num2a = ((-num2|3) >> 7) | 128
-    num2b = (-num2|3) & 127
-    shape = gcrootmap.get_basic_shape()
-    gcrootmap.add_ebp_offset(shape, num1)
-    gcrootmap.add_ebp_offset(shape, num2)
-    assert shape == map(chr, [6, 7, 11, 15, 2, 0, num1a, num2b, num2a])
-    gcrootmap.add_callee_save_reg(shape, 1)
-    assert shape == map(chr, [6, 7, 11, 15, 2, 0, num1a, num2b, num2a,
-                              4])
-    gcrootmap.add_callee_save_reg(shape, 2)
-    assert shape == map(chr, [6, 7, 11, 15, 2, 0, num1a, num2b, num2a,
-                              4, 8])
-    gcrootmap.add_callee_save_reg(shape, 3)
-    assert shape == map(chr, [6, 7, 11, 15, 2, 0, num1a, num2b, num2a,
-                              4, 8, 12])
-    gcrootmap.add_callee_save_reg(shape, 4)
-    assert shape == map(chr, [6, 7, 11, 15, 2, 0, num1a, num2b, num2a,
-                              4, 8, 12, 16])
-    #
-    shapeaddr = gcrootmap.compress_callshape(shape)
-    PCALLSHAPE = lltype.Ptr(GcRootMap_asmgcc.CALLSHAPE_ARRAY)
-    p = llmemory.cast_adr_to_ptr(shapeaddr, PCALLSHAPE)
-    for i, expected in enumerate([16, 12, 8, 4,
-                                  num2a, num2b, num1a, 0, 2, 15, 11, 7, 6]):
-        assert p[i] == expected
-    #
-    retaddr = rffi.cast(llmemory.Address, 1234567890)
-    gcrootmap.put(retaddr, shapeaddr)
-    assert gcrootmap._gcmap[0] == retaddr
-    assert gcrootmap._gcmap[1] == shapeaddr
-    assert gcrootmap.gcmapstart().address[0] == retaddr
-    #
-    # the same as before, but enough times to trigger a few resizes
-    expected_shapeaddr = {}
-    for i in range(1, 700):
+class TestGcRootMapAsmGcc:
+
+    def test_make_shapes(self):
+        def frame_pos(n):
+            return -4*(4+n)
+        gcrootmap = GcRootMap_asmgcc()
+        num1 = frame_pos(-5)
+        num1a = num1|2
+        num2 = frame_pos(55)
+        num2a = ((-num2|3) >> 7) | 128
+        num2b = (-num2|3) & 127
         shape = gcrootmap.get_basic_shape()
-        gcrootmap.add_ebp_offset(shape, frame_pos(i))
-        shapeaddr = gcrootmap.compress_callshape(shape)
-        expected_shapeaddr[i] = shapeaddr
-        retaddr = rffi.cast(llmemory.Address, 123456789 + i)
+        gcrootmap.add_ebp_offset(shape, num1)
+        gcrootmap.add_ebp_offset(shape, num2)
+        assert shape == map(chr, [6, 7, 11, 15, 2, 0, num1a, num2b, num2a])
+        gcrootmap.add_callee_save_reg(shape, 1)
+        assert shape == map(chr, [6, 7, 11, 15, 2, 0, num1a, num2b, num2a,
+                                  4])
+        gcrootmap.add_callee_save_reg(shape, 2)
+        assert shape == map(chr, [6, 7, 11, 15, 2, 0, num1a, num2b, num2a,
+                                  4, 8])
+        gcrootmap.add_callee_save_reg(shape, 3)
+        assert shape == map(chr, [6, 7, 11, 15, 2, 0, num1a, num2b, num2a,
+                                  4, 8, 12])
+        gcrootmap.add_callee_save_reg(shape, 4)
+        assert shape == map(chr, [6, 7, 11, 15, 2, 0, num1a, num2b, num2a,
+                                  4, 8, 12, 16])
+
+    def test_compress_callshape(self):
+        class FakeDataBlockWrapper:
+            def malloc_aligned(self, size, alignment):
+                assert alignment == 1    # here
+                assert size == 4
+                return rffi.cast(lltype.Signed, p)
+        datablockwrapper = FakeDataBlockWrapper()
+        p = lltype.malloc(rffi.CArray(lltype.Char), 4, immortal=True)
+        gcrootmap = GcRootMap_asmgcc()
+        shape = ['a', 'b', 'c', 'd']
+        gcrootmap.compress_callshape(shape, datablockwrapper)
+        assert p[0] == 'd'
+        assert p[1] == 'c'
+        assert p[2] == 'b'
+        assert p[3] == 'a'
+
+    def test_put_basic(self):
+        gcrootmap = GcRootMap_asmgcc()
+        retaddr = 1234567890
+        shapeaddr = 51627384
         gcrootmap.put(retaddr, shapeaddr)
-    for i in range(1, 700):
-        expected_retaddr = rffi.cast(llmemory.Address, 123456789 + i)
-        assert gcrootmap._gcmap[i*2+0] == expected_retaddr
-        assert gcrootmap._gcmap[i*2+1] == expected_shapeaddr[i]
+        assert gcrootmap._gcmap[0] == retaddr
+        assert gcrootmap._gcmap[1] == shapeaddr
+        p = rffi.cast(rffi.LONGP, gcrootmap.gcmapstart())
+        assert p[0] == retaddr
+        assert (gcrootmap.gcmapend() ==
+                gcrootmap.gcmapstart() + rffi.sizeof(lltype.Signed) * 2)
+
+    def test_put_resize(self):
+        # the same as before, but enough times to trigger a few resizes
+        gcrootmap = GcRootMap_asmgcc()
+        for i in range(700):
+            shapeaddr = i * 100 + 1
+            retaddr = 123456789 + i
+            gcrootmap.put(retaddr, shapeaddr)
+        for i in range(700):
+            assert gcrootmap._gcmap[i*2+0] == 123456789 + i
+            assert gcrootmap._gcmap[i*2+1] == i * 100 + 1
+
+    def test_remove_nulls(self):
+        expected = []
+        def check():
+            assert gcrootmap._gcmap_curlength == len(expected) * 2
+            for i, (a, b) in enumerate(expected):
+                assert gcrootmap._gcmap[i*2] == a
+                assert gcrootmap._gcmap[i*2+1] == b
+        #
+        gcrootmap = GcRootMap_asmgcc()
+        for i in range(700):
+            shapeaddr = i * 100       # 0 if i == 0
+            retaddr = 123456789 + i
+            gcrootmap.put(retaddr, shapeaddr)
+            if shapeaddr != 0:
+                expected.append((retaddr, shapeaddr))
+        # at the first resize, the 0 should be removed
+        check()
+        for repeat in range(10):
+            # now clear up half the entries
+            assert len(expected) == 699
+            for i in range(0, len(expected), 2):
+                gcrootmap._gcmap[i*2+1] = 0
+                gcrootmap._gcmap_deadentries += 1
+            expected = expected[1::2]
+            assert gcrootmap._gcmap_deadentries*6 > gcrootmap._gcmap_maxlength
+            # check that we can again insert 350 entries without a resize
+            oldgcmap = gcrootmap._gcmap
+            for i in range(0, 699, 2):
+                gcrootmap.put(515151 + i + repeat, 626262 + i)
+                expected.append((515151 + i + repeat, 626262 + i))
+            assert gcrootmap._gcmap == oldgcmap
+            check()
+
+    def test_freeing_block(self):
+        from pypy.jit.backend.llsupport import gc
+        class Asmgcroot:
+            arrayitemsize = 2 * llmemory.sizeof(llmemory.Address)
+            sort_count = 0
+            def sort_gcmap(self, gcmapstart, gcmapend):
+                self.sort_count += 1
+            def binary_search(self, gcmapstart, gcmapend, startaddr):
+                i = 0
+                while (i < gcrootmap._gcmap_curlength//2 and
+                       gcrootmap._gcmap[i*2] < startaddr):
+                    i += 1
+                if i > 0:
+                    i -= 1
+                assert 0 <= i < gcrootmap._gcmap_curlength//2
+                p = rffi.cast(rffi.CArrayPtr(llmemory.Address), gcmapstart)
+                p = rffi.ptradd(p, 2*i)
+                return llmemory.cast_ptr_to_adr(p)
+        saved = gc.asmgcroot
+        try:
+            gc.asmgcroot = Asmgcroot()
+            #
+            gcrootmap = GcRootMap_asmgcc()
+            gcrootmap._gcmap = lltype.malloc(gcrootmap.GCMAP_ARRAY,
+                                             1400, flavor='raw',
+                                             immortal=True)
+            for i in range(700):
+                gcrootmap._gcmap[i*2] = 1200000 + i
+                gcrootmap._gcmap[i*2+1] = i * 100 + 1
+            assert gcrootmap._gcmap_deadentries == 0
+            assert gc.asmgcroot.sort_count == 0
+            gcrootmap._gcmap_maxlength = 1400
+            gcrootmap._gcmap_curlength = 1400
+            gcrootmap._gcmap_sorted = False
+            #
+            gcrootmap.freeing_block(1200000 - 100, 1200000)
+            assert gcrootmap._gcmap_deadentries == 0
+            assert gc.asmgcroot.sort_count == 1
+            #
+            gcrootmap.freeing_block(1200000 + 100, 1200000 + 200)
+            assert gcrootmap._gcmap_deadentries == 100
+            assert gc.asmgcroot.sort_count == 1
+            for i in range(700):
+                if 100 <= i < 200:
+                    expected = 0
+                else:
+                    expected = i * 100 + 1
+                assert gcrootmap._gcmap[i*2] == 1200000 + i
+                assert gcrootmap._gcmap[i*2+1] == expected
+            #
+            gcrootmap.freeing_block(1200000 + 650, 1200000 + 750)
+            assert gcrootmap._gcmap_deadentries == 150
+            assert gc.asmgcroot.sort_count == 1
+            for i in range(700):
+                if 100 <= i < 200 or 650 <= i:
+                    expected = 0
+                else:
+                    expected = i * 100 + 1
+                assert gcrootmap._gcmap[i*2] == 1200000 + i
+                assert gcrootmap._gcmap[i*2+1] == expected
+        #
+        finally:
+            gc.asmgcroot = saved
 
 
 class FakeLLOp(object):

Modified: pypy/branch/jitypes2/pypy/jit/backend/model.py
==============================================================================
--- pypy/branch/jitypes2/pypy/jit/backend/model.py	(original)
+++ pypy/branch/jitypes2/pypy/jit/backend/model.py	Fri Dec  3 11:04:29 2010
@@ -1,3 +1,4 @@
+from pypy.rlib.debug import debug_start, debug_print, debug_stop
 from pypy.jit.metainterp import history, compile
 
 
@@ -7,17 +8,27 @@
     done_with_this_frame_int_v = -1
     done_with_this_frame_ref_v = -1
     done_with_this_frame_float_v = -1
+    total_compiled_loops = 0
+    total_compiled_bridges = 0
+    total_freed_loops = 0
+    total_freed_bridges = 0
 
     def __init__(self):
         self.fail_descr_list = []
+        self.fail_descr_free_list = []
 
     def get_fail_descr_number(self, descr):
         assert isinstance(descr, history.AbstractFailDescr)
         n = descr.index
         if n < 0:
             lst = self.fail_descr_list
-            n = len(lst)
-            lst.append(descr)
+            if len(self.fail_descr_free_list) > 0:
+                n = self.fail_descr_free_list.pop()
+                assert lst[n] is None
+                lst[n] = descr
+            else:
+                n = len(lst)
+                lst.append(descr)
             descr.index = n
         return n
 
@@ -35,12 +46,14 @@
 
     def compile_loop(self, inputargs, operations, looptoken, log=True):
         """Assemble the given loop.
-        Extra attributes should be put in the LoopToken to
-        point to the compiled loop in assembler.
+        Should create and attach a fresh CompiledLoopToken to
+        looptoken.compiled_loop_token and stick extra attributes
+        on it to point to the compiled loop in assembler.
         """
         raise NotImplementedError
 
-    def compile_bridge(self, faildescr, inputargs, operations, log=True):
+    def compile_bridge(self, faildescr, inputargs, operations,
+                       original_loop_token, log=True):
         """Assemble the bridge.
         The FailDescr is the descr of the original guard that failed.
         """
@@ -113,6 +126,28 @@
         oldlooptoken so that from now own they will call newlooptoken."""
         raise NotImplementedError
 
+    def free_loop_and_bridges(self, compiled_loop_token):
+        """This method is called to free resources (machine code,
+        references to resume guards, etc.) allocated by the compilation
+        of a loop and all bridges attached to it.  After this call, the
+        frontend cannot use this compiled loop any more; in fact, it
+        guarantees that at the point of the call to free_code_group(),
+        none of the corresponding assembler is currently running.
+        """
+        # The base class provides a limited implementation: freeing the
+        # resume descrs.  This is already quite helpful, because the
+        # resume descrs are the largest consumers of memory (about 3x
+        # more than the assembler, in the case of the x86 backend).
+        lst = self.fail_descr_list
+        # We expect 'compiled_loop_token' to be itself garbage-collected soon,
+        # but better safe than sorry: be ready to handle several calls to
+        # free_loop_and_bridges() for the same compiled_loop_token.
+        faildescr_indices = compiled_loop_token.faildescr_indices
+        compiled_loop_token.faildescr_indices = []
+        for n in faildescr_indices:
+            lst[n] = None
+        self.fail_descr_free_list.extend(faildescr_indices)
+
     @staticmethod
     def sizeof(S):
         raise NotImplementedError
@@ -237,3 +272,40 @@
 
     def force(self, force_token):
         raise NotImplementedError
+
+
+class CompiledLoopToken(object):
+    asmmemmgr_blocks = None
+    asmmemmgr_gcroots = 0
+
+    def __init__(self, cpu, number):
+        cpu.total_compiled_loops += 1
+        self.cpu = cpu
+        self.number = number
+        self.bridges_count = 0
+        # This growing list gives the 'descr_number' of all fail descrs
+        # that belong to this loop or to a bridge attached to it.
+        # Filled by the frontend calling record_faildescr_index().
+        self.faildescr_indices = []
+        debug_start("jit-mem-looptoken-alloc")
+        debug_print("allocating Loop #", self.number)
+        debug_stop("jit-mem-looptoken-alloc")
+
+    def record_faildescr_index(self, n):
+        self.faildescr_indices.append(n)
+
+    def compiling_a_bridge(self):
+        self.cpu.total_compiled_bridges += 1
+        self.bridges_count += 1
+        debug_start("jit-mem-looptoken-alloc")
+        debug_print("allocating Bridge #", self.bridges_count, "of Loop #", self.number)
+        debug_stop("jit-mem-looptoken-alloc")
+
+    def __del__(self):
+        debug_start("jit-mem-looptoken-free")
+        debug_print("freeing Loop #", self.number, 'with',
+                    self.bridges_count, 'attached bridges')
+        self.cpu.free_loop_and_bridges(self)
+        self.cpu.total_freed_loops += 1
+        self.cpu.total_freed_bridges += self.bridges_count
+        debug_stop("jit-mem-looptoken-free")

Modified: pypy/branch/jitypes2/pypy/jit/backend/test/runner_test.py
==============================================================================
--- pypy/branch/jitypes2/pypy/jit/backend/test/runner_test.py	(original)
+++ pypy/branch/jitypes2/pypy/jit/backend/test/runner_test.py	Fri Dec  3 11:04:29 2010
@@ -174,6 +174,8 @@
         assert not wr_i1() and not wr_guard()
 
     def test_compile_bridge(self):
+        self.cpu.total_compiled_loops = 0
+        self.cpu.total_compiled_bridges = 0
         i0 = BoxInt()
         i1 = BoxInt()
         i2 = BoxInt()
@@ -199,7 +201,7 @@
         ]
         bridge[1].setfailargs([i1b])
 
-        self.cpu.compile_bridge(faildescr1, [i1b], bridge)        
+        self.cpu.compile_bridge(faildescr1, [i1b], bridge, looptoken)
 
         self.cpu.set_future_value_int(0, 2)
         fail = self.cpu.execute_token(looptoken)
@@ -207,6 +209,10 @@
         res = self.cpu.get_latest_value_int(0)
         assert res == 20
 
+        assert self.cpu.total_compiled_loops == 1
+        assert self.cpu.total_compiled_bridges == 1
+        return looptoken
+
     def test_compile_bridge_with_holes(self):
         i0 = BoxInt()
         i1 = BoxInt()
@@ -233,7 +239,7 @@
         ]
         bridge[1].setfailargs([i1b])
 
-        self.cpu.compile_bridge(faildescr1, [i1b], bridge)        
+        self.cpu.compile_bridge(faildescr1, [i1b], bridge, looptoken)
 
         self.cpu.set_future_value_int(0, 2)
         fail = self.cpu.execute_token(looptoken)
@@ -1050,7 +1056,7 @@
             ResOperation(rop.JUMP, [f3] + fboxes2[1:], None, descr=looptoken),
         ]
 
-        self.cpu.compile_bridge(faildescr1, fboxes2, bridge)
+        self.cpu.compile_bridge(faildescr1, fboxes2, bridge, looptoken)
 
         for i in range(len(fboxes)):
             self.cpu.set_future_value_float(i, 13.5 + 6.73 * i)
@@ -1197,6 +1203,13 @@
         yield nan_and_infinity, rop.FLOAT_GT,  operator.gt,  all_cases_binary
         yield nan_and_infinity, rop.FLOAT_GE,  operator.ge,  all_cases_binary
 
+    def test_noops(self):
+        c_box = self.alloc_string("hi there").constbox()
+        c_nest = ConstInt(0)
+        self.execute_operation(rop.DEBUG_MERGE_POINT, [c_box, c_nest], 'void')
+        self.execute_operation(rop.JIT_DEBUG, [c_box, c_nest, c_nest,
+                                               c_nest, c_nest], 'void')
+
 
 class LLtypeBackendTest(BaseBackendTest):
 
@@ -2224,6 +2237,20 @@
             assert res.value == expected, (
                 "%r: got %r, expected %r" % (RESTYPE, res.value, expected))
 
+    def test_free_loop_and_bridges(self):
+        from pypy.jit.backend.llsupport.llmodel import AbstractLLCPU
+        if not isinstance(self.cpu, AbstractLLCPU):
+            py.test.skip("not a subclass of llmodel.AbstractLLCPU")
+        if hasattr(self.cpu, 'setup_once'):
+            self.cpu.setup_once()
+        mem0 = self.cpu.asmmemmgr.total_mallocs
+        looptoken = self.test_compile_bridge()
+        mem1 = self.cpu.asmmemmgr.total_mallocs
+        self.cpu.free_loop_and_bridges(looptoken.compiled_loop_token)
+        mem2 = self.cpu.asmmemmgr.total_mallocs
+        assert mem2 < mem1
+        assert mem2 == mem0
+
 
 class OOtypeBackendTest(BaseBackendTest):
 

Modified: pypy/branch/jitypes2/pypy/jit/backend/test/test_random.py
==============================================================================
--- pypy/branch/jitypes2/pypy/jit/backend/test/test_random.py	(original)
+++ pypy/branch/jitypes2/pypy/jit/backend/test/test_random.py	Fri Dec  3 11:04:29 2010
@@ -524,7 +524,7 @@
         self.prebuilt_ptr_consts = []
         self.r = r
         self.build_random_loop(cpu, builder_factory, r, startvars)
-        
+
     def build_random_loop(self, cpu, builder_factory, r, startvars):
 
         loop = TreeLoop('test_random_function')
@@ -685,11 +685,12 @@
             subloop.operations[-1] = jump_op
             self.guard_op = rl.guard_op
             self.prebuilt_ptr_consts += rl.prebuilt_ptr_consts
+            self.loop.token.record_jump_to(rl.loop.token)
             self.dont_generate_more = True
         if r.random() < .05:
             return False
         self.builder.cpu.compile_bridge(fail_descr, fail_args,
-                                        subloop.operations)
+                                        subloop.operations, self.loop.token)
         return True
 
 def check_random_function(cpu, BuilderClass, r, num=None, max=None):

Modified: pypy/branch/jitypes2/pypy/jit/backend/x86/assembler.py
==============================================================================
--- pypy/branch/jitypes2/pypy/jit/backend/x86/assembler.py	(original)
+++ pypy/branch/jitypes2/pypy/jit/backend/x86/assembler.py	Fri Dec  3 11:04:29 2010
@@ -1,12 +1,13 @@
 import sys, os
 from pypy.jit.backend.llsupport import symbolic
+from pypy.jit.backend.llsupport.asmmemmgr import MachineDataBlockWrapper
 from pypy.jit.metainterp.history import Const, Box, BoxInt, BoxPtr, BoxFloat
 from pypy.jit.metainterp.history import (AbstractFailDescr, INT, REF, FLOAT,
                                          LoopToken)
 from pypy.rpython.lltypesystem import lltype, rffi, rstr, llmemory
 from pypy.rpython.lltypesystem.lloperation import llop
 from pypy.rpython.annlowlevel import llhelper
-from pypy.tool.uid import fixid
+from pypy.jit.backend.model import CompiledLoopToken
 from pypy.jit.backend.x86.regalloc import (RegAlloc, X86RegisterManager,
                                            X86XMMRegisterManager, get_ebp_ofs,
                                            _get_scale)
@@ -30,10 +31,11 @@
 from pypy.jit.backend.x86 import rx86, regloc, codebuf
 from pypy.jit.metainterp.resoperation import rop, ResOperation
 from pypy.jit.backend.x86.support import values_array
-from pypy.rlib.debug import debug_print
+from pypy.jit.backend.x86 import support
+from pypy.rlib.debug import (debug_print, debug_start, debug_stop,
+                             have_debug_prints)
 from pypy.rlib import rgc
 from pypy.jit.backend.x86.jump import remap_frame_layout
-from pypy.rlib.streamio import open_file_as_stream
 from pypy.jit.metainterp.history import ConstInt, BoxInt
 
 # darwin requires the stack to be 16 bytes aligned on calls. Same for gcc 4.5.0,
@@ -43,123 +45,17 @@
 def align_stack_words(words):
     return (words + CALL_ALIGN - 1) & ~(CALL_ALIGN-1)
 
-class MachineCodeBlockWrapper(object):
-    MC_DEFAULT_SIZE = 1024*1024
-
-    def __init__(self, assembler, bigsize, profile_agent=None):
-        self.assembler = assembler
-        self.old_mcs = [] # keepalive
-        self.bigsize = bigsize
-        self._mc = self._instantiate_mc()
-        self.function_name = None
-        self.profile_agent = profile_agent
-        self.reset_reserved_bytes()
-
-    def _instantiate_mc(self): # hook for testing
-        return codebuf.MachineCodeBlock(self.bigsize)
-
-    def ensure_bytes_available(self, num_bytes):
-        if self.bytes_free() <= (self._reserved_bytes + num_bytes):
-            self.make_new_mc()
-
-    def reserve_bytes(self, num_bytes):
-        self.ensure_bytes_available(num_bytes)
-        self._reserved_bytes += num_bytes
-
-    def reset_reserved_bytes(self):
-        # XXX er.... pretty random number, just to be sure
-        #     not to write half-instruction
-        self._reserved_bytes = 64
-
-    def get_relative_pos(self):
-        return self._mc.get_relative_pos()
-
-    def overwrite(self, pos, listofchars):
-        return self._mc.overwrite(pos, listofchars)
-
-    def bytes_free(self):
-        return self._mc._size - self._mc.get_relative_pos()
-
-    def start_function(self, name):
-        self.function_name = name
-        self.start_pos = self._mc.get_relative_pos()
-
-    def end_function(self, done=True):
-        assert self.function_name is not None
-        size = self._mc.get_relative_pos() - self.start_pos
-        address = self.tell() - size
-        if self.profile_agent is not None:
-            self.profile_agent.native_code_written(self.function_name,
-                                                   address, size)
-        if done:
-            self.function_name = None
-
-    def make_new_mc(self):
-        new_mc = self._instantiate_mc()
-        debug_print('[new machine code block at', new_mc.tell(), ']')
-
-        if IS_X86_64:
-            # The scratch register is sometimes used as a temporary
-            # register, but the JMP below might clobber it. Rather than risk
-            # subtle bugs, we preserve the scratch register across the jump.
-            self._mc.PUSH_r(X86_64_SCRATCH_REG.value)
-            
-        self._mc.JMP(imm(new_mc.tell()))
-
-        if IS_X86_64:
-            # Restore scratch reg
-            new_mc.POP_r(X86_64_SCRATCH_REG.value)
-
-        if self.function_name is not None:
-            self.end_function(done=False)
-            self.start_pos = new_mc.get_relative_pos()
-
-        self.assembler.write_pending_failure_recoveries()
-
-        self._mc.done()
-        self.old_mcs.append(self._mc)
-        self._mc = new_mc
-    make_new_mc._dont_inline_ = True
-
-    def tell(self):
-        return self._mc.tell()
-
-    def done(self):
-        self._mc.done()
-
-def _new_method(name):
-    def method(self, *args):
-        if self.bytes_free() < self._reserved_bytes:
-            self.make_new_mc()
-        getattr(self._mc, name)(*args)    
-    method.func_name = name
-    return method
-
-for _name in rx86.all_instructions + regloc.all_extra_instructions:
-    setattr(MachineCodeBlockWrapper, _name, _new_method(_name))
-
-for name in dir(codebuf.MachineCodeBlock):
-    if name.upper() == name or name == "writechr":
-        setattr(MachineCodeBlockWrapper, name, _new_method(name))
 
 class GuardToken(object):
-    def __init__(self, faildescr, failargs, fail_locs, exc, desc_bytes):
+    def __init__(self, faildescr, failargs, fail_locs, exc):
         self.faildescr = faildescr
         self.failargs = failargs
         self.fail_locs = fail_locs
         self.exc = exc
-        self.desc_bytes = desc_bytes
-
-    def recovery_stub_size(self):
-        # XXX: 32 is pulled out of the air
-        return 32 + len(self.desc_bytes)
 
 DEBUG_COUNTER = lltype.Struct('DEBUG_COUNTER', ('i', lltype.Signed))
 
 class Assembler386(object):
-    mc = None
-    mc_size = MachineCodeBlockWrapper.MC_DEFAULT_SIZE
-    _float_constants = None
     _regalloc = None
     _output_loop_log = None
 
@@ -177,16 +73,18 @@
         self.fail_boxes_float = values_array(lltype.Float, failargs_limit)
         self.fail_ebp = 0
         self.loop_run_counters = []
-        # if we have 10000 loops, we have some other problems I guess
         self.float_const_neg_addr = 0
         self.float_const_abs_addr = 0
         self.malloc_fixedsize_slowpath1 = 0
         self.malloc_fixedsize_slowpath2 = 0
-        self.pending_guard_tokens = None
         self.memcpy_addr = 0
         self.setup_failure_recovery()
         self._debug = False
         self.debug_counter_descr = cpu.fielddescrof(DEBUG_COUNTER, 'i')
+        self.fail_boxes_count = 0
+        self._current_depths_cache = (0, 0)
+        self.datablockwrapper = None
+        self.teardown()
 
     def leave_jitted_hook(self):
         ptrs = self.fail_boxes_ptr.ar
@@ -196,67 +94,65 @@
     def set_debug(self, v):
         self._debug = v
 
-    def setup(self):
-        if self.mc is None:
-            # the address of the function called by 'new'
-            gc_ll_descr = self.cpu.gc_ll_descr
-            gc_ll_descr.initialize()
-            ll_new = gc_ll_descr.get_funcptr_for_new()
-            self.malloc_func_addr = rffi.cast(lltype.Signed, ll_new)
-            if gc_ll_descr.get_funcptr_for_newarray is not None:
-                ll_new_array = gc_ll_descr.get_funcptr_for_newarray()
-                self.malloc_array_func_addr = rffi.cast(lltype.Signed,
-                                                        ll_new_array)
-            if gc_ll_descr.get_funcptr_for_newstr is not None:
-                ll_new_str = gc_ll_descr.get_funcptr_for_newstr()
-                self.malloc_str_func_addr = rffi.cast(lltype.Signed,
-                                                      ll_new_str)
-            if gc_ll_descr.get_funcptr_for_newunicode is not None:
-                ll_new_unicode = gc_ll_descr.get_funcptr_for_newunicode()
-                self.malloc_unicode_func_addr = rffi.cast(lltype.Signed,
-                                                          ll_new_unicode)
-            self.memcpy_addr = self.cpu.cast_ptr_to_int(codebuf.memcpy_fn)
-            self.mc = MachineCodeBlockWrapper(self, self.mc_size, self.cpu.profile_agent)
-            self._build_failure_recovery(False)
-            self._build_failure_recovery(True)
-            if self.cpu.supports_floats:
-                self._build_failure_recovery(False, withfloats=True)
-                self._build_failure_recovery(True, withfloats=True)
-                codebuf.ensure_sse2_floats()
-                self._build_float_constants()
-            if hasattr(gc_ll_descr, 'get_malloc_fixedsize_slowpath_addr'):
-                self._build_malloc_fixedsize_slowpath()
-            s = os.environ.get('PYPYLOG')
-            if s:
-                if s.find(':') != -1:
-                    s = s.split(':')[-1]
-                self.set_debug(True)
-                self._output_loop_log = s + ".count"
-            # Intialize here instead of __init__ to prevent
-            # pending_guard_tokens from being considered a prebuilt object,
-            # which sometimes causes memory leaks since the prebuilt list is
-            # still considered a GC root after we re-assign
-            # pending_guard_tokens in write_pending_failure_recoveries
-            self.pending_guard_tokens = []
+    def setup_once(self):
+        # the address of the function called by 'new'
+        gc_ll_descr = self.cpu.gc_ll_descr
+        gc_ll_descr.initialize()
+        ll_new = gc_ll_descr.get_funcptr_for_new()
+        self.malloc_func_addr = rffi.cast(lltype.Signed, ll_new)
+        if gc_ll_descr.get_funcptr_for_newarray is not None:
+            ll_new_array = gc_ll_descr.get_funcptr_for_newarray()
+            self.malloc_array_func_addr = rffi.cast(lltype.Signed,
+                                                    ll_new_array)
+        if gc_ll_descr.get_funcptr_for_newstr is not None:
+            ll_new_str = gc_ll_descr.get_funcptr_for_newstr()
+            self.malloc_str_func_addr = rffi.cast(lltype.Signed,
+                                                  ll_new_str)
+        if gc_ll_descr.get_funcptr_for_newunicode is not None:
+            ll_new_unicode = gc_ll_descr.get_funcptr_for_newunicode()
+            self.malloc_unicode_func_addr = rffi.cast(lltype.Signed,
+                                                      ll_new_unicode)
+        self.memcpy_addr = self.cpu.cast_ptr_to_int(support.memcpy_fn)
+        self._build_failure_recovery(False)
+        self._build_failure_recovery(True)
+        if self.cpu.supports_floats:
+            self._build_failure_recovery(False, withfloats=True)
+            self._build_failure_recovery(True, withfloats=True)
+            support.ensure_sse2_floats()
+            self._build_float_constants()
+        if hasattr(gc_ll_descr, 'get_malloc_fixedsize_slowpath_addr'):
+            self._build_malloc_fixedsize_slowpath()
+        debug_start('jit-backend-counts')
+        self.set_debug(have_debug_prints())
+        debug_stop('jit-backend-counts')
+
+    def setup(self, looptoken):
+        assert self.memcpy_addr != 0, "setup_once() not called?"
+        self.pending_guard_tokens = []
+        self.mc = codebuf.MachineCodeBlockWrapper()
+        if self.datablockwrapper is None:
+            allblocks = self.get_asmmemmgr_blocks(looptoken)
+            self.datablockwrapper = MachineDataBlockWrapper(self.cpu.asmmemmgr,
+                                                            allblocks)
+
+    def teardown(self):
+        self.pending_guard_tokens = None
+        self.mc = None
+        self.looppos = -1
+        self.currently_compiling_loop = None
 
     def finish_once(self):
         if self._debug:
-            output_log = self._output_loop_log
-            assert output_log is not None
-            f = open_file_as_stream(output_log, "w")
+            debug_start('jit-backend-counts')
             for i in range(len(self.loop_run_counters)):
-                name, struct = self.loop_run_counters[i]
-                f.write(str(name) + ":" +  str(struct.i) + "\n")
-            f.close()
+                struct = self.loop_run_counters[i]
+                debug_print(str(i) + ':' + str(struct.i))
+            debug_stop('jit-backend-counts')
 
     def _build_float_constants(self):
-        # 44 bytes: 32 bytes for the data, and up to 12 bytes for alignment
-        addr = lltype.malloc(rffi.CArray(lltype.Char), 44, flavor='raw',
-                             track_allocation=False)
-        if not we_are_translated():
-            self._keepalive_malloced_float_consts = addr
-        float_constants = rffi.cast(lltype.Signed, addr)
-        float_constants = (float_constants + 15) & ~15    # align to 16 bytes
+        datablockwrapper = MachineDataBlockWrapper(self.cpu.asmmemmgr, [])
+        float_constants = datablockwrapper.malloc_aligned(32, alignment=16)
+        datablockwrapper.done()
         addr = rffi.cast(rffi.CArrayPtr(lltype.Char), float_constants)
         qword_padding = '\x00\x00\x00\x00\x00\x00\x00\x00'
         # 0x8000000000000000
@@ -271,45 +167,56 @@
 
     def _build_malloc_fixedsize_slowpath(self):
         # ---------- first helper for the slow path of malloc ----------
-        self.malloc_fixedsize_slowpath1 = self.mc.tell()
+        mc = codebuf.MachineCodeBlockWrapper()
         if self.cpu.supports_floats:          # save the XMM registers in
             for i in range(self.cpu.NUM_REGS):# the *caller* frame, from esp+8
-                self.mc.MOVSD_sx((WORD*2)+8*i, i)
-        self.mc.SUB_rr(edx.value, eax.value)       # compute the size we want
+                mc.MOVSD_sx((WORD*2)+8*i, i)
+        mc.SUB_rr(edx.value, eax.value)       # compute the size we want
         if IS_X86_32:
-            self.mc.MOV_sr(WORD, edx.value)        # save it as the new argument
+            mc.MOV_sr(WORD, edx.value)        # save it as the new argument
         elif IS_X86_64:
             # rdi can be clobbered: its content was forced to the stack
             # by _fastpath_malloc(), like all other save_around_call_regs.
-            self.mc.MOV_rr(edi.value, edx.value)
+            mc.MOV_rr(edi.value, edx.value)
 
         addr = self.cpu.gc_ll_descr.get_malloc_fixedsize_slowpath_addr()
-        self.mc.JMP(imm(addr))                    # tail call to the real malloc
+        mc.JMP(imm(addr))                    # tail call to the real malloc
+        rawstart = mc.materialize(self.cpu.asmmemmgr, [])
+        self.malloc_fixedsize_slowpath1 = rawstart
         # ---------- second helper for the slow path of malloc ----------
-        self.malloc_fixedsize_slowpath2 = self.mc.tell()
+        mc = codebuf.MachineCodeBlockWrapper()
         if self.cpu.supports_floats:          # restore the XMM registers
             for i in range(self.cpu.NUM_REGS):# from where they were saved
-                self.mc.MOVSD_xs(i, (WORD*2)+8*i)
+                mc.MOVSD_xs(i, (WORD*2)+8*i)
         nursery_free_adr = self.cpu.gc_ll_descr.get_nursery_free_addr()
-        self.mc.MOV(edx, heap(nursery_free_adr))   # load this in EDX
-        self.mc.RET()
-        self.mc.done()
+        mc.MOV(edx, heap(nursery_free_adr))   # load this in EDX
+        mc.RET()
+        rawstart = mc.materialize(self.cpu.asmmemmgr, [])
+        self.malloc_fixedsize_slowpath2 = rawstart
 
     def assemble_loop(self, inputargs, operations, looptoken, log):
-        """adds the following attributes to looptoken:
+        '''adds the following attributes to looptoken:
                _x86_loop_code       (an integer giving an address)
                _x86_bootstrap_code  (an integer giving an address)
-               _x86_direct_bootstrap_code
+               _x86_direct_bootstrap_code  ( "    "     "    "   )
                _x86_frame_depth
                _x86_param_depth
                _x86_arglocs
                _x86_debug_checksum
-        """
+        '''
+        # XXX this function is too longish and contains some code
+        # duplication with assemble_bridge().  Also, we should think
+        # about not storing on 'self' attributes that will live only
+        # for the duration of compiling one loop or a one bridge.
+
+        clt = CompiledLoopToken(self.cpu, looptoken.number)
+        looptoken.compiled_loop_token = clt
         if not we_are_translated():
             # Arguments should be unique
             assert len(set(inputargs)) == len(inputargs)
 
-        self.setup()
+        self.setup(looptoken)
+        self.currently_compiling_loop = looptoken
         funcname = self._find_debug_merge_point(operations)
         if log:
             self._register_counter()
@@ -319,43 +226,61 @@
         arglocs = regalloc.prepare_loop(inputargs, operations, looptoken)
         looptoken._x86_arglocs = arglocs
 
-        # profile support
-        name = "Loop # %s: %s" % (looptoken.number, funcname)
-        self.mc.start_function(name)
-        looptoken._x86_bootstrap_code = self.mc.tell()
-        adr_stackadjust = self._assemble_bootstrap_code(inputargs, arglocs)
-        curadr = self.mc.tell()
-        looptoken._x86_loop_code = curadr
+        bootstrappos = self.mc.get_relative_pos()
+        stackadjustpos = self._assemble_bootstrap_code(inputargs, arglocs)
+        self.looppos = self.mc.get_relative_pos()
         looptoken._x86_frame_depth = -1     # temporarily
         looptoken._x86_param_depth = -1     # temporarily        
         frame_depth, param_depth = self._assemble(regalloc, operations)
-        self._patch_stackadjust(adr_stackadjust, frame_depth+param_depth)
         looptoken._x86_frame_depth = frame_depth
         looptoken._x86_param_depth = param_depth
 
-        looptoken._x86_direct_bootstrap_code = self.mc.tell()
-        self._assemble_bootstrap_direct_call(arglocs, curadr,
+        directbootstrappos = self.mc.get_relative_pos()
+        self._assemble_bootstrap_direct_call(arglocs, self.looppos,
                                              frame_depth+param_depth)
-        #
-        debug_print("Loop #%d has address %x to %x" % (looptoken.number,
-                                                       looptoken._x86_loop_code,
-                                                       self.mc.tell()))
-        self.mc.end_function()
         self.write_pending_failure_recoveries()
-        
-    def assemble_bridge(self, faildescr, inputargs, operations, log):
+        fullsize = self.mc.get_relative_pos()
+        #
+        rawstart = self.materialize_loop(looptoken)
+        debug_print("Loop #%d (%s) has address %x to %x" % (
+            looptoken.number, funcname,
+            rawstart + self.looppos,
+            rawstart + directbootstrappos))
+        self._patch_stackadjust(rawstart + stackadjustpos,
+                                frame_depth + param_depth)
+        self.patch_pending_failure_recoveries(rawstart)
+        #
+        looptoken._x86_bootstrap_code = rawstart + bootstrappos
+        looptoken._x86_loop_code = rawstart + self.looppos
+        looptoken._x86_direct_bootstrap_code = rawstart + directbootstrappos
+        self.teardown()
+        # oprofile support
+        if self.cpu.profile_agent is not None:
+            name = "Loop # %s: %s" % (looptoken.number, funcname)
+            self.cpu.profile_agent.native_code_written(name,
+                                                       rawstart, fullsize)
+
+    def assemble_bridge(self, faildescr, inputargs, operations,
+                        original_loop_token, log):
         if not we_are_translated():
             # Arguments should be unique
             assert len(set(inputargs)) == len(inputargs)
 
-        self.setup()
+        descr_number = self.cpu.get_fail_descr_number(faildescr)
+        try:
+            failure_recovery = self._find_failure_recovery_bytecode(faildescr)
+        except ValueError:
+            debug_print("Bridge out of guard", descr_number,
+                        "was already compiled!")
+            return
+
+        self.setup(original_loop_token)
         funcname = self._find_debug_merge_point(operations)
         if log:
             self._register_counter()
             operations = self._inject_debugging_code(faildescr, operations)
 
-        arglocs = self.rebuild_faillocs_from_descr(
-            faildescr._x86_failure_recovery_bytecode)
+        arglocs = self.rebuild_faillocs_from_descr(failure_recovery)
         if not we_are_translated():
             assert ([loc.assembler() for loc in arglocs] ==
                     [loc.assembler() for loc in faildescr._x86_debug_faillocs])
@@ -364,37 +289,63 @@
         regalloc.prepare_bridge(fail_depths, inputargs, arglocs,
                                 operations)
 
-        # oprofile support
-        descr_number = self.cpu.get_fail_descr_number(faildescr)
-        name = "Bridge # %s: %s" % (descr_number, funcname)
-        self.mc.start_function(name)
-
-        adr_bridge = self.mc.tell()
-        adr_stackadjust = self._patchable_stackadjust()
+        stackadjustpos = self._patchable_stackadjust()
         frame_depth, param_depth = self._assemble(regalloc, operations)
-        self._patch_stackadjust(adr_stackadjust, frame_depth+param_depth)
+        codeendpos = self.mc.get_relative_pos()
+        self.write_pending_failure_recoveries()
+        fullsize = self.mc.get_relative_pos()
+        #
+        rawstart = self.materialize_loop(original_loop_token)
+
+        debug_print("Bridge out of guard %d (%s) has address %x to %x" %
+                    (descr_number, funcname, rawstart, rawstart + codeendpos))
+        self._patch_stackadjust(rawstart + stackadjustpos,
+                                frame_depth + param_depth)
+        self.patch_pending_failure_recoveries(rawstart)
         if not we_are_translated():
             # for the benefit of tests
             faildescr._x86_bridge_frame_depth = frame_depth
             faildescr._x86_bridge_param_depth = param_depth
         # patch the jump from original guard
-        self.patch_jump_for_descr(faildescr, adr_bridge)
-        debug_print("Bridge out of guard %d has address %x to %x" %
-                    (descr_number, adr_bridge, self.mc.tell()))
-        self.mc.end_function()
-        self.write_pending_failure_recoveries()
+        self.patch_jump_for_descr(faildescr, rawstart)
+        self.teardown()
+        # oprofile support
+        if self.cpu.profile_agent is not None:
+            name = "Bridge # %s: %s" % (descr_number, funcname)
+            self.cpu.profile_agent.native_code_written(name,
+                                                       rawstart, fullsize)
 
     def write_pending_failure_recoveries(self):
+        # for each pending guard, generate the code of the recovery stub
+        # at the end of self.mc.
         for tok in self.pending_guard_tokens:
-            # Okay to write to _mc because we've already made sure that
-            # there's enough space by "reserving" bytes.
-            addr = self.generate_quick_failure(self.mc._mc, tok.faildescr, tok.failargs, tok.fail_locs, tok.exc, tok.desc_bytes)
-            tok.faildescr._x86_adr_recovery_stub = addr
-            self.patch_jump_for_descr(tok.faildescr, addr)
+            tok.pos_recovery_stub = self.generate_quick_failure(tok)
 
-        self.pending_guard_tokens = []
-        self.mc.reset_reserved_bytes()
-        self.mc.done()
+    def patch_pending_failure_recoveries(self, rawstart):
+        # after we wrote the assembler to raw memory, set up
+        # tok.faildescr._x86_adr_jump_offset to contain the raw address of
+        # the 4-byte target field in the JMP/Jcond instruction, and patch
+        # the field in question to point (initially) to the recovery stub
+        for tok in self.pending_guard_tokens:
+            addr = rawstart + tok.pos_jump_offset
+            tok.faildescr._x86_adr_jump_offset = addr
+            relative_target = tok.pos_recovery_stub - (tok.pos_jump_offset + 4)
+            assert rx86.fits_in_32bits(relative_target)
+            p = rffi.cast(rffi.INTP, addr)
+            p[0] = rffi.cast(rffi.INT, relative_target)
+
+    def get_asmmemmgr_blocks(self, looptoken):
+        clt = looptoken.compiled_loop_token
+        if clt.asmmemmgr_blocks is None:
+            clt.asmmemmgr_blocks = []
+        return clt.asmmemmgr_blocks
+
+    def materialize_loop(self, looptoken):
+        self.datablockwrapper.done()      # finish using cpu.asmmemmgr
+        self.datablockwrapper = None
+        allblocks = self.get_asmmemmgr_blocks(looptoken)
+        return self.mc.materialize(self.cpu.asmmemmgr, allblocks,
+                                   self.cpu.gc_ll_descr.gcrootmap)
 
     def _find_debug_merge_point(self, operations):
 
@@ -409,29 +360,50 @@
 
     def _register_counter(self):
         if self._debug:
+            # YYY very minor leak -- we need the counters to stay alive
+            # forever, just because we want to report them at the end
+            # of the process
             struct = lltype.malloc(DEBUG_COUNTER, flavor='raw',
-                                   track_allocation=False)   # known to leak
+                                   track_allocation=False)
             struct.i = 0
-            self.loop_run_counters.append((len(self.loop_run_counters), struct))
-        
+            self.loop_run_counters.append(struct)
+
+    def _find_failure_recovery_bytecode(self, faildescr):
+        adr_jump_offset = faildescr._x86_adr_jump_offset
+        if adr_jump_offset == 0:
+            raise ValueError
+        # follow the JMP/Jcond
+        p = rffi.cast(rffi.INTP, adr_jump_offset)
+        adr_target = adr_jump_offset + 4 + rffi.cast(lltype.Signed, p[0])
+        # skip the CALL
+        if WORD == 4:
+            adr_target += 5     # CALL imm
+        else:
+            adr_target += 13    # MOV r11, imm; CALL *r11
+        return adr_target
+
     def patch_jump_for_descr(self, faildescr, adr_new_target):
         adr_jump_offset = faildescr._x86_adr_jump_offset
-        adr_recovery_stub = faildescr._x86_adr_recovery_stub
+        assert adr_jump_offset != 0
         offset = adr_new_target - (adr_jump_offset + 4)
         # If the new target fits within a rel32 of the jump, just patch
         # that. Otherwise, leave the original rel32 to the recovery stub in
         # place, but clobber the recovery stub with a jump to the real
         # target.
+        mc = codebuf.MachineCodeBlockWrapper()
         if rx86.fits_in_32bits(offset):
-            mc = codebuf.InMemoryCodeBuilder(adr_jump_offset, adr_jump_offset + 4)
             mc.writeimm32(offset)
+            mc.copy_to_raw_memory(adr_jump_offset)
         else:
-            # "mov r11, addr; jmp r11" is 13 bytes
-            mc = codebuf.InMemoryCodeBuilder(adr_recovery_stub, adr_recovery_stub + 13)
+            # "mov r11, addr; jmp r11" is 13 bytes, which fits in there
+            # because we always write "mov r11, addr; call *r11" in the
+            # first place.
             mc.MOV_ri(X86_64_SCRATCH_REG.value, adr_new_target)
             mc.JMP_r(X86_64_SCRATCH_REG.value)
-
-        mc.done()
+            p = rffi.cast(rffi.INTP, adr_jump_offset)
+            adr_target = adr_jump_offset + 4 + rffi.cast(lltype.Signed, p[0])
+            mc.copy_to_raw_memory(adr_target)
+        faildescr._x86_adr_jump_offset = 0    # means "patched"
 
     @specialize.argtype(1)
     def _inject_debugging_code(self, looptoken, operations):
@@ -442,7 +414,7 @@
                 s += op.getopnum()
             looptoken._x86_debug_checksum = s
             c_adr = ConstInt(rffi.cast(lltype.Signed,
-                                     self.loop_run_counters[-1][1]))
+                                       self.loop_run_counters[-1]))
             box = BoxInt()
             box2 = BoxInt()
             ops = [ResOperation(rop.GETFIELD_RAW, [c_adr],
@@ -451,19 +423,11 @@
                    ResOperation(rop.SETFIELD_RAW, [c_adr, box2],
                                 None, descr=self.debug_counter_descr)]
             operations = ops + operations
-            # # we need one register free (a bit of a hack, but whatever)
-            # self.mc.PUSH(eax)
-            # adr = rffi.cast(lltype.Signed, self.loop_run_counters[-1][1])
-            # self.mc.MOV(eax, heap(adr))
-            # self.mc.ADD(eax, imm1)
-            # self.mc.MOV(heap(adr), eax)
-            # self.mc.POP(eax)
         return operations
 
     def _assemble(self, regalloc, operations):
         self._regalloc = regalloc
         regalloc.walk_operations(operations)        
-        self.mc.done()
         if we_are_translated() or self.cpu.dont_keepalive_stuff:
             self._regalloc = None   # else keep it around for debugging
         frame_depth = regalloc.fm.frame_depth
@@ -479,30 +443,31 @@
     def _patchable_stackadjust(self):
         # stack adjustment LEA
         self.mc.LEA32_rb(esp.value, 0)
-        return self.mc.tell() - 4
+        return self.mc.get_relative_pos() - 4
 
-    def _patch_stackadjust(self, adr_lea, reserved_depth):
+    def _patch_stackadjust(self, adr_lea, allocated_depth):
         # patch stack adjustment LEA
-        mc = codebuf.InMemoryCodeBuilder(adr_lea, adr_lea + 4)
-        # Compute the correct offset for the instruction LEA ESP, [EBP-4*words].
+        mc = codebuf.MachineCodeBlockWrapper()
+        # Compute the correct offset for the instruction LEA ESP, [EBP-4*words]
+        mc.writeimm32(self._get_offset_of_ebp_from_esp(allocated_depth))
+        mc.copy_to_raw_memory(adr_lea)
+
+    def _get_offset_of_ebp_from_esp(self, allocated_depth):
         # Given that [EBP] is where we saved EBP, i.e. in the last word
         # of our fixed frame, then the 'words' value is:
-        words = (self.cpu.FRAME_FIXED_SIZE - 1) + reserved_depth
-        # align, e.g. for Mac OS X        
+        words = (self.cpu.FRAME_FIXED_SIZE - 1) + allocated_depth
+        # align, e.g. for Mac OS X
         aligned_words = align_stack_words(words+2)-2 # 2 = EIP+EBP
-        mc.writeimm32(-WORD * aligned_words)
-        mc.done()
+        return -WORD * aligned_words
 
     def _call_header(self):
+        # NB. the shape of the frame is hard-coded in get_basic_shape() too.
+        # Also, make sure this is consistent with FRAME_FIXED_SIZE.
         self.mc.PUSH_r(ebp.value)
         self.mc.MOV_rr(ebp.value, esp.value)
         for regloc in self.cpu.CALLEE_SAVE_REGISTERS:
             self.mc.PUSH_r(regloc.value)
 
-        # NB. the shape of the frame is hard-coded in get_basic_shape() too.
-        # Also, make sure this is consistent with FRAME_FIXED_SIZE.
-        return self._patchable_stackadjust()
-
     def _call_footer(self):
         self.mc.LEA_rb(esp.value, -len(self.cpu.CALLEE_SAVE_REGISTERS) * WORD)
 
@@ -512,17 +477,16 @@
         self.mc.POP_r(ebp.value)
         self.mc.RET()
 
-    def _assemble_bootstrap_direct_call(self, arglocs, jmpadr, stackdepth):
+    def _assemble_bootstrap_direct_call(self, arglocs, jmppos, stackdepth):
         if IS_X86_64:
-            return self._assemble_bootstrap_direct_call_64(arglocs, jmpadr, stackdepth)
+            return self._assemble_bootstrap_direct_call_64(arglocs, jmppos, stackdepth)
         # XXX pushing ebx esi and edi is a bit pointless, since we store
         #     all regsiters anyway, for the case of guard_not_forced
         # XXX this can be improved greatly. Right now it'll behave like
         #     a normal call
         nonfloatlocs, floatlocs = arglocs
-        # XXX not to repeat the logic, a bit around
-        adr_stackadjust = self._call_header()
-        self._patch_stackadjust(adr_stackadjust, stackdepth)
+        self._call_header()
+        self.mc.LEA_rb(esp.value, self._get_offset_of_ebp_from_esp(stackdepth))
         for i in range(len(nonfloatlocs)):
             loc = nonfloatlocs[i]
             if isinstance(loc, RegLoc):
@@ -544,9 +508,11 @@
                 self.mc.MOVSD_xb(xmmtmp.value, (1 + i) * 2 * WORD)
                 assert isinstance(loc, StackLoc)
                 self.mc.MOVSD_bx(loc.value, xmmtmp.value)
-        self.mc.JMP_l(jmpadr)
+        endpos = self.mc.get_relative_pos() + 5
+        self.mc.JMP_l(jmppos - endpos)
+        assert endpos == self.mc.get_relative_pos()
 
-    def _assemble_bootstrap_direct_call_64(self, arglocs, jmpadr, stackdepth):
+    def _assemble_bootstrap_direct_call_64(self, arglocs, jmppos, stackdepth):
         # XXX: Very similar to _emit_call_64
 
         src_locs = []
@@ -560,8 +526,8 @@
         unused_xmm = [xmm7, xmm6, xmm5, xmm4, xmm3, xmm2, xmm1, xmm0]
 
         nonfloatlocs, floatlocs = arglocs
-        adr_stackadjust = self._call_header()
-        self._patch_stackadjust(adr_stackadjust, stackdepth)
+        self._call_header()
+        self.mc.LEA_rb(esp.value, self._get_offset_of_ebp_from_esp(stackdepth))
 
         # The lists are padded with Nones
         assert len(nonfloatlocs) == len(floatlocs)
@@ -597,8 +563,9 @@
                 # clobber the scratch register
                 self.mc.MOV(loc, X86_64_SCRATCH_REG)
 
-        finaljmp = self.mc.tell()
-        self.mc.JMP(imm(jmpadr))
+        endpos = self.mc.get_relative_pos() + 5
+        self.mc.JMP_l(jmppos - endpos)
+        assert endpos == self.mc.get_relative_pos()
 
     def redirect_call_assembler(self, oldlooptoken, newlooptoken):
         # some minimal sanity checking
@@ -611,16 +578,17 @@
         # Ideally we should rather patch all existing CALLs, but well.
         oldadr = oldlooptoken._x86_direct_bootstrap_code
         target = newlooptoken._x86_direct_bootstrap_code
-        mc = codebuf.InMemoryCodeBuilder(oldadr, oldadr + 16)
+        mc = codebuf.MachineCodeBlockWrapper()
         mc.JMP(imm(target))
-        mc.done()
+        mc.copy_to_raw_memory(oldadr)
 
     def _assemble_bootstrap_code(self, inputargs, arglocs):
         nonfloatlocs, floatlocs = arglocs
-        adr_stackadjust = self._call_header()
+        self._call_header()
+        stackadjustpos = self._patchable_stackadjust()
         tmp = X86RegisterManager.all_regs[0]
         xmmtmp = X86XMMRegisterManager.all_regs[0]
-        self.mc._mc.begin_reuse_scratch_register()
+        self.mc.begin_reuse_scratch_register()
         for i in range(len(nonfloatlocs)):
             loc = nonfloatlocs[i]
             if loc is None:
@@ -652,8 +620,8 @@
                 self.mc.MOVSD(xmmtmp, heap(adr))
                 assert isinstance(loc, StackLoc)
                 self.mc.MOVSD_bx(loc.value, xmmtmp.value)
-        self.mc._mc.end_reuse_scratch_register()
-        return adr_stackadjust
+        self.mc.end_reuse_scratch_register()
+        return stackadjustpos
 
     def dump(self, text):
         if not self.verbose:
@@ -661,7 +629,8 @@
         _prev = Box._extended_display
         try:
             Box._extended_display = False
-            print >> sys.stderr, ' 0x%x  %s' % (fixid(self.mc.tell()), text)
+            pos = self.mc.get_relative_pos()
+            print >> sys.stderr, ' 0x%x  %s' % (pos, text)
         finally:
             Box._extended_display = _prev
 
@@ -721,7 +690,7 @@
                                          arglocs, resloc)
         if not we_are_translated():
             # must be added by the genop_guard_list[]()
-            assert hasattr(faildescr, '_x86_adr_jump_offset')
+            assert guard_token is self.pending_guard_tokens[-1]
 
     def regalloc_perform_guard(self, guard_op, faillocs, arglocs, resloc,
                                current_depths):
@@ -794,9 +763,6 @@
                                   result_loc):
             guard_opnum = guard_op.getopnum()
             self.mc.UCOMISD(arglocs[0], arglocs[1])
-            # 16 is enough space for the rel8 jumps below and the rel32
-            # jump in implement_guard
-            self.mc.ensure_bytes_available(16 + guard_token.recovery_stub_size())
             if guard_opnum == rop.GUARD_FALSE:
                 if need_jp:
                     self.mc.J_il8(rx86.Conditions['P'], 6)
@@ -964,9 +930,6 @@
     def genop_guard_float_ne(self, op, guard_op, guard_token, arglocs, result_loc):
         guard_opnum = guard_op.getopnum()
         self.mc.UCOMISD(arglocs[0], arglocs[1])
-        # 16 is enough space for the rel8 jumps below and the rel32
-        # jump in implement_guard
-        self.mc.ensure_bytes_available(16 + guard_token.recovery_stub_size())
         if guard_opnum == rop.GUARD_TRUE:
             self.mc.J_il8(rx86.Conditions['P'], 6)
             self.implement_guard(guard_token, 'E')
@@ -1290,13 +1253,11 @@
                 self.mc.CMP32_mi((locs[0].value, 0), expected_typeid)
 
     def genop_guard_guard_class(self, ign_1, guard_op, guard_token, locs, ign_2):
-        self.mc.ensure_bytes_available(256)
         self._cmp_guard_class(locs)
         self.implement_guard(guard_token, 'NE')
 
     def genop_guard_guard_nonnull_class(self, ign_1, guard_op,
                                         guard_token, locs, ign_2):
-        self.mc.ensure_bytes_available(256)
         self.mc.CMP(locs[0], imm1)
         # Patched below
         self.mc.J_il8(rx86.Conditions['B'], 0)
@@ -1305,7 +1266,7 @@
         # patch the JB above
         offset = self.mc.get_relative_pos() - jb_location
         assert 0 < offset <= 127
-        self.mc.overwrite(jb_location-1, [chr(offset)])
+        self.mc.overwrite(jb_location-1, chr(offset))
         #
         self.implement_guard(guard_token, 'NE')
 
@@ -1314,42 +1275,33 @@
         exc = (guard_opnum == rop.GUARD_EXCEPTION or
                guard_opnum == rop.GUARD_NO_EXCEPTION or
                guard_opnum == rop.GUARD_NOT_FORCED)
-        desc_bytes = self.failure_recovery_description(failargs, fail_locs)
-        return GuardToken(faildescr, failargs, fail_locs, exc, desc_bytes)
+        return GuardToken(faildescr, failargs, fail_locs, exc)
 
-    def generate_quick_failure(self, mc, faildescr, failargs, fail_locs, exc, desc_bytes):
+    def generate_quick_failure(self, guardtok):
         """Generate the initial code for handling a failure.  We try to
-        keep it as compact as possible.  The idea is that this code is
-        executed at most once (and very often, zero times); when
-        executed, it generates a more complete piece of code which can
-        really handle recovery from this particular failure.
+        keep it as compact as possible.
         """
-        fail_index = self.cpu.get_fail_descr_number(faildescr)
-        addr = mc.tell()
+        fail_index = self.cpu.get_fail_descr_number(guardtok.faildescr)
+        mc = self.mc
+        startpos = mc.get_relative_pos()
         withfloats = False
-        for box in failargs:
+        for box in guardtok.failargs:
             if box is not None and box.type == FLOAT:
                 withfloats = True
                 break
+        exc = guardtok.exc
         mc.CALL(imm(self.failure_recovery_code[exc + 2 * withfloats]))
         # write tight data that describes the failure recovery
-        faildescr._x86_failure_recovery_bytecode = mc.tell()
-        for byte in desc_bytes:
-            mc.writechr(ord(byte))
+        self.write_failure_recovery_description(mc, guardtok.failargs,
+                                                guardtok.fail_locs)
         # write the fail_index too
         mc.writeimm32(fail_index)
         # for testing the decoding, write a final byte 0xCC
         if not we_are_translated():
-            mc.writechr(0xCC)
-            faildescr._x86_debug_faillocs = [loc for loc in fail_locs
-                                                 if loc is not None]
-
-        # Make sure the recovery stub is at least 16 bytes long (for the
-        # case where we overwrite the recovery stub with a 64-bit absolute
-        # jump)
-        while mc.tell() - addr < 16:
-            mc.writechr(0x00)
-        return addr
+            mc.writechar('\xCC')
+            faillocs = [loc for loc in guardtok.fail_locs if loc is not None]
+            guardtok.faildescr._x86_debug_faillocs = faillocs
+        return startpos
 
     DESCR_REF       = 0x00
     DESCR_INT       = 0x01
@@ -1360,8 +1312,7 @@
     CODE_STOP       = 0 | DESCR_SPECIAL
     CODE_HOLE       = 4 | DESCR_SPECIAL
 
-    def failure_recovery_description(self, failargs, locs):
-        desc_bytes = []
+    def write_failure_recovery_description(self, mc, failargs, locs):
         for i in range(len(failargs)):
             arg = failargs[i]
             if arg is not None:
@@ -1381,19 +1332,14 @@
                     n = loc.value
                 n = kind + 4*n
                 while n > 0x7F:
-                    desc_bytes.append(chr((n & 0x7F) | 0x80))
+                    mc.writechar(chr((n & 0x7F) | 0x80))
                     n >>= 7
             else:
                 n = self.CODE_HOLE
-            desc_bytes.append(chr(n))
-        desc_bytes.append(chr(self.CODE_STOP))
+            mc.writechar(chr(n))
+        mc.writechar(chr(self.CODE_STOP))
         # assert that the fail_boxes lists are big enough
         assert len(failargs) <= self.fail_boxes_int.SIZE
-        return desc_bytes
-
-    def write_failure_recovery_description(self, mc, failargs, locs):
-        for byte in self.failure_recovery_description(failargs, locs):
-            mc.writechr(ord(byte))
 
     def rebuild_faillocs_from_descr(self, bytecode):
         from pypy.jit.backend.x86.regalloc import X86FrameManager
@@ -1531,10 +1477,8 @@
                                          self.failure_recovery_func)
         failure_recovery_func = rffi.cast(lltype.Signed,
                                           failure_recovery_func)
-        mc = self.mc._mc
-        # Assume that we are called at the beginning, when there is no risk
-        # that 'mc' runs out of space.  Checked by asserts in mc.write().
-        recovery_addr = mc.tell()
+        mc = codebuf.MachineCodeBlockWrapper()
+        self.mc = mc
 
         # Push all general purpose registers
         for gpr in range(self.cpu.NUM_REGS-1, -1, -1):
@@ -1585,11 +1529,12 @@
         # above.
 
         self._call_footer()
-        self.mc.done()
-        self.failure_recovery_code[exc + 2 * withfloats] = recovery_addr
+        rawstart = mc.materialize(self.cpu.asmmemmgr, [])
+        self.failure_recovery_code[exc + 2 * withfloats] = rawstart
+        self.mc = None
 
     def generate_failure(self, fail_index, locs, exc, locs_are_ref):
-        self.mc._mc.begin_reuse_scratch_register()
+        self.mc.begin_reuse_scratch_register()
         for i in range(len(locs)):
             loc = locs[i]
             if isinstance(loc, RegLoc):
@@ -1616,7 +1561,7 @@
                         adr = self.fail_boxes_int.get_addr_for_num(i)
                     self.mc.MOV(eax, loc)
                     self.mc.MOV(heap(adr), eax)
-        self.mc._mc.end_reuse_scratch_register()
+        self.mc.end_reuse_scratch_register()
 
         # we call a provided function that will
         # - call our on_leave_jitted_hook which will mark
@@ -1632,17 +1577,13 @@
         self._call_footer()
 
     def implement_guard(self, guard_token, condition=None):
-        self.mc.reserve_bytes(guard_token.recovery_stub_size())
-        self.pending_guard_tokens.append(guard_token)
-        # These jumps are patched later, the mc.tell() are just
-        # dummy values.  Also, use self.mc._mc to avoid triggering a
-        # "buffer full" exactly here.
-        mc = self.mc._mc
+        # These jumps are patched later.
         if condition:
-            mc.J_il(rx86.Conditions[condition], mc.tell())
+            self.mc.J_il(rx86.Conditions[condition], 0)
         else:
-            mc.JMP_l(mc.tell())
-        guard_token.faildescr._x86_adr_jump_offset = mc.tell() - 4
+            self.mc.JMP_l(0)
+        guard_token.pos_jump_offset = self.mc.get_relative_pos() - 4
+        self.pending_guard_tokens.append(guard_token)
 
     def genop_call(self, op, arglocs, resloc):
         sizeloc = arglocs[0]
@@ -1697,7 +1638,6 @@
         # Write a call to the direct_bootstrap_code of the target assembler
         self._emit_call(imm(descr._x86_direct_bootstrap_code), arglocs, 2,
                         tmp=eax)
-        self.mc.ensure_bytes_available(256)
         if op.result is None:
             assert result_loc is None
             value = self.cpu.done_with_this_frame_void_v
@@ -1733,7 +1673,7 @@
         # Path B: fast path.  Must load the return value, and reset the token
         offset = jmp_location - je_location
         assert 0 < offset <= 127
-        self.mc.overwrite(je_location - 1, [chr(offset)])
+        self.mc.overwrite(je_location - 1, chr(offset))
         #
         # Reset the vable token --- XXX really too much special logic here:-(
         if jd.index_of_virtualizable >= 0:
@@ -1768,7 +1708,7 @@
         # Here we join Path A and Path B again
         offset = self.mc.get_relative_pos() - jmp_location
         assert 0 <= offset <= 127
-        self.mc.overwrite(jmp_location - 1, [chr(offset)])
+        self.mc.overwrite(jmp_location - 1, chr(offset))
         self.mc.CMP_bi(FORCE_INDEX_OFS, 0)
         self.implement_guard(guard_token, 'L')
 
@@ -1783,9 +1723,6 @@
             cls = self.cpu.gc_ll_descr.has_write_barrier_class()
             assert cls is not None and isinstance(descr, cls)
         loc_base = arglocs[0]
-        # ensure that enough bytes are available to write the whole
-        # following piece of code atomically (for the JZ)
-        self.mc.ensure_bytes_available(256)
         self.mc.TEST8_mi((loc_base.value, descr.jit_wb_if_flag_byteofs),
                 descr.jit_wb_if_flag_singlebyte)
         self.mc.J_il8(rx86.Conditions['Z'], 0) # patched later
@@ -1828,7 +1765,7 @@
         # patch the JZ above
         offset = self.mc.get_relative_pos() - jz_location
         assert 0 < offset <= 127
-        self.mc.overwrite(jz_location-1, [chr(offset)])
+        self.mc.overwrite(jz_location-1, chr(offset))
 
     def genop_force_token(self, op, arglocs, resloc):
         # RegAlloc.consider_force_token ensures this:
@@ -1851,18 +1788,21 @@
         gcrootmap = self.cpu.gc_ll_descr.gcrootmap
         if gcrootmap:
             mark = self._regalloc.get_mark_gc_roots(gcrootmap)
-            gcrootmap.put(rffi.cast(llmemory.Address, self.mc.tell()), mark)
+            self.mc.insert_gcroot_marker(mark)
 
     def target_arglocs(self, loop_token):
         return loop_token._x86_arglocs
 
     def closing_jump(self, loop_token):
-        self.mc.JMP(imm(loop_token._x86_loop_code))
+        if loop_token is self.currently_compiling_loop:
+            curpos = self.mc.get_relative_pos() + 5
+            self.mc.JMP_l(self.looppos - curpos)
+        else:
+            self.mc.JMP(imm(loop_token._x86_loop_code))
 
     def malloc_cond_fixedsize(self, nursery_free_adr, nursery_top_adr,
                               size, tid):
         size = max(size, self.cpu.gc_ll_descr.minimal_size_in_nursery)
-        self.mc.ensure_bytes_available(256)
         self.mc.MOV(eax, heap(nursery_free_adr))
         self.mc.LEA_rm(edx.value, (eax.value, size))
         self.mc.CMP(edx, heap(nursery_top_adr))
@@ -1890,7 +1830,7 @@
 
         offset = self.mc.get_relative_pos() - jmp_adr
         assert 0 < offset <= 127
-        self.mc.overwrite(jmp_adr-1, [chr(offset)])
+        self.mc.overwrite(jmp_adr-1, chr(offset))
         # on 64-bits, 'tid' is a value that fits in 31 bits
         self.mc.MOV_mi((eax.value, 0), tid)
         self.mc.MOV(heap(nursery_free_adr), edx)

Modified: pypy/branch/jitypes2/pypy/jit/backend/x86/regalloc.py
==============================================================================
--- pypy/branch/jitypes2/pypy/jit/backend/x86/regalloc.py	(original)
+++ pypy/branch/jitypes2/pypy/jit/backend/x86/regalloc.py	Fri Dec  3 11:04:29 2010
@@ -60,32 +60,6 @@
         r15: 5,
     }
 
-class FloatConstants(object):
-    BASE_CONSTANT_SIZE = 1000
-
-    def __init__(self):
-        self.cur_array_free = 0
-        self.const_id = 0
-
-    def _get_new_array(self):
-        n = self.BASE_CONSTANT_SIZE
-        # known to leak
-        self.cur_array = lltype.malloc(rffi.CArray(lltype.Float), n,
-                                       flavor='raw', track_allocation=False)
-        self.cur_array_free = n
-    _get_new_array._dont_inline_ = True
-
-    def record_float(self, floatval):
-        if self.cur_array_free == 0:
-            self._get_new_array()
-        arr = self.cur_array
-        n = self.cur_array_free - 1
-        arr[n] = floatval
-        self.cur_array_free = n
-        self.const_id += 1
-        return (self.const_id, rffi.cast(lltype.Signed, arr) + n * 8)
-
-
 class X86XMMRegisterManager(RegisterManager):
 
     box_types = [FLOAT]
@@ -93,20 +67,11 @@
     # we never need lower byte I hope
     save_around_call_regs = all_regs
 
-    def __init__(self, longevity, frame_manager=None, assembler=None):
-        RegisterManager.__init__(self, longevity, frame_manager=frame_manager,
-                                 assembler=assembler)
-        if assembler is None:
-            self.float_constants = FloatConstants()
-        else:
-            if assembler._float_constants is None:
-                assembler._float_constants = FloatConstants()
-            self.float_constants = assembler._float_constants
-
     def convert_to_imm(self, c):
-        const_id, adr = self.float_constants.record_float(c.getfloat())
-        return ConstFloatLoc(adr, const_id)
-        
+        adr = self.assembler.datablockwrapper.malloc_aligned(8, 8)
+        rffi.cast(rffi.CArrayPtr(rffi.DOUBLE), adr)[0] = c.getfloat()
+        return ConstFloatLoc(adr)
+
     def after_call(self, v):
         # the result is stored in st0, but we don't have this around,
         # so genop_call will move it to some frame location immediately
@@ -320,11 +285,22 @@
     def locs_for_fail(self, guard_op):
         return [self.loc(v) for v in guard_op.getfailargs()]
 
+    def get_current_depth(self):
+        # return (self.fm.frame_depth, self.param_depth), but trying to share
+        # the resulting tuple among several calls
+        arg0 = self.fm.frame_depth
+        arg1 = self.param_depth
+        result = self.assembler._current_depths_cache
+        if result[0] != arg0 or result[1] != arg1:
+            result = (arg0, arg1)
+            self.assembler._current_depths_cache = result
+        return result
+
     def perform_with_guard(self, op, guard_op, arglocs, result_loc):
         faillocs = self.locs_for_fail(guard_op)
         self.rm.position += 1
         self.xrm.position += 1
-        current_depths = (self.fm.frame_depth, self.param_depth)
+        current_depths = self.get_current_depth()
         self.assembler.regalloc_perform_with_guard(op, guard_op, faillocs,
                                                    arglocs, result_loc,
                                                    current_depths)
@@ -340,7 +316,7 @@
                                                       arglocs))
             else:
                 self.assembler.dump('%s(%s)' % (guard_op, arglocs))
-        current_depths = (self.fm.frame_depth, self.param_depth)                
+        current_depths = self.get_current_depth()
         self.assembler.regalloc_perform_guard(guard_op, faillocs, arglocs,
                                               result_loc,
                                               current_depths)
@@ -1097,7 +1073,8 @@
             if (isinstance(v, BoxPtr) and self.rm.stays_alive(v)):
                 assert reg in self.rm.REGLOC_TO_GCROOTMAP_REG_INDEX
                 gcrootmap.add_callee_save_reg(shape, self.rm.REGLOC_TO_GCROOTMAP_REG_INDEX[reg])
-        return gcrootmap.compress_callshape(shape)
+        return gcrootmap.compress_callshape(shape,
+                                            self.assembler.datablockwrapper)
 
     def consider_force_token(self, op):
         loc = self.rm.force_allocate_reg(op.result)

Modified: pypy/branch/jitypes2/pypy/jit/backend/x86/regloc.py
==============================================================================
--- pypy/branch/jitypes2/pypy/jit/backend/x86/regloc.py	(original)
+++ pypy/branch/jitypes2/pypy/jit/backend/x86/regloc.py	Fri Dec  3 11:04:29 2010
@@ -177,24 +177,15 @@
 
 class ConstFloatLoc(AssemblerLocation):
     # XXX: We have to use this class instead of just AddressLoc because
-    # AddressLoc is "untyped" and also we to have need some sort of unique
-    # identifier that we can use in _getregkey (for jump.py)
-
+    # we want a width of 8  (... I think.  Check this!)
     _immutable_ = True
-
     width = 8
 
-    def __init__(self, address, const_id):
+    def __init__(self, address):
         self.value = address
-        self.const_id = const_id
 
     def __repr__(self):
-        return '<ConstFloatLoc(%s, %s)>' % (self.value, self.const_id)
-
-    def _getregkey(self):
-        # XXX: 1000 is kind of magic: We just don't want to be confused
-        # with any registers
-        return 1000 + self.const_id
+        return '<ConstFloatLoc @%s>' % (self.value,)
 
     def location_code(self):
         return 'j'
@@ -334,9 +325,9 @@
                 if code == possible_code:
                     val = getattr(loc, "value_" + possible_code)()
                     if possible_code == 'i':
-                        offset = intmask(val - (self.tell() + 5))
-                        if rx86.fits_in_32bits(offset):
+                        if self.WORD == 4:
                             _rx86_getattr(self, name + "_l")(val)
+                            self.add_pending_relocation()
                         else:
                             assert self.WORD == 8
                             self._load_scratch(val)

Modified: pypy/branch/jitypes2/pypy/jit/backend/x86/runner.py
==============================================================================
--- pypy/branch/jitypes2/pypy/jit/backend/x86/runner.py	(original)
+++ pypy/branch/jitypes2/pypy/jit/backend/x86/runner.py	Fri Dec  3 11:04:29 2010
@@ -44,6 +44,7 @@
 
     def setup_once(self):
         self.profile_agent.startup()
+        self.assembler.setup_once()
 
     def finish_once(self):
         self.assembler.finish_once()
@@ -53,9 +54,12 @@
         self.assembler.assemble_loop(inputargs, operations, looptoken,
                                      log=log)
 
-    def compile_bridge(self, faildescr, inputargs, operations, log=True):
+    def compile_bridge(self, faildescr, inputargs, operations,
+                       original_loop_token, log=True):
+        clt = original_loop_token.compiled_loop_token
+        clt.compiling_a_bridge()
         self.assembler.assemble_bridge(faildescr, inputargs, operations,
-                                       log=log)
+                                       original_loop_token, log=log)
 
     def set_future_value_int(self, index, intvalue):
         self.assembler.fail_boxes_int.setitem(index, intvalue)
@@ -124,8 +128,8 @@
         assert fail_index >= 0, "already forced!"
         faildescr = self.get_fail_descr_from_number(fail_index)
         rffi.cast(TP, addr_of_force_index)[0] = -1
-        bytecode = rffi.cast(rffi.UCHARP,
-                             faildescr._x86_failure_recovery_bytecode)
+        frb = self.assembler._find_failure_recovery_bytecode(faildescr)
+        bytecode = rffi.cast(rffi.UCHARP, frb)
         # start of "no gc operation!" block
         fail_index_2 = self.assembler.grab_frame_values(
             bytecode,
@@ -165,17 +169,12 @@
 CPU = CPU386
 
 # silence warnings
-
-history.LoopToken._x86_param_depth = 0
-history.LoopToken._x86_arglocs = (None, None)
-history.LoopToken._x86_frame_depth = 0
-history.LoopToken._x86_bootstrap_code = 0
-history.LoopToken._x86_direct_bootstrap_code = 0
-history.LoopToken._x86_failure_recovery_bytecode = 0
-history.LoopToken._x86_loop_code = 0
-history.LoopToken._x86_current_depths = (0, 0)
-
-compile._DoneWithThisFrameDescr._x86_current_depths = (0, 0)
-compile._DoneWithThisFrameDescr._x86_failure_recovery_bytecode = 0
-compile._DoneWithThisFrameDescr._x86_adr_jump_offset = 0
-
+##history.LoopToken._x86_param_depth = 0
+##history.LoopToken._x86_arglocs = (None, None)
+##history.LoopToken._x86_frame_depth = 0
+##history.LoopToken._x86_bootstrap_code = 0
+##history.LoopToken._x86_direct_bootstrap_code = 0
+##history.LoopToken._x86_loop_code = 0
+##history.LoopToken._x86_debug_checksum = 0
+##compile.AbstractFailDescr._x86_current_depths = (0, 0)
+##compile.AbstractFailDescr._x86_adr_jump_offset = 0

Modified: pypy/branch/jitypes2/pypy/jit/backend/x86/rx86.py
==============================================================================
--- pypy/branch/jitypes2/pypy/jit/backend/x86/rx86.py	(original)
+++ pypy/branch/jitypes2/pypy/jit/backend/x86/rx86.py	Fri Dec  3 11:04:29 2010
@@ -137,10 +137,9 @@
 # ____________________________________________________________
 # Emit an immediate displacement (relative to the cur insn)
 
-def encode_relative(mc, target, _, orbyte):
+def encode_relative(mc, relative_target, _, orbyte):
     assert orbyte == 0
-    offset = intmask(target - (mc.tell() + 4))
-    mc.writeimm32(offset)
+    mc.writeimm32(relative_target)
     return 0
 
 def relative(argnum):

Modified: pypy/branch/jitypes2/pypy/jit/backend/x86/support.py
==============================================================================
--- pypy/branch/jitypes2/pypy/jit/backend/x86/support.py	(original)
+++ pypy/branch/jitypes2/pypy/jit/backend/x86/support.py	Fri Dec  3 11:04:29 2010
@@ -1,4 +1,7 @@
+import sys
 from pypy.rpython.lltypesystem import lltype, rffi, llmemory
+from pypy.translator.tool.cbuild import ExternalCompilationInfo
+
 
 def values_array(TP, size):
     ATP = lltype.GcArray(TP)
@@ -23,3 +26,22 @@
             return True
 
     return ValuesArray()
+
+# ____________________________________________________________
+
+memcpy_fn = rffi.llexternal('memcpy', [llmemory.Address, llmemory.Address,
+                                       rffi.SIZE_T], lltype.Void,
+                            sandboxsafe=True, _nowrapper=True)
+
+# ____________________________________________________________
+
+if sys.platform == 'win32':
+    ensure_sse2_floats = lambda : None
+else:
+    _sse2_eci = ExternalCompilationInfo(
+        compile_extra = ['-msse2', '-mfpmath=sse'],
+        separate_module_sources = ['void PYPY_NO_OP(void) {}'],
+        )
+    ensure_sse2_floats = rffi.llexternal('PYPY_NO_OP', [], lltype.Void,
+                                         compilation_info=_sse2_eci,
+                                         sandboxsafe=True)

Modified: pypy/branch/jitypes2/pypy/jit/backend/x86/test/test_assembler.py
==============================================================================
--- pypy/branch/jitypes2/pypy/jit/backend/x86/test/test_assembler.py	(original)
+++ pypy/branch/jitypes2/pypy/jit/backend/x86/test/test_assembler.py	Fri Dec  3 11:04:29 2010
@@ -1,5 +1,5 @@
 from pypy.jit.backend.x86.regloc import *
-from pypy.jit.backend.x86.assembler import Assembler386, MachineCodeBlockWrapper
+from pypy.jit.backend.x86.assembler import Assembler386
 from pypy.jit.backend.x86.regalloc import X86FrameManager, get_ebp_ofs
 from pypy.jit.metainterp.history import BoxInt, BoxPtr, BoxFloat, INT, REF, FLOAT
 from pypy.rlib.rarithmetic import intmask
@@ -19,28 +19,10 @@
         return 42
 
 class FakeMC:
-    def __init__(self, base_address=0):
+    def __init__(self):
         self.content = []
-        self._size = 100
-        self.base_address = base_address
-    def writechr(self, n):
-        self.content.append(n)
-    def tell(self):
-        return self.base_address + len(self.content)
-    def get_relative_pos(self):
-        return len(self.content)
-    def JMP(self, *args):
-        self.content.append(("JMP", args))
-    def done(self):
-        pass
-    def PUSH_r(self, reg):
-        pass
-    def POP_r(self, reg):
-        pass
-
-class FakeAssembler:
-    def write_pending_failure_recoveries(self):
-        pass
+    def writechar(self, char):
+        self.content.append(ord(char))
 
 def test_write_failure_recovery_description():
     assembler = Assembler386(FakeCPU())
@@ -255,41 +237,3 @@
         assert assembler.fail_boxes_int.getitem(i) == expected_ints[i]
         assert assembler.fail_boxes_ptr.getitem(i) == expected_ptrs[i]
         assert assembler.fail_boxes_float.getitem(i) == expected_floats[i]
-
-class FakeProfileAgent(object):
-    def __init__(self):
-        self.functions = []
-
-    def native_code_written(self, name, address, size):
-        self.functions.append((name, address, size))
-
-class FakeMCWrapper(MachineCodeBlockWrapper):
-    count = 0
-    def _instantiate_mc(self):
-        self.count += 1
-        return FakeMC(200 * (self.count - 1))
-
-def test_mc_wrapper_profile_agent():
-    agent = FakeProfileAgent()
-    assembler = FakeAssembler()
-    mc = FakeMCWrapper(assembler, 100, agent)
-    mc.start_function("abc")
-    mc.writechr("x")
-    mc.writechr("x")
-    mc.writechr("x")
-    mc.writechr("x")
-    mc.end_function()
-    assert agent.functions == [("abc", 0, 4)]
-    mc.writechr("x")
-    mc.start_function("cde")
-    mc.writechr("x")
-    mc.writechr("x")
-    mc.writechr("x")
-    mc.writechr("x")
-    mc.end_function()
-    assert agent.functions == [("abc", 0, 4), ("cde", 5, 4)]
-    mc.start_function("xyz")
-    for i in range(50):
-        mc.writechr("x")
-    mc.end_function()
-    assert agent.functions == [("abc", 0, 4), ("cde", 5, 4), ("xyz", 9, 29), ("xyz", 200, 22)]

Modified: pypy/branch/jitypes2/pypy/jit/backend/x86/test/test_gc_integration.py
==============================================================================
--- pypy/branch/jitypes2/pypy/jit/backend/x86/test/test_gc_integration.py	(original)
+++ pypy/branch/jitypes2/pypy/jit/backend/x86/test/test_gc_integration.py	Fri Dec  3 11:04:29 2010
@@ -33,7 +33,8 @@
     def add_callee_save_reg(self, shape, reg_index):
         index_to_name = { 1: 'ebx', 2: 'esi', 3: 'edi' }
         shape.append(index_to_name[reg_index])
-    def compress_callshape(self, shape):
+    def compress_callshape(self, shape, datablockwrapper):
+        assert datablockwrapper == 'fakedatablockwrapper'
         assert shape[0] == 'shape'
         return ['compressed'] + shape[1:]
 
@@ -58,7 +59,9 @@
 
     def test_mark_gc_roots(self):
         cpu = CPU(None, None)
+        cpu.setup_once()
         regalloc = RegAlloc(MockAssembler(cpu, MockGcDescr(False)))
+        regalloc.assembler.datablockwrapper = 'fakedatablockwrapper'
         boxes = [BoxPtr() for i in range(len(X86RegisterManager.all_regs))]
         longevity = {}
         for box in boxes:
@@ -90,6 +93,7 @@
     
     cpu = CPU(None, None)
     cpu.gc_ll_descr = MockGcDescr(False)
+    cpu.setup_once()
     
     S = lltype.GcForwardReference()
     S.become(lltype.GcStruct('S', ('field', lltype.Ptr(S)),
@@ -214,6 +218,7 @@
         cpu = CPU(None, None)
         cpu.vtable_offset = WORD
         cpu.gc_ll_descr = GCDescrFastpathMalloc()
+        cpu.setup_once()
 
         NODE = lltype.Struct('node', ('tid', lltype.Signed),
                                      ('value', lltype.Signed))

Modified: pypy/branch/jitypes2/pypy/jit/backend/x86/test/test_regalloc.py
==============================================================================
--- pypy/branch/jitypes2/pypy/jit/backend/x86/test/test_regalloc.py	(original)
+++ pypy/branch/jitypes2/pypy/jit/backend/x86/test/test_regalloc.py	Fri Dec  3 11:04:29 2010
@@ -9,7 +9,7 @@
 from pypy.jit.backend.llsupport.descr import GcCache
 from pypy.jit.backend.detect_cpu import getcpuclass
 from pypy.jit.backend.x86.regalloc import RegAlloc, X86RegisterManager,\
-     FloatConstants, is_comparison_or_ovf_op
+     is_comparison_or_ovf_op
 from pypy.jit.backend.x86.arch import IS_X86_32, IS_X86_64
 from pypy.jit.tool.oparser import parse
 from pypy.rpython.lltypesystem import lltype, llmemory, rffi
@@ -41,7 +41,10 @@
         self.movs = []
         self.performs = []
         self.lea = []
-        self.cpu = cpu or CPU(None, None)
+        if cpu is None:
+            cpu = CPU(None, None)
+            cpu.setup_once()
+        self.cpu = cpu
         if gc_ll_descr is None:
             gc_ll_descr = MockGcDescr(False)
         self.cpu.gc_ll_descr = gc_ll_descr
@@ -76,6 +79,7 @@
 
 class BaseTestRegalloc(object):
     cpu = CPU(None, None)
+    cpu.setup_once()
 
     def raising_func(i):
         if i:
@@ -166,7 +170,8 @@
         assert ([box.type for box in bridge.inputargs] ==
                 [box.type for box in guard_op.getfailargs()])
         faildescr = guard_op.getdescr()
-        self.cpu.compile_bridge(faildescr, bridge.inputargs, bridge.operations)
+        self.cpu.compile_bridge(faildescr, bridge.inputargs, bridge.operations,
+                                loop.token)
         return bridge
 
     def run(self, loop):
@@ -515,16 +520,6 @@
         self.interpret(ops, [0.1, .2, .3, .4, .5, .6, .7, .8, .9])
         assert self.getfloats(9) == [.1+.2, .9+3.5, .3, .4, .5, .6, .7, .8, .9]
 
-    def test_float_overflow_const_list(self):
-        ops = ['[f0]']
-        BASE_CONSTANT_SIZE = FloatConstants.BASE_CONSTANT_SIZE
-        for i in range(BASE_CONSTANT_SIZE * 2):
-            ops.append('f%d = float_add(f%d, 3.5)' % (i + 1, i))
-        ops.append('finish(f%d)' % (BASE_CONSTANT_SIZE * 2))
-        ops = "\n".join(ops)
-        self.interpret(ops, [0.1])
-        assert abs(self.getfloat(0) - (BASE_CONSTANT_SIZE * 2) * 3.5 - 0.1) < 0.00001
-
     def test_lt_const(self):
         ops = '''
         [f0]

Modified: pypy/branch/jitypes2/pypy/jit/backend/x86/test/test_regalloc2.py
==============================================================================
--- pypy/branch/jitypes2/pypy/jit/backend/x86/test/test_regalloc2.py	(original)
+++ pypy/branch/jitypes2/pypy/jit/backend/x86/test/test_regalloc2.py	Fri Dec  3 11:04:29 2010
@@ -19,6 +19,7 @@
         ResOperation(rop.FINISH, [v4, v3], None, descr=BasicFailDescr()),
         ]
     cpu = CPU(None, None)
+    cpu.setup_once()
     looptoken = LoopToken()
     cpu.compile_loop(inputargs, operations, looptoken)
     cpu.set_future_value_int(0, 9)
@@ -41,6 +42,7 @@
         ResOperation(rop.FINISH, [v4, v3, tmp5], None, descr=BasicFailDescr()),
             ]
     cpu = CPU(None, None)
+    cpu.setup_once()
     looptoken = LoopToken()
     cpu.compile_loop(inputargs, operations, looptoken)
     cpu.set_future_value_int(0, -10)
@@ -137,6 +139,7 @@
         ResOperation(rop.FINISH, [v40, v36, v37, v31, v16, v34, v35, v23, v22, v29, v14, v39, v30, v38], None, descr=BasicFailDescr()),
             ]
     cpu = CPU(None, None)
+    cpu.setup_once()
     looptoken = LoopToken()
     cpu.compile_loop(inputargs, operations, looptoken)
     cpu.set_future_value_int(0, -13)
@@ -251,6 +254,7 @@
         ResOperation(rop.FINISH, [v40, v10, v36, v26, v13, v30, v21, v33, v18, v25, v31, v32, v28, v29, v35, v38, v20, v39, v34, v23, v37], None, descr=BasicFailDescr()),
             ]
     cpu = CPU(None, None)
+    cpu.setup_once()
     looptoken = LoopToken()
     cpu.compile_loop(inputargs, operations, looptoken)
     cpu.set_future_value_int(0, 17)

Modified: pypy/branch/jitypes2/pypy/jit/backend/x86/test/test_regloc.py
==============================================================================
--- pypy/branch/jitypes2/pypy/jit/backend/x86/test/test_regloc.py	(original)
+++ pypy/branch/jitypes2/pypy/jit/backend/x86/test/test_regloc.py	Fri Dec  3 11:04:29 2010
@@ -1,4 +1,4 @@
-import struct
+import struct, sys
 from pypy.jit.backend.x86.regloc import *
 from pypy.jit.backend.x86.test.test_rx86 import CodeBuilder32, CodeBuilder64, assert_encodes_as
 from pypy.jit.backend.x86.assembler import heap
@@ -37,26 +37,36 @@
     assert_encodes_as(cb64, "CMP16", (ecx, ImmedLoc(12345)), '\x66\x81\xF9\x39\x30')
     assert_encodes_as(cb64, "CMP16", (AddressLoc(r13, ImmedLoc(0), 0, 0), ImmedLoc(12345)), '\x66\x41\x81\x7D\x00\x39\x30')
 
-def test_jmp_wraparound():
-    if not IS_X86_32:
-        py.test.skip()
-
-    pos_addr = intmask(0x7FFFFF00)
-    neg_addr = intmask(0x800000BB)
-
-    # JMP to "negative" address from "positive" address
-    s = cb32()
-    s.base_address = pos_addr
-    s.JMP(ImmedLoc(neg_addr))
-    expected_ofs = neg_addr - (pos_addr+5)
-    assert s.getvalue() == '\xE9' + struct.pack("<i", expected_ofs)
-
-    # JMP to a "positive" address from a "negative" address
-    s = cb32()
-    s.base_address = neg_addr
-    s.JMP(ImmedLoc(pos_addr))
-    expected_ofs = pos_addr - (neg_addr+5)
-    assert s.getvalue() == '\xE9' + struct.pack("<i", expected_ofs)
+def test_relocation():
+    from pypy.rpython.lltypesystem import lltype, rffi
+    from pypy.jit.backend.x86 import codebuf
+    for target in [0x01020304, 0x0102030405060708]:
+        if target > sys.maxint:
+            continue
+        mc = codebuf.MachineCodeBlockWrapper()
+        mc.CALL(ImmedLoc(target))
+        length = mc.get_relative_pos()
+        buf = lltype.malloc(rffi.CCHARP.TO, length, flavor='raw')
+        rawstart = rffi.cast(lltype.Signed, buf)
+        if IS_X86_32:
+            assert length == 5
+            assert mc.relocations == [5]
+            expected = "\xE8" + struct.pack('<i', target - (rawstart + 5))
+        elif IS_X86_64:
+            assert mc.relocations == []
+            if target <= 0x7fffffff:
+                assert length == 10
+                expected = (
+                    "\x49\xC7\xC3\x04\x03\x02\x01"  # MOV %r11, target
+                    "\x41\xFF\xD3")                 # CALL *%r11
+            else:
+                assert length == 13
+                expected = (
+                    "\x49\xBB\x08\x07\x06\x05\x04\x03\x02\x01" # MOV %r11, targ
+                    "\x41\xFF\xD3")                 # CALL *%r11
+        mc.copy_to_raw_memory(rawstart)
+        assert ''.join([buf[i] for i in range(length)]) == expected
+        lltype.free(buf, flavor='raw')
 
 
 class Test64Bits:

Modified: pypy/branch/jitypes2/pypy/jit/backend/x86/test/test_runner.py
==============================================================================
--- pypy/branch/jitypes2/pypy/jit/backend/x86/test/test_runner.py	(original)
+++ pypy/branch/jitypes2/pypy/jit/backend/x86/test/test_runner.py	Fri Dec  3 11:04:29 2010
@@ -33,6 +33,7 @@
     
     def setup_method(self, meth):
         self.cpu = CPU(rtyper=None, stats=FakeStats())
+        self.cpu.setup_once()
 
     def test_execute_ptr_operation(self):
         cpu = self.cpu
@@ -329,7 +330,11 @@
                         assert result != expected
 
     def test_compile_bridge_check_profile_info(self):
-        from pypy.jit.backend.x86.test.test_assembler import FakeProfileAgent
+        class FakeProfileAgent(object):
+            def __init__(self):
+                self.functions = []
+            def native_code_written(self, name, address, size):
+                self.functions.append((name, address, size))
         self.cpu.profile_agent = agent = FakeProfileAgent()
 
         i0 = BoxInt()
@@ -338,6 +343,7 @@
         faildescr1 = BasicFailDescr(1)
         faildescr2 = BasicFailDescr(2)
         looptoken = LoopToken()
+        looptoken.number = 17
         class FakeString(object):
             def __init__(self, val):
                 self.val = val
@@ -356,7 +362,7 @@
         operations[3].setfailargs([i1])
         self.cpu.compile_loop(inputargs, operations, looptoken)
         name, loopaddress, loopsize = agent.functions[0]
-        assert name == "Loop # 0: hello"
+        assert name == "Loop # 17: hello"
         assert loopaddress <= looptoken._x86_loop_code
         assert loopsize >= 40 # randomish number
 
@@ -370,7 +376,7 @@
         ]
         bridge[1].setfailargs([i1b])
 
-        self.cpu.compile_bridge(faildescr1, [i1b], bridge)        
+        self.cpu.compile_bridge(faildescr1, [i1b], bridge, looptoken)
         name, address, size = agent.functions[1]
         assert name == "Bridge # 0: bye"
         # Would be exactly ==, but there are some guard failure recovery
@@ -397,104 +403,15 @@
         assert res.value == 4.0
 
 
-class TestX86OverflowMC(TestX86):
-
-    def setup_method(self, meth):
-        self.cpu = CPU(rtyper=None, stats=FakeStats())
-        self.cpu.assembler.mc_size = 1024
-
-    def test_overflow_mc(self):
-        ops = []
-        base_v = BoxInt()
-        v = base_v
-        for i in range(1024):
-            next_v = BoxInt()
-            ops.append(ResOperation(rop.INT_ADD, [v, ConstInt(1)], next_v))
-            v = next_v
-        ops.append(ResOperation(rop.FINISH, [v], None,
-                                descr=BasicFailDescr()))
-        looptoken = LoopToken()
-        self.cpu.assembler.setup()
-        old_mc_mc = self.cpu.assembler.mc._mc
-        self.cpu.compile_loop([base_v], ops, looptoken)
-        assert self.cpu.assembler.mc._mc != old_mc_mc   # overflowed
-        self.cpu.set_future_value_int(0, base_v.value)
-        self.cpu.execute_token(looptoken)
-        assert self.cpu.get_latest_value_int(0) == 1024
-
-    def test_overflow_guard_float_cmp(self):
-        # The float comparisons on x86 tend to use small relative jumps,
-        # which may run into trouble if they fall on the edge of a
-        # MachineCodeBlock change.
-        a = BoxFloat(1.0)
-        b = BoxFloat(2.0)
-        failed = BoxInt(41)
-        finished = BoxInt(42)
-
-        # We select guards that will always succeed, so that execution will
-        # continue through the entire set of comparisions
-        ops_to_test = (
-            (rop.FLOAT_LT, [a, b], rop.GUARD_TRUE),
-            (rop.FLOAT_LT, [b, a], rop.GUARD_FALSE),
-
-            (rop.FLOAT_LE, [a, a], rop.GUARD_TRUE),
-            (rop.FLOAT_LE, [a, b], rop.GUARD_TRUE),
-            (rop.FLOAT_LE, [b, a], rop.GUARD_FALSE),
-
-            (rop.FLOAT_EQ, [a, a], rop.GUARD_TRUE),
-            (rop.FLOAT_EQ, [a, b], rop.GUARD_FALSE),
-
-            (rop.FLOAT_NE, [a, b], rop.GUARD_TRUE),
-            (rop.FLOAT_NE, [a, a], rop.GUARD_FALSE),
-
-            (rop.FLOAT_GT, [b, a], rop.GUARD_TRUE),
-            (rop.FLOAT_GT, [a, b], rop.GUARD_FALSE),
-
-            (rop.FLOAT_GE, [a, a], rop.GUARD_TRUE),
-            (rop.FLOAT_GE, [b, a], rop.GUARD_TRUE),
-            (rop.FLOAT_GE, [a, b], rop.GUARD_FALSE),
-        )
-
-        for float_op, args, guard_op in ops_to_test:
-            ops = []
-
-            for i in range(200):
-                cmp_result = BoxInt()
-                ops.append(ResOperation(float_op, args, cmp_result))
-                ops.append(ResOperation(guard_op, [cmp_result], None, descr=BasicFailDescr()))
-                ops[-1].setfailargs([failed])
-
-            ops.append(ResOperation(rop.FINISH, [finished], None, descr=BasicFailDescr()))
-
-            looptoken = LoopToken()
-            self.cpu.compile_loop([a, b, failed, finished], ops, looptoken)
-            self.cpu.set_future_value_float(0, a.value)
-            self.cpu.set_future_value_float(1, b.value)
-            self.cpu.set_future_value_int(2, failed.value)
-            self.cpu.set_future_value_int(3, finished.value)
-            self.cpu.execute_token(looptoken)
-
-            # Really just a sanity check. We're actually interested in
-            # whether the test segfaults.
-            assert self.cpu.get_latest_value_int(0) == finished.value
-
-    def test_overflow_guard_exception(self):
-        for i in range(50):
-            self.test_exceptions()
-
-
 class TestDebuggingAssembler(object):
     def setup_method(self, meth):
-        self.pypylog = os.environ.get('PYPYLOG', None)
-        self.logfile = str(udir.join('x86_runner.log'))
-        os.environ['PYPYLOG'] = "mumble:" + self.logfile
         self.cpu = CPU(rtyper=None, stats=FakeStats())
-
-    def teardown_method(self, meth):
-        if self.pypylog is not None:
-            os.environ['PYPYLOG'] = self.pypylog
+        self.cpu.setup_once()
 
     def test_debugger_on(self):
+        from pypy.tool.logparser import parse_log_file, extract_category
+        from pypy.rlib import debug
+        
         loop = """
         [i0]
         debug_merge_point('xyz', 0)
@@ -504,17 +421,19 @@
         jump(i1)
         """
         ops = parse(loop)
-        self.cpu.assembler.set_debug(True)
-        self.cpu.compile_loop(ops.inputargs, ops.operations, ops.token)
-        self.cpu.set_future_value_int(0, 0)
-        self.cpu.execute_token(ops.token)
-        # check debugging info
-        name, struct = self.cpu.assembler.loop_run_counters[0]
-        assert name == 0       # 'xyz'
-        assert struct.i == 10
-        self.cpu.finish_once()
-        lines = py.path.local(self.logfile + ".count").readlines()
-        assert lines[0] == '0:10\n'  # '10      xyz\n'
+        debug._log = dlog = debug.DebugLog()
+        try:
+            self.cpu.assembler.set_debug(True)
+            self.cpu.compile_loop(ops.inputargs, ops.operations, ops.token)
+            self.cpu.set_future_value_int(0, 0)
+            self.cpu.execute_token(ops.token)
+            # check debugging info
+            struct = self.cpu.assembler.loop_run_counters[0]
+            assert struct.i == 10
+            self.cpu.finish_once()
+        finally:
+            debug._log = None
+        assert ('jit-backend-counts', [('debug_print', '0:10')]) in dlog
 
     def test_debugger_checksum(self):
         loop = """

Modified: pypy/branch/jitypes2/pypy/jit/backend/x86/test/test_rx86.py
==============================================================================
--- pypy/branch/jitypes2/pypy/jit/backend/x86/test/test_rx86.py	(original)
+++ pypy/branch/jitypes2/pypy/jit/backend/x86/test/test_rx86.py	Fri Dec  3 11:04:29 2010
@@ -5,7 +5,6 @@
 class CodeBuilderMixin(object):
     def __init__(self):
         self.buffer = []
-        self.base_address = 0x76543210
 
     def writechar(self, c):
         assert isinstance(c, str) and len(c) == 1
@@ -14,9 +13,6 @@
     def getvalue(self):
         return ''.join(self.buffer)
 
-    def tell(self):
-        return self.base_address + len(self.buffer)
-
 def assert_encodes_as(code_builder_cls, insn_name, args, expected_encoding):
     s = code_builder_cls()
     getattr(s, insn_name)(*args)
@@ -104,21 +100,18 @@
 
 def test_call_l(s=None):
     s = s or CodeBuilder32()
-    s.CALL_l(0x01234567)
-    ofs = 0x01234567 - (0x76543210+5)
-    assert s.getvalue() == '\xE8' + struct.pack("<i", ofs)
+    s.CALL_l(0x01234567)   # relative offset
+    assert s.getvalue() == '\xE8' + struct.pack("<i", 0x01234567)
 
 def test_jmp_l():
     s = CodeBuilder32()
-    s.JMP_l(0x01234567)
-    ofs = 0x01234567 - (0x76543210+5)
-    assert s.getvalue() == '\xE9' + struct.pack("<i", ofs)
+    s.JMP_l(0x01234567)   # relative offset
+    assert s.getvalue() == '\xE9' + struct.pack("<i", 0x01234567)
 
 def test_j_il():
     s = CodeBuilder32()
-    s.J_il(5, 0x01234567)
-    ofs = 0x01234567 - (0x76543210+6)
-    assert s.getvalue() == '\x0F\x85' + struct.pack("<i", ofs)
+    s.J_il(5, 0x01234567)   # relative offset
+    assert s.getvalue() == '\x0F\x85' + struct.pack("<i", 0x01234567)
 
 def test_set_ir():
     s = CodeBuilder32()

Modified: pypy/branch/jitypes2/pypy/jit/backend/x86/test/test_zll_random.py
==============================================================================
--- pypy/branch/jitypes2/pypy/jit/backend/x86/test/test_zll_random.py	(original)
+++ pypy/branch/jitypes2/pypy/jit/backend/x86/test/test_zll_random.py	Fri Dec  3 11:04:29 2010
@@ -6,9 +6,7 @@
 
 def test_stress():
     cpu = CPU(None, None)
+    cpu.setup_once()
     r = Random()
     for i in range(1000):
         check_random_function(cpu, LLtypeOperationBuilder, r, i, 1000)
-
-
-

Modified: pypy/branch/jitypes2/pypy/jit/backend/x86/test/test_zmath.py
==============================================================================
--- pypy/branch/jitypes2/pypy/jit/backend/x86/test/test_zmath.py	(original)
+++ pypy/branch/jitypes2/pypy/jit/backend/x86/test/test_zmath.py	Fri Dec  3 11:04:29 2010
@@ -4,7 +4,7 @@
 import py, math
 from pypy.module.math.test import test_direct
 from pypy.translator.c.test.test_genc import compile
-from pypy.jit.backend.x86.codebuf import ensure_sse2_floats
+from pypy.jit.backend.x86.support import ensure_sse2_floats
 
 
 def get_test_case((fnname, args, expected)):

Modified: pypy/branch/jitypes2/pypy/jit/backend/x86/valgrind.py
==============================================================================
--- pypy/branch/jitypes2/pypy/jit/backend/x86/valgrind.py	(original)
+++ pypy/branch/jitypes2/pypy/jit/backend/x86/valgrind.py	Fri Dec  3 11:04:29 2010
@@ -27,4 +27,4 @@
 
 def discard_translations(data, size):
     if we_are_translated() and VALGRIND_DISCARD_TRANSLATIONS is not None:
-        VALGRIND_DISCARD_TRANSLATIONS(llmemory.cast_ptr_to_adr(data), size)
+        VALGRIND_DISCARD_TRANSLATIONS(llmemory.cast_int_to_adr(data), size)

Modified: pypy/branch/jitypes2/pypy/jit/codewriter/call.py
==============================================================================
--- pypy/branch/jitypes2/pypy/jit/codewriter/call.py	(original)
+++ pypy/branch/jitypes2/pypy/jit/codewriter/call.py	Fri Dec  3 11:04:29 2010
@@ -95,15 +95,8 @@
             else:
                 v_obj = op.args[1].concretetype
                 graphs = v_obj._lookup_graphs(op.args[0].value)
-            if graphs is not None:
-                result = []
-                for graph in graphs:
-                    if is_candidate(graph):
-                        result.append(graph)
-                if result:
-                    return result  # common case: look inside these graphs,
-                                   # and ignore the others if there are any
-            else:
+            #
+            if graphs is None:
                 # special case: handle the indirect call that goes to
                 # the 'instantiate' methods.  This check is a bit imprecise
                 # but it's not too bad if we mistake a random indirect call
@@ -112,7 +105,16 @@
                 CALLTYPE = op.args[0].concretetype
                 if (op.opname == 'indirect_call' and len(op.args) == 2 and
                     CALLTYPE == rclass.OBJECT_VTABLE.instantiate):
-                    return list(self._graphs_of_all_instantiate())
+                    graphs = list(self._graphs_of_all_instantiate())
+            #
+            if graphs is not None:
+                result = []
+                for graph in graphs:
+                    if is_candidate(graph):
+                        result.append(graph)
+                if result:
+                    return result  # common case: look inside these graphs,
+                                   # and ignore the others if there are any
         # residual call case: we don't need to look into any graph
         return None
 

Modified: pypy/branch/jitypes2/pypy/jit/codewriter/jtransform.py
==============================================================================
--- pypy/branch/jitypes2/pypy/jit/codewriter/jtransform.py	(original)
+++ pypy/branch/jitypes2/pypy/jit/codewriter/jtransform.py	Fri Dec  3 11:04:29 2010
@@ -24,6 +24,7 @@
 
 
 class Transformer(object):
+    vable_array_vars = None
 
     def __init__(self, cpu=None, callcontrol=None, portal_jd=None):
         self.cpu = cpu
@@ -38,7 +39,6 @@
     def optimize_block(self, block):
         if block.operations == ():
             return
-        self.immutable_arrays = {}
         self.vable_array_vars = {}
         self.vable_flags = {}
         renamings = {}
@@ -83,6 +83,7 @@
         self.follow_constant_exit(block)
         self.optimize_goto_if_not(block)
         for link in block.exits:
+            self._check_no_vable_array(link.args)
             self._do_renaming_on_link(renamings, link)
 
     def _do_renaming(self, rename, op):
@@ -100,6 +101,28 @@
                 op.args[i] = ListOfKind(v.kind, newlst)
         return op
 
+    def _check_no_vable_array(self, list):
+        if not self.vable_array_vars:
+            return
+        for v in list:
+            if v in self.vable_array_vars:
+                raise AssertionError(
+                    "A virtualizable array is passed around; it should\n"
+                    "only be used immediately after being read.  Note\n"
+                    "that a possible cause is indexing with an index not\n"
+                    "known non-negative, or catching IndexError, or\n"
+                    "not inlining at all (for tests: use listops=True).\n"
+                    "Occurred in: %r" % self.graph)
+            # extra expanation: with the way things are organized in
+            # rpython/rlist.py, the ll_getitem becomes a function call
+            # that is typically meant to be inlined by the JIT, but
+            # this does not work with vable arrays because
+            # jtransform.py expects the getfield and the getarrayitem
+            # to be in the same basic block.  It works a bit as a hack
+            # for simple cases where we performed the backendopt
+            # inlining before (even with a very low threshold, because
+            # there is _always_inline_ on the relevant functions).
+
     def _do_renaming_on_link(self, rename, link):
         for i, v in enumerate(link.args):
             if isinstance(v, Variable):
@@ -170,9 +193,12 @@
         else:
             return rewrite(self, op)
 
-    def rewrite_op_same_as(self, op): pass
-    def rewrite_op_cast_pointer(self, op): pass
-    def rewrite_op_cast_opaque_ptr(self, op): pass   # rlib.rerased
+    def rewrite_op_same_as(self, op):
+        if op.args[0] in self.vable_array_vars:
+            self.vable_array_vars[op.result]= self.vable_array_vars[op.args[0]]
+
+    rewrite_op_cast_pointer = rewrite_op_same_as
+    rewrite_op_cast_opaque_ptr = rewrite_op_same_as   # rlib.rerased
     def rewrite_op_cast_primitive(self, op): pass
     def rewrite_op_cast_bool_to_int(self, op): pass
     def rewrite_op_cast_bool_to_uint(self, op): pass
@@ -257,6 +283,7 @@
            The name is one of '{residual,direct}_call_{r,ir,irf}_{i,r,f,v}'."""
         if args is None:
             args = op.args[1:]
+        self._check_no_vable_array(args)
         lst_i, lst_r, lst_f = self.make_three_lists(args)
         reskind = getkind(op.result.concretetype)[0]
         if lst_f or reskind == 'f': kinds = 'irf'
@@ -398,6 +425,7 @@
     rewrite_op_int_lshift_ovf  = _do_builtin_call
     rewrite_op_int_abs         = _do_builtin_call
     rewrite_op_gc_identityhash = _do_builtin_call
+    rewrite_op_gc_id           = _do_builtin_call
 
     # ----------
     # getfield/setfield/mallocs etc.
@@ -524,17 +552,14 @@
                                                 arrayfielddescr,
                                                 arraydescr)
             return []
-        # check for deepfrozen structures that force constant-folding
-        immut = v_inst.concretetype.TO._immutable_field(c_fieldname.value)
-        if immut:
+        # check for _immutable_fields_ hints
+        if v_inst.concretetype.TO._immutable_field(c_fieldname.value):
             if (self.callcontrol is not None and
                 self.callcontrol.could_be_green_field(v_inst.concretetype.TO,
                                                       c_fieldname.value)):
                 pure = '_greenfield'
             else:
                 pure = '_pure'
-            if immut == "[*]":
-                self.immutable_arrays[op.result] = True
         else:
             pure = ''
         argname = getattr(v_inst.concretetype.TO, '_gckind', 'gc')
@@ -931,21 +956,19 @@
         # base hints on the name of the ll function, which is a bit xxx-ish
         # but which is safe for now
         assert func.func_name.startswith('ll_')
+        # check that we have carefully placed the oopspec in
+        # pypy/rpython/rlist.py.  There should not be an oopspec on
+        # a ll_getitem or ll_setitem that expects a 'func' argument.
+        # The idea is that a ll_getitem/ll_setitem with dum_checkidx
+        # should get inlined by the JIT, so that we see the potential
+        # 'raise IndexError'.
+        assert 'func' not in func.func_code.co_varnames
         non_negative = '_nonneg' in func.func_name
         fast = '_fast' in func.func_name
-        if fast:
-            can_raise = False
-            non_negative = True
-        else:
-            tag = op.args[1].value
-            assert tag in (rlist.dum_nocheck, rlist.dum_checkidx)
-            can_raise = tag != rlist.dum_nocheck
-        return non_negative, can_raise
+        return non_negative or fast
 
     def _prepare_list_getset(self, op, descr, args, checkname):
-        non_negative, can_raise = self._get_list_nonneg_canraise_flags(op)
-        if can_raise:
-            raise NotSupported("list operation can raise")
+        non_negative = self._get_list_nonneg_canraise_flags(op)
         if non_negative:
             return args[1], []
         else:
@@ -957,9 +980,8 @@
             return v_posindex, [op0, op1]
 
     def _prepare_void_list_getset(self, op):
-        non_negative, can_raise = self._get_list_nonneg_canraise_flags(op)
-        if can_raise:
-            raise NotSupported("list operation can raise")
+        # sanity check:
+        self._get_list_nonneg_canraise_flags(op)
 
     def _get_initial_newlist_length(self, op, args):
         # normalize number of arguments to the 'newlist' function
@@ -1004,7 +1026,7 @@
         v_index, extraop = self._prepare_list_getset(op, arraydescr, args,
                                                      'check_neg_index')
         extra = getkind(op.result.concretetype)[0]
-        if pure or args[0] in self.immutable_arrays:
+        if pure:
             extra = 'pure_' + extra
         op = SpaceOperation('getarrayitem_gc_%s' % extra,
                             [args[0], arraydescr, v_index], op.result)

Modified: pypy/branch/jitypes2/pypy/jit/codewriter/support.py
==============================================================================
--- pypy/branch/jitypes2/pypy/jit/codewriter/support.py	(original)
+++ pypy/branch/jitypes2/pypy/jit/codewriter/support.py	Fri Dec  3 11:04:29 2010
@@ -168,6 +168,9 @@
 def _ll_1_gc_identityhash(x):
     return lltype.identityhash(x)
 
+def _ll_1_gc_id(ptr):
+    return llop.gc_id(lltype.Signed, ptr)
+
 def _ll_1_jit_force_virtual(inst):
     return llop.jit_force_virtual(lltype.typeOf(inst), inst)
 
@@ -548,6 +551,9 @@
 def get_identityhash_oopspec(op):
     return 'gc_identityhash', op.args
 
+def get_gcid_oopspec(op):
+    return 'gc_id', op.args
+
 
 RENAMED_ADT_NAME = {
     'list': {
@@ -578,6 +584,8 @@
         return get_oostring_oopspec(op)
     elif op.opname == 'gc_identityhash':
         return get_identityhash_oopspec(op)
+    elif op.opname == 'gc_id':
+        return get_gcid_oopspec(op)
     else:
         raise ValueError(op.opname)
 

Modified: pypy/branch/jitypes2/pypy/jit/codewriter/test/test_codewriter.py
==============================================================================
--- pypy/branch/jitypes2/pypy/jit/codewriter/test/test_codewriter.py	(original)
+++ pypy/branch/jitypes2/pypy/jit/codewriter/test/test_codewriter.py	Fri Dec  3 11:04:29 2010
@@ -152,6 +152,42 @@
     assert 'B2' in names
     assert 'dont_look' in names
 
+def test_instantiate_with_unreasonable_attr():
+    # It is possible to have in real code the instantiate() function for
+    # a class be dont-look-inside.  This is caused by the code that
+    # initialize the instance attributes: if one attribute has a strange
+    # type, the whole function is disabled.  Check that it still works.
+    class MyFakePolicy:
+        def look_inside_graph(self, graph):
+            name = graph.name
+            return not (name.startswith('instantiate_') and
+                        name.endswith('A2'))
+    class A1:
+        pass
+    class A2(A1):
+        pass
+    def f(n):
+        if n > 5:
+            x = A1
+        else:
+            x = A2
+        x()
+    rtyper = support.annotate(f, [35])
+    maingraph = rtyper.annotator.translator.graphs[0]
+    cw = CodeWriter(FakeCPU(rtyper), [FakeJitDriverSD(maingraph)])
+    cw.find_all_graphs(MyFakePolicy())
+    cw.make_jitcodes(verbose=True)
+    #
+    names = [jitcode.name for jitcode in cw.assembler.indirectcalltargets]
+    assert len(names) == 1
+    assert names[0].startswith('instantiate_') and names[0].endswith('A1')
+    #
+    print cw.assembler.list_of_addr2name
+    names = dict.fromkeys([value
+                           for key, value in cw.assembler.list_of_addr2name])
+    assert 'A1' in names
+    assert 'A2' in names
+
 def test_int_abs():
     def f(n):
         return abs(n)

Modified: pypy/branch/jitypes2/pypy/jit/codewriter/test/test_list.py
==============================================================================
--- pypy/branch/jitypes2/pypy/jit/codewriter/test/test_list.py	(original)
+++ pypy/branch/jitypes2/pypy/jit/codewriter/test/test_list.py	Fri Dec  3 11:04:29 2010
@@ -56,9 +56,8 @@
     if '/' in oopspec_name:
         oopspec_name, property = oopspec_name.split('/')
         def force_flags(op):
-            if property == 'NONNEG':   return True, False
-            if property == 'NEG':      return False, False
-            if property == 'CANRAISE': return False, True
+            if property == 'NONNEG':   return True
+            if property == 'NEG':      return False
             raise ValueError(property)
         tr._get_list_nonneg_canraise_flags = force_flags
     op = SpaceOperation('direct_call',
@@ -122,9 +121,6 @@
                      check_neg_index %r0, <ArrayDescr>, %i0 -> %i1
                      getarrayitem_gc_i %r0, <ArrayDescr>, %i1 -> %i2
                  """)
-    builtin_test('list.getitem/CANRAISE',
-                 [varoftype(FIXEDLIST), varoftype(lltype.Signed)],
-                 lltype.Signed, NotSupported)
 
 def test_fixed_getitem_foldable():
     builtin_test('list.getitem_foldable/NONNEG',
@@ -139,9 +135,6 @@
                      check_neg_index %r0, <ArrayDescr>, %i0 -> %i1
                      getarrayitem_gc_pure_i %r0, <ArrayDescr>, %i1 -> %i2
                  """)
-    builtin_test('list.getitem_foldable/CANRAISE',
-                 [varoftype(FIXEDLIST), varoftype(lltype.Signed)],
-                 lltype.Signed, NotSupported)
 
 def test_fixed_setitem():
     builtin_test('list.setitem/NONNEG', [varoftype(FIXEDLIST),
@@ -158,10 +151,6 @@
                      check_neg_index %r0, <ArrayDescr>, %i0 -> %i1
                      setarrayitem_gc_i %r0, <ArrayDescr>, %i1, %i2
                  """)
-    builtin_test('list.setitem/CANRAISE', [varoftype(FIXEDLIST),
-                                           varoftype(lltype.Signed),
-                                           varoftype(lltype.Signed)],
-                 lltype.Void, NotSupported)
 
 def test_fixed_len():
     builtin_test('list.len', [varoftype(FIXEDLIST)], lltype.Signed,
@@ -206,9 +195,6 @@
         check_resizable_neg_index %r0, <FieldDescr length>, %i0 -> %i1
         getlistitem_gc_i %r0, <FieldDescr items>, <ArrayDescr>, %i1 -> %i2
                  """)
-    builtin_test('list.getitem/CANRAISE',
-                 [varoftype(VARLIST), varoftype(lltype.Signed)],
-                 lltype.Signed, NotSupported)
 
 def test_resizable_setitem():
     builtin_test('list.setitem/NONNEG', [varoftype(VARLIST),
@@ -225,10 +211,6 @@
         check_resizable_neg_index %r0, <FieldDescr length>, %i0 -> %i1
         setlistitem_gc_i %r0, <FieldDescr items>, <ArrayDescr>, %i1, %i2
                  """)
-    builtin_test('list.setitem/CANRAISE', [varoftype(VARLIST),
-                                           varoftype(lltype.Signed),
-                                           varoftype(lltype.Signed)],
-                 lltype.Void, NotSupported)
 
 def test_resizable_len():
     builtin_test('list.len', [varoftype(VARLIST)], lltype.Signed,

Modified: pypy/branch/jitypes2/pypy/jit/codewriter/test/test_void_list.py
==============================================================================
--- pypy/branch/jitypes2/pypy/jit/codewriter/test/test_void_list.py	(original)
+++ pypy/branch/jitypes2/pypy/jit/codewriter/test/test_void_list.py	Fri Dec  3 11:04:29 2010
@@ -51,9 +51,6 @@
     builtin_test('list.getitem/NEG',
                  [varoftype(FIXEDLIST), varoftype(lltype.Signed)],
                  lltype.Void, "")
-    builtin_test('list.getitem/CANRAISE',
-                 [varoftype(FIXEDLIST), varoftype(lltype.Signed)],
-                 lltype.Void, NotSupported)
 
 def test_fixed_getitem_foldable():
     builtin_test('list.getitem_foldable/NONNEG',
@@ -62,9 +59,6 @@
     builtin_test('list.getitem_foldable/NEG',
                  [varoftype(FIXEDLIST), varoftype(lltype.Signed)],
                  lltype.Void, "")
-    builtin_test('list.getitem_foldable/CANRAISE',
-                 [varoftype(FIXEDLIST), varoftype(lltype.Signed)],
-                 lltype.Void, NotSupported)
 
 def test_fixed_setitem():
     builtin_test('list.setitem/NONNEG', [varoftype(FIXEDLIST),
@@ -75,10 +69,6 @@
                                       varoftype(lltype.Signed),
                                       varoftype(lltype.Void)],
                  lltype.Void, "")
-    builtin_test('list.setitem/CANRAISE', [varoftype(FIXEDLIST),
-                                           varoftype(lltype.Signed),
-                                           varoftype(lltype.Void)],
-                 lltype.Void, NotSupported)
 
 def test_fixed_len():
     builtin_test('list.len', [varoftype(FIXEDLIST)], lltype.Signed,
@@ -115,9 +105,6 @@
     builtin_test('list.getitem/NEG',
                  [varoftype(VARLIST), varoftype(lltype.Signed)],
                  lltype.Void, "")
-    builtin_test('list.getitem/CANRAISE',
-                 [varoftype(VARLIST), varoftype(lltype.Signed)],
-                 lltype.Void, NotSupported)
 
 def test_resizable_setitem():
     builtin_test('list.setitem/NONNEG', [varoftype(VARLIST),
@@ -128,10 +115,6 @@
                                       varoftype(lltype.Signed),
                                       varoftype(lltype.Void)],
                  lltype.Void, "")
-    builtin_test('list.setitem/CANRAISE', [varoftype(VARLIST),
-                                           varoftype(lltype.Signed),
-                                           varoftype(lltype.Void)],
-                 lltype.Void, NotSupported)
 
 def test_resizable_len():
     builtin_test('list.len', [varoftype(VARLIST)], lltype.Signed,

Modified: pypy/branch/jitypes2/pypy/jit/conftest.py
==============================================================================
--- pypy/branch/jitypes2/pypy/jit/conftest.py	(original)
+++ pypy/branch/jitypes2/pypy/jit/conftest.py	Fri Dec  3 11:04:29 2010
@@ -1,7 +1,5 @@
 import py
 
-option = py.test.config.option
-
 def pytest_addoption(parser):
     group = parser.getgroup("JIT options")
     group.addoption('--slow', action="store_true",

Modified: pypy/branch/jitypes2/pypy/jit/metainterp/compile.py
==============================================================================
--- pypy/branch/jitypes2/pypy/jit/metainterp/compile.py	(original)
+++ pypy/branch/jitypes2/pypy/jit/metainterp/compile.py	Fri Dec  3 11:04:29 2010
@@ -1,4 +1,4 @@
-
+import weakref
 from pypy.rpython.lltypesystem import lltype
 from pypy.rpython.ootypesystem import ootype
 from pypy.objspace.flow.model import Constant, Variable
@@ -48,6 +48,32 @@
     loop_token.outermost_jitdriver_sd = jitdriver_sd
     return loop_token
 
+def record_loop_or_bridge(loop):
+    """Do post-backend recordings and cleanups on 'loop'.
+    """
+    # get the original loop token (corresponding to 'loop', or if that is
+    # a bridge, to the loop that this bridge belongs to)
+    looptoken = loop.token
+    assert looptoken is not None
+    wref = weakref.ref(looptoken)
+    for op in loop.operations:
+        descr = op.getdescr()
+        if isinstance(descr, ResumeDescr):
+            descr.wref_original_loop_token = wref   # stick it there
+            n = descr.index
+            if n >= 0:       # we also record the resumedescr number
+                looptoken.compiled_loop_token.record_faildescr_index(n)
+        elif isinstance(descr, LoopToken):
+            # for a JUMP or a CALL_ASSEMBLER: record it as a potential jump.
+            # (the following test is not enough to prevent more complicated
+            # cases of cycles, but at least it helps in simple tests of
+            # test_memgr.py)
+            if descr is not looptoken:
+                looptoken.record_jump_to(descr)
+            op.setdescr(None)    # clear reference, mostly for tests
+    # mostly for tests: make sure we don't keep a reference to the LoopToken
+    loop.token = None
+
 # ____________________________________________________________
 
 def compile_new_loop(metainterp, old_loop_tokens, start):
@@ -77,6 +103,7 @@
         return old_loop_token
     send_loop_to_backend(metainterp_sd, loop, "loop")
     insert_loop_token(old_loop_tokens, loop_token)
+    record_loop_or_bridge(loop)
     return loop_token
 
 def insert_loop_token(old_loop_tokens, loop_token):
@@ -117,8 +144,11 @@
         else:
             loop._ignore_during_counting = True
     metainterp_sd.log("compiled new " + type)
+    if metainterp_sd.warmrunnerdesc is not None:    # for tests
+        metainterp_sd.warmrunnerdesc.memory_manager.keep_loop_alive(loop.token)
 
-def send_bridge_to_backend(metainterp_sd, faildescr, inputargs, operations):
+def send_bridge_to_backend(metainterp_sd, faildescr, inputargs, operations,
+                           original_loop_token):
     n = metainterp_sd.cpu.get_fail_descr_number(faildescr)
     metainterp_sd.logger_ops.log_bridge(inputargs, operations, n)
     if not we_are_translated():
@@ -127,7 +157,8 @@
     metainterp_sd.profiler.start_backend()
     debug_start("jit-backend")
     try:
-        metainterp_sd.cpu.compile_bridge(faildescr, inputargs, operations)
+        metainterp_sd.cpu.compile_bridge(faildescr, inputargs, operations,
+                                         original_loop_token)
     finally:
         debug_stop("jit-backend")
     metainterp_sd.profiler.end_backend()
@@ -227,9 +258,6 @@
     CNT_FLOAT = -0x60000000
     CNT_MASK  =  0x1FFFFFFF
 
-    def __init__(self, metainterp_sd):
-        self.metainterp_sd = metainterp_sd
-
     def store_final_boxes(self, guard_op, boxes):
         guard_op.setfailargs(boxes)
         self.guard_opnum = guard_op.getopnum()
@@ -314,12 +342,14 @@
 
     def compile_and_attach(self, metainterp, new_loop):
         # We managed to create a bridge.  Attach the new operations
-        # to the corrsponding guard_op and compile from there
+        # to the corresponding guard_op and compile from there
+        assert metainterp.resumekey_original_loop_token is not None
+        new_loop.token = metainterp.resumekey_original_loop_token
         inputargs = metainterp.history.inputargs
         if not we_are_translated():
             self._debug_suboperations = new_loop.operations
         send_bridge_to_backend(metainterp.staticdata, self, inputargs,
-                               new_loop.operations)
+                               new_loop.operations, new_loop.token)
 
     def copy_all_attrbutes_into(self, res):
         # XXX a bit ugly to have to list them all here
@@ -331,14 +361,14 @@
         res.rd_pendingfields = self.rd_pendingfields
 
     def _clone_if_mutable(self):
-        res = ResumeGuardDescr(self.metainterp_sd)
+        res = ResumeGuardDescr()
         self.copy_all_attrbutes_into(res)
         return res
 
 class ResumeGuardForcedDescr(ResumeGuardDescr):
 
     def __init__(self, metainterp_sd, jitdriver_sd):
-        ResumeGuardDescr.__init__(self, metainterp_sd)
+        self.metainterp_sd = metainterp_sd
         self.jitdriver_sd = jitdriver_sd
 
     def handle_fail(self, metainterp_sd, jitdriver_sd):
@@ -482,6 +512,8 @@
         metainterp_sd = metainterp.staticdata
         jitdriver_sd = metainterp.jitdriver_sd
         redargs = new_loop.inputargs
+        # We make a new LoopToken for this entry bridge, and stick it
+        # to every guard in the loop.
         new_loop_token = make_loop_token(len(redargs), jitdriver_sd)
         new_loop.token = new_loop_token
         send_loop_to_backend(metainterp_sd, new_loop, "entry bridge")
@@ -489,12 +521,14 @@
         jitdriver_sd.warmstate.attach_unoptimized_bridge_from_interp(
             self.original_greenkey,
             new_loop_token)
-        # store the new loop in compiled_merge_points too
+        # store the new loop in compiled_merge_points_wref too
         old_loop_tokens = metainterp.get_compiled_merge_points(
             self.original_greenkey)
         # it always goes at the end of the list, as it is the most
         # general loop token
         old_loop_tokens.append(new_loop_token)
+        metainterp.set_compiled_merge_points(self.original_greenkey,
+                                             old_loop_tokens)
 
     def reset_counter_from_failure(self):
         pass
@@ -529,6 +563,7 @@
         # know exactly what we must do (ResumeGuardDescr/ResumeFromInterpDescr)
         prepare_last_operation(new_loop, target_loop_token)
         resumekey.compile_and_attach(metainterp, new_loop)
+        record_loop_or_bridge(new_loop)
     return target_loop_token
 
 def prepare_last_operation(new_loop, target_loop_token):
@@ -555,7 +590,8 @@
 
 propagate_exception_descr = PropagateExceptionDescr()
 
-def compile_tmp_callback(cpu, jitdriver_sd, greenboxes, redboxes):
+def compile_tmp_callback(cpu, jitdriver_sd, greenboxes, redboxes,
+                         memory_manager=None):
     """Make a LoopToken that corresponds to assembler code that just
     calls back the interpreter.  Used temporarily: a fully compiled
     version of the code may end up replacing it.
@@ -595,4 +631,6 @@
         ]
     operations[1].setfailargs([])
     cpu.compile_loop(inputargs, operations, loop_token, log=False)
+    if memory_manager is not None:    # for tests
+        memory_manager.keep_loop_alive(loop_token)
     return loop_token

Modified: pypy/branch/jitypes2/pypy/jit/metainterp/history.py
==============================================================================
--- pypy/branch/jitypes2/pypy/jit/metainterp/history.py	(original)
+++ pypy/branch/jitypes2/pypy/jit/metainterp/history.py	Fri Dec  3 11:04:29 2010
@@ -4,8 +4,7 @@
 from pypy.rpython.ootypesystem import ootype
 from pypy.rlib.objectmodel import we_are_translated, r_dict, Symbolic
 from pypy.rlib.objectmodel import compute_hash, compute_unique_id
-from pypy.rlib.rarithmetic import intmask
-from pypy.tool.uid import uid
+from pypy.rlib.rarithmetic import intmask, r_int64
 from pypy.conftest import option
 
 from pypy.jit.metainterp.resoperation import ResOperation, rop
@@ -730,14 +729,28 @@
     outermost_jitdriver_sd = None
     # specnodes = ...
     # and more data specified by the backend when the loop is compiled
-    number = 0
+    number = -1
+    generation = r_int64(0)
+    # one purpose of LoopToken is to keep alive the CompiledLoopToken
+    # returned by the backend.  When the LoopToken goes away, the
+    # CompiledLoopToken has its __del__ called, which frees the assembler
+    # memory and the ResumeGuards.
+    compiled_loop_token = None
 
-    def __init__(self, number=0):
-        self.number = number
+    def __init__(self):
+        # For memory management of assembled loops
+        self._keepalive_target_looktokens = {}      # set of other LoopTokens
+
+    def record_jump_to(self, target_loop_token):
+        self._keepalive_target_looktokens[target_loop_token] = None
+
+    def __repr__(self):
+        return '<Loop %d, gen=%d>' % (self.number, self.generation)
 
     def repr_of_descr(self):
         return '<Loop%d>' % self.number
 
+
 class TreeLoop(object):
     inputargs = None
     operations = None

Modified: pypy/branch/jitypes2/pypy/jit/metainterp/jitprof.py
==============================================================================
--- pypy/branch/jitypes2/pypy/jit/metainterp/jitprof.py	(original)
+++ pypy/branch/jitypes2/pypy/jit/metainterp/jitprof.py	Fri Dec  3 11:04:29 2010
@@ -2,9 +2,9 @@
 """ A small helper module for profiling JIT
 """
 
-import os
 import time
-from pypy.rlib.debug import debug_print
+from pypy.rlib.debug import debug_print, debug_start, debug_stop
+from pypy.rlib.debug import have_debug_prints
 from pypy.jit.metainterp.jitexc import JitException
 
 counters="""
@@ -24,6 +24,10 @@
 NVIRTUALS
 NVHOLES
 NVREUSED
+TOTAL_COMPILED_LOOPS
+TOTAL_COMPILED_BRIDGES
+TOTAL_FREED_LOOPS
+TOTAL_FREED_BRIDGES
 """
 
 def _setup():
@@ -35,6 +39,7 @@
 _setup()
 
 JITPROF_LINES = ncounters + 1 + 1 # one for TOTAL, 1 for calls, update if needed
+_CPU_LINES = 4       # the last 4 lines are stored on the cpu
 
 class BaseProfiler(object):
     pass
@@ -48,9 +53,6 @@
     def finish(self):
         pass
 
-    def set_printing(self, printing):
-        pass
-
     def start_tracing(self):
         pass
 
@@ -90,23 +92,19 @@
     counters = None
     calls = 0
     current = None
-    printing = True
+    cpu = None
 
     def start(self):
         self.starttime = self.timer()
         self.t1 = self.starttime
         self.times = [0, 0]
-        self.counters = [0] * ncounters
+        self.counters = [0] * (ncounters - _CPU_LINES)
         self.calls = 0
         self.current = []
 
     def finish(self):
         self.tk = self.timer()
-        if self.printing:
-            self.print_stats()
-
-    def set_printing(self, printing):
-        self.printing = printing
+        self.print_stats()
 
     def _start(self, event):
         t0 = self.t1
@@ -154,6 +152,12 @@
             self.calls += 1
 
     def print_stats(self):
+        debug_start("jit-summary")
+        if have_debug_prints():
+            self._print_stats()
+        debug_stop("jit-summary")
+
+    def _print_stats(self):
         cnt = self.counters
         tim = self.times
         calls = self.calls
@@ -161,8 +165,8 @@
         self._print_line_time("Backend", cnt[BACKEND],   tim[BACKEND])
         self._print_intline("Running asm", cnt[RUNNING])
         self._print_intline("Blackhole", cnt[BLACKHOLE])
-        line = "TOTAL:      \t\t%f\n" % (self.tk - self.starttime, )
-        os.write(2, line)
+        line = "TOTAL:      \t\t%f" % (self.tk - self.starttime, )
+        debug_print(line)
         self._print_intline("ops", cnt[OPS])
         self._print_intline("recorded ops", cnt[RECORDED_OPS])
         self._print_intline("  calls", calls)
@@ -176,17 +180,26 @@
         self._print_intline("nvirtuals", cnt[NVIRTUALS])
         self._print_intline("nvholes", cnt[NVHOLES])
         self._print_intline("nvreused", cnt[NVREUSED])
+        cpu = self.cpu
+        if cpu is not None:   # for some tests
+            self._print_intline("Total # of loops",
+                                cpu.total_compiled_loops)
+            self._print_intline("Total # of bridges",
+                                cpu.total_compiled_bridges)
+            self._print_intline("Freed # of loops",
+                                cpu.total_freed_loops)
+            self._print_intline("Freed # of bridges",
+                                cpu.total_freed_bridges)
 
     def _print_line_time(self, string, i, tim):
-        final = "%s:%s\t%d\t%f\n" % (string, " " * max(0, 13-len(string)), i, tim)
-        os.write(2, final)
+        final = "%s:%s\t%d\t%f" % (string, " " * max(0, 13-len(string)), i, tim)
+        debug_print(final)
 
     def _print_intline(self, string, i):
         final = string + ':' + " " * max(0, 16-len(string))
-        final += '\t' + str(i) + '\n'
-        os.write(2, final)
-        
-        
+        final += '\t' + str(i)
+        debug_print(final)
+
 
 class BrokenProfilerData(JitException):
     pass

Modified: pypy/branch/jitypes2/pypy/jit/metainterp/pyjitpl.py
==============================================================================
--- pypy/branch/jitypes2/pypy/jit/metainterp/pyjitpl.py	(original)
+++ pypy/branch/jitypes2/pypy/jit/metainterp/pyjitpl.py	Fri Dec  3 11:04:29 2010
@@ -14,11 +14,10 @@
 from pypy.jit.metainterp.logger import Logger
 from pypy.jit.metainterp.jitprof import EmptyProfiler
 from pypy.jit.metainterp.jitprof import GUARDS, RECORDED_OPS, ABORT_ESCAPE
-from pypy.jit.metainterp.jitprof import ABORT_TOO_LONG
+from pypy.jit.metainterp.jitprof import ABORT_TOO_LONG, ABORT_BRIDGE
 from pypy.jit.metainterp.jitexc import JitException, get_llexception
 from pypy.rlib.rarithmetic import intmask
 from pypy.rlib.objectmodel import specialize
-from pypy.rlib.jit import DEBUG_OFF, DEBUG_PROFILE, DEBUG_STEPS, DEBUG_DETAILED
 from pypy.jit.codewriter.jitcode import JitCode, SwitchDictDescr
 from pypy.jit.codewriter import heaptracker
 
@@ -613,8 +612,10 @@
         virtualizable = vinfo.unwrap_virtualizable_box(virtualizable_box)
         arrayindex = vinfo.array_field_by_descrs[arrayfielddescr]
         index = indexbox.getint()
-        if index < 0:
-            index += vinfo.get_array_length(virtualizable, arrayindex)
+        # Support for negative index: disabled
+        # (see codewriter/jtransform.py, _check_no_vable_array).
+        #if index < 0:
+        #    index += vinfo.get_array_length(virtualizable, arrayindex)
         assert 0 <= index < vinfo.get_array_length(virtualizable, arrayindex)
         return vinfo.get_index_in_array(virtualizable, arrayindex, index)
 
@@ -1069,7 +1070,7 @@
             resumedescr = compile.ResumeGuardForcedDescr(metainterp_sd,
                                                    metainterp.jitdriver_sd)
         else:
-            resumedescr = compile.ResumeGuardDescr(metainterp_sd)
+            resumedescr = compile.ResumeGuardDescr()
         guard_op = metainterp.history.record(opnum, moreargs, None,
                                              descr=resumedescr)
         virtualizable_boxes = None
@@ -1223,6 +1224,7 @@
         self.logger_ops = Logger(self, guard_number=True)
 
         self.profiler = ProfilerClass()
+        self.profiler.cpu = cpu
         self.warmrunnerdesc = warmrunnerdesc
 
         backendmodule = self.cpu.__module__
@@ -1341,6 +1343,11 @@
                     return jitcode
             return None
 
+    def try_to_free_some_loops(self):
+        # Increase here the generation recorded by the memory manager.
+        if self.warmrunnerdesc is not None:       # for tests
+            self.warmrunnerdesc.memory_manager.next_generation()
+
     # ---------------- logging ------------------------
 
     def log(self, msg):
@@ -1637,6 +1644,7 @@
         self.staticdata._setup_once()
         self.staticdata.profiler.start_tracing()
         assert jitdriver_sd is self.jitdriver_sd
+        self.staticdata.try_to_free_some_loops()
         self.create_empty_history()
         try:
             original_boxes = self.initialize_original_boxes(jitdriver_sd, *args)
@@ -1665,10 +1673,15 @@
         debug_start('jit-tracing')
         self.staticdata.profiler.start_tracing()
         assert isinstance(key, compile.ResumeGuardDescr)
+        # store the resumekey.wref_original_loop_token() on 'self' to make
+        # sure that it stays alive as long as this MetaInterp
+        self.resumekey_original_loop_token = key.wref_original_loop_token()
+        self.staticdata.try_to_free_some_loops()
         self.initialize_state_from_guard_failure(key)
         try:
             return self._handle_guard_failure(key)
         finally:
+            self.resumekey_original_loop_token = None
             self.staticdata.profiler.end_tracing()
             debug_stop('jit-tracing')
 
@@ -1678,6 +1691,8 @@
         self.seen_loop_header_for_jdindex = -1
         try:
             self.prepare_resume_from_failure(key.guard_opnum)
+            if self.resumekey_original_loop_token is None:   # very rare case
+                raise SwitchToBlackhole(ABORT_BRIDGE)
             self.interpret()
         except GenerateMergePoint, gmp:
             return self.designate_target_loop(gmp)
@@ -1799,10 +1814,15 @@
             raise NotImplementedError(opname[opnum])
 
     def get_compiled_merge_points(self, greenkey):
+        """Get the list of looptokens corresponding to the greenkey.
+        Turns the (internal) list of weakrefs into regular refs.
+        """
+        cell = self.jitdriver_sd.warmstate.jit_cell_at_key(greenkey)
+        return cell.get_compiled_merge_points()
+
+    def set_compiled_merge_points(self, greenkey, looptokens):
         cell = self.jitdriver_sd.warmstate.jit_cell_at_key(greenkey)
-        if cell.compiled_merge_points is None:
-            cell.compiled_merge_points = []
-        return cell.compiled_merge_points
+        cell.set_compiled_merge_points(looptokens)
 
     def compile(self, original_boxes, live_arg_boxes, start):
         num_green_args = self.jitdriver_sd.num_green_args
@@ -1812,6 +1832,7 @@
         self.history.record(rop.JUMP, live_arg_boxes[num_green_args:], None)
         loop_token = compile.compile_new_loop(self, old_loop_tokens, start)
         if loop_token is not None: # raise if it *worked* correctly
+            self.set_compiled_merge_points(greenkey, old_loop_tokens)
             raise GenerateMergePoint(live_arg_boxes, loop_token)
         self.history.operations.pop()     # remove the JUMP
 

Modified: pypy/branch/jitypes2/pypy/jit/metainterp/test/test_basic.py
==============================================================================
--- pypy/branch/jitypes2/pypy/jit/metainterp/test/test_basic.py	(original)
+++ pypy/branch/jitypes2/pypy/jit/metainterp/test/test_basic.py	Fri Dec  3 11:04:29 2010
@@ -19,7 +19,11 @@
     from pypy.jit.metainterp import simple_optimize
 
     class FakeJitCell:
-        compiled_merge_points = None
+        __compiled_merge_points = []
+        def get_compiled_merge_points(self):
+            return self.__compiled_merge_points[:]
+        def set_compiled_merge_points(self, lst):
+            self.__compiled_merge_points = lst
 
     class FakeWarmRunnerState:
         def attach_unoptimized_bridge_from_interp(self, greenkey, newloop):
@@ -35,7 +39,6 @@
         optimize_bridge = staticmethod(simple_optimize.optimize_bridge)
 
         trace_limit = sys.maxint
-        debug_level = 2
 
     func._jit_unroll_safe_ = True
     rtyper = support.annotate(func, values, type_system=type_system)
@@ -1698,6 +1701,29 @@
         res = self.meta_interp(f, [5, 2])
         assert 4 < res < 14
 
+    def test_compute_identity_hash(self):
+        from pypy.rlib.objectmodel import compute_identity_hash
+        class A(object):
+            pass
+        def f():
+            a = A()
+            return compute_identity_hash(a) == compute_identity_hash(a)
+        res = self.interp_operations(f, [])
+        assert res
+        # a "did not crash" kind of test
+
+    def test_compute_unique_id(self):
+        from pypy.rlib.objectmodel import compute_unique_id
+        class A(object):
+            pass
+        def f():
+            a1 = A()
+            a2 = A()
+            return (compute_unique_id(a1) == compute_unique_id(a1) and
+                    compute_unique_id(a1) != compute_unique_id(a2))
+        res = self.interp_operations(f, [])
+        assert res
+
 
 class TestOOtype(BasicTests, OOJitMixin):
 

Modified: pypy/branch/jitypes2/pypy/jit/metainterp/test/test_compile.py
==============================================================================
--- pypy/branch/jitypes2/pypy/jit/metainterp/test/test_compile.py	(original)
+++ pypy/branch/jitypes2/pypy/jit/metainterp/test/test_compile.py	Fri Dec  3 11:04:29 2010
@@ -42,7 +42,6 @@
 
 class FakeState:
     optimize_loop = staticmethod(optimize.optimize_loop)
-    debug_level = 0
 
 class FakeGlobalData:
     loopnumbering = 0
@@ -54,6 +53,7 @@
 
     stats = Stats()
     profiler = jitprof.EmptyProfiler()
+    warmrunnerdesc = None
     def log(self, msg, event_kind=None):
         pass
 
@@ -207,14 +207,12 @@
         class ExitFrameWithExceptionRef(Exception):
             pass
     FakeMetaInterpSD.cpu = cpu
-    class FakeJitDriverSD:
-        pass
     cpu.set_future_value_int(0, -156)
     cpu.set_future_value_int(1, -178)
     cpu.set_future_value_int(2, -190)
     fail_descr = cpu.execute_token(loop_token)
     try:
-        fail_descr.handle_fail(FakeMetaInterpSD(), FakeJitDriverSD())
+        fail_descr.handle_fail(FakeMetaInterpSD(), None)
     except FakeMetaInterpSD.ExitFrameWithExceptionRef, e:
         assert lltype.cast_opaque_ptr(lltype.Ptr(EXC), e.args[1]) == llexc
     else:

Modified: pypy/branch/jitypes2/pypy/jit/metainterp/test/test_list.py
==============================================================================
--- pypy/branch/jitypes2/pypy/jit/metainterp/test/test_list.py	(original)
+++ pypy/branch/jitypes2/pypy/jit/metainterp/test/test_list.py	Fri Dec  3 11:04:29 2010
@@ -188,6 +188,26 @@
         assert res == f(4)
         self.check_loops(call=0, getfield_gc=0)
 
+    def test_fold_indexerror(self):
+        jitdriver = JitDriver(greens = [], reds = ['total', 'n', 'lst'])
+        def f(n):
+            lst = []
+            total = 0
+            while n > 0:
+                jitdriver.can_enter_jit(lst=lst, n=n, total=total)
+                jitdriver.jit_merge_point(lst=lst, n=n, total=total)
+                lst.append(n)
+                try:
+                    total += lst[n]
+                except IndexError:
+                    total += 1000
+                n -= 1
+            return total
+
+        res = self.meta_interp(f, [15], listops=True)
+        assert res == f(15)
+        self.check_loops(guard_exception=0)
+
 class TestOOtype(ListTests, OOJitMixin):
     pass
 

Modified: pypy/branch/jitypes2/pypy/jit/metainterp/test/test_logger.py
==============================================================================
--- pypy/branch/jitypes2/pypy/jit/metainterp/test/test_logger.py	(original)
+++ pypy/branch/jitypes2/pypy/jit/metainterp/test/test_logger.py	Fri Dec  3 11:04:29 2010
@@ -14,11 +14,20 @@
 
 def capturing(func, *args, **kwds):
     log_stream = StringIO()
-    debug._stderr = log_stream
+    class MyDebugLog:
+        def debug_print(self, *args):
+            for arg in args:
+                print >> log_stream, arg,
+            print >> log_stream
+        def debug_start(self, *args):
+            pass
+        def debug_stop(self, *args):
+            pass
     try:
+        debug._log = MyDebugLog()
         func(*args, **kwds)
     finally:
-        debug._stderr = sys.stderr
+        debug._log = None
     return log_stream.getvalue()
 
 class Logger(logger.Logger):
@@ -112,7 +121,8 @@
         equaloplists(loop.operations, oloop.operations)
 
     def test_jump(self):
-        namespace = {'target': LoopToken(3)}
+        namespace = {'target': LoopToken()}
+        namespace['target'].number = 3
         inp = '''
         [i0]
         jump(i0, descr=target)

Modified: pypy/branch/jitypes2/pypy/jit/metainterp/test/test_optimizeopt.py
==============================================================================
--- pypy/branch/jitypes2/pypy/jit/metainterp/test/test_optimizeopt.py	(original)
+++ pypy/branch/jitypes2/pypy/jit/metainterp/test/test_optimizeopt.py	Fri Dec  3 11:04:29 2010
@@ -41,7 +41,7 @@
     b1 = BoxInt()
     opt = optimizeopt.Optimizer(FakeMetaInterpStaticData(LLtypeMixin.cpu),
                                 None)
-    fdescr = ResumeGuardDescr(None)
+    fdescr = ResumeGuardDescr()
     op = ResOperation(rop.GUARD_TRUE, ['dummy'], None, descr=fdescr)
     # setup rd data
     fi0 = resume.FrameInfo(None, "code0", 11)

Modified: pypy/branch/jitypes2/pypy/jit/metainterp/test/test_pyjitpl.py
==============================================================================
--- pypy/branch/jitypes2/pypy/jit/metainterp/test/test_pyjitpl.py	(original)
+++ pypy/branch/jitypes2/pypy/jit/metainterp/test/test_pyjitpl.py	Fri Dec  3 11:04:29 2010
@@ -17,6 +17,7 @@
     portal.setup(None)
     class FakeStaticData:
         cpu = None
+        warmrunnerdesc = None
 
     metainterp = pyjitpl.MetaInterp(FakeStaticData(), None)
     metainterp.framestack = []
@@ -53,6 +54,7 @@
 def test_remove_consts_and_duplicates():
     class FakeStaticData:
         cpu = None
+        warmrunnerdesc = None
     def is_another_box_like(box, referencebox):
         assert box is not referencebox
         assert isinstance(box, referencebox.clonebox().__class__)

Modified: pypy/branch/jitypes2/pypy/jit/metainterp/test/test_recursive.py
==============================================================================
--- pypy/branch/jitypes2/pypy/jit/metainterp/test/test_recursive.py	(original)
+++ pypy/branch/jitypes2/pypy/jit/metainterp/test/test_recursive.py	Fri Dec  3 11:04:29 2010
@@ -927,12 +927,16 @@
                                             x=x)
                 frame.s = hint(frame.s, promote=True)
                 n -= 1
-                x += frame.l[frame.s]
+                s = frame.s
+                assert s >= 0
+                x += frame.l[s]
                 frame.s += 1
                 if codeno == 0:
                     subframe = Frame([n, n+1, n+2, n+3], 0)
                     x += f(1, 10, 1, subframe)
-                x += frame.l[frame.s]
+                s = frame.s
+                assert s >= 0
+                x += frame.l[s]
                 x += len(frame.l)
                 frame.s -= 1
             return x

Modified: pypy/branch/jitypes2/pypy/jit/metainterp/test/test_virtualizable.py
==============================================================================
--- pypy/branch/jitypes2/pypy/jit/metainterp/test/test_virtualizable.py	(original)
+++ pypy/branch/jitypes2/pypy/jit/metainterp/test/test_virtualizable.py	Fri Dec  3 11:04:29 2010
@@ -480,9 +480,13 @@
                 myjitdriver.jit_merge_point(frame=frame, n=n, x=x)
                 frame.s = hint(frame.s, promote=True)
                 n -= 1
-                x += frame.l[frame.s]
+                s = frame.s
+                assert s >= 0
+                x += frame.l[s]
                 frame.s += 1
-                x += frame.l[frame.s]
+                s = frame.s
+                assert s >= 0
+                x += frame.l[s]
                 x += len(frame.l)
                 frame.s -= 1
             return x
@@ -994,7 +998,9 @@
                 jitdriver.can_enter_jit(frame=frame, n=n)
                 jitdriver.jit_merge_point(frame=frame, n=n)
                 popped = frame.stack[frame.stackpos]
-                frame.stackpos -= 1
+                sp = frame.stackpos - 1
+                assert sp >= 0
+                frame.stackpos = sp
                 to_push = intmask(popped * 3)
                 frame.stack[frame.stackpos] = to_push
                 frame.stackpos += 1

Modified: pypy/branch/jitypes2/pypy/jit/metainterp/test/test_warmspot.py
==============================================================================
--- pypy/branch/jitypes2/pypy/jit/metainterp/test/test_warmspot.py	(original)
+++ pypy/branch/jitypes2/pypy/jit/metainterp/test/test_warmspot.py	Fri Dec  3 11:04:29 2010
@@ -132,91 +132,6 @@
         assert state.optimize_loop is optimize.optimize_loop
         assert state.optimize_bridge is optimize.optimize_bridge
 
-    def test_static_debug_level(self, capfd):
-        py.test.skip("debug_level is being deprecated")
-        from pypy.rlib.jit import DEBUG_PROFILE, DEBUG_OFF, DEBUG_STEPS
-        from pypy.jit.metainterp.jitprof import EmptyProfiler, Profiler
-        
-        myjitdriver = JitDriver(greens = [], reds = ['n'])
-        def f(n):
-            while n > 0:
-                myjitdriver.can_enter_jit(n=n)
-                myjitdriver.jit_merge_point(n=n)
-                n -= 1
-            return n
-
-        capfd.readouterr()
-        self.meta_interp(f, [10], debug_level=DEBUG_OFF,
-                                  ProfilerClass=Profiler)
-        out, err = capfd.readouterr()
-        assert not 'ENTER' in err
-        assert not 'LEAVE' in err
-        assert not "Running asm" in err
-        self.meta_interp(f, [10], debug_level=DEBUG_PROFILE,
-                                  ProfilerClass=Profiler)
-        out, err = capfd.readouterr()
-        assert not 'ENTER' in err
-        assert not 'LEAVE' in err
-        assert not 'compiled new' in err
-        assert "Running asm" in err
-
-        self.meta_interp(f, [10], debug_level=DEBUG_STEPS,
-                                  ProfilerClass=Profiler)
-        out, err = capfd.readouterr()
-        assert 'ENTER' in err
-        assert 'LEAVE' in err
-        assert "Running asm" in err
-
-        self.meta_interp(f, [10], debug_level=DEBUG_STEPS,
-                                  ProfilerClass=EmptyProfiler)
-        out, err = capfd.readouterr()
-        assert 'ENTER' in err
-        assert 'LEAVE' in err
-        assert not "Running asm" in err
-
-    def test_set_param_debug(self):
-        py.test.skip("debug_level is being deprecated")
-        from pypy.rlib.jit import DEBUG_PROFILE, DEBUG_OFF, DEBUG_STEPS
-        from pypy.jit.metainterp.jitprof import EmptyProfiler, Profiler
-        
-        myjitdriver = JitDriver(greens = [], reds = ['n'])
-        def f(n):
-            while n > 0:
-                myjitdriver.can_enter_jit(n=n)
-                myjitdriver.jit_merge_point(n=n)
-                n -= 1
-            return n
-
-        def main(n, debug):
-            myjitdriver.set_param("debug", debug)
-            print f(n)
-
-        outerr = py.io.StdCaptureFD()
-        self.meta_interp(main, [10, DEBUG_OFF], debug_level=DEBUG_STEPS,
-                                                ProfilerClass=Profiler)
-        out, errf = outerr.done()
-        err = errf.read()
-        assert not 'ENTER' in err
-        assert not 'LEAVE' in err
-        assert not "Running asm" in err
-        outerr = py.io.StdCaptureFD()
-        self.meta_interp(main, [10, DEBUG_PROFILE], debug_level=DEBUG_STEPS,
-                                                    ProfilerClass=Profiler)
-        out, errf = outerr.done()
-        err = errf.read()
-        assert not 'ENTER' in err
-        assert not 'LEAVE' in err
-        assert not 'compiled new' in err
-        assert "Running asm" in err
-        outerr = py.io.StdCaptureFD()
-        self.meta_interp(main, [10, DEBUG_STEPS], debug_level=DEBUG_OFF,
-                                                  ProfilerClass=Profiler)
-        out, errf = outerr.done()
-        err = errf.read()
-        assert 'ENTER' in err
-        assert 'LEAVE' in err
-        assert "Running asm" in err
-
     def test_unwanted_loops(self):
         mydriver = JitDriver(reds = ['n', 'total', 'm'], greens = [])
 
@@ -378,23 +293,30 @@
         exc_vtable = lltype.malloc(OBJECT_VTABLE, immortal=True)
         cls.exc_vtable = exc_vtable
 
-        class FakeFailDescr(object):
+        class FakeLoopToken:
             def __init__(self, no):
                 self.no = no
+                self.generation = 0
+
+        class FakeFailDescr(object):
+            def __init__(self, looptoken):
+                assert isinstance(looptoken, FakeLoopToken)
+                self.looptoken = looptoken
             
             def handle_fail(self, metainterp_sd, jitdrivers_sd):
-                if self.no == 0:
+                no = self.looptoken.no
+                if no == 0:
                     raise metainterp_sd.warmrunnerdesc.DoneWithThisFrameInt(3)
-                if self.no == 1:
+                if no == 1:
                     raise metainterp_sd.warmrunnerdesc.ContinueRunningNormally(
                         [0], [], [], [1], [], [])
-                if self.no == 3:
+                if no == 3:
                     exc = lltype.malloc(OBJECT)
                     exc.typeptr = exc_vtable
                     raise metainterp_sd.warmrunnerdesc.ExitFrameWithExceptionRef(
                         metainterp_sd.cpu,
                         lltype.cast_opaque_ptr(llmemory.GCREF, exc))
-                return self.no
+                return self.looptoken
 
         class FakeDescr:
             def as_vtable_size_descr(self):
@@ -419,11 +341,11 @@
             sizeof       = nodescr
 
             def get_fail_descr_from_number(self, no):
-                return FakeFailDescr(no)
+                return FakeFailDescr(FakeLoopToken(no))
 
             def execute_token(self, token):
-                assert token == 2
-                return FakeFailDescr(1)
+                assert token.no == 2
+                return FakeFailDescr(FakeLoopToken(1))
 
         driver = JitDriver(reds = ['red'], greens = ['green'])
         

Modified: pypy/branch/jitypes2/pypy/jit/metainterp/test/test_warmstate.py
==============================================================================
--- pypy/branch/jitypes2/pypy/jit/metainterp/test/test_warmstate.py	(original)
+++ pypy/branch/jitypes2/pypy/jit/metainterp/test/test_warmstate.py	Fri Dec  3 11:04:29 2010
@@ -99,6 +99,8 @@
                                          lltype.Float], lltype.Void))
     class FakeWarmRunnerDesc:
         rtyper = FakeRTyper()
+        cpu = None
+        memory_manager = None
     class FakeJitDriverSD:
         _get_jitcell_at_ptr = llhelper(GETTER, getter)
         _set_jitcell_at_ptr = llhelper(SETTER, setter)
@@ -126,6 +128,7 @@
             future_values[j] = "float", value
     class FakeWarmRunnerDesc:
         cpu = FakeCPU()
+        memory_manager = None
     class FakeJitDriverSD:
         _red_args_types = ["int", "float"]
         virtualizable_info = None
@@ -154,16 +157,20 @@
         _get_jitcell_at_ptr = None
     state = WarmEnterState(None, FakeJitDriverSD())
     get_jitcell = state.make_jitcell_getter()
+    class FakeLoopToken(object):
+        pass
+    looptoken = FakeLoopToken()
     state.attach_unoptimized_bridge_from_interp([ConstInt(5),
                                                  ConstFloat(2.25)],
-                                                "entry loop token")
+                                                looptoken)
     cell1 = get_jitcell(True, 5, 2.25)
     assert cell1.counter < 0
-    assert cell1.entry_loop_token == "entry loop token"
+    assert cell1.get_entry_loop_token() is looptoken
 
 def test_make_jitdriver_callbacks_1():
     class FakeWarmRunnerDesc:
         cpu = None
+        memory_manager = None
     class FakeJitDriverSD:
         _green_args_spec = [lltype.Signed, lltype.Float]
         _get_printable_location_ptr = None
@@ -189,6 +196,7 @@
     class FakeWarmRunnerDesc:
         rtyper = None
         cpu = None
+        memory_manager = None
     class FakeJitDriverSD:
         _green_args_spec = [lltype.Signed, lltype.Float]
         _get_printable_location_ptr = llhelper(GET_LOCATION, get_location)
@@ -211,6 +219,7 @@
     class FakeWarmRunnerDesc:
         rtyper = None
         cpu = None
+        memory_manager = None
     class FakeJitDriverSD:
         _green_args_spec = [lltype.Signed, lltype.Float]
         _get_printable_location_ptr = None
@@ -233,6 +242,7 @@
     class FakeWarmRunnerDesc:
         rtyper = None
         cpu = None
+        memory_manager = None
     class FakeJitDriverSD:
         _green_args_spec = [lltype.Signed, lltype.Float]
         _get_printable_location_ptr = None

Modified: pypy/branch/jitypes2/pypy/jit/metainterp/warmspot.py
==============================================================================
--- pypy/branch/jitypes2/pypy/jit/metainterp/warmspot.py	(original)
+++ pypy/branch/jitypes2/pypy/jit/metainterp/warmspot.py	Fri Dec  3 11:04:29 2010
@@ -12,11 +12,12 @@
 from pypy.rlib.unroll import unrolling_iterable
 from pypy.rlib.rarithmetic import r_uint, intmask
 from pypy.rlib.debug import debug_print, fatalerror
+from pypy.rlib.debug import debug_start, debug_stop
 from pypy.rpython.lltypesystem.lloperation import llop
 from pypy.translator.simplify import get_funcobj, get_functype
 from pypy.translator.unsimplify import call_final_function
 
-from pypy.jit.metainterp import history, pyjitpl, gc
+from pypy.jit.metainterp import history, pyjitpl, gc, memmgr
 from pypy.jit.metainterp.pyjitpl import MetaInterpStaticData, MetaInterp
 from pypy.jit.metainterp.typesystem import LLTypeHelper, OOTypeHelper
 from pypy.jit.metainterp.jitprof import Profiler, EmptyProfiler
@@ -24,21 +25,17 @@
 from pypy.jit.metainterp.jitdriver import JitDriverStaticData
 from pypy.jit.codewriter import support, codewriter
 from pypy.jit.codewriter.policy import JitPolicy
-from pypy.rlib.jit import DEBUG_STEPS, DEBUG_DETAILED, DEBUG_OFF, DEBUG_PROFILE
 
 # ____________________________________________________________
 # Bootstrapping
 
-def apply_jit(translator, backend_name="auto", debug_level=DEBUG_STEPS,
-              inline=False,
-              **kwds):
+def apply_jit(translator, backend_name="auto", inline=False, **kwds):
     if 'CPUClass' not in kwds:
         from pypy.jit.backend.detect_cpu import getcpuclass
         kwds['CPUClass'] = getcpuclass(backend_name)
-    if debug_level > DEBUG_OFF:
-        ProfilerClass = Profiler
-    else:
-        ProfilerClass = EmptyProfiler
+    ProfilerClass = Profiler
+    # Always use Profiler here, which should have a very low impact.
+    # Otherwise you can try with ProfilerClass = EmptyProfiler.
     warmrunnerdesc = WarmRunnerDesc(translator,
                                     translate_support_code=True,
                                     listops=True,
@@ -47,7 +44,6 @@
                                     **kwds)
     for jd in warmrunnerdesc.jitdrivers_sd:
         jd.warmstate.set_param_inlining(inline)
-        jd.warmstate.set_param_debug(debug_level)
     warmrunnerdesc.finish()
     translator.warmrunnerdesc = warmrunnerdesc    # for later debugging
 
@@ -66,7 +62,7 @@
 
 def jittify_and_run(interp, graph, args, repeat=1,
                     backendopt=False, trace_limit=sys.maxint,
-                    debug_level=DEBUG_STEPS, inline=False, **kwds):
+                    inline=False, loop_longevity=0, **kwds):
     from pypy.config.config import ConfigError
     translator = interp.typer.annotator.translator
     try:
@@ -83,7 +79,7 @@
         jd.warmstate.set_param_trace_eagerness(2)    # for tests
         jd.warmstate.set_param_trace_limit(trace_limit)
         jd.warmstate.set_param_inlining(inline)
-        jd.warmstate.set_param_debug(debug_level)
+        jd.warmstate.set_param_loop_longevity(loop_longevity)
     warmrunnerdesc.finish()
     res = interp.eval_graph(graph, args)
     if not kwds.get('translate_support_code', False):
@@ -151,6 +147,7 @@
                  optimizer=None, ProfilerClass=EmptyProfiler, **kwds):
         pyjitpl._warmrunnerdesc = self   # this is a global for debugging only!
         self.set_translator(translator)
+        self.memory_manager = memmgr.MemoryManager()
         self.build_cpu(CPUClass, **kwds)
         self.find_portals()
         self.codewriter = codewriter.CodeWriter(self.cpu, self.jitdrivers_sd)
@@ -162,6 +159,8 @@
         self.check_access_directly_sanity(graphs)
         if backendopt:
             self.prejit_optimizations(policy, graphs)
+        elif self.opt.listops:
+            self.prejit_optimizations_minimal_inline(policy, graphs)
 
         self.build_meta_interp(ProfilerClass)
         self.make_args_specifications()
@@ -259,6 +258,10 @@
                               remove_asserts=True,
                               really_remove_asserts=True)
 
+    def prejit_optimizations_minimal_inline(self, policy, graphs):
+        from pypy.translator.backendopt.inline import auto_inline_graphs
+        auto_inline_graphs(self.translator, graphs, 0.01)
+
     def build_cpu(self, CPUClass, translate_support_code=False,
                   no_stats=False, **kwds):
         assert CPUClass is not None
@@ -713,7 +716,7 @@
                     loop_token = fail_descr.handle_fail(self.metainterp_sd, jd)
                 except JitException, e:
                     return handle_jitexception(e)
-                fail_descr = self.cpu.execute_token(loop_token)
+                fail_descr = self.execute_token(loop_token)
 
         jd._assembler_call_helper = assembler_call_helper # for debugging
         jd._assembler_helper_ptr = self.helper_func(
@@ -807,3 +810,10 @@
             py.test.skip("rewrite_force_virtual: port it to ootype")
         all_graphs = self.translator.graphs
         vrefinfo.replace_force_virtual_with_call(all_graphs)
+
+    # ____________________________________________________________
+
+    def execute_token(self, loop_token):
+        fail_descr = self.cpu.execute_token(loop_token)
+        self.memory_manager.keep_loop_alive(loop_token)
+        return fail_descr

Modified: pypy/branch/jitypes2/pypy/jit/metainterp/warmstate.py
==============================================================================
--- pypy/branch/jitypes2/pypy/jit/metainterp/warmstate.py	(original)
+++ pypy/branch/jitypes2/pypy/jit/metainterp/warmstate.py	Fri Dec  3 11:04:29 2010
@@ -1,4 +1,4 @@
-import sys
+import sys, weakref
 from pypy.rpython.lltypesystem import lltype, llmemory, rstr, rffi
 from pypy.rpython.ootypesystem import ootype
 from pypy.rpython.annlowlevel import hlstr, llstr, cast_base_ptr_to_instance
@@ -9,7 +9,6 @@
 from pypy.rlib.unroll import unrolling_iterable
 from pypy.rlib.jit import (PARAMETERS, OPTIMIZER_SIMPLE, OPTIMIZER_FULL,
                            OPTIMIZER_NO_PERFECTSPEC)
-from pypy.rlib.jit import DEBUG_PROFILE
 from pypy.rlib.jit import BaseJitCell
 from pypy.rlib.debug import debug_start, debug_stop, debug_print
 from pypy.jit.metainterp import history
@@ -150,9 +149,34 @@
     #     counter == -1: there is an entry bridge for this cell
     #     counter == -2: tracing is currently going on for this cell
     counter = 0
-    compiled_merge_points = None
+    compiled_merge_points_wref = None    # list of weakrefs to LoopToken
     dont_trace_here = False
-    entry_loop_token = None
+    wref_entry_loop_token = None         # (possibly) one weakref to LoopToken
+
+    def get_compiled_merge_points(self):
+        result = []
+        if self.compiled_merge_points_wref is not None:
+            for wref in self.compiled_merge_points_wref:
+                looptoken = wref()
+                if looptoken is not None:
+                    result.append(looptoken)
+        return result
+
+    def set_compiled_merge_points(self, looptokens):
+        self.compiled_merge_points_wref = [self._makeref(token)
+                                           for token in looptokens]
+
+    def get_entry_loop_token(self):
+        if self.wref_entry_loop_token is not None:
+            return self.wref_entry_loop_token()
+        return None
+
+    def set_entry_loop_token(self, looptoken):
+        self.wref_entry_loop_token = self._makeref(looptoken)
+
+    def _makeref(self, looptoken):
+        assert looptoken is not None
+        return weakref.ref(looptoken)
 
 # ____________________________________________________________
 
@@ -165,6 +189,8 @@
         "NOT_RPYTHON"
         self.warmrunnerdesc = warmrunnerdesc
         self.jitdriver_sd = jitdriver_sd
+        if warmrunnerdesc is not None:       # for tests
+            self.cpu = warmrunnerdesc.cpu
         try:
             self.profiler = warmrunnerdesc.metainterp_sd.profiler
         except AttributeError:       # for tests
@@ -176,7 +202,7 @@
             meth(default_value)
 
     def set_param_threshold(self, threshold):
-        if threshold < 0:
+        if threshold <= 0:
             self.increment_threshold = 0   # never reach the THRESHOLD_LIMIT
             return
         if threshold < 2:
@@ -209,10 +235,11 @@
         else:
             raise ValueError("unknown optimizer")
 
-    def set_param_debug(self, value):
-        self.debug_level = value
-        if self.profiler is not None:
-            self.profiler.set_printing(value >= DEBUG_PROFILE)
+    def set_param_loop_longevity(self, value):
+        # note: it's a global parameter, not a per-jitdriver one
+        if (self.warmrunnerdesc is not None and
+            self.warmrunnerdesc.memory_manager is not None):   # all for tests
+            self.warmrunnerdesc.memory_manager.set_max_age(value)
 
     def disable_noninlinable_function(self, greenkey):
         cell = self.jit_cell_at_key(greenkey)
@@ -225,12 +252,15 @@
     def attach_unoptimized_bridge_from_interp(self, greenkey,
                                               entry_loop_token):
         cell = self.jit_cell_at_key(greenkey)
-        cell.counter = -1
-        old_token = cell.entry_loop_token
-        cell.entry_loop_token = entry_loop_token
+        old_token = cell.get_entry_loop_token()
+        cell.set_entry_loop_token(entry_loop_token)
+        cell.counter = -1       # valid entry bridge attached
         if old_token is not None:
-            cpu = self.warmrunnerdesc.cpu
-            cpu.redirect_call_assembler(old_token, entry_loop_token)
+            self.cpu.redirect_call_assembler(old_token, entry_loop_token)
+            # entry_loop_token is also kept alive by any loop that used
+            # to point to old_token.  Actually freeing old_token early
+            # is a pointless optimization (it is tiny).
+            old_token.record_jump_to(entry_loop_token)
 
     # ----------
 
@@ -239,7 +269,8 @@
         if hasattr(self, 'maybe_compile_and_run'):
             return self.maybe_compile_and_run
 
-        metainterp_sd = self.warmrunnerdesc.metainterp_sd
+        warmrunnerdesc = self.warmrunnerdesc
+        metainterp_sd = warmrunnerdesc.metainterp_sd
         jitdriver_sd = self.jitdriver_sd
         vinfo = jitdriver_sd.virtualizable_info
         index_of_virtualizable = jitdriver_sd.index_of_virtualizable
@@ -297,23 +328,27 @@
                 assert cell.counter == -1
                 if not confirm_enter_jit(*args):
                     return
+                loop_token = cell.get_entry_loop_token()
+                if loop_token is None:   # it was a weakref that has been freed
+                    cell.counter = 0
+                    return
                 # machine code was already compiled for these greenargs
                 # get the assembler and fill in the boxes
                 set_future_values(*args[num_green_args:])
-                loop_token = cell.entry_loop_token
 
             # ---------- execute assembler ----------
             while True:     # until interrupted by an exception
                 metainterp_sd.profiler.start_running()
                 debug_start("jit-running")
-                fail_descr = metainterp_sd.cpu.execute_token(loop_token)
+                fail_descr = warmrunnerdesc.execute_token(loop_token)
                 debug_stop("jit-running")
                 metainterp_sd.profiler.end_running()
+                loop_token = None     # for test_memmgr
                 if vinfo is not None:
                     vinfo.reset_vable_token(virtualizable)
                 loop_token = fail_descr.handle_fail(metainterp_sd,
                                                     jitdriver_sd)
-       
+
         maybe_compile_and_run._dont_inline_ = True
         self.maybe_compile_and_run = maybe_compile_and_run
         return maybe_compile_and_run
@@ -459,7 +494,7 @@
 
         warmrunnerdesc = self.warmrunnerdesc
         jitdriver_sd   = self.jitdriver_sd
-        cpu = warmrunnerdesc.cpu
+        cpu = self.cpu
         vinfo = jitdriver_sd.virtualizable_info
         red_args_types = unrolling_iterable(jitdriver_sd._red_args_types)
         #
@@ -508,10 +543,11 @@
         if hasattr(self, 'get_location_str'):
             return
         #
+        warmrunnerdesc = self.warmrunnerdesc
         unwrap_greenkey = self.make_unwrap_greenkey()
         jit_getter = self.make_jitcell_getter()
         jd = self.jitdriver_sd
-        cpu = self.warmrunnerdesc.cpu
+        cpu = self.cpu
 
         def can_inline_greenargs(*greenargs):
             if can_never_inline(*greenargs):
@@ -529,11 +565,16 @@
         def get_assembler_token(greenkey, redboxes):
             # 'redboxes' is only used to know the types of red arguments
             cell = self.jit_cell_at_key(greenkey)
-            if cell.entry_loop_token is None:
+            entry_loop_token = cell.get_entry_loop_token()
+            if entry_loop_token is None:
                 from pypy.jit.metainterp.compile import compile_tmp_callback
-                cell.entry_loop_token = compile_tmp_callback(cpu, jd, greenkey,
-                                                             redboxes)
-            return cell.entry_loop_token
+                if cell.counter == -1:    # used to be a valid entry bridge,
+                    cell.counter = 0      # but was freed in the meantime.
+                memmgr = warmrunnerdesc.memory_manager
+                entry_loop_token = compile_tmp_callback(cpu, jd, greenkey,
+                                                        redboxes, memmgr)
+                cell.set_entry_loop_token(entry_loop_token)
+            return entry_loop_token
         self.get_assembler_token = get_assembler_token
         
         #

Modified: pypy/branch/jitypes2/pypy/jit/tl/spli/interpreter.py
==============================================================================
--- pypy/branch/jitypes2/pypy/jit/tl/spli/interpreter.py	(original)
+++ pypy/branch/jitypes2/pypy/jit/tl/spli/interpreter.py	Fri Dec  3 11:04:29 2010
@@ -105,26 +105,32 @@
         self.stack_depth += 1
 
     def pop(self):
-        self.stack_depth -= 1
-        val = self.value_stack[self.stack_depth]
-        self.value_stack[self.stack_depth] = None
+        sd = self.stack_depth - 1
+        assert sd >= 0
+        self.stack_depth = sd
+        val = self.value_stack[sd]
+        self.value_stack[sd] = None
         return val
 
     def pop_many(self, n):
         return [self.pop() for i in range(n)]
 
     def peek(self):
-        return self.value_stack[self.stack_depth - 1]
+        sd = self.stack_depth - 1
+        assert sd >= 0
+        return self.value_stack[sd]
 
     def POP_TOP(self, _, next_instr, code):
         self.pop()
         return next_instr
 
     def LOAD_FAST(self, name_index, next_instr, code):
+        assert name_index >= 0
         self.push(self.locals[name_index])
         return next_instr
 
     def STORE_FAST(self, name_index, next_instr, code):
+        assert name_index >= 0
         self.locals[name_index] = self.pop()
         return next_instr
 

Modified: pypy/branch/jitypes2/pypy/jit/tl/tl.py
==============================================================================
--- pypy/branch/jitypes2/pypy/jit/tl/tl.py	(original)
+++ pypy/branch/jitypes2/pypy/jit/tl/tl.py	Fri Dec  3 11:04:29 2010
@@ -16,32 +16,40 @@
     def __init__(self, size):
         self = hint(self, access_directly=True, fresh_virtualizable=True)
         self.stack = [0] * size
-        self.stackpos = 0
+        self.stackpos = 0        # always store a known-nonneg integer here
 
     def append(self, elem):
         self.stack[self.stackpos] = elem
         self.stackpos += 1
 
     def pop(self):
-        self.stackpos -= 1
-        if self.stackpos < 0:
+        stackpos = self.stackpos - 1
+        if stackpos < 0:
             raise IndexError
-        return self.stack[self.stackpos]
+        self.stackpos = stackpos     # always store a known-nonneg integer here
+        return self.stack[stackpos]
 
     def pick(self, i):
-        self.append(self.stack[self.stackpos - i - 1])
+        n = self.stackpos - i - 1
+        assert n >= 0
+        self.append(self.stack[n])
 
     def put(self, i):
         elem = self.pop()
-        self.stack[self.stackpos - i - 1] = elem
+        n = self.stackpos - i - 1
+        assert n >= 0
+        self.stack[n] = elem
 
     def roll(self, r):
         if r < -1:
             i = self.stackpos + r
             if i < 0:
                 raise IndexError
-            elem = self.stack[self.stackpos - 1]
+            n = self.stackpos - 1
+            assert n >= 0
+            elem = self.stack[n]
             for j in range(self.stackpos - 2, i - 1, -1):
+                assert j >= 0
                 self.stack[j + 1] = self.stack[j]
             self.stack[i] = elem
         elif r > 1:
@@ -51,7 +59,9 @@
             elem = self.stack[i]
             for j in range(i, self.stackpos - 1):
                 self.stack[j] = self.stack[j + 1]
-            self.stack[self.stackpos - 1] = elem
+            n = self.stackpos - 1
+            assert n >= 0
+            self.stack[n] = elem
 
 
 def make_interp(supports_call):

Modified: pypy/branch/jitypes2/pypy/jit/tool/jitoutput.py
==============================================================================
--- pypy/branch/jitypes2/pypy/jit/tool/jitoutput.py	(original)
+++ pypy/branch/jitypes2/pypy/jit/tool/jitoutput.py	Fri Dec  3 11:04:29 2010
@@ -27,6 +27,10 @@
     (('nvirtuals',), '^nvirtuals:\s+(\d+)$'),
     (('nvholes',), '^nvholes:\s+(\d+)$'),
     (('nvreused',), '^nvreused:\s+(\d+)$'),
+    (('total_compiled_loops',),   '^Total # of loops:\s+(\d+)$'),
+    (('total_compiled_bridges',), '^Total # of bridges:\s+(\d+)$'),
+    (('total_freed_loops',),      '^Freed # of loops:\s+(\d+)$'),
+    (('total_freed_bridges',),    '^Freed # of bridges:\s+(\d+)$'),
     ]
 
 class Ops(object):

Modified: pypy/branch/jitypes2/pypy/jit/tool/log-template.gnumeric
==============================================================================
Binary files. No diff available.

Modified: pypy/branch/jitypes2/pypy/jit/tool/log2gnumeric.py
==============================================================================
--- pypy/branch/jitypes2/pypy/jit/tool/log2gnumeric.py	(original)
+++ pypy/branch/jitypes2/pypy/jit/tool/log2gnumeric.py	Fri Dec  3 11:04:29 2010
@@ -14,42 +14,85 @@
 
 import re, sys
 import gzip
+import optparse
 
-def main():
+
+def main(logname, options):
     logname = sys.argv[1]
     outname = logname + '.gnumeric'
     data = open(logname).read()
     data = data.replace('\n', '')
-    xml = gzip.open('log-template.gnumeric').read()
+    minclock, maxclock = get_clock_range(data)
+    time0 = minclock # we want "relative clocks"
+    maxtime = maxclock-time0
     #
-    xml = replace_sheet(xml, 'translation-task', tasks_rows(data))
-    xml = replace_sheet(xml, 'gc-collect', gc_collect_rows(data))
+    xml = gzip.open('log-template.gnumeric').read()
+    xml = replace_sheet(xml, 'translation-task', tasks_rows(time0, data))
+    xml = replace_sheet(xml, 'gc-collect', gc_collect_rows(time0, data))
+    xml = replace_sheet(xml, 'loops', loops_rows(time0, data))
+    xml = replace_sheet(xml, 'vmrss', vmrss_rows(logname + '.vmrss', maxtime))
+    xml = replace_sheet(xml, 'cpython-vmrss', vmrss_rows(options.cpython_vmrss, maxtime))
     #
     out = gzip.open(outname, 'wb')
     out.write(xml)
     out.close()
 
 
+# ========================================================================
+# functions to manipulate gnumeric files
+# ========================================================================
+
 def replace_sheet(xml, sheet_name, data):
-    pattern = '(<gnm:Sheet .*?<gnm:Name>%s</gnm:Name>.*?)<gnm:Cells>.*?</gnm:Cells>'
+    pattern = '<gnm:Sheet .*?<gnm:Name>%s</gnm:Name>.*?(<gnm:Cells>.*?</gnm:Cells>)'
     regex = re.compile(pattern % sheet_name, re.DOTALL)
     cells = gen_cells(data)
-    xml2 = regex.sub(r'\1%s' % cells, xml)
-    assert xml != xml2
+    match = regex.search(xml)
+    if not match:
+        print 'Cannot find sheet %s' % sheet_name
+        return xml
+    a, b = match.span(1)
+    xml2 = xml[:a] + cells + xml[b:]
     return xml2
 
 def gen_cells(data):
+    # values for the ValueType attribute
+    ValueType_Empty  = 'ValueType="10"'
+    ValueType_Number = 'ValueType="40"'
+    ValueType_String = 'ValueType="60"'
+    #
     parts = []
-    parts.append('      <gnm:Cells>')
+    parts.append('<gnm:Cells>')
     for i, row in enumerate(data):
         for j, val in enumerate(row):
-            cell = '         <gnm:Cell Row="%d" Col="%d">%s</gnm:Cell>'
-            parts.append(cell % (i, j, val))
+            if val is None:
+                attr = ValueType_Empty
+                val = ''
+            elif isinstance(val, (int, long, float)):
+                attr = ValueType_Number
+            else:
+                attr = ValueType_String
+            cell = '        <gnm:Cell Row="%d" Col="%d" %s>%s</gnm:Cell>'
+            parts.append(cell % (i, j, attr, val))
     parts.append('      </gnm:Cells>')
-    return ''.join(parts)
+    return '\n'.join(parts)
     
 
-def gc_collect_rows(data, show_header=True):
+# ========================================================================
+# functions to extract various data from the logs
+# ========================================================================
+
+CLOCK_FACTOR = 1
+def read_clock(x):
+    timestamp = int(x, 16)
+    return timestamp / CLOCK_FACTOR
+
+def get_clock_range(data):
+    s = r"\[([0-9a-f]+)\] "
+    r = re.compile(s)
+    clocks = [read_clock(x) for x in r.findall(data)]
+    return min(clocks), max(clocks)
+
+def gc_collect_rows(time0, data):
     s = r"""
 ----------- Full collection ------------------
 \| used before collection:
@@ -63,19 +106,75 @@
 \[([0-9a-f]+)\] gc-collect\}"""
     #
     r = re.compile(s.replace('\n', ''))
+    yield 'clock', 'gc-before', 'gc-after'
     for a,b,c,d,e,f in r.findall(data):
-        yield int(f, 16), int(a)+int(b), int(c)+int(d)
+        clock = read_clock(f) - time0
+        yield clock, int(a)+int(b), int(c)+int(d)
 
-def tasks_rows(data):
+def tasks_rows(time0, data):
     s = r"""
-\{translation-task
+\[([0-9a-f]+)\] \{translation-task
 starting ([\w-]+)
-\[([0-9a-f]+)\] translation-task\}"""
+"""
     #
     r = re.compile(s.replace('\n', ''))
+    yield 'clock', None, 'task'
     for a,b in r.findall(data):
-        yield int(b, 16), 1, a
+        clock = read_clock(a) - time0
+        yield clock, 1, b
+
+
+def loops_rows(time0, data):
+    s = r"""
+\[([0-9a-f]+)\] \{jit-mem-looptoken-(alloc|free)
+(.*?)\[
+"""
+    #
+    r = re.compile(s.replace('\n', ''))
+    yield 'clock', 'total', 'loops', 'bridges'
+    loops = 0
+    bridges = 0
+    fake_total = 0
+    for clock, action, text in r.findall(data):
+        clock = read_clock(clock) - time0
+        if text.startswith('allocating Loop #'):
+            loops += 1
+        elif text.startswith('allocating Bridge #'):
+            bridges += 1
+        elif text.startswith('freeing Loop #'):
+            match = re.match('freeing Loop # .* with ([0-9]*) attached bridges', text)
+            loops -=1
+            bridges -= int(match.group(1))
+        total = loops+bridges
+        yield clock, loops+bridges, loops, bridges
+
+
+def vmrss_rows(filename, maxtime):
+    lines = []
+    if options.cpython_vmrss:
+        try:
+            lines = open(filename).readlines()
+        except IOError:
+            print 'Warning: cannot find file %s, skipping this sheet'
+    for row in vmrss_rows_impl(lines, maxtime):
+        yield row
+
+def vmrss_rows_impl(lines, maxtime):
+    yield 'inferred clock', 'VmRSS'
+    numlines = len(lines)
+    for i, line in enumerate(lines):
+        mem = int(line)
+        clock = maxtime * i // (numlines-1)
+        yield clock, mem
 
 
 if __name__ == '__main__':
-    main()
+    CLOCK_FACTOR = 1000000000.0 # report GigaTicks instead of Ticks
+    parser = optparse.OptionParser(usage="%prog logfile [options]")
+    parser.add_option('-c', '--cpython-vmrss', dest='cpython_vmrss', default=None, metavar='FILE', type=str,
+                      help='the .vmrss file produced by CPython')
+    options, args = parser.parse_args()
+    if len(args) != 1:
+        parser.print_help()
+        sys.exit(2)
+    main(args[0], options)

Modified: pypy/branch/jitypes2/pypy/jit/tool/test/test_jitoutput.py
==============================================================================
--- pypy/branch/jitypes2/pypy/jit/tool/test/test_jitoutput.py	(original)
+++ pypy/branch/jitypes2/pypy/jit/tool/test/test_jitoutput.py	Fri Dec  3 11:04:29 2010
@@ -1,10 +1,11 @@
 
 import py
 from pypy.jit.metainterp.warmspot import ll_meta_interp
-from pypy.rlib.jit import JitDriver, DEBUG_PROFILE
+from pypy.rlib.jit import JitDriver
 from pypy.jit.backend.llgraph import runner
 from pypy.jit.metainterp.jitprof import Profiler, JITPROF_LINES
 from pypy.jit.tool.jitoutput import parse_prof
+from pypy.tool.logparser import parse_log, extract_category
 
 def test_really_run():
     """ This test checks whether output of jitprof did not change.
@@ -21,13 +22,15 @@
     cap = py.io.StdCaptureFD()
     try:
         ll_meta_interp(f, [10], CPUClass=runner.LLtypeCPU, type_system='lltype',
-                       ProfilerClass=Profiler, debug_level=DEBUG_PROFILE)
+                       ProfilerClass=Profiler)
     finally:
         out, err = cap.reset()
-    err = "\n".join(err.splitlines()[-JITPROF_LINES:])
-    print err
-    assert err.count("\n") == JITPROF_LINES - 1
-    info = parse_prof(err)
+
+    log = parse_log(err.splitlines(True))
+    err_sections = list(extract_category(log, 'jit-summary'))
+    [err1] = err_sections    # there should be exactly one jit-summary
+    assert err1.count("\n") == JITPROF_LINES
+    info = parse_prof(err1)
     # assert did not crash
     # asserts below are a bit delicate, possibly they might be deleted
     assert info.tracing_no == 1
@@ -60,6 +63,10 @@
 nvirtuals:              13
 nvholes:                14
 nvreused:               15
+Total # of loops:       100
+Total # of bridges:     300
+Freed # of loops:       99
+Freed # of bridges:     299
 '''
 
 def test_parse():

Modified: pypy/branch/jitypes2/pypy/module/__pypy__/__init__.py
==============================================================================
--- pypy/branch/jitypes2/pypy/module/__pypy__/__init__.py	(original)
+++ pypy/branch/jitypes2/pypy/module/__pypy__/__init__.py	Fri Dec  3 11:04:29 2010
@@ -11,6 +11,11 @@
         'internal_repr'             : 'interp_magic.internal_repr',
         'bytebuffer'                : 'bytebuffer.bytebuffer',
         'identity_dict'             : 'interp_identitydict.W_IdentityDict',
+        'debug_start'               : 'interp_debug.debug_start',
+        'debug_print'               : 'interp_debug.debug_print',
+        'debug_stop'                : 'interp_debug.debug_stop',
+        'debug_print_once'          : 'interp_debug.debug_print_once',
+        'builtinify'                : 'interp_magic.builtinify',
     }
 
     def setup_after_space_initialization(self):

Modified: pypy/branch/jitypes2/pypy/module/__pypy__/interp_magic.py
==============================================================================
--- pypy/branch/jitypes2/pypy/module/__pypy__/interp_magic.py	(original)
+++ pypy/branch/jitypes2/pypy/module/__pypy__/interp_magic.py	Fri Dec  3 11:04:29 2010
@@ -51,3 +51,9 @@
     return space.newtuple([space.newint(cache.hits.get(name, 0)),
                            space.newint(cache.misses.get(name, 0))])
 mapdict_cache_counter.unwrap_spec = [ObjSpace, str]
+
+def builtinify(space, w_func):
+    from pypy.interpreter.function import Function, BuiltinFunction
+    func = space.interp_w(Function, w_func)
+    bltn = BuiltinFunction(func)
+    return space.wrap(bltn)

Modified: pypy/branch/jitypes2/pypy/module/__pypy__/test/test_special.py
==============================================================================
--- pypy/branch/jitypes2/pypy/module/__pypy__/test/test_special.py	(original)
+++ pypy/branch/jitypes2/pypy/module/__pypy__/test/test_special.py	Fri Dec  3 11:04:29 2010
@@ -21,3 +21,18 @@
     def test_cpumodel(self):
         import __pypy__
         assert hasattr(__pypy__, 'cpumodel')
+
+    def test_builtinify(self):
+        import __pypy__
+        class A(object):
+            a = lambda *args: args
+            b = __pypy__.builtinify(a)
+        my = A()
+        assert my.a() == (my,)
+        assert my.b() == ()
+        assert A.a(my) == (my,)
+        assert A.b(my) == (my,)
+        assert A.a.im_func(my) == (my,)
+        assert not hasattr(A.b, 'im_func')
+        assert A.a is not A.__dict__['a']
+        assert A.b is A.__dict__['b']

Modified: pypy/branch/jitypes2/pypy/module/_minimal_curses/__init__.py
==============================================================================
--- pypy/branch/jitypes2/pypy/module/_minimal_curses/__init__.py	(original)
+++ pypy/branch/jitypes2/pypy/module/_minimal_curses/__init__.py	Fri Dec  3 11:04:29 2010
@@ -4,7 +4,7 @@
     try:
         import _minimal_curses as _curses   # when running on top of pypy-c
     except ImportError:
-        import py; py.test.skip("no _curses module")    # no _curses at all
+        raise ImportError("no _curses or _minimal_curses module")  # no _curses at all
 
 from pypy.interpreter.mixedmodule import MixedModule
 from pypy.module._minimal_curses import fficurses

Modified: pypy/branch/jitypes2/pypy/module/_pickle_support/maker.py
==============================================================================
--- pypy/branch/jitypes2/pypy/module/_pickle_support/maker.py	(original)
+++ pypy/branch/jitypes2/pypy/module/_pickle_support/maker.py	Fri Dec  3 11:04:29 2010
@@ -67,11 +67,12 @@
     return space.wrap(tb)
 traceback_new.unwrap_spec = [ObjSpace]
 
-def generator_new(space, frame, running):
+def generator_new(space, w_frame, running):
+    frame = space.interp_w(PyFrame, w_frame, can_be_None=True)
     new_generator = GeneratorIterator(frame)
     new_generator.running = running
     return space.wrap(new_generator)
-generator_new.unwrap_spec = [ObjSpace, PyFrame, int]
+generator_new.unwrap_spec = [ObjSpace, W_Root, int]
 
 def xrangeiter_new(space, current, remaining, step):
     from pypy.module.__builtin__.functional import W_XRangeIterator

Modified: pypy/branch/jitypes2/pypy/module/cpyext/api.py
==============================================================================
--- pypy/branch/jitypes2/pypy/module/cpyext/api.py	(original)
+++ pypy/branch/jitypes2/pypy/module/cpyext/api.py	Fri Dec  3 11:04:29 2010
@@ -321,6 +321,8 @@
     'PyCObject_Type', 'init_pycobject',
 
     'PyObject_AsReadBuffer', 'PyObject_AsWriteBuffer', 'PyObject_CheckReadBuffer',
+
+    'PyStructSequence_InitType', 'PyStructSequence_New',
 ]
 TYPES = {}
 GLOBALS = { # this needs to include all prebuilt pto, otherwise segfaults occur
@@ -367,7 +369,7 @@
         }.items():
         GLOBALS['Py%s_Type#' % (cpyname, )] = ('PyTypeObject*', pypyexpr)
 
-    for cpyname in 'Method List Int Long Dict Tuple Class'.split():
+    for cpyname in 'Method List Int Long Dict Class'.split():
         FORWARD_DECLS.append('typedef struct { PyObject_HEAD } '
                              'Py%sObject' % (cpyname, ))
 build_exported_objects()
@@ -845,6 +847,7 @@
                                source_dir / "bufferobject.c",
                                source_dir / "object.c",
                                source_dir / "cobject.c",
+                               source_dir / "structseq.c",
                                ],
         separate_module_sources = [code, struct_source],
         export_symbols=export_symbols_eci,

Modified: pypy/branch/jitypes2/pypy/module/cpyext/cdatetime.py
==============================================================================
--- pypy/branch/jitypes2/pypy/module/cpyext/cdatetime.py	(original)
+++ pypy/branch/jitypes2/pypy/module/cpyext/cdatetime.py	Fri Dec  3 11:04:29 2010
@@ -4,8 +4,7 @@
 from pypy.module.cpyext.api import (
     cpython_api, CANNOT_FAIL, cpython_struct, PyObjectFields)
 from pypy.module.cpyext.import_ import PyImport_Import
-from pypy.module.cpyext.typeobject import PyTypeObjectPtr, render_immortal
-from pypy.module.cpyext.state import State
+from pypy.module.cpyext.typeobject import PyTypeObjectPtr
 from pypy.interpreter.error import OperationError
 from pypy.tool.sourcetools import func_renamer
 
@@ -25,48 +24,26 @@
     datetimeAPI = lltype.malloc(PyDateTime_CAPI, flavor='raw',
                                 track_allocation=False)
 
-    if not we_are_translated():
-        datetimeAPI_dealloc(space)
-        space.fromcache(State).datetimeAPI = datetimeAPI
-
     w_datetime = PyImport_Import(space, space.wrap("datetime"))
 
     w_type = space.getattr(w_datetime, space.wrap("date"))
     datetimeAPI.c_DateType = rffi.cast(
         PyTypeObjectPtr, make_ref(space, w_type))
-    render_immortal(datetimeAPI.c_DateType, w_type)
 
     w_type = space.getattr(w_datetime, space.wrap("datetime"))
     datetimeAPI.c_DateTimeType = rffi.cast(
         PyTypeObjectPtr, make_ref(space, w_type))
-    render_immortal(datetimeAPI.c_DateTimeType, w_type)
 
     w_type = space.getattr(w_datetime, space.wrap("time"))
     datetimeAPI.c_TimeType = rffi.cast(
         PyTypeObjectPtr, make_ref(space, w_type))
-    render_immortal(datetimeAPI.c_TimeType, w_type)
 
     w_type = space.getattr(w_datetime, space.wrap("timedelta"))
     datetimeAPI.c_DeltaType = rffi.cast(
         PyTypeObjectPtr, make_ref(space, w_type))
-    render_immortal(datetimeAPI.c_DeltaType, w_type)
 
     return datetimeAPI
 
-def datetimeAPI_dealloc(space):
-    "Used in tests only, to please the refcount checker"
-    if we_are_translated():
-        return
-    datetimeAPI = space.fromcache(State).datetimeAPI
-    if datetimeAPI is None:
-        return
-    space.fromcache(State).datetimeAPI = None
-    Py_DecRef(space, rffi.cast(PyObject, datetimeAPI.c_DateType))
-    Py_DecRef(space, rffi.cast(PyObject, datetimeAPI.c_DateTimeType))
-    Py_DecRef(space, rffi.cast(PyObject, datetimeAPI.c_TimeType))
-    Py_DecRef(space, rffi.cast(PyObject, datetimeAPI.c_DeltaType))
-    lltype.free(datetimeAPI, flavor='raw')
-
 PyDateTime_Date = PyObject
 PyDateTime_Time = PyObject
 PyDateTime_DateTime = PyObject

Modified: pypy/branch/jitypes2/pypy/module/cpyext/include/tupleobject.h
==============================================================================
--- pypy/branch/jitypes2/pypy/module/cpyext/include/tupleobject.h	(original)
+++ pypy/branch/jitypes2/pypy/module/cpyext/include/tupleobject.h	Fri Dec  3 11:04:29 2010
@@ -10,9 +10,19 @@
 /* defined in varargswrapper.c */
 PyObject * PyTuple_Pack(Py_ssize_t, ...);
 
-#define PyTuple_SET_ITEM PyTuple_SetItem
-#define PyTuple_GET_ITEM PyTuple_GetItem
+typedef struct {
+    PyObject_HEAD
+    PyObject **items;
+    Py_ssize_t size;
+} PyTupleObject;
 
+#define PyTuple_GET_ITEM        PyTuple_GetItem
+
+/* Macro, trading safety for speed */
+#define PyTuple_GET_SIZE(op)    (((PyTupleObject *)(op))->size)
+
+/* Macro, *only* to be used to fill in brand new tuples */
+#define PyTuple_SET_ITEM(op, i, v) (((PyTupleObject *)(op))->items[i] = v)
 
 #ifdef __cplusplus
 }

Modified: pypy/branch/jitypes2/pypy/module/cpyext/sequence.py
==============================================================================
--- pypy/branch/jitypes2/pypy/module/cpyext/sequence.py	(original)
+++ pypy/branch/jitypes2/pypy/module/cpyext/sequence.py	Fri Dec  3 11:04:29 2010
@@ -116,6 +116,14 @@
     This is the equivalent of the Python expression o1 + o2."""
     return space.add(w_o1, w_o2)
 
+ at cpython_api([PyObject, PyObject], rffi.INT_real, error=-1)
+def PySequence_Contains(space, w_obj, w_value):
+    """Determine if o contains value.  If an item in o is equal to value,
+    return 1, otherwise return 0. On error, return -1.  This is
+    equivalent to the Python expression value in o."""
+    w_res = space.contains(w_obj, w_value)
+    return space.int_w(w_res)
+
 @cpython_api([PyObject], PyObject)
 def PySeqIter_New(space, w_seq):
     """Return an iterator that works with a general sequence object, seq.  The

Modified: pypy/branch/jitypes2/pypy/module/cpyext/slotdefs.py
==============================================================================
--- pypy/branch/jitypes2/pypy/module/cpyext/slotdefs.py	(original)
+++ pypy/branch/jitypes2/pypy/module/cpyext/slotdefs.py	Fri Dec  3 11:04:29 2010
@@ -6,7 +6,7 @@
     unaryfunc, wrapperfunc, ternaryfunc, PyTypeObjectPtr, binaryfunc,
     getattrfunc, setattrofunc, lenfunc, ssizeargfunc, ssizessizeargfunc,
     ssizeobjargproc, iternextfunc, initproc, richcmpfunc, hashfunc,
-    descrgetfunc, descrsetfunc)
+    descrgetfunc, descrsetfunc, objobjproc)
 from pypy.module.cpyext.pyobject import from_ref
 from pypy.module.cpyext.pyerrors import PyErr_Occurred
 from pypy.module.cpyext.state import State
@@ -28,14 +28,14 @@
 
 def check_num_args(space, ob, n):
     from pypy.module.cpyext.tupleobject import PyTuple_CheckExact, \
-            PyTuple_GET_SIZE
+            _PyTuple_Size_Fast
     if not PyTuple_CheckExact(space, ob):
         raise OperationError(space.w_SystemError,
             space.wrap("PyArg_UnpackTuple() argument list is not a tuple"))
-    if n == PyTuple_GET_SIZE(space, ob):
+    if n == _PyTuple_Size_Fast(space, ob):
         return
     raise operationerrfmt(space.w_TypeError,
-        "expected %d arguments, got %d", n, PyTuple_GET_SIZE(space, ob))
+        "expected %d arguments, got %d", n, _PyTuple_Size_Fast(space, ob))
 
 def wrap_init(space, w_self, w_args, func, w_kwargs):
     func_init = rffi.cast(initproc, func)
@@ -156,6 +156,15 @@
     if rffi.cast(lltype.Signed, res) == -1:
         space.fromcache(State).check_and_raise_exception(always=True)
 
+def wrap_objobjproc(space, w_self, w_args, func):
+    func_target = rffi.cast(objobjproc, func)
+    check_num_args(space, w_args, 1)
+    w_value, = space.fixedview(w_args)
+    res = generic_cpy_call(space, func_target, w_self, w_value)
+    if rffi.cast(lltype.Signed, res) == -1:
+        space.fromcache(State).check_and_raise_exception(always=True)
+    return space.wrap(res)
+
 def wrap_ssizessizeargfunc(space, w_self, w_args, func):
     func_target = rffi.cast(ssizessizeargfunc, func)
     check_num_args(space, w_args, 2)

Modified: pypy/branch/jitypes2/pypy/module/cpyext/state.py
==============================================================================
--- pypy/branch/jitypes2/pypy/module/cpyext/state.py	(original)
+++ pypy/branch/jitypes2/pypy/module/cpyext/state.py	Fri Dec  3 11:04:29 2010
@@ -5,8 +5,6 @@
 
 
 class State:
-    datetimeAPI = None # used in tests
-
     def __init__(self, space):
         self.space = space
         self.reset()

Modified: pypy/branch/jitypes2/pypy/module/cpyext/stubs.py
==============================================================================
--- pypy/branch/jitypes2/pypy/module/cpyext/stubs.py	(original)
+++ pypy/branch/jitypes2/pypy/module/cpyext/stubs.py	Fri Dec  3 11:04:29 2010
@@ -2289,13 +2289,6 @@
     in your code for properly supporting 64-bit systems."""
     raise NotImplementedError
 
- at cpython_api([PyObject, PyObject], rffi.INT_real, error=-1)
-def PySequence_Contains(space, o, value):
-    """Determine if o contains value.  If an item in o is equal to value,
-    return 1, otherwise return 0. On error, return -1.  This is
-    equivalent to the Python expression value in o."""
-    raise NotImplementedError
-
 @cpython_api([PyObject, PyObject], Py_ssize_t, error=-1)
 def PySequence_Index(space, o, value):
     """Return the first index i for which o[i] == value.  On error, return

Modified: pypy/branch/jitypes2/pypy/module/cpyext/test/test_arraymodule.py
==============================================================================
--- pypy/branch/jitypes2/pypy/module/cpyext/test/test_arraymodule.py	(original)
+++ pypy/branch/jitypes2/pypy/module/cpyext/test/test_arraymodule.py	Fri Dec  3 11:04:29 2010
@@ -14,6 +14,7 @@
         arr.append(4)
         assert arr.tolist() == [1, 2, 3, 4]
         assert len(arr) == 4
+        self.cleanup_references()
 
     def test_iter(self):
         module = self.import_module(name='array')
@@ -22,6 +23,7 @@
         for i in arr: 
             sum += i
         assert sum == 6
+        self.cleanup_references()
 
     def test_index(self):
         module = self.import_module(name='array')
@@ -32,6 +34,7 @@
         assert arr.tolist() == [1,2,4]
         arr[2] = 99
         assert arr.tolist() == [1,2,99]
+        self.cleanup_references()
 
     def test_slice_get(self):
         module = self.import_module(name='array')
@@ -40,3 +43,4 @@
         assert arr[1:].tolist() == [2,3,4]
         assert arr[:2].tolist() == [1,2]
         assert arr[1:3].tolist() == [2,3]
+        self.cleanup_references()

Modified: pypy/branch/jitypes2/pypy/module/cpyext/test/test_cpyext.py
==============================================================================
--- pypy/branch/jitypes2/pypy/module/cpyext/test/test_cpyext.py	(original)
+++ pypy/branch/jitypes2/pypy/module/cpyext/test/test_cpyext.py	Fri Dec  3 11:04:29 2010
@@ -1,10 +1,12 @@
 import sys
+import weakref
 import os.path
 
 import py
 
 from pypy.conftest import gettestobjspace
 from pypy.interpreter.error import OperationError
+from pypy.interpreter.gateway import interp2app
 from pypy.rpython.lltypesystem import rffi, lltype, ll2ctypes
 from pypy.translator.tool.cbuild import ExternalCompilationInfo
 from pypy.translator import platform
@@ -79,6 +81,23 @@
     self.frozen_ll2callocations = set(ll2ctypes.ALLOCATED.values())
 
 class LeakCheckingTest(object):
+    @staticmethod
+    def cleanup_references(space):
+        state = space.fromcache(RefcountState)
+
+        import gc; gc.collect()
+        # Clear all lifelines, objects won't resurrect
+        for w_obj, obj in state.lifeline_dict._dict.items():
+            if w_obj not in state.py_objects_w2r:
+                state.lifeline_dict.set(w_obj, None)
+            del obj
+        import gc; gc.collect()
+
+        for w_obj in state.non_heaptypes_w:
+            Py_DecRef(space, w_obj)
+        state.non_heaptypes_w[:] = []
+        state.reset_borrowed_references()
+
     def check_and_print_leaks(self):
         # check for sane refcnts
         import gc
@@ -89,13 +108,6 @@
         lost_objects_w = identity_dict()
         lost_objects_w.update((key, None) for key in self.frozen_refcounts.keys())
 
-        # Clear all lifelines, objects won't resurrect
-        for w_obj, obj in state.lifeline_dict._dict.items():
-            if w_obj not in state.py_objects_w2r:
-                state.lifeline_dict.set(w_obj, None)
-            del obj
-        gc.collect()
-
         for w_obj, obj in state.py_objects_w2r.iteritems():
             base_refcnt = self.frozen_refcounts.get(w_obj)
             delta = obj.c_ob_refcnt
@@ -105,7 +117,12 @@
             if delta != 0:
                 leaking = True
                 print >>sys.stderr, "Leaking %r: %i references" % (w_obj, delta)
-                lifeline = state.lifeline_dict.get(w_obj)
+                try:
+                    weakref.ref(w_obj)
+                except TypeError:
+                    lifeline = None
+                else:
+                    lifeline = state.lifeline_dict.get(w_obj)
                 if lifeline is not None:
                     refcnt = lifeline.pyo.c_ob_refcnt
                     if refcnt > 0:
@@ -137,6 +154,8 @@
         state = cls.space.fromcache(RefcountState)
         state.non_heaptypes_w[:] = []
 
+        cls.w_cleanup_references = cls.space.wrap(interp2app(cls.cleanup_references))
+
     def compile_module(self, name, **kwds):
         """
         Build an extension module linked against the cpyext api library.
@@ -256,13 +275,7 @@
     def teardown_method(self, func):
         for name in self.imported_module_names:
             self.unimport_module(name)
-        state = self.space.fromcache(RefcountState)
-        for w_obj in state.non_heaptypes_w:
-            Py_DecRef(self.space, w_obj)
-        state.non_heaptypes_w[:] = []
-        state.reset_borrowed_references()
-        from pypy.module.cpyext import cdatetime
-        cdatetime.datetimeAPI_dealloc(self.space)
+        self.cleanup_references(self.space)
         if self.check_and_print_leaks():
             assert False, "Test leaks or loses object(s)."
 
@@ -532,16 +545,17 @@
             PyObject *true = Py_True;
             PyObject *tup = NULL;
             int refcnt = true->ob_refcnt;
-            int refcnt_after;
+            int refcnt_middle, refcnt_after;
 
             tup = PyTuple_New(1);
             Py_INCREF(true);
             if (PyTuple_SetItem(tup, 0, true) < 0)
                 return NULL;
-            refcnt_after = true->ob_refcnt;
+            refcnt_middle = true->ob_refcnt;
             Py_DECREF(tup);
-            fprintf(stderr, "REFCNT2 %i %i\\n", refcnt, refcnt_after);
-            return PyBool_FromLong(refcnt_after == refcnt);
+            refcnt_after = true->ob_refcnt;
+            fprintf(stderr, "REFCNT2 %i %i %i\\n", refcnt, refcnt_middle, refcnt_after);
+            return PyBool_FromLong(refcnt_after == refcnt && refcnt_middle == refcnt+1);
         }
 
         static PyMethodDef methods[] = {

Modified: pypy/branch/jitypes2/pypy/module/cpyext/test/test_datetime.py
==============================================================================
--- pypy/branch/jitypes2/pypy/module/cpyext/test/test_datetime.py	(original)
+++ pypy/branch/jitypes2/pypy/module/cpyext/test/test_datetime.py	Fri Dec  3 11:04:29 2010
@@ -92,9 +92,20 @@
                                      PyDateTimeAPI->TimeType,
                                      PyDateTimeAPI->DeltaType);
              """),
+            ("clear_types", "METH_NOARGS",
+             """
+                 Py_DECREF(PyDateTimeAPI->DateType);
+                 Py_DECREF(PyDateTimeAPI->DateTimeType);
+                 Py_DECREF(PyDateTimeAPI->TimeType);
+                 Py_DECREF(PyDateTimeAPI->DeltaType);
+                 Py_RETURN_NONE;
+             """
+             )
             ])
         import datetime
         assert module.get_types() == (datetime.date,
                                       datetime.datetime,
                                       datetime.time,
                                       datetime.timedelta)
+        module.clear_types()
+        self.cleanup_references()

Modified: pypy/branch/jitypes2/pypy/module/cpyext/test/test_sequence.py
==============================================================================
--- pypy/branch/jitypes2/pypy/module/cpyext/test/test_sequence.py	(original)
+++ pypy/branch/jitypes2/pypy/module/cpyext/test/test_sequence.py	Fri Dec  3 11:04:29 2010
@@ -70,3 +70,11 @@
         assert space.unwrap(space.next(w_iter)) == 2
         exc = raises(OperationError, space.next, w_iter)
         assert exc.value.match(space, space.w_StopIteration)
+
+    def test_contains(self, space, api):
+        w_t = space.wrap((1, 'ha'))
+        assert api.PySequence_Contains(w_t, space.wrap(u'ha'))
+        assert not api.PySequence_Contains(w_t, space.wrap(2))
+        assert api.PySequence_Contains(space.w_None, space.wrap(2)) == -1
+        assert api.PyErr_Occurred()
+        api.PyErr_Clear()

Modified: pypy/branch/jitypes2/pypy/module/cpyext/test/test_tupleobject.py
==============================================================================
--- pypy/branch/jitypes2/pypy/module/cpyext/test/test_tupleobject.py	(original)
+++ pypy/branch/jitypes2/pypy/module/cpyext/test/test_tupleobject.py	Fri Dec  3 11:04:29 2010
@@ -7,24 +7,34 @@
 class TestTupleObject(BaseApiTest):
     def test_tupleobject(self, space, api):
         assert not api.PyTuple_Check(space.w_None)
-        assert api.PyTuple_SetItem(space.w_None, 0, space.w_None) == -1
+        #assert api.PyTuple_SetItem(space.w_None, 0, space.w_None) == -1     XXX
         atuple = space.newtuple([0, 1, 'yay'])
         assert api.PyTuple_Size(atuple) == 3
-        assert api.PyTuple_GET_SIZE(atuple) == 3
-        raises(TypeError, api.PyTuple_Size(space.newlist([])))
+        #raises(TypeError, api.PyTuple_Size(space.newlist([])))     XXX
         api.PyErr_Clear()
     
     def test_tuple_resize(self, space, api):
-        py_tuple = api.PyTuple_New(3)
+        ref_tup = api.PyTuple_New(3)
         ar = lltype.malloc(PyObjectP.TO, 1, flavor='raw')
-        ar[0] = rffi.cast(PyObject, make_ref(space, py_tuple))
+        ar[0] = rffi.cast(PyObject, ref_tup)
         api._PyTuple_Resize(ar, 2)
-        py_tuple = from_ref(space, ar[0])
-        assert len(py_tuple.wrappeditems) == 2
+        assert ar[0] == rffi.cast(PyObject, ref_tup)
+        # ^^^ our _PyTuple_Resize does not actually need to change the ptr so far
+        assert api.PyTuple_Size(ar[0]) == 2
         
         api._PyTuple_Resize(ar, 10)
-        py_tuple = from_ref(space, ar[0])
-        assert len(py_tuple.wrappeditems) == 10
+        assert api.PyTuple_Size(ar[0]) == 10
         
         api.Py_DecRef(ar[0])
         lltype.free(ar, flavor='raw')
+
+    def test_tuple_setup(self, space, api):
+        ref_tup = api.PyTuple_New(2)
+        ref0 = make_ref(space, space.wrap(123))
+        api.PyTuple_SetItem(ref_tup, 0, ref0)
+        ref1 = make_ref(space, space.wrap(456))
+        api.PyTuple_SetItem(ref_tup, 1, ref1)
+
+        w_tup = from_ref(space, ref_tup)
+        assert space.is_true(space.eq(w_tup, space.wrap((123, 456))))
+        api.Py_DecRef(ref_tup)

Modified: pypy/branch/jitypes2/pypy/module/cpyext/test/test_typeobject.py
==============================================================================
--- pypy/branch/jitypes2/pypy/module/cpyext/test/test_typeobject.py	(original)
+++ pypy/branch/jitypes2/pypy/module/cpyext/test/test_typeobject.py	Fri Dec  3 11:04:29 2010
@@ -20,6 +20,7 @@
         assert type(obj) is module.fooType
         print "type of obj has type", type(type(obj))
         print "type of type of obj has type", type(type(type(obj)))
+        self.cleanup_references()
 
     def test_typeobject_method_descriptor(self):
         module = self.import_module(name='foo')
@@ -38,6 +39,7 @@
         print obj.foo
         assert obj.foo == 42
         assert obj.int_member == obj.foo
+        self.cleanup_references()
 
     def test_typeobject_data_member(self):
         module = self.import_module(name='foo')
@@ -54,6 +56,7 @@
         raises(SystemError, "obj.broken_member = 42")
         assert module.fooType.broken_member.__doc__ is None
         assert module.fooType.object_member.__doc__ == "A Python object."
+        self.cleanup_references()
 
     def test_typeobject_object_member(self):
         module = self.import_module(name='foo')
@@ -74,6 +77,7 @@
 
         obj.set_foo = 32
         assert obj.foo == 32
+        self.cleanup_references()
 
     def test_typeobject_string_member(self):
         module = self.import_module(name='foo')
@@ -91,6 +95,7 @@
         assert obj.char_member == "a"
         raises(TypeError, "obj.char_member = 'spam'")
         raises(TypeError, "obj.char_member = 42")
+        self.cleanup_references()
 
     def test_staticmethod(self):
         module = self.import_module(name="foo")
@@ -98,6 +103,7 @@
         assert obj.foo == 42
         obj2 = obj.create()
         assert obj2.foo == 42
+        self.cleanup_references()
 
     def test_new(self):
         module = self.import_module(name='foo')
@@ -118,7 +124,8 @@
                 return self
         assert fuu2(u"abc").baz().escape()
         raises(TypeError, module.fooType.object_member.__get__, 1)
-    
+        self.cleanup_references()
+
     def test_init(self):
         module = self.import_module(name="foo")
         newobj = module.FuuType()
@@ -137,6 +144,7 @@
         newobj = Fuu2()
         assert newobj.get_val() == 42
         assert newobj.foobar == 32
+        self.cleanup_references()
 
     def test_metatype(self):
         module = self.import_module(name='foo')
@@ -145,6 +153,7 @@
         assert isinstance(x, type)
         assert isinstance(x, module.MetaType)
         x()
+        self.cleanup_references()
 
     def test_metaclass_compatible(self):
         # metaclasses should not conflict here
@@ -153,7 +162,9 @@
         assert type(module.fooType).__mro__ == (type, object)
         y = module.MetaType('other', (module.fooType,), {})
         assert isinstance(y, module.MetaType)
-        y()
+        x = y()
+        del x, y
+        self.cleanup_references()
 
     def test_sre(self):
         module = self.import_module(name='_sre')
@@ -172,17 +183,21 @@
         assert "groupdict" in dir(m)
         re._cache.clear()
         re._cache_repl.clear()
+        del prog, m
+        self.cleanup_references()
 
     def test_init_error(self):
         module = self.import_module("foo")
         raises(ValueError, module.InitErrType)
-    
+        self.cleanup_references()
+
     def test_cmps(self):
         module = self.import_module("comparisons")
         cmpr = module.CmpType()
         assert cmpr == 3
         assert cmpr != 42
-    
+        self.cleanup_references()
+
     def test_hash(self):
         module = self.import_module("comparisons")
         cmpr = module.CmpType()
@@ -191,6 +206,7 @@
         d[cmpr] = 72
         assert d[cmpr] == 72
         assert d[3] == 72
+        self.cleanup_references()
 
     def test_descriptor(self):
         module = self.import_module("foo")
@@ -205,6 +221,7 @@
         assert obj.y == (prop, 2)
         del obj.x
         assert obj.z == prop
+        self.cleanup_references()
 
     def test_tp_dict(self):
         foo = self.import_module("foo")
@@ -226,6 +243,7 @@
             ])
         obj = foo.new()
         assert module.read_tp_dict(obj) == foo.fooType.copy
+        self.cleanup_references()
 
 
 class TestTypes(BaseApiTest):

Modified: pypy/branch/jitypes2/pypy/module/cpyext/tupleobject.py
==============================================================================
--- pypy/branch/jitypes2/pypy/module/cpyext/tupleobject.py	(original)
+++ pypy/branch/jitypes2/pypy/module/cpyext/tupleobject.py	Fri Dec  3 11:04:29 2010
@@ -1,55 +1,144 @@
 from pypy.interpreter.error import OperationError
 from pypy.rpython.lltypesystem import rffi, lltype
 from pypy.module.cpyext.api import (cpython_api, Py_ssize_t, CANNOT_FAIL,
-                                    build_type_checkers)
+                                    build_type_checkers, PyObjectFields,
+                                    cpython_struct, bootstrap_function)
 from pypy.module.cpyext.pyobject import (PyObject, PyObjectP, Py_DecRef,
-    borrow_from, make_ref, from_ref)
+    borrow_from, make_ref, from_ref, make_typedescr, get_typedescr, Reference,
+    track_reference)
 from pypy.module.cpyext.pyerrors import PyErr_BadInternalCall
-from pypy.objspace.std.tupleobject import W_TupleObject
 
+##
+## Implementation of PyTupleObject
+## ===============================
+##
+## We have the same problem as PyStringObject: a PyTupleObject can be
+## initially used in a read-write way with PyTuple_New(), PyTuple_SetItem()
+## and _PyTuple_Resize().
+##
+## The 'size' and 'items' fields of a PyTupleObject are always valid.
+## Apart from that detail, see the big comment in stringobject.py for
+## more information.
+##
+
+ARRAY_OF_PYOBJ = rffi.CArrayPtr(PyObject)
+PyTupleObjectStruct = lltype.ForwardReference()
+PyTupleObject = lltype.Ptr(PyTupleObjectStruct)
+PyTupleObjectFields = PyObjectFields + \
+    (("items", ARRAY_OF_PYOBJ), ("size", Py_ssize_t))
+cpython_struct("PyTupleObject", PyTupleObjectFields, PyTupleObjectStruct)
+
+ at bootstrap_function
+def init_tupleobject(space):
+    "Type description of PyTupleObject"
+    make_typedescr(space.w_tuple.instancetypedef,
+                   basestruct=PyTupleObject.TO,
+                   attach=tuple_attach,
+                   dealloc=tuple_dealloc,
+                   realize=tuple_realize)
 
 PyTuple_Check, PyTuple_CheckExact = build_type_checkers("Tuple")
 
+def new_empty_tuple(space, length):
+    """
+    Allocate a PyTupleObject and its array, but without a corresponding
+    interpreter object.  The array items may be mutated, until
+    tuple_realize() is called.
+    """
+    typedescr = get_typedescr(space.w_tuple.instancetypedef)
+    py_obj = typedescr.allocate(space, space.w_tuple)
+    py_tup = rffi.cast(PyTupleObject, py_obj)
+
+    py_tup.c_items = lltype.malloc(ARRAY_OF_PYOBJ.TO, length,
+                                   flavor='raw', zero=True)
+    py_tup.c_size = length
+    return py_tup
+
+def tuple_attach(space, py_obj, w_obj):
+    """
+    Fills a newly allocated PyTupleObject with the given tuple object.
+    """
+    items_w = space.fixedview(w_obj)
+    py_tup = rffi.cast(PyTupleObject, py_obj)
+    py_tup.c_items = lltype.nullptr(ARRAY_OF_PYOBJ.TO)
+    py_tup.c_size = len(items_w)
+
+def tuple_realize(space, py_obj):
+    """
+    Creates the tuple in the interpreter. The PyTupleObject items array
+    must not be modified after this call.
+    """
+    py_tup = rffi.cast(PyTupleObject, py_obj)
+    # If your CPython extension creates a self-referential tuple
+    # with PyTuple_SetItem(), you loose.
+    c_items = py_tup.c_items
+    items_w = [from_ref(space, c_items[i]) for i in range(py_tup.c_size)]
+    w_obj = space.newtuple(items_w)
+    track_reference(space, py_obj, w_obj)
+    return w_obj
+
+ at cpython_api([PyObject], lltype.Void, external=False)
+def tuple_dealloc(space, py_obj):
+    """Frees allocated PyTupleObject resources.
+    """
+    py_tup = rffi.cast(PyTupleObject, py_obj)
+    if py_tup.c_items:
+        for i in range(py_tup.c_size):
+            Py_DecRef(space, py_tup.c_items[i])
+        lltype.free(py_tup.c_items, flavor="raw")
+    from pypy.module.cpyext.object import PyObject_dealloc
+    PyObject_dealloc(space, py_obj)
+
+#_______________________________________________________________________
+
 @cpython_api([Py_ssize_t], PyObject)
 def PyTuple_New(space, size):
-    return space.newtuple([space.w_None] * size)
+    return rffi.cast(PyObject, new_empty_tuple(space, size))
 
 @cpython_api([PyObject, Py_ssize_t, PyObject], rffi.INT_real, error=-1)
-def PyTuple_SetItem(space, w_t, pos, w_obj):
-    if not PyTuple_Check(space, w_t):
-        # XXX this should also steal a reference, test it!!!
-        PyErr_BadInternalCall(space)
-    assert isinstance(w_t, W_TupleObject)
-    w_t.wrappeditems[pos] = w_obj
-    Py_DecRef(space, w_obj) # SetItem steals a reference!
+def PyTuple_SetItem(space, ref, pos, ref_item):
+    # XXX steals a reference at the level of PyObjects.  Don't try to
+    # XXX call this function with an interpreter object as ref_item!
+
+    # XXX do PyTuple_Check, without forcing ref as an interpreter object
+    # XXX -- then if it fails it should also steal a reference, test it!!!
+    ref_tup = rffi.cast(PyTupleObject, ref)
+    if not ref_tup.c_items:
+        msg = "PyTuple_SetItem() called on an already-escaped tuple object"
+        raise OperationError(space.w_SystemError, space.wrap(msg))
+    ref_old = ref_tup.c_items[pos]
+    ref_tup.c_items[pos] = ref_item      # SetItem steals a reference!
+    Py_DecRef(space, ref_old)
     return 0
 
 @cpython_api([PyObject, Py_ssize_t], PyObject)
-def PyTuple_GetItem(space, w_t, pos):
-    if not PyTuple_Check(space, w_t):
-        PyErr_BadInternalCall(space)
-    assert isinstance(w_t, W_TupleObject)
-    w_obj = w_t.wrappeditems[pos]
-    return borrow_from(w_t, w_obj)
-
- at cpython_api([PyObject], Py_ssize_t, error=CANNOT_FAIL)
-def PyTuple_GET_SIZE(space, w_t):
-    """Return the size of the tuple p, which must be non-NULL and point to a tuple;
-    no error checking is performed. """
-    assert isinstance(w_t, W_TupleObject)
-    return len(w_t.wrappeditems)
+def PyTuple_GetItem(space, ref, pos):
+    # XXX do PyTuple_Check, without forcing ref as an interpreter object
+    ref_tup = rffi.cast(PyTupleObject, ref)
+    if ref_tup.c_items:
+        return Reference(ref_tup.c_items[pos])     # borrowed reference
+    else:
+        w_t = from_ref(space, ref)
+        w_obj = space.getitem(w_t, space.wrap(pos))
+        return borrow_from(w_t, w_obj)
+
+ at cpython_api([PyObject], Py_ssize_t, error=-1)
+def _PyTuple_Size_Fast(space, ref):
+    # custom version: it's not a macro, so it can be called from other .py
+    # files; but it doesn't include PyTuple_Check()
+    ref_tup = rffi.cast(PyTupleObject, ref)
+    return ref_tup.c_size
 
 @cpython_api([PyObject], Py_ssize_t, error=-1)
 def PyTuple_Size(space, ref):
     """Take a pointer to a tuple object, and return the size of that tuple."""
-    if not PyTuple_Check(space, ref):
-        raise OperationError(space.w_TypeError,
-                             space.wrap("expected tuple object"))
-    return PyTuple_GET_SIZE(space, ref)
+    # XXX do PyTuple_Check, without forcing ref as an interpreter object
+    ref_tup = rffi.cast(PyTupleObject, ref)
+    return ref_tup.c_size
 
 
 @cpython_api([PyObjectP, Py_ssize_t], rffi.INT_real, error=-1)
-def _PyTuple_Resize(space, ref, newsize):
+def _PyTuple_Resize(space, refp, newsize):
     """Can be used to resize a tuple.  newsize will be the new length of the tuple.
     Because tuples are supposed to be immutable, this should only be used if there
     is only one reference to the object.  Do not use this if the tuple may already
@@ -60,18 +149,22 @@
     this function. If the object referenced by *p is replaced, the original
     *p is destroyed.  On failure, returns -1 and sets *p to NULL, and
     raises MemoryError or SystemError."""
-    py_tuple = from_ref(space, ref[0])
-    if not PyTuple_Check(space, py_tuple):
-        PyErr_BadInternalCall(space)
-    assert isinstance(py_tuple, W_TupleObject)
-    py_newtuple = PyTuple_New(space, newsize)
-    
-    to_cp = newsize
-    oldsize = len(py_tuple.wrappeditems)
-    if oldsize < newsize:
-        to_cp = oldsize
-    for i in range(to_cp):
-        py_newtuple.wrappeditems[i] = py_tuple.wrappeditems[i]
-    Py_DecRef(space, ref[0])
-    ref[0] = make_ref(space, py_newtuple)
+    # XXX do PyTuple_Check, without forcing ref as an interpreter object
+    # XXX -- then if it fails it should reset refp[0] to null
+    ref_tup = rffi.cast(PyTupleObject, refp[0])
+    c_newitems = lltype.malloc(ARRAY_OF_PYOBJ.TO, newsize,
+                               flavor='raw', zero=True)
+    c_olditems = ref_tup.c_items
+    if not c_olditems:
+        msg = "_PyTuple_Resize() called on an already-escaped tuple object"
+        raise OperationError(space.w_SystemError, space.wrap(msg))
+    oldsize = ref_tup.c_size
+    for i in range(min(oldsize, newsize)):
+        c_newitems[i] = c_olditems[i]
+    # decref items deleted by shrinkage
+    for i in range(newsize, oldsize):
+        Py_DecRef(space, c_olditems[i])
+    ref_tup.c_items = c_newitems
+    ref_tup.c_size = newsize
+    lltype.free(c_olditems, flavor='raw')
     return 0

Modified: pypy/branch/jitypes2/pypy/module/cpyext/typeobject.py
==============================================================================
--- pypy/branch/jitypes2/pypy/module/cpyext/typeobject.py	(original)
+++ pypy/branch/jitypes2/pypy/module/cpyext/typeobject.py	Fri Dec  3 11:04:29 2010
@@ -24,7 +24,7 @@
 from pypy.module.cpyext.structmember import PyMember_GetOne, PyMember_SetOne
 from pypy.module.cpyext.typeobjectdefs import (
     PyTypeObjectPtr, PyTypeObject, PyGetSetDef, PyMemberDef, newfunc,
-    PyNumberMethods)
+    PyNumberMethods, PySequenceMethods)
 from pypy.module.cpyext.slotdefs import (
     slotdefs_for_tp_slots, slotdefs_for_wrappers, get_slot_tp_function)
 from pypy.interpreter.error import OperationError
@@ -136,6 +136,8 @@
             if not struct:
                 if slot_names[0] == 'c_tp_as_number':
                     STRUCT_TYPE = PyNumberMethods
+                elif slot_names[0] == 'c_tp_as_sequence':
+                    STRUCT_TYPE = PySequenceMethods
                 else:
                     raise AssertionError(
                         "Structure not allocated: %s" % (slot_names[0],))
@@ -392,6 +394,8 @@
             lltype.free(obj_pto.c_tp_as_buffer, flavor='raw')
         if obj_pto.c_tp_as_number:
             lltype.free(obj_pto.c_tp_as_number, flavor='raw')
+        if obj_pto.c_tp_as_sequence:
+            lltype.free(obj_pto.c_tp_as_sequence, flavor='raw')
         Py_DecRef(space, base_pyo)
         rffi.free_charp(obj_pto.c_tp_name)
         PyObject_dealloc(space, obj)
@@ -433,12 +437,6 @@
     finish_type_1(space, pto)
     finish_type_2(space, pto, w_type)
 
-    if space.type(w_type).is_cpytype():
-        # XXX Types with a C metatype are never freed, try to see why...
-        render_immortal(pto, w_type)
-        lltype.render_immortal(pto)
-        lltype.render_immortal(pto.c_tp_name)
-
     pto.c_tp_basicsize = rffi.sizeof(typedescr.basestruct)
     if pto.c_tp_base:
         if pto.c_tp_base.c_tp_basicsize > pto.c_tp_basicsize:
@@ -544,25 +542,12 @@
     w_obj.ready()
 
     finish_type_2(space, py_type, w_obj)
-    render_immortal(py_type, w_obj)
 
     state = space.fromcache(RefcountState)
     state.non_heaptypes_w.append(w_obj)
 
     return w_obj
 
-def render_immortal(py_type, w_obj):
-    lltype.render_immortal(py_type.c_tp_bases)
-    lltype.render_immortal(py_type.c_tp_mro)
-
-    assert isinstance(w_obj, W_TypeObject)
-    if w_obj.is_cpytype():
-        lltype.render_immortal(py_type.c_tp_dict)
-    else:
-        lltype.render_immortal(py_type.c_tp_name)
-    if not w_obj.is_cpytype() and w_obj.is_heaptype():
-        lltype.render_immortal(py_type)
-
 def finish_type_1(space, pto):
     """
     Sets up tp_bases, necessary before creating the interpreter type.
@@ -599,7 +584,8 @@
 
     if w_obj.is_cpytype():
         Py_DecRef(space, pto.c_tp_dict)
-        pto.c_tp_dict = make_ref(space, w_obj.getdict())
+        w_dict = space.newdict(from_strdict_shared=w_obj.dict_w)
+        pto.c_tp_dict = make_ref(space, w_dict)
 
 @cpython_api([PyTypeObjectPtr, PyTypeObjectPtr], rffi.INT_real, error=CANNOT_FAIL)
 def PyType_IsSubtype(space, a, b):

Modified: pypy/branch/jitypes2/pypy/module/fcntl/test/test_fcntl.py
==============================================================================
--- pypy/branch/jitypes2/pypy/module/fcntl/test/test_fcntl.py	(original)
+++ pypy/branch/jitypes2/pypy/module/fcntl/test/test_fcntl.py	Fri Dec  3 11:04:29 2010
@@ -63,7 +63,7 @@
         if sys.platform in ('netbsd1', 'netbsd2', 'netbsd3', 
                             'Darwin1.2', 'darwin',
                             'freebsd2', 'freebsd3', 'freebsd4', 'freebsd5',
-                            'freebsd6', 'freebsd7', 
+                            'freebsd6', 'freebsd7', 'freebsd8', 'freebsd9',
                             'bsdos2', 'bsdos3', 'bsdos4',
                             'openbsd', 'openbsd2', 'openbsd3'):
             if struct.calcsize('l') == 8:
@@ -159,7 +159,7 @@
 
         if "linux" in sys.platform:
             TIOCGPGRP = 0x540f
-        elif "darwin" in sys.platform or "freebsd6" == sys.platform:
+        elif "darwin" in sys.platform or "freebsd" in sys.platform:
             TIOCGPGRP = 0x40047477
         else:
             skip("don't know how to test ioctl() on this platform")

Modified: pypy/branch/jitypes2/pypy/module/imp/importing.py
==============================================================================
--- pypy/branch/jitypes2/pypy/module/imp/importing.py	(original)
+++ pypy/branch/jitypes2/pypy/module/imp/importing.py	Fri Dec  3 11:04:29 2010
@@ -76,7 +76,7 @@
 
     return SEARCH_ERROR, None, None
 
-if sys.platform in ['linux2', 'freebsd']:
+if sys.platform == 'linux2' or 'freebsd' in sys.platform:
     def case_ok(filename):
         return True
 else:

Modified: pypy/branch/jitypes2/pypy/module/itertools/interp_itertools.py
==============================================================================
--- pypy/branch/jitypes2/pypy/module/itertools/interp_itertools.py	(original)
+++ pypy/branch/jitypes2/pypy/module/itertools/interp_itertools.py	Fri Dec  3 11:04:29 2010
@@ -391,7 +391,8 @@
         self.iterators_w = iterators_w
         self.current_iterator = 0
         self.num_iterators = len(iterators_w)
-        self.started = False
+        if self.num_iterators > 0:
+            self.w_it = iterators_w[0]
 
     def iter_w(self):
         return self.space.wrap(self)
@@ -399,26 +400,23 @@
     def next_w(self):
         if self.current_iterator >= self.num_iterators:
             raise OperationError(self.space.w_StopIteration, self.space.w_None)
-        if not self.started:
-            self.current_iterator = 0
-            self.w_it = self.iterators_w[self.current_iterator]
-            self.started = True
+        try:
+            return self.space.next(self.w_it)
+        except OperationError, e:
+            return self._handle_error(e)
 
+    def _handle_error(self, e):
         while True:
+            if not e.match(self.space, self.space.w_StopIteration):
+                raise e
+            self.current_iterator += 1
+            if self.current_iterator >= self.num_iterators:
+                raise e
+            self.w_it = self.iterators_w[self.current_iterator]
             try:
-                w_obj = self.space.next(self.w_it)
+                return self.space.next(self.w_it)
             except OperationError, e:
-                if e.match(self.space, self.space.w_StopIteration):
-                    self.current_iterator += 1
-                    if self.current_iterator >= self.num_iterators:
-                        raise OperationError(self.space.w_StopIteration, self.space.w_None)
-                    else:
-                        self.w_it = self.iterators_w[self.current_iterator]
-                else:
-                    raise
-            else:
-                break
-        return w_obj
+                pass   # loop back to the start of _handle_error(e)
 
 def W_Chain___new__(space, w_subtype, args_w):
     return space.wrap(W_Chain(space, args_w))
@@ -446,8 +444,10 @@
 
     def __init__(self, space, w_fun, args_w):
         self.space = space
-        self.identity_fun = (self.space.is_w(w_fun, space.w_None))
-        self.w_fun = w_fun
+        if self.space.is_w(w_fun, space.w_None):
+            self.w_fun = None
+        else:
+            self.w_fun = w_fun
 
         iterators_w = []
         i = 0
@@ -470,12 +470,26 @@
         return self.space.wrap(self)
 
     def next_w(self):
-        w_objects = self.space.newtuple([self.space.next(w_it) for w_it in self.iterators_w])
-        if self.identity_fun:
+        # common case: 1 or 2 arguments
+        iterators_w = self.iterators_w
+        length = len(iterators_w)
+        if length == 1:
+            objects = [self.space.next(iterators_w[0])]
+        elif length == 2:
+            objects = [self.space.next(iterators_w[0]),
+                       self.space.next(iterators_w[1])]
+        else:
+            objects = self._get_objects()
+        w_objects = self.space.newtuple(objects)
+        if self.w_fun is None:
             return w_objects
         else:
             return self.space.call(self.w_fun, w_objects)
 
+    def _get_objects(self):
+        # the loop is out of the way of the JIT
+        return [self.space.next(w_elem) for w_elem in self.iterators_w]
+
 
 def W_IMap___new__(space, w_subtype, w_fun, args_w):
     if len(args_w) == 0:
@@ -769,15 +783,7 @@
             raise OperationError(self.space.w_StopIteration, self.space.w_None)
 
         if not self.new_group:
-            # Consume unwanted input until we reach the next group
-            try:
-                while True:
-                    self.group_next(self.index)
-
-            except StopIteration:
-                pass
-            if self.exhausted:
-                raise OperationError(self.space.w_StopIteration, self.space.w_None)
+            self._consume_unwanted_input()
 
         if not self.started:
             self.started = True
@@ -799,6 +805,16 @@
         w_iterator = self.space.wrap(W_GroupByIterator(self.space, self.index, self))
         return self.space.newtuple([self.w_key, w_iterator])
 
+    def _consume_unwanted_input(self):
+        # Consume unwanted input until we reach the next group
+        try:
+            while True:
+                self.group_next(self.index)
+        except StopIteration:
+            pass
+        if self.exhausted:
+            raise OperationError(self.space.w_StopIteration, self.space.w_None)
+
     def group_next(self, group_index):
         if group_index < self.index:
             raise StopIteration

Modified: pypy/branch/jitypes2/pypy/module/posix/__init__.py
==============================================================================
--- pypy/branch/jitypes2/pypy/module/posix/__init__.py	(original)
+++ pypy/branch/jitypes2/pypy/module/posix/__init__.py	Fri Dec  3 11:04:29 2010
@@ -96,6 +96,8 @@
         interpleveldefs['fork'] = 'interp_posix.fork'
     if hasattr(os, 'openpty'):
         interpleveldefs['openpty'] = 'interp_posix.openpty'
+    if hasattr(os, 'forkpty'):
+        interpleveldefs['forkpty'] = 'interp_posix.forkpty'
     if hasattr(os, 'waitpid'):
         interpleveldefs['waitpid'] = 'interp_posix.waitpid'
     if hasattr(os, 'execv'):

Modified: pypy/branch/jitypes2/pypy/module/posix/interp_posix.py
==============================================================================
--- pypy/branch/jitypes2/pypy/module/posix/interp_posix.py	(original)
+++ pypy/branch/jitypes2/pypy/module/posix/interp_posix.py	Fri Dec  3 11:04:29 2010
@@ -608,6 +608,14 @@
         raise wrap_oserror(space, e)
     return space.newtuple([space.wrap(master_fd), space.wrap(slave_fd)])
 
+def forkpty(space):
+    try:
+        pid, master_fd = os.forkpty()
+    except OSError, e:
+        raise wrap_oserror(space, e)
+    return space.newtuple([space.wrap(pid),
+                           space.wrap(master_fd)])
+
 def waitpid(space, pid, options):
     """ waitpid(pid, options) -> (pid, status)
     

Modified: pypy/branch/jitypes2/pypy/module/posix/test/test_posix2.py
==============================================================================
--- pypy/branch/jitypes2/pypy/module/posix/test/test_posix2.py	(original)
+++ pypy/branch/jitypes2/pypy/module/posix/test/test_posix2.py	Fri Dec  3 11:04:29 2010
@@ -331,6 +331,22 @@
             data = os.read(master_fd, 100)
             assert data.startswith('x')
 
+    if hasattr(__import__(os.name), "forkpty"):
+        def test_forkpty(self):
+            import sys
+            os = self.posix
+            childpid, master_fd = os.forkpty()
+            assert isinstance(childpid, int)
+            assert isinstance(master_fd, int)
+            if childpid == 0:
+                data = os.read(0, 100)
+                if data.startswith('abc'):
+                    os._exit(42)
+                else:
+                    os._exit(43)
+            os.write(master_fd, 'abc\n')
+            _, status = os.waitpid(childpid, 0)
+            assert status >> 8 == 42
 
     if hasattr(__import__(os.name), "execv"):
         def test_execv(self):

Modified: pypy/branch/jitypes2/pypy/module/pyexpat/interp_pyexpat.py
==============================================================================
--- pypy/branch/jitypes2/pypy/module/pyexpat/interp_pyexpat.py	(original)
+++ pypy/branch/jitypes2/pypy/module/pyexpat/interp_pyexpat.py	Fri Dec  3 11:04:29 2010
@@ -329,7 +329,7 @@
         if self.returns_unicode:
             return space.call_function(
                 space.getattr(space.wrap(s), space.wrap("decode")),
-                space.wrap(self.encoding),
+                space.wrap("utf-8"),
                 space.wrap("strict"))
         else:
             return space.wrap(s)

Modified: pypy/branch/jitypes2/pypy/module/pyexpat/test/test_parser.py
==============================================================================
--- pypy/branch/jitypes2/pypy/module/pyexpat/test/test_parser.py	(original)
+++ pypy/branch/jitypes2/pypy/module/pyexpat/test/test_parser.py	Fri Dec  3 11:04:29 2010
@@ -15,3 +15,17 @@
         assert res == 1
 
         raises(pyexpat.ExpatError, p.Parse, "3")
+
+    def test_encoding(self):
+        import pyexpat
+        for encoding_arg in (None, 'utf-8', 'iso-8859-1'):
+            for namespace_arg in (None, '{'):
+                print encoding_arg, namespace_arg
+                p = pyexpat.ParserCreate(encoding_arg, namespace_arg)
+                data = []
+                p.CharacterDataHandler = lambda s: data.append(s)
+                encoding = encoding_arg is None and 'utf-8' or encoding_arg
+
+                res = p.Parse(u"<xml>\u00f6</xml>".encode(encoding), isfinal=True)
+                assert res == 1
+                assert data == [u"\u00f6"]

Modified: pypy/branch/jitypes2/pypy/module/pypyjit/policy.py
==============================================================================
--- pypy/branch/jitypes2/pypy/module/pypyjit/policy.py	(original)
+++ pypy/branch/jitypes2/pypy/module/pypyjit/policy.py	Fri Dec  3 11:04:29 2010
@@ -12,19 +12,13 @@
         if '.' in modname:
             modname, _ = modname.split('.', 1)
         if modname in ['pypyjit', 'signal', 'micronumpy', 'math', 'exceptions',
-                       'imp', 'sys', 'array', '_ffi']:
+                       'imp', 'sys', 'array', '_ffi', 'itertools', 'operator']:
             return True
         return False
 
     def look_inside_function(self, func):
-        # this function should never actually return True directly
-        # but instead call the base implementation
         mod = func.__module__ or '?'
 
-        if mod.startswith('pypy.objspace.'):
-            # gc_id operation
-            if func.__name__ == 'id__ANY':
-                return False
         if mod == 'pypy.rlib.rbigint' or mod == 'pypy.rlib.rlocale':
             return False
         if '_geninterp_' in func.func_globals: # skip all geninterped stuff

Modified: pypy/branch/jitypes2/pypy/module/pypyjit/test/test_policy.py
==============================================================================
--- pypy/branch/jitypes2/pypy/module/pypyjit/test/test_policy.py	(original)
+++ pypy/branch/jitypes2/pypy/module/pypyjit/test/test_policy.py	Fri Dec  3 11:04:29 2010
@@ -4,7 +4,7 @@
 
 def test_id_any():
     from pypy.objspace.std.default import id__ANY
-    assert not pypypolicy.look_inside_function(id__ANY)
+    assert pypypolicy.look_inside_function(id__ANY)
 
 def test_bigint():
     from pypy.rlib.rbigint import rbigint

Modified: pypy/branch/jitypes2/pypy/module/pypyjit/test/test_pypy_c.py
==============================================================================
--- pypy/branch/jitypes2/pypy/module/pypyjit/test/test_pypy_c.py	(original)
+++ pypy/branch/jitypes2/pypy/module/pypyjit/test/test_pypy_c.py	Fri Dec  3 11:04:29 2010
@@ -654,6 +654,32 @@
         ''', 3000, ([0], 2000*3))
         assert len(self.loops) == 1
 
+    def test_getattr_with_dynamic_attribute(self):
+        self.run_source('''
+        class A(object):
+            pass
+
+        l = ["x", "y"]
+
+        def main(arg):
+            sum = 0
+            a = A()
+            a.a1 = 0
+            a.a2 = 0
+            a.a3 = 0
+            a.a4 = 0
+            a.a5 = 0 # workaround, because the first five attributes need a promotion
+            a.x = 1
+            a.y = 2
+            i = 0
+            while i < 2000:
+                name = l[i % 2]
+                sum += getattr(a, name)
+                i += 1
+            return sum
+        ''', 3000, ([0], 3000))
+        assert len(self.loops) == 1
+
     def test_blockstack_virtualizable(self):
         self.run_source('''
         from pypyjit import residual_call
@@ -697,11 +723,9 @@
                 i = t2[3]
                 del t2
             return i
-        ''', 100, ([], 100))
+        ''', 40, ([], 100))
         bytecode, = self.get_by_bytecode('BINARY_SUBSCR')
-        assert len(bytecode.get_opnames('new_array')) == 1
-        # XXX I would like here to say that it's 0, but unfortunately
-        #     call that can raise is not exchanged into getarrayitem_gc
+        assert len(bytecode.get_opnames('new_array')) == 0
 
     def test_overflow_checking(self):
         startvalue = sys.maxint - 2147483647

Modified: pypy/branch/jitypes2/pypy/module/sys/__init__.py
==============================================================================
--- pypy/branch/jitypes2/pypy/module/sys/__init__.py	(original)
+++ pypy/branch/jitypes2/pypy/module/sys/__init__.py	Fri Dec  3 11:04:29 2010
@@ -60,8 +60,6 @@
         'pypy_svn_url'          : 'version.get_svn_url(space)',
         'subversion'            : 'version.get_subversion_info(space)',
         'hexversion'            : 'version.get_hexversion(space)',
-        'ps1'                   : 'space.wrap(">>>> ")', 
-        'ps2'                   : 'space.wrap(".... ")', 
 
         'displayhook'           : 'hook.displayhook', 
         '__displayhook__'       : 'hook.__displayhook__', 

Modified: pypy/branch/jitypes2/pypy/module/test_lib_pypy/ctypes_tests/test_guess_argtypes.py
==============================================================================
--- pypy/branch/jitypes2/pypy/module/test_lib_pypy/ctypes_tests/test_guess_argtypes.py	(original)
+++ pypy/branch/jitypes2/pypy/module/test_lib_pypy/ctypes_tests/test_guess_argtypes.py	Fri Dec  3 11:04:29 2010
@@ -11,21 +11,23 @@
         py.test.skip("pypy white-box test")
     from _ctypes.function import CFuncPtr
 
-    guess = CFuncPtr._guess_argtypes
+    def guess(value):
+        cobj = CFuncPtr._conv_param(None, value, 0)
+        return type(cobj)
 
-    assert guess([13]) == [c_int]
-    assert guess([0]) == [c_int]
-    assert guess(['xca']) == [c_char_p]
-    assert guess([None]) == [c_void_p]
-    assert guess([c_int(3)]) == [c_int]
-    assert guess([u'xca']) == [c_wchar_p]
+    assert guess(13) == c_int
+    assert guess(0) == c_int
+    assert guess('xca') == c_char_p
+    assert guess(None) == c_void_p
+    assert guess(c_int(3)) == c_int
+    assert guess(u'xca') == c_wchar_p
 
     class Stuff:
         pass
     s = Stuff()
     s._as_parameter_ = None
     
-    assert guess([s]) == [c_void_p]
+    assert guess(s) == c_void_p
 
 def test_guess_unicode():
     if not hasattr(sys, 'pypy_translation_info') and sys.platform != 'win32':

Modified: pypy/branch/jitypes2/pypy/module/test_lib_pypy/ctypes_tests/test_keepalive.py
==============================================================================
--- pypy/branch/jitypes2/pypy/module/test_lib_pypy/ctypes_tests/test_keepalive.py	(original)
+++ pypy/branch/jitypes2/pypy/module/test_lib_pypy/ctypes_tests/test_keepalive.py	Fri Dec  3 11:04:29 2010
@@ -99,7 +99,7 @@
     def test_primitive(self):
         if not hasattr(sys, 'pypy_translation_info'):
             py.test.skip("pypy white-box test")
-        assert c_char_p("abc")._objects['0']._buffer[0] == "a"
+        assert c_char_p("abc")._objects._buffer[0] == "a"
         assert c_int(3)._objects is None
 
     def test_pointer_to_pointer(self):
@@ -123,7 +123,7 @@
             pass
         cf = CFUNCTYPE(c_int, c_int)(f)
         p1 = cast(cf, c_void_p)
-        assert p1._objects == {'1': cf, '0': {'0': cf}}
+        assert p1._objects == {id(cf): cf, '0': cf}
 
     def test_array_of_struct_with_pointer(self):
         class S(Structure):
@@ -221,7 +221,7 @@
         import gc; gc.collect()
         print 'x =', repr(x)
         assert x.value == 'hellohello'
-        assert x._objects.keys() == ['0']
+        assert x._objects == 'hellohello'
         #
         class datum(Structure):
             _fields_ = [

Modified: pypy/branch/jitypes2/pypy/objspace/std/mapdict.py
==============================================================================
--- pypy/branch/jitypes2/pypy/objspace/std/mapdict.py	(original)
+++ pypy/branch/jitypes2/pypy/objspace/std/mapdict.py	Fri Dec  3 11:04:29 2010
@@ -42,11 +42,23 @@
         return None
 
     def index(self, selector):
-        if (self.space.config.objspace.std.withmethodcache and 
-                not jit.we_are_jitted()):
-            return self._index_cache(selector)
+        if jit.we_are_jitted():
+            # hack for the jit:
+            # the _index method is pure too, but its argument is never
+            # constant, because it is always a new tuple
+            return self._index_jit_pure(selector[0], selector[1])
         else:
-            return self._index(selector)
+            return self._index_indirection(selector)
+
+    @jit.purefunction
+    def _index_jit_pure(self, name, index):
+        return self._index_indirection((name, index))
+
+    @jit.dont_look_inside
+    def _index_indirection(self, selector):
+        if (self.space.config.objspace.std.withmethodcache):
+            return self._index_cache(selector)
+        return self._index(selector)
 
     @jit.dont_look_inside
     def _index_cache(self, selector):
@@ -498,10 +510,11 @@
 
         def _mapdict_read_storage(self, index):
             assert index >= 0
-            for i in rangenmin1:
-                if index == i:
-                    erased = getattr(self, "_value%s" % i)
-                    return rerased.unerase(erased, W_Root)
+            if index < nmin1:
+                for i in rangenmin1:
+                    if index == i:
+                        erased = getattr(self, "_value%s" % i)
+                        return rerased.unerase(erased, W_Root)
             if self._has_storage_list():
                 return self._mapdict_get_storage_list()[index - nmin1]
             erased = getattr(self, "_value%s" % nmin1)

Modified: pypy/branch/jitypes2/pypy/objspace/std/objspace.py
==============================================================================
--- pypy/branch/jitypes2/pypy/objspace/std/objspace.py	(original)
+++ pypy/branch/jitypes2/pypy/objspace/std/objspace.py	Fri Dec  3 11:04:29 2010
@@ -9,7 +9,7 @@
 from pypy.objspace.descroperation import DescrOperation, raiseattrerror
 from pypy.rlib.objectmodel import instantiate, r_dict, specialize
 from pypy.rlib.debug import make_sure_not_resized
-from pypy.rlib.rarithmetic import base_int
+from pypy.rlib.rarithmetic import base_int, widen
 from pypy.rlib.objectmodel import we_are_translated
 from pypy.rlib.jit import hint
 from pypy.tool.sourcetools import func_with_new_name
@@ -176,7 +176,11 @@
             #print 'wrapping', x, '->', w_result
             return w_result
         if isinstance(x, base_int):
-            return W_LongObject.fromrarith_int(x)
+            x = widen(x)
+            if isinstance(x, int):
+                return self.newint(x)
+            else:
+                return W_LongObject.fromrarith_int(x)
 
         # _____ below here is where the annotator should not get _____
 
@@ -372,7 +376,7 @@
                     self, w_obj, expected_length)[:])
         if expected_length != -1 and len(t) != expected_length:
             raise self._wrap_expected_length(expected_length, len(t))
-        return t
+        return make_sure_not_resized(t)
 
     def fixedview_unroll(self, w_obj, expected_length=-1):
         return self.fixedview(w_obj, expected_length, unroll=True)

Modified: pypy/branch/jitypes2/pypy/rlib/debug.py
==============================================================================
--- pypy/branch/jitypes2/pypy/rlib/debug.py	(original)
+++ pypy/branch/jitypes2/pypy/rlib/debug.py	Fri Dec  3 11:04:29 2010
@@ -53,13 +53,11 @@
 
 _log = None       # patched from tests to be an object of class DebugLog
                   # or compatible
-_stderr = sys.stderr   # alternatively, this is patched from tests
-                       # (redirects debug_print(), but not debug_start/stop)
 
 def debug_print(*args):
     for arg in args:
-        print >> _stderr, arg,
-    print >> _stderr
+        print >> sys.stderr, arg,
+    print >> sys.stderr
     if _log is not None:
         _log.debug_print(*args)
 
@@ -87,13 +85,15 @@
     _stop_colors = ""
 
 def debug_start(category):
-    print >> sys.stderr, '%s[%s] {%s%s' % (_start_colors_1, time.clock(),
+    c = int(time.clock() * 100)
+    print >> sys.stderr, '%s[%x] {%s%s' % (_start_colors_1, c,
                                            category, _stop_colors)
     if _log is not None:
         _log.debug_start(category)
 
 def debug_stop(category):
-    print >> sys.stderr, '%s[%s] %s}%s' % (_start_colors_2, time.clock(),
+    c = int(time.clock() * 100)
+    print >> sys.stderr, '%s[%x] %s}%s' % (_start_colors_2, c,
                                            category, _stop_colors)
     if _log is not None:
         _log.debug_stop(category)
@@ -226,31 +226,6 @@
         hop.exception_cannot_occur()
         return hop.inputarg(hop.args_r[0], arg=0)
 
-def make_sure_not_modified(arg):
-    """ Function checking whether annotation of SomeList is never resized
-    and never modified, useful for debugging. Does nothing when run directly
-    """
-    return arg
-
-class Entry(ExtRegistryEntry):
-    _about_ = make_sure_not_modified
-
-    def compute_result_annotation(self, s_arg):
-        from pypy.annotation.model import SomeList
-        assert isinstance(s_arg, SomeList)
-        # the logic behind it is that we try not to propagate
-        # make_sure_not_resized, when list comprehension is not on
-        if self.bookkeeper.annotator.translator.config.translation.list_comprehension_operations:
-            s_arg.listdef.never_mutate()
-        else:
-            from pypy.annotation.annrpython import log
-            log.WARNING('make_sure_not_modified called, but has no effect since list_comprehension is off')
-        return s_arg
-    
-    def specialize_call(self, hop):
-        hop.exception_cannot_occur()
-        return hop.inputarg(hop.args_r[0], arg=0)
-
 
 class IntegerCanBeNegative(Exception):
     pass

Modified: pypy/branch/jitypes2/pypy/rlib/jit.py
==============================================================================
--- pypy/branch/jitypes2/pypy/rlib/jit.py	(original)
+++ pypy/branch/jitypes2/pypy/rlib/jit.py	Fri Dec  3 11:04:29 2010
@@ -156,7 +156,7 @@
 
 def jit_debug(string, arg1=-sys.maxint-1, arg2=-sys.maxint-1,
                       arg3=-sys.maxint-1, arg4=-sys.maxint-1):
-    """When JITted, cause an extra operation DEBUG_MERGE_POINT to appear in
+    """When JITted, cause an extra operation JIT_DEBUG to appear in
     the graphs.  Should not be left after debugging."""
     keepalive_until_here(string) # otherwise the whole function call is removed
 jit_debug.oopspec = 'jit.debug(string, arg1, arg2, arg3, arg4)'
@@ -260,17 +260,12 @@
 OPTIMIZER_NO_PERFECTSPEC = 1
 OPTIMIZER_FULL = 2
 
-DEBUG_OFF = 0
-DEBUG_PROFILE = 1
-DEBUG_STEPS = 2
-DEBUG_DETAILED = 3
-
 PARAMETERS = {'threshold': 1000,
               'trace_eagerness': 200,
               'trace_limit': 10000,
               'inlining': False,
               'optimizer': OPTIMIZER_FULL,
-              'debug' : DEBUG_STEPS,
+              'loop_longevity': 1000,
               }
 unroll_parameters = unrolling_iterable(PARAMETERS.keys())
 

Modified: pypy/branch/jitypes2/pypy/rlib/libffi.py
==============================================================================
--- pypy/branch/jitypes2/pypy/rlib/libffi.py	(original)
+++ pypy/branch/jitypes2/pypy/rlib/libffi.py	Fri Dec  3 11:04:29 2010
@@ -200,6 +200,9 @@
         # the optimizer will fail to recognize the pattern and won't turn it
         # into a fast CALL.  Note that "arg = arg.next" is optimized away,
         # assuming that archain is completely virtual.
+        if argchain.numargs != len(self.argtypes):
+            raise TypeError, 'Wrong number of arguments: %d expected, got %d' %\
+                (argchain.numargs, len(self.argtypes))
         ll_args = self._prepare()
         i = 0
         arg = argchain.first

Modified: pypy/branch/jitypes2/pypy/rlib/rarithmetic.py
==============================================================================
--- pypy/branch/jitypes2/pypy/rlib/rarithmetic.py	(original)
+++ pypy/branch/jitypes2/pypy/rlib/rarithmetic.py	Fri Dec  3 11:04:29 2010
@@ -92,7 +92,8 @@
         return False
     r_class = rffi.platform.numbertype_to_rclass[tp]
     assert issubclass(r_class, base_int)
-    return r_class.BITS < LONG_BIT
+    return r_class.BITS < LONG_BIT or (
+        r_class.BITS == LONG_BIT and r_class.SIGNED)
 _should_widen_type._annspecialcase_ = 'specialize:memo'
 
 del _bits, _itest, _Ltest
@@ -389,6 +390,11 @@
 r_longlong = build_int('r_longlong', True, 64)
 r_ulonglong = build_int('r_ulonglong', False, 64)
 
+if r_longlong is not r_int:
+    r_int64 = r_longlong
+else:
+    r_int64 = int
+
 
 # float as string  -> sign, beforept, afterpt, exponent
 

Modified: pypy/branch/jitypes2/pypy/rlib/rdynload.py
==============================================================================
--- pypy/branch/jitypes2/pypy/rlib/rdynload.py	(original)
+++ pypy/branch/jitypes2/pypy/rlib/rdynload.py	Fri Dec  3 11:04:29 2010
@@ -14,7 +14,7 @@
 _MINGW = platform.name == "mingw32"
 _WIN32 = _MSVC or _MINGW
 _MAC_OS = platform.name == "darwin"
-_FREEBSD_7 = platform.name == "freebsd7"
+_FREEBSD = platform.name == "freebsd"
 
 if _WIN32:
     from pypy.rlib import rwin32
@@ -27,7 +27,7 @@
 else: 
     pre_include_bits = []
 
-if _FREEBSD_7 or _WIN32:
+if _FREEBSD or _WIN32:
     libraries = []
 else:
     libraries = ['dl']

Modified: pypy/branch/jitypes2/pypy/rlib/rerased.py
==============================================================================
--- pypy/branch/jitypes2/pypy/rlib/rerased.py	(original)
+++ pypy/branch/jitypes2/pypy/rlib/rerased.py	Fri Dec  3 11:04:29 2010
@@ -91,7 +91,7 @@
             return annmodel.SomeInteger()
         assert isinstance(s_type, annmodel.SomePBC)
         assert len(s_type.descriptions) == 1
-        clsdef = s_type.descriptions.keys()[0].getuniqueclassdef()
+        clsdef = s_type.any_description().getuniqueclassdef()
         return annmodel.SomeInstance(clsdef)
 
     def specialize_call(self, hop):
@@ -108,7 +108,7 @@
     def compute_result_annotation(self, s_obj, s_type):
         assert isinstance(s_type, annmodel.SomePBC)
         assert len(s_type.descriptions) == 1
-        clsdef = s_type.descriptions.keys()[0].getuniqueclassdef()
+        clsdef = s_type.any_description().getuniqueclassdef()
         s_item = annmodel.SomeInstance(clsdef)
         return self.bookkeeper.newlist(s_item)
 

Modified: pypy/branch/jitypes2/pypy/rlib/rsre/rsre_core.py
==============================================================================
--- pypy/branch/jitypes2/pypy/rlib/rsre/rsre_core.py	(original)
+++ pypy/branch/jitypes2/pypy/rlib/rsre/rsre_core.py	Fri Dec  3 11:04:29 2010
@@ -1,5 +1,5 @@
 import sys
-from pypy.rlib.debug import check_nonneg, make_sure_not_modified
+from pypy.rlib.debug import check_nonneg
 from pypy.rlib.unroll import unrolling_iterable
 from pypy.rlib.rsre import rsre_char
 from pypy.tool.sourcetools import func_with_new_name
@@ -471,7 +471,6 @@
     while True:
         op = ctx.pat(ppos)
         ppos += 1
-        make_sure_not_modified(ctx.pattern)
 
         #jit.jit_debug("sre_match", op, ppos, ptr)
         #

Modified: pypy/branch/jitypes2/pypy/rlib/rsre/test/test_zjit.py
==============================================================================
--- pypy/branch/jitypes2/pypy/rlib/rsre/test/test_zjit.py	(original)
+++ pypy/branch/jitypes2/pypy/rlib/rsre/test/test_zjit.py	Fri Dec  3 11:04:29 2010
@@ -1,6 +1,5 @@
 from pypy.jit.metainterp.test import test_basic
 from pypy.rlib.nonconst import NonConstant
-from pypy.rlib.debug import make_sure_not_modified
 from pypy.rlib.rsre.test.test_match import get_code
 from pypy.rlib.rsre import rsre_core
 from pypy.rpython.lltypesystem import lltype

Modified: pypy/branch/jitypes2/pypy/rlib/test/test_debug.py
==============================================================================
--- pypy/branch/jitypes2/pypy/rlib/test/test_debug.py	(original)
+++ pypy/branch/jitypes2/pypy/rlib/test/test_debug.py	Fri Dec  3 11:04:29 2010
@@ -42,14 +42,14 @@
     py.test.raises(IntegerCanBeNegative, interpret, g, [9])
 
 def test_make_sure_not_resized():
-    from pypy.annotation.listdef import TooLateForChange
+    from pypy.annotation.listdef import ListChangeUnallowed
     def f():
         result = [1,2,3]
         make_sure_not_resized(result)
         result.append(4)
         return len(result)
 
-    py.test.raises(TooLateForChange, interpret, f, [], 
+    py.test.raises(ListChangeUnallowed, interpret, f, [], 
                    list_comprehension_operations=True)
 
 

Modified: pypy/branch/jitypes2/pypy/rlib/test/test_libffi.py
==============================================================================
--- pypy/branch/jitypes2/pypy/rlib/test/test_libffi.py	(original)
+++ pypy/branch/jitypes2/pypy/rlib/test/test_libffi.py	Fri Dec  3 11:04:29 2010
@@ -282,3 +282,24 @@
         res = self.call(func, [x, y], rffi.FLOAT, init_result=0.0)
         expected = c_float(c_float(12.34).value + c_float(56.78).value).value
         assert res == expected
+
+    def test_wrong_number_of_arguments(self):
+        from pypy.rpython.llinterp import LLException
+        libfoo = self.get_libfoo() 
+        func = (libfoo, 'sum_xy', [types.sint, types.double], types.sint)
+
+        glob = globals()
+        loc = locals()
+        def my_raises(s):
+            try:
+                exec s in glob, loc
+            except TypeError:
+                pass
+            except LLException, e:
+                if str(e) != "<LLException 'TypeError'>":
+                    raise
+            else:
+                assert False, 'Did not raise'
+
+        my_raises("self.call(func, [38], rffi.LONG)") # one less
+        my_raises("self.call(func, [38, 12.3, 42], rffi.LONG)") # one more

Modified: pypy/branch/jitypes2/pypy/rpython/extfunc.py
==============================================================================
--- pypy/branch/jitypes2/pypy/rpython/extfunc.py	(original)
+++ pypy/branch/jitypes2/pypy/rpython/extfunc.py	Fri Dec  3 11:04:29 2010
@@ -201,6 +201,11 @@
                 exec py.code.compile("""
                     from pypy.rlib.objectmodel import running_on_llinterp
                     from pypy.rlib.debug import llinterpcall
+                    from pypy.rlib.jit import dont_look_inside
+                    # note: we say 'dont_look_inside' mostly because the
+                    # JIT does not support 'running_on_llinterp', but in
+                    # theory it is probably right to stop jitting anyway.
+                    @dont_look_inside
                     def ll_wrapper(%s):
                         if running_on_llinterp:
                             return llinterpcall(s_result, fakeimpl, %s)

Modified: pypy/branch/jitypes2/pypy/rpython/lltypesystem/ll2ctypes.py
==============================================================================
--- pypy/branch/jitypes2/pypy/rpython/lltypesystem/ll2ctypes.py	(original)
+++ pypy/branch/jitypes2/pypy/rpython/lltypesystem/ll2ctypes.py	Fri Dec  3 11:04:29 2010
@@ -442,6 +442,9 @@
                             "not allocated from RPython at all")
         self._storage = None
 
+    def _getid(self):
+        return self._addressof_storage()
+
     def __eq__(self, other):
         if isinstance(other, _llgcopaque):
             addressof_other = other.intval
@@ -1291,7 +1294,7 @@
             def _where_is_errno():
                 return standard_c_lib.__errno_location()
 
-        elif sys.platform in ('darwin', 'freebsd7'):
+        elif sys.platform in ('darwin', 'freebsd7', 'freebsd8', 'freebsd9'):
             standard_c_lib.__error.restype = ctypes.POINTER(ctypes.c_int)
             def _where_is_errno():
                 return standard_c_lib.__error()

Modified: pypy/branch/jitypes2/pypy/rpython/lltypesystem/llmemory.py
==============================================================================
--- pypy/branch/jitypes2/pypy/rpython/lltypesystem/llmemory.py	(original)
+++ pypy/branch/jitypes2/pypy/rpython/lltypesystem/llmemory.py	Fri Dec  3 11:04:29 2010
@@ -93,8 +93,10 @@
                 return endmarker._as_ptr()
             else:
                 return parent.getitem(index)._as_ptr()
-        elif (isinstance(A, lltype.FixedSizeArray) and
-              array_item_type_match(A.OF, self.TYPE)):
+        elif ((isinstance(A, lltype.FixedSizeArray)
+               or (isinstance(A, lltype.Array) and A._hints.get('nolength',
+                                                                False)))
+              and array_item_type_match(A.OF, self.TYPE)):
             # for array of primitives or pointers
             return lltype.direct_ptradd(firstitemptr, self.repeat)
         else:

Modified: pypy/branch/jitypes2/pypy/rpython/lltypesystem/rbuiltin.py
==============================================================================
--- pypy/branch/jitypes2/pypy/rpython/lltypesystem/rbuiltin.py	(original)
+++ pypy/branch/jitypes2/pypy/rpython/lltypesystem/rbuiltin.py	Fri Dec  3 11:04:29 2010
@@ -42,7 +42,7 @@
         return hop.genop('cast_pointer', [v_inst],    # v_type implicit in r_result
                          resulttype = hop.r_result.lowleveltype)
 
-    classdef = s_class.descriptions.keys()[0].getuniqueclassdef()
+    classdef = s_class.any_description().getuniqueclassdef()
     return rclass.rtype_new_instance(hop.rtyper, classdef, hop.llops)
 
 def rtype_builtin_hasattr(hop):

Modified: pypy/branch/jitypes2/pypy/rpython/lltypesystem/rclass.py
==============================================================================
--- pypy/branch/jitypes2/pypy/rpython/lltypesystem/rclass.py	(original)
+++ pypy/branch/jitypes2/pypy/rpython/lltypesystem/rclass.py	Fri Dec  3 11:04:29 2010
@@ -392,7 +392,7 @@
                 source_classdef = source_desc.getclassdef(None)
                 source_repr = getinstancerepr(self.rtyper, source_classdef)
                 assert len(s_func.descriptions) == 1
-                funcdesc = s_func.descriptions.keys()[0]
+                funcdesc, = s_func.descriptions
                 graph = funcdesc.getuniquegraph()
                 FUNCTYPE = FuncType([Ptr(source_repr.object_type)], Void)
                 destrptr = functionptr(FUNCTYPE, graph.name,

Modified: pypy/branch/jitypes2/pypy/rpython/lltypesystem/rdict.py
==============================================================================
--- pypy/branch/jitypes2/pypy/rpython/lltypesystem/rdict.py	(original)
+++ pypy/branch/jitypes2/pypy/rpython/lltypesystem/rdict.py	Fri Dec  3 11:04:29 2010
@@ -581,7 +581,7 @@
 def ll_dict_lookup_clean(d, hash):
     # a simplified version of ll_dict_lookup() which assumes that the
     # key is new, and the dictionary doesn't contain deleted entries.
-    # It only find the next free slot for the given hash.
+    # It only finds the next free slot for the given hash.
     entries = d.entries
     mask = len(entries) - 1
     i = hash & mask

Modified: pypy/branch/jitypes2/pypy/rpython/lltypesystem/rpbc.py
==============================================================================
--- pypy/branch/jitypes2/pypy/rpython/lltypesystem/rpbc.py	(original)
+++ pypy/branch/jitypes2/pypy/rpython/lltypesystem/rpbc.py	Fri Dec  3 11:04:29 2010
@@ -127,7 +127,7 @@
     def __init__(self, rtyper, s_pbc):
         self.rtyper = rtyper
         self.s_pbc = s_pbc
-        self.callfamily = s_pbc.descriptions.iterkeys().next().getcallfamily()
+        self.callfamily = s_pbc.any_description().getcallfamily()
         concretetable, uniquerows = get_concrete_calltable(self.rtyper,
                                                            self.callfamily)
         assert len(uniquerows) == 1
@@ -166,7 +166,7 @@
         return self, 0
 
     def get_s_signatures(self, shape):
-        funcdesc = self.s_pbc.descriptions.iterkeys().next()
+        funcdesc = self.s_pbc.any_description()
         return funcdesc.get_s_signatures(shape)
 
     def convert_desc(self, funcdesc):
@@ -230,7 +230,7 @@
         bk = self.rtyper.annotator.bookkeeper
         args = bk.build_args(opname, hop.args_s[1:])
         s_pbc = hop.args_s[0]   # possibly more precise than self.s_pbc
-        descs = s_pbc.descriptions.keys()
+        descs = list(s_pbc.descriptions)
         shape, index = description.FunctionDesc.variant_for_call_site(bk, self.callfamily, descs, args)
         row_of_graphs = self.callfamily.calltables[shape][index]
         anygraph = row_of_graphs.itervalues().next()  # pick any witness

Modified: pypy/branch/jitypes2/pypy/rpython/memory/gc/base.py
==============================================================================
--- pypy/branch/jitypes2/pypy/rpython/memory/gc/base.py	(original)
+++ pypy/branch/jitypes2/pypy/rpython/memory/gc/base.py	Fri Dec  3 11:04:29 2010
@@ -5,7 +5,6 @@
 from pypy.rpython.memory.support import get_address_stack, get_address_deque
 from pypy.rpython.memory.support import AddressDict
 from pypy.rpython.lltypesystem.llmemory import NULL, raw_malloc_usage
-from pypy.rlib.rarithmetic import r_uint
 
 TYPEID_MAP = lltype.GcStruct('TYPEID_MAP', ('count', lltype.Signed),
                              ('size', lltype.Signed),
@@ -19,6 +18,7 @@
     malloc_zero_filled = False
     prebuilt_gc_objects_are_static_roots = True
     object_minimal_size = 0
+    gcflag_extra = 0   # or a real GC flag that is always 0 when not collecting
 
     def __init__(self, config, chunk_size=DEFAULT_CHUNK_SIZE,
                  translated_to_c=True):
@@ -410,42 +410,6 @@
     GCClass = getattr(module, classname)
     return GCClass, GCClass.TRANSLATION_PARAMS
 
-def _read_float_and_factor_from_env(varname):
-    import os
-    value = os.environ.get(varname)
-    if value:
-        if len(value) > 1 and value[-1] in 'bB':
-            value = value[:-1]
-        realvalue = value[:-1]
-        if value[-1] in 'kK':
-            factor = 1024
-        elif value[-1] in 'mM':
-            factor = 1024*1024
-        elif value[-1] in 'gG':
-            factor = 1024*1024*1024
-        else:
-            factor = 1
-            realvalue = value
-        try:
-            return (float(realvalue), factor)
-        except ValueError:
-            pass
-    return (0.0, 0)
-
-def read_from_env(varname):
-    value, factor = _read_float_and_factor_from_env(varname)
-    return int(value * factor)
-
-def read_uint_from_env(varname):
-    value, factor = _read_float_and_factor_from_env(varname)
-    return r_uint(value * factor)
-
-def read_float_from_env(varname):
-    value, factor = _read_float_and_factor_from_env(varname)
-    if factor != 1:
-        return 0.0
-    return value
-
 def _convert_callback_formats(callback):
     callback = getattr(callback, 'im_func', callback)
     if callback not in _converted_callback_formats:

Modified: pypy/branch/jitypes2/pypy/rpython/memory/gc/generation.py
==============================================================================
--- pypy/branch/jitypes2/pypy/rpython/memory/gc/generation.py	(original)
+++ pypy/branch/jitypes2/pypy/rpython/memory/gc/generation.py	Fri Dec  3 11:04:29 2010
@@ -2,7 +2,7 @@
 from pypy.rpython.memory.gc.semispace import SemiSpaceGC
 from pypy.rpython.memory.gc.semispace import GCFLAG_EXTERNAL, GCFLAG_FORWARDED
 from pypy.rpython.memory.gc.semispace import GC_HASH_TAKEN_ADDR
-from pypy.rpython.memory.gc.base import read_from_env
+from pypy.rpython.memory.gc import env
 from pypy.rpython.lltypesystem.llmemory import NULL, raw_malloc_usage
 from pypy.rpython.lltypesystem import lltype, llmemory, llarena
 from pypy.rlib.objectmodel import free_non_gc_object
@@ -93,7 +93,7 @@
         if self.auto_nursery_size:
             newsize = nursery_size_from_env()
             if newsize <= 0:
-                newsize = estimate_best_nursery_size()
+                newsize = env.estimate_best_nursery_size()
             if newsize > 0:
                 self.set_nursery_size(newsize)
 
@@ -633,139 +633,5 @@
 
 # ____________________________________________________________
 
-import os
-
 def nursery_size_from_env():
-    return read_from_env('PYPY_GENERATIONGC_NURSERY')
-
-def best_nursery_size_for_L2cache(L2cache):
-    # Heuristically, the best nursery size to choose is about half
-    # of the L2 cache.  XXX benchmark some more.
-    return L2cache // 2
-
-
-if sys.platform == 'linux2':
-    def estimate_best_nursery_size():
-        """Try to estimate the best nursery size at run-time, depending
-        on the machine we are running on.
-        """
-        debug_start("gc-L2cache")
-        L2cache = sys.maxint
-        try:
-            fd = os.open('/proc/cpuinfo', os.O_RDONLY, 0644)
-            try:
-                data = []
-                while True:
-                    buf = os.read(fd, 4096)
-                    if not buf:
-                        break
-                    data.append(buf)
-            finally:
-                os.close(fd)
-        except OSError:
-            pass
-        else:
-            data = ''.join(data)
-            linepos = 0
-            while True:
-                start = findend(data, '\ncache size', linepos)
-                if start < 0:
-                    break    # done
-                linepos = findend(data, '\n', start)
-                if linepos < 0:
-                    break    # no end-of-line??
-                # *** data[start:linepos] == "   : 2048 KB\n"
-                start = skipspace(data, start)
-                if data[start] != ':':
-                    continue
-                # *** data[start:linepos] == ": 2048 KB\n"
-                start = skipspace(data, start + 1)
-                # *** data[start:linepos] == "2048 KB\n"
-                end = start
-                while '0' <= data[end] <= '9':
-                    end += 1
-                # *** data[start:end] == "2048"
-                if start == end:
-                    continue
-                number = int(data[start:end])
-                # *** data[end:linepos] == " KB\n"
-                end = skipspace(data, end)
-                if data[end] not in ('K', 'k'):    # assume kilobytes for now
-                    continue
-                number = number * 1024
-                # for now we look for the smallest of the L2 caches of the CPUs
-                if number < L2cache:
-                    L2cache = number
-
-        debug_print("L2cache =", L2cache)
-        debug_stop("gc-L2cache")
-
-        if L2cache < sys.maxint:
-            return best_nursery_size_for_L2cache(L2cache)
-        else:
-            # Print a top-level warning even in non-debug builds
-            llop.debug_print(lltype.Void,
-                "Warning: cannot find your CPU L2 cache size in /proc/cpuinfo")
-            return -1
-
-    def findend(data, pattern, pos):
-        pos = data.find(pattern, pos)
-        if pos < 0:
-            return -1
-        return pos + len(pattern)
-
-    def skipspace(data, pos):
-        while data[pos] in (' ', '\t'):
-            pos += 1
-        return pos
-
-elif sys.platform == 'darwin':
-    from pypy.rpython.lltypesystem import rffi
-
-    sysctlbyname = rffi.llexternal('sysctlbyname',
-                                   [rffi.CCHARP, rffi.VOIDP, rffi.SIZE_TP,
-                                    rffi.VOIDP, rffi.SIZE_T],
-                                   rffi.INT,
-                                   sandboxsafe=True)
-
-    def estimate_best_nursery_size():
-        """Try to estimate the best nursery size at run-time, depending
-        on the machine we are running on.
-        """
-        debug_start("gc-L2cache")
-        L2cache = 0
-        l2cache_p = lltype.malloc(rffi.LONGLONGP.TO, 1, flavor='raw')
-        try:
-            len_p = lltype.malloc(rffi.SIZE_TP.TO, 1, flavor='raw')
-            try:
-                size = rffi.sizeof(rffi.LONGLONG)
-                l2cache_p[0] = rffi.cast(rffi.LONGLONG, 0)
-                len_p[0] = rffi.cast(rffi.SIZE_T, size)
-                # XXX a hack for llhelper not being robust-enough
-                result = sysctlbyname("hw.l2cachesize",
-                                      rffi.cast(rffi.VOIDP, l2cache_p),
-                                      len_p,
-                                      lltype.nullptr(rffi.VOIDP.TO), 
-                                      rffi.cast(rffi.SIZE_T, 0))
-                if (rffi.cast(lltype.Signed, result) == 0 and
-                    rffi.cast(lltype.Signed, len_p[0]) == size):
-                    L2cache = rffi.cast(lltype.Signed, l2cache_p[0])
-                    if rffi.cast(rffi.LONGLONG, L2cache) != l2cache_p[0]:
-                        L2cache = 0    # overflow!
-            finally:
-                lltype.free(len_p, flavor='raw')
-        finally:
-            lltype.free(l2cache_p, flavor='raw')
-        debug_print("L2cache =", L2cache)
-        debug_stop("gc-L2cache")
-        if L2cache > 0:
-            return best_nursery_size_for_L2cache(L2cache)
-        else:
-            # Print a top-level warning even in non-debug builds
-            llop.debug_print(lltype.Void,
-                "Warning: cannot find your CPU L2 cache size with sysctl()")
-            return -1
-
-else:
-    def estimate_best_nursery_size():
-        return -1     # XXX implement me for other platforms
+    return env.read_from_env('PYPY_GENERATIONGC_NURSERY')

Modified: pypy/branch/jitypes2/pypy/rpython/memory/gc/inspector.py
==============================================================================
--- pypy/branch/jitypes2/pypy/rpython/memory/gc/inspector.py	(original)
+++ pypy/branch/jitypes2/pypy/rpython/memory/gc/inspector.py	Fri Dec  3 11:04:29 2010
@@ -101,21 +101,24 @@
 
 AddressStack = get_address_stack()
 
-class HeapDumper:
+class HeapDumper(object):
     _alloc_flavor_ = "raw"
     BUFSIZE = 8192     # words
 
     def __init__(self, gc, fd):
         self.gc = gc
+        self.gcflag = gc.gcflag_extra
         self.fd = rffi.cast(rffi.INT, fd)
         self.writebuffer = lltype.malloc(rffi.LONGP.TO, self.BUFSIZE,
                                          flavor='raw')
         self.buf_count = 0
-        self.seen = AddressDict()
+        if self.gcflag == 0:
+            self.seen = AddressDict()
         self.pending = AddressStack()
 
     def delete(self):
-        self.seen.delete()
+        if self.gcflag == 0:
+            self.seen.delete()
         self.pending.delete()
         lltype.free(self.writebuffer, flavor='raw')
         free_non_gc_object(self)
@@ -140,6 +143,8 @@
             self.flush()
     write._always_inline_ = True
 
+    # ----------
+
     def write_marker(self):
         self.write(0)
         self.write(0)
@@ -161,9 +166,15 @@
         self.add(obj)
 
     def add(self, obj):
-        if not self.seen.contains(obj):
-            self.seen.setitem(obj, obj)
-            self.pending.append(obj)
+        if self.gcflag == 0:
+            if not self.seen.contains(obj):
+                self.seen.setitem(obj, obj)
+                self.pending.append(obj)
+        else:
+            hdr = self.gc.header(obj)
+            if (hdr.tid & self.gcflag) == 0:
+                hdr.tid |= self.gcflag
+                self.pending.append(obj)
 
     def add_roots(self):
         self.gc.enumerate_all_roots(_hd_add_root, self)
@@ -177,14 +188,50 @@
         while pending.non_empty():
             self.writeobj(pending.pop())
 
+    # ----------
+    # A simplified copy of the above, to make sure we walk again all the
+    # objects to clear the 'gcflag'.
+
+    def unwriteobj(self, obj):
+        gc = self.gc
+        gc.trace(obj, self._unwriteref, None)
+
+    def _unwriteref(self, pointer, _):
+        obj = pointer.address[0]
+        self.unadd(obj)
+
+    def unadd(self, obj):
+        assert self.gcflag != 0
+        hdr = self.gc.header(obj)
+        if (hdr.tid & self.gcflag) != 0:
+            hdr.tid &= ~self.gcflag
+            self.pending.append(obj)
+
+    def clear_gcflag_again(self):
+        self.gc.enumerate_all_roots(_hd_unadd_root, self)
+        pendingroots = self.pending
+        self.pending = AddressStack()
+        self.unwalk(pendingroots)
+        pendingroots.delete()
+
+    def unwalk(self, pending):
+        while pending.non_empty():
+            self.unwriteobj(pending.pop())
+
 def _hd_add_root(obj, heap_dumper):
     heap_dumper.add(obj)
 
+def _hd_unadd_root(obj, heap_dumper):
+    heap_dumper.unadd(obj)
+
 def dump_rpy_heap(gc, fd):
     heapdumper = HeapDumper(gc, fd)
     heapdumper.add_roots()
     heapdumper.walk(heapdumper.pending)
     heapdumper.flush()
+    if heapdumper.gcflag != 0:
+        heapdumper.clear_gcflag_again()
+        heapdumper.unwalk(heapdumper.pending)
     heapdumper.delete()
     return True
 

Modified: pypy/branch/jitypes2/pypy/rpython/memory/gc/markcompact.py
==============================================================================
--- pypy/branch/jitypes2/pypy/rpython/memory/gc/markcompact.py	(original)
+++ pypy/branch/jitypes2/pypy/rpython/memory/gc/markcompact.py	Fri Dec  3 11:04:29 2010
@@ -1,5 +1,6 @@
 from pypy.rpython.lltypesystem import lltype, llmemory, llarena, llgroup
-from pypy.rpython.memory.gc.base import MovingGCBase, read_from_env
+from pypy.rpython.memory.gc.base import MovingGCBase
+from pypy.rpython.memory.gc import env
 from pypy.rlib.debug import ll_assert, have_debug_prints
 from pypy.rlib.debug import debug_print, debug_start, debug_stop
 from pypy.rpython.memory.support import get_address_stack, get_address_deque
@@ -110,10 +111,10 @@
         return next
 
     def setup(self):
-        envsize = read_from_env('PYPY_MARKCOMPACTGC_MAX')
+        envsize = env.read_from_env('PYPY_MARKCOMPACTGC_MAX')
         if envsize >= 4096:
             self.space_size = envsize & ~4095
-        mincollect = read_from_env('PYPY_MARKCOMPACTGC_MIN')
+        mincollect = env.read_from_env('PYPY_MARKCOMPACTGC_MIN')
         if mincollect >= 4096:
             self.min_next_collect_after = mincollect
 

Modified: pypy/branch/jitypes2/pypy/rpython/memory/gc/minimark.py
==============================================================================
--- pypy/branch/jitypes2/pypy/rpython/memory/gc/minimark.py	(original)
+++ pypy/branch/jitypes2/pypy/rpython/memory/gc/minimark.py	Fri Dec  3 11:04:29 2010
@@ -12,7 +12,7 @@
                         collection.
 
  PYPY_GC_GROWTH         Major collection threshold's max growth rate.
-                        Default is '1.3'.  Useful to collect more often
+                        Default is '1.4'.  Useful to collect more often
                         than normally on sudden memory growth, e.g. when
                         there is a temporary peak in memory usage.
 
@@ -22,6 +22,12 @@
                         crash the program with a fatal error.  Try values
                         like '1.6GB'.
 
+ PYPY_GC_MAX_DELTA      The major collection threshold will never be set
+                        to more than PYPY_GC_MAX_DELTA the amount really
+                        used after a collection.  Defaults to 1/8th of the
+                        total RAM size (which is constrained to be at most
+                        2/3/4GB on 32-bit systems).  Try values like '200MB'.
+
  PYPY_GC_MIN            Don't collect while the memory size is below this
                         limit.  Useful to avoid spending all the time in
                         the GC in very small programs.  Defaults to 8
@@ -36,7 +42,7 @@
 from pypy.rpython.lltypesystem.lloperation import llop
 from pypy.rpython.lltypesystem.llmemory import raw_malloc_usage
 from pypy.rpython.memory.gc.base import GCBase, MovingGCBase
-from pypy.rpython.memory.gc import minimarkpage, base, generation
+from pypy.rpython.memory.gc import minimarkpage, env
 from pypy.rlib.rarithmetic import ovfcheck, LONG_BIT, intmask, r_uint
 from pypy.rlib.rarithmetic import LONG_BIT_SHIFT
 from pypy.rlib.debug import ll_assert, debug_print, debug_start, debug_stop
@@ -96,6 +102,7 @@
     needs_write_barrier = True
     prebuilt_gc_objects_are_static_roots = False
     malloc_zero_filled = True    # xxx experiment with False
+    gcflag_extra = GCFLAG_FINALIZATION_ORDERING
 
     # All objects start with a HDR, i.e. with a field 'tid' which contains
     # a word.  This word is divided in two halves: the lower half contains
@@ -154,7 +161,7 @@
         # grow at most by the following factor from one collection to the
         # next.  Used e.g. when there is a sudden, temporary peak in memory
         # usage; this avoids that the upper bound grows too fast.
-        "growth_rate_max": 1.3,
+        "growth_rate_max": 1.4,
 
         # The number of array indices that are mapped to a single bit in
         # write_barrier_from_array().  Must be a power of two.  The default
@@ -198,6 +205,7 @@
         self.min_heap_size = 0.0
         self.max_heap_size = 0.0
         self.max_heap_size_already_raised = False
+        self.max_delta = float(r_uint(-1))
         #
         self.card_page_indices = card_page_indices
         if self.card_page_indices > 0:
@@ -282,36 +290,42 @@
             #
             # From there on, the GC is fully initialized and the code
             # below can use it
-            newsize = base.read_from_env('PYPY_GC_NURSERY')
+            newsize = env.read_from_env('PYPY_GC_NURSERY')
             # PYPY_GC_NURSERY=1 forces a minor collect for every malloc.
             # Useful to debug external factors, like trackgcroot or the
             # handling of the write barrier.
             self.debug_always_do_minor_collect = newsize == 1
             if newsize <= 0:
-                newsize = generation.estimate_best_nursery_size()
+                newsize = env.estimate_best_nursery_size()
                 if newsize <= 0:
                     newsize = defaultsize
             newsize = max(newsize, minsize)
             #
-            major_coll = base.read_float_from_env('PYPY_GC_MAJOR_COLLECT')
+            major_coll = env.read_float_from_env('PYPY_GC_MAJOR_COLLECT')
             if major_coll > 1.0:
                 self.major_collection_threshold = major_coll
             #
-            growth = base.read_float_from_env('PYPY_GC_GROWTH')
+            growth = env.read_float_from_env('PYPY_GC_GROWTH')
             if growth > 1.0:
                 self.growth_rate_max = growth
             #
-            min_heap_size = base.read_uint_from_env('PYPY_GC_MIN')
+            min_heap_size = env.read_uint_from_env('PYPY_GC_MIN')
             if min_heap_size > 0:
                 self.min_heap_size = float(min_heap_size)
             else:
                 # defaults to 8 times the nursery
                 self.min_heap_size = newsize * 8
             #
-            max_heap_size = base.read_uint_from_env('PYPY_GC_MAX')
+            max_heap_size = env.read_uint_from_env('PYPY_GC_MAX')
             if max_heap_size > 0:
                 self.max_heap_size = float(max_heap_size)
             #
+            max_delta = env.read_uint_from_env('PYPY_GC_MAX_DELTA')
+            if max_delta > 0:
+                self.max_delta = float(max_delta)
+            else:
+                self.max_delta = 0.125 * env.get_total_memory()
+            #
             self.minor_collection()    # to empty the nursery
             llarena.arena_free(self.nursery)
             self.nursery_size = newsize
@@ -638,8 +652,13 @@
         # means recording that they have a smaller size, so that when
         # moved out of the nursery, they will consume less memory.
         # In particular, an array with GCFLAG_HAS_CARDS is never resized.
+        # Also, a nursery object with GCFLAG_HAS_SHADOW is not resized
+        # either, as this would potentially loose part of the memory in
+        # the already-allocated shadow.
         if not self.is_in_nursery(obj):
             return False
+        if self.header(obj).tid & GCFLAG_HAS_SHADOW:
+            return False
         #
         size_gc_header = self.gcheaderbuilder.size_gc_header
         typeid = self.get_type_id(obj)
@@ -1245,9 +1264,12 @@
         #
         # Set the threshold for the next major collection to be when we
         # have allocated 'major_collection_threshold' times more than
+        # we currently have -- but no more than 'max_delta' more than
         # we currently have.
+        total_memory_used = float(self.get_total_memory_used())
         bounded = self.set_major_threshold_from(
-            self.get_total_memory_used() * self.major_collection_threshold,
+            min(total_memory_used * self.major_collection_threshold,
+                total_memory_used + self.max_delta),
             reserving_size)
         #
         # Max heap size: gives an upper bound on the threshold.  If we
@@ -1406,12 +1428,21 @@
                     size = self.get_size(obj)
                     shadowhdr = self._malloc_out_of_nursery(size_gc_header +
                                                             size)
-                    # initialize to an invalid tid *without* GCFLAG_VISITED,
-                    # so that if the object dies before the next minor
-                    # collection, the shadow will stay around but be collected
-                    # by the next major collection.
+                    # Initialize the shadow enough to be considered a
+                    # valid gc object.  If the original object stays
+                    # alive at the next minor collection, it will anyway
+                    # be copied over the shadow and overwrite the
+                    # following fields.  But if the object dies, then
+                    # the shadow will stay around and only be freed at
+                    # the next major collection, at which point we want
+                    # it to look valid (but ready to be freed).
                     shadow = shadowhdr + size_gc_header
-                    self.header(shadow).tid = 0
+                    self.header(shadow).tid = self.header(obj).tid
+                    typeid = self.get_type_id(obj)
+                    if self.is_varsize(typeid):
+                        lenofs = self.varsize_offset_to_length(typeid)
+                        (shadow + lenofs).signed[0] = (obj + lenofs).signed[0]
+                    #
                     self.header(obj).tid |= GCFLAG_HAS_SHADOW
                     self.young_objects_shadows.setitem(obj, shadow)
                 #

Modified: pypy/branch/jitypes2/pypy/rpython/memory/gc/semispace.py
==============================================================================
--- pypy/branch/jitypes2/pypy/rpython/memory/gc/semispace.py	(original)
+++ pypy/branch/jitypes2/pypy/rpython/memory/gc/semispace.py	Fri Dec  3 11:04:29 2010
@@ -42,6 +42,7 @@
     inline_simple_malloc_varsize = True
     malloc_zero_filled = True
     first_unused_gcflag = first_gcflag << 5
+    gcflag_extra = GCFLAG_FINALIZATION_ORDERING
 
     HDR = lltype.Struct('header', ('tid', lltype.Signed))   # XXX or rffi.INT?
     typeid_is_in_field = 'tid'

Modified: pypy/branch/jitypes2/pypy/rpython/memory/gc/test/test_direct.py
==============================================================================
--- pypy/branch/jitypes2/pypy/rpython/memory/gc/test/test_direct.py	(original)
+++ pypy/branch/jitypes2/pypy/rpython/memory/gc/test/test_direct.py	Fri Dec  3 11:04:29 2010
@@ -60,7 +60,7 @@
         pass
 
 
-class DirectGCTest(object):
+class BaseDirectGCTest(object):
     GC_PARAMS = {}
 
     def setup_method(self, meth):
@@ -106,6 +106,9 @@
         addr = self.gc.malloc(self.get_type_id(TYPE), n, zero=True)
         return llmemory.cast_adr_to_ptr(addr, lltype.Ptr(TYPE))
 
+
+class DirectGCTest(BaseDirectGCTest):
+
     def test_simple(self):
         p = self.malloc(S)
         p.x = 5
@@ -339,6 +342,15 @@
             self.gc.collect()
             assert hash == self.gc.identityhash(self.stackroots[-1])
             self.stackroots.pop()
+        # (7) the same, but the objects are dying young
+        for i in range(10):
+            self.gc.collect()
+            p = self.malloc(VAR, i)
+            self.stackroots.append(p)
+            hash1 = self.gc.identityhash(p)
+            hash2 = self.gc.identityhash(p)
+            assert hash1 == hash2
+            self.stackroots.pop()
 
     def test_memory_alignment(self):
         A1 = lltype.GcArray(lltype.Char)

Modified: pypy/branch/jitypes2/pypy/rpython/memory/gctransform/asmgcroot.py
==============================================================================
--- pypy/branch/jitypes2/pypy/rpython/memory/gctransform/asmgcroot.py	(original)
+++ pypy/branch/jitypes2/pypy/rpython/memory/gctransform/asmgcroot.py	Fri Dec  3 11:04:29 2010
@@ -139,12 +139,13 @@
         self._shape_decompressor = ShapeDecompressor()
         if hasattr(gctransformer.translator, '_jit2gc'):
             jit2gc = gctransformer.translator._jit2gc
-            self._extra_gcmapstart = jit2gc['gcmapstart']
-            self._extra_gcmapend   = jit2gc['gcmapend']
+            self._extra_gcmapstart  = jit2gc['gcmapstart']
+            self._extra_gcmapend    = jit2gc['gcmapend']
+            self._extra_mark_sorted = jit2gc['gcmarksorted']
         else:
-            returns_null = lambda: llmemory.NULL
-            self._extra_gcmapstart = returns_null
-            self._extra_gcmapend   = returns_null
+            self._extra_gcmapstart  = lambda: llmemory.NULL
+            self._extra_gcmapend    = lambda: llmemory.NULL
+            self._extra_mark_sorted = lambda: True
 
     def need_thread_support(self, gctransformer, getfn):
         # Threads supported "out of the box" by the rest of the code.
@@ -295,14 +296,16 @@
             # we have a non-empty JIT-produced table to look in
             item = search_in_gcmap2(gcmapstart2, gcmapend2, retaddr)
             if item:
-                self._shape_decompressor.setaddr(item.address[1])
+                self._shape_decompressor.setaddr(item)
                 return
             # maybe the JIT-produced table is not sorted?
-            sort_gcmap(gcmapstart2, gcmapend2)
-            item = search_in_gcmap2(gcmapstart2, gcmapend2, retaddr)
-            if item:
-                self._shape_decompressor.setaddr(item.address[1])
-                return
+            was_already_sorted = self._extra_mark_sorted()
+            if not was_already_sorted:
+                sort_gcmap(gcmapstart2, gcmapend2)
+                item = search_in_gcmap2(gcmapstart2, gcmapend2, retaddr)
+                if item:
+                    self._shape_decompressor.setaddr(item)
+                    return
         # the item may have been not found because the main array was
         # not sorted.  Sort it and try again.
         win32_follow_gcmap_jmp(gcmapstart, gcmapend)
@@ -357,7 +360,8 @@
     The interval from the start address (included) to the end address
     (excluded) is assumed to be a sorted arrays of pairs (addr1, addr2).
     This searches for the item with a given addr1 and returns its
-    address.
+    address.  If not found exactly, it tries to return the address
+    of the item left of addr1 (i.e. such that result.address[0] < addr1).
     """
     count = (end - start) // arrayitemsize
     while count > 1:
@@ -386,7 +390,7 @@
     # (item.signed[1] is an address in this case, not a signed at all!)
     item = binary_search(gcmapstart, gcmapend, retaddr)
     if item.address[0] == retaddr:
-        return item     # found
+        return item.address[1]     # found
     else:
         return llmemory.NULL    # failed
 

Modified: pypy/branch/jitypes2/pypy/rpython/memory/gctransform/boehm.py
==============================================================================
--- pypy/branch/jitypes2/pypy/rpython/memory/gctransform/boehm.py	(original)
+++ pypy/branch/jitypes2/pypy/rpython/memory/gctransform/boehm.py	Fri Dec  3 11:04:29 2010
@@ -120,10 +120,11 @@
             fptr = self.annotate_finalizer(d['ll_finalizer'], [llmemory.Address], lltype.Void)
         elif destrptr:
             EXC_INSTANCE_TYPE = self.translator.rtyper.exceptiondata.lltype_of_exception_value
+            typename = TYPE.__name__
             def ll_finalizer(addr):
                 exc_instance = llop.gc_fetch_exception(EXC_INSTANCE_TYPE)
                 v = llmemory.cast_adr_to_ptr(addr, DESTR_ARG)
-                ll_call_destructor(destrptr, v)
+                ll_call_destructor(destrptr, v, typename)
                 llop.gc_restore_exception(lltype.Void, exc_instance)
             fptr = self.annotate_finalizer(ll_finalizer, [llmemory.Address], lltype.Void)
         else:

Modified: pypy/branch/jitypes2/pypy/rpython/memory/gctransform/framework.py
==============================================================================
--- pypy/branch/jitypes2/pypy/rpython/memory/gctransform/framework.py	(original)
+++ pypy/branch/jitypes2/pypy/rpython/memory/gctransform/framework.py	Fri Dec  3 11:04:29 2010
@@ -1204,9 +1204,10 @@
 
         assert not type_contains_pyobjs(TYPE), "not implemented"
         if destrptr:
+            typename = TYPE.__name__
             def ll_finalizer(addr):
                 v = llmemory.cast_adr_to_ptr(addr, DESTR_ARG)
-                ll_call_destructor(destrptr, v)
+                ll_call_destructor(destrptr, v, typename)
             fptr = self.transformer.annotate_finalizer(ll_finalizer,
                                                        [llmemory.Address],
                                                        lltype.Void)

Modified: pypy/branch/jitypes2/pypy/rpython/memory/gctransform/refcounting.py
==============================================================================
--- pypy/branch/jitypes2/pypy/rpython/memory/gctransform/refcounting.py	(original)
+++ pypy/branch/jitypes2/pypy/rpython/memory/gctransform/refcounting.py	Fri Dec  3 11:04:29 2010
@@ -227,7 +227,7 @@
         # refcount is at zero, temporarily bump it to 1:
         gcheader.refcount = 1
         destr_v = cast_pointer(DESTR_ARG, v)
-        ll_call_destructor(destrptr, destr_v)
+        ll_call_destructor(destrptr, destr_v, %r)
         refcount = gcheader.refcount - 1
         gcheader.refcount = refcount
         if refcount == 0:
@@ -239,7 +239,7 @@
     pop_alive(exc_instance)
     # XXX layering of exceptiontransform versus gcpolicy
 
-""" % (body, TYPE._gckind)
+""" % (TYPE.__name__, body, TYPE._gckind)
         else:
             call_del = None
             body = '\n'.join(_static_deallocator_body_for_type('v', TYPE))

Modified: pypy/branch/jitypes2/pypy/rpython/memory/gctransform/support.py
==============================================================================
--- pypy/branch/jitypes2/pypy/rpython/memory/gctransform/support.py	(original)
+++ pypy/branch/jitypes2/pypy/rpython/memory/gctransform/support.py	Fri Dec  3 11:04:29 2010
@@ -98,11 +98,15 @@
         hop.exception_cannot_occur()
         return hop.inputconst(hop.r_result.lowleveltype, hop.s_result.const)
 
-def ll_call_destructor(destrptr, destr_v):
+def ll_call_destructor(destrptr, destr_v, typename):
     try:
         destrptr(destr_v)
-    except:
+    except Exception, e:
         try:
-            os.write(2, "a destructor raised an exception, ignoring it\n")
+            os.write(2, "a destructor of type ")
+            os.write(2, typename)
+            os.write(2, " raised an exception ")
+            os.write(2, str(e))
+            os.write(2, " ignoring it\n")
         except:
             pass

Modified: pypy/branch/jitypes2/pypy/rpython/module/ll_os.py
==============================================================================
--- pypy/branch/jitypes2/pypy/rpython/module/ll_os.py	(original)
+++ pypy/branch/jitypes2/pypy/rpython/module/ll_os.py	Fri Dec  3 11:04:29 2010
@@ -1386,6 +1386,25 @@
         return extdef([], (int, int), "ll_os.ll_os_openpty",
                       llimpl=openpty_llimpl)
 
+    @registering_if(os, 'forkpty')
+    def register_os_forkpty(self):
+        os_forkpty = self.llexternal(
+            'forkpty',
+            [rffi.INTP, rffi.VOIDP, rffi.VOIDP, rffi.VOIDP],
+            rffi.PID_T,
+            compilation_info=ExternalCompilationInfo(libraries=['util']))
+        def forkpty_llimpl():
+            master_p = lltype.malloc(rffi.INTP.TO, 1, flavor='raw')
+            childpid = os_forkpty(master_p, None, None, None)
+            master_fd = master_p[0]
+            lltype.free(master_p, flavor='raw')
+            if childpid == -1:
+                raise OSError(rposix.get_errno(), "os_forkpty failed")
+            return (rffi.cast(lltype.Signed, childpid),
+                    rffi.cast(lltype.Signed, master_fd))
+
+        return extdef([], (int, int), "ll_os.ll_os_forkpty",
+                      llimpl=forkpty_llimpl)
 
     @registering(os._exit)
     def register_os__exit(self):

Modified: pypy/branch/jitypes2/pypy/rpython/module/ll_time.py
==============================================================================
--- pypy/branch/jitypes2/pypy/rpython/module/ll_time.py	(original)
+++ pypy/branch/jitypes2/pypy/rpython/module/ll_time.py	Fri Dec  3 11:04:29 2010
@@ -41,7 +41,7 @@
         RUSAGE = platform.Struct('struct rusage', [('ru_utime', TIMEVAL),
                                                    ('ru_stime', TIMEVAL)])
 
-if sys.platform == 'freebsd7':
+if "freebsd" in sys.platform:
     libraries = ['compat']
 else:
     libraries = []

Modified: pypy/branch/jitypes2/pypy/rpython/ootypesystem/rpbc.py
==============================================================================
--- pypy/branch/jitypes2/pypy/rpython/ootypesystem/rpbc.py	(original)
+++ pypy/branch/jitypes2/pypy/rpython/ootypesystem/rpbc.py	Fri Dec  3 11:04:29 2010
@@ -49,7 +49,7 @@
         return hop.genop('runtimenew', [v_class], resulttype=resulttype)
 
     def getlowleveltype(self):
-        classdescs = self.s_pbc.descriptions.keys()
+        classdescs = list(self.s_pbc.descriptions)
         # if any of the classdefs get the lowleveltype ootype.Class,
         # we can only pick ootype.Class for us too.  Otherwise META.
         for classdesc in classdescs:
@@ -70,7 +70,7 @@
 class MethodImplementations(object):
 
     def __init__(self, rtyper, methdescs):
-        samplemdesc = methdescs.iterkeys().next()
+        samplemdesc = iter(methdescs).next()
         concretetable, uniquerows = get_concrete_calltable(rtyper,
                                              samplemdesc.funcdesc.getcallfamily())
         self.row_mapping = {}
@@ -117,7 +117,7 @@
     concretetable = None # set by _setup_repr_final
 
     def _setup_repr_final(self):
-        sampledesc = self.s_pbc.descriptions.iterkeys().next()
+        sampledesc = self.s_pbc.any_description()
         self.concretetable, _ = get_concrete_calltable(self.rtyper,
                                              sampledesc.funcdesc.getcallfamily())
 

Modified: pypy/branch/jitypes2/pypy/rpython/rlist.py
==============================================================================
--- pypy/branch/jitypes2/pypy/rpython/rlist.py	(original)
+++ pypy/branch/jitypes2/pypy/rpython/rlist.py	Fri Dec  3 11:04:29 2010
@@ -9,7 +9,7 @@
 from pypy.rpython import robject
 from pypy.rlib.objectmodel import malloc_zero_filled
 from pypy.rlib.debug import ll_assert
-from pypy.rlib.rarithmetic import ovfcheck, widen
+from pypy.rlib.rarithmetic import ovfcheck, widen, r_uint, intmask
 from pypy.rpython.annlowlevel import ADTInterface
 from pypy.rlib import rgc
 
@@ -241,17 +241,22 @@
 class __extend__(pairtype(AbstractBaseListRepr, IntegerRepr)):
 
     def rtype_getitem((r_lst, r_int), hop, checkidx=False):
+        v_lst, v_index = hop.inputargs(r_lst, Signed)
         if checkidx:
-            spec = dum_checkidx
+            hop.exception_is_here()
         else:
-            spec = dum_nocheck
-        v_func = hop.inputconst(Void, spec)
-        v_lst, v_index = hop.inputargs(r_lst, Signed)
+            hop.exception_cannot_occur()
         if hop.args_s[0].listdef.listitem.mutated or checkidx:
             if hop.args_s[1].nonneg:
                 llfn = ll_getitem_nonneg
             else:
                 llfn = ll_getitem
+            if checkidx:
+                spec = dum_checkidx
+            else:
+                spec = dum_nocheck
+            c_func_marker = hop.inputconst(Void, spec)
+            v_res = hop.gendirectcall(llfn, c_func_marker, v_lst, v_index)
         else:
             # this is the 'foldable' version, which is not used when
             # we check for IndexError
@@ -259,11 +264,7 @@
                 llfn = ll_getitem_foldable_nonneg
             else:
                 llfn = ll_getitem_foldable
-        if checkidx:
-            hop.exception_is_here()
-        else:
-            hop.exception_cannot_occur()
-        v_res = hop.gendirectcall(llfn, v_func, v_lst, v_index)
+            v_res = hop.gendirectcall(llfn, v_lst, v_index)
         return r_lst.recast(hop.llops, v_res)
 
     rtype_getitem_key = rtype_getitem
@@ -538,12 +539,14 @@
             dest.ll_setitem_fast(dest_start + i, item)
             i += 1
 ll_arraycopy._annenforceargs_ = [None, None, int, int, int]
+# no oopspec -- the function is inlined by the JIT
 
 def ll_copy(RESLIST, l):
     length = l.ll_length()
     new_lst = RESLIST.ll_newlist(length)
     ll_arraycopy(l, new_lst, 0, 0, length)
     return new_lst
+# no oopspec -- the function is inlined by the JIT
 
 def ll_len(l):
     return l.ll_length()
@@ -551,6 +554,7 @@
 def ll_list_is_true(l):
     # check if a list is True, allowing for None
     return bool(l) and l.ll_length() != 0
+# no oopspec -- the function is inlined by the JIT
 
 def ll_len_foldable(l):
     return l.ll_length()
@@ -558,6 +562,7 @@
 
 def ll_list_is_true_foldable(l):
     return bool(l) and ll_len_foldable(l) != 0
+# no oopspec -- the function is inlined by the JIT
 
 def ll_append(l, newitem):
     length = l.ll_length()
@@ -588,6 +593,7 @@
     ll_arraycopy(l1, l, 0, 0, len1)
     ll_arraycopy(l2, l, 0, len1, len2)
     return l
+# no oopspec -- the function is inlined by the JIT
 
 def ll_insert_nonneg(l, index, newitem):
     length = l.ll_length()
@@ -674,60 +680,72 @@
         l.ll_setitem_fast(length_1_i, tmp)
         i += 1
         length_1_i -= 1
+ll_reverse.oopspec = 'list.reverse(l)'
 
 def ll_getitem_nonneg(func, l, index):
     ll_assert(index >= 0, "unexpectedly negative list getitem index")
     if func is dum_checkidx:
         if index >= l.ll_length():
             raise IndexError
-    else:
-        ll_assert(index < l.ll_length(), "list getitem index out of bound")
     return l.ll_getitem_fast(index)
-ll_getitem_nonneg.oopspec = 'list.getitem(l, index)'
+ll_getitem_nonneg._always_inline_ = True
+# no oopspec -- the function is inlined by the JIT
 
 def ll_getitem(func, l, index):
-    length = l.ll_length()
-    if index < 0:
-        index += length
     if func is dum_checkidx:
-        if index < 0 or index >= length:
-            raise IndexError
+        length = l.ll_length()    # common case: 0 <= index < length
+        if r_uint(index) >= r_uint(length):
+            # Failed, so either (-length <= index < 0), or we have to raise
+            # IndexError.  First add 'length' to get the final index, then
+            # check that we now have (0 <= index < length).
+            index = r_uint(index) + r_uint(length)
+            if index >= r_uint(length):
+                raise IndexError
+            index = intmask(index)
     else:
-        ll_assert(index >= 0, "negative list getitem index out of bound")
-        ll_assert(index < length, "list getitem index out of bound")
+        # We don't want checking, but still want to support index < 0.
+        # Only call ll_length() if needed.
+        if index < 0:
+            index += l.ll_length()
+            ll_assert(index >= 0, "negative list getitem index out of bound")
     return l.ll_getitem_fast(index)
-ll_getitem.oopspec = 'list.getitem(l, index)'
+# no oopspec -- the function is inlined by the JIT
 
-def ll_getitem_foldable_nonneg(func, l, index):
-    return ll_getitem_nonneg(func, l, index)
+def ll_getitem_foldable_nonneg(l, index):
+    ll_assert(index >= 0, "unexpectedly negative list getitem index")
+    return l.ll_getitem_fast(index)
 ll_getitem_foldable_nonneg.oopspec = 'list.getitem_foldable(l, index)'
 
-def ll_getitem_foldable(func, l, index):
-    return ll_getitem(func, l, index)
-ll_getitem_foldable.oopspec = 'list.getitem_foldable(l, index)'
+def ll_getitem_foldable(l, index):
+    if index < 0:
+        index += l.ll_length()
+    return ll_getitem_foldable_nonneg(l, index)
+ll_getitem_foldable._always_inline_ = True
+# no oopspec -- the function is inlined by the JIT
 
 def ll_setitem_nonneg(func, l, index, newitem):
     ll_assert(index >= 0, "unexpectedly negative list setitem index")
     if func is dum_checkidx:
         if index >= l.ll_length():
             raise IndexError
-    else:
-        ll_assert(index < l.ll_length(), "list setitem index out of bound")
     l.ll_setitem_fast(index, newitem)
-ll_setitem_nonneg.oopspec = 'list.setitem(l, index, newitem)'
+ll_setitem_nonneg._always_inline_ = True
+# no oopspec -- the function is inlined by the JIT
 
 def ll_setitem(func, l, index, newitem):
-    length = l.ll_length()
-    if index < 0:
-        index += length
     if func is dum_checkidx:
-        if index < 0 or index >= length:
-            raise IndexError
+        length = l.ll_length()
+        if r_uint(index) >= r_uint(length):   # see comments in ll_getitem().
+            index = r_uint(index) + r_uint(length)
+            if index >= r_uint(length):
+                raise IndexError
+            index = intmask(index)
     else:
-        ll_assert(index >= 0, "negative list setitem index out of bound")
-        ll_assert(index < length, "list setitem index out of bound")
+        if index < 0:
+            index += l.ll_length()
+            ll_assert(index >= 0, "negative list setitem index out of bound")
     l.ll_setitem_fast(index, newitem)
-ll_setitem.oopspec = 'list.setitem(l, index, newitem)'
+# no oopspec -- the function is inlined by the JIT
 
 def ll_delitem_nonneg(func, l, index):
     ll_assert(index >= 0, "unexpectedly negative list delitem index")
@@ -751,19 +769,20 @@
     l._ll_resize_le(newlength)
 ll_delitem_nonneg.oopspec = 'list.delitem(l, index)'
 
-def ll_delitem(func, l, i):
-    length = l.ll_length()
-    if i < 0:
-        i += length
+def ll_delitem(func, l, index):
     if func is dum_checkidx:
-        if i < 0 or i >= length:
-            raise IndexError
+        length = l.ll_length()
+        if r_uint(index) >= r_uint(length):   # see comments in ll_getitem().
+            index = r_uint(index) + r_uint(length)
+            if index >= r_uint(length):
+                raise IndexError
+            index = intmask(index)
     else:
-        ll_assert(i >= 0, "negative list delitem index out of bound")
-        ll_assert(i < length, "list delitem index out of bound")
-    ll_delitem_nonneg(dum_nocheck, l, i)
-ll_delitem.oopspec = 'list.delitem(l, i)'
-
+        if index < 0:
+            index += l.ll_length()
+            ll_assert(index >= 0, "negative list delitem index out of bound")
+    ll_delitem_nonneg(dum_nocheck, l, index)
+# no oopspec -- the function is inlined by the JIT
 
 def ll_extend(l1, l2):
     len1 = l1.ll_length()
@@ -799,6 +818,7 @@
         lst.ll_setitem_fast(j, c)
         i += 1
         j += 1
+# not inlined by the JIT -- contains a loop
 
 def ll_extend_with_str_slice_startstop(lst, s, getstrlen, getstritem,
                                        start, stop):
@@ -824,6 +844,7 @@
         lst.ll_setitem_fast(j, c)
         i += 1
         j += 1
+# not inlined by the JIT -- contains a loop
 
 def ll_extend_with_str_slice_minusone(lst, s, getstrlen, getstritem):
     len1 = lst.ll_length()
@@ -843,6 +864,7 @@
         lst.ll_setitem_fast(j, c)
         i += 1
         j += 1
+# not inlined by the JIT -- contains a loop
 
 def ll_extend_with_char_count(lst, char, count):
     if count <= 0:
@@ -859,6 +881,7 @@
     while j < newlength:
         lst.ll_setitem_fast(j, char)
         j += 1
+# not inlined by the JIT -- contains a loop
 
 def ll_listslice_startonly(RESLIST, l1, start):
     len1 = l1.ll_length()
@@ -869,6 +892,7 @@
     ll_arraycopy(l1, l, start, 0, newlength)
     return l
 ll_listslice_startonly._annenforceargs_ = (None, None, int)
+# no oopspec -- the function is inlined by the JIT
 
 def ll_listslice_startstop(RESLIST, l1, start, stop):
     length = l1.ll_length()
@@ -881,6 +905,7 @@
     l = RESLIST.ll_newlist(newlength)
     ll_arraycopy(l1, l, start, 0, newlength)
     return l
+# no oopspec -- the function is inlined by the JIT
 
 def ll_listslice_minusone(RESLIST, l1):
     newlength = l1.ll_length() - 1
@@ -888,6 +913,7 @@
     l = RESLIST.ll_newlist(newlength)
     ll_arraycopy(l1, l, 0, 0, newlength)
     return l
+# no oopspec -- the function is inlined by the JIT
 
 def ll_listdelslice_startonly(l, start):
     ll_assert(start >= 0, "del l[start:] with unexpectedly negative start")
@@ -958,6 +984,7 @@
                 return False
         j += 1
     return True
+# not inlined by the JIT -- contains a loop
 
 def ll_listcontains(lst, obj, eqfn):
     lng = lst.ll_length()
@@ -971,6 +998,7 @@
                 return True
         j += 1
     return False
+# not inlined by the JIT -- contains a loop
 
 def ll_listindex(lst, obj, eqfn):
     lng = lst.ll_length()
@@ -984,6 +1012,7 @@
                 return j
         j += 1
     raise ValueError # can't say 'list.index(x): x not in list'
+# not inlined by the JIT -- contains a loop
 
 def ll_listremove(lst, obj, eqfn):
     index = ll_listindex(lst, obj, eqfn) # raises ValueError if obj not in lst
@@ -1030,3 +1059,4 @@
             i += 1
         j += length
     return res
+# not inlined by the JIT -- contains a loop

Modified: pypy/branch/jitypes2/pypy/rpython/rpbc.py
==============================================================================
--- pypy/branch/jitypes2/pypy/rpython/rpbc.py	(original)
+++ pypy/branch/jitypes2/pypy/rpython/rpbc.py	Fri Dec  3 11:04:29 2010
@@ -15,11 +15,10 @@
 
 from pypy.rpython import callparse
 
-
 def small_cand(rtyper, s_pbc):
     if 1 < len(s_pbc.descriptions) < rtyper.getconfig().translation.withsmallfuncsets and \
            hasattr(rtyper.type_system.rpbc, 'SmallFunctionSetPBCRepr'):
-        callfamily = s_pbc.descriptions.iterkeys().next().getcallfamily()
+        callfamily = s_pbc.any_description().getcallfamily()
         concretetable, uniquerows = get_concrete_calltable(rtyper, callfamily)
         if len(uniquerows) == 1 and (not s_pbc.subset_of or small_cand(rtyper, s_pbc.subset_of)):
             return True
@@ -31,7 +30,7 @@
             return none_frozen_pbc_repr 
         kind = self.getKind()
         if issubclass(kind, description.FunctionDesc):
-            sample = self.descriptions.keys()[0]
+            sample = self.any_description()
             callfamily = sample.querycallfamily()
             if callfamily and callfamily.total_calltable_size > 0:
                 if sample.overridden:
@@ -181,7 +180,7 @@
     def __init__(self, rtyper, s_pbc):
         self.rtyper = rtyper
         self.s_pbc = s_pbc
-        self.callfamily = s_pbc.descriptions.iterkeys().next().getcallfamily()
+        self.callfamily = s_pbc.any_description().getcallfamily()
         if len(s_pbc.descriptions) == 1 and not s_pbc.can_be_None:
             # a single function
             self.lowleveltype = Void
@@ -207,7 +206,7 @@
         return self, 0
 
     def get_s_signatures(self, shape):
-        funcdesc = self.s_pbc.descriptions.iterkeys().next()
+        funcdesc = self.s_pbc.any_description()
         return funcdesc.get_s_signatures(shape)
 
 ##    def function_signatures(self):
@@ -322,7 +321,7 @@
         bk = self.rtyper.annotator.bookkeeper
         args = bk.build_args(opname, hop.args_s[1:])
         s_pbc = hop.args_s[0]   # possibly more precise than self.s_pbc
-        descs = s_pbc.descriptions.keys()
+        descs = list(s_pbc.descriptions)
         shape, index = description.FunctionDesc.variant_for_call_site(bk, self.callfamily, descs, args)
         row_of_graphs = self.callfamily.calltables[shape][index]
         anygraph = row_of_graphs.itervalues().next()  # pick any witness
@@ -368,7 +367,7 @@
     return robject.pyobj_repr
 
 def getFrozenPBCRepr(rtyper, s_pbc):
-    descs = s_pbc.descriptions.keys()
+    descs = list(s_pbc.descriptions)
     assert len(descs) >= 1
     if len(descs) == 1 and not s_pbc.can_be_None:
         return SingleFrozenPBCRepr(descs[0])
@@ -530,7 +529,7 @@
 
     def __init__(self, rtyper, s_pbc):
         self.rtyper = rtyper
-        self.funcdesc = s_pbc.descriptions.keys()[0].funcdesc
+        self.funcdesc = s_pbc.any_description().funcdesc
 
         # a hack to force the underlying function to show up in call_families
         # (generally not needed, as normalizecalls() should ensure this,
@@ -662,7 +661,7 @@
         and the ClassRepr of the class which stores this attribute in
         its vtable.
         """
-        classdescs = self.s_pbc.descriptions.keys()
+        classdescs = list(self.s_pbc.descriptions)
         access = classdescs[0].queryattrfamily(attrname)
         for classdesc in classdescs[1:]:
             access1 = classdesc.queryattrfamily(attrname)
@@ -819,7 +818,7 @@
         if s_pbc.isNone():
             raise TyperError("unsupported: variable of type "
                              "bound-method-object or None")
-        mdescs = s_pbc.descriptions.keys()
+        mdescs = list(s_pbc.descriptions)
         methodname = mdescs[0].name
         classdef = mdescs[0].selfclassdef
         flags    = mdescs[0].flags

Modified: pypy/branch/jitypes2/pypy/rpython/test/test_rclass.py
==============================================================================
--- pypy/branch/jitypes2/pypy/rpython/test/test_rclass.py	(original)
+++ pypy/branch/jitypes2/pypy/rpython/test/test_rclass.py	Fri Dec  3 11:04:29 2010
@@ -917,6 +917,7 @@
         assert destrptr is not None
     
     def test_del_inheritance(self):
+        from pypy.rlib import rgc
         class State:
             pass
         s = State()
@@ -937,6 +938,7 @@
             A()
             B()
             C()
+            rgc.collect()
             return s.a_dels * 10 + s.b_dels
         res = f()
         assert res == 42
@@ -1067,6 +1069,7 @@
         assert meth.finalizer
 
     def test_del_inheritance(self):
+        from pypy.rlib import rgc
         class State:
             pass
         s = State()
@@ -1087,6 +1090,7 @@
             A()
             B()
             C()
+            rgc.collect()
             return s.a_dels * 10 + s.b_dels
         res = f()
         assert res == 42

Modified: pypy/branch/jitypes2/pypy/rpython/test/test_rint.py
==============================================================================
--- pypy/branch/jitypes2/pypy/rpython/test/test_rint.py	(original)
+++ pypy/branch/jitypes2/pypy/rpython/test/test_rint.py	Fri Dec  3 11:04:29 2010
@@ -4,14 +4,9 @@
 from pypy.annotation import model as annmodel
 from pypy.rpython.test import snippet
 from pypy.rlib.rarithmetic import r_int, r_uint, r_longlong, r_ulonglong
-from pypy.rlib.rarithmetic import ovfcheck
+from pypy.rlib.rarithmetic import ovfcheck, r_int64
 from pypy.rpython.test.tool import BaseRtypingTest, LLRtypeMixin, OORtypeMixin
 
-if r_longlong is not r_int:
-    int64 = r_longlong
-else:
-    int64 = int
-
 
 class TestSnippet(object):
 
@@ -110,10 +105,10 @@
         def f(i):
             return str(i)
 
-        res = self.interpret(f, [int64(0)])
+        res = self.interpret(f, [r_int64(0)])
         assert self.ll_to_string(res) == '0'
 
-        res = self.interpret(f, [int64(413974738222117)])
+        res = self.interpret(f, [r_int64(413974738222117)])
         assert self.ll_to_string(res) == '413974738222117'
 
     def test_unsigned(self):
@@ -135,7 +130,7 @@
         f._annspecialcase_ = "specialize:argtype(0)"
         def g(n):
             if n > 0:
-                return f(int64(0))
+                return f(r_int64(0))
             else:
                 return f(0)
         res = self.interpret(g, [0])
@@ -147,7 +142,7 @@
     def test_downcast_int(self):
         def f(i):
             return int(i)
-        res = self.interpret(f, [int64(0)])
+        res = self.interpret(f, [r_int64(0)])
         assert res == 0
 
     def test_isinstance_vs_int_types(self):
@@ -157,7 +152,7 @@
                     return [None]
                 if isinstance(x, str):
                     return x
-                if isinstance(x, int64):
+                if isinstance(x, r_int64):
                     return int(x)
                 return "XXX"
             wrap._annspecialcase_ = 'specialize:argtype(0)'
@@ -165,7 +160,7 @@
         space = FakeSpace()
         def wrap(x):
             return space.wrap(x)
-        res = self.interpret(wrap, [int64(0)])
+        res = self.interpret(wrap, [r_int64(0)])
         assert res == 0
 
     def test_truediv(self):
@@ -178,25 +173,25 @@
     def test_float_conversion(self):
         def f(ii):
             return float(ii)
-        res = self.interpret(f, [int64(100000000)])
+        res = self.interpret(f, [r_int64(100000000)])
         assert type(res) is float
         assert res == 100000000.
-        res = self.interpret(f, [int64(1234567890123456789)])
+        res = self.interpret(f, [r_int64(1234567890123456789)])
         assert type(res) is float
         assert self.float_eq(res, 1.2345678901234568e+18)
 
     def test_float_conversion_implicit(self):
         def f(ii):
             return 1.0 + ii
-        res = self.interpret(f, [int64(100000000)])
+        res = self.interpret(f, [r_int64(100000000)])
         assert type(res) is float
         assert res == 100000001.
-        res = self.interpret(f, [int64(1234567890123456789)])
+        res = self.interpret(f, [r_int64(1234567890123456789)])
         assert type(res) is float
         assert self.float_eq(res, 1.2345678901234568e+18)
 
     def test_rarithmetic(self):
-        inttypes = [int, r_uint, int64, r_ulonglong]
+        inttypes = [int, r_uint, r_int64, r_ulonglong]
         for inttype in inttypes:
             c = inttype()
             def f():
@@ -231,16 +226,16 @@
             res = self.interpret(f, [int(-1<<(r_int.BITS-1))])
             assert res == 0
 
-            res = self.interpret(f, [int64(-1)])
+            res = self.interpret(f, [r_int64(-1)])
             assert res == 1
-            res = self.interpret(f, [int64(-1)<<(r_longlong.BITS-1)])
+            res = self.interpret(f, [r_int64(-1)<<(r_longlong.BITS-1)])
             assert res == 0
 
     div_mod_iteration_count = 1000
     def test_div_mod(self):
         import random
 
-        for inttype in (int, int64):
+        for inttype in (int, r_int64):
 
             def d(x, y):
                 return x/y
@@ -303,7 +298,7 @@
             except ZeroDivisionError:
                 return 84
 
-        for inttype in (int, int64):
+        for inttype in (int, r_int64):
 
             args = [( 5, 2), (-5, 2), ( 5,-2), (-5,-2),
                     ( 6, 2), (-6, 2), ( 6,-2), (-6,-2),

Modified: pypy/branch/jitypes2/pypy/rpython/test/test_rlist.py
==============================================================================
--- pypy/branch/jitypes2/pypy/rpython/test/test_rlist.py	(original)
+++ pypy/branch/jitypes2/pypy/rpython/test/test_rlist.py	Fri Dec  3 11:04:29 2010
@@ -12,6 +12,7 @@
 from pypy.rpython.rint import signed_repr
 from pypy.objspace.flow.model import Constant, Variable
 from pypy.rpython.test.tool import BaseRtypingTest, LLRtypeMixin, OORtypeMixin
+from pypy.rlib.debug import ll_assert
 
 # undo the specialization parameter
 for n1 in 'get set del'.split():
@@ -1076,7 +1077,13 @@
 
         res = self.interpret(f, [0])
         assert res == 1
-        py.test.raises(AssertionError, self.interpret, f, [1])
+        if self.type_system == 'lltype':
+            # on lltype we always get an AssertionError
+            py.test.raises(AssertionError, self.interpret, f, [1])
+        else:
+            # on ootype we happen to get through the ll_asserts and to
+            # hit the IndexError from ootype.py
+            self.interpret_raises(IndexError, f, [1])
 
         def f(x):
             l = [1]
@@ -1121,12 +1128,13 @@
 
         res = self.interpret(f, [0])
         assert res == 1
-        try:
-            self.interpret_raises(IndexError, f, [1])
-        except (AssertionError,), e:
-            pass
+        if self.type_system == 'lltype':
+            # on lltype we always get an AssertionError
+            py.test.raises(AssertionError, self.interpret, f, [1])
         else:
-            assert False
+            # on ootype we happen to get through the ll_asserts and to
+            # hit the IndexError from ootype.py
+            self.interpret_raises(IndexError, f, [1])
 
         def f(x):
             l = [1]
@@ -1163,12 +1171,13 @@
 
         res = self.interpret(f, [0])
         assert res == 1
-        try:
-            self.interpret_raises(IndexError, f, [1])
-        except (AssertionError,), e:
-            pass
+        if self.type_system == 'lltype':
+            # on lltype we always get an AssertionError
+            py.test.raises(AssertionError, self.interpret, f, [1])
         else:
-            assert False
+            # on ootype we happen to get through the ll_asserts and to
+            # hit the IndexError from ootype.py
+            self.interpret_raises(IndexError, f, [1])
 
     def test_charlist_extension_1(self):
         def f(n):
@@ -1327,8 +1336,32 @@
         res = self.interpret(f, [2])
         assert res == True
 
+    def test_immutable_list_out_of_instance(self):
+        from pypy.translator.simplify import get_funcobj
+        for immutable_fields in (["a", "b"], ["a", "b", "y[*]"]):
+            class A(object):
+                _immutable_fields_ = immutable_fields
+            class B(A):
+                pass
+            def f(i):
+                b = B()
+                lst = [i]
+                lst[0] += 1
+                b.y = lst
+                ll_assert(b.y is lst, "copying when reading out the attr?")
+                return b.y[0]
+            res = self.interpret(f, [10])
+            assert res == 11
+            t, rtyper, graph = self.gengraph(f, [int])
+            block = graph.startblock
+            op = block.operations[-1]
+            assert op.opname == 'direct_call'
+            func = get_funcobj(op.args[0].value)._callable
+            assert ('foldable' in func.func_name) == \
+                   ("y[*]" in immutable_fields)
 
 class TestLLtype(BaseTestRlist, LLRtypeMixin):
+    type_system = 'lltype'
     rlist = ll_rlist
 
     def test_memoryerror(self):
@@ -1420,14 +1453,16 @@
             lst2 = [i]
             lst2.append(42)    # mutated list
             return lst1[i] + lst2[i]
-        _, _, graph = self.gengraph(f, [int])
+        from pypy.annotation import model as annmodel
+        _, _, graph = self.gengraph(f, [annmodel.SomeInteger(nonneg=True)])
         block = graph.startblock
         lst1_getitem_op = block.operations[-3]     # XXX graph fishing
         lst2_getitem_op = block.operations[-2]
         func1 = lst1_getitem_op.args[0].value._obj._callable
         func2 = lst2_getitem_op.args[0].value._obj._callable
         assert func1.oopspec == 'list.getitem_foldable(l, index)'
-        assert func2.oopspec == 'list.getitem(l, index)'
+        assert not hasattr(func2, 'oopspec')
 
 class TestOOtype(BaseTestRlist, OORtypeMixin):
     rlist = oo_rlist
+    type_system = 'ootype'

Modified: pypy/branch/jitypes2/pypy/rpython/tool/rffi_platform.py
==============================================================================
--- pypy/branch/jitypes2/pypy/rpython/tool/rffi_platform.py	(original)
+++ pypy/branch/jitypes2/pypy/rpython/tool/rffi_platform.py	Fri Dec  3 11:04:29 2010
@@ -639,6 +639,7 @@
 C_HEADER = """
 #include <stdio.h>
 #include <stddef.h>   /* for offsetof() */
+#include <stdint.h>   /* FreeBSD: for uint64_t */
 
 void dump(char* key, int value) {
     printf("%s: %d\\n", key, value);

Modified: pypy/branch/jitypes2/pypy/tool/ansi_print.py
==============================================================================
--- pypy/branch/jitypes2/pypy/tool/ansi_print.py	(original)
+++ pypy/branch/jitypes2/pypy/tool/ansi_print.py	Fri Dec  3 11:04:29 2010
@@ -16,6 +16,7 @@
         'WARNING': ((31,), False),
         'event': ((1,), True),
         'ERROR': ((1, 31), False),
+        'Error': ((1, 31), False),
         'info': ((35,), False),
         'stub': ((34,), False),
     }

Modified: pypy/branch/jitypes2/pypy/tool/logparser.py
==============================================================================
--- pypy/branch/jitypes2/pypy/tool/logparser.py	(original)
+++ pypy/branch/jitypes2/pypy/tool/logparser.py	Fri Dec  3 11:04:29 2010
@@ -12,14 +12,6 @@
 from pypy.tool import progressbar
 
 def parse_log_file(filename, verbose=True):
-    r_start = re.compile(r"\[([0-9a-fA-F]+)\] \{([\w-]+)$")
-    r_stop  = re.compile(r"\[([0-9a-fA-F]+)\] ([\w-]+)\}$")
-    lasttime = 0
-    log = DebugLog()
-    time_decrase = False
-    performance_log = True
-    nested = 0
-    #
     f = open(filename, 'r')
     if f.read(2) == 'BZ':
         f.close()
@@ -30,19 +22,33 @@
     lines = f.readlines()
     f.close()
     #
-    if sys.stdout.isatty():
+    return parse_log(lines, verbose=verbose)
+
+def parse_log(lines, verbose=False):
+    color = "(?:\x1b.*?m)?"
+    r_start = re.compile(color + r"\[([0-9a-fA-F]+)\] \{([\w-]+)" + color + "$")
+    r_stop  = re.compile(color + r"\[([0-9a-fA-F]+)\] ([\w-]+)\}" + color + "$")
+    lasttime = 0
+    log = DebugLog()
+    time_decrase = False
+    performance_log = True
+    nested = 0
+    #
+    if verbose and sys.stdout.isatty():
         progress = progressbar.ProgressBar(color='green')
+        counter = 0
+    else:
+        progress = None
     single_percent = len(lines) / 100
     if verbose:
-        vnext = single_percent
+        vnext = 0
     else:
-        vnext = len(lines)
-    counter = 0
+        vnext = -1
     for i, line in enumerate(lines):
         if i == vnext:
-            counter += 1
-            if sys.stdout.isatty():
+            if progress is not None:
                 progress.render(counter)
+                counter += 1
                 vnext += single_percent
             else:
                 sys.stderr.write('%d%%..' % int(100.0*i/len(lines)))

Modified: pypy/branch/jitypes2/pypy/translator/c/funcgen.py
==============================================================================
--- pypy/branch/jitypes2/pypy/translator/c/funcgen.py	(original)
+++ pypy/branch/jitypes2/pypy/translator/c/funcgen.py	Fri Dec  3 11:04:29 2010
@@ -1,3 +1,4 @@
+import sys
 from pypy.translator.c.support import USESLOTS # set to False if necessary while refactoring
 from pypy.translator.c.support import cdecl
 from pypy.translator.c.support import llvalue_from_constant, gen_assignments
@@ -757,6 +758,16 @@
                 format.append('%s')
                 argv.append('(%s) ? "True" : "False"' % self.expr(arg))
                 continue
+            elif T == SignedLongLong:
+                if sys.platform == 'win32':
+                    format.append('%I64d')
+                else:
+                    format.append('%lld')
+            elif T == UnsignedLongLong:
+                if sys.platform == 'win32':
+                    format.append('%I64u')
+                else:
+                    format.append('%llu')
             else:
                 raise Exception("don't know how to debug_print %r" % (T,))
             argv.append(self.expr(arg))
@@ -765,17 +776,20 @@
             "if (PYPY_HAVE_DEBUG_PRINTS) { fprintf(PYPY_DEBUG_FILE, %s); %s}"
             % (', '.join(argv), free_line))
 
+    def _op_debug(self, opname, arg):
+        if isinstance(arg, Constant):
+            string_literal = c_string_constant(''.join(arg.value.chars))
+            return "%s(%s);" % (opname, string_literal)
+        else:
+            x = "%s(RPyString_AsCharP(%s));\n" % (opname, self.expr(arg))
+            x += "RPyString_FreeCache();"
+            return x
+
     def OP_DEBUG_START(self, op):
-        arg = op.args[0]
-        assert isinstance(arg, Constant)
-        return "PYPY_DEBUG_START(%s);" % (
-            c_string_constant(''.join(arg.value.chars)),)
+        return self._op_debug('PYPY_DEBUG_START', op.args[0])
 
     def OP_DEBUG_STOP(self, op):
-        arg = op.args[0]
-        assert isinstance(arg, Constant)
-        return "PYPY_DEBUG_STOP(%s);" % (
-            c_string_constant(''.join(arg.value.chars)),)
+        return self._op_debug('PYPY_DEBUG_STOP', op.args[0])
 
     def OP_DEBUG_ASSERT(self, op):
         return 'RPyAssert(%s, %s);' % (self.expr(op.args[0]),

Modified: pypy/branch/jitypes2/pypy/translator/c/gcc/trackgcroot.py
==============================================================================
--- pypy/branch/jitypes2/pypy/translator/c/gcc/trackgcroot.py	(original)
+++ pypy/branch/jitypes2/pypy/translator/c/gcc/trackgcroot.py	Fri Dec  3 11:04:29 2010
@@ -1106,7 +1106,7 @@
     format = 'darwin64'
     function_names_prefix = '_'
 
-    LABEL = ElfFunctionGcRootTracker32.LABEL
+    LABEL = ElfFunctionGcRootTracker64.LABEL
     r_jmptable_item = re.compile(r"\t.(?:long|quad)\t"+LABEL+"(-\"?[A-Za-z0-9$]+\"?)?\s*$")
 
     r_functionstart = re.compile(r"_(\w+):\s*$")

Modified: pypy/branch/jitypes2/pypy/translator/c/src/debug_alloc.h
==============================================================================
--- pypy/branch/jitypes2/pypy/translator/c/src/debug_alloc.h	(original)
+++ pypy/branch/jitypes2/pypy/translator/c/src/debug_alloc.h	Fri Dec  3 11:04:29 2010
@@ -1,5 +1,5 @@
 /**************************************************************/
- /***  tracking raw mallocs and frees for debugging          ***/
+/***  tracking raw mallocs and frees for debugging          ***/
 
 #ifndef RPY_ASSERT
 
@@ -62,8 +62,8 @@
     count++;
   if (count > 0)
     {
-      fprintf(stderr, "debug_alloc.h: %ld mallocs left", count);
       char *env = getenv("PYPY_ALLOC");
+      fprintf(stderr, "debug_alloc.h: %ld mallocs left", count);
       if (env && *env)
         {
           fprintf(stderr, " (most recent first):\n");

Modified: pypy/branch/jitypes2/pypy/translator/c/src/debug_print.h
==============================================================================
--- pypy/branch/jitypes2/pypy/translator/c/src/debug_print.h	(original)
+++ pypy/branch/jitypes2/pypy/translator/c/src/debug_print.h	Fri Dec  3 11:04:29 2010
@@ -72,7 +72,11 @@
 {
   char *filename = getenv("PYPYLOG");
   if (filename)
+#ifndef MS_WINDOWS
     unsetenv("PYPYLOG");   /* don't pass it to subprocesses */
+#else
+    putenv("PYPYLOG=");    /* don't pass it to subprocesses */
+#endif
   if (filename && filename[0])
     {
       char *colon = strchr(filename, ':');

Modified: pypy/branch/jitypes2/pypy/translator/c/src/mem.h
==============================================================================
--- pypy/branch/jitypes2/pypy/translator/c/src/mem.h	(original)
+++ pypy/branch/jitypes2/pypy/translator/c/src/mem.h	Fri Dec  3 11:04:29 2010
@@ -233,4 +233,4 @@
 #define OP_GC_GET_RPY_MEMORY_USAGE(x, r) r = -1
 #define OP_GC_GET_RPY_TYPE_INDEX(x, r)   r = -1
 #define OP_GC_IS_RPY_INSTANCE(x, r)      r = 0
-#define OP_GC_DUMP_RPY_HEAP(r)           r = 0
+#define OP_GC_DUMP_RPY_HEAP(fd, r)       r = 0

Modified: pypy/branch/jitypes2/pypy/translator/c/test/test_newgc.py
==============================================================================
--- pypy/branch/jitypes2/pypy/translator/c/test/test_newgc.py	(original)
+++ pypy/branch/jitypes2/pypy/translator/c/test/test_newgc.py	Fri Dec  3 11:04:29 2010
@@ -1064,14 +1064,16 @@
     def test_get_rpy_type_index(self):
         self.run("get_rpy_type_index")
 
-    filename_dump = str(udir.join('test_dump_rpy_heap'))
+    filename1_dump = str(udir.join('test_dump_rpy_heap.1'))
+    filename2_dump = str(udir.join('test_dump_rpy_heap.2'))
     def define_dump_rpy_heap(self):
         U = lltype.GcForwardReference()
         U.become(lltype.GcStruct('U', ('next', lltype.Ptr(U)),
                                  ('x', lltype.Signed)))
         S = lltype.GcStruct('S', ('u', lltype.Ptr(U)))
         A = lltype.GcArray(lltype.Ptr(S))
-        filename = self.filename_dump
+        filename1 = self.filename1_dump
+        filename2 = self.filename2_dump
 
         def fn():
             s = lltype.malloc(S)
@@ -1081,20 +1083,31 @@
             a = lltype.malloc(A, 1000)
             s2 = lltype.malloc(S)
             #
-            fd = os.open(filename, os.O_WRONLY | os.O_CREAT, 0666)
-            rgc.dump_rpy_heap(fd)
+            fd1 = os.open(filename1, os.O_WRONLY | os.O_CREAT, 0666)
+            fd2 = os.open(filename2, os.O_WRONLY | os.O_CREAT, 0666)
+            rgc.dump_rpy_heap(fd1)
+            rgc.dump_rpy_heap(fd2)      # try twice in a row
             keepalive_until_here(s2)
             keepalive_until_here(s)
             keepalive_until_here(a)
-            os.close(fd)
+            os.close(fd1)
+            os.close(fd2)
             return 0
 
         return fn
 
     def test_dump_rpy_heap(self):
         self.run("dump_rpy_heap")
-        assert os.path.exists(self.filename_dump)
-        assert os.path.getsize(self.filename_dump) > 64
+        for fn in [self.filename1_dump, self.filename2_dump]:
+            assert os.path.exists(fn)
+            assert os.path.getsize(fn) > 64
+        f = open(self.filename1_dump)
+        data1 = f.read()
+        f.close()
+        f = open(self.filename2_dump)
+        data2 = f.read()
+        f.close()
+        assert data1 == data2
 
     filename_dump_typeids_z = str(udir.join('test_typeids_z'))
     def define_write_typeids_z(self):

Modified: pypy/branch/jitypes2/pypy/translator/c/test/test_standalone.py
==============================================================================
--- pypy/branch/jitypes2/pypy/translator/c/test/test_standalone.py	(original)
+++ pypy/branch/jitypes2/pypy/translator/c/test/test_standalone.py	Fri Dec  3 11:04:29 2010
@@ -272,7 +272,7 @@
             x = "got:"
             debug_start  ("mycat")
             if have_debug_prints(): x += "b"
-            debug_print    ("foo", 2, "bar", 3)
+            debug_print    ("foo", r_longlong(2), "bar", 3)
             debug_start      ("cat2")
             if have_debug_prints(): x += "c"
             debug_print        ("baz")
@@ -403,6 +403,20 @@
         assert not err
         assert path.check(file=0)
 
+    def test_debug_print_start_stop_nonconst(self):
+        def entry_point(argv):
+            debug_start(argv[1])
+            debug_print(argv[2])
+            debug_stop(argv[1])
+            return 0
+        t, cbuilder = self.compile(entry_point)
+        out, err = cbuilder.cmdexec("foo bar", err=True, env={'PYPYLOG': ':-'})
+        lines = err.splitlines()
+        assert '{foo' in lines[0]
+        assert 'bar' == lines[1]
+        assert 'foo}' in lines[2]
+
+
     def test_fatal_error(self):
         def g(x):
             if x == 1:

Modified: pypy/branch/jitypes2/pypy/translator/driver.py
==============================================================================
--- pypy/branch/jitypes2/pypy/translator/driver.py	(original)
+++ pypy/branch/jitypes2/pypy/translator/driver.py	Fri Dec  3 11:04:29 2010
@@ -11,7 +11,7 @@
 from pypy.annotation import policy as annpolicy
 import optparse
 from pypy.tool.udir import udir
-from pypy.rlib.jit import DEBUG_OFF, DEBUG_DETAILED, DEBUG_PROFILE, DEBUG_STEPS
+from pypy.tool.debug_print import debug_start, debug_print, debug_stop
 from pypy.rlib.entrypoint import secondary_entrypoints
 
 import py
@@ -37,13 +37,6 @@
     'c': 'lltype',
 }
 
-JIT_DEBUG = {
-    'off' : DEBUG_OFF,
-    'profile' : DEBUG_PROFILE,
-    'steps' : DEBUG_STEPS,
-    'detailed' : DEBUG_DETAILED,
-}
-
 def backend_to_typesystem(backend):
     return _BACKEND_TO_TYPESYSTEM.get(backend, 'ootype')
 
@@ -283,6 +276,8 @@
             return
         else:
             self.log.info("%s..." % title)
+        debug_start('translation-task')
+        debug_print('starting', goal)
         self.timer.start_event(goal)
         try:
             instrument = False
@@ -300,11 +295,13 @@
                 assert False, 'we should not get here'
         finally:
             try:
+                debug_stop('translation-task')
                 self.timer.end_event(goal)
             except (KeyboardInterrupt, SystemExit):
                 raise
             except:
                 pass
+        #import gc; gc.dump_rpy_heap('rpyheap-after-%s.dump' % goal)
         return res
 
     def task_annotate(self):
@@ -399,7 +396,6 @@
         #
         from pypy.jit.metainterp.warmspot import apply_jit
         apply_jit(self.translator, policy=self.jitpolicy,
-                  debug_level=JIT_DEBUG[self.config.translation.jit_debug],
                   backend_name=self.config.translation.jit_backend, inline=True)
         #
         self.log.info("the JIT compiler was generated")
@@ -417,7 +413,6 @@
         #
         from pypy.jit.metainterp.warmspot import apply_jit
         apply_jit(self.translator, policy=self.jitpolicy,
-                  debug_level=JIT_DEBUG[self.config.translation.jit_debug],
                   backend_name='cli', inline=True) #XXX
         #
         self.log.info("the JIT compiler was generated")

Modified: pypy/branch/jitypes2/pypy/translator/goal/app_main.py
==============================================================================
--- pypy/branch/jitypes2/pypy/translator/goal/app_main.py	(original)
+++ pypy/branch/jitypes2/pypy/translator/goal/app_main.py	Fri Dec  3 11:04:29 2010
@@ -11,6 +11,7 @@
   -h, --help     show this help message and exit
   -m             library module to be run as a script (terminates option list)
   -W arg         warning control (arg is action:message:category:module:lineno)
+  -E             ignore environment variables (such as PYTHONPATH)
   --version      print the PyPy version
   --info         print translation information about this PyPy executable
 """
@@ -199,7 +200,7 @@
         break      # found!
     return newpath
 
-def setup_initial_paths(executable, nanos):
+def setup_initial_paths(executable, nanos, readenv=True, **extra):
     # a substituted os if we are translated
     global os
     os = nanos
@@ -220,7 +221,7 @@
     sys.executable = os.path.abspath(executable)
 
     newpath = get_library_path(executable)
-    path = os.getenv('PYTHONPATH')
+    path = readenv and os.getenv('PYTHONPATH')
     if path:
         newpath = path.split(os.pathsep) + newpath
     # remove duplicates
@@ -230,7 +231,6 @@
         if dir not in _seen:
             sys.path.append(dir)
             _seen[dir] = True
-    return executable
 
 
 def parse_command_line(argv):
@@ -242,6 +242,7 @@
     run_stdin = False
     warnoptions = []
     unbuffered = False
+    readenv = True
     while i < len(argv):
         arg = argv[i]
         if not arg.startswith('-'):
@@ -253,6 +254,8 @@
             argv[i] = '-c'
             run_command = True
             break
+        elif arg == '-E':
+            readenv = False
         elif arg == '-u':
             unbuffered = True
         elif arg == '-O' or arg == '-OO':
@@ -305,6 +308,7 @@
                      run_stdin,
                      warnoptions,
                      unbuffered,
+                     readenv,
                      cmd=None,
                      **ignored):
     # with PyPy in top of CPython we can only have around 100 
@@ -355,7 +359,7 @@
         #     * PYTHONINSPECT is set and stdin is a tty.
         #
         return (go_interactive or
-                (os.getenv('PYTHONINSPECT') and sys.stdin.isatty()))
+            (readenv and os.getenv('PYTHONINSPECT') and sys.stdin.isatty()))
 
     success = True
 
@@ -388,7 +392,7 @@
                 # If stdin is a tty or if "-i" is specified, we print
                 # a banner and run $PYTHONSTARTUP.
                 print_banner()
-                python_startup = os.getenv('PYTHONSTARTUP')
+                python_startup = readenv and os.getenv('PYTHONSTARTUP')
                 if python_startup:
                     try:
                         f = open(python_startup)
@@ -451,7 +455,6 @@
            '"license" for more information.')
 
 def entry_point(executable, argv, nanos):
-    executable = setup_initial_paths(executable, nanos)
     try:
         cmdline = parse_command_line(argv)
     except CommandLineError, e:
@@ -459,8 +462,8 @@
         return 2
     if cmdline is None:
         return 0
-    else:
-        return run_command_line(**cmdline)
+    setup_initial_paths(executable, nanos, **cmdline)
+    return run_command_line(**cmdline)
 
 
 if __name__ == '__main__':
@@ -495,13 +498,13 @@
     sys.pypy_version_info = PYPY_VERSION
     sys.pypy_initial_path = pypy_initial_path
     os = nanos.os_module_for_testing
-    sys.ps1 = '>>>> '
-    sys.ps2 = '.... '
     try:
         sys.exit(int(entry_point(sys.argv[0], sys.argv[1:], os)))
     finally:
-        sys.ps1 = '>>> '     # restore the normal ones, in case
-        sys.ps2 = '... '     # we are dropping to CPython's prompt
+        # restore the normal prompt (which was changed by _pypy_interact), in
+        # case we are dropping to CPython's prompt
+        sys.ps1 = '>>> '
+        sys.ps2 = '... '
         import os; os.environ.update(reset)
         assert old_argv is sys.argv
         assert old_path is sys.path

Modified: pypy/branch/jitypes2/pypy/translator/goal/test2/test_app_main.py
==============================================================================
--- pypy/branch/jitypes2/pypy/translator/goal/test2/test_app_main.py	(original)
+++ pypy/branch/jitypes2/pypy/translator/goal/test2/test_app_main.py	Fri Dec  3 11:04:29 2010
@@ -217,6 +217,38 @@
         finally:
             os.environ['PYTHONSTARTUP'] = old
 
+    def test_ignore_python_startup(self):
+        old = os.environ.get('PYTHONSTARTUP', '')
+        try:
+            os.environ['PYTHONSTARTUP'] = crashing_demo_script
+            child = self.spawn(['-E'])
+            child.expect(re.escape(banner))
+            index = child.expect(['Traceback', '>>> '])
+            assert index == 1      # no traceback
+        finally:
+            os.environ['PYTHONSTARTUP'] = old
+
+    def test_ignore_python_inspect(self):
+        os.environ['PYTHONINSPECT_'] = '1'
+        try:
+            child = self.spawn(['-E', '-c', 'pass'])
+            from pexpect import EOF
+            index = child.expect(['>>> ', EOF])
+            assert index == 1      # no prompt
+        finally:
+            del os.environ['PYTHONINSPECT_']
+
+    def test_ignore_python_path(self):
+        old = os.environ.get('PYTHONPATH', '')
+        try:
+            os.environ['PYTHONPATH'] = 'foobarbaz'
+            child = self.spawn(['-E', '-c', 'import sys; print sys.path'])
+            from pexpect import EOF
+            index = child.expect(['foobarbaz', EOF])
+            assert index == 1      # no foobarbaz
+        finally:
+            os.environ['PYTHONPATH'] = old
+
     def test_unbuffered(self):
         line = 'import os,sys;sys.stdout.write(str(789));os.read(0,1)'
         child = self.spawn(['-u', '-c', line])
@@ -329,6 +361,10 @@
         child = self.spawn(['-mpypy.translator.goal.test2.mymodule'])
         child.expect('mymodule running')
 
+    def test_ps1_only_if_interactive(self):
+        argv = ['-c', 'import sys; print hasattr(sys, "ps1")']
+        child = self.spawn(argv)
+        child.expect('False')
 
 class TestNonInteractive:
 

Modified: pypy/branch/jitypes2/pypy/translator/platform/__init__.py
==============================================================================
--- pypy/branch/jitypes2/pypy/translator/platform/__init__.py	(original)
+++ pypy/branch/jitypes2/pypy/translator/platform/__init__.py	Fri Dec  3 11:04:29 2010
@@ -123,7 +123,9 @@
             errorfile.write(stderr, 'wb')
             stderrlines = stderr.splitlines()
             for line in stderrlines:
-                log.ERROR(line)
+                log.Error(line)
+            # ^^^ don't use ERROR, because it might actually be fine.
+            # Also, ERROR confuses lib-python/conftest.py.
             raise CompilationError(stdout, stderr)
         else:
             for line in stderr.splitlines():
@@ -215,13 +217,13 @@
         host_factory = Darwin_i386
     else:
         host_factory = Darwin_x86_64
-elif sys.platform == 'freebsd7':
-    from pypy.translator.platform.freebsd7 import Freebsd7, Freebsd7_64
+elif "freebsd" in sys.platform:
+    from pypy.translator.platform.freebsd import Freebsd, Freebsd_64
     import platform
     if platform.architecture()[0] == '32bit':
-        host_factory = Freebsd7
+        host_factory = Freebsd
     else:
-        host_factory = Freebsd7_64
+        host_factory = Freebsd_64
 elif os.name == 'nt':
     from pypy.translator.platform.windows import Windows
     host_factory = Windows

Modified: pypy/branch/jitypes2/pypy/translator/platform/darwin.py
==============================================================================
--- pypy/branch/jitypes2/pypy/translator/platform/darwin.py	(original)
+++ pypy/branch/jitypes2/pypy/translator/platform/darwin.py	Fri Dec  3 11:04:29 2010
@@ -12,12 +12,14 @@
 
     so_ext = 'so'
     
+    default_cc = 'gcc'
+
     def __init__(self, cc=None):
         if cc is None:
             try:
                 cc = os.environ['CC']
             except KeyError:
-                cc = 'gcc'
+                cc = self.default_cc
         self.cc = cc
 
     def _args_for_shared(self, args):
@@ -85,3 +87,4 @@
     link_flags = ('-arch', 'x86_64', '-mmacosx-version-min=10.4')
     cflags = ('-arch', 'x86_64', '-O3', '-fomit-frame-pointer',
               '-mmacosx-version-min=10.4')
+    default_cc = 'gcc-4.0'

Modified: pypy/branch/jitypes2/pypy/translator/tool/cbuild.py
==============================================================================
--- pypy/branch/jitypes2/pypy/translator/tool/cbuild.py	(original)
+++ pypy/branch/jitypes2/pypy/translator/tool/cbuild.py	Fri Dec  3 11:04:29 2010
@@ -309,6 +309,7 @@
 #define _POSIX_C_SOURCE 200112L
 /* Define on FreeBSD to activate all library features */
 #define __BSD_VISIBLE 1
+#define __XSI_VISIBLE 700
 /* Windows: winsock/winsock2 mess */
 #define WIN32_LEAN_AND_MEAN
 '''

Modified: pypy/branch/jitypes2/pypy/translator/tool/reftracker.py
==============================================================================
--- pypy/branch/jitypes2/pypy/translator/tool/reftracker.py	(original)
+++ pypy/branch/jitypes2/pypy/translator/tool/reftracker.py	Fri Dec  3 11:04:29 2010
@@ -3,7 +3,7 @@
 Usage: call track(obj).
 """
 
-import autopath, sys, os
+import autopath, sys, os, types
 import gc
 from pypy.translator.tool.graphpage import GraphPage, DotGen
 from pypy.tool.uid import uid
@@ -39,7 +39,7 @@
                 if o2 is None:
                     continue
                 addedge(objectlist[i], o2)
-                id2typename[uid(o2)] = type(o2).__name__
+                id2typename[uid(o2)] = self.shortrepr(o2)
                 del o2
             for o2 in self.get_referrers(objectlist[i]):
                 if o2 is None:
@@ -47,7 +47,7 @@
                 if type(o2) is list and o2 and o2[0] is MARKER:
                     continue
                 addedge(o2, objectlist[i])
-                id2typename[uid(o2)] = type(o2).__name__
+                id2typename[uid(o2)] = self.shortrepr(o2)
                 del o2
 
         for ids, label in edges.items():
@@ -82,13 +82,23 @@
         return self.newpage(objectlist)
 
     def formatobject(self, o):
+        header = self.shortrepr(o, compact=False)
+        secondline = repr(o.__class__)
+        return header, secondline, repr(o)
+
+    def shortrepr(self, o, compact=True):
+        t = type(o)
+        if t is types.FrameType:
+            if compact:
+                return 'frame %r' % (o.f_code.co_name,)
+            else:
+                return 'frame %r' % (o.f_code,)
         s = repr(o)
         if len(s) > 50:
-            linktext = s
             s = s[:20] + ' ... ' + s[-20:]
-        else:
-            linktext = ''
-        return type(o).__name__, s, linktext
+        if s.startswith('<') and s.endswith('>'):
+            s = s[1:-1]
+        return s
 
     def edgelabel(self, o1, o2):
         return ''



More information about the Pypy-commit mailing list