[pypy-svn] r79720 - in pypy/branch/fast-forward: . ctypes_configure lib-python lib-python/modified-2.5.2/distutils lib-python/modified-2.5.2/distutils/tests lib_pypy 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/backend 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/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/test pypy/module/pypyjit pypy/module/pypyjit/test pypy/module/sys pypy/objspace/std pypy/rlib pypy/rlib/rsre 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/test pypy/rpython/tool pypy/tool pypy/translator/c/gcc pypy/translator/c/src pypy/translator/goal pypy/translator/goal/test2 pypy/translator/platform pypy/translator/tool

afa at codespeak.net afa at codespeak.net
Wed Dec 1 18:08:30 CET 2010


Author: afa
Date: Wed Dec  1 18:08:21 2010
New Revision: 79720

Added:
   pypy/branch/fast-forward/lib_pypy/pypy_test/hack___pypy__.py
      - copied unchanged from r79701, pypy/trunk/lib_pypy/pypy_test/hack___pypy__.py
   pypy/branch/fast-forward/pypy/doc/config/objspace.usemodules.binascii.txt
      - copied unchanged from r79701, pypy/trunk/pypy/doc/config/objspace.usemodules.binascii.txt
   pypy/branch/fast-forward/pypy/jit/backend/llsupport/asmmemmgr.py
      - copied unchanged from r79701, pypy/trunk/pypy/jit/backend/llsupport/asmmemmgr.py
   pypy/branch/fast-forward/pypy/jit/backend/llsupport/test/test_asmmemmgr.py
      - copied unchanged from r79701, pypy/trunk/pypy/jit/backend/llsupport/test/test_asmmemmgr.py
   pypy/branch/fast-forward/pypy/jit/backend/x86/codebuf.py
      - copied unchanged from r79701, pypy/trunk/pypy/jit/backend/x86/codebuf.py
   pypy/branch/fast-forward/pypy/jit/tool/cpython.vmrss
      - copied unchanged from r79701, pypy/trunk/pypy/jit/tool/cpython.vmrss
   pypy/branch/fast-forward/pypy/jit/tool/test/test_log2gnumeric.py
      - copied unchanged from r79706, pypy/trunk/pypy/jit/tool/test/test_log2gnumeric.py
   pypy/branch/fast-forward/pypy/module/binascii/   (props changed)
      - copied from r79701, pypy/trunk/pypy/module/binascii/
   pypy/branch/fast-forward/pypy/module/binascii/__init__.py
      - copied unchanged from r79701, pypy/trunk/pypy/module/binascii/__init__.py
   pypy/branch/fast-forward/pypy/module/binascii/app_binascii.py
      - copied unchanged from r79701, pypy/trunk/pypy/module/binascii/app_binascii.py
   pypy/branch/fast-forward/pypy/module/binascii/interp_base64.py
      - copied unchanged from r79701, pypy/trunk/pypy/module/binascii/interp_base64.py
   pypy/branch/fast-forward/pypy/module/binascii/interp_binascii.py
      - copied unchanged from r79701, pypy/trunk/pypy/module/binascii/interp_binascii.py
   pypy/branch/fast-forward/pypy/module/binascii/interp_crc32.py
      - copied unchanged from r79701, pypy/trunk/pypy/module/binascii/interp_crc32.py
   pypy/branch/fast-forward/pypy/module/binascii/interp_hexlify.py
      - copied unchanged from r79701, pypy/trunk/pypy/module/binascii/interp_hexlify.py
   pypy/branch/fast-forward/pypy/module/binascii/interp_hqx.py
      - copied unchanged from r79701, pypy/trunk/pypy/module/binascii/interp_hqx.py
   pypy/branch/fast-forward/pypy/module/binascii/interp_qp.py
      - copied unchanged from r79701, pypy/trunk/pypy/module/binascii/interp_qp.py
   pypy/branch/fast-forward/pypy/module/binascii/interp_uu.py
      - copied unchanged from r79701, pypy/trunk/pypy/module/binascii/interp_uu.py
   pypy/branch/fast-forward/pypy/module/binascii/test/   (props changed)
      - copied from r79701, pypy/trunk/pypy/module/binascii/test/
   pypy/branch/fast-forward/pypy/module/binascii/test/test_binascii.py
      - copied unchanged from r79701, pypy/trunk/pypy/module/binascii/test/test_binascii.py
   pypy/branch/fast-forward/pypy/module/cpyext/include/structseq.h
      - copied unchanged from r79701, pypy/trunk/pypy/module/cpyext/include/structseq.h
   pypy/branch/fast-forward/pypy/module/cpyext/src/structseq.c
      - copied unchanged from r79701, pypy/trunk/pypy/module/cpyext/src/structseq.c
   pypy/branch/fast-forward/pypy/module/cpyext/test/test_structseq.py
      - copied unchanged from r79701, pypy/trunk/pypy/module/cpyext/test/test_structseq.py
   pypy/branch/fast-forward/pypy/rpython/memory/gc/test/test_inspector.py
      - copied unchanged from r79701, pypy/trunk/pypy/rpython/memory/gc/test/test_inspector.py
   pypy/branch/fast-forward/pypy/translator/platform/freebsd.py
      - copied unchanged from r79701, pypy/trunk/pypy/translator/platform/freebsd.py
Removed:
   pypy/branch/fast-forward/pypy/doc/config/translation.jit_debug.txt
   pypy/branch/fast-forward/pypy/translator/platform/freebsd7.py
Modified:
   pypy/branch/fast-forward/   (props changed)
   pypy/branch/fast-forward/ctypes_configure/configure.py
   pypy/branch/fast-forward/lib-python/conftest.py
   pypy/branch/fast-forward/lib-python/modified-2.5.2/distutils/msvccompiler.py
   pypy/branch/fast-forward/lib-python/modified-2.5.2/distutils/tests/test_msvccompiler.py
   pypy/branch/fast-forward/lib_pypy/_locale.py
   pypy/branch/fast-forward/lib_pypy/_marshal.py
   pypy/branch/fast-forward/lib_pypy/_minimal_curses.py
   pypy/branch/fast-forward/lib_pypy/_pypy_interact.py
   pypy/branch/fast-forward/lib_pypy/binascii.py
   pypy/branch/fast-forward/lib_pypy/cPickle.py
   pypy/branch/fast-forward/lib_pypy/cmath.py
   pypy/branch/fast-forward/lib_pypy/ctypes_support.py
   pypy/branch/fast-forward/lib_pypy/grp.py
   pypy/branch/fast-forward/lib_pypy/itertools.py
   pypy/branch/fast-forward/lib_pypy/msvcrt.py
   pypy/branch/fast-forward/lib_pypy/pwd.py
   pypy/branch/fast-forward/lib_pypy/pyexpat.py
   pypy/branch/fast-forward/lib_pypy/pypy_test/test_structseq.py
   pypy/branch/fast-forward/lib_pypy/readline.py
   pypy/branch/fast-forward/lib_pypy/resource.py
   pypy/branch/fast-forward/lib_pypy/syslog.py
   pypy/branch/fast-forward/pypy/   (props changed)
   pypy/branch/fast-forward/pypy/annotation/description.py
   pypy/branch/fast-forward/pypy/annotation/listdef.py
   pypy/branch/fast-forward/pypy/annotation/test/test_annrpython.py
   pypy/branch/fast-forward/pypy/annotation/unaryop.py
   pypy/branch/fast-forward/pypy/config/pypyoption.py
   pypy/branch/fast-forward/pypy/config/test/test_support.py
   pypy/branch/fast-forward/pypy/conftest.py
   pypy/branch/fast-forward/pypy/doc/config/objspace.usemodules.array.txt   (props changed)
   pypy/branch/fast-forward/pypy/doc/cpython_differences.txt
   pypy/branch/fast-forward/pypy/doc/faq.txt
   pypy/branch/fast-forward/pypy/doc/index.txt
   pypy/branch/fast-forward/pypy/doc/release-1.4.0.txt
   pypy/branch/fast-forward/pypy/doc/sprint-reports.txt
   pypy/branch/fast-forward/pypy/doc/statistic/release_dates.dat
   pypy/branch/fast-forward/pypy/doc/statistic/sprint_dates.dat
   pypy/branch/fast-forward/pypy/interpreter/function.py
   pypy/branch/fast-forward/pypy/interpreter/gateway.py
   pypy/branch/fast-forward/pypy/interpreter/pycode.py
   pypy/branch/fast-forward/pypy/interpreter/test/test_gateway.py
   pypy/branch/fast-forward/pypy/jit/backend/conftest.py
   pypy/branch/fast-forward/pypy/jit/backend/detect_cpu.py
   pypy/branch/fast-forward/pypy/jit/backend/llsupport/gc.py
   pypy/branch/fast-forward/pypy/jit/backend/llsupport/llmodel.py
   pypy/branch/fast-forward/pypy/jit/backend/llsupport/test/test_gc.py
   pypy/branch/fast-forward/pypy/jit/backend/model.py
   pypy/branch/fast-forward/pypy/jit/backend/test/runner_test.py
   pypy/branch/fast-forward/pypy/jit/backend/x86/assembler.py
   pypy/branch/fast-forward/pypy/jit/backend/x86/regalloc.py
   pypy/branch/fast-forward/pypy/jit/backend/x86/regloc.py
   pypy/branch/fast-forward/pypy/jit/backend/x86/runner.py
   pypy/branch/fast-forward/pypy/jit/backend/x86/rx86.py
   pypy/branch/fast-forward/pypy/jit/backend/x86/support.py
   pypy/branch/fast-forward/pypy/jit/backend/x86/test/test_assembler.py
   pypy/branch/fast-forward/pypy/jit/backend/x86/test/test_gc_integration.py
   pypy/branch/fast-forward/pypy/jit/backend/x86/test/test_regalloc.py
   pypy/branch/fast-forward/pypy/jit/backend/x86/test/test_regalloc2.py
   pypy/branch/fast-forward/pypy/jit/backend/x86/test/test_regloc.py
   pypy/branch/fast-forward/pypy/jit/backend/x86/test/test_runner.py
   pypy/branch/fast-forward/pypy/jit/backend/x86/test/test_rx86.py
   pypy/branch/fast-forward/pypy/jit/backend/x86/test/test_zll_random.py
   pypy/branch/fast-forward/pypy/jit/backend/x86/test/test_zmath.py
   pypy/branch/fast-forward/pypy/jit/backend/x86/test/test_ztranslation.py
   pypy/branch/fast-forward/pypy/jit/backend/x86/valgrind.py
   pypy/branch/fast-forward/pypy/jit/codewriter/call.py
   pypy/branch/fast-forward/pypy/jit/codewriter/jtransform.py
   pypy/branch/fast-forward/pypy/jit/codewriter/support.py
   pypy/branch/fast-forward/pypy/jit/codewriter/test/test_codewriter.py
   pypy/branch/fast-forward/pypy/jit/codewriter/test/test_list.py
   pypy/branch/fast-forward/pypy/jit/codewriter/test/test_void_list.py
   pypy/branch/fast-forward/pypy/jit/metainterp/history.py
   pypy/branch/fast-forward/pypy/jit/metainterp/memmgr.py
   pypy/branch/fast-forward/pypy/jit/metainterp/optimizeopt/optimizer.py   (props changed)
   pypy/branch/fast-forward/pypy/jit/metainterp/pyjitpl.py
   pypy/branch/fast-forward/pypy/jit/metainterp/test/test_basic.py
   pypy/branch/fast-forward/pypy/jit/metainterp/test/test_list.py
   pypy/branch/fast-forward/pypy/jit/metainterp/test/test_memmgr.py
   pypy/branch/fast-forward/pypy/jit/metainterp/test/test_recursive.py
   pypy/branch/fast-forward/pypy/jit/metainterp/test/test_virtualizable.py
   pypy/branch/fast-forward/pypy/jit/metainterp/warmspot.py
   pypy/branch/fast-forward/pypy/jit/tl/spli/interpreter.py
   pypy/branch/fast-forward/pypy/jit/tl/tl.py
   pypy/branch/fast-forward/pypy/jit/tool/log-template.gnumeric
   pypy/branch/fast-forward/pypy/jit/tool/log2gnumeric.py
   pypy/branch/fast-forward/pypy/module/__pypy__/__init__.py
   pypy/branch/fast-forward/pypy/module/__pypy__/interp_magic.py
   pypy/branch/fast-forward/pypy/module/__pypy__/test/test_special.py
   pypy/branch/fast-forward/pypy/module/array/benchmark/Makefile   (props changed)
   pypy/branch/fast-forward/pypy/module/array/benchmark/intimg.c   (props changed)
   pypy/branch/fast-forward/pypy/module/array/benchmark/intimgtst.c   (props changed)
   pypy/branch/fast-forward/pypy/module/array/benchmark/intimgtst.py   (props changed)
   pypy/branch/fast-forward/pypy/module/array/benchmark/loop.c   (props changed)
   pypy/branch/fast-forward/pypy/module/array/benchmark/sum.c   (props changed)
   pypy/branch/fast-forward/pypy/module/array/benchmark/sumtst.c   (props changed)
   pypy/branch/fast-forward/pypy/module/array/benchmark/sumtst.py   (props changed)
   pypy/branch/fast-forward/pypy/module/array/test/test_array_old.py   (props changed)
   pypy/branch/fast-forward/pypy/module/cpyext/api.py
   pypy/branch/fast-forward/pypy/module/cpyext/cdatetime.py
   pypy/branch/fast-forward/pypy/module/cpyext/include/tupleobject.h
   pypy/branch/fast-forward/pypy/module/cpyext/sequence.py
   pypy/branch/fast-forward/pypy/module/cpyext/slotdefs.py
   pypy/branch/fast-forward/pypy/module/cpyext/state.py
   pypy/branch/fast-forward/pypy/module/cpyext/stubs.py
   pypy/branch/fast-forward/pypy/module/cpyext/test/test_arraymodule.py
   pypy/branch/fast-forward/pypy/module/cpyext/test/test_cpyext.py
   pypy/branch/fast-forward/pypy/module/cpyext/test/test_datetime.py
   pypy/branch/fast-forward/pypy/module/cpyext/test/test_sequence.py
   pypy/branch/fast-forward/pypy/module/cpyext/test/test_tupleobject.py
   pypy/branch/fast-forward/pypy/module/cpyext/test/test_typeobject.py
   pypy/branch/fast-forward/pypy/module/cpyext/tupleobject.py
   pypy/branch/fast-forward/pypy/module/cpyext/typeobject.py
   pypy/branch/fast-forward/pypy/module/fcntl/test/test_fcntl.py
   pypy/branch/fast-forward/pypy/module/imp/importing.py
   pypy/branch/fast-forward/pypy/module/itertools/interp_itertools.py
   pypy/branch/fast-forward/pypy/module/posix/__init__.py
   pypy/branch/fast-forward/pypy/module/posix/interp_posix.py
   pypy/branch/fast-forward/pypy/module/posix/test/test_posix2.py
   pypy/branch/fast-forward/pypy/module/pyexpat/test/test_parser.py
   pypy/branch/fast-forward/pypy/module/pypyjit/policy.py
   pypy/branch/fast-forward/pypy/module/pypyjit/test/test_policy.py
   pypy/branch/fast-forward/pypy/module/pypyjit/test/test_pypy_c.py
   pypy/branch/fast-forward/pypy/module/sys/__init__.py
   pypy/branch/fast-forward/pypy/objspace/std/mapdict.py
   pypy/branch/fast-forward/pypy/objspace/std/objspace.py
   pypy/branch/fast-forward/pypy/rlib/debug.py
   pypy/branch/fast-forward/pypy/rlib/libffi.py
   pypy/branch/fast-forward/pypy/rlib/rarithmetic.py
   pypy/branch/fast-forward/pypy/rlib/rdynload.py
   pypy/branch/fast-forward/pypy/rlib/rerased.py   (props changed)
   pypy/branch/fast-forward/pypy/rlib/rsre/rsre_core.py
   pypy/branch/fast-forward/pypy/rlib/test/test_libffi.py
   pypy/branch/fast-forward/pypy/rlib/test/test_rerased.py   (props changed)
   pypy/branch/fast-forward/pypy/rpython/lltypesystem/ll2ctypes.py
   pypy/branch/fast-forward/pypy/rpython/lltypesystem/llmemory.py
   pypy/branch/fast-forward/pypy/rpython/memory/gc/inspector.py
   pypy/branch/fast-forward/pypy/rpython/memory/gc/test/test_direct.py
   pypy/branch/fast-forward/pypy/rpython/memory/gctransform/asmgcroot.py
   pypy/branch/fast-forward/pypy/rpython/module/ll_os.py
   pypy/branch/fast-forward/pypy/rpython/module/ll_time.py
   pypy/branch/fast-forward/pypy/rpython/rlist.py
   pypy/branch/fast-forward/pypy/rpython/test/test_rint.py
   pypy/branch/fast-forward/pypy/rpython/test/test_rlist.py
   pypy/branch/fast-forward/pypy/rpython/tool/rffi_platform.py
   pypy/branch/fast-forward/pypy/tool/ansi_print.py
   pypy/branch/fast-forward/pypy/tool/logparser.py
   pypy/branch/fast-forward/pypy/translator/c/gcc/trackgcroot.py
   pypy/branch/fast-forward/pypy/translator/c/src/mem.h
   pypy/branch/fast-forward/pypy/translator/goal/app_main.py
   pypy/branch/fast-forward/pypy/translator/goal/test2/test_app_main.py
   pypy/branch/fast-forward/pypy/translator/platform/__init__.py
   pypy/branch/fast-forward/pypy/translator/platform/darwin.py
   pypy/branch/fast-forward/pypy/translator/tool/cbuild.py
Log:
Merge from trunk
svn merge -r79456:79701 ../trunk


Modified: pypy/branch/fast-forward/ctypes_configure/configure.py
==============================================================================
--- pypy/branch/fast-forward/ctypes_configure/configure.py	(original)
+++ pypy/branch/fast-forward/ctypes_configure/configure.py	Wed Dec  1 18:08:21 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/fast-forward/lib-python/conftest.py
==============================================================================
--- pypy/branch/fast-forward/lib-python/conftest.py	(original)
+++ pypy/branch/fast-forward/lib-python/conftest.py	Wed Dec  1 18:08:21 2010
@@ -126,7 +126,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/fast-forward/lib-python/modified-2.5.2/distutils/msvccompiler.py
==============================================================================
--- pypy/branch/fast-forward/lib-python/modified-2.5.2/distutils/msvccompiler.py	(original)
+++ pypy/branch/fast-forward/lib-python/modified-2.5.2/distutils/msvccompiler.py	Wed Dec  1 18:08:21 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/fast-forward/lib-python/modified-2.5.2/distutils/tests/test_msvccompiler.py
==============================================================================
--- pypy/branch/fast-forward/lib-python/modified-2.5.2/distutils/tests/test_msvccompiler.py	(original)
+++ pypy/branch/fast-forward/lib-python/modified-2.5.2/distutils/tests/test_msvccompiler.py	Wed Dec  1 18:08:21 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/fast-forward/lib_pypy/_locale.py
==============================================================================
--- pypy/branch/fast-forward/lib_pypy/_locale.py	(original)
+++ pypy/branch/fast-forward/lib_pypy/_locale.py	Wed Dec  1 18:08:21 2010
@@ -11,6 +11,8 @@
 # load the platform-specific cache made by running locale.ctc.py
 from ctypes_config_cache._locale_cache import *
 
+import __pypy__
+
 
 # Ubuntu Gusty i386 structure
 class lconv(Structure):
@@ -158,6 +160,7 @@
     ul = ''.join(ul)
     string.letters = ul
 
+ at __pypy__.builtinify
 def setlocale(category, locale=None):
     "(integer,string=None) -> string. Activates/queries locale processing."
     if locale:
@@ -182,6 +185,7 @@
         groups.append(0)
     return groups
 
+ at __pypy__.builtinify
 def localeconv():
     "() -> dict. Returns numeric and monetary locale-specific parameters."
 
@@ -215,6 +219,7 @@
     }
     return result
 
+ at __pypy__.builtinify
 def strcoll(s1, s2):
     "string,string -> int. Compares two strings according to the locale."
 
@@ -233,6 +238,7 @@
     # Collate the strings.
     return _wcscoll(s1, s2)
 
+ at __pypy__.builtinify
 def strxfrm(s):
     "string -> string. Returns a string that behaves for cmp locale-aware."
 
@@ -246,6 +252,7 @@
         _strxfrm(buf, s, n2)
     return buf.value
 
+ at __pypy__.builtinify
 def getdefaultlocale():
     # TODO: Port code from CPython for Windows and Mac OS
     raise NotImplementedError()
@@ -267,26 +274,31 @@
         raise ValueError("unsupported langinfo constant")
 
 if HAS_LIBINTL:
+    @__pypy__.builtinify
     def gettext(msg):
         """gettext(msg) -> string
         Return translation of msg."""
         return _gettext(msg)
 
+    @__pypy__.builtinify
     def dgettext(domain, msg):
         """dgettext(domain, msg) -> string
         Return translation of msg in domain."""
         return _dgettext(domain, msg)
 
+    @__pypy__.builtinify
     def dcgettext(domain, msg, category):
         """dcgettext(domain, msg, category) -> string
         Return translation of msg in domain and category."""
         return _dcgettext(domain, msg, category)
 
+    @__pypy__.builtinify
     def textdomain(domain):
         """textdomain(domain) -> string
         Set the C library's textdomain to domain, returning the new domain."""
         return _textdomain(domain)
 
+    @__pypy__.builtinify
     def bindtextdomain(domain, dir):
         """bindtextdomain(domain, dir) -> string
         Bind the C library's domain to dir."""
@@ -297,6 +309,7 @@
         return dirname
 
     if HAS_BIND_TEXTDOMAIN_CODESET:
+        @__pypy__.builtinify
         def bind_textdomain_codeset(domain, codeset):
             """bind_textdomain_codeset(domain, codeset) -> string
             Bind the C library's domain to codeset."""

Modified: pypy/branch/fast-forward/lib_pypy/_marshal.py
==============================================================================
--- pypy/branch/fast-forward/lib_pypy/_marshal.py	(original)
+++ pypy/branch/fast-forward/lib_pypy/_marshal.py	Wed Dec  1 18:08:21 2010
@@ -3,7 +3,7 @@
 This module contains functions that can read and write Python values in a binary format. The format is specific to Python, but independent of machine architecture issues (e.g., you can write a Python value to a file on a PC, transport the file to a Sun, and read it back there). Details of the format may change between Python versions.
 """
 
-import types
+import types, __pypy__
 from _codecs import utf_8_decode, utf_8_encode
 
 TYPE_NULL     = '0'
@@ -645,15 +645,18 @@
 
 version = 1
 
+ at __pypy__.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 __pypy__.builtinify
 def load(f):
     um = _Unmarshaller(f.read)
     return um.load()
 
+ at __pypy__.builtinify
 def dumps(x, version=version):
     # XXX 'version' is ignored, we always dump in a version-0-compatible format
     buffer = []
@@ -661,6 +664,7 @@
     m.dump(x)
     return ''.join(buffer)
 
+ at __pypy__.builtinify
 def loads(s):
     um = _FastUnmarshaller(s)
     return um.load()

Modified: pypy/branch/fast-forward/lib_pypy/_minimal_curses.py
==============================================================================
--- pypy/branch/fast-forward/lib_pypy/_minimal_curses.py	(original)
+++ pypy/branch/fast-forward/lib_pypy/_minimal_curses.py	Wed Dec  1 18:08:21 2010
@@ -35,18 +35,23 @@
 
 # ____________________________________________________________
 
+import __pypy__
+
+ at __pypy__.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 __pypy__.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 __pypy__.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/fast-forward/lib_pypy/_pypy_interact.py
==============================================================================
--- pypy/branch/fast-forward/lib_pypy/_pypy_interact.py	(original)
+++ pypy/branch/fast-forward/lib_pypy/_pypy_interact.py	Wed Dec  1 18:08:21 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/fast-forward/lib_pypy/binascii.py
==============================================================================
--- pypy/branch/fast-forward/lib_pypy/binascii.py	(original)
+++ pypy/branch/fast-forward/lib_pypy/binascii.py	Wed Dec  1 18:08:21 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/fast-forward/lib_pypy/cPickle.py
==============================================================================
--- pypy/branch/fast-forward/lib_pypy/cPickle.py	(original)
+++ pypy/branch/fast-forward/lib_pypy/cPickle.py	Wed Dec  1 18:08:21 2010
@@ -4,6 +4,7 @@
 
 from pickle import *
 from pickle import __doc__, __version__, format_version, compatible_formats
+import __pypy__
 
 BadPickleGet = KeyError
 UnpickleableError = PicklingError
@@ -31,9 +32,11 @@
     def getvalue(self):
         return self.__f and self.__f.getvalue()
 
+ at __pypy__.builtinify
 def dump(obj, file, protocol=None):
     Pickler(file, protocol).dump(obj)
 
+ at __pypy__.builtinify
 def dumps(obj, protocol=None):
     file = StringIO()
     Pickler(file, protocol).dump(obj)

Modified: pypy/branch/fast-forward/lib_pypy/cmath.py
==============================================================================
--- pypy/branch/fast-forward/lib_pypy/cmath.py	(original)
+++ pypy/branch/fast-forward/lib_pypy/cmath.py	Wed Dec  1 18:08:21 2010
@@ -5,9 +5,9 @@
 
 # much code borrowed from mathmodule.c
 
-import math
+import math, __pypy__
 from math import e, pi
-        
+
 
 # constants
 _one = complex(1., 0.)
@@ -33,11 +33,13 @@
 
 
 
+ at __pypy__.builtinify
 def phase(x):
     x = _to_complex(x)
     return math.atan2(x.imag, x.real)
 
 
+ at __pypy__.builtinify
 def polar(x):
     x = _to_complex(x)
     phi = math.atan2(x.imag, x.real)
@@ -45,10 +47,12 @@
     return r, phi
 
 
+ at __pypy__.builtinify
 def rect(r, phi):
     return complex(r * math.cos(phi), r * math.sin(phi))
 
 
+ at __pypy__.builtinify
 def acos(x):
     """acos(x)
 
@@ -58,6 +62,7 @@
     return -(_prodi(log((x+(_i*sqrt((_one-(x*x))))))))
 
 
+ at __pypy__.builtinify
 def acosh(x):
     """acosh(x)
 
@@ -68,6 +73,7 @@
     return z+z
 
 
+ at __pypy__.builtinify
 def asin(x):
     """asin(x)
 
@@ -80,6 +86,7 @@
     return -(_prodi(log((sqrt_1_minus_x_sq+_prodi(x)))))
 
 
+ at __pypy__.builtinify
 def asinh(x):
     """asinh(x)
 
@@ -90,6 +97,7 @@
     return z+z
 
 
+ at __pypy__.builtinify
 def atan(x):
     """atan(x)
     
@@ -99,6 +107,7 @@
     return _halfi*log(((_i+x)/(_i-x)))
 
 
+ at __pypy__.builtinify
 def atanh(x):
     """atanh(x)
 
@@ -108,6 +117,7 @@
     return _half*log((_one+x)/(_one-x))
 
 
+ at __pypy__.builtinify
 def cos(x):
     """cos(x)
 
@@ -119,6 +129,7 @@
     return complex(real, imag)
 
 
+ at __pypy__.builtinify
 def cosh(x):
     """cosh(x)
     
@@ -130,6 +141,7 @@
     return complex(real, imag)
 
 
+ at __pypy__.builtinify
 def exp(x):
     """exp(x)
     
@@ -142,6 +154,7 @@
     return complex(real, imag)
 
 
+ at __pypy__.builtinify
 def log(x, base=None):
     """log(x)
 
@@ -156,6 +169,7 @@
     return complex(real, imag)
 
 
+ at __pypy__.builtinify
 def log10(x):
     """log10(x)
 
@@ -168,6 +182,7 @@
     return complex(real, imag)
 
 
+ at __pypy__.builtinify
 def sin(x):
     """sin(x)
 
@@ -179,6 +194,7 @@
     return complex(real, imag)
 
 
+ at __pypy__.builtinify
 def sinh(x):
     """sinh(x)
 
@@ -190,6 +206,7 @@
     return complex(real, imag)
 
 
+ at __pypy__.builtinify
 def sqrt(x):
     """sqrt(x)
 
@@ -215,6 +232,7 @@
 _sqrt_half = sqrt(_half)
 
 
+ at __pypy__.builtinify
 def tan(x):
     """tan(x)
 
@@ -235,6 +253,7 @@
     return complex(real, imag)
 
 
+ at __pypy__.builtinify
 def tanh(x):
     """tanh(x)
 

Modified: pypy/branch/fast-forward/lib_pypy/ctypes_support.py
==============================================================================
--- pypy/branch/fast-forward/lib_pypy/ctypes_support.py	(original)
+++ pypy/branch/fast-forward/lib_pypy/ctypes_support.py	Wed Dec  1 18:08:21 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/fast-forward/lib_pypy/grp.py
==============================================================================
--- pypy/branch/fast-forward/lib_pypy/grp.py	(original)
+++ pypy/branch/fast-forward/lib_pypy/grp.py	Wed Dec  1 18:08:21 2010
@@ -2,7 +2,7 @@
 """ This module provides ctypes version of cpython's grp module
 """
 
-import sys
+import sys, __pypy__
 if sys.platform == 'win32':
     raise ImportError("No grp module on Windows")
 
@@ -64,6 +64,7 @@
     return Group(res.contents.gr_name, res.contents.gr_passwd,
                  res.contents.gr_gid, mem)
 
+ at __pypy__.builtinify
 def getgrgid(gid):
     res = libc.getgrgid(gid)
     if not res:
@@ -71,6 +72,7 @@
         raise KeyError(gid)
     return _group_from_gstruct(res)
 
+ at __pypy__.builtinify
 def getgrnam(name):
     if not isinstance(name, str):
         raise TypeError("expected string")
@@ -79,6 +81,7 @@
         raise KeyError(name)
     return _group_from_gstruct(res)
 
+ at __pypy__.builtinify
 def getgrall():
     libc.setgrent()
     lst = []

Modified: pypy/branch/fast-forward/lib_pypy/itertools.py
==============================================================================
--- pypy/branch/fast-forward/lib_pypy/itertools.py	(original)
+++ pypy/branch/fast-forward/lib_pypy/itertools.py	Wed Dec  1 18:08:21 2010
@@ -27,6 +27,8 @@
            'ifilterfalse', 'imap', 'islice', 'izip', 'repeat', 'starmap',
            'takewhile', 'tee']
 
+import __pypy__
+
 
 class chain(object):
     """Make an iterator that returns elements from the first iterable
@@ -631,7 +633,8 @@
     def __iter__(self):
         return self
 
-    
+
+ at __pypy__.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/fast-forward/lib_pypy/msvcrt.py
==============================================================================
--- pypy/branch/fast-forward/lib_pypy/msvcrt.py	(original)
+++ pypy/branch/fast-forward/lib_pypy/msvcrt.py	Wed Dec  1 18:08:21 2010
@@ -11,6 +11,7 @@
 from ctypes_support import standard_c_lib as _c
 from ctypes_support import get_errno
 import errno
+import __pypy__
 
 try:
     open_osfhandle = _c._open_osfhandle
@@ -34,6 +35,7 @@
 _locking.argtypes = [ctypes.c_int, ctypes.c_int, ctypes.c_int]
 _locking.restype = ctypes.c_int
 
+ at __pypy__.builtinify
 def locking(fd, mode, nbytes):
     '''lock or unlock a number of bytes in a file.'''
     rv = _locking(fd, mode, nbytes)

Modified: pypy/branch/fast-forward/lib_pypy/pwd.py
==============================================================================
--- pypy/branch/fast-forward/lib_pypy/pwd.py	(original)
+++ pypy/branch/fast-forward/lib_pypy/pwd.py	Wed Dec  1 18:08:21 2010
@@ -10,7 +10,7 @@
 exception is raised if the entry asked for cannot be found.
 """
 
-import sys
+import sys, __pypy__
 if sys.platform == 'win32':
     raise ImportError("No pwd module on Windows")
 
@@ -79,10 +79,12 @@
 _endpwent.argtypes = None
 _endpwent.restype = None
 
+ at __pypy__.builtinify
 def mkpwent(pw):
     pw = pw.contents
     return struct_passwd(pw)
 
+ at __pypy__.builtinify
 def getpwuid(uid):
     """
     getpwuid(uid) -> (pw_name,pw_passwd,pw_uid,
@@ -95,6 +97,7 @@
         raise KeyError("getpwuid(): uid not found: %s" % uid)
     return mkpwent(pw)
 
+ at __pypy__.builtinify
 def getpwnam(name):
     """
     getpwnam(name) -> (pw_name,pw_passwd,pw_uid,
@@ -109,9 +112,10 @@
         raise KeyError("getpwname(): name not found: %s" % name)
     return mkpwent(pw)
 
+ at __pypy__.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/fast-forward/lib_pypy/pyexpat.py
==============================================================================
--- pypy/branch/fast-forward/lib_pypy/pyexpat.py	(original)
+++ pypy/branch/fast-forward/lib_pypy/pyexpat.py	Wed Dec  1 18:08:21 2010
@@ -2,7 +2,7 @@
 import ctypes
 import ctypes.util
 from ctypes import c_char_p, c_int, c_void_p, POINTER, c_char, c_wchar_p
-import sys
+import sys, __pypy__
 
 # load the platform-specific cache made by running pyexpat.ctc.py
 from ctypes_config_cache._pyexpat_cache import *
@@ -425,9 +425,11 @@
         new_parser._set_unknown_encoding_handler()
         return new_parser
 
+ at __pypy__.builtinify
 def ErrorString(errno):
     return XML_ErrorString(errno)[:200]
 
+ at __pypy__.builtinify
 def ParserCreate(encoding=None, namespace_separator=None, intern=None):
     if (not isinstance(encoding, str) and
         not encoding is None):

Modified: pypy/branch/fast-forward/lib_pypy/pypy_test/test_structseq.py
==============================================================================
--- pypy/branch/fast-forward/lib_pypy/pypy_test/test_structseq.py	(original)
+++ pypy/branch/fast-forward/lib_pypy/pypy_test/test_structseq.py	Wed Dec  1 18:08:21 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/fast-forward/lib_pypy/readline.py
==============================================================================
--- pypy/branch/fast-forward/lib_pypy/readline.py	(original)
+++ pypy/branch/fast-forward/lib_pypy/readline.py	Wed Dec  1 18:08:21 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/fast-forward/lib_pypy/resource.py
==============================================================================
--- pypy/branch/fast-forward/lib_pypy/resource.py	(original)
+++ pypy/branch/fast-forward/lib_pypy/resource.py	Wed Dec  1 18:08:21 2010
@@ -1,4 +1,4 @@
-import sys
+import sys, __pypy__
 if sys.platform == 'win32':
     raise ImportError('resource module not available for win32')
 
@@ -77,6 +77,7 @@
     ru_nvcsw = _structseq.structseqfield(14)
     ru_nivcsw = _structseq.structseqfield(15)
 
+ at __pypy__.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 +90,7 @@
         ("rlim_max", rlim_t),
     )
 
+ at __pypy__.builtinify
 def getrusage(who):
     ru = _struct_rusage()
     ret = _getrusage(who, byref(ru))
@@ -116,6 +118,7 @@
         ru.ru_nivcsw,
         ))
 
+ at __pypy__.builtinify
 def getrlimit(resource):
     if not(0 <= resource < RLIM_NLIMITS):
         return ValueError("invalid resource specified")
@@ -127,6 +130,7 @@
         raise error(errno)
     return (rlim.rlim_cur, rlim.rlim_max)
 
+ at __pypy__.builtinify
 def setrlimit(resource, rlim):
     if not(0 <= resource < RLIM_NLIMITS):
         return ValueError("invalid resource specified")
@@ -143,6 +147,7 @@
         else:
             raise error(errno)
 
+ at __pypy__.builtinify
 def getpagesize():
     pagesize = 0
     if _getpagesize:

Modified: pypy/branch/fast-forward/lib_pypy/syslog.py
==============================================================================
--- pypy/branch/fast-forward/lib_pypy/syslog.py	(original)
+++ pypy/branch/fast-forward/lib_pypy/syslog.py	Wed Dec  1 18:08:21 2010
@@ -5,7 +5,7 @@
 syslog facility.
 """
 
-import sys
+import sys, __pypy__
 if sys.platform == 'win32':
     raise ImportError("No syslog on Windows")
 
@@ -34,9 +34,11 @@
 _setlogmask.argtypes = (c_int,)
 _setlogmask.restype = c_int
 
+ at __pypy__.builtinify
 def openlog(ident, option, facility):
     _openlog(ident, option, facility)
 
+ at __pypy__.builtinify
 def syslog(arg1, arg2=None):
     if arg2 is not None:
         priority, message = arg1, arg2
@@ -44,15 +46,19 @@
         priority, message = LOG_INFO, arg1
     _syslog(priority, "%s", message)
 
+ at __pypy__.builtinify
 def closelog():
     _closelog()
 
+ at __pypy__.builtinify
 def setlogmask(mask):
     return _setlogmask(mask)
 
+ at __pypy__.builtinify
 def LOG_MASK(pri):
     return (1 << pri)
 
+ at __pypy__.builtinify
 def LOG_UPTO(pri):
     return (1 << (pri + 1)) - 1
 

Modified: pypy/branch/fast-forward/pypy/annotation/description.py
==============================================================================
--- pypy/branch/fast-forward/pypy/annotation/description.py	(original)
+++ pypy/branch/fast-forward/pypy/annotation/description.py	Wed Dec  1 18:08:21 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:

Modified: pypy/branch/fast-forward/pypy/annotation/listdef.py
==============================================================================
--- pypy/branch/fast-forward/pypy/annotation/listdef.py	(original)
+++ pypy/branch/fast-forward/pypy/annotation/listdef.py	Wed Dec  1 18:08:21 2010
@@ -14,7 +14,7 @@
     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
-    must_not_mutate = False   # list_not_modified_any_more()
+    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.
@@ -38,8 +38,7 @@
         if not self.mutated:
             if self.dont_change_any_more:
                 raise TooLateForChange
-            if self.must_not_mutate:
-                raise ListChangeUnallowed("mutating list")
+            self.immutable = False
             self.mutated = True
 
     def resize(self):
@@ -71,10 +70,7 @@
                     # things more general
                     self, other = other, self
 
-            if other.must_not_mutate:
-                if self.mutated:
-                    raise ListChangeUnallowed("list merge with a mutated")
-                self.must_not_mutate = True
+            self.immutable &= other.immutable
             if other.must_not_resize:
                 if self.resized:
                     raise ListChangeUnallowed("list merge with a resized")
@@ -189,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()
@@ -205,11 +203,17 @@
             raise ListChangeUnallowed("list already resized")
         self.listitem.must_not_resize = True
 
-    def never_mutate(self):
+    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 self.listitem.mutated:
-            raise ListChangeUnallowed("list already mutated")
-        self.listitem.must_not_mutate = True
+        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/fast-forward/pypy/annotation/test/test_annrpython.py
==============================================================================
--- pypy/branch/fast-forward/pypy/annotation/test/test_annrpython.py	(original)
+++ pypy/branch/fast-forward/pypy/annotation/test/test_annrpython.py	Wed Dec  1 18:08:21 2010
@@ -3375,23 +3375,69 @@
         a.build_types(fn, [])
         # assert did not raise ListChangeUnallowed
 
-    def test_list_not_modified_any_more(self):
-        from pypy.rlib.debug import list_not_modified_any_more
+    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
 
-        def pycode(consts):
-            return list_not_modified_any_more(consts)
-        def build1():
-            return pycode(consts=[1])
-        def build2():
-            return pycode(consts=[0])
-        def fn():
-            build1()
-            build2()
+        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()
-        a.translator.config.translation.list_comprehension_operations = True
-        a.build_types(fn, [])
-        # assert did not raise ListChangeUnallowed
+        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/fast-forward/pypy/annotation/unaryop.py
==============================================================================
--- pypy/branch/fast-forward/pypy/annotation/unaryop.py	(original)
+++ pypy/branch/fast-forward/pypy/annotation/unaryop.py	Wed Dec  1 18:08:21 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/fast-forward/pypy/config/pypyoption.py
==============================================================================
--- pypy/branch/fast-forward/pypy/config/pypyoption.py	(original)
+++ pypy/branch/fast-forward/pypy/config/pypyoption.py	Wed Dec  1 18:08:21 2010
@@ -31,7 +31,7 @@
      "crypt", "signal", "_rawffi", "termios", "zlib", "bz2",
      "struct", "_hashlib", "_md5", "_sha", "_minimal_curses", "cStringIO",
      "thread", "itertools", "pyexpat", "_ssl", "cpyext", "array",
-     "_bisect", "_multiprocessing", '_warnings']
+     "_bisect", "binascii", "_multiprocessing", '_warnings']
 ))
 
 translation_modules = default_modules.copy()
@@ -163,7 +163,6 @@
                suggests=[("objspace.allworkingmodules", False)]),
 
     BoolOption("geninterp", "specify whether geninterp should be used",
-               cmdline=None,
                default=True),
 
     BoolOption("logbytecodes",

Modified: pypy/branch/fast-forward/pypy/config/test/test_support.py
==============================================================================
--- pypy/branch/fast-forward/pypy/config/test/test_support.py	(original)
+++ pypy/branch/fast-forward/pypy/config/test/test_support.py	Wed Dec  1 18:08:21 2010
@@ -4,32 +4,32 @@
 import os, sys, py
 
 cpuinfo = """
-processor	: 0
+processor\t: 0
 
-processor	: 1
-vendor_id	: GenuineIntel
-cpu family	: 6
-model		: 37
-model name	: Intel(R) Core(TM) i7 CPU       L 620  @ 2.00GHz
-stepping	: 2
-
-processor	: 2
-vendor_id	: GenuineIntel
-cpu family	: 6
-model		: 37
-model name	: Intel(R) Core(TM) i7 CPU       L 620  @ 2.00GHz
-stepping	: 2
-
-processor	: 3
-vendor_id	: GenuineIntel
-cpu family	: 6
-model		: 37
-model name	: Intel(R) Core(TM) i7 CPU       L 620  @ 2.00GHz
-stepping	: 2
-cpu MHz		: 1199.000
-cache size	: 4096 KB
-physical id	: 0
-siblings	: 4
+processor\t: 1
+vendor_id\t: GenuineIntel
+cpu family\t: 6
+model\t\t: 37
+model name\t: Intel(R) Core(TM) i7 CPU       L 620  @ 2.00GHz
+stepping\t: 2
+
+processor\t: 2
+vendor_id\t: GenuineIntel
+cpu family\t: 6
+model\t\t: 37
+model name\t: Intel(R) Core(TM) i7 CPU       L 620  @ 2.00GHz
+stepping\t: 2
+
+processor\t: 3
+vendor_id\t: GenuineIntel
+cpu family\t: 6
+model\t\t: 37
+model name\t: Intel(R) Core(TM) i7 CPU       L 620  @ 2.00GHz
+stepping\t: 2
+cpu MHz\t\t: 1199.000
+cache size\t: 4096 KB
+physical id\t: 0
+siblings\t: 4
 """
 
 class FakeEnviron:

Modified: pypy/branch/fast-forward/pypy/conftest.py
==============================================================================
--- pypy/branch/fast-forward/pypy/conftest.py	(original)
+++ pypy/branch/fast-forward/pypy/conftest.py	Wed Dec  1 18:08:21 2010
@@ -343,13 +343,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/fast-forward/pypy/doc/cpython_differences.txt
==============================================================================
--- pypy/branch/fast-forward/pypy/doc/cpython_differences.txt	(original)
+++ pypy/branch/fast-forward/pypy/doc/cpython_differences.txt	Wed Dec  1 18:08:21 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/fast-forward/pypy/doc/faq.txt
==============================================================================
--- pypy/branch/fast-forward/pypy/doc/faq.txt	(original)
+++ pypy/branch/fast-forward/pypy/doc/faq.txt	Wed Dec  1 18:08:21 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/fast-forward/pypy/doc/index.txt
==============================================================================
--- pypy/branch/fast-forward/pypy/doc/index.txt	(original)
+++ pypy/branch/fast-forward/pypy/doc/index.txt	Wed Dec  1 18:08:21 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/fast-forward/pypy/doc/release-1.4.0.txt
==============================================================================
--- pypy/branch/fast-forward/pypy/doc/release-1.4.0.txt	(original)
+++ pypy/branch/fast-forward/pypy/doc/release-1.4.0.txt	Wed Dec  1 18:08:21 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/fast-forward/pypy/doc/sprint-reports.txt
==============================================================================
--- pypy/branch/fast-forward/pypy/doc/sprint-reports.txt	(original)
+++ pypy/branch/fast-forward/pypy/doc/sprint-reports.txt	Wed Dec  1 18:08:21 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/fast-forward/pypy/doc/statistic/release_dates.dat
==============================================================================
--- pypy/branch/fast-forward/pypy/doc/statistic/release_dates.dat	(original)
+++ pypy/branch/fast-forward/pypy/doc/statistic/release_dates.dat	Wed Dec  1 18:08:21 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/fast-forward/pypy/doc/statistic/sprint_dates.dat
==============================================================================
--- pypy/branch/fast-forward/pypy/doc/statistic/sprint_dates.dat	(original)
+++ pypy/branch/fast-forward/pypy/doc/statistic/sprint_dates.dat	Wed Dec  1 18:08:21 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/fast-forward/pypy/interpreter/function.py
==============================================================================
--- pypy/branch/fast-forward/pypy/interpreter/function.py	(original)
+++ pypy/branch/fast-forward/pypy/interpreter/function.py	Wed Dec  1 18:08:21 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/fast-forward/pypy/interpreter/gateway.py
==============================================================================
--- pypy/branch/fast-forward/pypy/interpreter/gateway.py	(original)
+++ pypy/branch/fast-forward/pypy/interpreter/gateway.py	Wed Dec  1 18:08:21 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/fast-forward/pypy/interpreter/pycode.py
==============================================================================
--- pypy/branch/fast-forward/pypy/interpreter/pycode.py	(original)
+++ pypy/branch/fast-forward/pypy/interpreter/pycode.py	Wed Dec  1 18:08:21 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, list_not_modified_any_more
+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 = list_not_modified_any_more(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/fast-forward/pypy/interpreter/test/test_gateway.py
==============================================================================
--- pypy/branch/fast-forward/pypy/interpreter/test/test_gateway.py	(original)
+++ pypy/branch/fast-forward/pypy/interpreter/test/test_gateway.py	Wed Dec  1 18:08:21 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/fast-forward/pypy/jit/backend/conftest.py
==============================================================================
--- pypy/branch/fast-forward/pypy/jit/backend/conftest.py	(original)
+++ pypy/branch/fast-forward/pypy/jit/backend/conftest.py	Wed Dec  1 18:08:21 2010
@@ -4,6 +4,8 @@
 """
 import py, random
 
+option = py.test.config.option
+
 def pytest_addoption(parser):
     group = parser.getgroup('random test options')
     group.addoption('--random-seed', action="store", type="int",

Modified: pypy/branch/fast-forward/pypy/jit/backend/detect_cpu.py
==============================================================================
--- pypy/branch/fast-forward/pypy/jit/backend/detect_cpu.py	(original)
+++ pypy/branch/fast-forward/pypy/jit/backend/detect_cpu.py	Wed Dec  1 18:08:21 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/fast-forward/pypy/jit/backend/llsupport/gc.py
==============================================================================
--- pypy/branch/fast-forward/pypy/jit/backend/llsupport/gc.py	(original)
+++ pypy/branch/fast-forward/pypy/jit/backend/llsupport/gc.py	Wed Dec  1 18:08:21 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,152 @@
     LOC_EBP_PLUS  = 2
     LOC_EBP_MINUS = 3
 
-    GCMAP_ARRAY = rffi.CArray(llmemory.Address)
+    GCMAP_ARRAY = rffi.CArray(lltype.Signed)
     CALLSHAPE_ARRAY = rffi.CArray(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 put(self, retaddr, callshapeaddr):
+    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
+
+    @rgc.no_collect
+    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)   # YYY leak
         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
+
+    def add_raw_gcroot_markers(self, asmmemmgr, allblocks,
+                               markers, total_size, rawstart):
+        """The interface is a bit custom, but this routine writes the
+        shapes of gcroots (for the GC to use) into raw memory."""
+        # xxx so far, we never try to share them.  But right now
+        # the amount of potential sharing would not be too large.
+        dst = 1
+        stop = 0
+        for relpos, shape in markers:
+            #
+            if dst + len(shape) > stop:
+                # No more space in the previous raw block,
+                # allocate a raw block of memory big enough to fit
+                # as many of the remaining 'shapes' as possible
+                start, stop = asmmemmgr.malloc(len(shape), total_size)
+                # add the raw block to 'compiled_loop_token.asmmemmgr_blocks'
+                allblocks.append((start, stop))
+                dst = start
+            #
+            # add the entry 'pos_after_call -> dst' to the table
+            self._put(rawstart + relpos, dst)
+            # Copy 'shape' into the raw memory, reversing the order
+            # of the bytes.  Similar to compress_callshape() in
+            # trackgcroot.py.
+            total_size -= len(shape)
+            src = len(shape) - 1
+            while src >= 0:
+                rffi.cast(rffi.CCHARP, dst)[0] = shape[src]
+                dst += 1
+                src -= 1
+
+    @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,18 +409,6 @@
         assert reg_index > 0
         shape.append(chr(self.LOC_REG | (reg_index << 2)))
 
-    def compress_callshape(self, shape):
-        # 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.
-        length = len(shape)
-        compressed = lltype.malloc(self.CALLSHAPE_ARRAY, length,
-                                   flavor='raw',
-                                   track_allocation=False)   # YYY leak
-        for i in range(length):
-            compressed[length-1-i] = rffi.cast(rffi.UCHAR, shape[i])
-        return llmemory.cast_ptr_to_adr(compressed)
-
 
 class WriteBarrierDescr(AbstractDescr):
     def __init__(self, gc_ll_descr):
@@ -379,6 +472,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 +735,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/fast-forward/pypy/jit/backend/llsupport/llmodel.py
==============================================================================
--- pypy/branch/fast-forward/pypy/jit/backend/llsupport/llmodel.py	(original)
+++ pypy/branch/fast-forward/pypy/jit/backend/llsupport/llmodel.py	Wed Dec  1 18:08:21 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/fast-forward/pypy/jit/backend/llsupport/test/test_gc.py
==============================================================================
--- pypy/branch/fast-forward/pypy/jit/backend/llsupport/test/test_gc.py	(original)
+++ pypy/branch/fast-forward/pypy/jit/backend/llsupport/test/test_gc.py	Wed Dec  1 18:08:21 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,214 @@
     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.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]
+        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_put_basic(self):
+        gcrootmap = GcRootMap_asmgcc()
+        retaddr = 1234567890
+        shapeaddr = 51627384
+        gcrootmap._put(retaddr, shapeaddr)
+        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_add_raw_gcroot_markers_maxalloc(self):
+        class FakeAsmMemMgr:
+            def malloc(self, minsize, maxsize):
+                assert minsize == 4
+                assert maxsize == 7
+                return (prawstart, prawstart + 8)
+        put = []
+        def fakeput(a, b):
+            put.append((a, b))
+        gcrootmap = GcRootMap_asmgcc()
+        gcrootmap._put = fakeput
+        memmgr = FakeAsmMemMgr()
+        allblocks = []
+        p = lltype.malloc(rffi.CArray(lltype.Char), 7, immortal=True)
+        prawstart = rffi.cast(lltype.Signed, p)
+        gcrootmap.add_raw_gcroot_markers(memmgr, allblocks,
+                                         [(2, ['a', 'b', 'c', 'd']),
+                                          (4, ['e', 'f', 'g'])],
+                                         4 + 3, 1200000)
+        assert allblocks == [(prawstart, prawstart + 8)]
+        assert ''.join([p[i] for i in range(7)]) == 'dcbagfe'
+        assert put == [(1200002, prawstart),
+                       (1200004, prawstart + 4)]
+
+    def test_add_raw_gcroot_markers_minalloc(self):
+        class FakeAsmMemMgr:
+            callnum = 0
+            def malloc(self, minsize, maxsize):
+                self.callnum += 1
+                if self.callnum == 1:
+                    assert minsize == 4
+                    assert maxsize == 7
+                    return (prawstart, prawstart + 6)
+                elif self.callnum == 2:
+                    assert minsize == 3
+                    assert maxsize == 3
+                    return (qrawstart, qrawstart + 5)
+                else:
+                    raise AssertionError
+        put = []
+        def fakeput(a, b):
+            put.append((a, b))
+        gcrootmap = GcRootMap_asmgcc()
+        gcrootmap._put = fakeput
+        memmgr = FakeAsmMemMgr()
+        allblocks = []
+        p = lltype.malloc(rffi.CArray(lltype.Char), 6, immortal=True)
+        prawstart = rffi.cast(lltype.Signed, p)
+        q = lltype.malloc(rffi.CArray(lltype.Char), 5, immortal=True)
+        qrawstart = rffi.cast(lltype.Signed, q)
+        gcrootmap.add_raw_gcroot_markers(memmgr, allblocks,
+                                         [(2, ['a', 'b', 'c', 'd']),
+                                          (4, ['e', 'f', 'g'])],
+                                         4 + 3, 1200000)
+        assert allblocks == [(prawstart, prawstart + 6),
+                             (qrawstart, qrawstart + 5)]
+        assert ''.join([p[i] for i in range(4)]) == 'dcba'
+        assert ''.join([q[i] for i in range(3)]) == 'gfe'
+        assert put == [(1200002, prawstart),
+                       (1200004, qrawstart)]
+
+    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/fast-forward/pypy/jit/backend/model.py
==============================================================================
--- pypy/branch/fast-forward/pypy/jit/backend/model.py	(original)
+++ pypy/branch/fast-forward/pypy/jit/backend/model.py	Wed Dec  1 18:08:21 2010
@@ -139,10 +139,14 @@
         # 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
-        for n in compiled_loop_token.faildescr_indices:
+        # 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(compiled_loop_token.faildescr_indices)
-        # We expect 'compiled_loop_token' to be itself garbage-collected soon.
+        self.fail_descr_free_list.extend(faildescr_indices)
 
     @staticmethod
     def sizeof(S):
@@ -271,6 +275,9 @@
 
 
 class CompiledLoopToken(object):
+    asmmemmgr_blocks = None
+    asmmemmgr_gcroots = 0
+
     def __init__(self, cpu, number):
         cpu.total_compiled_loops += 1
         self.cpu = cpu

Modified: pypy/branch/fast-forward/pypy/jit/backend/test/runner_test.py
==============================================================================
--- pypy/branch/fast-forward/pypy/jit/backend/test/runner_test.py	(original)
+++ pypy/branch/fast-forward/pypy/jit/backend/test/runner_test.py	Wed Dec  1 18:08:21 2010
@@ -211,6 +211,7 @@
 
         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()
@@ -2229,6 +2230,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/fast-forward/pypy/jit/backend/x86/assembler.py
==============================================================================
--- pypy/branch/fast-forward/pypy/jit/backend/x86/assembler.py	(original)
+++ pypy/branch/fast-forward/pypy/jit/backend/x86/assembler.py	Wed Dec  1 18:08:21 2010
@@ -6,7 +6,6 @@
 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,
@@ -31,7 +30,9 @@
 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, debug_start, debug_stop
+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.jit.metainterp.history import ConstInt, BoxInt
@@ -43,122 +44,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,17 @@
         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.teardown()
 
     def leave_jitted_hook(self):
         ptrs = self.fail_boxes_ptr.ar
@@ -196,54 +93,55 @@
     def set_debug(self, v):
         self._debug = v
 
+    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):
-        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)
-            # 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 = []
+        assert self.memcpy_addr != 0, "setup_once() not called?"
+        self.pending_guard_tokens = []
+        self.mc = codebuf.MachineCodeBlockWrapper()
+
+    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:
             debug_start('jit-backend-counts')
             for i in range(len(self.loop_run_counters)):
-                name, struct = self.loop_run_counters[i]
-                debug_print(str(name) + ':' + str(struct.i))
+                struct = self.loop_run_counters[i]
+                debug_print(str(i) + ':' + str(struct.i))
             debug_stop('jit-backend-counts')
 
     def _build_float_constants(self):
@@ -268,47 +166,51 @@
 
     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
-        """
-        looptoken.compiled_loop_token = CompiledLoopToken(self.cpu,
-                                                          looptoken.number)
+        '''
+        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.currently_compiling_loop = looptoken
         funcname = self._find_debug_merge_point(operations)
         if log:
             self._register_counter()
@@ -318,43 +220,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(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)
 
+        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()
         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])
@@ -363,37 +283,58 @@
         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(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 materialize(self, looptoken):
+        clt = looptoken.compiled_loop_token
+        if clt.asmmemmgr_blocks is None:
+            clt.asmmemmgr_blocks = []
+        return self.mc.materialize(self.cpu.asmmemmgr,
+                                   clt.asmmemmgr_blocks,
+                                   self.cpu.gc_ll_descr.gcrootmap)
 
     def _find_debug_merge_point(self, operations):
 
@@ -408,30 +349,50 @@
 
     def _register_counter(self):
         if self._debug:
-            # YYY leak -- just put it in self.mc instead
+            # 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)
             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 +403,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 +412,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 +432,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 +466,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 +497,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 +515,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 +552,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 +567,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 +609,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 +618,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 +679,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 +752,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 +919,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 +1242,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 +1255,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 +1264,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 +1301,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 +1321,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 +1466,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 +1518,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 +1550,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 +1566,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 +1627,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 +1662,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 +1697,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 +1712,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 +1754,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 +1777,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 +1819,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/fast-forward/pypy/jit/backend/x86/regalloc.py
==============================================================================
--- pypy/branch/fast-forward/pypy/jit/backend/x86/regalloc.py	(original)
+++ pypy/branch/fast-forward/pypy/jit/backend/x86/regalloc.py	Wed Dec  1 18:08:21 2010
@@ -320,11 +320,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 +351,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 +1108,7 @@
             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 shape
 
     def consider_force_token(self, op):
         loc = self.rm.force_allocate_reg(op.result)

Modified: pypy/branch/fast-forward/pypy/jit/backend/x86/regloc.py
==============================================================================
--- pypy/branch/fast-forward/pypy/jit/backend/x86/regloc.py	(original)
+++ pypy/branch/fast-forward/pypy/jit/backend/x86/regloc.py	Wed Dec  1 18:08:21 2010
@@ -334,9 +334,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/fast-forward/pypy/jit/backend/x86/runner.py
==============================================================================
--- pypy/branch/fast-forward/pypy/jit/backend/x86/runner.py	(original)
+++ pypy/branch/fast-forward/pypy/jit/backend/x86/runner.py	Wed Dec  1 18:08:21 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()
@@ -58,7 +59,7 @@
         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)
@@ -127,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,
@@ -168,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/fast-forward/pypy/jit/backend/x86/rx86.py
==============================================================================
--- pypy/branch/fast-forward/pypy/jit/backend/x86/rx86.py	(original)
+++ pypy/branch/fast-forward/pypy/jit/backend/x86/rx86.py	Wed Dec  1 18:08:21 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/fast-forward/pypy/jit/backend/x86/support.py
==============================================================================
--- pypy/branch/fast-forward/pypy/jit/backend/x86/support.py	(original)
+++ pypy/branch/fast-forward/pypy/jit/backend/x86/support.py	Wed Dec  1 18:08:21 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/fast-forward/pypy/jit/backend/x86/test/test_assembler.py
==============================================================================
--- pypy/branch/fast-forward/pypy/jit/backend/x86/test/test_assembler.py	(original)
+++ pypy/branch/fast-forward/pypy/jit/backend/x86/test/test_assembler.py	Wed Dec  1 18:08:21 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/fast-forward/pypy/jit/backend/x86/test/test_gc_integration.py
==============================================================================
--- pypy/branch/fast-forward/pypy/jit/backend/x86/test/test_gc_integration.py	(original)
+++ pypy/branch/fast-forward/pypy/jit/backend/x86/test/test_gc_integration.py	Wed Dec  1 18:08:21 2010
@@ -33,9 +33,6 @@
     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):
-        assert shape[0] == 'shape'
-        return ['compressed'] + shape[1:]
 
 class MockGcDescr(GcCache):
     def get_funcptr_for_new(self):
@@ -58,6 +55,7 @@
 
     def test_mark_gc_roots(self):
         cpu = CPU(None, None)
+        cpu.setup_once()
         regalloc = RegAlloc(MockAssembler(cpu, MockGcDescr(False)))
         boxes = [BoxPtr() for i in range(len(X86RegisterManager.all_regs))]
         longevity = {}
@@ -81,7 +79,7 @@
         assert len(regalloc.assembler.movs) == 3
         #
         mark = regalloc.get_mark_gc_roots(cpu.gc_ll_descr.gcrootmap)
-        assert mark[0] == 'compressed'
+        assert mark[0] == 'shape'
         base = -WORD * FRAME_FIXED_SIZE
         expected = ['ebx', 'esi', 'edi', base, base-WORD, base-WORD*2]
         assert dict.fromkeys(mark[1:]) == dict.fromkeys(expected)
@@ -90,6 +88,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 +213,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/fast-forward/pypy/jit/backend/x86/test/test_regalloc.py
==============================================================================
--- pypy/branch/fast-forward/pypy/jit/backend/x86/test/test_regalloc.py	(original)
+++ pypy/branch/fast-forward/pypy/jit/backend/x86/test/test_regalloc.py	Wed Dec  1 18:08:21 2010
@@ -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:

Modified: pypy/branch/fast-forward/pypy/jit/backend/x86/test/test_regalloc2.py
==============================================================================
--- pypy/branch/fast-forward/pypy/jit/backend/x86/test/test_regalloc2.py	(original)
+++ pypy/branch/fast-forward/pypy/jit/backend/x86/test/test_regalloc2.py	Wed Dec  1 18:08:21 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/fast-forward/pypy/jit/backend/x86/test/test_regloc.py
==============================================================================
--- pypy/branch/fast-forward/pypy/jit/backend/x86/test/test_regloc.py	(original)
+++ pypy/branch/fast-forward/pypy/jit/backend/x86/test/test_regloc.py	Wed Dec  1 18:08:21 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/fast-forward/pypy/jit/backend/x86/test/test_runner.py
==============================================================================
--- pypy/branch/fast-forward/pypy/jit/backend/x86/test/test_runner.py	(original)
+++ pypy/branch/fast-forward/pypy/jit/backend/x86/test/test_runner.py	Wed Dec  1 18:08:21 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()
@@ -398,102 +403,10 @@
         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
@@ -515,14 +428,12 @@
             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'
+            struct = self.cpu.assembler.loop_run_counters[0]
             assert struct.i == 10
             self.cpu.finish_once()
         finally:
             debug._log = None
-        assert dlog[1] == ('jit-backend-counts', [('debug_print', '0:10')])
-            
+        assert ('jit-backend-counts', [('debug_print', '0:10')]) in dlog
 
     def test_debugger_checksum(self):
         loop = """

Modified: pypy/branch/fast-forward/pypy/jit/backend/x86/test/test_rx86.py
==============================================================================
--- pypy/branch/fast-forward/pypy/jit/backend/x86/test/test_rx86.py	(original)
+++ pypy/branch/fast-forward/pypy/jit/backend/x86/test/test_rx86.py	Wed Dec  1 18:08:21 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/fast-forward/pypy/jit/backend/x86/test/test_zll_random.py
==============================================================================
--- pypy/branch/fast-forward/pypy/jit/backend/x86/test/test_zll_random.py	(original)
+++ pypy/branch/fast-forward/pypy/jit/backend/x86/test/test_zll_random.py	Wed Dec  1 18:08:21 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/fast-forward/pypy/jit/backend/x86/test/test_zmath.py
==============================================================================
--- pypy/branch/fast-forward/pypy/jit/backend/x86/test/test_zmath.py	(original)
+++ pypy/branch/fast-forward/pypy/jit/backend/x86/test/test_zmath.py	Wed Dec  1 18:08:21 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/fast-forward/pypy/jit/backend/x86/test/test_ztranslation.py
==============================================================================
--- pypy/branch/fast-forward/pypy/jit/backend/x86/test/test_ztranslation.py	(original)
+++ pypy/branch/fast-forward/pypy/jit/backend/x86/test/test_ztranslation.py	Wed Dec  1 18:08:21 2010
@@ -87,13 +87,8 @@
             return int(res)
         #
         def main(i, j):
-            res = f(i, j) + libffi_stuff(i, j)
-            fd = os.open('/tmp/x', os.O_WRONLY | os.O_CREAT, 0666)
-            rgc.dump_rpy_heap(fd)
-            os.close(fd)
-            return res
-        #expected = main(40, -49)
-        expected = 3
+            return f(i, j) + libffi_stuff(i, j)
+        expected = main(40, -49)
         res = self.meta_interp(main, [40, -49])
         assert res == expected
 

Modified: pypy/branch/fast-forward/pypy/jit/backend/x86/valgrind.py
==============================================================================
--- pypy/branch/fast-forward/pypy/jit/backend/x86/valgrind.py	(original)
+++ pypy/branch/fast-forward/pypy/jit/backend/x86/valgrind.py	Wed Dec  1 18:08:21 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/fast-forward/pypy/jit/codewriter/call.py
==============================================================================
--- pypy/branch/fast-forward/pypy/jit/codewriter/call.py	(original)
+++ pypy/branch/fast-forward/pypy/jit/codewriter/call.py	Wed Dec  1 18:08:21 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/fast-forward/pypy/jit/codewriter/jtransform.py
==============================================================================
--- pypy/branch/fast-forward/pypy/jit/codewriter/jtransform.py	(original)
+++ pypy/branch/fast-forward/pypy/jit/codewriter/jtransform.py	Wed Dec  1 18:08:21 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/fast-forward/pypy/jit/codewriter/support.py
==============================================================================
--- pypy/branch/fast-forward/pypy/jit/codewriter/support.py	(original)
+++ pypy/branch/fast-forward/pypy/jit/codewriter/support.py	Wed Dec  1 18:08:21 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/fast-forward/pypy/jit/codewriter/test/test_codewriter.py
==============================================================================
--- pypy/branch/fast-forward/pypy/jit/codewriter/test/test_codewriter.py	(original)
+++ pypy/branch/fast-forward/pypy/jit/codewriter/test/test_codewriter.py	Wed Dec  1 18:08:21 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/fast-forward/pypy/jit/codewriter/test/test_list.py
==============================================================================
--- pypy/branch/fast-forward/pypy/jit/codewriter/test/test_list.py	(original)
+++ pypy/branch/fast-forward/pypy/jit/codewriter/test/test_list.py	Wed Dec  1 18:08:21 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/fast-forward/pypy/jit/codewriter/test/test_void_list.py
==============================================================================
--- pypy/branch/fast-forward/pypy/jit/codewriter/test/test_void_list.py	(original)
+++ pypy/branch/fast-forward/pypy/jit/codewriter/test/test_void_list.py	Wed Dec  1 18:08:21 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/fast-forward/pypy/jit/metainterp/history.py
==============================================================================
--- pypy/branch/fast-forward/pypy/jit/metainterp/history.py	(original)
+++ pypy/branch/fast-forward/pypy/jit/metainterp/history.py	Wed Dec  1 18:08:21 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, r_longlong
-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
@@ -731,7 +730,7 @@
     # specnodes = ...
     # and more data specified by the backend when the loop is compiled
     number = -1
-    generation = r_longlong(0)
+    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

Modified: pypy/branch/fast-forward/pypy/jit/metainterp/memmgr.py
==============================================================================
--- pypy/branch/fast-forward/pypy/jit/metainterp/memmgr.py	(original)
+++ pypy/branch/fast-forward/pypy/jit/metainterp/memmgr.py	Wed Dec  1 18:08:21 2010
@@ -1,5 +1,5 @@
 import math
-from pypy.rlib.rarithmetic import r_longlong
+from pypy.rlib.rarithmetic import r_int64
 from pypy.rlib.debug import debug_start, debug_print, debug_stop
 from pypy.rlib.objectmodel import we_are_translated
 
@@ -24,7 +24,7 @@
 
     def __init__(self):
         self.check_frequency = -1
-        # NB. use of r_longlong to be extremely far on the safe side:
+        # NB. use of r_int64 to be extremely far on the safe side:
         # this is increasing by one after each loop or bridge is
         # compiled, and it must not overflow.  If the backend implements
         # complete freeing in cpu.free_loop_and_bridges(), then it may
@@ -32,13 +32,13 @@
         # enough.  But in this day and age, you'd still never have the
         # patience of waiting for a slowly-increasing 64-bit number to
         # overflow :-)
-        self.current_generation = r_longlong(1)
-        self.next_check = r_longlong(-1)
+        self.current_generation = r_int64(1)
+        self.next_check = r_int64(-1)
         self.alive_loops = {}
 
     def set_max_age(self, max_age, check_frequency=0):
         if max_age <= 0:
-            self.next_check = r_longlong(-1)
+            self.next_check = r_int64(-1)
         else:
             self.max_age = max_age
             if check_frequency <= 0:

Modified: pypy/branch/fast-forward/pypy/jit/metainterp/pyjitpl.py
==============================================================================
--- pypy/branch/fast-forward/pypy/jit/metainterp/pyjitpl.py	(original)
+++ pypy/branch/fast-forward/pypy/jit/metainterp/pyjitpl.py	Wed Dec  1 18:08:21 2010
@@ -612,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)
 

Modified: pypy/branch/fast-forward/pypy/jit/metainterp/test/test_basic.py
==============================================================================
--- pypy/branch/fast-forward/pypy/jit/metainterp/test/test_basic.py	(original)
+++ pypy/branch/fast-forward/pypy/jit/metainterp/test/test_basic.py	Wed Dec  1 18:08:21 2010
@@ -1701,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/fast-forward/pypy/jit/metainterp/test/test_list.py
==============================================================================
--- pypy/branch/fast-forward/pypy/jit/metainterp/test/test_list.py	(original)
+++ pypy/branch/fast-forward/pypy/jit/metainterp/test/test_list.py	Wed Dec  1 18:08:21 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/fast-forward/pypy/jit/metainterp/test/test_memmgr.py
==============================================================================
--- pypy/branch/fast-forward/pypy/jit/metainterp/test/test_memmgr.py	(original)
+++ pypy/branch/fast-forward/pypy/jit/metainterp/test/test_memmgr.py	Wed Dec  1 18:08:21 2010
@@ -1,9 +1,10 @@
-import sys, py
+import sys
 if len(sys.argv) >= 4 and sys.argv[1] == '--sub':
     sys.path[:] = eval(sys.argv[2])      # hacks for test_integration
     from pypy.conftest import option
     option.__dict__.update(eval(sys.argv[3]))
 
+import py
 from pypy.jit.metainterp.memmgr import MemoryManager
 from pypy.jit.metainterp.test.test_basic import LLJitMixin
 from pypy.rlib.jit import JitDriver, dont_look_inside

Modified: pypy/branch/fast-forward/pypy/jit/metainterp/test/test_recursive.py
==============================================================================
--- pypy/branch/fast-forward/pypy/jit/metainterp/test/test_recursive.py	(original)
+++ pypy/branch/fast-forward/pypy/jit/metainterp/test/test_recursive.py	Wed Dec  1 18:08:21 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/fast-forward/pypy/jit/metainterp/test/test_virtualizable.py
==============================================================================
--- pypy/branch/fast-forward/pypy/jit/metainterp/test/test_virtualizable.py	(original)
+++ pypy/branch/fast-forward/pypy/jit/metainterp/test/test_virtualizable.py	Wed Dec  1 18:08:21 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/fast-forward/pypy/jit/metainterp/warmspot.py
==============================================================================
--- pypy/branch/fast-forward/pypy/jit/metainterp/warmspot.py	(original)
+++ pypy/branch/fast-forward/pypy/jit/metainterp/warmspot.py	Wed Dec  1 18:08:21 2010
@@ -159,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()
@@ -256,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

Modified: pypy/branch/fast-forward/pypy/jit/tl/spli/interpreter.py
==============================================================================
--- pypy/branch/fast-forward/pypy/jit/tl/spli/interpreter.py	(original)
+++ pypy/branch/fast-forward/pypy/jit/tl/spli/interpreter.py	Wed Dec  1 18:08:21 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/fast-forward/pypy/jit/tl/tl.py
==============================================================================
--- pypy/branch/fast-forward/pypy/jit/tl/tl.py	(original)
+++ pypy/branch/fast-forward/pypy/jit/tl/tl.py	Wed Dec  1 18:08:21 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/fast-forward/pypy/jit/tool/log-template.gnumeric
==============================================================================
Binary files. No diff available.

Modified: pypy/branch/fast-forward/pypy/jit/tool/log2gnumeric.py
==============================================================================
--- pypy/branch/fast-forward/pypy/jit/tool/log2gnumeric.py	(original)
+++ pypy/branch/fast-forward/pypy/jit/tool/log2gnumeric.py	Wed Dec  1 18:08:21 2010
@@ -14,25 +14,34 @@
 
 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', '')
-    maxclock = find_max_clock(data)
+    minclock, maxclock = get_clock_range(data)
+    time0 = minclock # we want "relative clocks"
+    maxtime = maxclock-time0
     #
     xml = gzip.open('log-template.gnumeric').read()
-    xml = replace_sheet(xml, 'translation-task', tasks_rows(data))
-    xml = replace_sheet(xml, 'gc-collect', gc_collect_rows(data))
-    xml = replace_sheet(xml, 'memusage', memusage_rows(logname + '.memusage', maxclock))
+    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>)'
     regex = re.compile(pattern % sheet_name, re.DOTALL)
@@ -68,7 +77,22 @@
     return '\n'.join(parts)
     
 
-def gc_collect_rows(data):
+# ========================================================================
+# 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:
@@ -84,35 +108,73 @@
     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 memusage_rows(filename, maxclock):
-    try:
-        lines = open(filename)
-    except IOError:
-        print 'Warning: cannot find file %s, skipping the memusage sheet'
-        lines = []
-    yield 'n', 'computed clock', 'VmRSS'
+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)
-        yield i, "=max('gc-collect'!$A$1:$A$65536)*(A2/max($A$1:$A$65536)))", mem
+        clock = maxtime * i // (numlines-1)
+        yield clock, mem
 
-def find_max_clock(data):
-    s = r"\[([0-9a-f]+)\] "
-    r = re.compile(s)
-    clocks = [int(x, 16) for x in r.findall(data)]
-    return max(clocks)
 
 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/fast-forward/pypy/module/__pypy__/__init__.py
==============================================================================
--- pypy/branch/fast-forward/pypy/module/__pypy__/__init__.py	(original)
+++ pypy/branch/fast-forward/pypy/module/__pypy__/__init__.py	Wed Dec  1 18:08:21 2010
@@ -15,6 +15,7 @@
         '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/fast-forward/pypy/module/__pypy__/interp_magic.py
==============================================================================
--- pypy/branch/fast-forward/pypy/module/__pypy__/interp_magic.py	(original)
+++ pypy/branch/fast-forward/pypy/module/__pypy__/interp_magic.py	Wed Dec  1 18:08:21 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/fast-forward/pypy/module/__pypy__/test/test_special.py
==============================================================================
--- pypy/branch/fast-forward/pypy/module/__pypy__/test/test_special.py	(original)
+++ pypy/branch/fast-forward/pypy/module/__pypy__/test/test_special.py	Wed Dec  1 18:08:21 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/fast-forward/pypy/module/cpyext/api.py
==============================================================================
--- pypy/branch/fast-forward/pypy/module/cpyext/api.py	(original)
+++ pypy/branch/fast-forward/pypy/module/cpyext/api.py	Wed Dec  1 18:08:21 2010
@@ -326,6 +326,8 @@
     'PyCapsule_SetContext', 'PyCapsule_Import', 'PyCapsule_Type', 'init_capsule',
 
     'PyObject_AsReadBuffer', 'PyObject_AsWriteBuffer', 'PyObject_CheckReadBuffer',
+
+    'PyStructSequence_InitType', 'PyStructSequence_New',
 ]
 TYPES = {}
 GLOBALS = { # this needs to include all prebuilt pto, otherwise segfaults occur
@@ -372,7 +374,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()
@@ -874,6 +876,7 @@
                                source_dir / "bufferobject.c",
                                source_dir / "object.c",
                                source_dir / "cobject.c",
+                               source_dir / "structseq.c",
                                source_dir / "capsule.c",
                                ],
         separate_module_sources=separate_module_sources,

Modified: pypy/branch/fast-forward/pypy/module/cpyext/cdatetime.py
==============================================================================
--- pypy/branch/fast-forward/pypy/module/cpyext/cdatetime.py	(original)
+++ pypy/branch/fast-forward/pypy/module/cpyext/cdatetime.py	Wed Dec  1 18:08:21 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/fast-forward/pypy/module/cpyext/include/tupleobject.h
==============================================================================
--- pypy/branch/fast-forward/pypy/module/cpyext/include/tupleobject.h	(original)
+++ pypy/branch/fast-forward/pypy/module/cpyext/include/tupleobject.h	Wed Dec  1 18:08:21 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/fast-forward/pypy/module/cpyext/sequence.py
==============================================================================
--- pypy/branch/fast-forward/pypy/module/cpyext/sequence.py	(original)
+++ pypy/branch/fast-forward/pypy/module/cpyext/sequence.py	Wed Dec  1 18:08:21 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/fast-forward/pypy/module/cpyext/slotdefs.py
==============================================================================
--- pypy/branch/fast-forward/pypy/module/cpyext/slotdefs.py	(original)
+++ pypy/branch/fast-forward/pypy/module/cpyext/slotdefs.py	Wed Dec  1 18:08:21 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/fast-forward/pypy/module/cpyext/state.py
==============================================================================
--- pypy/branch/fast-forward/pypy/module/cpyext/state.py	(original)
+++ pypy/branch/fast-forward/pypy/module/cpyext/state.py	Wed Dec  1 18:08:21 2010
@@ -6,8 +6,6 @@
 import sys
 
 class State:
-    datetimeAPI = None # used in tests
-
     def __init__(self, space):
         self.space = space
         self.reset()

Modified: pypy/branch/fast-forward/pypy/module/cpyext/stubs.py
==============================================================================
--- pypy/branch/fast-forward/pypy/module/cpyext/stubs.py	(original)
+++ pypy/branch/fast-forward/pypy/module/cpyext/stubs.py	Wed Dec  1 18:08:21 2010
@@ -2254,13 +2254,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/fast-forward/pypy/module/cpyext/test/test_arraymodule.py
==============================================================================
--- pypy/branch/fast-forward/pypy/module/cpyext/test/test_arraymodule.py	(original)
+++ pypy/branch/fast-forward/pypy/module/cpyext/test/test_arraymodule.py	Wed Dec  1 18:08:21 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/fast-forward/pypy/module/cpyext/test/test_cpyext.py
==============================================================================
--- pypy/branch/fast-forward/pypy/module/cpyext/test/test_cpyext.py	(original)
+++ pypy/branch/fast-forward/pypy/module/cpyext/test/test_cpyext.py	Wed Dec  1 18:08:21 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
@@ -88,6 +90,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
@@ -98,13 +117,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
@@ -114,7 +126,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:
@@ -146,6 +163,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.
@@ -265,13 +284,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)."
 
@@ -541,16 +554,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/fast-forward/pypy/module/cpyext/test/test_datetime.py
==============================================================================
--- pypy/branch/fast-forward/pypy/module/cpyext/test/test_datetime.py	(original)
+++ pypy/branch/fast-forward/pypy/module/cpyext/test/test_datetime.py	Wed Dec  1 18:08:21 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/fast-forward/pypy/module/cpyext/test/test_sequence.py
==============================================================================
--- pypy/branch/fast-forward/pypy/module/cpyext/test/test_sequence.py	(original)
+++ pypy/branch/fast-forward/pypy/module/cpyext/test/test_sequence.py	Wed Dec  1 18:08:21 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/fast-forward/pypy/module/cpyext/test/test_tupleobject.py
==============================================================================
--- pypy/branch/fast-forward/pypy/module/cpyext/test/test_tupleobject.py	(original)
+++ pypy/branch/fast-forward/pypy/module/cpyext/test/test_tupleobject.py	Wed Dec  1 18:08:21 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/fast-forward/pypy/module/cpyext/test/test_typeobject.py
==============================================================================
--- pypy/branch/fast-forward/pypy/module/cpyext/test/test_typeobject.py	(original)
+++ pypy/branch/fast-forward/pypy/module/cpyext/test/test_typeobject.py	Wed Dec  1 18:08:21 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/fast-forward/pypy/module/cpyext/tupleobject.py
==============================================================================
--- pypy/branch/fast-forward/pypy/module/cpyext/tupleobject.py	(original)
+++ pypy/branch/fast-forward/pypy/module/cpyext/tupleobject.py	Wed Dec  1 18:08:21 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/fast-forward/pypy/module/cpyext/typeobject.py
==============================================================================
--- pypy/branch/fast-forward/pypy/module/cpyext/typeobject.py	(original)
+++ pypy/branch/fast-forward/pypy/module/cpyext/typeobject.py	Wed Dec  1 18:08:21 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/fast-forward/pypy/module/fcntl/test/test_fcntl.py
==============================================================================
--- pypy/branch/fast-forward/pypy/module/fcntl/test/test_fcntl.py	(original)
+++ pypy/branch/fast-forward/pypy/module/fcntl/test/test_fcntl.py	Wed Dec  1 18:08:21 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/fast-forward/pypy/module/imp/importing.py
==============================================================================
--- pypy/branch/fast-forward/pypy/module/imp/importing.py	(original)
+++ pypy/branch/fast-forward/pypy/module/imp/importing.py	Wed Dec  1 18:08:21 2010
@@ -77,7 +77,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/fast-forward/pypy/module/itertools/interp_itertools.py
==============================================================================
--- pypy/branch/fast-forward/pypy/module/itertools/interp_itertools.py	(original)
+++ pypy/branch/fast-forward/pypy/module/itertools/interp_itertools.py	Wed Dec  1 18:08:21 2010
@@ -394,18 +394,20 @@
             raise OperationError(self.space.w_StopIteration, self.space.w_None)
         if not self.w_it:
             self._advance()
+        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._advance() # may raise StopIteration itself
             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._advance() # may raise StopIteration itself
-                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):
     w_args = space.newtuple(args_w)
@@ -443,8 +445,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
@@ -467,12 +471,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:
@@ -827,15 +845,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
@@ -857,6 +867,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/fast-forward/pypy/module/posix/__init__.py
==============================================================================
--- pypy/branch/fast-forward/pypy/module/posix/__init__.py	(original)
+++ pypy/branch/fast-forward/pypy/module/posix/__init__.py	Wed Dec  1 18:08:21 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/fast-forward/pypy/module/posix/interp_posix.py
==============================================================================
--- pypy/branch/fast-forward/pypy/module/posix/interp_posix.py	(original)
+++ pypy/branch/fast-forward/pypy/module/posix/interp_posix.py	Wed Dec  1 18:08:21 2010
@@ -653,6 +653,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/fast-forward/pypy/module/posix/test/test_posix2.py
==============================================================================
--- pypy/branch/fast-forward/pypy/module/posix/test/test_posix2.py	(original)
+++ pypy/branch/fast-forward/pypy/module/posix/test/test_posix2.py	Wed Dec  1 18:08:21 2010
@@ -333,6 +333,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/fast-forward/pypy/module/pyexpat/test/test_parser.py
==============================================================================
--- pypy/branch/fast-forward/pypy/module/pyexpat/test/test_parser.py	(original)
+++ pypy/branch/fast-forward/pypy/module/pyexpat/test/test_parser.py	Wed Dec  1 18:08:21 2010
@@ -16,6 +16,20 @@
 
         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"]
+
     def test_intern(self):
         import pyexpat
         p = pyexpat.ParserCreate()

Modified: pypy/branch/fast-forward/pypy/module/pypyjit/policy.py
==============================================================================
--- pypy/branch/fast-forward/pypy/module/pypyjit/policy.py	(original)
+++ pypy/branch/fast-forward/pypy/module/pypyjit/policy.py	Wed Dec  1 18:08:21 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/fast-forward/pypy/module/pypyjit/test/test_policy.py
==============================================================================
--- pypy/branch/fast-forward/pypy/module/pypyjit/test/test_policy.py	(original)
+++ pypy/branch/fast-forward/pypy/module/pypyjit/test/test_policy.py	Wed Dec  1 18:08:21 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/fast-forward/pypy/module/pypyjit/test/test_pypy_c.py
==============================================================================
--- pypy/branch/fast-forward/pypy/module/pypyjit/test/test_pypy_c.py	(original)
+++ pypy/branch/fast-forward/pypy/module/pypyjit/test/test_pypy_c.py	Wed Dec  1 18:08:21 2010
@@ -630,6 +630,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
@@ -673,11 +699,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/fast-forward/pypy/module/sys/__init__.py
==============================================================================
--- pypy/branch/fast-forward/pypy/module/sys/__init__.py	(original)
+++ pypy/branch/fast-forward/pypy/module/sys/__init__.py	Wed Dec  1 18:08:21 2010
@@ -65,8 +65,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/fast-forward/pypy/objspace/std/mapdict.py
==============================================================================
--- pypy/branch/fast-forward/pypy/objspace/std/mapdict.py	(original)
+++ pypy/branch/fast-forward/pypy/objspace/std/mapdict.py	Wed Dec  1 18:08:21 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/fast-forward/pypy/objspace/std/objspace.py
==============================================================================
--- pypy/branch/fast-forward/pypy/objspace/std/objspace.py	(original)
+++ pypy/branch/fast-forward/pypy/objspace/std/objspace.py	Wed Dec  1 18:08:21 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/fast-forward/pypy/rlib/debug.py
==============================================================================
--- pypy/branch/fast-forward/pypy/rlib/debug.py	(original)
+++ pypy/branch/fast-forward/pypy/rlib/debug.py	Wed Dec  1 18:08:21 2010
@@ -226,33 +226,6 @@
         hop.exception_cannot_occur()
         return hop.inputarg(hop.args_r[0], arg=0)
 
-def list_not_modified_any_more(arg):
-    """ Returns an annotator-time copy of the list 'arg' which is
-    flagged as 'don't mutate me'.  Actually implemented as just
-    returning 'arg'.  This is useful for debugging only.
-    """
-    return arg
-
-class Entry(ExtRegistryEntry):
-    _about_ = list_not_modified_any_more
-
-    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 = s_arg.listdef.offspring()
-            s_arg.listdef.never_mutate()
-        else:
-            from pypy.annotation.annrpython import log
-            log.WARNING('list_not_modified_any_more 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/fast-forward/pypy/rlib/libffi.py
==============================================================================
--- pypy/branch/fast-forward/pypy/rlib/libffi.py	(original)
+++ pypy/branch/fast-forward/pypy/rlib/libffi.py	Wed Dec  1 18:08:21 2010
@@ -178,6 +178,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/fast-forward/pypy/rlib/rarithmetic.py
==============================================================================
--- pypy/branch/fast-forward/pypy/rlib/rarithmetic.py	(original)
+++ pypy/branch/fast-forward/pypy/rlib/rarithmetic.py	Wed Dec  1 18:08:21 2010
@@ -185,7 +185,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
@@ -486,6 +487,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/fast-forward/pypy/rlib/rdynload.py
==============================================================================
--- pypy/branch/fast-forward/pypy/rlib/rdynload.py	(original)
+++ pypy/branch/fast-forward/pypy/rlib/rdynload.py	Wed Dec  1 18:08:21 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/fast-forward/pypy/rlib/rsre/rsre_core.py
==============================================================================
--- pypy/branch/fast-forward/pypy/rlib/rsre/rsre_core.py	(original)
+++ pypy/branch/fast-forward/pypy/rlib/rsre/rsre_core.py	Wed Dec  1 18:08:21 2010
@@ -1,5 +1,5 @@
 import sys
-from pypy.rlib.debug import check_nonneg, list_not_modified_any_more
+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
@@ -91,7 +91,7 @@
         # and they must not be more than len(string).
         check_nonneg(match_start)
         check_nonneg(end)
-        self.pattern = list_not_modified_any_more(pattern)
+        self.pattern = pattern
         self.match_start = match_start
         self.end = end
         self.flags = flags

Modified: pypy/branch/fast-forward/pypy/rlib/test/test_libffi.py
==============================================================================
--- pypy/branch/fast-forward/pypy/rlib/test/test_libffi.py	(original)
+++ pypy/branch/fast-forward/pypy/rlib/test/test_libffi.py	Wed Dec  1 18:08:21 2010
@@ -262,3 +262,24 @@
         #
         res = self.call(get_dummy, [], rffi.LONG)
         assert res == initval+1
+
+    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/fast-forward/pypy/rpython/lltypesystem/ll2ctypes.py
==============================================================================
--- pypy/branch/fast-forward/pypy/rpython/lltypesystem/ll2ctypes.py	(original)
+++ pypy/branch/fast-forward/pypy/rpython/lltypesystem/ll2ctypes.py	Wed Dec  1 18:08:21 2010
@@ -446,6 +446,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
@@ -1299,7 +1302,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/fast-forward/pypy/rpython/lltypesystem/llmemory.py
==============================================================================
--- pypy/branch/fast-forward/pypy/rpython/lltypesystem/llmemory.py	(original)
+++ pypy/branch/fast-forward/pypy/rpython/lltypesystem/llmemory.py	Wed Dec  1 18:08:21 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/fast-forward/pypy/rpython/memory/gc/inspector.py
==============================================================================
--- pypy/branch/fast-forward/pypy/rpython/memory/gc/inspector.py	(original)
+++ pypy/branch/fast-forward/pypy/rpython/memory/gc/inspector.py	Wed Dec  1 18:08:21 2010
@@ -101,7 +101,7 @@
 
 AddressStack = get_address_stack()
 
-class HeapDumper:
+class HeapDumper(object):
     _alloc_flavor_ = "raw"
     BUFSIZE = 8192     # words
 

Modified: pypy/branch/fast-forward/pypy/rpython/memory/gc/test/test_direct.py
==============================================================================
--- pypy/branch/fast-forward/pypy/rpython/memory/gc/test/test_direct.py	(original)
+++ pypy/branch/fast-forward/pypy/rpython/memory/gc/test/test_direct.py	Wed Dec  1 18:08:21 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

Modified: pypy/branch/fast-forward/pypy/rpython/memory/gctransform/asmgcroot.py
==============================================================================
--- pypy/branch/fast-forward/pypy/rpython/memory/gctransform/asmgcroot.py	(original)
+++ pypy/branch/fast-forward/pypy/rpython/memory/gctransform/asmgcroot.py	Wed Dec  1 18:08:21 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/fast-forward/pypy/rpython/module/ll_os.py
==============================================================================
--- pypy/branch/fast-forward/pypy/rpython/module/ll_os.py	(original)
+++ pypy/branch/fast-forward/pypy/rpython/module/ll_os.py	Wed Dec  1 18:08:21 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/fast-forward/pypy/rpython/module/ll_time.py
==============================================================================
--- pypy/branch/fast-forward/pypy/rpython/module/ll_time.py	(original)
+++ pypy/branch/fast-forward/pypy/rpython/module/ll_time.py	Wed Dec  1 18:08:21 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/fast-forward/pypy/rpython/rlist.py
==============================================================================
--- pypy/branch/fast-forward/pypy/rpython/rlist.py	(original)
+++ pypy/branch/fast-forward/pypy/rpython/rlist.py	Wed Dec  1 18:08:21 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/fast-forward/pypy/rpython/test/test_rint.py
==============================================================================
--- pypy/branch/fast-forward/pypy/rpython/test/test_rint.py	(original)
+++ pypy/branch/fast-forward/pypy/rpython/test/test_rint.py	Wed Dec  1 18:08:21 2010
@@ -4,15 +4,10 @@
 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.rlib import objectmodel
 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):
 
@@ -111,10 +106,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):
@@ -136,7 +131,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])
@@ -148,7 +143,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):
@@ -158,7 +153,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)'
@@ -166,7 +161,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):
@@ -179,25 +174,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():
@@ -232,16 +227,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
@@ -304,7 +299,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/fast-forward/pypy/rpython/test/test_rlist.py
==============================================================================
--- pypy/branch/fast-forward/pypy/rpython/test/test_rlist.py	(original)
+++ pypy/branch/fast-forward/pypy/rpython/test/test_rlist.py	Wed Dec  1 18:08:21 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/fast-forward/pypy/rpython/tool/rffi_platform.py
==============================================================================
--- pypy/branch/fast-forward/pypy/rpython/tool/rffi_platform.py	(original)
+++ pypy/branch/fast-forward/pypy/rpython/tool/rffi_platform.py	Wed Dec  1 18:08:21 2010
@@ -673,6 +673,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/fast-forward/pypy/tool/ansi_print.py
==============================================================================
--- pypy/branch/fast-forward/pypy/tool/ansi_print.py	(original)
+++ pypy/branch/fast-forward/pypy/tool/ansi_print.py	Wed Dec  1 18:08:21 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/fast-forward/pypy/tool/logparser.py
==============================================================================
--- pypy/branch/fast-forward/pypy/tool/logparser.py	(original)
+++ pypy/branch/fast-forward/pypy/tool/logparser.py	Wed Dec  1 18:08:21 2010
@@ -25,7 +25,7 @@
     return parse_log(lines, verbose=verbose)
 
 def parse_log(lines, verbose=False):
-    color = "(?:\x1b.*?m)"
+    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

Modified: pypy/branch/fast-forward/pypy/translator/c/gcc/trackgcroot.py
==============================================================================
--- pypy/branch/fast-forward/pypy/translator/c/gcc/trackgcroot.py	(original)
+++ pypy/branch/fast-forward/pypy/translator/c/gcc/trackgcroot.py	Wed Dec  1 18:08:21 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/fast-forward/pypy/translator/c/src/mem.h
==============================================================================
--- pypy/branch/fast-forward/pypy/translator/c/src/mem.h	(original)
+++ pypy/branch/fast-forward/pypy/translator/c/src/mem.h	Wed Dec  1 18:08:21 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/fast-forward/pypy/translator/goal/app_main.py
==============================================================================
--- pypy/branch/fast-forward/pypy/translator/goal/app_main.py	(original)
+++ pypy/branch/fast-forward/pypy/translator/goal/app_main.py	Wed Dec  1 18:08:21 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
 """
@@ -204,7 +205,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
@@ -225,7 +226,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
@@ -235,7 +236,6 @@
         if dir not in _seen:
             sys.path.append(dir)
             _seen[dir] = True
-    return executable
 
 # Order is significant!
 sys_flags = (
@@ -271,6 +271,7 @@
     options['warnoptions'] = []
     print_sys_flags = False
     i = 0
+    readenv = True
     while i < len(argv):
         arg = argv[i]
         if not arg.startswith('-'):
@@ -310,6 +311,8 @@
             argv[i] = '-c'
             options["run_command"] = True
             break
+        elif arg == '-E':
+            readenv = False
         elif arg == '-u':
             options["unbuffered"] = True
         elif arg == '-O' or arg == '-OO':
@@ -378,6 +381,7 @@
                      run_stdin,
                      warnoptions,
                      unbuffered,
+                     readenv,
                      cmd=None,
                      **ignored):
     # with PyPy in top of CPython we can only have around 100 
@@ -431,7 +435,7 @@
         #     * PYTHONINSPECT is set and stdin is a tty.
         #
         return (interactive or
-                (os.getenv('PYTHONINSPECT') and sys.stdin.isatty()))
+            (readenv and os.getenv('PYTHONINSPECT') and sys.stdin.isatty()))
 
     success = True
 
@@ -464,7 +468,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)
@@ -538,7 +542,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:
@@ -546,8 +549,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__':
@@ -582,13 +585,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/fast-forward/pypy/translator/goal/test2/test_app_main.py
==============================================================================
--- pypy/branch/fast-forward/pypy/translator/goal/test2/test_app_main.py	(original)
+++ pypy/branch/fast-forward/pypy/translator/goal/test2/test_app_main.py	Wed Dec  1 18:08:21 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])
@@ -334,6 +366,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/fast-forward/pypy/translator/platform/__init__.py
==============================================================================
--- pypy/branch/fast-forward/pypy/translator/platform/__init__.py	(original)
+++ pypy/branch/fast-forward/pypy/translator/platform/__init__.py	Wed Dec  1 18:08:21 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/fast-forward/pypy/translator/platform/darwin.py
==============================================================================
--- pypy/branch/fast-forward/pypy/translator/platform/darwin.py	(original)
+++ pypy/branch/fast-forward/pypy/translator/platform/darwin.py	Wed Dec  1 18:08:21 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/fast-forward/pypy/translator/tool/cbuild.py
==============================================================================
--- pypy/branch/fast-forward/pypy/translator/tool/cbuild.py	(original)
+++ pypy/branch/fast-forward/pypy/translator/tool/cbuild.py	Wed Dec  1 18:08:21 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
 '''



More information about the Pypy-commit mailing list