[pypy-svn] r78530 - in pypy/branch/jit-unroll-loops: . dotviewer lib-python lib-python/modified-2.5.2/test lib_pypy/_ctypes pypy pypy/annotation pypy/annotation/test pypy/config pypy/config/test pypy/doc pypy/doc/config pypy/interpreter pypy/interpreter/astcompiler/test pypy/interpreter/pyparser pypy/interpreter/test pypy/jit/backend pypy/jit/backend/llgraph pypy/jit/backend/llsupport pypy/jit/backend/llsupport/test pypy/jit/backend/test pypy/jit/backend/x86 pypy/jit/backend/x86/test pypy/jit/codewriter pypy/jit/codewriter/test pypy/jit/metainterp pypy/jit/metainterp/optimizeopt pypy/jit/metainterp/test pypy/jit/tl pypy/jit/tl/spli pypy/jit/tl/tla pypy/jit/tool pypy/module/__builtin__ pypy/module/__builtin__/test pypy/module/_bisect pypy/module/_bisect/test pypy/module/_ffi pypy/module/_ffi/test pypy/module/_rawffi pypy/module/_rawffi/test pypy/module/_socket/test pypy/module/_sre pypy/module/_weakref pypy/module/_winreg pypy/module/array pypy/module/array/benchmark pypy/module/array/test pypy/module/bz2 pypy/module/cpyext pypy/module/cpyext/test pypy/module/gc pypy/module/gc/test pypy/module/imp pypy/module/imp/test pypy/module/parser/test pypy/module/pypyjit pypy/module/pypyjit/test pypy/module/signal pypy/module/sys pypy/module/test_lib_pypy/ctypes_tests pypy/module/thread pypy/objspace pypy/objspace/flow pypy/objspace/flow/test pypy/objspace/std pypy/objspace/std/test pypy/objspace/test pypy/rlib pypy/rlib/rsre pypy/rlib/rsre/test pypy/rlib/test pypy/rpython pypy/rpython/lltypesystem pypy/rpython/lltypesystem/test pypy/rpython/memory pypy/rpython/memory/gc pypy/rpython/memory/gc/test pypy/rpython/memory/gctransform pypy/rpython/memory/test pypy/rpython/module pypy/rpython/test pypy/tool pypy/tool/release pypy/tool/release/test pypy/tool/test pypy/translator pypy/translator/c pypy/translator/c/gcc pypy/translator/c/gcc/test pypy/translator/c/gcc/test/darwin64 pypy/translator/c/gcc/test/elf pypy/translator/c/gcc/test/elf64 pypy/translator/c/src pypy/translator/c/test pypy/translator/goal pypy/translator/jvm/test pypy/translator/oosupport/test_template pypy/translator/platform

hakanardo at codespeak.net hakanardo at codespeak.net
Sat Oct 30 16:41:30 CEST 2010


Author: hakanardo
Date: Sat Oct 30 16:41:17 2010
New Revision: 78530

Added:
   pypy/branch/jit-unroll-loops/lib-python/modified-2.5.2/test/test_dict.py
      - copied unchanged from r78528, pypy/trunk/lib-python/modified-2.5.2/test/test_dict.py
   pypy/branch/jit-unroll-loops/pypy/doc/config/objspace.std.withmapdict.txt
      - copied unchanged from r78528, pypy/trunk/pypy/doc/config/objspace.std.withmapdict.txt
   pypy/branch/jit-unroll-loops/pypy/doc/config/objspace.std.withstrbuf.txt
      - copied unchanged from r78528, pypy/trunk/pypy/doc/config/objspace.std.withstrbuf.txt
   pypy/branch/jit-unroll-loops/pypy/doc/config/objspace.usemodules._bisect.txt
      - copied unchanged from r78528, pypy/trunk/pypy/doc/config/objspace.usemodules._bisect.txt
   pypy/branch/jit-unroll-loops/pypy/doc/config/objspace.usemodules._ffi.txt
      - copied unchanged from r78528, pypy/trunk/pypy/doc/config/objspace.usemodules._ffi.txt
   pypy/branch/jit-unroll-loops/pypy/interpreter/pyparser/autopath.py
      - copied unchanged from r78528, pypy/trunk/pypy/interpreter/pyparser/autopath.py
   pypy/branch/jit-unroll-loops/pypy/interpreter/pyparser/genpytokenize.py
      - copied unchanged from r78528, pypy/trunk/pypy/interpreter/pyparser/genpytokenize.py
   pypy/branch/jit-unroll-loops/pypy/interpreter/pyparser/pylexer.py
      - copied unchanged from r78528, pypy/trunk/pypy/interpreter/pyparser/pylexer.py
   pypy/branch/jit-unroll-loops/pypy/jit/backend/conftest.py
      - copied unchanged from r78528, pypy/trunk/pypy/jit/backend/conftest.py
   pypy/branch/jit-unroll-loops/pypy/jit/backend/llsupport/ffisupport.py
      - copied unchanged from r78528, pypy/trunk/pypy/jit/backend/llsupport/ffisupport.py
   pypy/branch/jit-unroll-loops/pypy/jit/backend/llsupport/test/test_ffisupport.py
      - copied unchanged from r78528, pypy/trunk/pypy/jit/backend/llsupport/test/test_ffisupport.py
   pypy/branch/jit-unroll-loops/pypy/jit/codewriter/test/test_void_list.py
      - copied unchanged from r78528, pypy/trunk/pypy/jit/codewriter/test/test_void_list.py
   pypy/branch/jit-unroll-loops/pypy/jit/metainterp/greenfield.py
      - copied unchanged from r78528, pypy/trunk/pypy/jit/metainterp/greenfield.py
   pypy/branch/jit-unroll-loops/pypy/jit/metainterp/optimizeopt/fficall.py
      - copied unchanged from r78528, pypy/trunk/pypy/jit/metainterp/optimizeopt/fficall.py
   pypy/branch/jit-unroll-loops/pypy/jit/metainterp/test/test_fficall.py
      - copied unchanged from r78528, pypy/trunk/pypy/jit/metainterp/test/test_fficall.py
   pypy/branch/jit-unroll-loops/pypy/jit/metainterp/test/test_greenfield.py
      - copied unchanged from r78528, pypy/trunk/pypy/jit/metainterp/test/test_greenfield.py
   pypy/branch/jit-unroll-loops/pypy/jit/metainterp/test/test_optimizefficall.py
      - copied unchanged from r78528, pypy/trunk/pypy/jit/metainterp/test/test_optimizefficall.py
   pypy/branch/jit-unroll-loops/pypy/jit/tl/jittest.py
      - copied unchanged from r78528, pypy/trunk/pypy/jit/tl/jittest.py
   pypy/branch/jit-unroll-loops/pypy/jit/tool/oparser.py
      - copied unchanged from r78528, pypy/trunk/pypy/jit/tool/oparser.py
   pypy/branch/jit-unroll-loops/pypy/jit/tool/pypytrace.vim
      - copied unchanged from r78528, pypy/trunk/pypy/jit/tool/pypytrace.vim
   pypy/branch/jit-unroll-loops/pypy/module/_bisect/   (props changed)
      - copied from r78528, pypy/trunk/pypy/module/_bisect/
   pypy/branch/jit-unroll-loops/pypy/module/_ffi/   (props changed)
      - copied from r78528, pypy/trunk/pypy/module/_ffi/
   pypy/branch/jit-unroll-loops/pypy/objspace/std/mapdict.py
      - copied unchanged from r78528, pypy/trunk/pypy/objspace/std/mapdict.py
   pypy/branch/jit-unroll-loops/pypy/objspace/std/strbufobject.py
      - copied unchanged from r78528, pypy/trunk/pypy/objspace/std/strbufobject.py
   pypy/branch/jit-unroll-loops/pypy/objspace/std/test/test_mapdict.py
      - copied unchanged from r78528, pypy/trunk/pypy/objspace/std/test/test_mapdict.py
   pypy/branch/jit-unroll-loops/pypy/objspace/std/test/test_methodcache.py
      - copied unchanged from r78528, pypy/trunk/pypy/objspace/std/test/test_methodcache.py
   pypy/branch/jit-unroll-loops/pypy/objspace/std/test/test_strbufobject.py
      - copied unchanged from r78528, pypy/trunk/pypy/objspace/std/test/test_strbufobject.py
   pypy/branch/jit-unroll-loops/pypy/rlib/clibffi.py
      - copied unchanged from r78528, pypy/trunk/pypy/rlib/clibffi.py
   pypy/branch/jit-unroll-loops/pypy/rlib/libffi.py
      - copied unchanged from r78528, pypy/trunk/pypy/rlib/libffi.py
   pypy/branch/jit-unroll-loops/pypy/rlib/rerased.py
      - copied unchanged from r78528, pypy/trunk/pypy/rlib/rerased.py
   pypy/branch/jit-unroll-loops/pypy/rlib/rsre/rsre_jit.py
      - copied unchanged from r78528, pypy/trunk/pypy/rlib/rsre/rsre_jit.py
   pypy/branch/jit-unroll-loops/pypy/rlib/rsre/test/conftest.py
      - copied unchanged from r78528, pypy/trunk/pypy/rlib/rsre/test/conftest.py
   pypy/branch/jit-unroll-loops/pypy/rlib/rsre/test/test_zjit.py
      - copied unchanged from r78528, pypy/trunk/pypy/rlib/rsre/test/test_zjit.py
   pypy/branch/jit-unroll-loops/pypy/rlib/test/test_clibffi.py
      - copied unchanged from r78528, pypy/trunk/pypy/rlib/test/test_clibffi.py
   pypy/branch/jit-unroll-loops/pypy/rlib/test/test_libffi.py
      - copied unchanged from r78528, pypy/trunk/pypy/rlib/test/test_libffi.py
   pypy/branch/jit-unroll-loops/pypy/rlib/test/test_rerased.py
      - copied unchanged from r78528, pypy/trunk/pypy/rlib/test/test_rerased.py
   pypy/branch/jit-unroll-loops/pypy/tool/leakfinder.py
      - copied unchanged from r78528, pypy/trunk/pypy/tool/leakfinder.py
   pypy/branch/jit-unroll-loops/pypy/tool/test/test_leakfinder.py
      - copied unchanged from r78528, pypy/trunk/pypy/tool/test/test_leakfinder.py
   pypy/branch/jit-unroll-loops/pypy/translator/c/gcc/test/darwin64/
      - copied from r78528, pypy/trunk/pypy/translator/c/gcc/test/darwin64/
   pypy/branch/jit-unroll-loops/pypy/translator/c/gcc/test/elf/track10.s
      - copied unchanged from r78528, pypy/trunk/pypy/translator/c/gcc/test/elf/track10.s
   pypy/branch/jit-unroll-loops/pypy/translator/c/gcc/test/elf/track11.s
      - copied unchanged from r78528, pypy/trunk/pypy/translator/c/gcc/test/elf/track11.s
   pypy/branch/jit-unroll-loops/pypy/translator/c/gcc/test/elf64/track_loadconst.s
      - copied unchanged from r78528, pypy/trunk/pypy/translator/c/gcc/test/elf64/track_loadconst.s
   pypy/branch/jit-unroll-loops/pypy/translator/c/gcc/test/elf64/track_rpyassertfailed.s
      - copied unchanged from r78528, pypy/trunk/pypy/translator/c/gcc/test/elf64/track_rpyassertfailed.s
   pypy/branch/jit-unroll-loops/pypy/translator/c/src/debug_alloc.h
      - copied unchanged from r78528, pypy/trunk/pypy/translator/c/src/debug_alloc.h
Removed:
   pypy/branch/jit-unroll-loops/pypy/doc/config/objspace.std.withinlineddict.txt
   pypy/branch/jit-unroll-loops/pypy/doc/config/objspace.std.withshadowtracking.txt
   pypy/branch/jit-unroll-loops/pypy/doc/config/objspace.std.withsharingdict.txt
   pypy/branch/jit-unroll-loops/pypy/jit/backend/test/conftest.py
   pypy/branch/jit-unroll-loops/pypy/jit/metainterp/test/oparser.py
   pypy/branch/jit-unroll-loops/pypy/module/test_lib_pypy/ctypes_tests/test_find.py
   pypy/branch/jit-unroll-loops/pypy/objspace/std/inlinedict.py
   pypy/branch/jit-unroll-loops/pypy/objspace/std/sharingdict.py
   pypy/branch/jit-unroll-loops/pypy/objspace/std/test/test_inlinedict.py
   pypy/branch/jit-unroll-loops/pypy/objspace/std/test/test_shadowtracking.py
   pypy/branch/jit-unroll-loops/pypy/objspace/std/test/test_sharingdict.py
   pypy/branch/jit-unroll-loops/pypy/rpython/rspecialcase.py
   pypy/branch/jit-unroll-loops/pypy/rpython/test/test_rspecialcase.py
Modified:
   pypy/branch/jit-unroll-loops/   (props changed)
   pypy/branch/jit-unroll-loops/dotviewer/drawgraph.py
   pypy/branch/jit-unroll-loops/lib-python/conftest.py
   pypy/branch/jit-unroll-loops/lib-python/modified-2.5.2/test/test_descr.py
   pypy/branch/jit-unroll-loops/lib_pypy/_ctypes/function.py
   pypy/branch/jit-unroll-loops/lib_pypy/_ctypes/structure.py
   pypy/branch/jit-unroll-loops/lib_pypy/_ctypes/union.py
   pypy/branch/jit-unroll-loops/pypy/   (props changed)
   pypy/branch/jit-unroll-loops/pypy/annotation/bookkeeper.py
   pypy/branch/jit-unroll-loops/pypy/annotation/builtin.py
   pypy/branch/jit-unroll-loops/pypy/annotation/classdef.py
   pypy/branch/jit-unroll-loops/pypy/annotation/description.py
   pypy/branch/jit-unroll-loops/pypy/annotation/dictdef.py
   pypy/branch/jit-unroll-loops/pypy/annotation/listdef.py
   pypy/branch/jit-unroll-loops/pypy/annotation/model.py
   pypy/branch/jit-unroll-loops/pypy/annotation/policy.py
   pypy/branch/jit-unroll-loops/pypy/annotation/specialize.py
   pypy/branch/jit-unroll-loops/pypy/annotation/test/test_annrpython.py
   pypy/branch/jit-unroll-loops/pypy/annotation/test/test_model.py
   pypy/branch/jit-unroll-loops/pypy/annotation/unaryop.py
   pypy/branch/jit-unroll-loops/pypy/config/pypyoption.py
   pypy/branch/jit-unroll-loops/pypy/config/test/test_pypyoption.py
   pypy/branch/jit-unroll-loops/pypy/conftest.py
   pypy/branch/jit-unroll-loops/pypy/doc/config/objspace.opcodes.CALL_METHOD.txt
   pypy/branch/jit-unroll-loops/pypy/doc/docindex.txt
   pypy/branch/jit-unroll-loops/pypy/doc/interpreter-optimizations.txt
   pypy/branch/jit-unroll-loops/pypy/interpreter/astcompiler/test/test_compiler.py
   pypy/branch/jit-unroll-loops/pypy/interpreter/baseobjspace.py
   pypy/branch/jit-unroll-loops/pypy/interpreter/function.py
   pypy/branch/jit-unroll-loops/pypy/interpreter/gateway.py
   pypy/branch/jit-unroll-loops/pypy/interpreter/pycode.py
   pypy/branch/jit-unroll-loops/pypy/interpreter/pyframe.py
   pypy/branch/jit-unroll-loops/pypy/interpreter/pyopcode.py
   pypy/branch/jit-unroll-loops/pypy/interpreter/pyparser/pytokenize.py
   pypy/branch/jit-unroll-loops/pypy/interpreter/test/test_function.py
   pypy/branch/jit-unroll-loops/pypy/interpreter/typedef.py
   pypy/branch/jit-unroll-loops/pypy/jit/backend/detect_cpu.py
   pypy/branch/jit-unroll-loops/pypy/jit/backend/llgraph/llimpl.py
   pypy/branch/jit-unroll-loops/pypy/jit/backend/llgraph/runner.py
   pypy/branch/jit-unroll-loops/pypy/jit/backend/llsupport/descr.py
   pypy/branch/jit-unroll-loops/pypy/jit/backend/llsupport/gc.py
   pypy/branch/jit-unroll-loops/pypy/jit/backend/llsupport/llmodel.py
   pypy/branch/jit-unroll-loops/pypy/jit/backend/llsupport/symbolic.py
   pypy/branch/jit-unroll-loops/pypy/jit/backend/llsupport/test/test_descr.py
   pypy/branch/jit-unroll-loops/pypy/jit/backend/llsupport/test/test_gc.py
   pypy/branch/jit-unroll-loops/pypy/jit/backend/model.py
   pypy/branch/jit-unroll-loops/pypy/jit/backend/test/runner_test.py
   pypy/branch/jit-unroll-loops/pypy/jit/backend/test/test_ll_random.py
   pypy/branch/jit-unroll-loops/pypy/jit/backend/test/test_random.py
   pypy/branch/jit-unroll-loops/pypy/jit/backend/x86/assembler.py
   pypy/branch/jit-unroll-loops/pypy/jit/backend/x86/regalloc.py
   pypy/branch/jit-unroll-loops/pypy/jit/backend/x86/regloc.py
   pypy/branch/jit-unroll-loops/pypy/jit/backend/x86/runner.py
   pypy/branch/jit-unroll-loops/pypy/jit/backend/x86/rx86.py
   pypy/branch/jit-unroll-loops/pypy/jit/backend/x86/test/test_assembler.py
   pypy/branch/jit-unroll-loops/pypy/jit/backend/x86/test/test_gc_integration.py
   pypy/branch/jit-unroll-loops/pypy/jit/backend/x86/test/test_regalloc.py
   pypy/branch/jit-unroll-loops/pypy/jit/backend/x86/test/test_runner.py
   pypy/branch/jit-unroll-loops/pypy/jit/backend/x86/test/test_string.py
   pypy/branch/jit-unroll-loops/pypy/jit/backend/x86/test/test_zrpy_gc.py
   pypy/branch/jit-unroll-loops/pypy/jit/backend/x86/test/test_ztranslation.py
   pypy/branch/jit-unroll-loops/pypy/jit/codewriter/call.py
   pypy/branch/jit-unroll-loops/pypy/jit/codewriter/codewriter.py
   pypy/branch/jit-unroll-loops/pypy/jit/codewriter/effectinfo.py
   pypy/branch/jit-unroll-loops/pypy/jit/codewriter/format.py
   pypy/branch/jit-unroll-loops/pypy/jit/codewriter/jtransform.py
   pypy/branch/jit-unroll-loops/pypy/jit/codewriter/support.py
   pypy/branch/jit-unroll-loops/pypy/jit/codewriter/test/test_codewriter.py
   pypy/branch/jit-unroll-loops/pypy/jit/codewriter/test/test_effectinfo.py
   pypy/branch/jit-unroll-loops/pypy/jit/codewriter/test/test_jtransform.py
   pypy/branch/jit-unroll-loops/pypy/jit/codewriter/test/test_list.py
   pypy/branch/jit-unroll-loops/pypy/jit/metainterp/blackhole.py
   pypy/branch/jit-unroll-loops/pypy/jit/metainterp/compile.py
   pypy/branch/jit-unroll-loops/pypy/jit/metainterp/executor.py
   pypy/branch/jit-unroll-loops/pypy/jit/metainterp/graphpage.py
   pypy/branch/jit-unroll-loops/pypy/jit/metainterp/history.py
   pypy/branch/jit-unroll-loops/pypy/jit/metainterp/jitdriver.py
   pypy/branch/jit-unroll-loops/pypy/jit/metainterp/optimize_nopspec.py   (contents, props changed)
   pypy/branch/jit-unroll-loops/pypy/jit/metainterp/optimizeopt/__init__.py
   pypy/branch/jit-unroll-loops/pypy/jit/metainterp/optimizeopt/intbounds.py
   pypy/branch/jit-unroll-loops/pypy/jit/metainterp/optimizeopt/optimizer.py   (props changed)
   pypy/branch/jit-unroll-loops/pypy/jit/metainterp/optimizeopt/rewrite.py
   pypy/branch/jit-unroll-loops/pypy/jit/metainterp/optimizeopt/string.py
   pypy/branch/jit-unroll-loops/pypy/jit/metainterp/optimizeopt/virtualize.py
   pypy/branch/jit-unroll-loops/pypy/jit/metainterp/pyjitpl.py
   pypy/branch/jit-unroll-loops/pypy/jit/metainterp/resoperation.py
   pypy/branch/jit-unroll-loops/pypy/jit/metainterp/resume.py
   pypy/branch/jit-unroll-loops/pypy/jit/metainterp/simple_optimize.py
   pypy/branch/jit-unroll-loops/pypy/jit/metainterp/test/test_basic.py
   pypy/branch/jit-unroll-loops/pypy/jit/metainterp/test/test_compile.py
   pypy/branch/jit-unroll-loops/pypy/jit/metainterp/test/test_jitdriver.py
   pypy/branch/jit-unroll-loops/pypy/jit/metainterp/test/test_logger.py
   pypy/branch/jit-unroll-loops/pypy/jit/metainterp/test/test_loop_nopspec.py   (props changed)
   pypy/branch/jit-unroll-loops/pypy/jit/metainterp/test/test_oparser.py
   pypy/branch/jit-unroll-loops/pypy/jit/metainterp/test/test_optimizebasic.py
   pypy/branch/jit-unroll-loops/pypy/jit/metainterp/test/test_optimizefindnode.py
   pypy/branch/jit-unroll-loops/pypy/jit/metainterp/test/test_optimizeopt.py
   pypy/branch/jit-unroll-loops/pypy/jit/metainterp/test/test_resume.py
   pypy/branch/jit-unroll-loops/pypy/jit/metainterp/test/test_string.py
   pypy/branch/jit-unroll-loops/pypy/jit/metainterp/test/test_virtualref.py
   pypy/branch/jit-unroll-loops/pypy/jit/metainterp/test/test_warmspot.py
   pypy/branch/jit-unroll-loops/pypy/jit/metainterp/virtualref.py
   pypy/branch/jit-unroll-loops/pypy/jit/metainterp/warmspot.py
   pypy/branch/jit-unroll-loops/pypy/jit/metainterp/warmstate.py
   pypy/branch/jit-unroll-loops/pypy/jit/tl/pypyjit.py
   pypy/branch/jit-unroll-loops/pypy/jit/tl/pypyjit_child.py
   pypy/branch/jit-unroll-loops/pypy/jit/tl/spli/interpreter.py
   pypy/branch/jit-unroll-loops/pypy/jit/tl/tla/test_tla.py
   pypy/branch/jit-unroll-loops/pypy/jit/tool/loopviewer.py
   pypy/branch/jit-unroll-loops/pypy/jit/tool/showstats.py
   pypy/branch/jit-unroll-loops/pypy/jit/tool/traceviewer.py
   pypy/branch/jit-unroll-loops/pypy/module/__builtin__/interp_classobj.py
   pypy/branch/jit-unroll-loops/pypy/module/__builtin__/test/test_classobj.py
   pypy/branch/jit-unroll-loops/pypy/module/_bisect/test/   (props changed)
   pypy/branch/jit-unroll-loops/pypy/module/_ffi/test/   (props changed)
   pypy/branch/jit-unroll-loops/pypy/module/_rawffi/__init__.py
   pypy/branch/jit-unroll-loops/pypy/module/_rawffi/array.py
   pypy/branch/jit-unroll-loops/pypy/module/_rawffi/callback.py
   pypy/branch/jit-unroll-loops/pypy/module/_rawffi/interp_rawffi.py
   pypy/branch/jit-unroll-loops/pypy/module/_rawffi/structure.py
   pypy/branch/jit-unroll-loops/pypy/module/_rawffi/test/test__rawffi.py
   pypy/branch/jit-unroll-loops/pypy/module/_socket/test/test_sock_app.py
   pypy/branch/jit-unroll-loops/pypy/module/_sre/interp_sre.py
   pypy/branch/jit-unroll-loops/pypy/module/_weakref/interp__weakref.py
   pypy/branch/jit-unroll-loops/pypy/module/_winreg/interp_winreg.py
   pypy/branch/jit-unroll-loops/pypy/module/array/benchmark/Makefile   (props changed)
   pypy/branch/jit-unroll-loops/pypy/module/array/benchmark/intimg.c   (props changed)
   pypy/branch/jit-unroll-loops/pypy/module/array/benchmark/intimgtst.c   (props changed)
   pypy/branch/jit-unroll-loops/pypy/module/array/benchmark/intimgtst.py   (props changed)
   pypy/branch/jit-unroll-loops/pypy/module/array/benchmark/loop.c   (props changed)
   pypy/branch/jit-unroll-loops/pypy/module/array/benchmark/sum.c   (props changed)
   pypy/branch/jit-unroll-loops/pypy/module/array/benchmark/sumtst.c   (props changed)
   pypy/branch/jit-unroll-loops/pypy/module/array/benchmark/sumtst.py   (props changed)
   pypy/branch/jit-unroll-loops/pypy/module/array/interp_array.py
   pypy/branch/jit-unroll-loops/pypy/module/array/test/test_array_old.py   (props changed)
   pypy/branch/jit-unroll-loops/pypy/module/bz2/interp_bz2.py
   pypy/branch/jit-unroll-loops/pypy/module/cpyext/classobject.py
   pypy/branch/jit-unroll-loops/pypy/module/cpyext/test/test_cpyext.py
   pypy/branch/jit-unroll-loops/pypy/module/cpyext/test/test_unicodeobject.py
   pypy/branch/jit-unroll-loops/pypy/module/gc/interp_gc.py
   pypy/branch/jit-unroll-loops/pypy/module/gc/referents.py
   pypy/branch/jit-unroll-loops/pypy/module/gc/test/test_gc.py
   pypy/branch/jit-unroll-loops/pypy/module/imp/importing.py
   pypy/branch/jit-unroll-loops/pypy/module/imp/test/test_import.py
   pypy/branch/jit-unroll-loops/pypy/module/parser/test/test_parser.py
   pypy/branch/jit-unroll-loops/pypy/module/pypyjit/__init__.py
   pypy/branch/jit-unroll-loops/pypy/module/pypyjit/interp_jit.py
   pypy/branch/jit-unroll-loops/pypy/module/pypyjit/policy.py
   pypy/branch/jit-unroll-loops/pypy/module/pypyjit/test/test_pypy_c.py
   pypy/branch/jit-unroll-loops/pypy/module/signal/interp_signal.py
   pypy/branch/jit-unroll-loops/pypy/module/sys/__init__.py
   pypy/branch/jit-unroll-loops/pypy/module/sys/state.py
   pypy/branch/jit-unroll-loops/pypy/module/test_lib_pypy/ctypes_tests/_ctypes_test.c
   pypy/branch/jit-unroll-loops/pypy/module/test_lib_pypy/ctypes_tests/test_funcptr.py
   pypy/branch/jit-unroll-loops/pypy/module/test_lib_pypy/ctypes_tests/test_functions.py
   pypy/branch/jit-unroll-loops/pypy/module/test_lib_pypy/ctypes_tests/test_keepalive.py
   pypy/branch/jit-unroll-loops/pypy/module/thread/ll_thread.py
   pypy/branch/jit-unroll-loops/pypy/objspace/descroperation.py
   pypy/branch/jit-unroll-loops/pypy/objspace/flow/flowcontext.py
   pypy/branch/jit-unroll-loops/pypy/objspace/flow/test/test_objspace.py
   pypy/branch/jit-unroll-loops/pypy/objspace/std/callmethod.py
   pypy/branch/jit-unroll-loops/pypy/objspace/std/celldict.py
   pypy/branch/jit-unroll-loops/pypy/objspace/std/dictmultiobject.py
   pypy/branch/jit-unroll-loops/pypy/objspace/std/dicttype.py
   pypy/branch/jit-unroll-loops/pypy/objspace/std/fake.py
   pypy/branch/jit-unroll-loops/pypy/objspace/std/frozensettype.py
   pypy/branch/jit-unroll-loops/pypy/objspace/std/inttype.py
   pypy/branch/jit-unroll-loops/pypy/objspace/std/listobject.py
   pypy/branch/jit-unroll-loops/pypy/objspace/std/longtype.py
   pypy/branch/jit-unroll-loops/pypy/objspace/std/model.py
   pypy/branch/jit-unroll-loops/pypy/objspace/std/objspace.py
   pypy/branch/jit-unroll-loops/pypy/objspace/std/proxyobject.py
   pypy/branch/jit-unroll-loops/pypy/objspace/std/setobject.py
   pypy/branch/jit-unroll-loops/pypy/objspace/std/settype.py
   pypy/branch/jit-unroll-loops/pypy/objspace/std/smallintobject.py
   pypy/branch/jit-unroll-loops/pypy/objspace/std/stringobject.py
   pypy/branch/jit-unroll-loops/pypy/objspace/std/stringtype.py
   pypy/branch/jit-unroll-loops/pypy/objspace/std/strutil.py
   pypy/branch/jit-unroll-loops/pypy/objspace/std/test/test_dictmultiobject.py
   pypy/branch/jit-unroll-loops/pypy/objspace/std/test/test_longobject.py
   pypy/branch/jit-unroll-loops/pypy/objspace/std/test/test_setobject.py
   pypy/branch/jit-unroll-loops/pypy/objspace/std/test/test_strutil.py
   pypy/branch/jit-unroll-loops/pypy/objspace/std/test/test_typeobject.py
   pypy/branch/jit-unroll-loops/pypy/objspace/std/test/test_versionedtype.py
   pypy/branch/jit-unroll-loops/pypy/objspace/std/typeobject.py
   pypy/branch/jit-unroll-loops/pypy/objspace/test/test_descroperation.py
   pypy/branch/jit-unroll-loops/pypy/rlib/_rsocket_rffi.py
   pypy/branch/jit-unroll-loops/pypy/rlib/jit.py
   pypy/branch/jit-unroll-loops/pypy/rlib/objectmodel.py
   pypy/branch/jit-unroll-loops/pypy/rlib/rbigint.py
   pypy/branch/jit-unroll-loops/pypy/rlib/rgc.py
   pypy/branch/jit-unroll-loops/pypy/rlib/rmmap.py
   pypy/branch/jit-unroll-loops/pypy/rlib/rsre/rsre_char.py
   pypy/branch/jit-unroll-loops/pypy/rlib/rsre/rsre_core.py
   pypy/branch/jit-unroll-loops/pypy/rlib/rsre/test/test_match.py
   pypy/branch/jit-unroll-loops/pypy/rlib/rstring.py
   pypy/branch/jit-unroll-loops/pypy/rlib/test/test_jit.py
   pypy/branch/jit-unroll-loops/pypy/rlib/test/test_rbigint.py
   pypy/branch/jit-unroll-loops/pypy/rlib/test/test_rdynload.py
   pypy/branch/jit-unroll-loops/pypy/rlib/test/test_rsocket.py
   pypy/branch/jit-unroll-loops/pypy/rlib/test/test_rstring.py
   pypy/branch/jit-unroll-loops/pypy/rlib/test/test_runicode.py
   pypy/branch/jit-unroll-loops/pypy/rlib/test/test_rzlib.py
   pypy/branch/jit-unroll-loops/pypy/rpython/llinterp.py
   pypy/branch/jit-unroll-loops/pypy/rpython/lltypesystem/ll2ctypes.py
   pypy/branch/jit-unroll-loops/pypy/rpython/lltypesystem/llarena.py
   pypy/branch/jit-unroll-loops/pypy/rpython/lltypesystem/llmemory.py
   pypy/branch/jit-unroll-loops/pypy/rpython/lltypesystem/lloperation.py
   pypy/branch/jit-unroll-loops/pypy/rpython/lltypesystem/lltype.py
   pypy/branch/jit-unroll-loops/pypy/rpython/lltypesystem/rbuilder.py
   pypy/branch/jit-unroll-loops/pypy/rpython/lltypesystem/rclass.py
   pypy/branch/jit-unroll-loops/pypy/rpython/lltypesystem/rdict.py
   pypy/branch/jit-unroll-loops/pypy/rpython/lltypesystem/rffi.py
   pypy/branch/jit-unroll-loops/pypy/rpython/lltypesystem/test/test_ll2ctypes.py
   pypy/branch/jit-unroll-loops/pypy/rpython/lltypesystem/test/test_llmemory.py
   pypy/branch/jit-unroll-loops/pypy/rpython/lltypesystem/test/test_lltype.py
   pypy/branch/jit-unroll-loops/pypy/rpython/lltypesystem/test/test_rffi.py
   pypy/branch/jit-unroll-loops/pypy/rpython/memory/gc/base.py
   pypy/branch/jit-unroll-loops/pypy/rpython/memory/gc/generation.py
   pypy/branch/jit-unroll-loops/pypy/rpython/memory/gc/markcompact.py
   pypy/branch/jit-unroll-loops/pypy/rpython/memory/gc/marksweep.py
   pypy/branch/jit-unroll-loops/pypy/rpython/memory/gc/minimark.py
   pypy/branch/jit-unroll-loops/pypy/rpython/memory/gc/minimarkpage.py
   pypy/branch/jit-unroll-loops/pypy/rpython/memory/gc/semispace.py
   pypy/branch/jit-unroll-loops/pypy/rpython/memory/gc/test/test_direct.py
   pypy/branch/jit-unroll-loops/pypy/rpython/memory/gctransform/asmgcroot.py
   pypy/branch/jit-unroll-loops/pypy/rpython/memory/gctransform/framework.py
   pypy/branch/jit-unroll-loops/pypy/rpython/memory/gctransform/transform.py
   pypy/branch/jit-unroll-loops/pypy/rpython/memory/gcwrapper.py
   pypy/branch/jit-unroll-loops/pypy/rpython/memory/support.py
   pypy/branch/jit-unroll-loops/pypy/rpython/memory/test/test_gc.py
   pypy/branch/jit-unroll-loops/pypy/rpython/memory/test/test_transformed_gc.py
   pypy/branch/jit-unroll-loops/pypy/rpython/module/ll_time.py
   pypy/branch/jit-unroll-loops/pypy/rpython/rbuilder.py
   pypy/branch/jit-unroll-loops/pypy/rpython/rbuiltin.py
   pypy/branch/jit-unroll-loops/pypy/rpython/rpbc.py
   pypy/branch/jit-unroll-loops/pypy/rpython/rtyper.py
   pypy/branch/jit-unroll-loops/pypy/rpython/test/test_llinterp.py
   pypy/branch/jit-unroll-loops/pypy/rpython/test/test_nongc.py
   pypy/branch/jit-unroll-loops/pypy/rpython/test/test_rbuilder.py
   pypy/branch/jit-unroll-loops/pypy/rpython/test/test_rclass.py
   pypy/branch/jit-unroll-loops/pypy/rpython/test/test_rdict.py
   pypy/branch/jit-unroll-loops/pypy/rpython/test/test_rptr.py
   pypy/branch/jit-unroll-loops/pypy/tool/release/   (props changed)
   pypy/branch/jit-unroll-loops/pypy/tool/release/__init__.py   (props changed)
   pypy/branch/jit-unroll-loops/pypy/tool/release/force-builds.py   (props changed)
   pypy/branch/jit-unroll-loops/pypy/tool/release/make_release.py   (props changed)
   pypy/branch/jit-unroll-loops/pypy/tool/release/test/   (props changed)
   pypy/branch/jit-unroll-loops/pypy/tool/release/test/__init__.py   (props changed)
   pypy/branch/jit-unroll-loops/pypy/tool/release/test/test_make_release.py   (props changed)
   pypy/branch/jit-unroll-loops/pypy/translator/c/funcgen.py
   pypy/branch/jit-unroll-loops/pypy/translator/c/gcc/instruction.py
   pypy/branch/jit-unroll-loops/pypy/translator/c/gcc/test/elf/track5.s
   pypy/branch/jit-unroll-loops/pypy/translator/c/gcc/test/test_trackgcroot.py
   pypy/branch/jit-unroll-loops/pypy/translator/c/gcc/trackgcroot.py
   pypy/branch/jit-unroll-loops/pypy/translator/c/src/g_include.h
   pypy/branch/jit-unroll-loops/pypy/translator/c/src/main.h
   pypy/branch/jit-unroll-loops/pypy/translator/c/src/signals.h
   pypy/branch/jit-unroll-loops/pypy/translator/c/src/stack.h
   pypy/branch/jit-unroll-loops/pypy/translator/c/test/test_genc.py
   pypy/branch/jit-unroll-loops/pypy/translator/c/test/test_lltyped.py
   pypy/branch/jit-unroll-loops/pypy/translator/c/test/test_newgc.py
   pypy/branch/jit-unroll-loops/pypy/translator/c/test/test_standalone.py
   pypy/branch/jit-unroll-loops/pypy/translator/c/test/test_typed.py
   pypy/branch/jit-unroll-loops/pypy/translator/driver.py
   pypy/branch/jit-unroll-loops/pypy/translator/goal/ann_override.py
   pypy/branch/jit-unroll-loops/pypy/translator/goal/app_main.py
   pypy/branch/jit-unroll-loops/pypy/translator/goal/translate.py
   pypy/branch/jit-unroll-loops/pypy/translator/jvm/test/test_class.py
   pypy/branch/jit-unroll-loops/pypy/translator/oosupport/test_template/class_.py
   pypy/branch/jit-unroll-loops/pypy/translator/platform/darwin.py
   pypy/branch/jit-unroll-loops/pypy/translator/transform.py
Log:
svn merge -r77505:HEAD svn+ssh://hakanardo@codespeak.net/svn/pypy/trunk

Modified: pypy/branch/jit-unroll-loops/dotviewer/drawgraph.py
==============================================================================
--- pypy/branch/jit-unroll-loops/dotviewer/drawgraph.py	(original)
+++ pypy/branch/jit-unroll-loops/dotviewer/drawgraph.py	Sat Oct 30 16:41:17 2010
@@ -423,20 +423,43 @@
         else:
             for line in lines:
                 raw_line = line.replace('\\l','').replace('\r','') or ' '
-                img = TextSnippet(self, raw_line, (0, 0, 0), bgcolor)
-                w, h = img.get_size()
-                if w>wmax: wmax = w
-                if raw_line.strip():
-                    if line.endswith('\\l'):
-                        def cmd(img=img, y=hmax):
-                            img.draw(xleft, ytop+y)
-                    elif line.endswith('\r'):
-                        def cmd(img=img, y=hmax, w=w):
-                            img.draw(xright-w, ytop+y)
-                    else:
-                        def cmd(img=img, y=hmax, w=w):
-                            img.draw(xcenter-w//2, ytop+y)
+                if '\f' in raw_line:   # grayed out parts of the line
+                    imgs = []
+                    graytext = True
+                    h = 16
+                    w_total = 0
+                    for linepart in raw_line.split('\f'):
+                        graytext = not graytext
+                        if not linepart.strip():
+                            continue
+                        if graytext:
+                            fgcolor = (128, 160, 160)
+                        else:
+                            fgcolor = (0, 0, 0)
+                        img = TextSnippet(self, linepart, fgcolor, bgcolor)
+                        imgs.append((w_total, img))
+                        w, h = img.get_size()
+                        w_total += w
+                    if w_total > wmax: wmax = w_total
+                    def cmd(imgs=imgs, y=hmax):
+                        for x, img in imgs:
+                            img.draw(xleft+x, ytop+y)
                     commands.append(cmd)
+                else:
+                    img = TextSnippet(self, raw_line, (0, 0, 0), bgcolor)
+                    w, h = img.get_size()
+                    if w>wmax: wmax = w
+                    if raw_line.strip():
+                        if line.endswith('\\l'):
+                            def cmd(img=img, y=hmax):
+                                img.draw(xleft, ytop+y)
+                        elif line.endswith('\r'):
+                            def cmd(img=img, y=hmax, w=w):
+                                img.draw(xright-w, ytop+y)
+                        else:
+                            def cmd(img=img, y=hmax, w=w):
+                                img.draw(xcenter-w//2, ytop+y)
+                        commands.append(cmd)
                 hmax += h
                 #hmax += 8
 

Modified: pypy/branch/jit-unroll-loops/lib-python/conftest.py
==============================================================================
--- pypy/branch/jit-unroll-loops/lib-python/conftest.py	(original)
+++ pypy/branch/jit-unroll-loops/lib-python/conftest.py	Sat Oct 30 16:41:17 2010
@@ -144,7 +144,7 @@
     RegrTest('test_binhex.py'),
 
     RegrTest('test_binop.py', core=True),
-    RegrTest('test_bisect.py', core=True),
+    RegrTest('test_bisect.py', core=True, usemodules='_bisect'),
     RegrTest('test_bool.py', core=True),
     RegrTest('test_bsddb.py', skip="unsupported extension module"),
     RegrTest('test_bsddb185.py', skip="unsupported extension module"),
@@ -464,7 +464,12 @@
     RegrTest('test_coding.py'),
     RegrTest('test_complex_args.py'),
     RegrTest('test_contextlib.py', usemodules="thread"),
-    RegrTest('test_ctypes.py', usemodules="_rawffi"),
+    # we skip test ctypes, since we adapted it massively in order
+    # to test what we want to support. There are real failures,
+    # but it's about missing features that we don't want to support
+    # now
+    RegrTest('test_ctypes.py', usemodules="_rawffi",
+             skip="missing features that we don't want to support now"),
     RegrTest('test_defaultdict.py'),
     RegrTest('test_email_renamed.py'),
     RegrTest('test_exception_variations.py'),

Modified: pypy/branch/jit-unroll-loops/lib-python/modified-2.5.2/test/test_descr.py
==============================================================================
--- pypy/branch/jit-unroll-loops/lib-python/modified-2.5.2/test/test_descr.py	(original)
+++ pypy/branch/jit-unroll-loops/lib-python/modified-2.5.2/test/test_descr.py	Sat Oct 30 16:41:17 2010
@@ -2028,7 +2028,9 @@
     except TypeError, msg:
         verify(str(msg).find("weak reference") >= 0)
     else:
-        verify(0, "weakref.ref(no) should be illegal")
+        # in PyPy it is (sometimes) possible to take a weakref here
+        #verify(0, "weakref.ref(no) should be illegal")
+        pass
     class Weak(object):
         __slots__ = ['foo', '__weakref__']
     yes = Weak()

Modified: pypy/branch/jit-unroll-loops/lib_pypy/_ctypes/function.py
==============================================================================
--- pypy/branch/jit-unroll-loops/lib_pypy/_ctypes/function.py	(original)
+++ pypy/branch/jit-unroll-loops/lib_pypy/_ctypes/function.py	Sat Oct 30 16:41:17 2010
@@ -171,7 +171,7 @@
         return self._build_result(restype, resbuffer, argtypes, argsandobjs)
 
     def _getfuncptr(self, argtypes, restype, thisarg=None):
-        if self._ptr is not None:
+        if self._ptr is not None and argtypes is self._argtypes_:
             return self._ptr
         if restype is None or not isinstance(restype, _CDataMeta):
             import ctypes

Modified: pypy/branch/jit-unroll-loops/lib_pypy/_ctypes/structure.py
==============================================================================
--- pypy/branch/jit-unroll-loops/lib_pypy/_ctypes/structure.py	(original)
+++ pypy/branch/jit-unroll-loops/lib_pypy/_ctypes/structure.py	Sat Oct 30 16:41:17 2010
@@ -7,7 +7,7 @@
 def round_up(size, alignment):
     return (size + alignment - 1) & -alignment
 
-def size_alignment_pos(fields):
+def size_alignment_pos(fields, is_union=False):
     import ctypes
     size = 0
     alignment = 1
@@ -15,14 +15,19 @@
     for fieldname, ctype in fields:
         fieldsize = ctypes.sizeof(ctype)
         fieldalignment = ctypes.alignment(ctype)
-        size = round_up(size, fieldalignment)
         alignment = max(alignment, fieldalignment)
-        pos.append(size)
-        size += fieldsize
+        if is_union:
+            pos.append(0)
+            size = max(size, fieldsize)
+        else:
+            size = round_up(size, fieldalignment)
+            pos.append(size)
+            size += fieldsize
     size = round_up(size, alignment)
     return size, alignment, pos
 
-def names_and_fields(_fields_, superclass, zero_offset=False, anon=None):
+def names_and_fields(_fields_, superclass, zero_offset=False, anon=None,
+                     is_union=False):
     if isinstance(_fields_, tuple):
         _fields_ = list(_fields_)
     for _, tp in _fields_:
@@ -36,7 +41,7 @@
     rawfields = [(name, ctype._ffishape)
                  for name, ctype in all_fields]
     if not zero_offset:
-        _, _, pos = size_alignment_pos(all_fields)
+        _, _, pos = size_alignment_pos(all_fields, is_union)
     else:
         pos = [0] * len(all_fields)
     fields = {}
@@ -73,8 +78,8 @@
 
 # ________________________________________________________________
 
-def _set_shape(tp, rawfields):
-    tp._ffistruct = _rawffi.Structure(rawfields)
+def _set_shape(tp, rawfields, is_union=False):
+    tp._ffistruct = _rawffi.Structure(rawfields, is_union)
     tp._ffiargshape = tp._ffishape = (tp._ffistruct, 1)
     tp._fficompositesize = tp._ffistruct.size
 
@@ -92,13 +97,14 @@
             raise AttributeError("Structure or union cannot contain itself")
         self._names, rawfields, self._fieldtypes = names_and_fields(
             value, self.__bases__[0], False,
-            self.__dict__.get('_anonymous_', None))
+            self.__dict__.get('_anonymous_', None), self._is_union)
         _CDataMeta.__setattr__(self, '_fields_', value)
-        _set_shape(self, rawfields)
+        _set_shape(self, rawfields, self._is_union)
         return
     _CDataMeta.__setattr__(self, name, value)
 
-class StructureMeta(_CDataMeta):
+class StructOrUnionMeta(_CDataMeta):
+
     def __new__(self, name, cls, typedict):
         res = type.__new__(self, name, cls, typedict)
         if '_fields_' in typedict:
@@ -109,8 +115,8 @@
                     raise AttributeError("Anonymous field not found")
             res._names, rawfields, res._fieldtypes = names_and_fields(
                 typedict['_fields_'], cls[0], False,
-                typedict.get('_anonymous_', None))
-            _set_shape(res, rawfields)
+                typedict.get('_anonymous_', None), self._is_union)
+            _set_shape(res, rawfields, self._is_union)
 
         return res
 
@@ -150,8 +156,8 @@
         res.__dict__['_index'] = -1
         return res
 
-class Structure(_CData):
-    __metaclass__ = StructureMeta
+class StructOrUnion(_CData):
+    __metaclass__ = StructOrUnionMeta
 
     def __new__(cls, *args, **kwds):
         if not hasattr(cls, '_ffistruct'):
@@ -213,3 +219,10 @@
 
     def _get_buffer_value(self):
         return self._buffer.buffer
+
+
+class StructureMeta(StructOrUnionMeta):
+    _is_union = False
+
+class Structure(StructOrUnion):
+    __metaclass__ = StructureMeta

Modified: pypy/branch/jit-unroll-loops/lib_pypy/_ctypes/union.py
==============================================================================
--- pypy/branch/jit-unroll-loops/lib_pypy/_ctypes/union.py	(original)
+++ pypy/branch/jit-unroll-loops/lib_pypy/_ctypes/union.py	Sat Oct 30 16:41:17 2010
@@ -1,118 +1,7 @@
+from _ctypes import structure
 
+class UnionMeta(structure.StructOrUnionMeta):
+    _is_union = True
 
-import _rawffi
-from _ctypes.basics import _CData, _CDataMeta, store_reference, keepalive_key
-from _ctypes.basics import ensure_objects
-from _ctypes.structure import round_up, names_and_fields, struct_getattr,\
-     struct_setattr
-
-
-def _set_shape(tp):
-    size = tp._sizeofinstances()
-    alignment = tp._alignmentofinstances()
-    tp._ffiopaque = _rawffi.Structure((size, alignment)) # opaque
-    tp._ffiargshape = tp._ffishape = (tp._ffiopaque, 1)
-    tp._fficompositesize = tp._ffiopaque.size
-    # we need to create an array of size one for each
-    # of our elements
-    tp._ffiarrays = {}
-    for name, field in tp._fieldtypes.iteritems():
-        tp._ffiarrays[name] = _rawffi.Array(field.ctype._ffishape)
-        
-class UnionMeta(_CDataMeta):
-    def __new__(self, name, cls, typedict):
-        res = type.__new__(self, name, cls, typedict)
-        if '_fields_' in typedict:
-            res._names, rawfields, res._fieldtypes = names_and_fields(
-                typedict['_fields_'], cls[0], True,
-                typedict.get('_anonymous_', None))
-            _set_shape(res)
-
-        def __init__(self): # don't allow arguments by now
-            if not hasattr(self, '_ffiarrays'):
-                raise TypeError("Cannot instantiate union, has no type")
-            # malloc size
-            size = self.__class__._sizeofinstances()
-            self.__dict__['_objects'] = {}
-            self.__dict__['_buffer'] = self._ffiopaque(autofree=True)
-        res.__init__ = __init__
-        return res
-
-    def _sizeofinstances(self):
-        if not hasattr(self, '_size_'):
-            self._size_ = max([field.size for field in
-                               self._fieldtypes.values()] + [0])
-        return self._size_
-
-    def _alignmentofinstances(self):
-        from ctypes import alignment
-        if not hasattr(self, '_alignment_'):
-            self._alignment_ = max([alignment(field.ctype) for field in
-                                    self._fieldtypes.values()] + [1])
-        return self._alignment_
-    
-    __getattr__ = struct_getattr
-
-    def __setattr__(self, name, value):
-        if name == '_fields_':
-            if self.__dict__.get('_fields_', None):
-                raise AttributeError("_fields_ is final")
-            if self in [v for k, v in value]:
-                raise AttributeError("Union cannot contain itself")
-            self._names, rawfields, self._fieldtypes = names_and_fields(
-                value, self.__bases__[0], True,
-                self.__dict__.get('_anonymous_', None))
-            _CDataMeta.__setattr__(self, '_fields_', value)
-            _set_shape(self)
-        _CDataMeta.__setattr__(self, name, value)
-
-    def _CData_output(self, resarray, base=None, index=-1):
-        res = self.__new__(self)
-        ffiopaque = self._ffiopaque.fromaddress(resarray.buffer)
-        res.__dict__['_buffer'] = ffiopaque
-        res.__dict__['_base'] = base
-        res.__dict__['_index'] = index
-        return res
-    
-    def _CData_retval(self, resbuffer):
-        res = self.__new__(self)
-        res.__dict__['_buffer'] = resbuffer
-        res.__dict__['_base'] = None
-        res.__dict__['_index'] = -1
-        return res
-
-
-class Union(_CData):
+class Union(structure.StructOrUnion):
     __metaclass__ = UnionMeta
-
-    def __getattr__(self, name):
-        try:
-            field = self._fieldtypes[name]
-        except KeyError:
-            raise AttributeError(name)
-        fieldtype = field.ctype
-        val = self._ffiarrays[name].fromaddress(self._buffer.buffer, 1)
-        offset = field.num
-        return fieldtype._CData_output(val, self, offset)
-
-    def __setattr__(self, name, value):
-        try:
-            field = self._fieldtypes[name]
-        except KeyError:
-            raise AttributeError(name)
-        fieldtype = field.ctype
-        cobj = fieldtype.from_param(value)
-        if ensure_objects(cobj) is not None:
-            key = keepalive_key(field.num)
-            store_reference(self, key, cobj._objects)
-        arg = cobj._get_buffer_value()
-        if fieldtype._fficompositesize is not None:
-            from ctypes import memmove
-            dest = self._buffer.buffer
-            memmove(dest, arg, fieldtype._fficompositesize)
-        else:
-            buf = self._ffiarrays[name].fromaddress(self._buffer.buffer, 1)
-            buf[0] = arg
-
-    def _get_buffer_value(self):
-        return self._buffer.buffer

Modified: pypy/branch/jit-unroll-loops/pypy/annotation/bookkeeper.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/annotation/bookkeeper.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/annotation/bookkeeper.py	Sat Oct 30 16:41:17 2010
@@ -24,7 +24,7 @@
 from pypy.rpython import extregistry
 from pypy.tool.identity_dict import identity_dict
 
-class Stats:
+class Stats(object):
 
     def __init__(self, bookkeeper):
         self.bookkeeper = bookkeeper
@@ -137,7 +137,7 @@
     def consider_dict_delitem(self, dic):
         return dic
 
-class Bookkeeper:
+class Bookkeeper(object):
     """The log of choices that have been made while analysing the operations.
     It ensures that the same 'choice objects' will be returned if we ask
     again during reflowing.  Like ExecutionContext, there is an implicit
@@ -736,7 +736,7 @@
         return True
 
 # for parsing call arguments
-class RPythonCallsSpace:
+class RPythonCallsSpace(object):
     """Pseudo Object Space providing almost no real operation.
     For the Arguments class: if it really needs other operations, it means
     that the call pattern is too complex for R-Python.

Modified: pypy/branch/jit-unroll-loops/pypy/annotation/builtin.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/annotation/builtin.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/annotation/builtin.py	Sat Oct 30 16:41:17 2010
@@ -423,7 +423,7 @@
 from pypy.annotation.model import SomePtr
 from pypy.rpython.lltypesystem import lltype
 
-def malloc(s_T, s_n=None, s_flavor=None, s_zero=None):
+def malloc(s_T, s_n=None, s_flavor=None, s_zero=None, s_track_allocation=None):
     assert (s_n is None or s_n.knowntype == int
             or issubclass(s_n.knowntype, pypy.rlib.rarithmetic.base_int))
     assert s_T.is_constant()
@@ -438,13 +438,15 @@
         r = SomePtr(lltype.typeOf(p))
     else:
         assert s_flavor.is_constant()
+        assert s_track_allocation is None or s_track_allocation.is_constant()
         # not sure how to call malloc() for the example 'p' in the
         # presence of s_extraargs
         r = SomePtr(lltype.Ptr(s_T.const))
     return r
 
-def free(s_p, s_flavor):
+def free(s_p, s_flavor, s_track_allocation=None):
     assert s_flavor.is_constant()
+    assert s_track_allocation is None or s_track_allocation.is_constant()
     # same problem as in malloc(): some flavors are not easy to
     # malloc-by-example
     #T = s_p.ll_ptrtype.TO

Modified: pypy/branch/jit-unroll-loops/pypy/annotation/classdef.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/annotation/classdef.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/annotation/classdef.py	Sat Oct 30 16:41:17 2010
@@ -58,7 +58,7 @@
 #        same name in all subclasses of A, if any.  (Parent class attributes can
 #        be visible in reads from instances of subclasses.)
 
-class Attribute:
+class Attribute(object):
     # readonly-ness
     # SomeThing-ness
     # NB.  an attribute is readonly if it is a constant class attribute.
@@ -402,7 +402,7 @@
 
 # ____________________________________________________________
 
-class InstanceSource:
+class InstanceSource(object):
     instance_level = True
 
     def __init__(self, bookkeeper, obj):

Modified: pypy/branch/jit-unroll-loops/pypy/annotation/description.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/annotation/description.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/annotation/description.py	Sat Oct 30 16:41:17 2010
@@ -6,7 +6,7 @@
 from pypy.tool.sourcetools import valid_identifier
 from pypy.tool.pairtype import extendabletype
 
-class CallFamily:
+class CallFamily(object):
     """A family of Desc objects that could be called from common call sites.
     The call families are conceptually a partition of all (callable) Desc
     objects, where the equivalence relation is the transitive closure of
@@ -51,7 +51,7 @@
             self.total_calltable_size += 1
 
 
-class FrozenAttrFamily:
+class FrozenAttrFamily(object):
     """A family of FrozenDesc objects that have any common 'getattr' sites.
     The attr families are conceptually a partition of FrozenDesc objects,
     where the equivalence relation is the transitive closure of:
@@ -80,7 +80,7 @@
         self.attrs[attrname] = s_value
 
 
-class ClassAttrFamily:
+class ClassAttrFamily(object):
     """A family of ClassDesc objects that have common 'getattr' sites for a
     given attribute name.  The attr families are conceptually a partition
     of ClassDesc objects, where the equivalence relation is the transitive

Modified: pypy/branch/jit-unroll-loops/pypy/annotation/dictdef.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/annotation/dictdef.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/annotation/dictdef.py	Sat Oct 30 16:41:17 2010
@@ -77,7 +77,7 @@
             dictdef.dictvalue = self
 
 
-class DictDef:
+class DictDef(object):
     """A dict definition remembers how general the keys and values in that
     particular dict have to be.  Every dict creation makes a new DictDef,
     and the union of two dicts merges the DictKeys and DictValues that each

Modified: pypy/branch/jit-unroll-loops/pypy/annotation/listdef.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/annotation/listdef.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/annotation/listdef.py	Sat Oct 30 16:41:17 2010
@@ -6,7 +6,7 @@
 class TooLateForChange(Exception):
     pass
 
-class ListItem:
+class ListItem(object):
     mutated = False    # True for lists mutated after creation
     resized = False    # True for lists resized after creation
     range_step = None  # the step -- only for lists only created by a range()
@@ -117,7 +117,7 @@
         return updated
 
 
-class ListDef:
+class ListDef(object):
     """A list definition remembers how general the items in that particular
     list have to be.  Every list creation makes a new ListDef, and the union
     of two lists merges the ListItems that each ListDef stores."""

Modified: pypy/branch/jit-unroll-loops/pypy/annotation/model.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/annotation/model.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/annotation/model.py	Sat Oct 30 16:41:17 2010
@@ -574,11 +574,11 @@
         
 NUMBER = object()
 annotation_to_ll_map = [
+    (SomeSingleFloat(), lltype.SingleFloat),
     (s_None, lltype.Void),   # also matches SomeImpossibleValue()
     (s_Bool, lltype.Bool),
     (SomeInteger(knowntype=r_ulonglong), NUMBER),    
     (SomeFloat(), lltype.Float),
-    (SomeSingleFloat(), lltype.SingleFloat),
     (SomeChar(), lltype.Char),
     (SomeUnicodeCodePoint(), lltype.UniChar),
     (SomeAddress(), llmemory.Address),

Modified: pypy/branch/jit-unroll-loops/pypy/annotation/policy.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/annotation/policy.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/annotation/policy.py	Sat Oct 30 16:41:17 2010
@@ -1,4 +1,4 @@
-# base annotation policy for overrides and specialization
+# base annotation policy for specialization
 from pypy.annotation.specialize import default_specialize as default
 from pypy.annotation.specialize import specialize_argvalue, specialize_argtype, specialize_arglistitemtype
 from pypy.annotation.specialize import memo
@@ -41,7 +41,7 @@
         if directive is None:
             return pol.default_specialize
 
-        # specialize|override:name[(args)]
+        # specialize[(args)]
         directive_parts = directive.split('(', 1)
         if len(directive_parts) == 1:
             [name] = directive_parts
@@ -60,14 +60,6 @@
         except AttributeError:
             raise AttributeError("%r specialize tag not defined in annotation"
                                  "policy %s" % (name, pol))
-        if directive.startswith('override:'):
-            # different signature: override__xyz(*args_s)
-            if parms:
-                raise Exception, "override:* specialisations don't support parameters"
-            def specialize_override(funcdesc, args_s):
-                funcdesc.overridden = True
-                return specializer(*args_s)
-            return specialize_override
         else:
             if not parms:
                 return specializer
@@ -92,9 +84,5 @@
         from pypy.rpython.annlowlevel import LowLevelAnnotatorPolicy
         return LowLevelAnnotatorPolicy.specialize__ll_and_arg(*args)
 
-    def override__ignore(pol, *args):
-        bk = getbookkeeper()
-        return bk.immutablevalue(None)
-
 class StrictAnnotatorPolicy(AnnotatorPolicy):
     allow_someobjects = False

Modified: pypy/branch/jit-unroll-loops/pypy/annotation/specialize.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/annotation/specialize.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/annotation/specialize.py	Sat Oct 30 16:41:17 2010
@@ -100,7 +100,7 @@
 # ____________________________________________________________________________
 # specializations
 
-class MemoTable:
+class MemoTable(object):
     def __init__(self, funcdesc, args, value):
         self.funcdesc = funcdesc
         self.table = {args: value}

Modified: pypy/branch/jit-unroll-loops/pypy/annotation/test/test_annrpython.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/annotation/test/test_annrpython.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/annotation/test/test_annrpython.py	Sat Oct 30 16:41:17 2010
@@ -1,4 +1,4 @@
-
+from __future__ import with_statement
 import autopath
 import py.test
 import sys
@@ -766,28 +766,6 @@
         s = a.build_types(f, [list])
         assert s.classdef is a.bookkeeper.getuniqueclassdef(IndexError)  # KeyError ignored because l is a list
 
-    def test_overrides(self):
-        excs = []
-        def record_exc(e):
-            """NOT_RPYTHON"""
-            excs.append(sys.exc_info)
-        record_exc._annspecialcase_ = "override:record_exc"
-        def g():
-            pass
-        def f():
-            try:
-                g()
-            except Exception, e:
-                record_exc(e)
-        class MyAnnotatorPolicy(policy.AnnotatorPolicy):
-
-            def override__record_exc(pol, s_e):
-                return a.bookkeeper.immutablevalue(None)
-            
-        a = self.RPythonAnnotator(policy=MyAnnotatorPolicy())
-        s = a.build_types(f, [])
-        assert s.const is None
-
     def test_freeze_protocol(self):
         class Stuff:
             def __init__(self, flag):
@@ -3359,6 +3337,26 @@
         s = a.build_types(f, [])
         assert isinstance(s, annmodel.SomeChar)
 
+    def test_context_manager(self):
+        class C:
+            def __init__(self):
+                pass
+            def __enter__(self):
+                self.x = 1
+            def __exit__(self, *args):
+                self.x = 3
+        def f():
+            c = C()
+            with c:
+                pass
+            return c.x
+
+        a = self.RPythonAnnotator()
+        s = a.build_types(f, [])
+        assert isinstance(s, annmodel.SomeInteger)
+        # not a constant: both __enter__ and __exit__ have been annotated
+        assert not s.is_constant()
+
 
 def g(n):
     return [0,1,2,n]

Modified: pypy/branch/jit-unroll-loops/pypy/annotation/test/test_model.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/annotation/test/test_model.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/annotation/test/test_model.py	Sat Oct 30 16:41:17 2010
@@ -128,7 +128,7 @@
     assert isinstance(s_p, SomeOOInstance) and s_p.ootype == C
 
 def test_annotation_to_lltype():
-    from pypy.rlib.rarithmetic import r_uint
+    from pypy.rlib.rarithmetic import r_uint, r_singlefloat
     s_i = SomeInteger()
     s_pos = SomeInteger(nonneg=True)
     s_1 = SomeInteger(nonneg=True); s_1.const = 1
@@ -151,6 +151,9 @@
     C = ootype.Instance('C', ROOT, {})
     ref = SomeOOInstance(C)
     assert annotation_to_lltype(ref) == C
+    s_singlefloat = SomeSingleFloat()
+    s_singlefloat.const = r_singlefloat(0.0)
+    assert annotation_to_lltype(s_singlefloat) == lltype.SingleFloat
     
 def test_ll_union():
     PS1 = lltype.Ptr(lltype.GcStruct('s'))

Modified: pypy/branch/jit-unroll-loops/pypy/annotation/unaryop.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/annotation/unaryop.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/annotation/unaryop.py	Sat Oct 30 16:41:17 2010
@@ -434,6 +434,9 @@
     def method_clear(dct):
         pass
 
+    def method_popitem(dct):
+        return dct.getanyitem('items')
+
     def _can_only_throw(dic, *ignore):
         if dic1.dictdef.dictkey.custom_eq_hash:
             return None    # r_dict: can throw anything

Modified: pypy/branch/jit-unroll-loops/pypy/config/pypyoption.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/config/pypyoption.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/config/pypyoption.py	Sat Oct 30 16:41:17 2010
@@ -30,7 +30,8 @@
       "rctime" , "select", "zipimport", "_lsprof",
      "crypt", "signal", "_rawffi", "termios", "zlib",
      "struct", "md5", "sha", "bz2", "_minimal_curses", "cStringIO",
-     "thread", "itertools", "pyexpat", "_ssl", "cpyext", "array"]
+     "thread", "itertools", "pyexpat", "_ssl", "cpyext", "array",
+     "_bisect"]
 ))
 
 working_oo_modules = default_modules.copy()
@@ -73,9 +74,10 @@
     }
 
 module_import_dependencies = {
-    # no _rawffi if importing pypy.rlib.libffi raises ImportError
+    # no _rawffi if importing pypy.rlib.clibffi raises ImportError
     # or CompilationError
-    "_rawffi"   : ["pypy.rlib.libffi"],
+    "_rawffi"   : ["pypy.rlib.clibffi"],
+    "_ffi"      : ["pypy.rlib.clibffi"],
 
     "zlib"      : ["pypy.rlib.rzlib"],
     "bz2"       : ["pypy.module.bz2.interp_bz2"],
@@ -198,6 +200,9 @@
         BoolOption("withstrslice", "use strings optimized for slicing",
                    default=False),
 
+        BoolOption("withstrbuf", "use strings optimized for addition (ver 2)",
+                   default=False),
+
         BoolOption("withprebuiltchar",
                    "use prebuilt single-character string objects",
                    default=False),
@@ -210,7 +215,8 @@
         BoolOption("withrope", "use ropes as the string implementation",
                    default=False,
                    requires=[("objspace.std.withstrslice", False),
-                             ("objspace.std.withstrjoin", False)],
+                             ("objspace.std.withstrjoin", False),
+                             ("objspace.std.withstrbuf", False)],
                    suggests=[("objspace.std.withprebuiltchar", True),
                              ("objspace.std.sharesmallstr", True)]),
 
@@ -224,19 +230,17 @@
                    requires=[("objspace.opcodes.CALL_LIKELY_BUILTIN", False),
                              ("objspace.honor__builtins__", False)]),
 
-        BoolOption("withsharingdict",
-                   "use dictionaries that share the keys part",
-                   default=False),
-
         BoolOption("withdictmeasurement",
                    "create huge files with masses of information "
                    "about dictionaries",
                    default=False),
 
-        BoolOption("withinlineddict",
-                   "make instances more compact by revoming a level of indirection",
+        BoolOption("withmapdict",
+                   "make instances really small but slow without the JIT",
                    default=False,
-                   requires=[("objspace.std.withshadowtracking", False)]),
+                   requires=[("objspace.std.getattributeshortcut", True),
+                             ("objspace.std.withtypeversion", True),
+                       ]),
 
         BoolOption("withrangelist",
                    "enable special range list implementation that does not "
@@ -251,12 +255,6 @@
                    # weakrefs needed, because of get_subclasses()
                    requires=[("translation.rweakref", True)]),
 
-        BoolOption("withshadowtracking",
-                   "track whether an instance attribute shadows a type"
-                   " attribute",
-                   default=False,
-                   requires=[("objspace.std.withtypeversion", True),
-                             ("translation.rweakref", True)]),
         BoolOption("withmethodcache",
                    "try to cache method lookups",
                    default=False,
@@ -328,9 +326,6 @@
         config.objspace.std.suggest(optimized_list_getitem=True)
         config.objspace.std.suggest(getattributeshortcut=True)
         config.objspace.std.suggest(newshortcut=True)        
-        if type_system != 'ootype':
-            config.objspace.std.suggest(withsharingdict=True)
-        config.objspace.std.suggest(withinlineddict=True)
 
     # extra costly optimizations only go in level 3
     if level == '3':
@@ -343,7 +338,7 @@
         config.objspace.std.suggest(withprebuiltint=True)
         config.objspace.std.suggest(withrangelist=True)
         config.objspace.std.suggest(withprebuiltchar=True)
-        config.objspace.std.suggest(withinlineddict=True)
+        config.objspace.std.suggest(withmapdict=True)
         config.objspace.std.suggest(withstrslice=True)
         config.objspace.std.suggest(withstrjoin=True)
         # xxx other options? ropes maybe?
@@ -359,6 +354,7 @@
     # extra optimizations with the JIT
     if level == 'jit':
         config.objspace.std.suggest(withcelldict=True)
+        config.objspace.std.suggest(withmapdict=True)
 
 
 def enable_allworkingmodules(config):

Modified: pypy/branch/jit-unroll-loops/pypy/config/test/test_pypyoption.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/config/test/test_pypyoption.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/config/test/test_pypyoption.py	Sat Oct 30 16:41:17 2010
@@ -47,7 +47,7 @@
 def test_set_pypy_opt_level():
     conf = get_pypy_config()
     set_pypy_opt_level(conf, '2')
-    assert conf.objspace.std.withsharingdict
+    assert conf.objspace.std.newshortcut
     conf = get_pypy_config()
     set_pypy_opt_level(conf, '0')
     assert not conf.objspace.std.newshortcut
@@ -59,7 +59,6 @@
 
     assert not conf.objspace.std.withtypeversion
     assert not conf.objspace.std.withmethodcache
-    assert not conf.objspace.std.withshadowtracking
 
 def test_check_documentation():
     def check_file_exists(fn):

Modified: pypy/branch/jit-unroll-loops/pypy/conftest.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/conftest.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/conftest.py	Sat Oct 30 16:41:17 2010
@@ -7,6 +7,7 @@
 from inspect import isclass, getmro
 from pypy.tool.udir import udir
 from pypy.tool.autopath import pypydir
+from pypy.tool import leakfinder
 
 # pytest settings
 pytest_plugins = "resultlog",
@@ -354,7 +355,14 @@
 
     def runtest(self):
         try:
-            super(IntTestFunction, self).runtest()
+            leakfinder.start_tracking_allocations()
+            try:
+                super(IntTestFunction, self).runtest()
+            finally:
+                if leakfinder.TRACK_ALLOCATIONS:
+                    leaks = leakfinder.stop_tracking_allocations(False)
+                else:
+                    leaks = None   # stop_tracking_allocations() already called
         except OperationError, e:
             check_keyboard_interrupt(e)
             raise
@@ -373,6 +381,8 @@
                 _pygame_imported = True
                 assert option.view, ("should not invoke Pygame "
                                      "if conftest.option.view is False")
+        if leaks:        # check for leaks, but only if the test passed so far
+            raise leakfinder.MallocMismatch(leaks)
 
 class AppTestFunction(PyPyTestFunction):
     def _prunetraceback(self, traceback):

Modified: pypy/branch/jit-unroll-loops/pypy/doc/config/objspace.opcodes.CALL_METHOD.txt
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/doc/config/objspace.opcodes.CALL_METHOD.txt	(original)
+++ pypy/branch/jit-unroll-loops/pypy/doc/config/objspace.opcodes.CALL_METHOD.txt	Sat Oct 30 16:41:17 2010
@@ -5,8 +5,6 @@
 case.  So far, this only works for calls with no keyword, no ``*arg``
 and no ``**arg`` but it would be easy to extend.
 
-Gives the best results combined with :config:`objspace.std.withshadowtracking`.
-
 For more information, see the section in `Standard Interpreter Optimizations`_.
 
 .. _`Standard Interpreter Optimizations`: ../interpreter-optimizations.html#lookup-method-call-method

Modified: pypy/branch/jit-unroll-loops/pypy/doc/docindex.txt
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/doc/docindex.txt	(original)
+++ pypy/branch/jit-unroll-loops/pypy/doc/docindex.txt	Sat Oct 30 16:41:17 2010
@@ -84,7 +84,7 @@
 
 PyPy's own tests `summary`_, daily updated, run through BuildBot infrastructure.
 You can also find CPython's compliance tests run with compiled ``pypy-c``
-exeuctables there.
+executables there.
 
 information dating from early 2007: 
 

Modified: pypy/branch/jit-unroll-loops/pypy/doc/interpreter-optimizations.txt
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/doc/interpreter-optimizations.txt	(original)
+++ pypy/branch/jit-unroll-loops/pypy/doc/interpreter-optimizations.txt	Sat Oct 30 16:41:17 2010
@@ -153,8 +153,8 @@
 dicts:
 the representation of the instance dict contains only a list of values.
 
-You can enable this feature with the :config:`objspace.std.withsharingdict`
-option.
+A more advanced version of sharing dicts, called *map dicts,* is available
+with the :config:`objspace.std.withmapdict` option.
 
 Builtin-Shadowing
 +++++++++++++++++
@@ -219,8 +219,7 @@
 shadowing the class attribute. If we know that there is no shadowing (since
 instance dict tells us that) we can save this lookup on the instance dictionary.
 
-You can enable this feature with the :config:`objspace.std.withshadowtracking`
-option.
+*This was deprecated and is no longer available.*
 
 
 Method Caching

Modified: pypy/branch/jit-unroll-loops/pypy/interpreter/astcompiler/test/test_compiler.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/interpreter/astcompiler/test/test_compiler.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/interpreter/astcompiler/test/test_compiler.py	Sat Oct 30 16:41:17 2010
@@ -41,7 +41,7 @@
         co_expr = compile(evalexpr, '<evalexpr>', 'eval')
         space = self.space
         pyco_expr = PyCode._from_code(space, co_expr)
-        w_res = pyco_expr.exec_code(space, w_dict, w_dict)
+        w_res = pyco_expr.exec_host_bytecode(space, w_dict, w_dict)
         res = space.str_w(space.repr(w_res))
         if not isinstance(expected, float):
             assert res == repr(expected)

Modified: pypy/branch/jit-unroll-loops/pypy/interpreter/baseobjspace.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/interpreter/baseobjspace.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/interpreter/baseobjspace.py	Sat Oct 30 16:41:17 2010
@@ -36,13 +36,10 @@
             return space.finditem_str(w_dict, attr)
         return None
 
-    def getdictvalue_attr_is_in_class(self, space, attr):
-        return self.getdictvalue(space, attr)
-
-    def setdictvalue(self, space, attr, w_value, shadows_type=True):
+    def setdictvalue(self, space, attr, w_value):
         w_dict = self.getdict()
         if w_dict is not None:
-            space.setitem_str(w_dict, attr, w_value, shadows_type)
+            space.setitem_str(w_dict, attr, w_value)
             return True
         return False
 
@@ -168,6 +165,20 @@
     def _call_builtin_destructor(self):
         pass     # method overridden in typedef.py
 
+    # hooks that the mapdict implementations needs:
+    def _get_mapdict_map(self):
+        return None
+    def _set_mapdict_map(self, map):
+        raise NotImplementedError
+    def _mapdict_read_storage(self, index):
+        raise NotImplementedError
+    def _mapdict_write_storage(self, index, value):
+        raise NotImplementedError
+    def _mapdict_storage_length(self):
+        raise NotImplementedError
+    def _set_mapdict_storage_and_map(self, storage, map):
+        raise NotImplementedError
+
 
 class Wrappable(W_Root):
     """A subclass of Wrappable is an internal, interpreter-level class
@@ -643,7 +654,7 @@
         """shortcut for space.int_w(space.hash(w_obj))"""
         return self.int_w(self.hash(w_obj))
 
-    def setitem_str(self, w_obj, key, w_value, shadows_type=True):
+    def setitem_str(self, w_obj, key, w_value):
         return self.setitem(w_obj, self.wrap(key), w_value)
 
     def finditem_str(self, w_obj, key):
@@ -725,7 +736,7 @@
 
     def unpackiterable(self, w_iterable, expected_length=-1):
         """Unpack an iterable object into a real (interpreter-level) list.
-        Raise a real (subclass of) ValueError if the length is wrong."""
+        Raise an OperationError(w_ValueError) if the length is wrong."""
         w_iterator = self.iter(w_iterable)
         items = []
         while True:

Modified: pypy/branch/jit-unroll-loops/pypy/interpreter/function.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/interpreter/function.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/interpreter/function.py	Sat Oct 30 16:41:17 2010
@@ -430,8 +430,11 @@
         self.w_class = w_class         # possibly space.w_None
 
     def descr_method__new__(space, w_subtype, w_function, w_instance, w_class=None):
-        if space.is_w( w_instance, space.w_None ):
+        if space.is_w(w_instance, space.w_None):
             w_instance = None
+        if w_instance is None and space.is_w(w_class, space.w_None):
+            raise OperationError(space.w_TypeError,
+                                 space.wrap("unbound methods must have class"))
         method = space.allocate_instance(Method, w_subtype)
         Method.__init__(method, space, w_function, w_instance, w_class)
         return space.wrap(method)
@@ -586,12 +589,14 @@
             w_klass = space.type(w_obj)
         return space.wrap(Method(space, self.w_function, w_klass, space.w_None))
 
-    def descr_classmethod__new__(space, w_type, w_function):
+    def descr_classmethod__new__(space, w_subtype, w_function):
         if not space.is_true(space.callable(w_function)):
             typename = space.type(w_function).getname(space, '?')
             raise operationerrfmt(space.w_TypeError,
                                   "'%s' object is not callable", typename)
-        return space.wrap(ClassMethod(w_function))
+        instance = space.allocate_instance(ClassMethod, w_subtype)
+        instance.__init__(w_function)
+        return space.wrap(instance)
 
 class FunctionWithFixedCode(Function):
     can_change_code = False

Modified: pypy/branch/jit-unroll-loops/pypy/interpreter/gateway.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/interpreter/gateway.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/interpreter/gateway.py	Sat Oct 30 16:41:17 2010
@@ -28,7 +28,7 @@
 # internal non-translatable parts: 
 import py
 
-class SignatureBuilder:
+class SignatureBuilder(object):
     "NOT_RPYTHON"
     def __init__(self, func=None, argnames=None, varargname=None,
                  kwargname=None, name = None):
@@ -51,7 +51,7 @@
 
 #________________________________________________________________
 
-class UnwrapSpecRecipe:
+class UnwrapSpecRecipe(object):
     "NOT_RPYTHON"
 
     bases_order = [Wrappable, W_Root, ObjSpace, Arguments, object]

Modified: pypy/branch/jit-unroll-loops/pypy/interpreter/pycode.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/interpreter/pycode.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/interpreter/pycode.py	Sat Oct 30 16:41:17 2010
@@ -117,6 +117,10 @@
 
         self._compute_flatcall()
 
+        if self.space.config.objspace.std.withmapdict:
+            from pypy.objspace.std.mapdict import init_mapdict_cache
+            init_mapdict_cache(self)
+
     def _freeze_(self):
         if (self.magic == cpython_magic and
             '__pypy__' not in sys.builtin_module_names):
@@ -253,6 +257,12 @@
                          tuple(self.co_freevars),
                          tuple(self.co_cellvars) )
 
+    def exec_host_bytecode(self, w_dict, w_globals, w_locals):
+        from pypy.interpreter.pyframe import CPythonFrame
+        frame = CPythonFrame(self.space, self, w_globals, None)
+        frame.setdictscope(w_locals)
+        return frame.run()
+
     def dump(self):
         """A dis.dis() dump of the code object."""
         co = self._to_code()

Modified: pypy/branch/jit-unroll-loops/pypy/interpreter/pyframe.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/interpreter/pyframe.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/interpreter/pyframe.py	Sat Oct 30 16:41:17 2010
@@ -13,6 +13,7 @@
 from pypy.rlib.rarithmetic import intmask
 from pypy.rlib import jit, rstack
 from pypy.tool import stdlib_opcode
+from pypy.tool.stdlib_opcode import host_bytecode_spec
 
 # Define some opcodes used
 g = globals()
@@ -140,7 +141,8 @@
         # the following 'assert' is an annotation hint: it hides from
         # the annotator all methods that are defined in PyFrame but
         # overridden in the {,Host}FrameClass subclasses of PyFrame.
-        assert isinstance(self, self.space.FrameClass)
+        assert (isinstance(self, self.space.FrameClass) or
+                not self.space.config.translating)
         executioncontext = self.space.getexecutioncontext()
         executioncontext.enter(self)
         try:
@@ -634,6 +636,18 @@
             return space.wrap(self.builtin is not space.builtin)
         return space.w_False
 
+class CPythonFrame(PyFrame):
+    """
+    Execution of host (CPython) opcodes.
+    """
+
+    bytecode_spec = host_bytecode_spec
+    opcode_method_names = host_bytecode_spec.method_names
+    opcodedesc = host_bytecode_spec.opcodedesc
+    opdescmap = host_bytecode_spec.opdescmap
+    HAVE_ARGUMENT = host_bytecode_spec.HAVE_ARGUMENT
+
+
 # ____________________________________________________________
 
 def get_block_class(opname):

Modified: pypy/branch/jit-unroll-loops/pypy/interpreter/pyopcode.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/interpreter/pyopcode.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/interpreter/pyopcode.py	Sat Oct 30 16:41:17 2010
@@ -164,6 +164,9 @@
             next_instr = block.handle(self, unroller)
             return next_instr
 
+    def call_contextmanager_exit_function(self, w_func, w_typ, w_val, w_tb):
+        return self.space.call_function(w_func, w_typ, w_val, w_tb)
+
     @jit.unroll_safe
     def dispatch_bytecode(self, co_code, next_instr, ec):
         space = self.space
@@ -710,9 +713,14 @@
 
     def LOAD_ATTR(self, nameindex, next_instr):
         "obj.attributename"
-        w_attributename = self.getname_w(nameindex)
         w_obj = self.popvalue()
-        w_value = self.space.getattr(w_obj, w_attributename)
+        if (self.space.config.objspace.std.withmapdict
+            and not jit.we_are_jitted()):
+            from pypy.objspace.std.mapdict import LOAD_ATTR_caching
+            w_value = LOAD_ATTR_caching(self.getcode(), w_obj, nameindex)
+        else:
+            w_attributename = self.getname_w(nameindex)
+            w_value = self.space.getattr(w_obj, w_attributename)
         self.pushvalue(w_value)
     LOAD_ATTR._always_inline_ = True
 
@@ -868,23 +876,43 @@
 
     def WITH_CLEANUP(self, oparg, next_instr):
         # see comment in END_FINALLY for stack state
-        w_exitfunc = self.popvalue()
-        w_unroller = self.peekvalue(2)
+        # This opcode changed a lot between CPython versions
+        if (self.pycode.magic >= 0xa0df2ef
+            # Implementation since 2.7a0: 62191 (introduce SETUP_WITH)
+            or self.pycode.magic >= 0xa0df2d1):
+            # implementation since 2.6a1: 62161 (WITH_CLEANUP optimization)
+            self.popvalue()
+            self.popvalue()
+            w_unroller = self.popvalue()
+            w_exitfunc = self.popvalue()
+            self.pushvalue(w_unroller)
+            self.pushvalue(self.space.w_None)
+            self.pushvalue(self.space.w_None)
+        elif self.pycode.magic >= 0xa0df28c:
+            # Implementation since 2.5a0: 62092 (changed WITH_CLEANUP opcode)
+            w_exitfunc = self.popvalue()
+            w_unroller = self.peekvalue(2)
+        else:
+            raise NotImplementedError("WITH_CLEANUP for CPython <= 2.4")
+
         unroller = self.space.interpclass_w(w_unroller)
         if isinstance(unroller, SApplicationException):
             operr = unroller.operr
-            w_result = self.space.call_function(w_exitfunc,
-                                                operr.w_type,
-                                                operr.get_w_value(self.space),
-                                                operr.application_traceback)
+            w_traceback = self.space.wrap(operr.application_traceback)
+            w_result = self.call_contextmanager_exit_function(
+                w_exitfunc,
+                operr.w_type,
+                operr.get_w_value(self.space),
+                w_traceback)
             if self.space.is_true(w_result):
                 # __exit__() returned True -> Swallow the exception.
                 self.settopvalue(self.space.w_None, 2)
         else:
-            self.space.call_function(w_exitfunc,
-                                     self.space.w_None,
-                                     self.space.w_None,
-                                     self.space.w_None)
+            self.call_contextmanager_exit_function(
+                w_exitfunc,
+                self.space.w_None,
+                self.space.w_None,
+                self.space.w_None)
 
     @jit.unroll_safe
     def call_function(self, oparg, w_star=None, w_starstar=None):
@@ -1225,10 +1253,18 @@
         frame.pushvalue(frame.space.w_None)
         return self.handlerposition   # jump to the handler
 
+class WithBlock(FinallyBlock):
+
+    def really_handle(self, frame, unroller):
+        if (frame.space.full_exceptions and
+            isinstance(unroller, SApplicationException)):
+            unroller.operr.normalize_exception(frame.space)
+        return FinallyBlock.really_handle(self, frame, unroller)
 
 block_classes = {'SETUP_LOOP': LoopBlock,
                  'SETUP_EXCEPT': ExceptBlock,
-                 'SETUP_FINALLY': FinallyBlock}
+                 'SETUP_FINALLY': FinallyBlock,
+                 'SETUP_WITH': WithBlock}
 
 ### helpers written at the application-level ###
 # Some of these functions are expected to be generally useful if other

Modified: pypy/branch/jit-unroll-loops/pypy/interpreter/pyparser/pytokenize.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/interpreter/pyparser/pytokenize.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/interpreter/pyparser/pytokenize.py	Sat Oct 30 16:41:17 2010
@@ -21,40 +21,42 @@
 __all__ = [ "tokenize" ]
 
 # ______________________________________________________________________
-# Automatically generated DFA's (with one or two hand tweeks):
-pseudoStatesAccepts = [True, True, True, True, True, True, True, True,
-                       True, True, False, True, True, True, False, False,
-                       False, False, True, False, False, True, True, False,
-                       True, False, True, False, True, False, True, False,
-                       False, False, True, False, False, False, True]
-
-pseudoStates = [
-    {'\t': 0, '\n': 13, '\x0c': 0, '\r': 14, ' ': 0, '!': 10,
-     '"': 16, '#': 18, '%': 12, '&': 12,
-     "'": 15, '(': 13, ')': 13, '*': 7,
-     '+': 12, ',': 13, '-': 12, '.': 6,
-     '/': 11, '0': 4, '1': 5, '2': 5,
-     '3': 5, '4': 5, '5': 5, '6': 5,
-     '7': 5, '8': 5, '9': 5, ':': 13,
-     ';': 13, '<': 9, '=': 12, '>': 8,
-     '@': 13, 'A': 1,
-     'B': 1, 'C': 1, 'D': 1, 'E': 1,
-     'F': 1, 'G': 1, 'H': 1, 'I': 1,
-     'J': 1, 'K': 1, 'L': 1, 'M': 1,
-     'N': 1, 'O': 1, 'P': 1, 'Q': 1,
-     'R': 2, 'S': 1, 'T': 1, 'U': 3,
-     'V': 1, 'W': 1, 'X': 1, 'Y': 1,
-     'Z': 1, '[': 13, '\\': 17, ']': 13,
-     '^': 12, '_': 1, '`': 13, 'a': 1,
-     'b': 1, 'c': 1, 'd': 1, 'e': 1,
-     'f': 1, 'g': 1, 'h': 1, 'i': 1,
-     'j': 1, 'k': 1, 'l': 1, 'm': 1,
-     'n': 1, 'o': 1, 'p': 1, 'q': 1,
-     'r': 2, 's': 1, 't': 1, 'u': 3,
-     'v': 1, 'w': 1, 'x': 1, 'y': 1,
-     'z': 1, '{': 13, '|': 12, '}': 13,
-     '~': 13},
+# Automatically generated DFA's
 
+accepts = [True, True, True, True, True, True, True, True,
+           True, True, False, True, True, True, False, False,
+           False, False, True, True, True, False, True,
+           False, True, False, True, False, False, True,
+           False, False, False, False, True, False, False,
+           False, True]
+states = [
+    # 0
+    {'\t': 0, '\n': 13, '\x0c': 0,
+     '\r': 14, ' ': 0, '!': 10, '"': 16,
+     '#': 18, '%': 12, '&': 12, "'": 15,
+     '(': 13, ')': 13, '*': 7, '+': 12,
+     ',': 13, '-': 12, '.': 6, '/': 11,
+     '0': 4, '1': 5, '2': 5, '3': 5,
+     '4': 5, '5': 5, '6': 5, '7': 5,
+     '8': 5, '9': 5, ':': 13, ';': 13,
+     '<': 9, '=': 12, '>': 8, '@': 13,
+     'A': 1, 'B': 1, 'C': 1, 'D': 1,
+     'E': 1, 'F': 1, 'G': 1, 'H': 1,
+     'I': 1, 'J': 1, 'K': 1, 'L': 1,
+     'M': 1, 'N': 1, 'O': 1, 'P': 1,
+     'Q': 1, 'R': 2, 'S': 1, 'T': 1,
+     'U': 3, 'V': 1, 'W': 1, 'X': 1,
+     'Y': 1, 'Z': 1, '[': 13, '\\': 17,
+     ']': 13, '^': 12, '_': 1, '`': 13,
+     'a': 1, 'b': 1, 'c': 1, 'd': 1,
+     'e': 1, 'f': 1, 'g': 1, 'h': 1,
+     'i': 1, 'j': 1, 'k': 1, 'l': 1,
+     'm': 1, 'n': 1, 'o': 1, 'p': 1,
+     'q': 1, 'r': 2, 's': 1, 't': 1,
+     'u': 3, 'v': 1, 'w': 1, 'x': 1,
+     'y': 1, 'z': 1, '{': 13, '|': 12,
+     '}': 13, '~': 13},
+    # 1
     {'0': 1, '1': 1, '2': 1, '3': 1,
      '4': 1, '5': 1, '6': 1, '7': 1,
      '8': 1, '9': 1, 'A': 1, 'B': 1,
@@ -71,7 +73,7 @@
      'p': 1, 'q': 1, 'r': 1, 's': 1,
      't': 1, 'u': 1, 'v': 1, 'w': 1,
      'x': 1, 'y': 1, 'z': 1},
-
+    # 2
     {'"': 16, "'": 15, '0': 1, '1': 1,
      '2': 1, '3': 1, '4': 1, '5': 1,
      '6': 1, '7': 1, '8': 1, '9': 1,
@@ -89,7 +91,7 @@
      'r': 1, 's': 1, 't': 1, 'u': 1,
      'v': 1, 'w': 1, 'x': 1, 'y': 1,
      'z': 1},
-
+    # 3
     {'"': 16, "'": 15, '0': 1, '1': 1,
      '2': 1, '3': 1, '4': 1, '5': 1,
      '6': 1, '7': 1, '8': 1, '9': 1,
@@ -107,158 +109,182 @@
      'r': 2, 's': 1, 't': 1, 'u': 1,
      'v': 1, 'w': 1, 'x': 1, 'y': 1,
      'z': 1},
-
-    {'.': 24, '0': 22, '1': 22, '2': 22,
-     '3': 22, '4': 22, '5': 22, '6': 22,
-     '7': 22, '8': 23, '9': 23, 'E': 25,
-     'J': 13, 'L': 13, 'X': 21, 'e': 25,
-     'j': 13, 'l': 13, 'x': 21},
-
-    {'.': 24, '0': 5, '1': 5, '2': 5,
+    # 4
+    {'.': 22, '0': 20, '1': 20, '2': 20,
+     '3': 20, '4': 20, '5': 20, '6': 20,
+     '7': 20, '8': 21, '9': 21, 'E': 23,
+     'J': 13, 'L': 13, 'X': 19, 'e': 23,
+     'j': 13, 'l': 13, 'x': 19},
+    # 5
+    {'.': 22, '0': 5, '1': 5, '2': 5,
      '3': 5, '4': 5, '5': 5, '6': 5,
-     '7': 5, '8': 5, '9': 5, 'E': 25,
-     'J': 13, 'L': 13, 'e': 25, 'j': 13,
+     '7': 5, '8': 5, '9': 5, 'E': 23,
+     'J': 13, 'L': 13, 'e': 23, 'j': 13,
      'l': 13},
-
-    {'0': 26, '1': 26, '2': 26, '3': 26,
-     '4': 26, '5': 26, '6': 26, '7': 26,
-     '8': 26, '9': 26},
-
+    # 6
+    {'0': 24, '1': 24, '2': 24, '3': 24,
+     '4': 24, '5': 24, '6': 24, '7': 24,
+     '8': 24, '9': 24},
+    # 7
     {'*': 12, '=': 13},
-
+    # 8
     {'=': 13, '>': 12},
-
-    {'=': 13, '<': 12, '>': 13},
-
+    # 9
+    {'<': 12, '=': 13, '>': 13},
+    # 10
     {'=': 13},
-
-    {'=': 13, '/': 12},
-
+    # 11
+    {'/': 12, '=': 13},
+    # 12
     {'=': 13},
-
+    # 13
     {},
-
+    # 14
     {'\n': 13},
-
-    {automata.DEFAULT: 19, '\n': 27, '\\': 29, "'": 28},
-
-    {automata.DEFAULT: 20, '"': 30, '\n': 27, '\\': 31},
-
+    # 15
+    {automata.DEFAULT: 28, '\n': 25, "'": 26, '\\': 27},
+    # 16
+    {automata.DEFAULT: 31, '\n': 25, '"': 29, '\\': 30},
+    # 17
     {'\n': 13, '\r': 14},
-
-    {automata.DEFAULT: 18, '\n': 27, '\r': 27},
-
-    {automata.DEFAULT: 19, '\n': 27, '\\': 29, "'": 13},
-
-    {automata.DEFAULT: 20, '"': 13, '\n': 27, '\\': 31},
-                
-    {'0': 21, '1': 21, '2': 21, '3': 21,
-     '4': 21, '5': 21, '6': 21, '7': 21,
-     '8': 21, '9': 21, 'A': 21, 'B': 21,
-     'C': 21, 'D': 21, 'E': 21, 'F': 21,
-     'L': 13, 'a': 21, 'b': 21, 'c': 21,
-     'd': 21, 'e': 21, 'f': 21, 'l': 13},
-    
-    {'.': 24, '0': 22, '1': 22, '2': 22,
-     '3': 22, '4': 22, '5': 22, '6': 22,
-     '7': 22, '8': 23, '9': 23, 'E': 25,
-     'J': 13, 'L': 13, 'e': 25, 'j': 13,
+    # 18
+    {automata.DEFAULT: 18, '\n': 25, '\r': 25},
+    # 19
+    {'0': 19, '1': 19, '2': 19, '3': 19,
+     '4': 19, '5': 19, '6': 19, '7': 19,
+     '8': 19, '9': 19, 'A': 19, 'B': 19,
+     'C': 19, 'D': 19, 'E': 19, 'F': 19,
+     'L': 13, 'a': 19, 'b': 19, 'c': 19,
+     'd': 19, 'e': 19, 'f': 19, 'l': 13},
+    # 20
+    {'.': 22, '0': 20, '1': 20, '2': 20,
+     '3': 20, '4': 20, '5': 20, '6': 20,
+     '7': 20, '8': 21, '9': 21, 'E': 23,
+     'J': 13, 'L': 13, 'e': 23, 'j': 13,
      'l': 13},
-    
-    {'.': 24, '0': 23, '1': 23, '2': 23,
-     '3': 23, '4': 23, '5': 23, '6': 23,
-     '7': 23, '8': 23, '9': 23, 'E': 25,
-     'J': 13, 'e': 25, 'j': 13},
-    
-    {'0': 24, '1': 24, '2': 24, '3': 24,
-     '4': 24, '5': 24, '6': 24, '7': 24,
-     '8': 24, '9': 24, 'E': 32, 'J': 13,
+    # 21
+    {'.': 22, '0': 21, '1': 21, '2': 21,
+     '3': 21, '4': 21, '5': 21, '6': 21,
+     '7': 21, '8': 21, '9': 21, 'E': 23,
+     'J': 13, 'e': 23, 'j': 13},
+    # 22
+    {'0': 22, '1': 22, '2': 22, '3': 22,
+     '4': 22, '5': 22, '6': 22, '7': 22,
+     '8': 22, '9': 22, 'E': 32, 'J': 13,
      'e': 32, 'j': 13},
-    
+    # 23
     {'+': 33, '-': 33, '0': 34, '1': 34,
      '2': 34, '3': 34, '4': 34, '5': 34,
      '6': 34, '7': 34, '8': 34, '9': 34},
-    
-    {'0': 26, '1': 26, '2': 26, '3': 26,
-     '4': 26, '5': 26, '6': 26, '7': 26,
-     '8': 26, '9': 26, 'E': 32, 'J': 13,
+    # 24
+    {'0': 24, '1': 24, '2': 24, '3': 24,
+     '4': 24, '5': 24, '6': 24, '7': 24,
+     '8': 24, '9': 24, 'E': 32, 'J': 13,
      'e': 32, 'j': 13},
-    
+    # 25
     {},
-
+    # 26
     {"'": 13},
-
+    # 27
     {automata.DEFAULT: 35, '\n': 13, '\r': 14},
-
+    # 28
+    {automata.DEFAULT: 28, '\n': 25, "'": 13, '\\': 27},
+    # 29
     {'"': 13},
-
+    # 30
     {automata.DEFAULT: 36, '\n': 13, '\r': 14},
-
+    # 31
+    {automata.DEFAULT: 31, '\n': 25, '"': 13, '\\': 30},
+    # 32
     {'+': 37, '-': 37, '0': 38, '1': 38,
      '2': 38, '3': 38, '4': 38, '5': 38,
      '6': 38, '7': 38, '8': 38, '9': 38},
-    
-    
+    # 33
     {'0': 34, '1': 34, '2': 34, '3': 34,
      '4': 34, '5': 34, '6': 34, '7': 34,
      '8': 34, '9': 34},
-    
+    # 34
     {'0': 34, '1': 34, '2': 34, '3': 34,
      '4': 34, '5': 34, '6': 34, '7': 34,
      '8': 34, '9': 34, 'J': 13, 'j': 13},
-    
-    {automata.DEFAULT: 35, '\n': 27, '\\': 29, "'": 13},
-    
-    {automata.DEFAULT: 36, '"': 13, '\n': 27, '\\': 31},
-    
+    # 35
+    {automata.DEFAULT: 35, '\n': 25, "'": 13, '\\': 27},
+    # 36
+    {automata.DEFAULT: 36, '\n': 25, '"': 13, '\\': 30},
+    # 37
     {'0': 38, '1': 38, '2': 38, '3': 38,
      '4': 38, '5': 38, '6': 38, '7': 38,
      '8': 38, '9': 38},
-
+    # 38
     {'0': 38, '1': 38, '2': 38, '3': 38,
      '4': 38, '5': 38, '6': 38, '7': 38,
      '8': 38, '9': 38, 'J': 13, 'j': 13},
     ]
+pseudoDFA = automata.DFA(states, accepts)
 
-pseudoDFA = automata.DFA(pseudoStates, pseudoStatesAccepts)
-
-double3StatesAccepts = [False, False, False, False, False, True]
-double3States = [
+accepts = [False, False, False, False, False, True]
+states = [
+    # 0
     {automata.DEFAULT: 0, '"': 1, '\\': 2},
+    # 1
     {automata.DEFAULT: 4, '"': 3, '\\': 2},
+    # 2
     {automata.DEFAULT: 4},
+    # 3
     {automata.DEFAULT: 4, '"': 5, '\\': 2},
+    # 4
     {automata.DEFAULT: 4, '"': 1, '\\': 2},
+    # 5
     {automata.DEFAULT: 4, '"': 5, '\\': 2},
     ]
-double3DFA = automata.NonGreedyDFA(double3States, double3StatesAccepts)
+double3DFA = automata.NonGreedyDFA(states, accepts)
 
-single3StatesAccepts = [False, False, False, False, False, True]
-single3States = [
-    {automata.DEFAULT: 0, '\\': 2, "'": 1},
-    {automata.DEFAULT: 4, '\\': 2, "'": 3},
+accepts = [False, False, False, False, False, True]
+states = [
+    # 0
+    {automata.DEFAULT: 0, "'": 1, '\\': 2},
+    # 1
+    {automata.DEFAULT: 4, "'": 3, '\\': 2},
+    # 2
     {automata.DEFAULT: 4},
-    {automata.DEFAULT: 4, '\\': 2, "'": 5},
-    {automata.DEFAULT: 4, '\\': 2, "'": 1},
-    {automata.DEFAULT: 4, '\\': 2, "'": 5},
+    # 3
+    {automata.DEFAULT: 4, "'": 5, '\\': 2},
+    # 4
+    {automata.DEFAULT: 4, "'": 1, '\\': 2},
+    # 5
+    {automata.DEFAULT: 4, "'": 5, '\\': 2},
     ]
-single3DFA = automata.NonGreedyDFA(single3States, single3StatesAccepts)
+single3DFA = automata.NonGreedyDFA(states, accepts)
 
-singleStatesAccepts = [False, True, False]
-singleStates = [
-    {automata.DEFAULT: 0, '\\': 2, "'": 1},
+accepts = [False, True, False, False]
+states = [
+    # 0
+    {automata.DEFAULT: 0, "'": 1, '\\': 2},
+    # 1
     {},
-    {automata.DEFAULT: 0},
+    # 2
+    {automata.DEFAULT: 3},
+    # 3
+    {automata.DEFAULT: 3, "'": 1, '\\': 2},
     ]
-singleDFA = automata.DFA(singleStates, singleStatesAccepts)
+singleDFA = automata.DFA(states, accepts)
 
-doubleStatesAccepts = [False, True, False]
-doubleStates = [
+accepts = [False, True, False, False]
+states = [
+    # 0
     {automata.DEFAULT: 0, '"': 1, '\\': 2},
+    # 1
     {},
-    {automata.DEFAULT: 0},
+    # 2
+    {automata.DEFAULT: 3},
+    # 3
+    {automata.DEFAULT: 3, '"': 1, '\\': 2},
     ]
-doubleDFA = automata.DFA(doubleStates, doubleStatesAccepts)
+doubleDFA = automata.DFA(states, accepts)
+
+
+#_______________________________________________________________________
+# End of automatically generated DFA's
 
 endDFAs = {"'" : singleDFA,
            '"' : doubleDFA,

Modified: pypy/branch/jit-unroll-loops/pypy/interpreter/test/test_function.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/interpreter/test/test_function.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/interpreter/test/test_function.py	Sat Oct 30 16:41:17 2010
@@ -482,6 +482,11 @@
         raises(TypeError, m, MyInst(None))
         raises(TypeError, m, MyInst(42))
 
+    def test_invalid_creation(self):
+        import new
+        def f(): pass
+        raises(TypeError, new.instancemethod, f, None)
+
 
 class TestMethod: 
     def setup_method(self, method):

Modified: pypy/branch/jit-unroll-loops/pypy/interpreter/typedef.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/interpreter/typedef.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/interpreter/typedef.py	Sat Oct 30 16:41:17 2010
@@ -133,6 +133,13 @@
     typedef = cls.typedef
     if wants_dict and typedef.hasdict:
         wants_dict = False
+    if config.objspace.std.withmapdict and not typedef.hasdict:
+        # mapdict only works if the type does not already have a dict
+        if wants_del:
+            parentcls = get_unique_interplevel_subclass(config, cls, True, True,
+                                                        False, True)
+            return _usersubclswithfeature(config, parentcls, "del")
+        return _usersubclswithfeature(config, cls, "user", "dict", "weakref", "slots")
     # Forest of if's - see the comment above.
     if wants_del:
         if wants_dict:
@@ -186,10 +193,21 @@
 
     def add(Proto):
         for key, value in Proto.__dict__.items():
-            if not key.startswith('__') or key == '__del__':
+            if (not key.startswith('__') and not key.startswith('_mixin_') 
+                    or key == '__del__'):
+                if hasattr(value, "func_name"):
+                    value = func_with_new_name(value, value.func_name)
                 body[key] = value
 
+    if (config.objspace.std.withmapdict and "dict" in features):
+        from pypy.objspace.std.mapdict import BaseMapdictObject, ObjectMixin
+        add(BaseMapdictObject)
+        add(ObjectMixin)
+        body["user_overridden_class"] = True
+        features = ()
+
     if "user" in features:     # generic feature needed by all subcls
+
         class Proto(object):
             user_overridden_class = True
 
@@ -245,16 +263,10 @@
                 return self.slots_w[index]
         add(Proto)
 
-    wantdict = "dict" in features
-    if wantdict and config.objspace.std.withinlineddict:
-        from pypy.objspace.std.objectobject import W_ObjectObject
-        from pypy.objspace.std.inlinedict import make_mixin
-        if supercls is W_ObjectObject:
-            Mixin = make_mixin(config)
-            add(Mixin)
-            wantdict = False
-
-    if wantdict:
+    if "dict" in features:
+        base_user_setup = supercls.user_setup.im_func
+        if "user_setup" in body:
+            base_user_setup = body["user_setup"]
         class Proto(object):
             def getdict(self):
                 return self.w__dict__
@@ -263,24 +275,13 @@
                 self.w__dict__ = check_new_dictionary(space, w_dict)
             
             def user_setup(self, space, w_subtype):
-                self.space = space
-                self.w__class__ = w_subtype
                 self.w__dict__ = space.newdict(
                     instance=True, classofinstance=w_subtype)
-                self.user_setup_slots(w_subtype.nslots)
+                base_user_setup(self, space, w_subtype)
 
             def setclass(self, space, w_subtype):
                 # only used by descr_set___class__
                 self.w__class__ = w_subtype
-                if space.config.objspace.std.withshadowtracking:
-                    self.w__dict__.set_shadows_anything()
-
-            def getdictvalue_attr_is_in_class(self, space, name):
-                w_dict = self.w__dict__
-                if space.config.objspace.std.withshadowtracking:
-                    if not w_dict.shadows_anything():
-                        return None
-                return space.finditem_str(w_dict, name)
 
         add(Proto)
 

Modified: pypy/branch/jit-unroll-loops/pypy/jit/backend/detect_cpu.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/jit/backend/detect_cpu.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/jit/backend/detect_cpu.py	Sat Oct 30 16:41:17 2010
@@ -23,11 +23,6 @@
         mach = os.popen('uname -m', 'r').read().strip()
         if not mach:
             raise ProcessorAutodetectError, "cannot run 'uname -m'"
-    if mach == 'x86_64':
-        if sys.maxint == 2147483647:
-            mach = 'x86'     # it's a 64-bit processor but in 32-bits mode, maybe
-        else:
-            assert sys.maxint == 2 ** 63 - 1
     try:
         return {'i386': 'x86',
                 'i486': 'x86',
@@ -36,17 +31,21 @@
                 'i86pc': 'x86',    # Solaris/Intel
                 'x86':   'x86',    # Apple
                 'Power Macintosh': 'ppc',
-                'x86_64': 'x86_64', 
+                'x86_64': 'x86', 
                 }[mach]
     except KeyError:
         raise ProcessorAutodetectError, "unsupported processor '%s'" % mach
 
 def autodetect():
     model = autodetect_main_model()
-    if model == 'x86':
-        from pypy.jit.backend.x86.detect_sse2 import detect_sse2
-        if not detect_sse2():
-            model = 'x86-without-sse2'
+    if sys.maxint == 2**63-1:
+        model += '_64'
+    else:
+        assert sys.maxint == 2**31-1
+        if model == 'x86':
+            from pypy.jit.backend.x86.detect_sse2 import detect_sse2
+            if not detect_sse2():
+                model = 'x86-without-sse2'
     return model
 
 def getcpuclassname(backend_name="auto"):

Modified: pypy/branch/jit-unroll-loops/pypy/jit/backend/llgraph/llimpl.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/jit/backend/llgraph/llimpl.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/jit/backend/llgraph/llimpl.py	Sat Oct 30 16:41:17 2010
@@ -10,7 +10,7 @@
                                          BoxInt, BoxPtr, BoxObj, BoxFloat,
                                          REF, INT, FLOAT)
 from pypy.jit.codewriter import heaptracker
-from pypy.rpython.lltypesystem import lltype, llmemory, rclass, rstr
+from pypy.rpython.lltypesystem import lltype, llmemory, rclass, rstr, rffi
 from pypy.rpython.ootypesystem import ootype
 from pypy.rpython.module.support import LLSupport, OOSupport
 from pypy.rpython.llinterp import LLException
@@ -129,7 +129,7 @@
     'arraylen_gc'     : (('ref',), 'int'),
     'call'            : (('ref', 'varargs'), 'intorptr'),
     'call_assembler'  : (('varargs',), 'intorptr'),
-    'cond_call_gc_wb' : (('ptr',), None),
+    'cond_call_gc_wb' : (('ptr', 'ptr'), None),
     'oosend'          : (('varargs',), 'intorptr'),
     'oosend_pure'     : (('varargs',), 'intorptr'),
     'guard_true'      : (('bool',), None),
@@ -305,12 +305,12 @@
     loop = _from_opaque(loop)
     loop.operations.append(Operation(opnum))
 
-def compile_add_descr(loop, ofs, type):
+def compile_add_descr(loop, ofs, type, arg_types):
     from pypy.jit.backend.llgraph.runner import Descr
     loop = _from_opaque(loop)
     op = loop.operations[-1]
     assert isinstance(type, str) and len(type) == 1
-    op.descr = Descr(ofs, type)
+    op.descr = Descr(ofs, type, arg_types=arg_types)
 
 def compile_add_loop_token(loop, descr):
     if we_are_translated():
@@ -801,7 +801,7 @@
             else:
                 raise TypeError(x)
         try:
-            return _do_call_common(func, args_in_order)
+            return _do_call_common(func, args_in_order, calldescr)
         except LLException, lle:
             _last_exception = lle
             d = {'v': None,
@@ -810,7 +810,7 @@
                  FLOAT: 0.0}
             return d[calldescr.typeinfo]
 
-    def op_cond_call_gc_wb(self, descr, a):
+    def op_cond_call_gc_wb(self, descr, a, b):
         py.test.skip("cond_call_gc_wb not supported")
 
     def op_oosend(self, descr, obj, *args):
@@ -1018,6 +1018,9 @@
     if isinstance(TYPE, lltype.Ptr):
         if isinstance(x, (int, long, llmemory.AddressAsInt)):
             x = llmemory.cast_int_to_adr(x)
+        if TYPE is rffi.VOIDP:
+            # assume that we want a "C-style" cast, without typechecking the value
+            return rffi.cast(TYPE, x)
         return llmemory.cast_adr_to_ptr(x, TYPE)
     elif TYPE == llmemory.Address:
         if isinstance(x, (int, long, llmemory.AddressAsInt)):
@@ -1411,10 +1414,26 @@
 def do_call_pushfloat(x):
     _call_args_f.append(x)
 
-def _do_call_common(f, args_in_order=None):
+kind2TYPE = {
+    'i': lltype.Signed,
+    'f': lltype.Float,
+    'v': lltype.Void,
+    }
+
+def _do_call_common(f, args_in_order=None, calldescr=None):
     ptr = llmemory.cast_int_to_adr(f).ptr
-    FUNC = lltype.typeOf(ptr).TO
-    ARGS = FUNC.ARGS
+    PTR = lltype.typeOf(ptr)
+    if PTR == rffi.VOIDP:
+        # it's a pointer to a C function, so we don't have a precise
+        # signature: create one from the descr
+        ARGS = map(kind2TYPE.get, calldescr.arg_types)
+        RESULT = kind2TYPE[calldescr.typeinfo]
+        FUNC = lltype.FuncType(ARGS, RESULT)
+        func_to_call = rffi.cast(lltype.Ptr(FUNC), ptr)
+    else:
+        FUNC = PTR.TO
+        ARGS = FUNC.ARGS
+        func_to_call = ptr._obj._callable
     args = cast_call_args(ARGS, _call_args_i, _call_args_r, _call_args_f,
                           args_in_order)
     del _call_args_i[:]
@@ -1426,7 +1445,7 @@
         result = llinterp.eval_graph(ptr._obj.graph, args)
         # ^^^ may raise, in which case we get an LLException
     else:
-        result = ptr._obj._callable(*args)
+        result = func_to_call(*args)
     return result
 
 def do_call_void(f):

Modified: pypy/branch/jit-unroll-loops/pypy/jit/backend/llgraph/runner.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/jit/backend/llgraph/runner.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/jit/backend/llgraph/runner.py	Sat Oct 30 16:41:17 2010
@@ -118,13 +118,13 @@
             self._descrs[key] = descr
             return descr
 
-    def compile_bridge(self, faildescr, inputargs, operations):
+    def compile_bridge(self, faildescr, inputargs, operations, log=True):
         c = llimpl.compile_start()
         self._compile_loop_or_bridge(c, inputargs, operations)
         old, oldindex = faildescr._compiled_fail
         llimpl.compile_redirect_fail(old, oldindex, c)
 
-    def compile_loop(self, inputargs, operations, loopdescr):
+    def compile_loop(self, inputargs, operations, loopdescr, log=True):
         """In a real assembler backend, this should assemble the given
         list of operations.  Here we just generate a similar CompiledLoop
         instance.  The code here is RPython, whereas the code in llimpl
@@ -154,7 +154,7 @@
             llimpl.compile_add(c, op.getopnum())
             descr = op.getdescr()
             if isinstance(descr, Descr):
-                llimpl.compile_add_descr(c, descr.ofs, descr.typeinfo)
+                llimpl.compile_add_descr(c, descr.ofs, descr.typeinfo, descr.arg_types)
             if isinstance(descr, history.LoopToken) and op.getopnum() != rop.JUMP:
                 llimpl.compile_add_loop_token(c, descr)
             if self.is_oo and isinstance(descr, (OODescr, MethDescr)):
@@ -297,6 +297,18 @@
         return self.getdescr(0, token[0], extrainfo=extrainfo,
                              arg_types=''.join(arg_types))
 
+    def calldescrof_dynamic(self, ffi_args, ffi_result, extrainfo=None):
+        from pypy.jit.backend.llsupport.ffisupport import get_ffi_type_kind
+        arg_types = []
+        for arg in ffi_args:
+            kind = get_ffi_type_kind(arg)
+            if kind != history.VOID:
+                arg_types.append(kind)
+        reskind = get_ffi_type_kind(ffi_result)
+        return self.getdescr(0, reskind, extrainfo=extrainfo,
+                             arg_types=''.join(arg_types))
+
+
     def grab_exc_value(self):
         return llimpl.grab_exc_value()
 

Modified: pypy/branch/jit-unroll-loops/pypy/jit/backend/llsupport/descr.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/jit/backend/llsupport/descr.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/jit/backend/llsupport/descr.py	Sat Oct 30 16:41:17 2010
@@ -82,6 +82,7 @@
 
     _is_pointer_field = False   # unless overridden by GcPtrFieldDescr
     _is_float_field = False     # unless overridden by FloatFieldDescr
+    _is_field_signed = False    # unless overridden by XxxFieldDescr
 
     def is_pointer_field(self):
         return self._is_pointer_field
@@ -89,6 +90,9 @@
     def is_float_field(self):
         return self._is_float_field
 
+    def is_field_signed(self):
+        return self._is_field_signed
+
     def repr_of_descr(self):
         return '<%s %s %s>' % (self._clsname, self.name, self.offset)
 
@@ -105,7 +109,7 @@
 def getFieldDescrClass(TYPE):
     return getDescrClass(TYPE, BaseFieldDescr, GcPtrFieldDescr,
                          NonGcPtrFieldDescr, 'Field', 'get_field_size',
-                         '_is_float_field')
+                         '_is_float_field', '_is_field_signed')
 
 def get_field_descr(gccache, STRUCT, fieldname):
     cache = gccache._cache_field
@@ -144,6 +148,7 @@
 
     _is_array_of_pointers = False      # unless overridden by GcPtrArrayDescr
     _is_array_of_floats   = False      # unless overridden by FloatArrayDescr
+    _is_item_signed       = False      # unless overridden by XxxArrayDescr
 
     def is_array_of_pointers(self):
         return self._is_array_of_pointers
@@ -151,6 +156,9 @@
     def is_array_of_floats(self):
         return self._is_array_of_floats
 
+    def is_item_signed(self):
+        return self._is_item_signed
+
     def repr_of_descr(self):
         return '<%s>' % self._clsname
 
@@ -186,12 +194,12 @@
 def getArrayDescrClass(ARRAY):
     return getDescrClass(ARRAY.OF, BaseArrayDescr, GcPtrArrayDescr,
                          NonGcPtrArrayDescr, 'Array', 'get_item_size',
-                         '_is_array_of_floats')
+                         '_is_array_of_floats', '_is_item_signed')
 
 def getArrayNoLengthDescrClass(ARRAY):
     return getDescrClass(ARRAY.OF, BaseArrayNoLengthDescr, GcPtrArrayNoLengthDescr,
                          NonGcPtrArrayNoLengthDescr, 'ArrayNoLength', 'get_item_size',
-                         '_is_array_of_floats')
+                         '_is_array_of_floats', '_is_item_signed')
 
 def get_array_descr(gccache, ARRAY):
     cache = gccache._cache_array
@@ -242,6 +250,9 @@
     def get_result_size(self, translate_support_code):
         raise NotImplementedError
 
+    def is_result_signed(self):
+        return False    # unless overridden
+
     def create_call_stub(self, rtyper, RESULT):
         def process(c):
             arg = 'args_%s[%d]' % (c, seen[c])
@@ -307,6 +318,30 @@
     _return_type = history.INT
     call_stub = staticmethod(lambda func, args_i, args_r, args_f: 0)
 
+    _is_result_signed = False      # can be overridden in XxxCallDescr
+    def is_result_signed(self):
+        return self._is_result_signed
+
+class DynamicIntCallDescr(BaseIntCallDescr):
+    """
+    calldescr that works for every integer type, by explicitly passing it the
+    size of the result. Used only by get_call_descr_dynamic
+    """
+    _clsname = 'DynamicIntCallDescr'
+
+    def __init__(self, arg_classes, result_size, result_sign, extrainfo=None):
+        BaseIntCallDescr.__init__(self, arg_classes, extrainfo)
+        assert isinstance(result_sign, bool)
+        self._result_size = chr(result_size)
+        self._result_sign = result_sign
+
+    def get_result_size(self, translate_support_code):
+        return ord(self._result_size)
+
+    def is_result_signed(self):
+        return self._result_sign
+
+
 class NonGcPtrCallDescr(BaseIntCallDescr):
     _clsname = 'NonGcPtrCallDescr'
     def get_result_size(self, translate_support_code):
@@ -341,7 +376,8 @@
         return FloatCallDescr
     return getDescrClass(RESULT, BaseIntCallDescr, GcPtrCallDescr,
                          NonGcPtrCallDescr, 'Call', 'get_result_size',
-                         Ellipsis)  # <= floatattrname should not be used here
+                         Ellipsis,  # <= floatattrname should not be used here
+                         '_is_result_signed')
 
 def get_call_descr(gccache, ARGS, RESULT, extrainfo=None):
     arg_classes = []
@@ -368,7 +404,8 @@
 # ____________________________________________________________
 
 def getDescrClass(TYPE, BaseDescr, GcPtrDescr, NonGcPtrDescr,
-                  nameprefix, methodname, floatattrname, _cache={}):
+                  nameprefix, methodname, floatattrname, signedattrname,
+                  _cache={}):
     if isinstance(TYPE, lltype.Ptr):
         if TYPE.TO._gckind == 'gc':
             return GcPtrDescr
@@ -388,6 +425,8 @@
         #
         if TYPE is lltype.Float:
             setattr(Descr, floatattrname, True)
+        elif TYPE is not lltype.Bool and rffi.cast(TYPE, -1) == -1:
+            setattr(Descr, signedattrname, True)
         #
         _cache[nameprefix, TYPE] = Descr
         return Descr

Modified: pypy/branch/jit-unroll-loops/pypy/jit/backend/llsupport/gc.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/jit/backend/llsupport/gc.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/jit/backend/llsupport/gc.py	Sat Oct 30 16:41:17 2010
@@ -158,7 +158,7 @@
         # used to avoid too many duplications in the GCREF_LISTs.
         self.hashtable = lltype.malloc(self.HASHTABLE,
                                        self.HASHTABLE_SIZE+1,
-                                       flavor='raw')
+                                       flavor='raw', track_allocation=False)
         dummy = lltype.direct_ptradd(lltype.direct_arrayitems(self.hashtable),
                                      self.HASHTABLE_SIZE)
         dummy = llmemory.cast_ptr_to_adr(dummy)
@@ -252,14 +252,15 @@
 
     def _enlarge_gcmap(self):
         newlength = 250 + self._gcmap_maxlength * 2
-        newgcmap = lltype.malloc(self.GCMAP_ARRAY, newlength, flavor='raw')
+        newgcmap = lltype.malloc(self.GCMAP_ARRAY, newlength, flavor='raw',
+                                 track_allocation=False)
         oldgcmap = self._gcmap
         for i in range(self._gcmap_curlength):
             newgcmap[i] = oldgcmap[i]
         self._gcmap = newgcmap
         self._gcmap_maxlength = newlength
         if oldgcmap:
-            lltype.free(oldgcmap, flavor='raw')
+            lltype.free(oldgcmap, flavor='raw', track_allocation=False)
 
     def get_basic_shape(self, is_64_bit=False):
         # XXX: Should this code even really know about stack frame layout of
@@ -308,7 +309,8 @@
         # them inside bigger arrays) and we never try to share them.
         length = len(shape)
         compressed = lltype.malloc(self.CALLSHAPE_ARRAY, length,
-                                   flavor='raw')
+                                   flavor='raw',
+                                   track_allocation=False)   # memory leak
         for i in range(length):
             compressed[length-1-i] = rffi.cast(rffi.UCHAR, shape[i])
         return llmemory.cast_ptr_to_adr(compressed)
@@ -404,7 +406,7 @@
         self.GC_MALLOC_BASIC = lltype.Ptr(lltype.FuncType(
             [lltype.Signed, lltype.Signed], llmemory.GCREF))
         self.WB_FUNCPTR = lltype.Ptr(lltype.FuncType(
-            [llmemory.Address], lltype.Void))
+            [llmemory.Address, llmemory.Address], lltype.Void))
         self.write_barrier_descr = WriteBarrierDescr(self)
         #
         def malloc_array(itemsize, tid, num_elem):
@@ -550,7 +552,8 @@
             # the GC, and call it immediately
             llop1 = self.llop1
             funcptr = llop1.get_write_barrier_failing_case(self.WB_FUNCPTR)
-            funcptr(llmemory.cast_ptr_to_adr(gcref_struct))
+            funcptr(llmemory.cast_ptr_to_adr(gcref_struct),
+                    llmemory.cast_ptr_to_adr(gcref_newptr))
 
     def rewrite_assembler(self, cpu, operations):
         # Perform two kinds of rewrites in parallel:
@@ -589,7 +592,7 @@
                 v = op.getarg(1)
                 if isinstance(v, BoxPtr) or (isinstance(v, ConstPtr) and
                                              bool(v.value)): # store a non-NULL
-                    self._gen_write_barrier(newops, op.getarg(0))
+                    self._gen_write_barrier(newops, op.getarg(0), v)
                     op = op.copy_and_change(rop.SETFIELD_RAW)
             # ---------- write barrier for SETARRAYITEM_GC ----------
             if op.getopnum() == rop.SETARRAYITEM_GC:
@@ -598,15 +601,15 @@
                                              bool(v.value)): # store a non-NULL
                     # XXX detect when we should produce a
                     # write_barrier_from_array
-                    self._gen_write_barrier(newops, op.getarg(0))
+                    self._gen_write_barrier(newops, op.getarg(0), v)
                     op = op.copy_and_change(rop.SETARRAYITEM_RAW)
             # ----------
             newops.append(op)
         del operations[:]
         operations.extend(newops)
 
-    def _gen_write_barrier(self, newops, v_base):
-        args = [v_base]
+    def _gen_write_barrier(self, newops, v_base, v_value):
+        args = [v_base, v_value]
         newops.append(ResOperation(rop.COND_CALL_GC_WB, args, None,
                                    descr=self.write_barrier_descr))
 

Modified: pypy/branch/jit-unroll-loops/pypy/jit/backend/llsupport/llmodel.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/jit/backend/llsupport/llmodel.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/jit/backend/llsupport/llmodel.py	Sat Oct 30 16:41:17 2010
@@ -17,6 +17,7 @@
 from pypy.jit.backend.llsupport.descr import get_call_descr
 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.rpython.annlowlevel import cast_instance_to_base_ptr
 
 
@@ -82,7 +83,8 @@
         # read back by the machine code reading at the address given by
         # pos_exception() and pos_exc_value().
         _exception_emulator = lltype.malloc(rffi.CArray(lltype.Signed), 2,
-                                            zero=True, flavor='raw')
+                                            zero=True, flavor='raw',
+                                            immortal=True)
         self._exception_emulator = _exception_emulator
 
         def _store_exception(lle):
@@ -210,7 +212,8 @@
         assert isinstance(fielddescr, BaseFieldDescr)
         ofs = fielddescr.offset
         size = fielddescr.get_field_size(self.translate_support_code)
-        return ofs, size
+        sign = fielddescr.is_field_signed()
+        return ofs, size, sign
     unpack_fielddescr_size._always_inline_ = True
 
     def arraydescrof(self, A):
@@ -225,12 +228,16 @@
         assert isinstance(arraydescr, BaseArrayDescr)
         ofs = arraydescr.get_base_size(self.translate_support_code)
         size = arraydescr.get_item_size(self.translate_support_code)
-        return ofs, size
+        sign = arraydescr.is_item_signed()
+        return ofs, size, sign
     unpack_arraydescr_size._always_inline_ = True
 
     def calldescrof(self, FUNC, ARGS, RESULT, extrainfo=None):
         return get_call_descr(self.gc_ll_descr, ARGS, RESULT, extrainfo)
 
+    def calldescrof_dynamic(self, ffi_args, ffi_result, extrainfo=None):
+        return get_call_descr_dynamic(ffi_args, ffi_result, extrainfo)
+
     def get_overflow_error(self):
         ovf_vtable = self.cast_adr_to_int(self._ovf_error_vtable)
         ovf_inst = lltype.cast_opaque_ptr(llmemory.GCREF,
@@ -252,15 +259,21 @@
 
     @specialize.argtype(2)
     def bh_getarrayitem_gc_i(self, arraydescr, gcref, itemindex):
-        ofs, size = self.unpack_arraydescr_size(arraydescr)
+        ofs, size, sign = self.unpack_arraydescr_size(arraydescr)
         # --- start of GC unsafe code (no GC operation!) ---
         items = rffi.ptradd(rffi.cast(rffi.CCHARP, gcref), ofs)
-        for TYPE, itemsize in unroll_basic_sizes:
+        for STYPE, UTYPE, itemsize in unroll_basic_sizes:
             if size == itemsize:
-                items = rffi.cast(rffi.CArrayPtr(TYPE), items) 
-                val = items[itemindex]
+                if sign:
+                    items = rffi.cast(rffi.CArrayPtr(STYPE), items)
+                    val = items[itemindex]
+                    val = rffi.cast(lltype.Signed, val)
+                else:
+                    items = rffi.cast(rffi.CArrayPtr(UTYPE), items)
+                    val = items[itemindex]
+                    val = rffi.cast(lltype.Signed, val)
                 # --- end of GC unsafe code ---
-                return rffi.cast(lltype.Signed, val)
+                return val
         else:
             raise NotImplementedError("size = %d" % size)
 
@@ -285,10 +298,10 @@
 
     @specialize.argtype(2)
     def bh_setarrayitem_gc_i(self, arraydescr, gcref, itemindex, newvalue):
-        ofs, size = self.unpack_arraydescr_size(arraydescr)
+        ofs, size, sign = self.unpack_arraydescr_size(arraydescr)
         # --- start of GC unsafe code (no GC operation!) ---
         items = rffi.ptradd(rffi.cast(rffi.CCHARP, gcref), ofs)
-        for TYPE, itemsize in unroll_basic_sizes:
+        for TYPE, _, itemsize in unroll_basic_sizes:
             if size == itemsize:
                 items = rffi.cast(rffi.CArrayPtr(TYPE), items)
                 items[itemindex] = rffi.cast(TYPE, newvalue)
@@ -339,14 +352,22 @@
 
     @specialize.argtype(1)
     def _base_do_getfield_i(self, struct, fielddescr):
-        ofs, size = self.unpack_fielddescr_size(fielddescr)
+        ofs, size, sign = self.unpack_fielddescr_size(fielddescr)
         # --- start of GC unsafe code (no GC operation!) ---
         fieldptr = rffi.ptradd(rffi.cast(rffi.CCHARP, struct), ofs)
-        for TYPE, itemsize in unroll_basic_sizes:
+        for STYPE, UTYPE, itemsize in unroll_basic_sizes:
             if size == itemsize:
-                val = rffi.cast(rffi.CArrayPtr(TYPE), fieldptr)[0]
+                # Note that in the common case where size==sizeof(Signed),
+                # both cases of what follows are doing the same thing.
+                # But gcc is clever enough to figure this out :-)
+                if sign:
+                    val = rffi.cast(rffi.CArrayPtr(STYPE), fieldptr)[0]
+                    val = rffi.cast(lltype.Signed, val)
+                else:
+                    val = rffi.cast(rffi.CArrayPtr(UTYPE), fieldptr)[0]
+                    val = rffi.cast(lltype.Signed, val)
                 # --- end of GC unsafe code ---
-                return rffi.cast(lltype.Signed, val)
+                return val
         else:
             raise NotImplementedError("size = %d" % size)
 
@@ -378,10 +399,10 @@
 
     @specialize.argtype(1)
     def _base_do_setfield_i(self, struct, fielddescr, newvalue):
-        ofs, size = self.unpack_fielddescr_size(fielddescr)
+        ofs, size, sign = self.unpack_fielddescr_size(fielddescr)
         # --- start of GC unsafe code (no GC operation!) ---
         fieldptr = rffi.ptradd(rffi.cast(rffi.CCHARP, struct), ofs)
-        for TYPE, itemsize in unroll_basic_sizes:
+        for TYPE, _, itemsize in unroll_basic_sizes:
             if size == itemsize:
                 fieldptr = rffi.cast(rffi.CArrayPtr(TYPE), fieldptr)
                 fieldptr[0] = rffi.cast(TYPE, newvalue)

Modified: pypy/branch/jit-unroll-loops/pypy/jit/backend/llsupport/symbolic.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/jit/backend/llsupport/symbolic.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/jit/backend/llsupport/symbolic.py	Sat Oct 30 16:41:17 2010
@@ -69,8 +69,9 @@
 SIZEOF_INT   = get_size(rffi.INT, False)
 SIZEOF_FLOAT = get_size(lltype.Float, False)
 
-unroll_basic_sizes = unrolling_iterable([(lltype.Signed, WORD),
-                                         (lltype.Char,   SIZEOF_CHAR),
-                                         (rffi.SHORT,    SIZEOF_SHORT),
-                                         (rffi.INT,      SIZEOF_INT)])
+unroll_basic_sizes = unrolling_iterable([
+    (lltype.Signed,   lltype.Unsigned, WORD),
+    (rffi.SIGNEDCHAR, lltype.Char,     SIZEOF_CHAR),
+    (rffi.SHORT,      rffi.USHORT,     SIZEOF_SHORT),
+    (rffi.INT,        rffi.UINT,       SIZEOF_INT)])
 # does not contain Float ^^^ which must be special-cased

Modified: pypy/branch/jit-unroll-loops/pypy/jit/backend/llsupport/test/test_descr.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/jit/backend/llsupport/test/test_descr.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/jit/backend/llsupport/test/test_descr.py	Sat Oct 30 16:41:17 2010
@@ -83,6 +83,18 @@
         assert     descr_f.is_float_field()
 
 
+def test_get_field_descr_sign():
+    for RESTYPE, signed in [(rffi.SIGNEDCHAR, True), (rffi.UCHAR,  False),
+                            (rffi.SHORT,      True), (rffi.USHORT, False),
+                            (rffi.INT,        True), (rffi.UINT,   False),
+                            (rffi.LONG,       True), (rffi.ULONG,  False)]:
+        S = lltype.GcStruct('S', ('x', RESTYPE))
+        for tsc in [False, True]:
+            c2 = GcCache(tsc)
+            descr_x = get_field_descr(c2, S, 'x')
+            assert descr_x.is_field_signed() == signed
+
+
 def test_get_array_descr():
     U = lltype.Struct('U')
     T = lltype.GcStruct('T')
@@ -164,6 +176,25 @@
     assert descr.get_base_size(False) == 0
     assert descr.get_ofs_length(False) == -1
 
+
+def test_get_array_descr_sign():
+    for RESTYPE, signed in [(rffi.SIGNEDCHAR, True), (rffi.UCHAR,  False),
+                            (rffi.SHORT,      True), (rffi.USHORT, False),
+                            (rffi.INT,        True), (rffi.UINT,   False),
+                            (rffi.LONG,       True), (rffi.ULONG,  False)]:
+        A = lltype.GcArray(RESTYPE)
+        for tsc in [False, True]:
+            c2 = GcCache(tsc)
+            arraydescr = get_array_descr(c2, A)
+            assert arraydescr.is_item_signed() == signed
+        #
+        RA = rffi.CArray(RESTYPE)
+        for tsc in [False, True]:
+            c2 = GcCache(tsc)
+            arraydescr = get_array_descr(c2, RA)
+            assert arraydescr.is_item_signed() == signed
+
+
 def test_get_call_descr_not_translated():
     c0 = GcCache(False)
     descr1 = get_call_descr(c0, [lltype.Char, lltype.Signed], lltype.Char)
@@ -219,6 +250,17 @@
     extrainfo = descr3.get_extra_info()
     assert extrainfo is None
 
+def test_get_call_descr_sign():
+    for RESTYPE, signed in [(rffi.SIGNEDCHAR, True), (rffi.UCHAR,  False),
+                            (rffi.SHORT,      True), (rffi.USHORT, False),
+                            (rffi.INT,        True), (rffi.UINT,   False),
+                            (rffi.LONG,       True), (rffi.ULONG,  False)]:
+        A = lltype.GcArray(RESTYPE)
+        for tsc in [False, True]:
+            c2 = GcCache(tsc)
+            descr1 = get_call_descr(c2, [], RESTYPE)
+            assert descr1.is_result_signed() == signed
+
 
 def test_repr_of_descr():
     c0 = GcCache(False)

Modified: pypy/branch/jit-unroll-loops/pypy/jit/backend/llsupport/test/test_gc.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/jit/backend/llsupport/test/test_gc.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/jit/backend/llsupport/test/test_gc.py	Sat Oct 30 16:41:17 2010
@@ -141,8 +141,8 @@
                             repr(offset_to_length), p))
         return p
 
-    def _write_barrier_failing_case(self, adr_struct):
-        self.record.append(('barrier', adr_struct))
+    def _write_barrier_failing_case(self, adr_struct, adr_newptr):
+        self.record.append(('barrier', adr_struct, adr_newptr))
 
     def get_write_barrier_failing_case(self, FPTRTYPE):
         return llhelper(FPTRTYPE, self._write_barrier_failing_case)
@@ -239,6 +239,7 @@
         s_gcref = lltype.cast_opaque_ptr(llmemory.GCREF, s)
         r_gcref = lltype.cast_opaque_ptr(llmemory.GCREF, r)
         s_adr = llmemory.cast_ptr_to_adr(s)
+        r_adr = llmemory.cast_ptr_to_adr(r)
         #
         s_hdr.tid &= ~gc_ll_descr.GCClass.JIT_WB_IF_FLAG
         gc_ll_descr.do_write_barrier(s_gcref, r_gcref)
@@ -246,7 +247,7 @@
         #
         s_hdr.tid |= gc_ll_descr.GCClass.JIT_WB_IF_FLAG
         gc_ll_descr.do_write_barrier(s_gcref, r_gcref)
-        assert self.llop1.record == [('barrier', s_adr)]
+        assert self.llop1.record == [('barrier', s_adr, r_adr)]
 
     def test_gen_write_barrier(self):
         gc_ll_descr = self.gc_ll_descr
@@ -254,11 +255,13 @@
         #
         newops = []
         v_base = BoxPtr()
-        gc_ll_descr._gen_write_barrier(newops, v_base)
+        v_value = BoxPtr()
+        gc_ll_descr._gen_write_barrier(newops, v_base, v_value)
         assert llop1.record == []
         assert len(newops) == 1
         assert newops[0].getopnum() == rop.COND_CALL_GC_WB
         assert newops[0].getarg(0) == v_base
+        assert newops[0].getarg(1) == v_value
         assert newops[0].result is None
         wbdescr = newops[0].getdescr()
         assert isinstance(wbdescr.jit_wb_if_flag, int)
@@ -358,6 +361,7 @@
         #
         assert operations[0].getopnum() == rop.COND_CALL_GC_WB
         assert operations[0].getarg(0) == v_base
+        assert operations[0].getarg(1) == v_value
         assert operations[0].result is None
         #
         assert operations[1].getopnum() == rop.SETFIELD_RAW
@@ -381,6 +385,7 @@
         #
         assert operations[0].getopnum() == rop.COND_CALL_GC_WB
         assert operations[0].getarg(0) == v_base
+        assert operations[0].getarg(1) == v_value
         assert operations[0].result is None
         #
         assert operations[1].getopnum() == rop.SETARRAYITEM_RAW

Modified: pypy/branch/jit-unroll-loops/pypy/jit/backend/model.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/jit/backend/model.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/jit/backend/model.py	Sat Oct 30 16:41:17 2010
@@ -33,14 +33,14 @@
         pass
 
 
-    def compile_loop(self, inputargs, operations, looptoken):
+    def compile_loop(self, inputargs, operations, looptoken, log=True):
         """Assemble the given loop.
         Extra attributes should be put in the LoopToken to
         point to the compiled loop in assembler.
         """
         raise NotImplementedError
 
-    def compile_bridge(self, faildescr, inputargs, operations):
+    def compile_bridge(self, faildescr, inputargs, operations, log=True):
         """Assemble the bridge.
         The FailDescr is the descr of the original guard that failed.
         """

Modified: pypy/branch/jit-unroll-loops/pypy/jit/backend/test/runner_test.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/jit/backend/test/runner_test.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/jit/backend/test/runner_test.py	Sat Oct 30 16:41:17 2010
@@ -9,12 +9,13 @@
                                          ConstObj, BoxFloat, ConstFloat)
 from pypy.jit.metainterp.resoperation import ResOperation, rop
 from pypy.jit.metainterp.typesystem import deref
-from pypy.jit.metainterp.test.oparser import parse
+from pypy.jit.tool.oparser import parse
 from pypy.rpython.lltypesystem import lltype, llmemory, rstr, rffi, rclass
 from pypy.rpython.ootypesystem import ootype
 from pypy.rpython.annlowlevel import llhelper
 from pypy.rpython.llinterp import LLException
 from pypy.jit.codewriter import heaptracker
+from pypy.rlib.rarithmetic import intmask
 
 
 class Runner(object):
@@ -421,6 +422,7 @@
             assert x == 3.5 - 42
 
     def test_call(self):
+        from pypy.rlib.libffi import types
 
         def func_int(a, b):
             return a + b
@@ -428,23 +430,31 @@
             return chr(ord(c) + ord(c1))
 
         functions = [
-            (func_int, lltype.Signed, 655360),
-            (func_int, rffi.SHORT, 1213),
-            (func_char, lltype.Char, 12)
+            (func_int, lltype.Signed, types.sint, 655360),
+            (func_int, rffi.SHORT, types.sint16, 1213),
+            (func_char, lltype.Char, types.uchar, 12)
             ]
 
-        for func, TP, num in functions:
+        for func, TP, ffi_type, num in functions:
             cpu = self.cpu
             #
             FPTR = self.Ptr(self.FuncType([TP, TP], TP))
             func_ptr = llhelper(FPTR, func)
             FUNC = deref(FPTR)
-            calldescr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT)
             funcbox = self.get_funcbox(cpu, func_ptr)
+            # first, try it with the "normal" calldescr
+            calldescr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT)
             res = self.execute_operation(rop.CALL,
                                          [funcbox, BoxInt(num), BoxInt(num)],
                                          'int', descr=calldescr)
             assert res.value == 2 * num
+            # then, try it with the dynamic calldescr
+            dyn_calldescr = cpu.calldescrof_dynamic([ffi_type, ffi_type], ffi_type)
+            res = self.execute_operation(rop.CALL,
+                                         [funcbox, BoxInt(num), BoxInt(num)],
+                                         'int', descr=dyn_calldescr)
+            assert res.value == 2 * num
+            
 
         if cpu.supports_floats:
             def func(f0, f1, f2, f3, f4, f5, f6, i0, i1, f7, f8, f9):
@@ -507,6 +517,24 @@
                                          'int', descr=calldescr)
             assert res.value == func_ints(*args)
 
+    def test_call_to_c_function(self):
+        from pypy.rlib.libffi import CDLL, types, ArgChain
+        from pypy.rpython.lltypesystem.ll2ctypes import libc_name
+        libc = CDLL(libc_name)
+        c_tolower = libc.getpointer('tolower', [types.uchar], types.sint)
+        argchain = ArgChain().arg(ord('A'))
+        assert c_tolower.call(argchain, rffi.INT) == ord('a')
+
+        func_adr = llmemory.cast_ptr_to_adr(c_tolower.funcsym)
+        funcbox = ConstInt(heaptracker.adr2int(func_adr))
+        calldescr = self.cpu.calldescrof_dynamic([types.uchar], types.sint)
+        res = self.execute_operation(rop.CALL,
+                                     [funcbox, BoxInt(ord('A'))],
+                                     'int',
+                                     descr=calldescr)
+        assert res.value == ord('a')
+
+
     def test_field_basic(self):
         t_box, T_box = self.alloc_instance(self.T)
         fielddescr = self.cpu.fielddescrof(self.S, 'value')
@@ -833,6 +861,23 @@
                                                         length_box], 'void')
                                 assert self.look_string(r_box) == "!??cdef?!"
 
+    def test_copyunicodecontent(self):
+        s_box = self.alloc_unicode(u"abcdef")
+        for s_box in [s_box, s_box.constbox()]:
+            for srcstart_box in [BoxInt(2), ConstInt(2)]:
+                for dststart_box in [BoxInt(3), ConstInt(3)]:
+                    for length_box in [BoxInt(4), ConstInt(4)]:
+                        for r_box_is_const in [False, True]:
+                            r_box = self.alloc_unicode(u"!???????!")
+                            if r_box_is_const:
+                                r_box = r_box.constbox()
+                                self.execute_operation(rop.COPYUNICODECONTENT,
+                                                       [s_box, r_box,
+                                                        srcstart_box,
+                                                        dststart_box,
+                                                        length_box], 'void')
+                                assert self.look_unicode(r_box) == u"!??cdef?!"
+
     def test_do_unicode_basic(self):
         u = self.cpu.bh_newunicode(5)
         self.cpu.bh_unicodesetitem(u, 4, 123)
@@ -1227,6 +1272,10 @@
         u_box = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, u))
         return u_box
 
+    def look_unicode(self, unicode_box):
+        u = unicode_box.getref(lltype.Ptr(rstr.UNICODE))
+        return u''.join(u.chars)
+
 
     def test_casts(self):
         py.test.skip("xxx fix or kill")
@@ -1283,6 +1332,7 @@
                                    descr=fd)
             res = self.execute_operation(get_op, [s_box], 'int', descr=fd)
             assert res.getint()  == 32
+        lltype.free(s, flavor='raw')
 
     def test_new_with_vtable(self):
         cpu = self.cpu
@@ -1427,12 +1477,12 @@
         assert not excvalue
 
     def test_cond_call_gc_wb(self):
-        def func_void(a):
-            record.append(a)
+        def func_void(a, b):
+            record.append((a, b))
         record = []
         #
         S = lltype.GcStruct('S', ('tid', lltype.Signed))
-        FUNC = self.FuncType([lltype.Ptr(S)], lltype.Void)
+        FUNC = self.FuncType([lltype.Ptr(S), lltype.Signed], lltype.Void)
         func_ptr = llhelper(lltype.Ptr(FUNC), func_void)
         funcbox = self.get_funcbox(self.cpu, func_ptr)
         class WriteBarrierDescr(AbstractDescr):
@@ -1453,10 +1503,10 @@
             sgcref = lltype.cast_opaque_ptr(llmemory.GCREF, s)
             del record[:]
             self.execute_operation(rop.COND_CALL_GC_WB,
-                                   [BoxPtr(sgcref)],
+                                   [BoxPtr(sgcref), ConstInt(-2121)],
                                    'void', descr=WriteBarrierDescr())
             if cond:
-                assert record == [s]
+                assert record == [(s, -2121)]
             else:
                 assert record == []
 
@@ -1980,6 +2030,196 @@
         assert self.cpu.get_latest_value_float(0) == 13.5
         assert called
 
+    def test_short_result_of_getfield_direct(self):
+        # Test that a getfield that returns a CHAR, SHORT or INT, signed
+        # or unsigned, properly gets zero-extended or sign-extended.
+        # Direct bh_xxx test.
+        cpu = self.cpu
+        for RESTYPE in [rffi.SIGNEDCHAR, rffi.UCHAR,
+                        rffi.SHORT, rffi.USHORT,
+                        rffi.INT, rffi.UINT,
+                        rffi.LONG, rffi.ULONG]:
+            S = lltype.GcStruct('S', ('x', RESTYPE))
+            descrfld_x = cpu.fielddescrof(S, 'x')
+            s = lltype.malloc(S)
+            value = intmask(0xFFEEDDCCBBAA9988)
+            expected = rffi.cast(lltype.Signed, rffi.cast(RESTYPE, value))
+            s.x = rffi.cast(RESTYPE, value)
+            x = cpu.bh_getfield_gc_i(lltype.cast_opaque_ptr(llmemory.GCREF, s),
+                                     descrfld_x)
+            assert x == expected, (
+                "%r: got %r, expected %r" % (RESTYPE, x, expected))
+
+    def test_short_result_of_getfield_compiled(self):
+        # Test that a getfield that returns a CHAR, SHORT or INT, signed
+        # or unsigned, properly gets zero-extended or sign-extended.
+        # Machine code compilation test.
+        cpu = self.cpu
+        for RESTYPE in [rffi.SIGNEDCHAR, rffi.UCHAR,
+                        rffi.SHORT, rffi.USHORT,
+                        rffi.INT, rffi.UINT,
+                        rffi.LONG, rffi.ULONG]:
+            S = lltype.GcStruct('S', ('x', RESTYPE))
+            descrfld_x = cpu.fielddescrof(S, 'x')
+            s = lltype.malloc(S)
+            value = intmask(0xFFEEDDCCBBAA9988)
+            expected = rffi.cast(lltype.Signed, rffi.cast(RESTYPE, value))
+            s.x = rffi.cast(RESTYPE, value)
+            s_gcref = lltype.cast_opaque_ptr(llmemory.GCREF, s)
+            res = self.execute_operation(rop.GETFIELD_GC, [BoxPtr(s_gcref)],
+                                         'int', descr=descrfld_x)
+            assert res.value == expected, (
+                "%r: got %r, expected %r" % (RESTYPE, res.value, expected))
+
+    def test_short_result_of_getarrayitem_direct(self):
+        # Test that a getarrayitem that returns a CHAR, SHORT or INT, signed
+        # or unsigned, properly gets zero-extended or sign-extended.
+        # Direct bh_xxx test.
+        cpu = self.cpu
+        for RESTYPE in [rffi.SIGNEDCHAR, rffi.UCHAR,
+                        rffi.SHORT, rffi.USHORT,
+                        rffi.INT, rffi.UINT,
+                        rffi.LONG, rffi.ULONG]:
+            A = lltype.GcArray(RESTYPE)
+            descrarray = cpu.arraydescrof(A)
+            a = lltype.malloc(A, 5)
+            value = intmask(0xFFEEDDCCBBAA9988)
+            expected = rffi.cast(lltype.Signed, rffi.cast(RESTYPE, value))
+            a[3] = rffi.cast(RESTYPE, value)
+            x = cpu.bh_getarrayitem_gc_i(
+                descrarray, lltype.cast_opaque_ptr(llmemory.GCREF, a), 3)
+            assert x == expected, (
+                "%r: got %r, expected %r" % (RESTYPE, x, expected))
+
+    def test_short_result_of_getarrayitem_compiled(self):
+        # Test that a getarrayitem that returns a CHAR, SHORT or INT, signed
+        # or unsigned, properly gets zero-extended or sign-extended.
+        # Machine code compilation test.
+        cpu = self.cpu
+        for RESTYPE in [rffi.SIGNEDCHAR, rffi.UCHAR,
+                        rffi.SHORT, rffi.USHORT,
+                        rffi.INT, rffi.UINT,
+                        rffi.LONG, rffi.ULONG]:
+            A = lltype.GcArray(RESTYPE)
+            descrarray = cpu.arraydescrof(A)
+            a = lltype.malloc(A, 5)
+            value = intmask(0xFFEEDDCCBBAA9988)
+            expected = rffi.cast(lltype.Signed, rffi.cast(RESTYPE, value))
+            a[3] = rffi.cast(RESTYPE, value)
+            a_gcref = lltype.cast_opaque_ptr(llmemory.GCREF, a)
+            res = self.execute_operation(rop.GETARRAYITEM_GC,
+                                         [BoxPtr(a_gcref), BoxInt(3)],
+                                         'int', descr=descrarray)
+            assert res.value == expected, (
+                "%r: got %r, expected %r" % (RESTYPE, res.value, expected))
+
+    def test_short_result_of_getarrayitem_raw_direct(self):
+        # Test that a getarrayitem that returns a CHAR, SHORT or INT, signed
+        # or unsigned, properly gets zero-extended or sign-extended.
+        # Direct bh_xxx test.
+        cpu = self.cpu
+        for RESTYPE in [rffi.SIGNEDCHAR, rffi.UCHAR,
+                        rffi.SHORT, rffi.USHORT,
+                        rffi.INT, rffi.UINT,
+                        rffi.LONG, rffi.ULONG]:
+            A = rffi.CArray(RESTYPE)
+            descrarray = cpu.arraydescrof(A)
+            a = lltype.malloc(A, 5, flavor='raw')
+            value = intmask(0xFFEEDDCCBBAA9988)
+            expected = rffi.cast(lltype.Signed, rffi.cast(RESTYPE, value))
+            a[3] = rffi.cast(RESTYPE, value)
+            a_rawint = heaptracker.adr2int(llmemory.cast_ptr_to_adr(a))
+            x = cpu.bh_getarrayitem_raw_i(descrarray, a_rawint, 3)
+            assert x == expected, (
+                "%r: got %r, expected %r" % (RESTYPE, x, expected))
+            lltype.free(a, flavor='raw')
+
+    def test_short_result_of_getarrayitem_raw_compiled(self):
+        # Test that a getarrayitem that returns a CHAR, SHORT or INT, signed
+        # or unsigned, properly gets zero-extended or sign-extended.
+        # Machine code compilation test.
+        cpu = self.cpu
+        for RESTYPE in [rffi.SIGNEDCHAR, rffi.UCHAR,
+                        rffi.SHORT, rffi.USHORT,
+                        rffi.INT, rffi.UINT,
+                        rffi.LONG, rffi.ULONG]:
+            A = rffi.CArray(RESTYPE)
+            descrarray = cpu.arraydescrof(A)
+            a = lltype.malloc(A, 5, flavor='raw')
+            value = intmask(0xFFEEDDCCBBAA9988)
+            expected = rffi.cast(lltype.Signed, rffi.cast(RESTYPE, value))
+            a[3] = rffi.cast(RESTYPE, value)
+            a_rawint = heaptracker.adr2int(llmemory.cast_ptr_to_adr(a))
+            res = self.execute_operation(rop.GETARRAYITEM_RAW,
+                                         [BoxInt(a_rawint), BoxInt(3)],
+                                         'int', descr=descrarray)
+            assert res.value == expected, (
+                "%r: got %r, expected %r" % (RESTYPE, res.value, expected))
+            lltype.free(a, flavor='raw')
+
+    def test_short_result_of_call_direct(self):
+        # Test that calling a function that returns a CHAR, SHORT or INT,
+        # signed or unsigned, properly gets zero-extended or sign-extended.
+        from pypy.translator.tool.cbuild import ExternalCompilationInfo
+        for RESTYPE in [rffi.SIGNEDCHAR, rffi.UCHAR,
+                        rffi.SHORT, rffi.USHORT,
+                        rffi.INT, rffi.UINT,
+                        rffi.LONG, rffi.ULONG]:
+            # Tested with a function that intentionally does not cast the
+            # result to RESTYPE, but makes sure that we return the whole
+            # value in eax or rax.
+            eci = ExternalCompilationInfo(separate_module_sources=["""
+                long fn_test_result_of_call(long x)
+                {
+                    return x + 1;
+                }
+            """])
+            f = rffi.llexternal('fn_test_result_of_call', [lltype.Signed],
+                                RESTYPE, compilation_info=eci, _nowrapper=True)
+            value = intmask(0xFFEEDDCCBBAA9988)
+            expected = rffi.cast(lltype.Signed, rffi.cast(RESTYPE, value + 1))
+            assert intmask(f(value)) == expected
+            #
+            FUNC = self.FuncType([lltype.Signed], RESTYPE)
+            FPTR = self.Ptr(FUNC)
+            calldescr = self.cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT)
+            x = self.cpu.bh_call_i(self.get_funcbox(self.cpu, f).value,
+                                   calldescr, [value], None, None)
+            assert x == expected, (
+                "%r: got %r, expected %r" % (RESTYPE, x, expected))
+
+    def test_short_result_of_call_compiled(self):
+        # Test that calling a function that returns a CHAR, SHORT or INT,
+        # signed or unsigned, properly gets zero-extended or sign-extended.
+        from pypy.translator.tool.cbuild import ExternalCompilationInfo
+        for RESTYPE in [rffi.SIGNEDCHAR, rffi.UCHAR,
+                        rffi.SHORT, rffi.USHORT,
+                        rffi.INT, rffi.UINT,
+                        rffi.LONG, rffi.ULONG]:
+            # Tested with a function that intentionally does not cast the
+            # result to RESTYPE, but makes sure that we return the whole
+            # value in eax or rax.
+            eci = ExternalCompilationInfo(separate_module_sources=["""
+                long fn_test_result_of_call(long x)
+                {
+                    return x + 1;
+                }
+            """])
+            f = rffi.llexternal('fn_test_result_of_call', [lltype.Signed],
+                                RESTYPE, compilation_info=eci, _nowrapper=True)
+            value = intmask(0xFFEEDDCCBBAA9988)
+            expected = rffi.cast(lltype.Signed, rffi.cast(RESTYPE, value + 1))
+            assert intmask(f(value)) == expected
+            #
+            FUNC = self.FuncType([lltype.Signed], RESTYPE)
+            FPTR = self.Ptr(FUNC)
+            calldescr = self.cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT)
+            funcbox = self.get_funcbox(self.cpu, f)
+            res = self.execute_operation(rop.CALL, [funcbox, BoxInt(value)],
+                                         'int', descr=calldescr)
+            assert res.value == expected, (
+                "%r: got %r, expected %r" % (RESTYPE, res.value, expected))
+
 
 class OOtypeBackendTest(BaseBackendTest):
 

Modified: pypy/branch/jit-unroll-loops/pypy/jit/backend/test/test_ll_random.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/jit/backend/test/test_ll_random.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/jit/backend/test/test_ll_random.py	Sat Oct 30 16:41:17 2010
@@ -386,6 +386,20 @@
         v_string = self.get_string(builder, r)
         builder.do(self.opnum, [v_string])
 
+class AbstractCopyContentOperation(AbstractStringOperation):
+    def produce_into(self, builder, r):
+        v_srcstring = self.get_string(builder, r)
+        v_dststring = self.get_string(builder, r)
+        if v_srcstring.value == v_dststring.value:    # because it's not a
+            raise test_random.CannotProduceOperation  # memmove(), but memcpy()
+        srclen = len(v_srcstring.getref(self.ptr).chars)
+        dstlen = len(v_dststring.getref(self.ptr).chars)
+        v_length = builder.get_index(min(srclen, dstlen), r)
+        v_srcstart = builder.get_index(srclen - v_length.value + 1, r)
+        v_dststart = builder.get_index(dstlen - v_length.value + 1, r)
+        builder.do(self.opnum, [v_srcstring, v_dststring,
+                                v_srcstart, v_dststart, v_length])
+
 class StrGetItemOperation(AbstractGetItemOperation, _StrOperation):
     pass
 
@@ -404,6 +418,13 @@
 class UnicodeLenOperation(AbstractStringLenOperation, _UnicodeOperation):
     pass
 
+class CopyStrContentOperation(AbstractCopyContentOperation, _StrOperation):
+    pass
+
+class CopyUnicodeContentOperation(AbstractCopyContentOperation,
+                                  _UnicodeOperation):
+    pass
+
 
 # there are five options in total:
 # 1. non raising call and guard_no_exception
@@ -577,6 +598,8 @@
     OPERATIONS.append(UnicodeSetItemOperation(rop.UNICODESETITEM))
     OPERATIONS.append(StrLenOperation(rop.STRLEN))
     OPERATIONS.append(UnicodeLenOperation(rop.UNICODELEN))
+    OPERATIONS.append(CopyStrContentOperation(rop.COPYSTRCONTENT))
+    OPERATIONS.append(CopyUnicodeContentOperation(rop.COPYUNICODECONTENT))
 
 for i in range(2):
     OPERATIONS.append(GuardClassOperation(rop.GUARD_CLASS))

Modified: pypy/branch/jit-unroll-loops/pypy/jit/backend/test/test_random.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/jit/backend/test/test_random.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/jit/backend/test/test_random.py	Sat Oct 30 16:41:17 2010
@@ -1,7 +1,7 @@
 import py, sys
 from pypy.rlib.rarithmetic import intmask, LONG_BIT
 from pypy.rpython.lltypesystem import llmemory
-from pypy.jit.backend.test import conftest as demo_conftest
+from pypy.jit.backend import conftest as demo_conftest
 from pypy.jit.metainterp.history import BasicFailDescr, TreeLoop
 from pypy.jit.metainterp.history import BoxInt, ConstInt, LoopToken
 from pypy.jit.metainterp.history import BoxPtr, ConstPtr
@@ -102,7 +102,7 @@
             elif isinstance(v, ConstFloat):
                 args.append('ConstFloat(%r)' % v.value)
             elif isinstance(v, ConstInt):
-                args.append('ConstInt(%d)' % v.value)
+                args.append('ConstInt(%s)' % v.value)
             else:
                 raise NotImplementedError(v)
         if op.getdescr() is None:
@@ -113,7 +113,7 @@
             except AttributeError:
                 descrstr = ', descr=...'
         print >>s, '        ResOperation(rop.%s, [%s], %s%s),' % (
-            opname[op.opnum], ', '.join(args), names[op.result], descrstr)
+            opname[op.getopnum()], ', '.join(args), names[op.result], descrstr)
         #if getattr(op, 'suboperations', None) is not None:
         #    subops.append(op)
 
@@ -189,7 +189,7 @@
                                                                        v.value)
         print >>s, '    op = cpu.execute_token(looptoken)'
         if self.should_fail_by is None:
-            fail_args = self.loop.operations[-1].args
+            fail_args = self.loop.operations[-1].getarglist()
         else:
             fail_args = self.should_fail_by.getfailargs()
         for i, v in enumerate(fail_args):

Modified: pypy/branch/jit-unroll-loops/pypy/jit/backend/x86/assembler.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/jit/backend/x86/assembler.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/jit/backend/x86/assembler.py	Sat Oct 30 16:41:17 2010
@@ -8,7 +8,8 @@
 from pypy.rpython.annlowlevel import llhelper
 from pypy.tool.uid import fixid
 from pypy.jit.backend.x86.regalloc import (RegAlloc, X86RegisterManager,
-                                           X86XMMRegisterManager, get_ebp_ofs)
+                                           X86XMMRegisterManager, get_ebp_ofs,
+                                           _get_scale)
 
 from pypy.jit.backend.x86.arch import (FRAME_FIXED_SIZE, FORCE_INDEX_OFS, WORD,
                                        IS_X86_32, IS_X86_64)
@@ -22,7 +23,8 @@
                                          X86_64_SCRATCH_REG,
                                          X86_64_XMM_SCRATCH_REG,
                                          RegLoc, StackLoc, ConstFloatLoc,
-                                         ImmedLoc, AddressLoc, imm)
+                                         ImmedLoc, AddressLoc, imm,
+                                         imm0, imm1)
 
 from pypy.rlib.objectmodel import we_are_translated, specialize
 from pypy.jit.backend.x86 import rx86, regloc, codebuf
@@ -244,12 +246,13 @@
             f = open_file_as_stream(output_log, "w")
             for i in range(len(self.loop_run_counters)):
                 name, struct = self.loop_run_counters[i]
-                f.write(str(struct.i) + " " * (8 - len(str(struct.i))) + name + "\n")
+                f.write(str(name) + ":" +  str(struct.i) + "\n")
             f.close()
 
     def _build_float_constants(self):
         # 44 bytes: 32 bytes for the data, and up to 12 bytes for alignment
-        addr = lltype.malloc(rffi.CArray(lltype.Char), 44, flavor='raw')
+        addr = lltype.malloc(rffi.CArray(lltype.Char), 44, flavor='raw',
+                             track_allocation=False)
         if not we_are_translated():
             self._keepalive_malloced_float_consts = addr
         float_constants = rffi.cast(lltype.Signed, addr)
@@ -292,7 +295,7 @@
         self.mc.RET()
         self.mc.done()
 
-    def assemble_loop(self, inputargs, operations, looptoken):
+    def assemble_loop(self, inputargs, operations, looptoken, log):
         """adds the following attributes to looptoken:
                _x86_loop_code       (an integer giving an address)
                _x86_bootstrap_code  (an integer giving an address)
@@ -307,10 +310,11 @@
 
         self.setup()
         funcname = self._find_debug_merge_point(operations)
-
+        if log:
+            self._register_counter()
+            operations = self._inject_debugging_code(operations)
         
         regalloc = RegAlloc(self, self.cpu.translate_support_code)
-        operations = self._inject_debugging_code(operations)
         arglocs = regalloc.prepare_loop(inputargs, operations, looptoken)
         looptoken._x86_arglocs = arglocs
 
@@ -337,13 +341,16 @@
         self.mc.end_function()
         self.write_pending_failure_recoveries()
         
-    def assemble_bridge(self, faildescr, inputargs, operations):
+    def assemble_bridge(self, faildescr, inputargs, operations, log):
         if not we_are_translated():
             # Arguments should be unique
             assert len(set(inputargs)) == len(inputargs)
 
         self.setup()
         funcname = self._find_debug_merge_point(operations)
+        if log:
+            self._register_counter()
+            operations = self._inject_debugging_code(operations)
 
         arglocs = self.rebuild_faillocs_from_descr(
             faildescr._x86_failure_recovery_bytecode)
@@ -398,11 +405,14 @@
         else:
             funcname = "<loop %d>" % len(self.loop_run_counters)
         # invent the counter, so we don't get too confused
+        return funcname
+
+    def _register_counter(self):
         if self._debug:
-            struct = lltype.malloc(DEBUG_COUNTER, flavor='raw')
+            struct = lltype.malloc(DEBUG_COUNTER, flavor='raw',
+                                   track_allocation=False)   # known to leak
             struct.i = 0
-            self.loop_run_counters.append((funcname, struct))
-        return funcname
+            self.loop_run_counters.append((len(self.loop_run_counters), struct))
         
     def patch_jump_for_descr(self, faildescr, adr_new_target):
         adr_jump_offset = faildescr._x86_adr_jump_offset
@@ -440,7 +450,7 @@
             # 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, imm(1))
+            # self.mc.ADD(eax, imm1)
             # self.mc.MOV(heap(adr), eax)
             # self.mc.POP(eax)
         return operations
@@ -711,7 +721,7 @@
         self.regalloc_perform_with_guard(None, guard_op, faillocs, arglocs,
                                          resloc, current_depths)
 
-    def load_effective_addr(self, sizereg, baseofs, scale, result, frm=imm(0)):
+    def load_effective_addr(self, sizereg, baseofs, scale, result, frm=imm0):
         self.mc.LEA(result, addr_add(frm, sizereg, baseofs, scale))
 
     def _unaryop(asmop):
@@ -973,28 +983,28 @@
 
     def genop_guard_int_is_true(self, op, guard_op, guard_token, arglocs, resloc):
         guard_opnum = guard_op.getopnum()
-        self.mc.CMP(arglocs[0], imm(0))
+        self.mc.CMP(arglocs[0], imm0)
         if guard_opnum == rop.GUARD_TRUE:
             return self.implement_guard(guard_token, 'Z')
         else:
             return self.implement_guard(guard_token, 'NZ')
 
     def genop_int_is_true(self, op, arglocs, resloc):
-        self.mc.CMP(arglocs[0], imm(0))
+        self.mc.CMP(arglocs[0], imm0)
         rl = resloc.lowest8bits()
         self.mc.SET_ir(rx86.Conditions['NE'], rl.value)
         self.mc.MOVZX8(resloc, rl)
 
     def genop_guard_int_is_zero(self, op, guard_op, guard_token, arglocs, resloc):
         guard_opnum = guard_op.getopnum()
-        self.mc.CMP(arglocs[0], imm(0))
+        self.mc.CMP(arglocs[0], imm0)
         if guard_opnum == rop.GUARD_TRUE:
             return self.implement_guard(guard_token, 'NZ')
         else:
             return self.implement_guard(guard_token, 'Z')
 
     def genop_int_is_zero(self, op, arglocs, resloc):
-        self.mc.CMP(arglocs[0], imm(0))
+        self.mc.CMP(arglocs[0], imm0)
         rl = resloc.lowest8bits()
         self.mc.SET_ir(rx86.Conditions['E'], rl.value)
         self.mc.MOVZX8(resloc, rl)
@@ -1050,50 +1060,66 @@
         assert result_loc is eax
         self.call(self.malloc_unicode_func_addr, arglocs, eax)
 
-    def genop_getfield_gc(self, op, arglocs, resloc):
-        base_loc, ofs_loc, size_loc = arglocs
-        assert isinstance(size_loc, ImmedLoc)
+    # ----------
+
+    def load_from_mem(self, resloc, source_addr, size_loc, sign_loc):
         assert isinstance(resloc, RegLoc)
         size = size_loc.value
-
-        source_addr = AddressLoc(base_loc, ofs_loc)
+        sign = sign_loc.value
         if resloc.is_xmm:
             self.mc.MOVSD(resloc, source_addr)
+        elif size == WORD:
+            self.mc.MOV(resloc, source_addr)
         elif size == 1:
-            self.mc.MOVZX8(resloc, source_addr)
+            if sign:
+                self.mc.MOVSX8(resloc, source_addr)
+            else:
+                self.mc.MOVZX8(resloc, source_addr)
         elif size == 2:
-            self.mc.MOVZX16(resloc, source_addr)
+            if sign:
+                self.mc.MOVSX16(resloc, source_addr)
+            else:
+                self.mc.MOVZX16(resloc, source_addr)
+        elif IS_X86_64 and size == 4:
+            if sign:
+                self.mc.MOVSX32(resloc, source_addr)
+            else:
+                self.mc.MOV32(resloc, source_addr)    # zero-extending
+        else:
+            not_implemented("load_from_mem size = %d" % size)
+
+    def save_into_mem(self, dest_addr, value_loc, size_loc):
+        size = size_loc.value
+        if isinstance(value_loc, RegLoc) and value_loc.is_xmm:
+            self.mc.MOVSD(dest_addr, value_loc)
+        elif size == 1:
+            self.mc.MOV8(dest_addr, value_loc.lowest8bits())
+        elif size == 2:
+            self.mc.MOV16(dest_addr, value_loc)
         elif size == 4:
-            # MOV32 is zero-extending on 64-bit, so this is okay
-            self.mc.MOV32(resloc, source_addr)
+            self.mc.MOV32(dest_addr, value_loc)
         elif IS_X86_64 and size == 8:
-            self.mc.MOV(resloc, source_addr)
+            self.mc.MOV(dest_addr, value_loc)
         else:
-            raise NotImplementedError("getfield size = %d" % size)
+            not_implemented("save_into_mem size = %d" % size)
+
+    def genop_getfield_gc(self, op, arglocs, resloc):
+        base_loc, ofs_loc, size_loc, sign_loc = arglocs
+        assert isinstance(size_loc, ImmedLoc)
+        source_addr = AddressLoc(base_loc, ofs_loc)
+        self.load_from_mem(resloc, source_addr, size_loc, sign_loc)
 
     genop_getfield_raw = genop_getfield_gc
     genop_getfield_raw_pure = genop_getfield_gc
     genop_getfield_gc_pure = genop_getfield_gc
 
     def genop_getarrayitem_gc(self, op, arglocs, resloc):
-        base_loc, ofs_loc, scale, ofs = arglocs
+        base_loc, ofs_loc, size_loc, ofs, sign_loc = arglocs
         assert isinstance(ofs, ImmedLoc)
-        assert isinstance(scale, ImmedLoc)
-        src_addr = addr_add(base_loc, ofs_loc, ofs.value, scale.value)
-        if op.result.type == FLOAT:
-            self.mc.MOVSD(resloc, src_addr)
-        else:
-            if scale.value == 0:
-                self.mc.MOVZX8(resloc, src_addr)
-            elif scale.value == 1:
-                self.mc.MOVZX16(resloc, src_addr)
-            elif scale.value == 2:
-                self.mc.MOV32(resloc, src_addr)
-            elif IS_X86_64 and scale.value == 3:
-                self.mc.MOV(resloc, src_addr)
-            else:
-                print "[asmgen]getarrayitem unsupported size: %d" % scale.value
-                raise NotImplementedError()
+        assert isinstance(size_loc, ImmedLoc)
+        scale = _get_scale(size_loc.value)
+        src_addr = addr_add(base_loc, ofs_loc, ofs.value, scale)
+        self.load_from_mem(resloc, src_addr, size_loc, sign_loc)
 
     genop_getarrayitem_gc_pure = genop_getarrayitem_gc
     genop_getarrayitem_raw = genop_getarrayitem_gc
@@ -1101,40 +1127,16 @@
     def genop_discard_setfield_gc(self, op, arglocs):
         base_loc, ofs_loc, size_loc, value_loc = arglocs
         assert isinstance(size_loc, ImmedLoc)
-        size = size_loc.value
         dest_addr = AddressLoc(base_loc, ofs_loc)
-        if isinstance(value_loc, RegLoc) and value_loc.is_xmm:
-            self.mc.MOVSD(dest_addr, value_loc)
-        elif IS_X86_64 and size == 8:
-            self.mc.MOV(dest_addr, value_loc)
-        elif size == 4:
-            self.mc.MOV32(dest_addr, value_loc)
-        elif size == 2:
-            self.mc.MOV16(dest_addr, value_loc)
-        elif size == 1:
-            self.mc.MOV8(dest_addr, value_loc.lowest8bits())
-        else:
-            print "[asmgen]setfield addr size %d" % size
-            raise NotImplementedError("Addr size %d" % size)
+        self.save_into_mem(dest_addr, value_loc, size_loc)
 
     def genop_discard_setarrayitem_gc(self, op, arglocs):
-        base_loc, ofs_loc, value_loc, scale_loc, baseofs = arglocs
+        base_loc, ofs_loc, value_loc, size_loc, baseofs = arglocs
         assert isinstance(baseofs, ImmedLoc)
-        assert isinstance(scale_loc, ImmedLoc)
-        dest_addr = AddressLoc(base_loc, ofs_loc, scale_loc.value, baseofs.value)
-        if op.getarg(2).type == FLOAT:
-            self.mc.MOVSD(dest_addr, value_loc)
-        else:
-            if IS_X86_64 and scale_loc.value == 3:
-                self.mc.MOV(dest_addr, value_loc)
-            elif scale_loc.value == 2:
-                self.mc.MOV32(dest_addr, value_loc)
-            elif scale_loc.value == 1:
-                self.mc.MOV16(dest_addr, value_loc)
-            elif scale_loc.value == 0:
-                self.mc.MOV8(dest_addr, value_loc.lowest8bits())
-            else:
-                raise NotImplementedError("scale = %d" % scale_loc.value)
+        assert isinstance(size_loc, ImmedLoc)
+        scale = _get_scale(size_loc.value)
+        dest_addr = AddressLoc(base_loc, ofs_loc, scale, baseofs.value)
+        self.save_into_mem(dest_addr, value_loc, size_loc)
 
     def genop_discard_strsetitem(self, op, arglocs):
         base_loc, ofs_loc, val_loc = arglocs
@@ -1201,7 +1203,7 @@
 
     def genop_guard_guard_no_exception(self, ign_1, guard_op, guard_token,
                                        locs, ign_2):
-        self.mc.CMP(heap(self.cpu.pos_exception()), imm(0))
+        self.mc.CMP(heap(self.cpu.pos_exception()), imm0)
         return self.implement_guard(guard_token, 'NZ')
 
     def genop_guard_guard_exception(self, ign_1, guard_op, guard_token,
@@ -1213,8 +1215,8 @@
         addr = self.implement_guard(guard_token, 'NE')
         if resloc is not None:
             self.mc.MOV(resloc, heap(self.cpu.pos_exc_value()))
-        self.mc.MOV(heap(self.cpu.pos_exception()), imm(0))
-        self.mc.MOV(heap(self.cpu.pos_exc_value()), imm(0))
+        self.mc.MOV(heap(self.cpu.pos_exception()), imm0)
+        self.mc.MOV(heap(self.cpu.pos_exc_value()), imm0)
         return addr
 
     def _gen_guard_overflow(self, guard_op, guard_token):
@@ -1224,8 +1226,8 @@
         elif guard_opnum == rop.GUARD_OVERFLOW:
             return self.implement_guard(guard_token, 'NO')
         else:
-            print "int_xxx_ovf followed by", guard_op.getopname()
-            raise AssertionError
+            not_implemented("int_xxx_ovf followed by %s" %
+                            guard_op.getopname())
 
     def genop_guard_int_add_ovf(self, op, guard_op, guard_token, arglocs, result_loc):
         self.genop_int_add(op, arglocs, result_loc)
@@ -1288,7 +1290,7 @@
     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], imm(1))
+        self.mc.CMP(locs[0], imm1)
         # Patched below
         self.mc.J_il8(rx86.Conditions['B'], 0)
         jb_location = self.mc.get_relative_pos()
@@ -1637,25 +1639,34 @@
         sizeloc = arglocs[0]
         assert isinstance(sizeloc, ImmedLoc)
         size = sizeloc.value
+        signloc = arglocs[1]
 
         if isinstance(op.getarg(0), Const):
             x = imm(op.getarg(0).getint())
         else:
-            x = arglocs[1]
+            x = arglocs[2]
         if x is eax:
             tmp = ecx
         else:
             tmp = eax
         
-        self._emit_call(x, arglocs, 2, tmp=tmp)
+        self._emit_call(x, arglocs, 3, tmp=tmp)
+
+        if IS_X86_32 and isinstance(resloc, StackLoc) and resloc.width == 8:
+            self.mc.FSTP_b(resloc.value)   # float return
+        elif size == WORD:
+            assert resloc is eax or resloc is xmm0    # a full word
+        elif size == 0:
+            pass    # void return
+        else:
+            # use the code in load_from_mem to do the zero- or sign-extension
+            assert resloc is eax
+            if size == 1:
+                srcloc = eax.lowest8bits()
+            else:
+                srcloc = eax
+            self.load_from_mem(eax, srcloc, sizeloc, signloc)
 
-        if isinstance(resloc, StackLoc) and resloc.width == 8 and IS_X86_32:
-            self.mc.FSTP_b(resloc.value)
-        elif size == 1:
-            self.mc.AND_ri(eax.value, 0xff)
-        elif size == 2:
-            self.mc.AND_ri(eax.value, 0xffff)
-    
     def genop_guard_call_may_force(self, op, guard_op, guard_token,
                                    arglocs, result_loc):
         faildescr = guard_op.getdescr()
@@ -1780,11 +1791,12 @@
                     self.mc.PUSH_i32(loc.getint())
         
         if IS_X86_64:
-            # We clobber this register to pass the arguments, but that's
+            # We clobber these registers to pass the arguments, but that's
             # okay, because consider_cond_call_gc_wb makes sure that any
             # caller-save registers with values in them are present in arglocs,
             # so they are saved on the stack above and restored below 
             self.mc.MOV_rs(edi.value, 0)
+            self.mc.MOV_rs(esi.value, 8)
 
         # misaligned stack in the call, but it's ok because the write barrier
         # is not going to call anything more.  Also, this assumes that the
@@ -1807,20 +1819,16 @@
         self.mc.LEA_rb(resloc.value, FORCE_INDEX_OFS)
 
     def not_implemented_op_discard(self, op, arglocs):
-        msg = "not implemented operation: %s" % op.getopname()
-        print msg
-        raise NotImplementedError(msg)
+        not_implemented("not implemented operation: %s" % op.getopname())
 
     def not_implemented_op(self, op, arglocs, resloc):
-        msg = "not implemented operation with res: %s" % op.getopname()
-        print msg
-        raise NotImplementedError(msg)
+        not_implemented("not implemented operation with res: %s" %
+                        op.getopname())
 
     def not_implemented_op_guard(self, op, guard_op,
                                  failaddr, arglocs, resloc):
-        msg = "not implemented operation (guard): %s" % op.getopname()
-        print msg
-        raise NotImplementedError(msg)
+        not_implemented("not implemented operation (guard): %s" %
+                        op.getopname())
 
     def mark_gc_roots(self):
         gcrootmap = self.cpu.gc_ll_descr.gcrootmap
@@ -1904,3 +1912,7 @@
 
 def heap(addr):
     return AddressLoc(ImmedLoc(addr), ImmedLoc(0), 0, 0)
+
+def not_implemented(msg):
+    os.write(2, '[x86/asm] %s\n' % msg)
+    raise NotImplementedError(msg)

Modified: pypy/branch/jit-unroll-loops/pypy/jit/backend/x86/regalloc.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/jit/backend/x86/regalloc.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/jit/backend/x86/regalloc.py	Sat Oct 30 16:41:17 2010
@@ -2,6 +2,7 @@
 """ Register allocation scheme.
 """
 
+import os
 from pypy.jit.metainterp.history import (Box, Const, ConstInt, ConstPtr,
                                          ResOperation, BoxPtr,
                                          LoopToken, INT, REF, FLOAT)
@@ -40,12 +41,10 @@
             return imm(c.value)
         elif isinstance(c, ConstPtr):
             if we_are_translated() and c.value and rgc.can_move(c.value):
-                print "convert_to_imm: ConstPtr needs special care"
-                raise AssertionError
+                not_implemented("convert_to_imm: ConstPtr needs special care")
             return imm(rffi.cast(lltype.Signed, c.value))
         else:
-            print "convert_to_imm: got a %s" % c
-            raise AssertionError
+            not_implemented("convert_to_imm: got a %s" % c)
 
 class X86_64_RegisterManager(X86RegisterManager):
     # r11 omitted because it's used as scratch
@@ -70,8 +69,9 @@
 
     def _get_new_array(self):
         n = self.BASE_CONSTANT_SIZE
+        # known to leak
         self.cur_array = lltype.malloc(rffi.CArray(lltype.Float), n,
-                                       flavor='raw')
+                                       flavor='raw', track_allocation=False)
         self.cur_array_free = n
     _get_new_array._dont_inline_ = True
 
@@ -359,8 +359,8 @@
             if op.is_ovf():
                 if (operations[i + 1].getopnum() != rop.GUARD_NO_OVERFLOW and
                     operations[i + 1].getopnum() != rop.GUARD_OVERFLOW):
-                    print "int_xxx_ovf not followed by guard_(no)_overflow"
-                    raise AssertionError
+                    not_implemented("int_xxx_ovf not followed by "
+                                    "guard_(no)_overflow")
                 return True
             return False
         if (operations[i + 1].getopnum() != rop.GUARD_TRUE and
@@ -412,8 +412,8 @@
                 arg = op.getarg(j)
                 if isinstance(arg, Box):
                     if arg not in start_live:
-                        print "Bogus arg in operation %d at %d" % (op.getopnum(), i)
-                        raise AssertionError
+                        not_implemented("Bogus arg in operation %d at %d" %
+                                        (op.getopnum(), i))
                     longevity[arg] = (start_live[arg], i)
             if op.is_guard():
                 for arg in op.getfailargs():
@@ -421,8 +421,8 @@
                         continue
                     assert isinstance(arg, Box)
                     if arg not in start_live:
-                        print "Bogus arg in guard %d at %d" % (op.getopnum(), i)
-                        raise AssertionError
+                        not_implemented("Bogus arg in guard %d at %d" %
+                                        (op.getopnum(), i))
                     longevity[arg] = (start_live[arg], i)
         for arg in inputargs:
             if arg not in longevity:
@@ -667,7 +667,13 @@
         assert isinstance(calldescr, BaseCallDescr)
         assert len(calldescr.arg_classes) == op.numargs() - 1
         size = calldescr.get_result_size(self.translate_support_code)
-        self._call(op, [imm(size)] + [self.loc(op.getarg(i)) for i in range(op.numargs())],
+        sign = calldescr.is_result_signed()
+        if sign:
+            sign_loc = imm1
+        else:
+            sign_loc = imm0
+        self._call(op, [imm(size), sign_loc] +
+                       [self.loc(op.getarg(i)) for i in range(op.numargs())],
                    guard_not_forced_op=guard_not_forced_op)
 
     def consider_call(self, op):
@@ -688,7 +694,7 @@
             self.rm._sync_var(op.getarg(vable_index))
             vable = self.fm.loc(op.getarg(vable_index))
         else:
-            vable = imm(0)
+            vable = imm0
         self._call(op, [imm(size), vable] +
                    [self.loc(op.getarg(i)) for i in range(op.numargs())],
                    guard_not_forced_op=guard_op)
@@ -696,9 +702,13 @@
     def consider_cond_call_gc_wb(self, op):
         assert op.result is None
         args = op.getarglist()
+        loc_newvalue = self.rm.make_sure_var_in_reg(op.getarg(1), args)
+        # ^^^ we force loc_newvalue in a reg (unless it's a Const),
+        # because it will be needed anyway by the following setfield_gc.
+        # It avoids loading it twice from the memory.
         loc_base = self.rm.make_sure_var_in_reg(op.getarg(0), args,
                                                 imm_fine=False)
-        arglocs = [loc_base]
+        arglocs = [loc_base, loc_newvalue]
         # add eax, ecx and edx as extra "arguments" to ensure they are
         # saved and restored.  Fish in self.rm to know which of these
         # registers really need to be saved (a bit of a hack).  Moreover,
@@ -774,15 +784,11 @@
             loc = self.loc(op.getarg(0))
             return self._call(op, [loc])
         # boehm GC (XXX kill the following code at some point)
-        ofs_items, itemsize, ofs = symbolic.get_array_token(rstr.UNICODE, self.translate_support_code)
-        if itemsize == 4:
-            return self._malloc_varsize(ofs_items, ofs, 2, op.getarg(0),
-                                        op.result)
-        elif itemsize == 2:
-            return self._malloc_varsize(ofs_items, ofs, 1, op.getarg(0),
-                                        op.result)
-        else:
-            assert False, itemsize
+        ofs_items, _, ofs = symbolic.get_array_token(rstr.UNICODE,
+                                                   self.translate_support_code)
+        scale = self._get_unicode_item_scale()
+        return self._malloc_varsize(ofs_items, ofs, scale, op.getarg(0),
+                                    op.result)
 
     def _malloc_varsize(self, ofs_items, ofs_length, scale, v, res_v):
         # XXX kill this function at some point
@@ -814,8 +820,9 @@
             arglocs.append(self.loc(op.getarg(0)))
             return self._call(op, arglocs)
         # boehm GC (XXX kill the following code at some point)
-        scale_of_field, basesize, ofs_length, _ = (
+        itemsize, basesize, ofs_length, _, _ = (
             self._unpack_arraydescr(op.getdescr()))
+        scale_of_field = _get_scale(itemsize)
         return self._malloc_varsize(basesize, ofs_length, scale_of_field,
                                     op.getarg(0), op.result)
 
@@ -825,21 +832,19 @@
         ofs = arraydescr.get_base_size(self.translate_support_code)
         size = arraydescr.get_item_size(self.translate_support_code)
         ptr = arraydescr.is_array_of_pointers()
-        scale = 0
-        while (1 << scale) < size:
-            scale += 1
-        assert (1 << scale) == size
-        return scale, ofs, ofs_length, ptr
+        sign = arraydescr.is_item_signed()
+        return size, ofs, ofs_length, ptr, sign
 
     def _unpack_fielddescr(self, fielddescr):
         assert isinstance(fielddescr, BaseFieldDescr)
         ofs = fielddescr.offset
         size = fielddescr.get_field_size(self.translate_support_code)
         ptr = fielddescr.is_pointer_field()
-        return imm(ofs), imm(size), ptr
+        sign = fielddescr.is_field_signed()
+        return imm(ofs), imm(size), ptr, sign
 
     def consider_setfield_gc(self, op):
-        ofs_loc, size_loc, ptr = self._unpack_fielddescr(op.getdescr())
+        ofs_loc, size_loc, _, _ = self._unpack_fielddescr(op.getdescr())
         assert isinstance(size_loc, ImmedLoc)
         if size_loc.value == 1:
             need_lower_byte = True
@@ -866,10 +871,10 @@
     consider_unicodesetitem = consider_strsetitem
 
     def consider_setarrayitem_gc(self, op):
-        scale, ofs, _, ptr = self._unpack_arraydescr(op.getdescr())
+        itemsize, ofs, _, _, _ = self._unpack_arraydescr(op.getdescr())
         args = op.getarglist()
         base_loc  = self.rm.make_sure_var_in_reg(op.getarg(0), args)
-        if scale == 0:
+        if itemsize == 1:
             need_lower_byte = True
         else:
             need_lower_byte = False
@@ -878,30 +883,39 @@
         ofs_loc = self.rm.make_sure_var_in_reg(op.getarg(1), args)
         self.possibly_free_vars(args)
         self.PerformDiscard(op, [base_loc, ofs_loc, value_loc,
-                                 imm(scale), imm(ofs)])
+                                 imm(itemsize), imm(ofs)])
 
     consider_setarrayitem_raw = consider_setarrayitem_gc
 
     def consider_getfield_gc(self, op):
-        ofs_loc, size_loc, _ = self._unpack_fielddescr(op.getdescr())
+        ofs_loc, size_loc, _, sign = self._unpack_fielddescr(op.getdescr())
         args = op.getarglist()
         base_loc = self.rm.make_sure_var_in_reg(op.getarg(0), args)
         self.rm.possibly_free_vars(args)
         result_loc = self.force_allocate_reg(op.result)
-        self.Perform(op, [base_loc, ofs_loc, size_loc], result_loc)
+        if sign:
+            sign_loc = imm1
+        else:
+            sign_loc = imm0
+        self.Perform(op, [base_loc, ofs_loc, size_loc, sign_loc], result_loc)
 
     consider_getfield_raw = consider_getfield_gc
     consider_getfield_raw_pure = consider_getfield_gc
     consider_getfield_gc_pure = consider_getfield_gc
 
     def consider_getarrayitem_gc(self, op):
-        scale, ofs, _, _ = self._unpack_arraydescr(op.getdescr())
+        itemsize, ofs, _, _, sign = self._unpack_arraydescr(op.getdescr())
         args = op.getarglist()
         base_loc = self.rm.make_sure_var_in_reg(op.getarg(0), args)
         ofs_loc = self.rm.make_sure_var_in_reg(op.getarg(1), args)
         self.rm.possibly_free_vars_for_op(op)
         result_loc = self.force_allocate_reg(op.result)
-        self.Perform(op, [base_loc, ofs_loc, imm(scale), imm(ofs)], result_loc)
+        if sign:
+            sign_loc = imm1
+        else:
+            sign_loc = imm0
+        self.Perform(op, [base_loc, ofs_loc, imm(itemsize), imm(ofs),
+                          sign_loc], result_loc)
 
     consider_getarrayitem_raw = consider_getarrayitem_gc
     consider_getarrayitem_gc_pure = consider_getarrayitem_gc
@@ -955,41 +969,85 @@
     consider_unicodegetitem = consider_strgetitem
 
     def consider_copystrcontent(self, op):
+        self._consider_copystrcontent(op, is_unicode=False)
+
+    def consider_copyunicodecontent(self, op):
+        self._consider_copystrcontent(op, is_unicode=True)
+
+    def _consider_copystrcontent(self, op, is_unicode):
         # compute the source address
         args = op.getarglist()
         base_loc = self.rm.make_sure_var_in_reg(args[0], args)
         ofs_loc = self.rm.make_sure_var_in_reg(args[2], args)
+        assert args[0] is not args[1]    # forbidden case of aliasing
         self.rm.possibly_free_var(args[0])
-        self.rm.possibly_free_var(args[2])
+        if args[3] is not args[2] is not args[4]:  # MESS MESS MESS: don't free
+            self.rm.possibly_free_var(args[2])     # it if ==args[3] or args[4]
         srcaddr_box = TempBox()
-        srcaddr_loc = self.rm.force_allocate_reg(srcaddr_box)
-        self._gen_address_inside_string(base_loc, ofs_loc, srcaddr_loc)
+        forbidden_vars = [args[1], args[3], args[4], srcaddr_box]
+        srcaddr_loc = self.rm.force_allocate_reg(srcaddr_box, forbidden_vars)
+        self._gen_address_inside_string(base_loc, ofs_loc, srcaddr_loc,
+                                        is_unicode=is_unicode)
         # compute the destination address
-        base_loc = self.rm.make_sure_var_in_reg(args[1], args)
-        ofs_loc = self.rm.make_sure_var_in_reg(args[3], args)
+        base_loc = self.rm.make_sure_var_in_reg(args[1], forbidden_vars)
+        ofs_loc = self.rm.make_sure_var_in_reg(args[3], forbidden_vars)
         self.rm.possibly_free_var(args[1])
-        self.rm.possibly_free_var(args[3])
+        if args[3] is not args[4]:     # more of the MESS described above
+            self.rm.possibly_free_var(args[3])
+        forbidden_vars = [args[4], srcaddr_box]
         dstaddr_box = TempBox()
-        dstaddr_loc = self.rm.force_allocate_reg(dstaddr_box)
-        self._gen_address_inside_string(base_loc, ofs_loc, dstaddr_loc)
+        dstaddr_loc = self.rm.force_allocate_reg(dstaddr_box, forbidden_vars)
+        self._gen_address_inside_string(base_loc, ofs_loc, dstaddr_loc,
+                                        is_unicode=is_unicode)
+        # compute the length in bytes
+        length_box = args[4]
+        length_loc = self.loc(length_box)
+        if is_unicode:
+            self.rm.possibly_free_var(length_box)
+            forbidden_vars = [srcaddr_box, dstaddr_box]
+            bytes_box = TempBox()
+            bytes_loc = self.rm.force_allocate_reg(bytes_box, forbidden_vars)
+            scale = self._get_unicode_item_scale()
+            if not (isinstance(length_loc, ImmedLoc) or
+                    isinstance(length_loc, RegLoc)):
+                self.assembler.mov(length_loc, bytes_loc)
+                length_loc = bytes_loc
+            self.assembler.load_effective_addr(length_loc, 0, scale, bytes_loc)
+            length_box = bytes_box
+            length_loc = bytes_loc
         # call memcpy()
-        length_loc = self.loc(args[4])
         self.rm.before_call()
         self.xrm.before_call()
         self.assembler._emit_call(imm(self.assembler.memcpy_addr),
                                   [dstaddr_loc, srcaddr_loc, length_loc])
-        self.rm.possibly_free_var(args[4])
+        self.rm.possibly_free_var(length_box)
         self.rm.possibly_free_var(dstaddr_box)
         self.rm.possibly_free_var(srcaddr_box)
 
-    def _gen_address_inside_string(self, baseloc, ofsloc, resloc):
+    def _gen_address_inside_string(self, baseloc, ofsloc, resloc, is_unicode):
         cpu = self.assembler.cpu
-        ofs_items, itemsize, _ = symbolic.get_array_token(rstr.STR,
+        if is_unicode:
+            ofs_items, _, _ = symbolic.get_array_token(rstr.UNICODE,
                                                   self.translate_support_code)
-        assert itemsize == 1
-        self.assembler.load_effective_addr(ofsloc, ofs_items, 0,
+            scale = self._get_unicode_item_scale()
+        else:
+            ofs_items, itemsize, _ = symbolic.get_array_token(rstr.STR,
+                                                  self.translate_support_code)
+            assert itemsize == 1
+            scale = 0
+        self.assembler.load_effective_addr(ofsloc, ofs_items, scale,
                                            resloc, baseloc)
 
+    def _get_unicode_item_scale(self):
+        _, itemsize, _ = symbolic.get_array_token(rstr.UNICODE,
+                                                  self.translate_support_code)
+        if itemsize == 4:
+            return 2
+        elif itemsize == 2:
+            return 1
+        else:
+            raise AssertionError("bad unicode item size")
+
     def consider_jump(self, op):
         assembler = self.assembler
         assert self.jump_target_descr is None
@@ -1024,6 +1082,9 @@
     def consider_debug_merge_point(self, op):
         pass
 
+    def consider_jit_debug(self, op):
+        pass
+
     def get_mark_gc_roots(self, gcrootmap):
         shape = gcrootmap.get_basic_shape(IS_X86_64)
         for v, val in self.fm.frame_bindings.items():
@@ -1043,15 +1104,11 @@
         self.Perform(op, [], loc)
 
     def not_implemented_op(self, op):
-        msg = "[regalloc] Not implemented operation: %s" % op.getopname()
-        print msg
-        raise NotImplementedError(msg)
+        not_implemented("not implemented operation: %s" % op.getopname())
 
     def not_implemented_op_with_guard(self, op, guard_op):
-        msg = "[regalloc] Not implemented operation with guard: %s" % (
-            op.getopname(),)
-        print msg
-        raise NotImplementedError(msg)
+        not_implemented("not implemented operation with guard: %s" % (
+            op.getopname(),))
 
 oplist = [RegAlloc.not_implemented_op] * rop._LAST
 oplist_with_guard = [RegAlloc.not_implemented_op_with_guard] * rop._LAST
@@ -1085,3 +1142,14 @@
     # Returns (ebp-20), (ebp-24), (ebp-28)...
     # i.e. the n'th word beyond the fixed frame size.
     return -WORD * (FRAME_FIXED_SIZE + position)
+
+def _get_scale(size):
+    assert size == 1 or size == 2 or size == 4 or size == 8
+    if size < 4:
+        return size - 1         # 1, 2 => 0, 1
+    else:
+        return (size >> 2) + 1  # 4, 8 => 2, 3
+
+def not_implemented(msg):
+    os.write(2, '[x86/regalloc] %s\n' % msg)
+    raise NotImplementedError(msg)

Modified: pypy/branch/jit-unroll-loops/pypy/jit/backend/x86/regloc.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/jit/backend/x86/regloc.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/jit/backend/x86/regloc.py	Sat Oct 30 16:41:17 2010
@@ -442,8 +442,11 @@
     MOV8 = _binaryop('MOV8')
     MOV16 = _16_bit_binaryop('MOV')
     MOVZX8 = _binaryop('MOVZX8')
+    MOVSX8 = _binaryop('MOVSX8')
     MOVZX16 = _binaryop('MOVZX16')
+    MOVSX16 = _binaryop('MOVSX16')
     MOV32 = _binaryop('MOV32')
+    MOVSX32 = _binaryop('MOVSX32')
     XCHG = _binaryop('XCHG')
 
     PUSH = _unaryop('PUSH')
@@ -473,6 +476,9 @@
     else:
         return ImmedLoc(x)
 
+imm0 = imm(0)
+imm1 = imm(1)
+
 all_extra_instructions = [name for name in LocationCodeBuilder.__dict__
                           if name[0].isupper()]
 all_extra_instructions.sort()

Modified: pypy/branch/jit-unroll-loops/pypy/jit/backend/x86/runner.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/jit/backend/x86/runner.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/jit/backend/x86/runner.py	Sat Oct 30 16:41:17 2010
@@ -49,11 +49,13 @@
         self.assembler.finish_once()
         self.profile_agent.shutdown()
 
-    def compile_loop(self, inputargs, operations, looptoken):
-        self.assembler.assemble_loop(inputargs, operations, looptoken)
-
-    def compile_bridge(self, faildescr, inputargs, operations):
-        self.assembler.assemble_bridge(faildescr, inputargs, operations)
+    def compile_loop(self, inputargs, operations, looptoken, log=True):
+        self.assembler.assemble_loop(inputargs, operations, looptoken,
+                                     log=log)
+
+    def compile_bridge(self, faildescr, inputargs, operations, log=True):
+        self.assembler.assemble_bridge(faildescr, inputargs, operations,
+                                       log=log)
 
     def set_future_value_int(self, index, intvalue):
         self.assembler.fail_boxes_int.setitem(index, intvalue)
@@ -87,7 +89,9 @@
 
     def execute_token(self, executable_token):
         addr = executable_token._x86_bootstrap_code
+        #llop.debug_print(lltype.Void, ">>>> Entering", addr)
         func = rffi.cast(lltype.Ptr(self.BOOTSTRAP_TP), addr)
+        #llop.debug_print(lltype.Void, "<<<< Back")
         fail_index = self._execute_call(func)
         return self.get_fail_descr_from_number(fail_index)
 
@@ -99,10 +103,7 @@
             LLInterpreter.current_interpreter = self.debug_ll_interpreter
         res = 0
         try:
-            #llop.debug_print(lltype.Void, ">>>> Entering",
-            #                 rffi.cast(lltype.Signed, func))
             res = func()
-            #llop.debug_print(lltype.Void, "<<<< Back")
         finally:
             if not self.translate_support_code:
                 LLInterpreter.current_interpreter = prev_interpreter
@@ -114,7 +115,8 @@
         return CPU386.cast_adr_to_int(adr)
 
     all_null_registers = lltype.malloc(rffi.LONGP.TO, 24,
-                                       flavor='raw', zero=True)
+                                       flavor='raw', zero=True,
+                                       immortal=True)
 
     def force(self, addr_of_force_index):
         TP = rffi.CArrayPtr(lltype.Signed)

Modified: pypy/branch/jit-unroll-loops/pypy/jit/backend/x86/rx86.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/jit/backend/x86/rx86.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/jit/backend/x86/rx86.py	Sat Oct 30 16:41:17 2010
@@ -642,7 +642,10 @@
 define_modrm_modes('MOV8_*i', [rex_w, '\xC6', orbyte(0<<3)], [immediate(2, 'b')], regtype='BYTE')
 
 define_modrm_modes('MOVZX8_r*', [rex_w, '\x0F\xB6', register(1, 8)], regtype='BYTE')
+define_modrm_modes('MOVSX8_r*', [rex_w, '\x0F\xBE', register(1, 8)], regtype='BYTE')
 define_modrm_modes('MOVZX16_r*', [rex_w, '\x0F\xB7', register(1, 8)])
+define_modrm_modes('MOVSX16_r*', [rex_w, '\x0F\xBF', register(1, 8)])
+define_modrm_modes('MOVSX32_r*', [rex_w, '\x63', register(1, 8)])
 
 define_modrm_modes('MOVSD_x*', ['\xF2', rex_nw, '\x0F\x10', register(1,8)], regtype='XMM')
 define_modrm_modes('MOVSD_*x', ['\xF2', rex_nw, '\x0F\x11', register(2,8)], regtype='XMM')

Modified: pypy/branch/jit-unroll-loops/pypy/jit/backend/x86/test/test_assembler.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/jit/backend/x86/test/test_assembler.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/jit/backend/x86/test/test_assembler.py	Sat Oct 30 16:41:17 2010
@@ -81,7 +81,8 @@
 
     # also test rebuild_faillocs_from_descr(), which should not
     # reproduce the holes at all
-    bytecode = lltype.malloc(rffi.UCHARP.TO, len(mc.content), flavor='raw')
+    bytecode = lltype.malloc(rffi.UCHARP.TO, len(mc.content), flavor='raw',
+                             immortal=True)
     for i in range(len(mc.content)):
         assert 0 <= mc.content[i] <= 255
         bytecode[i] = rffi.cast(rffi.UCHAR, mc.content[i])
@@ -115,7 +116,8 @@
         assert withfloats
         value = random.random() - 0.5
         # make sure it fits into 64 bits
-        tmp = lltype.malloc(rffi.LONGP.TO, 2, flavor='raw')
+        tmp = lltype.malloc(rffi.LONGP.TO, 2, flavor='raw',
+                            track_allocation=False)
         rffi.cast(rffi.DOUBLEP, tmp)[0] = value
         return rffi.cast(rffi.DOUBLEP, tmp)[0], tmp[0], tmp[1]
 
@@ -152,10 +154,12 @@
 
     # prepare the expected target arrays, the descr_bytecode,
     # the 'registers' and the 'stack' arrays according to 'content'
-    xmmregisters = lltype.malloc(rffi.LONGP.TO, 16+ACTUAL_CPU.NUM_REGS+1, flavor='raw')
+    xmmregisters = lltype.malloc(rffi.LONGP.TO, 16+ACTUAL_CPU.NUM_REGS+1,
+                                 flavor='raw', immortal=True)
     registers = rffi.ptradd(xmmregisters, 16)
     stacklen = baseloc + 10
-    stack = lltype.malloc(rffi.LONGP.TO, stacklen, flavor='raw')
+    stack = lltype.malloc(rffi.LONGP.TO, stacklen, flavor='raw',
+                          immortal=True)
     expected_ints = [0] * len(content)
     expected_ptrs = [lltype.nullptr(llmemory.GCREF.TO)] * len(content)
     expected_floats = [0.0] * len(content)
@@ -221,7 +225,7 @@
     descr_bytecode.append(0x00)
     descr_bytecode.append(0xCC)   # end marker
     descr_bytes = lltype.malloc(rffi.UCHARP.TO, len(descr_bytecode),
-                                flavor='raw')
+                                flavor='raw', immortal=True)
     for i in range(len(descr_bytecode)):
         assert 0 <= descr_bytecode[i] <= 255
         descr_bytes[i] = rffi.cast(rffi.UCHAR, descr_bytecode[i])

Modified: pypy/branch/jit-unroll-loops/pypy/jit/backend/x86/test/test_gc_integration.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/jit/backend/x86/test/test_gc_integration.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/jit/backend/x86/test/test_gc_integration.py	Sat Oct 30 16:41:17 2010
@@ -12,7 +12,7 @@
 from pypy.jit.backend.detect_cpu import getcpuclass
 from pypy.jit.backend.x86.regalloc import RegAlloc
 from pypy.jit.backend.x86.arch import WORD, FRAME_FIXED_SIZE
-from pypy.jit.metainterp.test.oparser import parse
+from pypy.jit.tool.oparser import parse
 from pypy.rpython.lltypesystem import lltype, llmemory, rffi
 from pypy.rpython.annlowlevel import llhelper
 from pypy.rpython.lltypesystem import rclass, rstr

Modified: pypy/branch/jit-unroll-loops/pypy/jit/backend/x86/test/test_regalloc.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/jit/backend/x86/test/test_regalloc.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/jit/backend/x86/test/test_regalloc.py	Sat Oct 30 16:41:17 2010
@@ -11,7 +11,7 @@
 from pypy.jit.backend.x86.regalloc import RegAlloc, X86RegisterManager,\
      FloatConstants, is_comparison_or_ovf_op
 from pypy.jit.backend.x86.arch import IS_X86_32, IS_X86_64
-from pypy.jit.metainterp.test.oparser import parse
+from pypy.jit.tool.oparser import parse
 from pypy.rpython.lltypesystem import lltype, llmemory, rffi
 from pypy.rpython.annlowlevel import llhelper
 from pypy.rpython.lltypesystem import rclass, rstr

Modified: pypy/branch/jit-unroll-loops/pypy/jit/backend/x86/test/test_runner.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/jit/backend/x86/test/test_runner.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/jit/backend/x86/test/test_runner.py	Sat Oct 30 16:41:17 2010
@@ -10,7 +10,7 @@
 from pypy.jit.metainterp.resoperation import rop
 from pypy.jit.metainterp.executor import execute
 from pypy.jit.backend.test.runner_test import LLtypeBackendTest
-from pypy.jit.metainterp.test.oparser import parse
+from pypy.jit.tool.oparser import parse
 from pypy.tool.udir import udir
 import ctypes
 import sys
@@ -506,8 +506,8 @@
         self.cpu.execute_token(ops.token)
         # check debugging info
         name, struct = self.cpu.assembler.loop_run_counters[0]
-        assert name == 'xyz'
+        assert name == 0       # 'xyz'
         assert struct.i == 10
         self.cpu.finish_once()
         lines = py.path.local(self.logfile + ".count").readlines()
-        assert lines[0] == '10      xyz\n'
+        assert lines[0] == '0:10\n'  # '10      xyz\n'

Modified: pypy/branch/jit-unroll-loops/pypy/jit/backend/x86/test/test_string.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/jit/backend/x86/test/test_string.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/jit/backend/x86/test/test_string.py	Sat Oct 30 16:41:17 2010
@@ -2,8 +2,12 @@
 from pypy.jit.metainterp.test import test_string
 from pypy.jit.backend.x86.test.test_basic import Jit386Mixin
 
-class TestString(Jit386Mixin, test_string.StringTests):
+class TestString(Jit386Mixin, test_string.TestLLtype):
     # for the individual tests see
     # ====> ../../../metainterp/test/test_string.py
-    CALL = 'call'
-    CALL_PURE = 'call_pure'
+    pass
+
+class TestUnicode(Jit386Mixin, test_string.TestLLtypeUnicode):
+    # for the individual tests see
+    # ====> ../../../metainterp/test/test_string.py
+    pass

Modified: pypy/branch/jit-unroll-loops/pypy/jit/backend/x86/test/test_zrpy_gc.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/jit/backend/x86/test/test_zrpy_gc.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/jit/backend/x86/test/test_zrpy_gc.py	Sat Oct 30 16:41:17 2010
@@ -191,6 +191,33 @@
     def run_orig(self, name, n, x):
         self.main_allfuncs(name, n, x)
 
+    def define_libffi_workaround(cls):
+        # XXX: this is a workaround for a bug in database.py.  It seems that
+        # the problem is triggered by optimizeopt/fficall.py, and in
+        # particular by the ``cast_base_ptr_to_instance(Func, llfunc)``: in
+        # these tests, that line is the only place where libffi.Func is
+        # referenced.
+        #
+        # The problem occurs because the gctransformer tries to annotate a
+        # low-level helper to call the __del__ of libffi.Func when it's too
+        # late.
+        #
+        # This workaround works by forcing the annotator (and all the rest of
+        # the toolchain) to see libffi.Func in a "proper" context, not just as
+        # the target of cast_base_ptr_to_instance.  Note that the function
+        # below is *never* called by any actual test, it's just annotated.
+        #
+        from pypy.rlib.libffi import get_libc_name, CDLL, types, ArgChain
+        libc_name = get_libc_name()
+        def f(n, x, *args):
+            libc = CDLL(libc_name)
+            ptr = libc.getpointer('labs', [types.slong], types.slong)
+            chain = ArgChain()
+            chain.arg(n)
+            n = ptr.call(chain, lltype.Signed)
+            return (n, x) + args
+        return None, f, None
+
     def define_compile_framework_1(cls):
         # a moving GC.  Supports malloc_varsize_nonmovable.  Simple test, works
         # without write_barriers and root stack enumeration.

Modified: pypy/branch/jit-unroll-loops/pypy/jit/backend/x86/test/test_ztranslation.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/jit/backend/x86/test/test_ztranslation.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/jit/backend/x86/test/test_ztranslation.py	Sat Oct 30 16:41:17 2010
@@ -1,4 +1,4 @@
-import py, os
+import py, os, sys
 from pypy.tool.udir import udir
 from pypy.rlib.jit import JitDriver, OPTIMIZER_FULL, unroll_parameters
 from pypy.rlib.jit import PARAMETERS, dont_look_inside
@@ -63,8 +63,32 @@
                 if k - abs(j):  raise ValueError
                 if k - abs(-j): raise ValueError
             return total * 10
+        #
+        from pypy.rpython.lltypesystem import lltype, rffi
+        from pypy.rlib.libffi import types, CDLL, ArgChain
+        from pypy.rlib.test.test_libffi import get_libm_name
+        libm_name = get_libm_name(sys.platform)
+        jitdriver2 = JitDriver(greens=[], reds = ['i', 'func', 'res', 'x'])
+        def libffi_stuff(i, j):
+            lib = CDLL(libm_name)
+            func = lib.getpointer('fabs', [types.double], types.double)
+            res = 0.0
+            x = float(j)
+            while i > 0:
+                jitdriver2.jit_merge_point(i=i, res=res, func=func, x=x)
+                jitdriver2.can_enter_jit(i=i, res=res, func=func, x=x)
+                func = hint(func, promote=True)
+                argchain = ArgChain()
+                argchain.arg(x)
+                res = func.call(argchain, rffi.DOUBLE)
+                i -= 1
+            return res
+        #
+        def main(i, j):
+            return f(i, j) + libffi_stuff(i, j)
+        expected = f(40, -49)
         res = self.meta_interp(f, [40, -49])
-        assert res == f(40, -49)
+        assert res == expected
 
     def test_direct_assembler_call_translates(self):
         class Thing(object):

Modified: pypy/branch/jit-unroll-loops/pypy/jit/codewriter/call.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/jit/codewriter/call.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/jit/codewriter/call.py	Sat Oct 30 16:41:17 2010
@@ -277,3 +277,11 @@
             return seen.pop()
         else:
             return None
+
+    def could_be_green_field(self, GTYPE, fieldname):
+        GTYPE_fieldname = (GTYPE, fieldname)
+        for jd in self.jitdrivers_sd:
+            if jd.greenfield_info is not None:
+                if GTYPE_fieldname in jd.greenfield_info.green_fields:
+                    return True
+        return False

Modified: pypy/branch/jit-unroll-loops/pypy/jit/codewriter/codewriter.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/jit/codewriter/codewriter.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/jit/codewriter/codewriter.py	Sat Oct 30 16:41:17 2010
@@ -95,18 +95,18 @@
             print '%s:' % (ssarepr.name,)
             print format_assembler(ssarepr)
         else:
-            dir = udir.ensure("jitcodes", dir=1)
-            if portal_jitdriver:
-                name = "%02d_portal_runner" % (portal_jitdriver.index,)
-            elif ssarepr.name and ssarepr.name != '?':
-                name = ssarepr.name
-            else:
-                name = 'unnamed' % id(ssarepr)
-            i = 1
-            extra = ''
-            while name+extra in self._seen_files:
-                i += 1
-                extra = '.%d' % i
-            self._seen_files.add(name+extra)
-            dir.join(name+extra).write(format_assembler(ssarepr))
             log.dot()
+        dir = udir.ensure("jitcodes", dir=1)
+        if portal_jitdriver:
+            name = "%02d_portal_runner" % (portal_jitdriver.index,)
+        elif ssarepr.name and ssarepr.name != '?':
+            name = ssarepr.name
+        else:
+            name = 'unnamed' % id(ssarepr)
+        i = 1
+        extra = ''
+        while name+extra in self._seen_files:
+            i += 1
+            extra = '.%d' % i
+        self._seen_files.add(name+extra)
+        dir.join(name+extra).write(format_assembler(ssarepr))

Modified: pypy/branch/jit-unroll-loops/pypy/jit/codewriter/effectinfo.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/jit/codewriter/effectinfo.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/jit/codewriter/effectinfo.py	Sat Oct 30 16:41:17 2010
@@ -18,19 +18,34 @@
     # the 'oopspecindex' field is one of the following values:
     OS_NONE                     = 0    # normal case, no oopspec
     OS_ARRAYCOPY                = 1    # "list.ll_arraycopy"
-    OS_STR_CONCAT               = 2    # "stroruni.concat"
-    OS_UNI_CONCAT               = 3    # "stroruni.concat"
-    OS_STR_SLICE                = 4    # "stroruni.slice"
-    OS_UNI_SLICE                = 5    # "stroruni.slice"
-    OS_STR_EQUAL                = 6    # "stroruni.equal"
-    OS_UNI_EQUAL                = 7    # "stroruni.equal"
-    OS_STREQ_SLICE_CHECKNULL    = 8    # s2!=NULL and s1[x:x+length]==s2
-    OS_STREQ_SLICE_NONNULL      = 9    # s1[x:x+length]==s2   (assert s2!=NULL)
-    OS_STREQ_SLICE_CHAR         = 10   # s1[x:x+length]==char
-    OS_STREQ_NONNULL            = 11   # s1 == s2    (assert s1!=NULL,s2!=NULL)
-    OS_STREQ_NONNULL_CHAR       = 12   # s1 == char  (assert s1!=NULL)
-    OS_STREQ_CHECKNULL_CHAR     = 13   # s1!=NULL and s1==char
-    OS_STREQ_LENGTHOK           = 14   # s1 == s2    (assert len(s1)==len(s2))
+    OS_STR2UNICODE              = 2    # "str.str2unicode"
+    #
+    OS_STR_CONCAT               = 22   # "stroruni.concat"
+    OS_STR_SLICE                = 23   # "stroruni.slice"
+    OS_STR_EQUAL                = 24   # "stroruni.equal"
+    OS_STREQ_SLICE_CHECKNULL    = 25   # s2!=NULL and s1[x:x+length]==s2
+    OS_STREQ_SLICE_NONNULL      = 26   # s1[x:x+length]==s2   (assert s2!=NULL)
+    OS_STREQ_SLICE_CHAR         = 27   # s1[x:x+length]==char
+    OS_STREQ_NONNULL            = 28   # s1 == s2    (assert s1!=NULL,s2!=NULL)
+    OS_STREQ_NONNULL_CHAR       = 29   # s1 == char  (assert s1!=NULL)
+    OS_STREQ_CHECKNULL_CHAR     = 30   # s1!=NULL and s1==char
+    OS_STREQ_LENGTHOK           = 31   # s1 == s2    (assert len(s1)==len(s2))
+    #
+    OS_UNI_CONCAT               = 42   #
+    OS_UNI_SLICE                = 43   #
+    OS_UNI_EQUAL                = 44   #
+    OS_UNIEQ_SLICE_CHECKNULL    = 45   #
+    OS_UNIEQ_SLICE_NONNULL      = 46   #
+    OS_UNIEQ_SLICE_CHAR         = 47   #
+    OS_UNIEQ_NONNULL            = 48   #   the same for unicode
+    OS_UNIEQ_NONNULL_CHAR       = 49   #   (must be the same amount as for
+    OS_UNIEQ_CHECKNULL_CHAR     = 50   #   STR, in the same order)
+    OS_UNIEQ_LENGTHOK           = 51   #
+    _OS_offset_uni              = OS_UNI_CONCAT - OS_STR_CONCAT
+    #
+    OS_LIBFFI_PREPARE           = 60
+    OS_LIBFFI_PUSH_ARG          = 61
+    OS_LIBFFI_CALL              = 62
 
     def __new__(cls, readonly_descrs_fields,
                 write_descrs_fields, write_descrs_arrays,

Modified: pypy/branch/jit-unroll-loops/pypy/jit/codewriter/format.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/jit/codewriter/format.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/jit/codewriter/format.py	Sat Oct 30 16:41:17 2010
@@ -80,7 +80,8 @@
 
 def assert_format(ssarepr, expected):
     asm = format_assembler(ssarepr)
-    expected = str(py.code.Source(expected)).strip() + '\n'
+    if expected != '':
+        expected = str(py.code.Source(expected)).strip() + '\n'
     asmlines = asm.split("\n")
     explines = expected.split("\n")
     for asm, exp in zip(asmlines, explines):

Modified: pypy/branch/jit-unroll-loops/pypy/jit/codewriter/jtransform.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/jit/codewriter/jtransform.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/jit/codewriter/jtransform.py	Sat Oct 30 16:41:17 2010
@@ -172,6 +172,7 @@
 
     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_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
@@ -316,8 +317,14 @@
             prepare = self._handle_list_call
         elif oopspec_name.startswith('stroruni.'):
             prepare = self._handle_stroruni_call
+        elif oopspec_name == 'str.str2unicode':
+            prepare = self._handle_str2unicode_call
         elif oopspec_name.startswith('virtual_ref'):
             prepare = self._handle_virtual_ref_call
+        elif oopspec_name.startswith('jit.'):
+            prepare = self._handle_jit_call
+        elif oopspec_name.startswith('libffi_'):
+            prepare = self._handle_libffi_call
         else:
             prepare = self.prepare_builtin_call
         try:
@@ -427,7 +434,8 @@
                                   op.result)
 
     def rewrite_op_free(self, op):
-        assert op.args[1].value == 'raw'
+        flags = op.args[1].value
+        assert flags['flavor'] == 'raw'
         ARRAY = op.args[0].concretetype.TO
         return self._do_builtin_call(op, 'raw_free', [op.args[0]],
                                      extra = (ARRAY,), extrakey = ARRAY)
@@ -519,7 +527,12 @@
         # check for deepfrozen structures that force constant-folding
         immut = v_inst.concretetype.TO._immutable_field(c_fieldname.value)
         if immut:
-            pure = '_pure'
+            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:
@@ -819,6 +832,8 @@
     def rewrite_op_jit_marker(self, op):
         key = op.args[0].value
         jitdriver = op.args[1].value
+        if not jitdriver.active:
+            return []
         return getattr(self, 'handle_jit_marker__%s' % key)(op, jitdriver)
 
     def handle_jit_marker__jit_merge_point(self, op, jitdriver):
@@ -852,6 +867,15 @@
                     (self.graph,))
         return []
 
+    def _handle_jit_call(self, op, oopspec_name, args):
+        if oopspec_name == 'jit.debug':
+            return SpaceOperation('jit_debug', args, None)
+        elif oopspec_name == 'jit.assert_green':
+            kind = getkind(args[0].concretetype)
+            return SpaceOperation('%s_assert_green' % kind, args, None)
+        else:
+            raise AssertionError("missing support for %r" % oopspec_name)
+
     # ----------
     # Lists.
 
@@ -870,17 +894,21 @@
             prefix = 'do_resizable_'
             ARRAY = LIST.items.TO
             if self._array_of_voids(ARRAY):
-                raise NotSupported("resizable lists of voids")
-            descrs = (self.cpu.arraydescrof(ARRAY),
-                      self.cpu.fielddescrof(LIST, 'length'),
-                      self.cpu.fielddescrof(LIST, 'items'),
-                      self.cpu.sizeof(LIST))
+                prefix += 'void_'
+                descrs = ()
+            else:
+                descrs = (self.cpu.arraydescrof(ARRAY),
+                          self.cpu.fielddescrof(LIST, 'length'),
+                          self.cpu.fielddescrof(LIST, 'items'),
+                          self.cpu.sizeof(LIST))
         else:
             prefix = 'do_fixed_'
             if self._array_of_voids(LIST):
-                raise NotSupported("fixed lists of voids")
-            arraydescr = self.cpu.arraydescrof(LIST)
-            descrs = (arraydescr,)
+                prefix += 'void_'
+                descrs = ()
+            else:
+                arraydescr = self.cpu.arraydescrof(LIST)
+                descrs = (arraydescr,)
         #
         try:
             meth = getattr(self, prefix + oopspec_name.replace('.', '_'))
@@ -919,6 +947,11 @@
                                              descr, args[1]], v_posindex)
             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")
+
     def _get_initial_newlist_length(self, op, args):
         # normalize number of arguments to the 'newlist' function
         if len(args) > 1:
@@ -990,6 +1023,12 @@
     def do_fixed_list_ll_arraycopy(self, op, args, arraydescr):
         return self._handle_oopspec_call(op, args, EffectInfo.OS_ARRAYCOPY)
 
+    def do_fixed_void_list_getitem(self, op, args):
+        self._prepare_void_list_getset(op)
+        return []
+    do_fixed_void_list_getitem_foldable = do_fixed_void_list_getitem
+    do_fixed_void_list_setitem = do_fixed_void_list_getitem
+
     # ---------- resizable lists ----------
 
     def do_resizable_newlist(self, op, args, arraydescr, lengthdescr,
@@ -1025,11 +1064,19 @@
         return SpaceOperation('getfield_gc_i',
                               [args[0], lengthdescr], op.result)
 
+    def do_resizable_void_list_getitem(self, op, args):
+        self._prepare_void_list_getset(op)
+        return []
+    do_resizable_void_list_getitem_foldable = do_resizable_void_list_getitem
+    do_resizable_void_list_setitem = do_resizable_void_list_getitem
+
     # ----------
     # Strings and Unicodes.
 
-    def _handle_oopspec_call(self, op, args, oopspecindex):
+    def _handle_oopspec_call(self, op, args, oopspecindex, extraeffect=None):
         calldescr = self.callcontrol.getcalldescr(op, oopspecindex)
+        if extraeffect:
+            calldescr.get_extra_info().extraeffect = extraeffect
         if isinstance(op.args[0].value, str):
             pass  # for tests only
         else:
@@ -1055,28 +1102,32 @@
                             [c_func] + [varoftype(T) for T in argtypes],
                             varoftype(resulttype))
         calldescr = self.callcontrol.getcalldescr(op, oopspecindex)
-        func = heaptracker.adr2int(
-            llmemory.cast_ptr_to_adr(c_func.value))
+        if isinstance(c_func.value, str):    # in tests only
+            func = c_func.value
+        else:
+            func = heaptracker.adr2int(
+                llmemory.cast_ptr_to_adr(c_func.value))
         _callinfo_for_oopspec[oopspecindex] = calldescr, func
 
     def _handle_stroruni_call(self, op, oopspec_name, args):
-        if args[0].concretetype.TO == rstr.STR:
+        SoU = args[0].concretetype     # Ptr(STR) or Ptr(UNICODE)
+        if SoU.TO == rstr.STR:
             dict = {"stroruni.concat": EffectInfo.OS_STR_CONCAT,
                     "stroruni.slice":  EffectInfo.OS_STR_SLICE,
                     "stroruni.equal":  EffectInfo.OS_STR_EQUAL,
                     }
-        elif args[0].concretetype.TO == rstr.UNICODE:
+            CHR = lltype.Char
+        elif SoU.TO == rstr.UNICODE:
             dict = {"stroruni.concat": EffectInfo.OS_UNI_CONCAT,
                     "stroruni.slice":  EffectInfo.OS_UNI_SLICE,
                     "stroruni.equal":  EffectInfo.OS_UNI_EQUAL,
                     }
+            CHR = lltype.UniChar
         else:
             assert 0, "args[0].concretetype must be STR or UNICODE"
         #
         if oopspec_name == "stroruni.equal":
-            SoU = args[0].concretetype     # Ptr(STR) or Ptr(UNICODE)
             for otherindex, othername, argtypes, resulttype in [
-
                 (EffectInfo.OS_STREQ_SLICE_CHECKNULL,
                      "str.eq_slice_checknull",
                      [SoU, lltype.Signed, lltype.Signed, SoU],
@@ -1087,7 +1138,7 @@
                      lltype.Signed),
                 (EffectInfo.OS_STREQ_SLICE_CHAR,
                      "str.eq_slice_char",
-                     [SoU, lltype.Signed, lltype.Signed, lltype.Char],
+                     [SoU, lltype.Signed, lltype.Signed, CHR],
                      lltype.Signed),
                 (EffectInfo.OS_STREQ_NONNULL,
                      "str.eq_nonnull",
@@ -1095,22 +1146,27 @@
                      lltype.Signed),
                 (EffectInfo.OS_STREQ_NONNULL_CHAR,
                      "str.eq_nonnull_char",
-                     [SoU, lltype.Char],
+                     [SoU, CHR],
                      lltype.Signed),
                 (EffectInfo.OS_STREQ_CHECKNULL_CHAR,
                      "str.eq_checknull_char",
-                     [SoU, lltype.Char],
+                     [SoU, CHR],
                      lltype.Signed),
                 (EffectInfo.OS_STREQ_LENGTHOK,
                      "str.eq_lengthok",
                      [SoU, SoU],
                      lltype.Signed),
                 ]:
+                if args[0].concretetype.TO == rstr.UNICODE:
+                    otherindex += EffectInfo._OS_offset_uni
                 self._register_extra_helper(otherindex, othername,
                                             argtypes, resulttype)
         #
         return self._handle_oopspec_call(op, args, dict[oopspec_name])
 
+    def _handle_str2unicode_call(self, op, oopspec_name, args):
+        return self._handle_oopspec_call(op, args, EffectInfo.OS_STR2UNICODE)
+
     # ----------
     # VirtualRefs.
 
@@ -1121,6 +1177,23 @@
                                           vrefinfo.JIT_VIRTUAL_REF)
         return SpaceOperation(oopspec_name, list(args), op.result)
 
+    # -----------
+    # rlib.libffi
+
+    def _handle_libffi_call(self, op, oopspec_name, args):
+        if oopspec_name == 'libffi_prepare_call':
+            oopspecindex = EffectInfo.OS_LIBFFI_PREPARE
+            extraeffect = EffectInfo.EF_CANNOT_RAISE
+        elif oopspec_name.startswith('libffi_push_'):
+            oopspecindex = EffectInfo.OS_LIBFFI_PUSH_ARG
+            extraeffect = EffectInfo.EF_CANNOT_RAISE
+        elif oopspec_name.startswith('libffi_call_'):
+            oopspecindex = EffectInfo.OS_LIBFFI_CALL
+            extraeffect = EffectInfo.EF_FORCES_VIRTUAL_OR_VIRTUALIZABLE
+        else:
+            assert False, 'unsupported oopspec: %s' % oopspec_name
+        return self._handle_oopspec_call(op, args, oopspecindex, extraeffect)
+
     def rewrite_op_jit_force_virtual(self, op):
         return self._do_builtin_call(op)
 

Modified: pypy/branch/jit-unroll-loops/pypy/jit/codewriter/support.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/jit/codewriter/support.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/jit/codewriter/support.py	Sat Oct 30 16:41:17 2010
@@ -1,5 +1,5 @@
 import sys
-from pypy.rpython.lltypesystem import lltype, rclass
+from pypy.rpython.lltypesystem import lltype, rclass, rffi
 from pypy.rpython.ootypesystem import ootype
 from pypy.rpython import rlist
 from pypy.rpython.lltypesystem import rstr as ll_rstr, rdict as ll_rdict
@@ -8,6 +8,7 @@
 from pypy.rpython.ootypesystem import rdict as oo_rdict
 from pypy.rpython.llinterp import LLInterpreter
 from pypy.rpython.extregistry import ExtRegistryEntry
+from pypy.rpython.annlowlevel import cast_base_ptr_to_instance
 from pypy.translator.simplify import get_funcobj
 from pypy.translator.unsimplify import split_block
 from pypy.objspace.flow.model import Constant
@@ -60,7 +61,7 @@
     return rtyper.annotator.translator.graphs[0]
 
 def split_before_jit_merge_point(graph, portalblock, portalopindex):
-    """Find the block with 'jit_merge_point' and split just before,
+    """Split the block just before the 'jit_merge_point',
     making sure the input args are in the canonical order.
     """
     # split the block just before the jit_merge_point()
@@ -217,6 +218,33 @@
     else:
         return x
 
+
+# libffi support
+# --------------
+
+def func(llfunc):
+    from pypy.rlib.libffi import Func
+    return cast_base_ptr_to_instance(Func, llfunc)
+
+def _ll_1_libffi_prepare_call(llfunc):
+    return func(llfunc)._prepare()
+
+def _ll_4_libffi_push_int(llfunc, value, ll_args, i):
+    return func(llfunc)._push_int(value, ll_args, i)
+
+def _ll_4_libffi_push_float(llfunc, value, ll_args, i):
+    return func(llfunc)._push_float(value, ll_args, i)
+
+def _ll_3_libffi_call_int(llfunc, funcsym, ll_args):
+    return func(llfunc)._do_call(funcsym, ll_args, rffi.LONG)
+
+def _ll_3_libffi_call_float(llfunc, funcsym, ll_args):
+    return func(llfunc)._do_call(funcsym, ll_args, rffi.DOUBLE)
+
+def _ll_3_libffi_call_void(llfunc, funcsym, ll_args):
+    return func(llfunc)._do_call(funcsym, ll_args, lltype.Void)
+
+
 # in the following calls to builtins, the JIT is allowed to look inside:
 inline_calls_to = [
     ('int_floordiv_ovf_zer', [lltype.Signed, lltype.Signed], lltype.Signed),

Modified: pypy/branch/jit-unroll-loops/pypy/jit/codewriter/test/test_codewriter.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/jit/codewriter/test/test_codewriter.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/jit/codewriter/test/test_codewriter.py	Sat Oct 30 16:41:17 2010
@@ -45,6 +45,7 @@
         self.portal_graph = portal_graph
         self.portal_runner_ptr = "???"
         self.virtualizable_info = None
+        self.greenfield_info = None
 
 
 def test_loop():

Modified: pypy/branch/jit-unroll-loops/pypy/jit/codewriter/test/test_effectinfo.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/jit/codewriter/test/test_effectinfo.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/jit/codewriter/test/test_effectinfo.py	Sat Oct 30 16:41:17 2010
@@ -1,7 +1,8 @@
 from pypy.rpython.lltypesystem.rclass import OBJECT
 from pypy.rpython.lltypesystem import lltype
 from pypy.rpython.ootypesystem import ootype
-from pypy.jit.codewriter.effectinfo import effectinfo_from_writeanalyze
+from pypy.jit.codewriter.effectinfo import effectinfo_from_writeanalyze,\
+    EffectInfo
 
 class FakeCPU:
     def fielddescrof(self, T, fieldname):
@@ -9,6 +10,14 @@
     def arraydescrof(self, A):
         return ('arraydescr', A)
 
+def test_no_oopspec_duplicate():
+    # check that all the various EffectInfo.OS_* have unique values
+    oopspecs = set()
+    for name, value in EffectInfo.__dict__.iteritems():
+        if name.startswith('OS_'):
+            assert value not in oopspecs
+            oopspecs.add(value)
+
 def test_include_read_field():
     S = lltype.GcStruct("S", ("a", lltype.Signed))
     effects = frozenset([("readstruct", lltype.Ptr(S), "a")])

Modified: pypy/branch/jit-unroll-loops/pypy/jit/codewriter/test/test_jtransform.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/jit/codewriter/test/test_jtransform.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/jit/codewriter/test/test_jtransform.py	Sat Oct 30 16:41:17 2010
@@ -77,7 +77,32 @@
 class FakeBuiltinCallControl:
     def guess_call_kind(self, op):
         return 'builtin'
-    def getcalldescr(self, op, oopspecindex):
+    def getcalldescr(self, op, oopspecindex=None):
+        assert oopspecindex is not None    # in this test
+        EI = effectinfo.EffectInfo
+        if oopspecindex != EI.OS_ARRAYCOPY:
+            PSTR = lltype.Ptr(rstr.STR)
+            PUNICODE = lltype.Ptr(rstr.UNICODE)
+            INT = lltype.Signed
+            UNICHAR = lltype.UniChar
+            argtypes = {
+             EI.OS_STR2UNICODE:([PSTR], PUNICODE),
+             EI.OS_STR_CONCAT: ([PSTR, PSTR], PSTR),
+             EI.OS_STR_SLICE:  ([PSTR, INT, INT], PSTR),
+             EI.OS_UNI_CONCAT: ([PUNICODE, PUNICODE], PUNICODE),
+             EI.OS_UNI_SLICE:  ([PUNICODE, INT, INT], PUNICODE),
+             EI.OS_UNI_EQUAL:  ([PUNICODE, PUNICODE], lltype.Bool),
+             EI.OS_UNIEQ_SLICE_CHECKNULL:([PUNICODE, INT, INT, PUNICODE], INT),
+             EI.OS_UNIEQ_SLICE_NONNULL:  ([PUNICODE, INT, INT, PUNICODE], INT),
+             EI.OS_UNIEQ_SLICE_CHAR:     ([PUNICODE, INT, INT, UNICHAR], INT),
+             EI.OS_UNIEQ_NONNULL:        ([PUNICODE, PUNICODE], INT),
+             EI.OS_UNIEQ_NONNULL_CHAR:   ([PUNICODE, UNICHAR], INT),
+             EI.OS_UNIEQ_CHECKNULL_CHAR: ([PUNICODE, UNICHAR], INT),
+             EI.OS_UNIEQ_LENGTHOK:       ([PUNICODE, PUNICODE], INT),
+            }
+            argtypes = argtypes[oopspecindex]
+            assert argtypes[0] == [v.concretetype for v in op.args[1:]]
+            assert argtypes[1] == op.result.concretetype
         return 'calldescr-%d' % oopspecindex
     def calldescr_canraise(self, calldescr):
         return False
@@ -662,6 +687,80 @@
     assert block.operations[1].result is None
     assert block.exits[0].args == [v1]
 
+def test_jit_merge_point_1():
+    class FakeJitDriverSD:
+        index = 42
+        class jitdriver:
+            active = True
+            greens = ['green1', 'green2', 'voidgreen3']
+            reds = ['red1', 'red2', 'voidred3']
+    jd = FakeJitDriverSD()
+    v1 = varoftype(lltype.Signed)
+    v2 = varoftype(lltype.Signed)
+    vvoid1 = varoftype(lltype.Void)
+    v3 = varoftype(lltype.Signed)
+    v4 = varoftype(lltype.Signed)
+    vvoid2 = varoftype(lltype.Void)
+    v5 = varoftype(lltype.Void)
+    op = SpaceOperation('jit_marker',
+                        [Constant('jit_merge_point', lltype.Void),
+                         Constant(jd.jitdriver, lltype.Void),
+                         v1, v2, vvoid1, v3, v4, vvoid2], v5)
+    tr = Transformer()
+    tr.portal_jd = jd
+    oplist = tr.rewrite_operation(op)
+    assert len(oplist) == 6
+    assert oplist[0].opname == '-live-'
+    assert oplist[1].opname == 'int_guard_value'
+    assert oplist[1].args   == [v1]
+    assert oplist[2].opname == '-live-'
+    assert oplist[3].opname == 'int_guard_value'
+    assert oplist[3].args   == [v2]
+    assert oplist[4].opname == 'jit_merge_point'
+    assert oplist[4].args[0].value == 42
+    assert list(oplist[4].args[1]) == [v1, v2]
+    assert list(oplist[4].args[4]) == [v3, v4]
+    assert oplist[5].opname == '-live-'
+
+def test_getfield_gc():
+    S = lltype.GcStruct('S', ('x', lltype.Char))
+    v1 = varoftype(lltype.Ptr(S))
+    v2 = varoftype(lltype.Char)
+    op = SpaceOperation('getfield', [v1, Constant('x', lltype.Void)], v2)
+    op1 = Transformer(FakeCPU()).rewrite_operation(op)
+    assert op1.opname == 'getfield_gc_i'
+    assert op1.args == [v1, ('fielddescr', S, 'x')]
+    assert op1.result == v2
+
+def test_getfield_gc_pure():
+    S = lltype.GcStruct('S', ('x', lltype.Char),
+                        hints={'immutable': True})
+    v1 = varoftype(lltype.Ptr(S))
+    v2 = varoftype(lltype.Char)
+    op = SpaceOperation('getfield', [v1, Constant('x', lltype.Void)], v2)
+    op1 = Transformer(FakeCPU()).rewrite_operation(op)
+    assert op1.opname == 'getfield_gc_i_pure'
+    assert op1.args == [v1, ('fielddescr', S, 'x')]
+    assert op1.result == v2
+
+def test_getfield_gc_greenfield():
+    class FakeCC:
+        def get_vinfo(self, v):
+            return None
+        def could_be_green_field(self, S1, name1):
+            assert S1 is S
+            assert name1 == 'x'
+            return True
+    S = lltype.GcStruct('S', ('x', lltype.Char),
+                        hints={'immutable': True})
+    v1 = varoftype(lltype.Ptr(S))
+    v2 = varoftype(lltype.Char)
+    op = SpaceOperation('getfield', [v1, Constant('x', lltype.Void)], v2)
+    op1 = Transformer(FakeCPU(), FakeCC()).rewrite_operation(op)
+    assert op1.opname == 'getfield_gc_i_greenfield'
+    assert op1.args == [v1, ('fielddescr', S, 'x')]
+    assert op1.result == v2
+
 def test_int_abs():
     v1 = varoftype(lltype.Signed)
     v2 = varoftype(lltype.Signed)
@@ -766,6 +865,46 @@
     assert op1.args[3] == ListOfKind('ref', [v1])
     assert op1.result == v4
 
+def test_str2unicode():
+    # test that the oopspec is present and correctly transformed
+    PSTR = lltype.Ptr(rstr.STR)
+    PUNICODE = lltype.Ptr(rstr.UNICODE)
+    FUNC = lltype.FuncType([PSTR], PUNICODE)
+    func = lltype.functionptr(FUNC, 'll_str2unicode',
+                            _callable=rstr.LLHelpers.ll_str2unicode)
+    v1 = varoftype(PSTR)
+    v2 = varoftype(PUNICODE)
+    op = SpaceOperation('direct_call', [const(func), v1], v2)
+    tr = Transformer(FakeCPU(), FakeBuiltinCallControl())
+    op1 = tr.rewrite_operation(op)
+    assert op1.opname == 'residual_call_r_r'
+    assert op1.args[0].value == func
+    assert op1.args[1] == 'calldescr-%d' % effectinfo.EffectInfo.OS_STR2UNICODE
+    assert op1.args[2] == ListOfKind('ref', [v1])
+    assert op1.result == v2
+
+def test_unicode_eq_checknull_char():
+    # test that the oopspec is present and correctly transformed
+    PUNICODE = lltype.Ptr(rstr.UNICODE)
+    FUNC = lltype.FuncType([PUNICODE, PUNICODE], lltype.Bool)
+    func = lltype.functionptr(FUNC, 'll_streq',
+                              _callable=rstr.LLHelpers.ll_streq)
+    v1 = varoftype(PUNICODE)
+    v2 = varoftype(PUNICODE)
+    v3 = varoftype(lltype.Bool)
+    op = SpaceOperation('direct_call', [const(func), v1, v2], v3)
+    tr = Transformer(FakeCPU(), FakeBuiltinCallControl())
+    op1 = tr.rewrite_operation(op)
+    assert op1.opname == 'residual_call_r_i'
+    assert op1.args[0].value == func
+    assert op1.args[1] == 'calldescr-%d' % effectinfo.EffectInfo.OS_UNI_EQUAL
+    assert op1.args[2] == ListOfKind('ref', [v1, v2])
+    assert op1.result == v3
+    # test that the OS_UNIEQ_* functions are registered
+    cifo = effectinfo._callinfo_for_oopspec
+    assert effectinfo.EffectInfo.OS_UNIEQ_SLICE_NONNULL in cifo
+    assert effectinfo.EffectInfo.OS_UNIEQ_CHECKNULL_CHAR in cifo
+
 def test_list_ll_arraycopy():
     from pypy.rlib.rgc import ll_arraycopy
     LIST = lltype.GcArray(lltype.Signed)

Modified: pypy/branch/jit-unroll-loops/pypy/jit/codewriter/test/test_list.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/jit/codewriter/test/test_list.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/jit/codewriter/test/test_list.py	Sat Oct 30 16:41:17 2010
@@ -19,6 +19,7 @@
 class FakeCPU:
     class arraydescrof(AbstractDescr):
         def __init__(self, ARRAY):
+            assert ARRAY.OF != lltype.Void
             self.ARRAY = ARRAY
         def __repr__(self):
             return '<ArrayDescr>'

Modified: pypy/branch/jit-unroll-loops/pypy/jit/metainterp/blackhole.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/jit/metainterp/blackhole.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/jit/metainterp/blackhole.py	Sat Oct 30 16:41:17 2010
@@ -760,6 +760,20 @@
     def bhimpl_debug_fatalerror(msg):
         llop.debug_fatalerror(lltype.Void, msg)
 
+    @arguments("r", "i", "i", "i", "i")
+    def bhimpl_jit_debug(string, arg1=0, arg2=0, arg3=0, arg4=0):
+        pass
+
+    @arguments("i")
+    def bhimpl_int_assert_green(x):
+        pass
+    @arguments("r")
+    def bhimpl_ref_assert_green(x):
+        pass
+    @arguments("f")
+    def bhimpl_float_assert_green(x):
+        pass
+
     # ----------
     # the main hints and recursive calls
 
@@ -1073,6 +1087,10 @@
     bhimpl_getfield_vable_r = bhimpl_getfield_gc_r
     bhimpl_getfield_vable_f = bhimpl_getfield_gc_f
 
+    bhimpl_getfield_gc_i_greenfield = bhimpl_getfield_gc_i
+    bhimpl_getfield_gc_r_greenfield = bhimpl_getfield_gc_r
+    bhimpl_getfield_gc_f_greenfield = bhimpl_getfield_gc_f
+
     @arguments("cpu", "i", "d", returns="i")
     def bhimpl_getfield_raw_i(cpu, struct, fielddescr):
         return cpu.bh_getfield_raw_i(struct, fielddescr)

Modified: pypy/branch/jit-unroll-loops/pypy/jit/metainterp/compile.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/jit/metainterp/compile.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/jit/metainterp/compile.py	Sat Oct 30 16:41:17 2010
@@ -140,7 +140,6 @@
     if not we_are_translated():
         show_loop(metainterp_sd)
         TreeLoop.check_consistency_of(inputargs, operations)
-        pass
     metainterp_sd.profiler.start_backend()
     debug_start("jit-backend")
     try:
@@ -387,7 +386,8 @@
         from pypy.jit.metainterp.resume import force_from_resumedata
         metainterp_sd = self.metainterp_sd
         vinfo = self.jitdriver_sd.virtualizable_info
-        all_virtuals = force_from_resumedata(metainterp_sd, self, vinfo)
+        ginfo = self.jitdriver_sd.greenfield_info
+        all_virtuals = force_from_resumedata(metainterp_sd, self, vinfo, ginfo)
         # The virtualizable data was stored on the real virtualizable above.
         # Handle all_virtuals: keep them for later blackholing from the
         # future failure of the GUARD_NOT_FORCED
@@ -616,5 +616,5 @@
         ResOperation(rop.FINISH, finishargs, None, descr=jd.portal_finishtoken)
         ]
     operations[1].setfailargs([])
-    cpu.compile_loop(inputargs, operations, loop_token)
+    cpu.compile_loop(inputargs, operations, loop_token, log=False)
     return loop_token

Modified: pypy/branch/jit-unroll-loops/pypy/jit/metainterp/executor.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/jit/metainterp/executor.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/jit/metainterp/executor.py	Sat Oct 30 16:41:17 2010
@@ -80,6 +80,9 @@
 do_call_loopinvariant = do_call
 do_call_may_force = do_call
 
+def do_call_c(cpu, metainterp, argboxes, descr):
+    raise NotImplementedError("Should never be called directly")
+
 def do_getarrayitem_gc(cpu, _, arraybox, indexbox, arraydescr):
     array = arraybox.getref_base()
     index = indexbox.getint()
@@ -205,8 +208,8 @@
 
 def do_copystrcontent(cpu, _, srcbox, dstbox,
                       srcstartbox, dststartbox, lengthbox):
-    src = srcbox.getptr(lltype.Ptr(rstr.STR))
-    dst = dstbox.getptr(lltype.Ptr(rstr.STR))
+    src = srcbox.getref(lltype.Ptr(rstr.STR))
+    dst = dstbox.getref(lltype.Ptr(rstr.STR))
     srcstart = srcstartbox.getint()
     dststart = dststartbox.getint()
     length = lengthbox.getint()
@@ -214,8 +217,8 @@
 
 def do_copyunicodecontent(cpu, _, srcbox, dstbox,
                           srcstartbox, dststartbox, lengthbox):
-    src = srcbox.getptr(lltype.Ptr(rstr.UNICODE))
-    dst = dstbox.getptr(lltype.Ptr(rstr.UNICODE))
+    src = srcbox.getref(lltype.Ptr(rstr.UNICODE))
+    dst = dstbox.getref(lltype.Ptr(rstr.UNICODE))
     srcstart = srcstartbox.getint()
     dststart = dststartbox.getint()
     length = lengthbox.getint()
@@ -304,6 +307,7 @@
                          rop.CALL_ASSEMBLER,
                          rop.COND_CALL_GC_WB,
                          rop.DEBUG_MERGE_POINT,
+                         rop.JIT_DEBUG,
                          rop.SETARRAYITEM_RAW,
                          ):      # list of opcodes never executed by pyjitpl
                 continue
@@ -428,6 +432,10 @@
         if arity == 3:
             func = get_execute_funclist(3, False)[opnum]
             return func(cpu, metainterp, argboxes[0], argboxes[1], argboxes[2])
+        if arity == 5:    # copystrcontent, copyunicodecontent
+            func = get_execute_funclist(5, False)[opnum]
+            return func(cpu, metainterp, argboxes[0], argboxes[1],
+                        argboxes[2], argboxes[3], argboxes[4])
     raise NotImplementedError
 
 

Modified: pypy/branch/jit-unroll-loops/pypy/jit/metainterp/graphpage.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/jit/metainterp/graphpage.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/jit/metainterp/graphpage.py	Sat Oct 30 16:41:17 2010
@@ -153,7 +153,7 @@
         opindex = opstartindex
         while True:
             op = operations[opindex]
-            lines.append(repr(op))
+            lines.append(op.repr(graytext=True))
             if is_interesting_guard(op):
                 tgt = op.getdescr()._debug_suboperations[0]
                 tgt_g, tgt_i = self.all_operations[tgt]

Modified: pypy/branch/jit-unroll-loops/pypy/jit/metainterp/history.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/jit/metainterp/history.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/jit/metainterp/history.py	Sat Oct 30 16:41:17 2010
@@ -698,6 +698,21 @@
     return result
 _const_ptr_for_string = {}
 
+def get_const_ptr_for_unicode(s):
+    from pypy.rpython.annlowlevel import llunicode
+    if not we_are_translated():
+        try:
+            return _const_ptr_for_unicode[s]
+        except KeyError:
+            pass
+    if isinstance(s, str):
+        s = unicode(s)
+    result = ConstPtr(lltype.cast_opaque_ptr(llmemory.GCREF, llunicode(s)))
+    if not we_are_translated():
+        _const_ptr_for_unicode[s] = result
+    return result
+_const_ptr_for_unicode = {}
+
 # ____________________________________________________________
 
 # The TreeLoop class contains a loop or a generalized loop, i.e. a tree

Modified: pypy/branch/jit-unroll-loops/pypy/jit/metainterp/jitdriver.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/jit/metainterp/jitdriver.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/jit/metainterp/jitdriver.py	Sat Oct 30 16:41:17 2010
@@ -13,8 +13,10 @@
     #    self.num_red_args      ... pypy.jit.metainterp.warmspot
     #    self.result_type       ... pypy.jit.metainterp.warmspot
     #    self.virtualizable_info... pypy.jit.metainterp.warmspot
+    #    self.greenfield_info   ... pypy.jit.metainterp.warmspot
     #    self.warmstate         ... pypy.jit.metainterp.warmspot
     #    self.handle_jitexc_from_bh pypy.jit.metainterp.warmspot
+    #    self.no_loop_header    ... pypy.jit.metainterp.warmspot
     #    self.portal_finishtoken... pypy.jit.metainterp.pyjitpl
     #    self.index             ... pypy.jit.codewriter.call
     #    self.mainjitcode       ... pypy.jit.codewriter.call

Modified: pypy/branch/jit-unroll-loops/pypy/jit/metainterp/optimize_nopspec.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/jit/metainterp/optimize_nopspec.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/jit/metainterp/optimize_nopspec.py	Sat Oct 30 16:41:17 2010
@@ -14,6 +14,9 @@
 def _optimize_loop(metainterp_sd, old_loop_tokens, loop):
     cpu = metainterp_sd.cpu
     metainterp_sd.logger_noopt.log_loop(loop.inputargs, loop.operations)
+    # XXX the following lines are probably still needed, to discard invalid
+    # loops. bit silly to run a full perfect specialization and throw the
+    # result away.
     finder = PerfectSpecializationFinder(cpu)
     finder.find_nodes_loop(loop, False)
     if old_loop_tokens:
@@ -31,6 +34,7 @@
 def _optimize_bridge(metainterp_sd, old_loop_tokens, bridge):
     cpu = metainterp_sd.cpu    
     metainterp_sd.logger_noopt.log_loop(bridge.inputargs, bridge.operations)
+    # XXX same comment as above applies
     finder = BridgeSpecializationFinder(cpu)
     finder.find_nodes_bridge(bridge)
     if old_loop_tokens:

Modified: pypy/branch/jit-unroll-loops/pypy/jit/metainterp/optimizeopt/__init__.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/jit/metainterp/optimizeopt/__init__.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/jit/metainterp/optimizeopt/__init__.py	Sat Oct 30 16:41:17 2010
@@ -3,6 +3,7 @@
 from pypy.jit.metainterp.optimizeopt.intbounds import OptIntBounds
 from pypy.jit.metainterp.optimizeopt.virtualize import OptVirtualize
 from pypy.jit.metainterp.optimizeopt.heap import OptHeap
+from pypy.jit.metainterp.optimizeopt.fficall import OptFfiCall
 from pypy.jit.metainterp.optimizeopt.string import OptString
 from pypy.jit.metainterp.optimizeopt.unroll import OptUnroll
 
@@ -17,6 +18,7 @@
                      OptVirtualize(),
                      OptString(),
                      OptHeap(),
+                     OptFfiCall(),
                     ]
     if not_a_bridge:
         optimizations.insert(0, OptUnroll())

Modified: pypy/branch/jit-unroll-loops/pypy/jit/metainterp/optimizeopt/intbounds.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/jit/metainterp/optimizeopt/intbounds.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/jit/metainterp/optimizeopt/intbounds.py	Sat Oct 30 16:41:17 2010
@@ -205,6 +205,7 @@
         v1.intbound.make_ge(IntLowerBound(0))
 
     optimize_STRLEN = optimize_ARRAYLEN_GC
+    optimize_UNICODELEN = optimize_ARRAYLEN_GC
 
     def make_int_lt(self, box1, box2):
         v1 = self.getvalue(box1)

Modified: pypy/branch/jit-unroll-loops/pypy/jit/metainterp/optimizeopt/rewrite.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/jit/metainterp/optimizeopt/rewrite.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/jit/metainterp/optimizeopt/rewrite.py	Sat Oct 30 16:41:17 2010
@@ -3,6 +3,7 @@
 from pypy.jit.metainterp.history import ConstInt
 from pypy.jit.metainterp.optimizeutil import _findall
 from pypy.jit.metainterp.resoperation import rop, ResOperation
+from pypy.jit.codewriter.effectinfo import EffectInfo
 
 class OptRewrite(Optimization):
     """Rewrite operations into equivalent, cheaper operations.
@@ -244,11 +245,11 @@
         self.optimizer.exception_might_have_happened = False
 
     def optimize_CALL_LOOPINVARIANT(self, op):
-        funcvalue = self.getvalue(op.getarg(0))
-        if not funcvalue.is_constant():
-            self.emit_operation(op)
-            return
-        key = make_hashable_int(op.getarg(0).getint())
+        arg = op.getarg(0)
+        # 'arg' must be a Const, because residual_call in codewriter
+        # expects a compile-time constant
+        assert isinstance(arg, Const)
+        key = make_hashable_int(arg.getint())
         resvalue = self.optimizer.loop_invariant_results.get(key, None)
         if resvalue is not None:
             self.make_equal_to(op.result, resvalue)
@@ -324,8 +325,37 @@
 ##            return
 ##        self.emit_operation(op)
 
-optimize_ops = _findall(OptRewrite, 'optimize_')
-        
+    def optimize_CALL(self, op):
+        # dispatch based on 'oopspecindex' to a method that handles
+        # specifically the given oopspec call.  For non-oopspec calls,
+        # oopspecindex is just zero.
+        effectinfo = op.getdescr().get_extra_info()
+        if effectinfo is not None:
+            oopspecindex = effectinfo.oopspecindex
+            if oopspecindex == EffectInfo.OS_ARRAYCOPY:
+                if self._optimize_CALL_ARRAYCOPY(op):
+                    return
+        self.emit_operation(op)
 
+    def _optimize_CALL_ARRAYCOPY(self, op):
+        source_value = self.getvalue(op.getarg(1))
+        dest_value = self.getvalue(op.getarg(2))
+        source_start_box = self.get_constant_box(op.getarg(3))
+        dest_start_box = self.get_constant_box(op.getarg(4))
+        length = self.get_constant_box(op.getarg(5))
+        if (source_value.is_virtual() and source_start_box and dest_start_box
+            and length and dest_value.is_virtual()):
+            # XXX optimize the case where dest value is not virtual,
+            #     but we still can avoid a mess
+            source_start = source_start_box.getint()
+            dest_start = dest_start_box.getint()
+            for index in range(length.getint()):
+                val = source_value.getitem(index + source_start)
+                dest_value.setitem(index + dest_start, val)
+            return True
+        if length and length.getint() == 0:
+            return True # 0-length arraycopy
+        return False
+
+optimize_ops = _findall(OptRewrite, 'optimize_')
 
-        

Modified: pypy/branch/jit-unroll-loops/pypy/jit/metainterp/optimizeopt/string.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/jit/metainterp/optimizeopt/string.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/jit/metainterp/optimizeopt/string.py	Sat Oct 30 16:41:17 2010
@@ -3,6 +3,7 @@
 from pypy.jit.metainterp.history import Box, BoxInt, BoxPtr
 from pypy.jit.metainterp.history import Const, ConstInt, ConstPtr
 from pypy.jit.metainterp.history import get_const_ptr_for_string
+from pypy.jit.metainterp.history import get_const_ptr_for_unicode
 from pypy.jit.metainterp.resoperation import rop, ResOperation
 from pypy.jit.metainterp.optimizeopt import optimizer, virtualize
 from pypy.jit.metainterp.optimizeopt.optimizer import CONST_0, CONST_1
@@ -11,56 +12,106 @@
 from pypy.jit.codewriter.effectinfo import EffectInfo, callinfo_for_oopspec
 from pypy.jit.codewriter import heaptracker
 from pypy.rlib.unroll import unrolling_iterable
+from pypy.rlib.objectmodel import specialize, we_are_translated
+
+
+class StrOrUnicode(object):
+    def __init__(self, LLTYPE, hlstr, emptystr, chr,
+                 NEWSTR, STRLEN, STRGETITEM, STRSETITEM, COPYSTRCONTENT,
+                 OS_offset):
+        self.LLTYPE = LLTYPE
+        self.hlstr = hlstr
+        self.emptystr = emptystr
+        self.chr = chr
+        self.NEWSTR = NEWSTR
+        self.STRLEN = STRLEN
+        self.STRGETITEM = STRGETITEM
+        self.STRSETITEM = STRSETITEM
+        self.COPYSTRCONTENT = COPYSTRCONTENT
+        self.OS_offset = OS_offset
+
+    def _freeze_(self):
+        return True
+
+mode_string = StrOrUnicode(rstr.STR, annlowlevel.hlstr, '', chr,
+                           rop.NEWSTR, rop.STRLEN, rop.STRGETITEM,
+                           rop.STRSETITEM, rop.COPYSTRCONTENT, 0)
+mode_unicode = StrOrUnicode(rstr.UNICODE, annlowlevel.hlunicode, u'', unichr,
+                            rop.NEWUNICODE, rop.UNICODELEN, rop.UNICODEGETITEM,
+                            rop.UNICODESETITEM, rop.COPYUNICODECONTENT,
+                            EffectInfo._OS_offset_uni)
+
+# ____________________________________________________________
 
 
 class __extend__(optimizer.OptValue):
     """New methods added to the base class OptValue for this file."""
 
-    def getstrlen(self, newoperations):
-        s = self.get_constant_string()
-        if s is not None:
-            return ConstInt(len(s))
+    def getstrlen(self, newoperations, mode):
+        if mode is mode_string:
+            s = self.get_constant_string_spec(mode_string)
+            if s is not None:
+                return ConstInt(len(s))
         else:
-            if newoperations is None:
-                return None
-            self.ensure_nonnull()
-            box = self.force_box()
-            lengthbox = BoxInt()
-            newoperations.append(ResOperation(rop.STRLEN, [box], lengthbox))
-            return lengthbox
+            s = self.get_constant_string_spec(mode_unicode)
+            if s is not None:
+                return ConstInt(len(s))
+        if newoperations is None:
+            return None
+        self.ensure_nonnull()
+        box = self.force_box()
+        lengthbox = BoxInt()
+        newoperations.append(ResOperation(mode.STRLEN, [box], lengthbox))
+        return lengthbox
 
-    def get_constant_string(self):
+    @specialize.arg(1)
+    def get_constant_string_spec(self, mode):
         if self.is_constant():
-            s = self.box.getref(lltype.Ptr(rstr.STR))
-            return annlowlevel.hlstr(s)
+            s = self.box.getref(lltype.Ptr(mode.LLTYPE))
+            return mode.hlstr(s)
         else:
             return None
 
-    def string_copy_parts(self, newoperations, targetbox, offsetbox):
+    def string_copy_parts(self, newoperations, targetbox, offsetbox, mode):
         # Copies the pointer-to-string 'self' into the target string
         # given by 'targetbox', at the specified offset.  Returns the offset
         # at the end of the copy.
-        lengthbox = self.getstrlen(newoperations)
+        lengthbox = self.getstrlen(newoperations, mode)
         srcbox = self.force_box()
         return copy_str_content(newoperations, srcbox, targetbox,
-                                CONST_0, offsetbox, lengthbox)
+                                CONST_0, offsetbox, lengthbox, mode)
 
 
 class VAbstractStringValue(virtualize.AbstractVirtualValue):
-    _attrs_ = ()
+    _attrs_ = ('mode',)
+
+    def __init__(self, optimizer, keybox, source_op, mode):
+        virtualize.AbstractVirtualValue.__init__(self, optimizer, keybox,
+                                                 source_op)
+        self.mode = mode
 
     def _really_force(self):
-        s = self.get_constant_string()
-        if s is not None:
-            c_s = get_const_ptr_for_string(s)
-            self.make_constant(c_s)
-            return
+        if self.mode is mode_string:
+            s = self.get_constant_string_spec(mode_string)
+            if s is not None:
+                c_s = get_const_ptr_for_string(s)
+                self.make_constant(c_s)
+                return
+        else:
+            s = self.get_constant_string_spec(mode_unicode)
+            if s is not None:
+                c_s = get_const_ptr_for_unicode(s)
+                self.make_constant(c_s)
+                return
         assert self.source_op is not None
         self.box = box = self.source_op.result
         newoperations = self.optimizer.newoperations
-        lengthbox = self.getstrlen(newoperations)
-        newoperations.append(ResOperation(rop.NEWSTR, [lengthbox], box))
-        self.string_copy_parts(newoperations, box, CONST_0)
+        lengthbox = self.getstrlen(newoperations, self.mode)
+        op = ResOperation(self.mode.NEWSTR, [lengthbox], box)
+        if not we_are_translated():
+            op.name = 'FORCE'
+        newoperations.append(op)
+        self.string_copy_parts(newoperations, box, CONST_0, self.mode)
 
 
 class VStringPlainValue(VAbstractStringValue):
@@ -74,7 +125,7 @@
         assert 0 <= start <= stop <= len(longerlist)
         self._chars = longerlist[start:stop]
 
-    def getstrlen(self, _):
+    def getstrlen(self, _, mode):
         if self._lengthbox is None:
             self._lengthbox = ConstInt(len(self._chars))
         return self._lengthbox
@@ -86,18 +137,21 @@
         assert isinstance(charvalue, optimizer.OptValue)
         self._chars[index] = charvalue
 
-    def get_constant_string(self):
+    @specialize.arg(1)
+    def get_constant_string_spec(self, mode):
         for c in self._chars:
             if c is optimizer.CVAL_UNINITIALIZED_ZERO or not c.is_constant():
                 return None
-        return ''.join([chr(c.box.getint()) for c in self._chars])
+        return mode.emptystr.join([mode.chr(c.box.getint())
+                                   for c in self._chars])
 
-    def string_copy_parts(self, newoperations, targetbox, offsetbox):
+    def string_copy_parts(self, newoperations, targetbox, offsetbox, mode):
         for i in range(len(self._chars)):
             charbox = self._chars[i].force_box()
-            newoperations.append(ResOperation(rop.STRSETITEM, [targetbox,
-                                                               offsetbox,
-                                                               charbox], None))
+            newoperations.append(ResOperation(mode.STRSETITEM, [targetbox,
+                                                                offsetbox,
+                                                                charbox],
+                                              None))
             offsetbox = _int_add(newoperations, offsetbox, CONST_1)
         return offsetbox
 
@@ -120,7 +174,7 @@
             boxes.append(self.box)
 
     def _make_virtual(self, modifier):
-        return modifier.make_vstrplain()
+        return modifier.make_vstrplain(self.mode is mode_unicode)
 
 
 class VStringConcatValue(VAbstractStringValue):
@@ -131,23 +185,24 @@
         self.right = right
         self.lengthbox = lengthbox
 
-    def getstrlen(self, _):
+    def getstrlen(self, _, mode):
         return self.lengthbox
 
-    def get_constant_string(self):
-        s1 = self.left.get_constant_string()
+    @specialize.arg(1)
+    def get_constant_string_spec(self, mode):
+        s1 = self.left.get_constant_string_spec(mode)
         if s1 is None:
             return None
-        s2 = self.right.get_constant_string()
+        s2 = self.right.get_constant_string_spec(mode)
         if s2 is None:
             return None
         return s1 + s2
 
-    def string_copy_parts(self, newoperations, targetbox, offsetbox):
+    def string_copy_parts(self, newoperations, targetbox, offsetbox, mode):
         offsetbox = self.left.string_copy_parts(newoperations, targetbox,
-                                                offsetbox)
+                                                offsetbox, mode)
         offsetbox = self.right.string_copy_parts(newoperations, targetbox,
-                                                 offsetbox)
+                                                 offsetbox, mode)
         return offsetbox
 
     def get_args_for_fail(self, modifier):
@@ -172,7 +227,7 @@
             boxes.append(self.box)
 
     def _make_virtual(self, modifier):
-        return modifier.make_vstrconcat()
+        return modifier.make_vstrconcat(self.mode is mode_unicode)
 
 
 class VStringSliceValue(VAbstractStringValue):
@@ -184,12 +239,13 @@
         self.vstart = vstart
         self.vlength = vlength
 
-    def getstrlen(self, _):
+    def getstrlen(self, _, mode):
         return self.vlength.force_box()
 
-    def get_constant_string(self):
+    @specialize.arg(1)
+    def get_constant_string_spec(self, mode):
         if self.vstart.is_constant() and self.vlength.is_constant():
-            s1 = self.vstr.get_constant_string()
+            s1 = self.vstr.get_constant_string_spec(mode)
             if s1 is None:
                 return None
             start = self.vstart.box.getint()
@@ -199,12 +255,12 @@
             return s1[start : start + length]
         return None
 
-    def string_copy_parts(self, newoperations, targetbox, offsetbox):
-        lengthbox = self.getstrlen(newoperations)
+    def string_copy_parts(self, newoperations, targetbox, offsetbox, mode):
+        lengthbox = self.getstrlen(newoperations, mode)
         return copy_str_content(newoperations,
                                 self.vstr.force_box(), targetbox,
                                 self.vstart.force_box(), offsetbox,
-                                lengthbox)
+                                lengthbox, mode)
 
     def get_args_for_fail(self, modifier):
         if self.box is None and not modifier.already_seen_virtual(self.keybox):
@@ -229,11 +285,11 @@
             boxes.append(self.box)
 
     def _make_virtual(self, modifier):
-        return modifier.make_vstrslice()
+        return modifier.make_vstrslice(self.mode is mode_unicode)
 
 
 def copy_str_content(newoperations, srcbox, targetbox,
-                     srcoffsetbox, offsetbox, lengthbox):
+                     srcoffsetbox, offsetbox, lengthbox, mode):
     if isinstance(srcbox, ConstPtr) and isinstance(srcoffsetbox, Const):
         M = 5
     else:
@@ -242,17 +298,18 @@
         # up to M characters are done "inline", i.e. with STRGETITEM/STRSETITEM
         # instead of just a COPYSTRCONTENT.
         for i in range(lengthbox.value):
-            charbox = _strgetitem(newoperations, srcbox, srcoffsetbox)
+            charbox = _strgetitem(newoperations, srcbox, srcoffsetbox, mode)
             srcoffsetbox = _int_add(newoperations, srcoffsetbox, CONST_1)
-            newoperations.append(ResOperation(rop.STRSETITEM, [targetbox,
-                                                               offsetbox,
-                                                               charbox], None))
+            newoperations.append(ResOperation(mode.STRSETITEM, [targetbox,
+                                                                offsetbox,
+                                                                charbox],
+                                              None))
             offsetbox = _int_add(newoperations, offsetbox, CONST_1)
     else:
         nextoffsetbox = _int_add(newoperations, offsetbox, lengthbox)
-        op = ResOperation(rop.COPYSTRCONTENT, [srcbox, targetbox,
-                                               srcoffsetbox, offsetbox,
-                                               lengthbox], None)
+        op = ResOperation(mode.COPYSTRCONTENT, [srcbox, targetbox,
+                                                srcoffsetbox, offsetbox,
+                                                lengthbox], None)
         newoperations.append(op)
         offsetbox = nextoffsetbox
     return offsetbox
@@ -279,12 +336,16 @@
     newoperations.append(ResOperation(rop.INT_SUB, [box1, box2], resbox))
     return resbox
 
-def _strgetitem(newoperations, strbox, indexbox):
+def _strgetitem(newoperations, strbox, indexbox, mode):
     if isinstance(strbox, ConstPtr) and isinstance(indexbox, ConstInt):
-        s = strbox.getref(lltype.Ptr(rstr.STR))
-        return ConstInt(ord(s.chars[indexbox.getint()]))
+        if mode is mode_string:
+            s = strbox.getref(lltype.Ptr(rstr.STR))
+            return ConstInt(ord(s.chars[indexbox.getint()]))
+        else:
+            s = strbox.getref(lltype.Ptr(rstr.UNICODE))
+            return ConstInt(ord(s.chars[indexbox.getint()]))
     resbox = BoxInt()
-    newoperations.append(ResOperation(rop.STRGETITEM, [strbox, indexbox],
+    newoperations.append(ResOperation(mode.STRGETITEM, [strbox, indexbox],
                                       resbox))
     return resbox
 
@@ -292,62 +353,34 @@
 class OptString(optimizer.Optimization):
     "Handling of strings and unicodes."
 
-    def make_vstring_plain(self, box, source_op=None):
-        vvalue = VStringPlainValue(self.optimizer, box, source_op)
+    def make_vstring_plain(self, box, source_op, mode):
+        vvalue = VStringPlainValue(self.optimizer, box, source_op, mode)
         self.make_equal_to(box, vvalue)
         return vvalue
 
-    def make_vstring_concat(self, box, source_op=None):
-        vvalue = VStringConcatValue(self.optimizer, box, source_op)
+    def make_vstring_concat(self, box, source_op, mode):
+        vvalue = VStringConcatValue(self.optimizer, box, source_op, mode)
         self.make_equal_to(box, vvalue)
         return vvalue
 
-    def make_vstring_slice(self, box, source_op=None):
-        vvalue = VStringSliceValue(self.optimizer, box, source_op)
+    def make_vstring_slice(self, box, source_op, mode):
+        vvalue = VStringSliceValue(self.optimizer, box, source_op, mode)
         self.make_equal_to(box, vvalue)
         return vvalue
 
-    def optimize_CALL(self, op):
-        # dispatch based on 'oopspecindex' to a method that handles
-        # specifically the given oopspec call.  For non-oopspec calls,
-        # oopspecindex is just zero.
-        effectinfo = op.getdescr().get_extra_info()
-        if effectinfo is not None:
-            oopspecindex = effectinfo.oopspecindex
-            for value, meth in opt_call_oopspec_ops:
-                if oopspecindex == value:
-                    if meth(self, op):
-                        return
-        self.emit_operation(op)
-
-    def opt_call_oopspec_ARRAYCOPY(self, op):
-        source_value = self.getvalue(op.getarg(1))
-        dest_value = self.getvalue(op.getarg(2))
-        source_start_box = self.get_constant_box(op.getarg(3))
-        dest_start_box = self.get_constant_box(op.getarg(4))
-        length = self.get_constant_box(op.getarg(5))
-        if (source_value.is_virtual() and source_start_box and dest_start_box
-            and length and dest_value.is_virtual()):
-            # XXX optimize the case where dest value is not virtual,
-            #     but we still can avoid a mess
-            source_start = source_start_box.getint()
-            dest_start = dest_start_box.getint()
-            for index in range(length.getint()):
-                val = source_value.getitem(index + source_start)
-                dest_value.setitem(index + dest_start, val)
-            return True
-        if length and length.getint() == 0:
-            return True # 0-length arraycopy
-        return False
-
     def optimize_NEWSTR(self, op):
+        self._optimize_NEWSTR(op, mode_string)
+    def optimize_NEWUNICODE(self, op):
+        self._optimize_NEWSTR(op, mode_unicode)
+
+    def _optimize_NEWSTR(self, op, mode):
         length_box = self.get_constant_box(op.getarg(0))
         if length_box:
             # if the original 'op' did not have a ConstInt as argument,
             # build a new one with the ConstInt argument
             if not isinstance(op.getarg(0), ConstInt):
-                op = ResOperation(rop.NEWSTR, [length_box], op.result)
-            vvalue = self.make_vstring_plain(op.result, op)
+                op = ResOperation(mode.NEWSTR, [length_box], op.result)
+            vvalue = self.make_vstring_plain(op.result, op, mode)
             vvalue.setup(length_box.getint())
         else:
             self.getvalue(op.result).ensure_nonnull()
@@ -363,13 +396,20 @@
         value.ensure_nonnull()
         self.emit_operation(op)
 
+    optimize_UNICODESETITEM = optimize_STRSETITEM
+
     def optimize_STRGETITEM(self, op):
+        self._optimize_STRGETITEM(op, mode_string)
+    def optimize_UNICODEGETITEM(self, op):
+        self._optimize_STRGETITEM(op, mode_unicode)
+
+    def _optimize_STRGETITEM(self, op, mode):
         value = self.getvalue(op.getarg(0))
         vindex = self.getvalue(op.getarg(1))
-        vresult = self.strgetitem(value, vindex)
+        vresult = self.strgetitem(value, vindex, mode)
         self.make_equal_to(op.result, vresult)
 
-    def strgetitem(self, value, vindex):
+    def strgetitem(self, value, vindex, mode):
         value.ensure_nonnull()
         #
         if value.is_virtual() and isinstance(value, VStringSliceValue):
@@ -384,28 +424,71 @@
                 return value.getitem(vindex.box.getint())
         #
         resbox = _strgetitem(self.optimizer.newoperations,
-                             value.force_box(),vindex.force_box())
+                             value.force_box(),vindex.force_box(), mode)
         return self.getvalue(resbox)
 
     def optimize_STRLEN(self, op):
+        self._optimize_STRLEN(op, mode_string)
+    def optimize_UNICODELEN(self, op):
+        self._optimize_STRLEN(op, mode_unicode)
+
+    def _optimize_STRLEN(self, op, mode):
         value = self.getvalue(op.getarg(0))
-        lengthbox = value.getstrlen(self.optimizer.newoperations)
+        lengthbox = value.getstrlen(self.optimizer.newoperations, mode)
         self.make_equal_to(op.result, self.getvalue(lengthbox))
 
-    def opt_call_oopspec_STR_CONCAT(self, op):
+    def optimize_CALL(self, op):
+        # dispatch based on 'oopspecindex' to a method that handles
+        # specifically the given oopspec call.  For non-oopspec calls,
+        # oopspecindex is just zero.
+        effectinfo = op.getdescr().get_extra_info()
+        if effectinfo is not None:
+            oopspecindex = effectinfo.oopspecindex
+            for value, meth in opt_call_oopspec_ops:
+                if oopspecindex == value:      # a match with the OS_STR_xxx
+                    if meth(self, op, mode_string):
+                        return
+                    break
+                if oopspecindex == value + EffectInfo._OS_offset_uni:
+                    # a match with the OS_UNI_xxx
+                    if meth(self, op, mode_unicode):
+                        return
+                    break
+            if oopspecindex == EffectInfo.OS_STR2UNICODE:
+                if self.opt_call_str_STR2UNICODE(op):
+                    return
+        self.emit_operation(op)
+
+    def opt_call_str_STR2UNICODE(self, op):
+        # Constant-fold unicode("constant string").
+        # More generally, supporting non-constant but virtual cases is
+        # not obvious, because of the exception UnicodeDecodeError that
+        # can be raised by ll_str2unicode()
+        varg = self.getvalue(op.getarg(1))
+        s = varg.get_constant_string_spec(mode_string)
+        if s is None:
+            return False
+        try:
+            u = unicode(s)
+        except UnicodeDecodeError:
+            return False
+        self.make_constant(op.result, get_const_ptr_for_unicode(u))
+        return True
+
+    def opt_call_stroruni_STR_CONCAT(self, op, mode):
         vleft = self.getvalue(op.getarg(1))
         vright = self.getvalue(op.getarg(2))
         vleft.ensure_nonnull()
         vright.ensure_nonnull()
         newoperations = self.optimizer.newoperations
-        len1box = vleft.getstrlen(newoperations)
-        len2box = vright.getstrlen(newoperations)
+        len1box = vleft.getstrlen(newoperations, mode)
+        len2box = vright.getstrlen(newoperations, mode)
         lengthbox = _int_add(newoperations, len1box, len2box)
-        value = self.make_vstring_concat(op.result, op)
+        value = self.make_vstring_concat(op.result, op, mode)
         value.setup(vleft, vright, lengthbox)
         return True
 
-    def opt_call_oopspec_STR_SLICE(self, op):
+    def opt_call_stroruni_STR_SLICE(self, op, mode):
         newoperations = self.optimizer.newoperations
         vstr = self.getvalue(op.getarg(1))
         vstart = self.getvalue(op.getarg(2))
@@ -414,7 +497,7 @@
         if (isinstance(vstr, VStringPlainValue) and vstart.is_constant()
             and vstop.is_constant()):
             # slicing with constant bounds of a VStringPlainValue
-            value = self.make_vstring_plain(op.result, op)
+            value = self.make_vstring_plain(op.result, op, mode)
             value.setup_slice(vstr._chars, vstart.box.getint(),
                                            vstop.box.getint())
             return True
@@ -432,16 +515,16 @@
                                 vstart.force_box())
             vstart = self.getvalue(startbox)
         #
-        value = self.make_vstring_slice(op.result, op)
+        value = self.make_vstring_slice(op.result, op, mode)
         value.setup(vstr, vstart, self.getvalue(lengthbox))
         return True
 
-    def opt_call_oopspec_STR_EQUAL(self, op):
+    def opt_call_stroruni_STR_EQUAL(self, op, mode):
         v1 = self.getvalue(op.getarg(1))
         v2 = self.getvalue(op.getarg(2))
         #
-        l1box = v1.getstrlen(None)
-        l2box = v2.getstrlen(None)
+        l1box = v1.getstrlen(None, mode)
+        l2box = v2.getstrlen(None, mode)
         if (l1box is not None and l2box is not None and
             isinstance(l1box, ConstInt) and
             isinstance(l2box, ConstInt) and
@@ -450,13 +533,13 @@
             self.make_constant(op.result, CONST_0)
             return True
         #
-        if self.handle_str_equal_level1(v1, v2, op.result):
+        if self.handle_str_equal_level1(v1, v2, op.result, mode):
             return True
-        if self.handle_str_equal_level1(v2, v1, op.result):
+        if self.handle_str_equal_level1(v2, v1, op.result, mode):
             return True
-        if self.handle_str_equal_level2(v1, v2, op.result):
+        if self.handle_str_equal_level2(v1, v2, op.result, mode):
             return True
-        if self.handle_str_equal_level2(v2, v1, op.result):
+        if self.handle_str_equal_level2(v2, v1, op.result, mode):
             return True
         #
         if v1.is_nonnull() and v2.is_nonnull():
@@ -468,37 +551,37 @@
             else:
                 do = EffectInfo.OS_STREQ_NONNULL
             self.generate_modified_call(do, [v1.force_box(),
-                                             v2.force_box()], op.result)
+                                             v2.force_box()], op.result, mode)
             return True
         return False
 
-    def handle_str_equal_level1(self, v1, v2, resultbox):
-        l2box = v2.getstrlen(None)
+    def handle_str_equal_level1(self, v1, v2, resultbox, mode):
+        l2box = v2.getstrlen(None, mode)
         if isinstance(l2box, ConstInt):
             if l2box.value == 0:
-                lengthbox = v1.getstrlen(self.optimizer.newoperations)
+                lengthbox = v1.getstrlen(self.optimizer.newoperations, mode)
                 seo = self.optimizer.send_extra_operation
                 seo(ResOperation(rop.INT_EQ, [lengthbox, CONST_0], resultbox))
                 return True
             if l2box.value == 1:
-                l1box = v1.getstrlen(None)
+                l1box = v1.getstrlen(None, mode)
                 if isinstance(l1box, ConstInt) and l1box.value == 1:
                     # comparing two single chars
-                    vchar1 = self.strgetitem(v1, optimizer.CVAL_ZERO)
-                    vchar2 = self.strgetitem(v2, optimizer.CVAL_ZERO)
+                    vchar1 = self.strgetitem(v1, optimizer.CVAL_ZERO, mode)
+                    vchar2 = self.strgetitem(v2, optimizer.CVAL_ZERO, mode)
                     seo = self.optimizer.send_extra_operation
                     seo(ResOperation(rop.INT_EQ, [vchar1.force_box(),
                                                   vchar2.force_box()],
                                      resultbox))
                     return True
                 if isinstance(v1, VStringSliceValue):
-                    vchar = self.strgetitem(v2, optimizer.CVAL_ZERO)
+                    vchar = self.strgetitem(v2, optimizer.CVAL_ZERO, mode)
                     do = EffectInfo.OS_STREQ_SLICE_CHAR
                     self.generate_modified_call(do, [v1.vstr.force_box(),
                                                      v1.vstart.force_box(),
                                                      v1.vlength.force_box(),
                                                      vchar.force_box()],
-                                                resultbox)
+                                                resultbox, mode)
                     return True
         #
         if v2.is_null():
@@ -516,17 +599,18 @@
         #
         return False
 
-    def handle_str_equal_level2(self, v1, v2, resultbox):
-        l2box = v2.getstrlen(None)
+    def handle_str_equal_level2(self, v1, v2, resultbox, mode):
+        l2box = v2.getstrlen(None, mode)
         if isinstance(l2box, ConstInt):
             if l2box.value == 1:
-                vchar = self.strgetitem(v2, optimizer.CVAL_ZERO)
+                vchar = self.strgetitem(v2, optimizer.CVAL_ZERO, mode)
                 if v1.is_nonnull():
                     do = EffectInfo.OS_STREQ_NONNULL_CHAR
                 else:
                     do = EffectInfo.OS_STREQ_CHECKNULL_CHAR
                 self.generate_modified_call(do, [v1.force_box(),
-                                                 vchar.force_box()], resultbox)
+                                                 vchar.force_box()], resultbox,
+                                            mode)
                 return True
         #
         if v1.is_virtual() and isinstance(v1, VStringSliceValue):
@@ -537,11 +621,12 @@
             self.generate_modified_call(do, [v1.vstr.force_box(),
                                              v1.vstart.force_box(),
                                              v1.vlength.force_box(),
-                                             v2.force_box()], resultbox)
+                                             v2.force_box()], resultbox, mode)
             return True
         return False
 
-    def generate_modified_call(self, oopspecindex, args, result):
+    def generate_modified_call(self, oopspecindex, args, result, mode):
+        oopspecindex += mode.OS_offset
         calldescr, func = callinfo_for_oopspec(oopspecindex)
         op = ResOperation(rop.CALL, [ConstInt(func)] + args, result,
                           descr=calldescr)
@@ -559,7 +644,7 @@
 optimize_ops = _findall(OptString, 'optimize_')
 
 def _findall_call_oopspec():
-    prefix = 'opt_call_oopspec_'
+    prefix = 'opt_call_stroruni_'
     result = []
     for name in dir(OptString):
         if name.startswith(prefix):

Modified: pypy/branch/jit-unroll-loops/pypy/jit/metainterp/optimizeopt/virtualize.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/jit/metainterp/optimizeopt/virtualize.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/jit/metainterp/optimizeopt/virtualize.py	Sat Oct 30 16:41:17 2010
@@ -76,6 +76,8 @@
         assert self.source_op is not None
         # ^^^ This case should not occur any more (see test_bug_3).
         #
+        if not we_are_translated():
+            self.source_op.name = 'FORCE ' + self.source_op.name
         newoperations = self.optimizer.newoperations
         newoperations.append(self.source_op)
         self.box = box = self.source_op.result
@@ -148,6 +150,11 @@
         fielddescrs = self._get_field_descr_list()
         return modifier.make_virtual(self.known_class, fielddescrs)
 
+    def __repr__(self):
+        cls_name = self.known_class.value.adr.ptr._obj._TYPE._name
+        field_names = [field.name for field in self._fields]
+        return "<VirtualValue cls=%s fields=%s>" % (cls_name, field_names)
+
 class VStructValue(AbstractVirtualStructValue):
 
     def __init__(self, optimizer, structdescr, keybox, source_op=None):
@@ -179,6 +186,8 @@
 
     def _really_force(self):
         assert self.source_op is not None
+        if not we_are_translated():
+            self.source_op.name = 'FORCE ' + self.source_op.name
         newoperations = self.optimizer.newoperations
         newoperations.append(self.source_op)
         self.box = box = self.source_op.result

Modified: pypy/branch/jit-unroll-loops/pypy/jit/metainterp/pyjitpl.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/jit/metainterp/pyjitpl.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/jit/metainterp/pyjitpl.py	Sat Oct 30 16:41:17 2010
@@ -1,4 +1,4 @@
-import py, os
+import py, os, sys
 from pypy.rpython.lltypesystem import lltype, llmemory, rclass
 from pypy.rlib.objectmodel import we_are_translated
 from pypy.rlib.unroll import unrolling_iterable
@@ -498,6 +498,22 @@
     opimpl_getfield_gc_r_pure = _opimpl_getfield_gc_pure_any
     opimpl_getfield_gc_f_pure = _opimpl_getfield_gc_pure_any
 
+    @arguments("orgpc", "box", "descr")
+    def _opimpl_getfield_gc_greenfield_any(self, pc, box, fielddescr):
+        ginfo = self.metainterp.jitdriver_sd.greenfield_info
+        if (ginfo is not None and fielddescr in ginfo.green_field_descrs
+            and not self._nonstandard_virtualizable(pc, box)):
+            # fetch the result, but consider it as a Const box and don't
+            # record any operation
+            resbox = executor.execute(self.metainterp.cpu, self.metainterp,
+                                      rop.GETFIELD_GC_PURE, fielddescr, box)
+            return resbox.constbox()
+        # fall-back
+        return self.execute_with_descr(rop.GETFIELD_GC_PURE, fielddescr, box)
+    opimpl_getfield_gc_i_greenfield = _opimpl_getfield_gc_greenfield_any
+    opimpl_getfield_gc_r_greenfield = _opimpl_getfield_gc_greenfield_any
+    opimpl_getfield_gc_f_greenfield = _opimpl_getfield_gc_greenfield_any
+
     @arguments("box", "descr", "box")
     def _opimpl_setfield_gc_any(self, box, fielddescr, valuebox):
         self.execute_with_descr(rop.SETFIELD_GC, fielddescr, box, valuebox)
@@ -529,7 +545,8 @@
     def _nonstandard_virtualizable(self, pc, box):
         # returns True if 'box' is actually not the "standard" virtualizable
         # that is stored in metainterp.virtualizable_boxes[-1]
-        if self.metainterp.jitdriver_sd.virtualizable_info is None:
+        if (self.metainterp.jitdriver_sd.virtualizable_info is None and
+            self.metainterp.jitdriver_sd.greenfield_info is None):
             return True      # can occur in case of multiple JITs
         standard_box = self.metainterp.virtualizable_boxes[-1]
         if standard_box is box:
@@ -799,12 +816,16 @@
 
     @arguments("orgpc", "int", "boxes3", "boxes3")
     def opimpl_jit_merge_point(self, orgpc, jdindex, greenboxes, redboxes):
+        any_operation = len(self.metainterp.history.operations) > 0
         jitdriver_sd = self.metainterp.staticdata.jitdrivers_sd[jdindex]
         self.verify_green_args(jitdriver_sd, greenboxes)
         # xxx we may disable the following line in some context later
         self.debug_merge_point(jitdriver_sd, greenboxes)
         if self.metainterp.seen_loop_header_for_jdindex < 0:
-            return
+            if not jitdriver_sd.no_loop_header or not any_operation:
+                return
+            # automatically add a loop_header if there is none
+            self.metainterp.seen_loop_header_for_jdindex = jdindex
         #
         assert self.metainterp.seen_loop_header_for_jdindex == jdindex, (
             "found a loop_header for a JitDriver that does not match "
@@ -893,6 +914,40 @@
         msg = box.getref(lltype.Ptr(rstr.STR))
         lloperation.llop.debug_fatalerror(msg)
 
+    @arguments("box", "box", "box", "box", "box")
+    def opimpl_jit_debug(self, stringbox, arg1box, arg2box, arg3box, arg4box):
+        from pypy.rpython.lltypesystem import rstr
+        from pypy.rpython.annlowlevel import hlstr
+        msg = stringbox.getref(lltype.Ptr(rstr.STR))
+        debug_print('jit_debug:', hlstr(msg),
+                    arg1box.getint(), arg2box.getint(),
+                    arg3box.getint(), arg4box.getint())
+        args = [stringbox, arg1box, arg2box, arg3box, arg4box]
+        i = 4
+        while i > 0 and args[i].getint() == -sys.maxint-1:
+            i -= 1
+        assert i >= 0
+        op = self.metainterp.history.record(rop.JIT_DEBUG, args[:i+1], None)
+        self.metainterp.attach_debug_info(op)
+
+    @arguments("box")
+    def _opimpl_assert_green(self, box):
+        if not isinstance(box, Const):
+            msg = "assert_green failed at %s:%d" % (
+                self.jitcode.name,
+                self.pc)
+            if we_are_translated():
+                from pypy.rpython.annlowlevel import llstr
+                from pypy.rpython.lltypesystem import lloperation
+                lloperation.llop.debug_fatalerror(lltype.Void, llstr(msg))
+            else:
+                from pypy.rlib.jit import AssertGreenFailed
+                raise AssertGreenFailed(msg)
+
+    opimpl_int_assert_green   = _opimpl_assert_green
+    opimpl_ref_assert_green   = _opimpl_assert_green
+    opimpl_float_assert_green = _opimpl_assert_green
+
     @arguments("box")
     def opimpl_virtual_ref(self, box):
         # Details on the content of metainterp.virtualref_boxes:
@@ -998,7 +1053,8 @@
         guard_op = metainterp.history.record(opnum, moreargs, None,
                                              descr=resumedescr)
         virtualizable_boxes = None
-        if metainterp.jitdriver_sd.virtualizable_info is not None:
+        if (metainterp.jitdriver_sd.virtualizable_info is not None or
+            metainterp.jitdriver_sd.greenfield_info is not None):
             virtualizable_boxes = metainterp.virtualizable_boxes
         saved_pc = self.pc
         if resumepc >= 0:
@@ -1646,6 +1702,7 @@
                                               duplicates)
             live_arg_boxes += self.virtualizable_boxes
             live_arg_boxes.pop()
+        #
         assert len(self.virtualref_boxes) == 0, "missing virtual_ref_finish()?"
         # Called whenever we reach the 'loop_header' hint.
         # First, attempt to make a bridge:
@@ -1832,6 +1889,7 @@
         f.setup_call(original_boxes)
         assert self.in_recursion == 0
         self.virtualref_boxes = []
+        self.initialize_withgreenfields(original_boxes)
         self.initialize_virtualizable(original_boxes)
 
     def initialize_state_from_guard_failure(self, resumedescr):
@@ -1856,6 +1914,14 @@
             self.virtualizable_boxes.append(virtualizable_box)
             self.initialize_virtualizable_enter()
 
+    def initialize_withgreenfields(self, original_boxes):
+        ginfo = self.jitdriver_sd.greenfield_info
+        if ginfo is not None:
+            assert self.jitdriver_sd.virtualizable_info is None
+            index = (self.jitdriver_sd.num_green_args +
+                     ginfo.red_index)
+            self.virtualizable_boxes = [original_boxes[index]]
+
     def initialize_virtualizable_enter(self):
         vinfo = self.jitdriver_sd.virtualizable_info
         virtualizable_box = self.virtualizable_boxes[-1]
@@ -1949,8 +2015,10 @@
 
     def rebuild_state_after_failure(self, resumedescr):
         vinfo = self.jitdriver_sd.virtualizable_info
+        ginfo = self.jitdriver_sd.greenfield_info
         self.framestack = []
-        boxlists = resume.rebuild_from_resumedata(self, resumedescr, vinfo)
+        boxlists = resume.rebuild_from_resumedata(self, resumedescr, vinfo,
+                                                  ginfo)
         inputargs_and_holes, virtualizable_boxes, virtualref_boxes = boxlists
         #
         # virtual refs: make the vrefs point to the freshly allocated virtuals
@@ -1975,6 +2043,12 @@
             assert not virtualizable.vable_token
             # fill the virtualizable with the local boxes
             self.synchronize_virtualizable()
+        #
+        elif self.jitdriver_sd.greenfield_info:
+            self.virtualizable_boxes = virtualizable_boxes
+        else:
+            assert not virtualizable_boxes
+        #
         return inputargs_and_holes
 
     def check_synchronized_virtualizable(self):
@@ -2048,7 +2122,8 @@
         for i in range(len(boxes)):
             if boxes[i] is oldbox:
                 boxes[i] = newbox
-        if self.jitdriver_sd.virtualizable_info is not None:
+        if (self.jitdriver_sd.virtualizable_info is not None or
+            self.jitdriver_sd.greenfield_info is not None):
             boxes = self.virtualizable_boxes
             for i in range(len(boxes)):
                 if boxes[i] is oldbox:

Modified: pypy/branch/jit-unroll-loops/pypy/jit/metainterp/resoperation.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/jit/metainterp/resoperation.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/jit/metainterp/resoperation.py	Sat Oct 30 16:41:17 2010
@@ -93,7 +93,7 @@
     def __repr__(self):
         return self.repr()
 
-    def repr(self):
+    def repr(self, graytext=False):
         # RPython-friendly version
         if self.result is not None:
             sres = '%s = ' % (self.result,)
@@ -101,6 +101,8 @@
             sres = ''
         if self.name:
             prefix = "%s:%s   " % (self.name, self.pc)
+            if graytext:
+                prefix = "\f%s\f" % prefix
         else:
             prefix = ""
         args = self.getarglist()
@@ -455,15 +457,16 @@
     'UNICODESETITEM/3',
     'NEWUNICODE/1',
     #'RUNTIMENEW/1',     # ootype operation    
-    'COND_CALL_GC_WB/1d',  # [objptr]   (for the write barrier)
+    'COND_CALL_GC_WB/2d', # [objptr, newvalue]   (for the write barrier)
     'DEBUG_MERGE_POINT/1',      # debugging only
+    'JIT_DEBUG/*',              # debugging only
     'VIRTUAL_REF_FINISH/2',   # removed before it's passed to the backend
     'COPYSTRCONTENT/5',       # src, dst, srcstart, dststart, length
     'COPYUNICODECONTENT/5',
 
     '_CANRAISE_FIRST', # ----- start of can_raise operations -----
     'CALL/*d',
-    'CALL_ASSEMBLER/*d',
+    'CALL_ASSEMBLER/*d',  # call already compiled assembler
     'CALL_MAY_FORCE/*d',
     'CALL_LOOPINVARIANT/*d',
     #'OOSEND',                     # ootype operation

Modified: pypy/branch/jit-unroll-loops/pypy/jit/metainterp/resume.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/jit/metainterp/resume.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/jit/metainterp/resume.py	Sat Oct 30 16:41:17 2010
@@ -255,13 +255,19 @@
     def make_varray(self, arraydescr):
         return VArrayInfo(arraydescr)
 
-    def make_vstrplain(self):
+    def make_vstrplain(self, is_unicode=False):
+        if is_unicode:
+            return VUniPlainInfo()
         return VStrPlainInfo()
 
-    def make_vstrconcat(self):
+    def make_vstrconcat(self, is_unicode=False):
+        if is_unicode:
+            return VUniConcatInfo()
         return VStrConcatInfo()
 
-    def make_vstrslice(self):
+    def make_vstrslice(self, is_unicode=False):
+        if is_unicode:
+            return VUniSliceInfo()
         return VStrSliceInfo()
 
     def register_virtual_fields(self, virtualbox, fieldboxes):
@@ -550,6 +556,60 @@
         for i in self.fieldnums:
             debug_print("\t\t", str(untag(i)))
 
+
+class VUniPlainInfo(AbstractVirtualInfo):
+    """Stands for the unicode string made out of the characters of all
+    fieldnums."""
+
+    @specialize.argtype(1)
+    def allocate(self, decoder, index):
+        length = len(self.fieldnums)
+        string = decoder.allocate_unicode(length)
+        decoder.virtuals_cache[index] = string
+        for i in range(length):
+            decoder.unicode_setitem(string, i, self.fieldnums[i])
+        return string
+
+    def debug_prints(self):
+        debug_print("\tvuniplaininfo length", len(self.fieldnums))
+
+
+class VUniConcatInfo(AbstractVirtualInfo):
+    """Stands for the unicode string made out of the concatenation of two
+    other unicode strings."""
+
+    @specialize.argtype(1)
+    def allocate(self, decoder, index):
+        # xxx for blackhole resuming, this will build all intermediate
+        # strings and throw them away immediately, which is a bit sub-
+        # efficient.  Not sure we care.
+        left, right = self.fieldnums
+        string = decoder.concat_unicodes(left, right)
+        decoder.virtuals_cache[index] = string
+        return string
+
+    def debug_prints(self):
+        debug_print("\tvuniconcatinfo")
+        for i in self.fieldnums:
+            debug_print("\t\t", str(untag(i)))
+
+
+class VUniSliceInfo(AbstractVirtualInfo):
+    """Stands for the unicode string made out of slicing another
+    unicode string."""
+
+    @specialize.argtype(1)
+    def allocate(self, decoder, index):
+        largerstr, start, length = self.fieldnums
+        string = decoder.slice_unicode(largerstr, start, length)
+        decoder.virtuals_cache[index] = string
+        return string
+
+    def debug_prints(self):
+        debug_print("\tvunisliceinfo")
+        for i in self.fieldnums:
+            debug_print("\t\t", str(untag(i)))
+
 # ____________________________________________________________
 
 class AbstractResumeDataReader(object):
@@ -629,9 +689,11 @@
 
 # ---------- when resuming for pyjitpl.py, make boxes ----------
 
-def rebuild_from_resumedata(metainterp, storage, virtualizable_info):
+def rebuild_from_resumedata(metainterp, storage, virtualizable_info,
+                            greenfield_info):
     resumereader = ResumeDataBoxReader(storage, metainterp)
-    boxes = resumereader.consume_vref_and_vable_boxes(virtualizable_info)
+    boxes = resumereader.consume_vref_and_vable_boxes(virtualizable_info,
+                                                      greenfield_info)
     virtualizable_boxes, virtualref_boxes = boxes
     frameinfo = storage.rd_frame_info_list
     while True:
@@ -676,15 +738,18 @@
         assert (end & 1) == 0
         return [self.decode_ref(nums[i]) for i in range(end)]
 
-    def consume_vref_and_vable_boxes(self, vinfo):
+    def consume_vref_and_vable_boxes(self, vinfo, ginfo):
         nums = self.cur_numb.nums
         self.cur_numb = self.cur_numb.prev
-        if vinfo is None:
-            virtualizable_boxes = None
-            end = len(nums)
-        else:
+        if vinfo is not None:
             virtualizable_boxes = self.consume_virtualizable_boxes(vinfo, nums)
             end = len(nums) - len(virtualizable_boxes)
+        elif ginfo is not None:
+            virtualizable_boxes = [self.decode_ref(nums[-1])]
+            end = len(nums) - 1
+        else:
+            virtualizable_boxes = None
+            end = len(nums)
         virtualref_boxes = self.consume_virtualref_boxes(nums, end)
         return virtualizable_boxes, virtualref_boxes
 
@@ -725,6 +790,32 @@
         return self.metainterp.execute_and_record_varargs(
             rop.CALL, [ConstInt(func), strbox, startbox, stopbox], calldescr)
 
+    def allocate_unicode(self, length):
+        return self.metainterp.execute_and_record(rop.NEWUNICODE,
+                                                  None, ConstInt(length))
+
+    def unicode_setitem(self, strbox, index, charnum):
+        charbox = self.decode_box(charnum, INT)
+        self.metainterp.execute_and_record(rop.UNICODESETITEM, None,
+                                           strbox, ConstInt(index), charbox)
+
+    def concat_unicodes(self, str1num, str2num):
+        calldescr, func = callinfo_for_oopspec(EffectInfo.OS_UNI_CONCAT)
+        str1box = self.decode_box(str1num, REF)
+        str2box = self.decode_box(str2num, REF)
+        return self.metainterp.execute_and_record_varargs(
+            rop.CALL, [ConstInt(func), str1box, str2box], calldescr)
+
+    def slice_unicode(self, strnum, startnum, lengthnum):
+        calldescr, func = callinfo_for_oopspec(EffectInfo.OS_UNI_SLICE)
+        strbox = self.decode_box(strnum, REF)
+        startbox = self.decode_box(startnum, INT)
+        lengthbox = self.decode_box(lengthnum, INT)
+        stopbox = self.metainterp.execute_and_record(rop.INT_ADD, None,
+                                                     startbox, lengthbox)
+        return self.metainterp.execute_and_record_varargs(
+            rop.CALL, [ConstInt(func), strbox, startbox, stopbox], calldescr)
+
     def setfield(self, descr, structbox, fieldnum):
         if descr.is_pointer_field():
             kind = REF
@@ -815,8 +906,9 @@
     resumereader = ResumeDataDirectReader(blackholeinterpbuilder.cpu, storage,
                                           all_virtuals)
     vinfo = jitdriver_sd.virtualizable_info
+    ginfo = jitdriver_sd.greenfield_info
     vrefinfo = blackholeinterpbuilder.metainterp_sd.virtualref_info
-    resumereader.consume_vref_and_vable(vrefinfo, vinfo)
+    resumereader.consume_vref_and_vable(vrefinfo, vinfo, ginfo)
     #
     # First get a chain of blackhole interpreters whose length is given
     # by the depth of rd_frame_info_list.  The first one we get must be
@@ -846,11 +938,11 @@
     resumereader.done()
     return firstbh
 
-def force_from_resumedata(metainterp_sd, storage, vinfo=None):
+def force_from_resumedata(metainterp_sd, storage, vinfo, ginfo):
     resumereader = ResumeDataDirectReader(metainterp_sd.cpu, storage)
     resumereader.handling_async_forcing()
     vrefinfo = metainterp_sd.virtualref_info
-    resumereader.consume_vref_and_vable(vrefinfo, vinfo)
+    resumereader.consume_vref_and_vable(vrefinfo, vinfo, ginfo)
     return resumereader.force_all_virtuals()
 
 class ResumeDataDirectReader(AbstractResumeDataReader):
@@ -925,11 +1017,12 @@
         return specialize_value(TYPE, x)
     load_value_of_type._annspecialcase_ = 'specialize:arg(1)'
 
-    def consume_vref_and_vable(self, vrefinfo, vinfo):
+    def consume_vref_and_vable(self, vrefinfo, vinfo, ginfo):
         nums = self.cur_numb.nums
         self.cur_numb = self.cur_numb.prev
         if self.resume_after_guard_not_forced != 2:
             end_vref = self.consume_vable_info(vinfo, nums)
+            if ginfo is not None: end_vref -= 1
             self.consume_virtualref_info(vrefinfo, nums, end_vref)
 
     def allocate_with_vtable(self, known_class):
@@ -967,6 +1060,31 @@
         result = funcptr(str, start, start + length)
         return lltype.cast_opaque_ptr(llmemory.GCREF, result)
 
+    def allocate_unicode(self, length):
+        return self.cpu.bh_newunicode(length)
+
+    def unicode_setitem(self, str, index, charnum):
+        char = self.decode_int(charnum)
+        self.cpu.bh_unicodesetitem(str, index, char)
+
+    def concat_unicodes(self, str1num, str2num):
+        str1 = self.decode_ref(str1num)
+        str2 = self.decode_ref(str2num)
+        str1 = lltype.cast_opaque_ptr(lltype.Ptr(rstr.UNICODE), str1)
+        str2 = lltype.cast_opaque_ptr(lltype.Ptr(rstr.UNICODE), str2)
+        funcptr = funcptr_for_oopspec(EffectInfo.OS_UNI_CONCAT)
+        result = funcptr(str1, str2)
+        return lltype.cast_opaque_ptr(llmemory.GCREF, result)
+
+    def slice_unicode(self, strnum, startnum, lengthnum):
+        str = self.decode_ref(strnum)
+        start = self.decode_int(startnum)
+        length = self.decode_int(lengthnum)
+        str = lltype.cast_opaque_ptr(lltype.Ptr(rstr.UNICODE), str)
+        funcptr = funcptr_for_oopspec(EffectInfo.OS_UNI_SLICE)
+        result = funcptr(str, start, start + length)
+        return lltype.cast_opaque_ptr(llmemory.GCREF, result)
+
     def setfield(self, descr, struct, fieldnum):
         if descr.is_pointer_field():
             newvalue = self.decode_ref(fieldnum)

Modified: pypy/branch/jit-unroll-loops/pypy/jit/metainterp/simple_optimize.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/jit/metainterp/simple_optimize.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/jit/metainterp/simple_optimize.py	Sat Oct 30 16:41:17 2010
@@ -9,11 +9,13 @@
 
 def transform(op):
     from pypy.jit.metainterp.history import AbstractDescr
-    # Rename CALL_PURE to CALL.
+    # Rename CALL_PURE and CALL_LOOPINVARIANT to CALL.
     # Simplify the VIRTUAL_REF_* so that they don't show up in the backend.
     if op.getopnum() == rop.CALL_PURE:
         op = ResOperation(rop.CALL, op.getarglist()[1:], op.result,
                           op.getdescr())
+    elif op.getopnum() == rop.CALL_LOOPINVARIANT:
+        op = op.copy_and_change(rop.CALL)
     elif op.getopnum() == rop.VIRTUAL_REF:
         op = ResOperation(rop.SAME_AS, [op.getarg(0)], op.result)
     elif op.getopnum() == rop.VIRTUAL_REF_FINISH:

Modified: pypy/branch/jit-unroll-loops/pypy/jit/metainterp/test/test_basic.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/jit/metainterp/test/test_basic.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/jit/metainterp/test/test_basic.py	Sat Oct 30 16:41:17 2010
@@ -2,6 +2,7 @@
 import sys
 from pypy.rlib.jit import JitDriver, we_are_jitted, hint, dont_look_inside
 from pypy.rlib.jit import OPTIMIZER_FULL, OPTIMIZER_SIMPLE, loop_invariant
+from pypy.rlib.jit import jit_debug, assert_green, AssertGreenFailed
 from pypy.jit.metainterp.warmspot import ll_meta_interp, get_stats
 from pypy.jit.backend.llgraph import runner
 from pypy.jit.metainterp import pyjitpl, history
@@ -44,6 +45,7 @@
         num_green_args = 0
         portal_graph = graphs[0]
         virtualizable_info = None
+        greenfield_info = None
         result_type = result_kind
         portal_runner_ptr = "???"
 
@@ -1775,6 +1777,33 @@
         res = self.interp_operations(f, [10, 3.5])
         assert res == 3.5
 
+    def test_jit_debug(self):
+        myjitdriver = JitDriver(greens = [], reds = ['x'])
+        class A:
+            pass
+        def f(x):
+            while x > 0:
+                myjitdriver.can_enter_jit(x=x)
+                myjitdriver.jit_merge_point(x=x)
+                jit_debug("hi there:", x)
+                jit_debug("foobar")
+                x -= 1
+            return x
+        res = self.meta_interp(f, [8])
+        assert res == 0
+        self.check_loops(jit_debug=2)
+
+    def test_assert_green(self):
+        def f(x, promote):
+            if promote:
+                x = hint(x, promote=True)
+            assert_green(x)
+            return x
+        res = self.interp_operations(f, [8, 1])
+        assert res == 8
+        py.test.raises(AssertGreenFailed, self.interp_operations, f, [8, 0])
+
+
 class TestOOtype(BasicTests, OOJitMixin):
 
     def test_oohash(self):
@@ -1882,7 +1911,7 @@
             c = bool(p1)
             d = not bool(p2)
             return 1000*a + 100*b + 10*c + d
-        prebuilt = [lltype.malloc(TP, flavor='raw')] * 2
+        prebuilt = [lltype.malloc(TP, flavor='raw', immortal=True)] * 2
         expected = f(0, 1)
         assert self.interp_operations(f, [0, 1]) == expected
 

Modified: pypy/branch/jit-unroll-loops/pypy/jit/metainterp/test/test_compile.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/jit/metainterp/test/test_compile.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/jit/metainterp/test/test_compile.py	Sat Oct 30 16:41:17 2010
@@ -6,8 +6,8 @@
 from pypy.jit.metainterp.compile import ResumeGuardCountersInt
 from pypy.jit.metainterp.compile import compile_tmp_callback
 from pypy.jit.metainterp import optimize_nopspec, jitprof, typesystem, compile
-from pypy.jit.metainterp.test.oparser import parse
 from pypy.jit.metainterp.test.test_optimizefindnode import LLtypeMixin
+from pypy.jit.tool.oparser import parse
 
 
 def test_insert_loop_token():

Modified: pypy/branch/jit-unroll-loops/pypy/jit/metainterp/test/test_jitdriver.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/jit/metainterp/test/test_jitdriver.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/jit/metainterp/test/test_jitdriver.py	Sat Oct 30 16:41:17 2010
@@ -72,6 +72,33 @@
         # we expect no loop at all for 'loop1': it should always be inlined
         self.check_tree_loop_count(2)    # 1 x loop, 1 x enter bridge
 
+    def test_inactive_jitdriver(self):
+        myjitdriver1 = JitDriver(greens=[], reds=['n', 'm'],
+                                 get_printable_location = getloc1)
+        myjitdriver2 = JitDriver(greens=['g'], reds=['r'],
+                                 get_printable_location = getloc2)
+        #
+        myjitdriver1.active = False    # <===
+        #
+        def loop1(n, m):
+            while n > 0:
+                myjitdriver1.can_enter_jit(n=n, m=m)
+                myjitdriver1.jit_merge_point(n=n, m=m)
+                n -= m
+            return n
+        #
+        def loop2(g, r):
+            while r > 0:
+                myjitdriver2.can_enter_jit(g=g, r=r)
+                myjitdriver2.jit_merge_point(g=g, r=r)
+                r += loop1(r, g) + (-1)
+            return r
+        #
+        res = self.meta_interp(loop2, [4, 40], repeat=7, inline=True)
+        assert res == loop2(4, 40)
+        # we expect no int_sub, but a residual call
+        self.check_loops(int_sub=0, call=1)
+
 
 class TestLLtype(MultipleJitDriversTests, LLJitMixin):
     pass

Modified: pypy/branch/jit-unroll-loops/pypy/jit/metainterp/test/test_logger.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/jit/metainterp/test/test_logger.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/jit/metainterp/test/test_logger.py	Sat Oct 30 16:41:17 2010
@@ -1,6 +1,6 @@
 import sys
 from pypy.rlib import debug
-from pypy.jit.metainterp.test.oparser import pure_parse
+from pypy.jit.tool.oparser import pure_parse
 from pypy.jit.metainterp import logger
 from pypy.jit.metainterp.typesystem import llhelper
 from StringIO import StringIO

Modified: pypy/branch/jit-unroll-loops/pypy/jit/metainterp/test/test_oparser.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/jit/metainterp/test/test_oparser.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/jit/metainterp/test/test_oparser.py	Sat Oct 30 16:41:17 2010
@@ -1,7 +1,7 @@
 
 from pypy.rpython.lltypesystem import lltype, llmemory
 
-from pypy.jit.metainterp.test.oparser import parse
+from pypy.jit.tool.oparser import parse
 from pypy.jit.metainterp.resoperation import rop
 from pypy.jit.metainterp.history import AbstractDescr, BoxInt, LoopToken,\
      BoxFloat

Modified: pypy/branch/jit-unroll-loops/pypy/jit/metainterp/test/test_optimizebasic.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/jit/metainterp/test/test_optimizebasic.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/jit/metainterp/test/test_optimizebasic.py	Sat Oct 30 16:41:17 2010
@@ -131,14 +131,21 @@
 # ____________________________________________________________
 
 def equaloplists(oplist1, oplist2, strict_fail_args=True, remap={}):
-    print '-'*20, 'Comparing lists', '-'*20
+    # try to use the full width of the terminal to display the list
+    # unfortunately, does not work with the default capture method of py.test
+    # (which is fd), you you need to use either -s or --capture=sys, else you
+    # get the standard 80 columns width
+    totwidth = py.io.get_terminal_width()
+    width = totwidth / 2 - 1
+    print ' Comparing lists '.center(totwidth, '-')
+    print '%s| %s' % ('optimized'.center(width), 'expected'.center(width))
     for op1, op2 in zip(oplist1, oplist2):
         txt1 = str(op1)
         txt2 = str(op2)
         while txt1 or txt2:
-            print '%-39s| %s' % (txt1[:39], txt2[:39])
-            txt1 = txt1[39:]
-            txt2 = txt2[39:]
+            print '%s| %s' % (txt1[:width].ljust(width), txt2[:width])
+            txt1 = txt1[width:]
+            txt2 = txt2[width:]
         assert op1.getopnum() == op2.getopnum()
         assert op1.numargs() == op2.numargs()
         for i in range(op1.numargs()):

Modified: pypy/branch/jit-unroll-loops/pypy/jit/metainterp/test/test_optimizefindnode.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/jit/metainterp/test/test_optimizefindnode.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/jit/metainterp/test/test_optimizefindnode.py	Sat Oct 30 16:41:17 2010
@@ -18,7 +18,7 @@
 from pypy.jit.metainterp.specnode import ConstantSpecNode
 from pypy.jit.codewriter.effectinfo import EffectInfo
 from pypy.jit.codewriter.heaptracker import register_known_gctype, adr2int
-from pypy.jit.metainterp.test.oparser import parse
+from pypy.jit.tool.oparser import parse
 
 def test_sort_descrs():
     class PseudoDescr(AbstractDescr):
@@ -117,33 +117,32 @@
                             EffectInfo.EF_FORCES_VIRTUAL_OR_VIRTUALIZABLE))
     arraycopydescr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
                  EffectInfo([], [], [], oopspecindex=EffectInfo.OS_ARRAYCOPY))
-    strconcatdescr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
-                 EffectInfo([], [], [], oopspecindex=EffectInfo.OS_STR_CONCAT))
-    slicedescr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
-                 EffectInfo([], [], [], oopspecindex=EffectInfo.OS_STR_SLICE))
-    strequaldescr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
-                 EffectInfo([], [], [], oopspecindex=EffectInfo.OS_STR_EQUAL))
-    streq_slice_checknull_descr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
-                 EffectInfo([], [], [],
-                     oopspecindex=EffectInfo.OS_STREQ_SLICE_CHECKNULL))
-    streq_slice_nonnull_descr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
-                 EffectInfo([], [], [],
-                     oopspecindex=EffectInfo.OS_STREQ_SLICE_NONNULL))
-    streq_slice_char_descr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
-                 EffectInfo([], [], [],
-                     oopspecindex=EffectInfo.OS_STREQ_SLICE_CHAR))
-    streq_nonnull_descr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
-                 EffectInfo([], [], [],
-                     oopspecindex=EffectInfo.OS_STREQ_NONNULL))
-    streq_nonnull_char_descr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
-                 EffectInfo([], [], [],
-                     oopspecindex=EffectInfo.OS_STREQ_NONNULL_CHAR))
-    streq_checknull_char_descr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
-                 EffectInfo([], [], [],
-                     oopspecindex=EffectInfo.OS_STREQ_CHECKNULL_CHAR))
-    streq_lengthok_descr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
-                 EffectInfo([], [], [],
-                     oopspecindex=EffectInfo.OS_STREQ_LENGTHOK))
+
+    for _name, _os in [
+        ('strconcatdescr',               'OS_STR_CONCAT'),
+        ('strslicedescr',                'OS_STR_SLICE'),
+        ('strequaldescr',                'OS_STR_EQUAL'),
+        ('streq_slice_checknull_descr',  'OS_STREQ_SLICE_CHECKNULL'),
+        ('streq_slice_nonnull_descr',    'OS_STREQ_SLICE_NONNULL'),
+        ('streq_slice_char_descr',       'OS_STREQ_SLICE_CHAR'),
+        ('streq_nonnull_descr',          'OS_STREQ_NONNULL'),
+        ('streq_nonnull_char_descr',     'OS_STREQ_NONNULL_CHAR'),
+        ('streq_checknull_char_descr',   'OS_STREQ_CHECKNULL_CHAR'),
+        ('streq_lengthok_descr',         'OS_STREQ_LENGTHOK'),
+        ]:
+        _oopspecindex = getattr(EffectInfo, _os)
+        locals()[_name] = \
+            cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
+                EffectInfo([], [], [], oopspecindex=_oopspecindex))
+        #
+        _oopspecindex = getattr(EffectInfo, _os.replace('STR', 'UNI'))
+        locals()[_name.replace('str', 'unicode')] = \
+            cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
+                EffectInfo([], [], [], oopspecindex=_oopspecindex))
+
+    s2u_descr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
+                EffectInfo([], [], [], oopspecindex=EffectInfo.OS_STR2UNICODE))
+    #
 
     class LoopToken(AbstractDescr):
         pass

Modified: pypy/branch/jit-unroll-loops/pypy/jit/metainterp/test/test_optimizeopt.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/jit/metainterp/test/test_optimizeopt.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/jit/metainterp/test/test_optimizeopt.py	Sat Oct 30 16:41:17 2010
@@ -12,7 +12,7 @@
 from pypy.jit.metainterp.jitprof import EmptyProfiler
 from pypy.jit.metainterp import executor, compile, resume, history
 from pypy.jit.metainterp.resoperation import rop, opname, ResOperation
-from pypy.jit.metainterp.test.oparser import pure_parse
+from pypy.jit.tool.oparser import pure_parse
 from pypy.jit.metainterp.test.test_optimizebasic import equaloplists
 
 class Fake(object):
@@ -28,7 +28,6 @@
         self.globaldata = Fake()
 
 # ____________________________________________________________
-
 class Storage(compile.ResumeGuardDescr):
     "for tests."
     def __init__(self, metainterp_sd=None, original_greenkey=None):
@@ -93,6 +92,10 @@
             expected = self.parse(expected_preamble)
             self.assert_equal(loop.preamble, expected)
 
+        return loop
+
+class OptimizeOptTest(BaseTestOptimizeOpt):
+
     def test_simple(self):
         ops = """
         []
@@ -2609,7 +2612,7 @@
             ''', rop.GUARD_TRUE)
 
 
-class TestLLtype(BaseTestOptimizeOpt, LLtypeMixin):
+class TestLLtype(OptimizeOptTest, LLtypeMixin):
 
     def test_residual_call_does_not_invalidate_caches(self):
         ops = """
@@ -3455,7 +3458,7 @@
         i0 = strlen(p0)
         jump(p0)
         """
-        self.optimize_loop(ops, 'Not', expected)
+        self.optimize_strunicode_loop(ops, 'Not', expected)
 
     def test_addsub_const(self):
         ops = """
@@ -3900,6 +3903,15 @@
         """
         self.optimize_loop(ops, 'Not, Not', expected)
 
+    # ----------
+    def optimize_strunicode_loop(self, ops, spectext, optops):
+        # check with the arguments passed in
+        self.optimize_loop(ops, spectext, optops)
+        # check with replacing 'str' with 'unicode' everywhere
+        self.optimize_loop(ops.replace('str','unicode').replace('s"', 'u"'),
+                           spectext,
+                           optops.replace('str','unicode').replace('s"', 'u"'))
+
     def test_newstr_1(self):
         ops = """
         [i0]
@@ -3912,7 +3924,7 @@
         [i0]
         jump(i0)
         """
-        self.optimize_loop(ops, 'Not', expected)
+        self.optimize_strunicode_loop(ops, 'Not', expected)
 
     def test_newstr_2(self):
         ops = """
@@ -3928,7 +3940,7 @@
         [i0, i1]
         jump(i1, i0)
         """
-        self.optimize_loop(ops, 'Not, Not', expected)
+        self.optimize_strunicode_loop(ops, 'Not, Not', expected)
 
     def test_str_concat_1(self):
         ops = """
@@ -3949,7 +3961,7 @@
         copystrcontent(p2, p3, 0, i4, i5)
         jump(p2, p3)
         """
-        self.optimize_loop(ops, 'Not, Not', expected)
+        self.optimize_strunicode_loop(ops, 'Not, Not', expected)
 
     def test_str_concat_vstr2_str(self):
         ops = """
@@ -3972,7 +3984,7 @@
         copystrcontent(p2, p3, 0, 2, i4)
         jump(i1, i0, p3)
         """
-        self.optimize_loop(ops, 'Not, Not, Not', expected)
+        self.optimize_strunicode_loop(ops, 'Not, Not, Not', expected)
 
     def test_str_concat_str_vstr2(self):
         ops = """
@@ -3996,7 +4008,7 @@
         i6 = int_add(i5, 1)      # will be killed by the backend
         jump(i1, i0, p3)
         """
-        self.optimize_loop(ops, 'Not, Not, Not', expected)
+        self.optimize_strunicode_loop(ops, 'Not, Not, Not', expected)
 
     def test_str_concat_str_str_str(self):
         ops = """
@@ -4023,12 +4035,12 @@
         copystrcontent(p3, p5, 0, i12b, i3b)
         jump(p2, p3, p5)
         """
-        self.optimize_loop(ops, 'Not, Not, Not', expected)
+        self.optimize_strunicode_loop(ops, 'Not, Not, Not', expected)
 
     def test_str_concat_str_cstr1(self):
         ops = """
         [p2]
-        p3 = call(0, p2, "x", descr=strconcatdescr)
+        p3 = call(0, p2, s"x", descr=strconcatdescr)
         jump(p3)
         """
         expected = """
@@ -4042,28 +4054,28 @@
         i5 = int_add(i4, 1)      # will be killed by the backend
         jump(p3)
         """
-        self.optimize_loop(ops, 'Not', expected)
+        self.optimize_strunicode_loop(ops, 'Not', expected)
 
     def test_str_concat_consts(self):
         ops = """
         []
-        p1 = same_as("ab")
-        p2 = same_as("cde")
+        p1 = same_as(s"ab")
+        p2 = same_as(s"cde")
         p3 = call(0, p1, p2, descr=strconcatdescr)
         escape(p3)
         jump()
         """
         expected = """
         []
-        escape("abcde")
+        escape(s"abcde")
         jump()
         """
-        self.optimize_loop(ops, '', expected)
+        self.optimize_strunicode_loop(ops, '', expected)
 
     def test_str_slice_1(self):
         ops = """
         [p1, i1, i2]
-        p2 = call(0, p1, i1, i2, descr=slicedescr)
+        p2 = call(0, p1, i1, i2, descr=strslicedescr)
         jump(p2, i1, i2)
         """
         expected = """
@@ -4073,12 +4085,12 @@
         copystrcontent(p1, p2, i1, 0, i3)
         jump(p2, i1, i2)
         """
-        self.optimize_loop(ops, 'Not, Not, Not', expected)
+        self.optimize_strunicode_loop(ops, 'Not, Not, Not', expected)
 
     def test_str_slice_2(self):
         ops = """
         [p1, i2]
-        p2 = call(0, p1, 0, i2, descr=slicedescr)
+        p2 = call(0, p1, 0, i2, descr=strslicedescr)
         jump(p2, i2)
         """
         expected = """
@@ -4087,13 +4099,13 @@
         copystrcontent(p1, p2, 0, 0, i2)
         jump(p2, i2)
         """
-        self.optimize_loop(ops, 'Not, Not', expected)
+        self.optimize_strunicode_loop(ops, 'Not, Not', expected)
 
     def test_str_slice_3(self):
         ops = """
         [p1, i1, i2, i3, i4]
-        p2 = call(0, p1, i1, i2, descr=slicedescr)
-        p3 = call(0, p2, i3, i4, descr=slicedescr)
+        p2 = call(0, p1, i1, i2, descr=strslicedescr)
+        p3 = call(0, p2, i3, i4, descr=strslicedescr)
         jump(p3, i1, i2, i3, i4)
         """
         expected = """
@@ -4105,12 +4117,12 @@
         copystrcontent(p1, p3, i6, 0, i5)
         jump(p3, i1, i2, i3, i4)
         """
-        self.optimize_loop(ops, 'Not, Not, Not, Not, Not', expected)
+        self.optimize_strunicode_loop(ops, 'Not, Not, Not, Not, Not', expected)
 
     def test_str_slice_getitem1(self):
         ops = """
         [p1, i1, i2, i3]
-        p2 = call(0, p1, i1, i2, descr=slicedescr)
+        p2 = call(0, p1, i1, i2, descr=strslicedescr)
         i4 = strgetitem(p2, i3)
         escape(i4)
         jump(p1, i1, i2, i3)
@@ -4123,7 +4135,7 @@
         escape(i4)
         jump(p1, i1, i2, i3)
         """
-        self.optimize_loop(ops, 'Not, Not, Not, Not', expected)
+        self.optimize_strunicode_loop(ops, 'Not, Not, Not, Not', expected)
 
     def test_str_slice_plain(self):
         ops = """
@@ -4131,7 +4143,7 @@
         p1 = newstr(2)
         strsetitem(p1, 0, i3)
         strsetitem(p1, 1, i4)
-        p2 = call(0, p1, 1, 2, descr=slicedescr)
+        p2 = call(0, p1, 1, 2, descr=strslicedescr)
         i5 = strgetitem(p2, 0)
         escape(i5)
         jump(i3, i4)
@@ -4141,12 +4153,12 @@
         escape(i4)
         jump(i3, i4)
         """
-        self.optimize_loop(ops, 'Not, Not', expected)
+        self.optimize_strunicode_loop(ops, 'Not, Not', expected)
 
     def test_str_slice_concat(self):
         ops = """
         [p1, i1, i2, p2]
-        p3 = call(0, p1, i1, i2, descr=slicedescr)
+        p3 = call(0, p1, i1, i2, descr=strslicedescr)
         p4 = call(0, p3, p2, descr=strconcatdescr)
         jump(p4, i1, i2, p2)
         """
@@ -4162,10 +4174,10 @@
         copystrcontent(p2, p4, 0, i3, i4b)
         jump(p4, i1, i2, p2)
         """
-        self.optimize_loop(ops, 'Not, Not, Not, Not', expected)
+        self.optimize_strunicode_loop(ops, 'Not, Not, Not, Not', expected)
 
     # ----------
-    def optimize_loop_extradescrs(self, ops, spectext, optops):
+    def optimize_strunicode_loop_extradescrs(self, ops, spectext, optops):
         from pypy.jit.metainterp.optimizeopt import string
         def my_callinfo_for_oopspec(oopspecindex):
             calldescrtype = type(LLtypeMixin.strequaldescr)
@@ -4180,7 +4192,7 @@
         saved = string.callinfo_for_oopspec
         try:
             string.callinfo_for_oopspec = my_callinfo_for_oopspec
-            self.optimize_loop(ops, spectext, optops)
+            self.optimize_strunicode_loop(ops, spectext, optops)
         finally:
             string.callinfo_for_oopspec = saved
 
@@ -4191,7 +4203,7 @@
         escape(i0)
         jump(p1, p2)
         """
-        self.optimize_loop_extradescrs(ops, 'Not, Not', ops)
+        self.optimize_strunicode_loop_extradescrs(ops, 'Not, Not', ops)
 
     def test_str_equal_noop2(self):
         ops = """
@@ -4216,12 +4228,13 @@
         escape(i0)
         jump(p1, p2, p3)
         """
-        self.optimize_loop_extradescrs(ops, 'Not, Not, Not', expected)
+        self.optimize_strunicode_loop_extradescrs(ops, 'Not, Not, Not',
+                                                  expected)
 
     def test_str_equal_slice1(self):
         ops = """
         [p1, i1, i2, p3]
-        p4 = call(0, p1, i1, i2, descr=slicedescr)
+        p4 = call(0, p1, i1, i2, descr=strslicedescr)
         i0 = call(0, p4, p3, descr=strequaldescr)
         escape(i0)
         jump(p1, i1, i2, p3)
@@ -4233,12 +4246,13 @@
         escape(i0)
         jump(p1, i1, i2, p3)
         """
-        self.optimize_loop_extradescrs(ops, 'Not, Not, Not, Not', expected)
+        self.optimize_strunicode_loop_extradescrs(ops, 'Not, Not, Not, Not',
+                                                  expected)
 
     def test_str_equal_slice2(self):
         ops = """
         [p1, i1, i2, p3]
-        p4 = call(0, p1, i1, i2, descr=slicedescr)
+        p4 = call(0, p1, i1, i2, descr=strslicedescr)
         i0 = call(0, p3, p4, descr=strequaldescr)
         escape(i0)
         jump(p1, i1, i2, p3)
@@ -4250,13 +4264,14 @@
         escape(i0)
         jump(p1, i1, i2, p3)
         """
-        self.optimize_loop_extradescrs(ops, 'Not, Not, Not, Not', expected)
+        self.optimize_strunicode_loop_extradescrs(ops, 'Not, Not, Not, Not',
+                                                  expected)
 
     def test_str_equal_slice3(self):
         ops = """
         [p1, i1, i2, p3]
         guard_nonnull(p3) []
-        p4 = call(0, p1, i1, i2, descr=slicedescr)
+        p4 = call(0, p1, i1, i2, descr=strslicedescr)
         i0 = call(0, p3, p4, descr=strequaldescr)
         escape(i0)
         jump(p1, i1, i2, p3)
@@ -4269,13 +4284,14 @@
         escape(i0)
         jump(p1, i1, i2, p3)
         """
-        self.optimize_loop_extradescrs(ops, 'Not, Not, Not, Not', expected)
+        self.optimize_strunicode_loop_extradescrs(ops, 'Not, Not, Not, Not',
+                                                  expected)
 
     def test_str_equal_slice4(self):
         ops = """
         [p1, i1, i2]
-        p3 = call(0, p1, i1, i2, descr=slicedescr)
-        i0 = call(0, p3, "x", descr=strequaldescr)
+        p3 = call(0, p1, i1, i2, descr=strslicedescr)
+        i0 = call(0, p3, s"x", descr=strequaldescr)
         escape(i0)
         jump(p1, i1, i2)
         """
@@ -4286,12 +4302,13 @@
         escape(i0)
         jump(p1, i1, i2)
         """
-        self.optimize_loop_extradescrs(ops, 'Not, Not, Not', expected)
+        self.optimize_strunicode_loop_extradescrs(ops, 'Not, Not, Not',
+                                                  expected)
 
     def test_str_equal_slice5(self):
         ops = """
         [p1, i1, i2, i3]
-        p4 = call(0, p1, i1, i2, descr=slicedescr)
+        p4 = call(0, p1, i1, i2, descr=strslicedescr)
         p5 = newstr(1)
         strsetitem(p5, 0, i3)
         i0 = call(0, p5, p4, descr=strequaldescr)
@@ -4305,7 +4322,8 @@
         escape(i0)
         jump(p1, i1, i2, i3)
         """
-        self.optimize_loop_extradescrs(ops, 'Not, Not, Not, Not', expected)
+        self.optimize_strunicode_loop_extradescrs(ops, 'Not, Not, Not, Not',
+                                                  expected)
 
     def test_str_equal_none1(self):
         ops = """
@@ -4320,7 +4338,7 @@
         escape(i0)
         jump(p1)
         """
-        self.optimize_loop_extradescrs(ops, 'Not', expected)
+        self.optimize_strunicode_loop_extradescrs(ops, 'Not', expected)
 
     def test_str_equal_none2(self):
         ops = """
@@ -4335,30 +4353,30 @@
         escape(i0)
         jump(p1)
         """
-        self.optimize_loop_extradescrs(ops, 'Not', expected)
+        self.optimize_strunicode_loop_extradescrs(ops, 'Not', expected)
 
     def test_str_equal_nonnull1(self):
         ops = """
         [p1]
         guard_nonnull(p1) []
-        i0 = call(0, p1, "hello world", descr=strequaldescr)
+        i0 = call(0, p1, s"hello world", descr=strequaldescr)
         escape(i0)
         jump(p1)
         """
         expected = """
         [p1]
         guard_nonnull(p1) []
-        i0 = call(0, p1, "hello world", descr=streq_nonnull_descr)
+        i0 = call(0, p1, s"hello world", descr=streq_nonnull_descr)
         escape(i0)
         jump(p1)
         """
-        self.optimize_loop_extradescrs(ops, 'Not', expected)
+        self.optimize_strunicode_loop_extradescrs(ops, 'Not', expected)
 
     def test_str_equal_nonnull2(self):
         ops = """
         [p1]
         guard_nonnull(p1) []
-        i0 = call(0, p1, "", descr=strequaldescr)
+        i0 = call(0, p1, s"", descr=strequaldescr)
         escape(i0)
         jump(p1)
         """
@@ -4370,13 +4388,13 @@
         escape(i0)
         jump(p1)
         """
-        self.optimize_loop_extradescrs(ops, 'Not', expected)
+        self.optimize_strunicode_loop_extradescrs(ops, 'Not', expected)
 
     def test_str_equal_nonnull3(self):
         ops = """
         [p1]
         guard_nonnull(p1) []
-        i0 = call(0, p1, "x", descr=strequaldescr)
+        i0 = call(0, p1, s"x", descr=strequaldescr)
         escape(i0)
         jump(p1)
         """
@@ -4387,13 +4405,13 @@
         escape(i0)
         jump(p1)
         """
-        self.optimize_loop_extradescrs(ops, 'Not', expected)
+        self.optimize_strunicode_loop_extradescrs(ops, 'Not', expected)
 
     def test_str_equal_nonnull4(self):
         ops = """
         [p1, p2]
         p4 = call(0, p1, p2, descr=strconcatdescr)
-        i0 = call(0, "hello world", p4, descr=strequaldescr)
+        i0 = call(0, s"hello world", p4, descr=strequaldescr)
         escape(i0)
         jump(p1, p2)
         """
@@ -4408,17 +4426,17 @@
         i5 = strlen(p2)
         i6 = int_add(i4, i5)      # will be killed by the backend
         copystrcontent(p2, p4, 0, i4, i5)
-        i0 = call(0, "hello world", p4, descr=streq_nonnull_descr)
+        i0 = call(0, s"hello world", p4, descr=streq_nonnull_descr)
         escape(i0)
         jump(p1, p2)
         """
-        self.optimize_loop_extradescrs(ops, 'Not, Not', expected)
+        self.optimize_strunicode_loop_extradescrs(ops, 'Not, Not', expected)
 
     def test_str_equal_chars0(self):
         ops = """
         [i1]
         p1 = newstr(0)
-        i0 = call(0, p1, "", descr=strequaldescr)
+        i0 = call(0, p1, s"", descr=strequaldescr)
         escape(i0)
         jump(i1)
         """
@@ -4427,14 +4445,14 @@
         escape(1)
         jump(i1)
         """
-        self.optimize_loop_extradescrs(ops, 'Not', expected)
+        self.optimize_strunicode_loop_extradescrs(ops, 'Not', expected)
 
     def test_str_equal_chars1(self):
         ops = """
         [i1]
         p1 = newstr(1)
         strsetitem(p1, 0, i1)
-        i0 = call(0, p1, "x", descr=strequaldescr)
+        i0 = call(0, p1, s"x", descr=strequaldescr)
         escape(i0)
         jump(i1)
         """
@@ -4444,7 +4462,7 @@
         escape(i0)
         jump(i1)
         """
-        self.optimize_loop_extradescrs(ops, 'Not', expected)
+        self.optimize_strunicode_loop_extradescrs(ops, 'Not', expected)
 
     def test_str_equal_chars2(self):
         ops = """
@@ -4452,7 +4470,7 @@
         p1 = newstr(2)
         strsetitem(p1, 0, i1)
         strsetitem(p1, 1, i2)
-        i0 = call(0, p1, "xy", descr=strequaldescr)
+        i0 = call(0, p1, s"xy", descr=strequaldescr)
         escape(i0)
         jump(i1, i2)
         """
@@ -4461,16 +4479,16 @@
         p1 = newstr(2)
         strsetitem(p1, 0, i1)
         strsetitem(p1, 1, i2)
-        i0 = call(0, p1, "xy", descr=streq_lengthok_descr)
+        i0 = call(0, p1, s"xy", descr=streq_lengthok_descr)
         escape(i0)
         jump(i1, i2)
         """
-        self.optimize_loop_extradescrs(ops, 'Not, Not', expected)
+        self.optimize_strunicode_loop_extradescrs(ops, 'Not, Not', expected)
 
     def test_str_equal_chars3(self):
         ops = """
         [p1]
-        i0 = call(0, "x", p1, descr=strequaldescr)
+        i0 = call(0, s"x", p1, descr=strequaldescr)
         escape(i0)
         jump(p1)
         """
@@ -4480,14 +4498,14 @@
         escape(i0)
         jump(p1)
         """
-        self.optimize_loop_extradescrs(ops, 'Not', expected)
+        self.optimize_strunicode_loop_extradescrs(ops, 'Not', expected)
 
     def test_str_equal_lengthmismatch1(self):
         ops = """
         [i1]
         p1 = newstr(1)
         strsetitem(p1, 0, i1)
-        i0 = call(0, "xy", p1, descr=strequaldescr)
+        i0 = call(0, s"xy", p1, descr=strequaldescr)
         escape(i0)
         jump(i1)
         """
@@ -4496,13 +4514,36 @@
         escape(0)
         jump(i1)
         """
-        self.optimize_loop_extradescrs(ops, 'Not', expected)
+        self.optimize_strunicode_loop_extradescrs(ops, 'Not', expected)
 
-    # XXX unicode operations
-    # XXX str2unicode
+    def test_str2unicode_constant(self):
+        ops = """
+        []
+        p0 = call(0, "xy", descr=s2u_descr)      # string -> unicode
+        escape(p0)
+        jump()
+        """
+        expected = """
+        []
+        escape(u"xy")
+        jump()
+        """
+        self.optimize_strunicode_loop_extradescrs(ops, '', expected)
+
+    def test_str2unicode_nonconstant(self):
+        ops = """
+        [p0]
+        p1 = call(0, p0, descr=s2u_descr)      # string -> unicode
+        escape(p1)
+        jump(p1)
+        """
+        self.optimize_strunicode_loop_extradescrs(ops, 'Not', ops)
+        # more generally, supporting non-constant but virtual cases is
+        # not obvious, because of the exception UnicodeDecodeError that
+        # can be raised by ll_str2unicode()
 
 
-##class TestOOtype(BaseTestOptimizeOpt, OOtypeMixin):
+##class TestOOtype(OptimizeOptTest, OOtypeMixin):
 
 ##    def test_instanceof(self):
 ##        ops = """

Modified: pypy/branch/jit-unroll-loops/pypy/jit/metainterp/test/test_resume.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/jit/metainterp/test/test_resume.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/jit/metainterp/test/test_resume.py	Sat Oct 30 16:41:17 2010
@@ -240,6 +240,17 @@
         return FakeBuiltObject(strconcat=[left, right])
     def slice_string(self, str, start, length):
         return FakeBuiltObject(strslice=[str, start, length])
+    def allocate_unicode(self, length):
+        return FakeBuiltObject(unistring=[None]*length)
+    def unicode_setitem(self, unistring, i, fieldnum):
+        value, tag = untag(fieldnum)
+        assert tag == TAGINT
+        assert 0 <= i < len(unistring.unistring)
+        unistring.unistring[i] = value
+    def concat_unicodes(self, left, right):
+        return FakeBuiltObject(uniconcat=[left, right])
+    def slice_unicode(self, str, start, length):
+        return FakeBuiltObject(unislice=[str, start, length])
 
 class FakeBuiltObject(object):
     def __init__(self, **kwds):
@@ -304,6 +315,30 @@
     assert reader.force_all_virtuals() == [
         FakeBuiltObject(strslice=info.fieldnums)]
 
+def test_vuniplaininfo():
+    info = VUniPlainInfo()
+    info.fieldnums = [tag(60, TAGINT)]
+    reader = FakeResumeDataReader()
+    reader._prepare_virtuals([info])
+    assert reader.force_all_virtuals() == [
+        FakeBuiltObject(unistring=[60])]
+
+def test_vuniconcatinfo():
+    info = VUniConcatInfo()
+    info.fieldnums = [tag(10, TAGBOX), tag(20, TAGBOX)]
+    reader = FakeResumeDataReader()
+    reader._prepare_virtuals([info])
+    assert reader.force_all_virtuals() == [
+        FakeBuiltObject(uniconcat=info.fieldnums)]
+
+def test_vunisliceinfo():
+    info = VUniSliceInfo()
+    info.fieldnums = [tag(10, TAGBOX), tag(20, TAGBOX), tag(30, TAGBOX)]
+    reader = FakeResumeDataReader()
+    reader._prepare_virtuals([info])
+    assert reader.force_all_virtuals() == [
+        FakeBuiltObject(unislice=info.fieldnums)]
+
 # ____________________________________________________________
 
 

Modified: pypy/branch/jit-unroll-loops/pypy/jit/metainterp/test/test_string.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/jit/metainterp/test/test_string.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/jit/metainterp/test/test_string.py	Sat Oct 30 16:41:17 2010
@@ -6,14 +6,17 @@
 
 
 class StringTests:
+    _str, _chr = str, chr
+
     def test_eq_residual(self):
+        _str = self._str
         jitdriver = JitDriver(greens = [], reds = ['n', 'i', 's'])
-        global_s = "hello"
+        global_s = _str("hello")
         def f(n, b, s):
             if b:
-                s += "ello"
+                s += _str("ello")
             else:
-                s += "allo"
+                s += _str("allo")
             i = 0
             while n > 0:
                 jitdriver.can_enter_jit(s=s, n=n, i=i)
@@ -21,18 +24,19 @@
                 n -= 1 + (s == global_s)
                 i += 1
             return i
-        res = self.meta_interp(f, [10, True, 'h'], listops=True)
+        res = self.meta_interp(f, [10, True, _str('h')], listops=True)
         assert res == 5
         self.check_loops(**{self.CALL: 1, self.CALL_PURE: 0})
 
     def test_eq_folded(self):
+        _str = self._str
         jitdriver = JitDriver(greens = ['s'], reds = ['n', 'i'])
-        global_s = "hello"
+        global_s = _str("hello")
         def f(n, b, s):
             if b:
-                s += "ello"
+                s += _str("ello")
             else:
-                s += "allo"
+                s += _str("allo")
             i = 0
             while n > 0:
                 jitdriver.can_enter_jit(s=s, n=n, i=i)
@@ -40,31 +44,18 @@
                 n -= 1 + (s == global_s)
                 i += 1
             return i
-        res = self.meta_interp(f, [10, True, 'h'], listops=True)
+        res = self.meta_interp(f, [10, True, _str('h')], listops=True)
         assert res == 5
         self.check_loops(**{self.CALL: 0, self.CALL_PURE: 0})
 
     def test_newstr(self):
+        _str, _chr = self._str, self._chr
         jitdriver = JitDriver(greens = [], reds = ['n', 'm'])
         def f(n, m):
             while True:
                 jitdriver.can_enter_jit(m=m, n=n)
                 jitdriver.jit_merge_point(m=m, n=n)
-                bytecode = 'adlfkj' + chr(n)
-                res = bytecode[n]
-                m -= 1
-                if m < 0:
-                    return ord(res)
-        res = self.meta_interp(f, [6, 10])
-        assert res == 6
-
-    def test_newunicode(self):
-        jitdriver = JitDriver(greens = [], reds = ['n', 'm'])
-        def f(n, m):
-            while True:
-                jitdriver.can_enter_jit(m=m, n=n)
-                jitdriver.jit_merge_point(m=m, n=n)
-                bytecode = u'adlfkj' + unichr(n)
+                bytecode = _str('adlfkj') + _chr(n)
                 res = bytecode[n]
                 m -= 1
                 if m < 0:
@@ -73,95 +64,96 @@
         assert res == 6
 
     def test_char2string_pure(self):
-        for dochr in [chr, ]: #unichr]:
-            jitdriver = JitDriver(greens = [], reds = ['n'])
-            @dont_look_inside
-            def escape(x):
-                pass
-            def f(n):
-                while n > 0:
-                    jitdriver.can_enter_jit(n=n)
-                    jitdriver.jit_merge_point(n=n)
-                    s = dochr(n)
-                    if not we_are_jitted():
-                        s += s     # forces to be a string
-                    if n > 100:
-                        escape(s)
-                    n -= 1
-                return 42
-            self.meta_interp(f, [6])
-            self.check_loops(newstr=0, strsetitem=0, strlen=0,
-                             newunicode=0, unicodesetitem=0, unicodelen=0)
+        _str, _chr = self._str, self._chr
+        jitdriver = JitDriver(greens = [], reds = ['n'])
+        @dont_look_inside
+        def escape(x):
+            pass
+        def f(n):
+            while n > 0:
+                jitdriver.can_enter_jit(n=n)
+                jitdriver.jit_merge_point(n=n)
+                s = _chr(n)
+                if not we_are_jitted():
+                    s += s     # forces to be a string
+                if n > 100:
+                    escape(s)
+                n -= 1
+            return 42
+        self.meta_interp(f, [6])
+        self.check_loops(newstr=0, strsetitem=0, strlen=0,
+                         newunicode=0, unicodesetitem=0, unicodelen=0)
 
     def test_char2string_escape(self):
-        for dochr in [chr, ]: #unichr]:
-            jitdriver = JitDriver(greens = [], reds = ['n', 'total'])
-            @dont_look_inside
-            def escape(x):
-                return ord(x[0])
-            def f(n):
-                total = 0
-                while n > 0:
-                    jitdriver.can_enter_jit(n=n, total=total)
-                    jitdriver.jit_merge_point(n=n, total=total)
-                    s = dochr(n)
-                    if not we_are_jitted():
-                        s += s    # forces to be a string
-                    total += escape(s)
-                    n -= 1
-                return total
-            res = self.meta_interp(f, [6])
-            assert res == 21
+        _str, _chr = self._str, self._chr
+        jitdriver = JitDriver(greens = [], reds = ['n', 'total'])
+        @dont_look_inside
+        def escape(x):
+            return ord(x[0])
+        def f(n):
+            total = 0
+            while n > 0:
+                jitdriver.can_enter_jit(n=n, total=total)
+                jitdriver.jit_merge_point(n=n, total=total)
+                s = _chr(n)
+                if not we_are_jitted():
+                    s += s    # forces to be a string
+                total += escape(s)
+                n -= 1
+            return total
+        res = self.meta_interp(f, [6])
+        assert res == 21
 
     def test_char2string2char(self):
-        for dochr in [chr, ]: #unichr]:
-            jitdriver = JitDriver(greens = [], reds = ['m', 'total'])
-            def f(m):
-                total = 0
-                while m > 0:
-                    jitdriver.can_enter_jit(m=m, total=total)
-                    jitdriver.jit_merge_point(m=m, total=total)
-                    string = dochr(m)
-                    if m > 100:
-                        string += string    # forces to be a string
-                    # read back the character
-                    c = string[0]
-                    total += ord(c)
-                    m -= 1
-                return total
-            res = self.meta_interp(f, [6])
-            assert res == 21
-            self.check_loops(newstr=0, strgetitem=0, strsetitem=0, strlen=0,
-                             newunicode=0, unicodegetitem=0, unicodesetitem=0,
-                             unicodelen=0)
+        _str, _chr = self._str, self._chr
+        jitdriver = JitDriver(greens = [], reds = ['m', 'total'])
+        def f(m):
+            total = 0
+            while m > 0:
+                jitdriver.can_enter_jit(m=m, total=total)
+                jitdriver.jit_merge_point(m=m, total=total)
+                string = _chr(m)
+                if m > 100:
+                    string += string    # forces to be a string
+                # read back the character
+                c = string[0]
+                total += ord(c)
+                m -= 1
+            return total
+        res = self.meta_interp(f, [6])
+        assert res == 21
+        self.check_loops(newstr=0, strgetitem=0, strsetitem=0, strlen=0,
+                         newunicode=0, unicodegetitem=0, unicodesetitem=0,
+                         unicodelen=0)
 
     def test_strconcat_pure(self):
-        for somestr in ["abc", ]: #u"def"]:
-            jitdriver = JitDriver(greens = [], reds = ['m', 'n'])
-            @dont_look_inside
-            def escape(x):
-                pass
-            mylist = [somestr+str(i) for i in range(10)]
-            def f(n, m):
-                while m >= 0:
-                    jitdriver.can_enter_jit(m=m, n=n)
-                    jitdriver.jit_merge_point(m=m, n=n)
-                    s = mylist[n] + mylist[m]
-                    if m > 100:
-                        escape(s)
-                    m -= 1
-                return 42
-            self.meta_interp(f, [6, 7])
-            self.check_loops(newstr=0, strsetitem=0,
-                             newunicode=0, unicodesetitem=0,
-                             call=0, call_pure=0)
+        _str = self._str
+        jitdriver = JitDriver(greens = [], reds = ['m', 'n'])
+        @dont_look_inside
+        def escape(x):
+            pass
+        mylist = [_str("abc") + _str(i) for i in range(10)]
+        def f(n, m):
+            while m >= 0:
+                jitdriver.can_enter_jit(m=m, n=n)
+                jitdriver.jit_merge_point(m=m, n=n)
+                s = mylist[n] + mylist[m]
+                if m > 100:
+                    escape(s)
+                m -= 1
+            return 42
+        self.meta_interp(f, [6, 7])
+        self.check_loops(newstr=0, strsetitem=0,
+                         newunicode=0, unicodesetitem=0,
+                         call=0, call_pure=0)
 
     def test_strconcat_escape_str_str(self):
+        _str = self._str
         jitdriver = JitDriver(greens = [], reds = ['m', 'n'])
         @dont_look_inside
         def escape(x):
             pass
-        mylist = ["somestr"+str(i) for i in range(10)]
+        mylist = [_str("somestr") + _str(i) for i in range(10)]
         def f(n, m):
             while m >= 0:
                 jitdriver.can_enter_jit(m=m, n=n)
@@ -171,46 +163,64 @@
                 m -= 1
             return 42
         self.meta_interp(f, [6, 7])
-        self.check_loops(newstr=1, strsetitem=0, copystrcontent=2,
-                         call=1, call_pure=0)   # escape
+        if _str is str:
+            self.check_loops(newstr=1, strsetitem=0, copystrcontent=2,
+                             call=1, call_pure=0)   # escape
+        else:
+            self.check_loops(newunicode=1, unicodesetitem=0,
+                             copyunicodecontent=2,
+                             call=1, call_pure=0)   # escape
 
     def test_strconcat_escape_str_char(self):
+        _str, _chr = self._str, self._chr
         jitdriver = JitDriver(greens = [], reds = ['m', 'n'])
         @dont_look_inside
         def escape(x):
             pass
-        mylist = ["somestr"+str(i) for i in range(10)]
+        mylist = [_str("somestr") + _str(i) for i in range(10)]
         def f(n, m):
             while m >= 0:
                 jitdriver.can_enter_jit(m=m, n=n)
                 jitdriver.jit_merge_point(m=m, n=n)
-                s = mylist[n] + chr(m)
+                s = mylist[n] + _chr(m)
                 escape(s)
                 m -= 1
             return 42
         self.meta_interp(f, [6, 7])
-        self.check_loops(newstr=1, strsetitem=1, copystrcontent=1,
-                         call=1, call_pure=0)   # escape
+        if _str is str:
+            self.check_loops(newstr=1, strsetitem=1, copystrcontent=1,
+                             call=1, call_pure=0)   # escape
+        else:
+            self.check_loops(newunicode=1, unicodesetitem=1,
+                             copyunicodecontent=1,
+                             call=1, call_pure=0)   # escape
 
     def test_strconcat_escape_char_str(self):
+        _str, _chr = self._str, self._chr
         jitdriver = JitDriver(greens = [], reds = ['m', 'n'])
         @dont_look_inside
         def escape(x):
             pass
-        mylist = ["somestr"+str(i) for i in range(10)]
+        mylist = [_str("somestr") + _str(i) for i in range(10)]
         def f(n, m):
             while m >= 0:
                 jitdriver.can_enter_jit(m=m, n=n)
                 jitdriver.jit_merge_point(m=m, n=n)
-                s = chr(n) + mylist[m]
+                s = _chr(n) + mylist[m]
                 escape(s)
                 m -= 1
             return 42
         self.meta_interp(f, [6, 7])
-        self.check_loops(newstr=1, strsetitem=1, copystrcontent=1,
-                         call=1, call_pure=0)   # escape
+        if _str is str:
+            self.check_loops(newstr=1, strsetitem=1, copystrcontent=1,
+                             call=1, call_pure=0)   # escape
+        else:
+            self.check_loops(newunicode=1, unicodesetitem=1,
+                             copyunicodecontent=1,
+                             call=1, call_pure=0)   # escape
 
     def test_strconcat_escape_char_char(self):
+        _str, _chr = self._str, self._chr
         jitdriver = JitDriver(greens = [], reds = ['m', 'n'])
         @dont_look_inside
         def escape(x):
@@ -219,91 +229,132 @@
             while m >= 0:
                 jitdriver.can_enter_jit(m=m, n=n)
                 jitdriver.jit_merge_point(m=m, n=n)
-                s = chr(n) + chr(m)
+                s = _chr(n) + _chr(m)
                 escape(s)
                 m -= 1
             return 42
         self.meta_interp(f, [6, 7])
-        self.check_loops(newstr=1, strsetitem=2, copystrcontent=0,
-                         call=1, call_pure=0)   # escape
+        if _str is str:
+            self.check_loops(newstr=1, strsetitem=2, copystrcontent=0,
+                             call=1, call_pure=0)   # escape
+        else:
+            self.check_loops(newunicode=1, unicodesetitem=2,
+                             copyunicodecontent=0,
+                             call=1, call_pure=0)   # escape
 
     def test_strconcat_escape_str_char_str(self):
+        _str, _chr = self._str, self._chr
         jitdriver = JitDriver(greens = [], reds = ['m', 'n'])
         @dont_look_inside
         def escape(x):
             pass
-        mylist = ["somestr"+str(i) for i in range(10)]
+        mylist = [_str("somestr") + _str(i) for i in range(10)]
         def f(n, m):
             while m >= 0:
                 jitdriver.can_enter_jit(m=m, n=n)
                 jitdriver.jit_merge_point(m=m, n=n)
-                s = mylist[n] + chr(n) + mylist[m]
+                s = mylist[n] + _chr(n) + mylist[m]
                 escape(s)
                 m -= 1
             return 42
         self.meta_interp(f, [6, 7])
-        self.check_loops(newstr=1, strsetitem=1, copystrcontent=2,
-                         call=1, call_pure=0)   # escape
+        if _str is str:
+            self.check_loops(newstr=1, strsetitem=1, copystrcontent=2,
+                             call=1, call_pure=0)   # escape
+        else:
+            self.check_loops(newunicode=1, unicodesetitem=1,
+                             copyunicodecontent=2,
+                             call=1, call_pure=0)   # escape
 
     def test_strconcat_guard_fail(self):
-        for somestr in ["abc", ]: #u"def"]:
-            jitdriver = JitDriver(greens = [], reds = ['m', 'n'])
-            @dont_look_inside
-            def escape(x):
-                pass
-            mylist = [somestr+str(i) for i in range(12)]
-            def f(n, m):
-                while m >= 0:
-                    jitdriver.can_enter_jit(m=m, n=n)
-                    jitdriver.jit_merge_point(m=m, n=n)
-                    s = mylist[n] + mylist[m]
-                    if m & 1:
-                        escape(s)
-                    m -= 1
-                return 42
-            self.meta_interp(f, [6, 10])
+        _str = self._str
+        jitdriver = JitDriver(greens = [], reds = ['m', 'n'])
+        @dont_look_inside
+        def escape(x):
+            pass
+        mylist = [_str("abc") + _str(i) for i in range(12)]
+        def f(n, m):
+            while m >= 0:
+                jitdriver.can_enter_jit(m=m, n=n)
+                jitdriver.jit_merge_point(m=m, n=n)
+                s = mylist[n] + mylist[m]
+                if m & 1:
+                    escape(s)
+                m -= 1
+            return 42
+        self.meta_interp(f, [6, 10])
 
     def test_strslice(self):
-        for somestr in ["abc", ]: #u"def"]:
-            jitdriver = JitDriver(greens = [], reds = ['m', 'n'])
-            @dont_look_inside
-            def escape(x):
-                pass
-            def f(n, m):
-                assert n >= 0
-                while m >= 0:
-                    jitdriver.can_enter_jit(m=m, n=n)
-                    jitdriver.jit_merge_point(m=m, n=n)
-                    s = "foobarbazetc"[m:n]
-                    if m <= 5:
-                        escape(s)
-                    m -= 1
-                return 42
-            self.meta_interp(f, [10, 10])
+        _str = self._str
+        longstring = _str("foobarbazetc")
+        jitdriver = JitDriver(greens = [], reds = ['m', 'n'])
+        @dont_look_inside
+        def escape(x):
+            pass
+        def f(n, m):
+            assert n >= 0
+            while m >= 0:
+                jitdriver.can_enter_jit(m=m, n=n)
+                jitdriver.jit_merge_point(m=m, n=n)
+                s = longstring[m:n]
+                if m <= 5:
+                    escape(s)
+                m -= 1
+            return 42
+        self.meta_interp(f, [10, 10])
 
     def test_streq_char(self):
-        for somestr in ["?abcdefg", ]: #u"def"]:
-            jitdriver = JitDriver(greens = [], reds = ['m', 'n'])
-            @dont_look_inside
-            def escape(x):
-                pass
-            def f(n, m):
-                assert n >= 0
-                while m >= 0:
-                    jitdriver.can_enter_jit(m=m, n=n)
-                    jitdriver.jit_merge_point(m=m, n=n)
-                    s = somestr[:m]
-                    escape(s == "?")
-                    m -= 1
-                return 42
-            self.meta_interp(f, [6, 7])
-            self.check_loops(newstr=0, newunicode=0)
-
-
-class TestOOtype(StringTests, OOJitMixin):
-    CALL = "oosend"
-    CALL_PURE = "oosend_pure"
+        _str = self._str
+        longstring = _str("?abcdefg")
+        somechar = _str("?")
+        jitdriver = JitDriver(greens = [], reds = ['m', 'n'])
+        @dont_look_inside
+        def escape(x):
+            pass
+        def f(n, m):
+            assert n >= 0
+            while m >= 0:
+                jitdriver.can_enter_jit(m=m, n=n)
+                jitdriver.jit_merge_point(m=m, n=n)
+                s = longstring[:m]
+                escape(s == somechar)
+                m -= 1
+            return 42
+        self.meta_interp(f, [6, 7])
+        self.check_loops(newstr=0, newunicode=0)
+
+
+#class TestOOtype(StringTests, OOJitMixin):
+#    CALL = "oosend"
+#    CALL_PURE = "oosend_pure"
 
 class TestLLtype(StringTests, LLJitMixin):
     CALL = "call"
     CALL_PURE = "call_pure"
+
+class TestLLtypeUnicode(TestLLtype):
+    _str, _chr = unicode, unichr
+
+    def test_str2unicode(self):
+        _str = self._str
+        jitdriver = JitDriver(greens = [], reds = ['m', 'n'])
+        class Foo:
+            pass
+        @dont_look_inside
+        def escape(x):
+            assert x == _str("6y")
+        def f(n, m):
+            while m >= 0:
+                jitdriver.can_enter_jit(m=m, n=n)
+                jitdriver.jit_merge_point(m=m, n=n)
+                foo = Foo()
+                foo.y = chr(m)
+                foo.y = "y"
+                s = _str(str(n)) + _str(foo.y)
+                escape(s)
+                m -= 1
+            return 42
+        self.meta_interp(f, [6, 7])
+        self.check_loops(call=3,    # str(), _str(), escape()
+                         newunicode=1, unicodegetitem=0,
+                         unicodesetitem=1, copyunicodecontent=1)

Modified: pypy/branch/jit-unroll-loops/pypy/jit/metainterp/test/test_virtualref.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/jit/metainterp/test/test_virtualref.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/jit/metainterp/test/test_virtualref.py	Sat Oct 30 16:41:17 2010
@@ -93,7 +93,7 @@
         lst = []
         vrefinfo.continue_tracing = lambda vref, virtual: \
                                         lst.append((vref, virtual))
-        resumereader.consume_vref_and_vable(vrefinfo, None)
+        resumereader.consume_vref_and_vable(vrefinfo, None, None)
         del vrefinfo.continue_tracing
         assert len(lst) == 1
         lltype.cast_opaque_ptr(lltype.Ptr(JIT_VIRTUAL_REF),

Modified: pypy/branch/jit-unroll-loops/pypy/jit/metainterp/test/test_warmspot.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/jit/metainterp/test/test_warmspot.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/jit/metainterp/test/test_warmspot.py	Sat Oct 30 16:41:17 2010
@@ -296,6 +296,69 @@
         assert res == 1
         self.check_loops(int_add=1)   # I get 13 without the loop_header()
 
+    def test_omit_can_enter_jit(self):
+        # Simple test comparing the effects of always giving a can_enter_jit(),
+        # or not giving any.  Mostly equivalent, except that if given, it is
+        # ignored the first time, and so it ends up taking one extra loop to
+        # start JITting.
+        mydriver = JitDriver(greens=[], reds=['m'])
+        #
+        for i2 in range(10):
+            def f2(m):
+                while m > 0:
+                    mydriver.jit_merge_point(m=m)
+                    m -= 1
+            self.meta_interp(f2, [i2])
+            try:
+                self.check_tree_loop_count(1)
+                break
+            except AssertionError:
+                print "f2: no loop generated for i2==%d" % i2
+        else:
+            raise     # re-raise the AssertionError: check_loop_count never 1
+        #
+        for i1 in range(10):
+            def f1(m):
+                while m > 0:
+                    mydriver.can_enter_jit(m=m)
+                    mydriver.jit_merge_point(m=m)
+                    m -= 1
+            self.meta_interp(f1, [i1])
+            try:
+                self.check_tree_loop_count(1)
+                break
+            except AssertionError:
+                print "f1: no loop generated for i1==%d" % i1
+        else:
+            raise     # re-raise the AssertionError: check_loop_count never 1
+        #
+        assert i1 - 1 == i2
+
+    def test_no_loop_at_all(self):
+        mydriver = JitDriver(greens=[], reds=['m'])
+        def f2(m):
+            mydriver.jit_merge_point(m=m)
+            return m - 1
+        def f1(m):
+            while m > 0:
+                m = f2(m)
+        self.meta_interp(f1, [8])
+        # it should generate one "loop" only, which ends in a FINISH
+        # corresponding to the return from f2.
+        self.check_tree_loop_count(1)
+        self.check_loop_count(0)
+
+    def test_simple_loop(self):
+        mydriver = JitDriver(greens=[], reds=['m'])
+        def f1(m):
+            while m > 0:
+                mydriver.jit_merge_point(m=m)
+                m = m - 1
+        self.meta_interp(f1, [8])
+        self.check_loop_count(1)
+        self.check_loops({'int_sub': 1, 'int_gt': 1, 'guard_true': 1,
+                          'jump': 1})
+
 
 class TestLLWarmspot(WarmspotTests, LLJitMixin):
     CPUClass = runner.LLtypeCPU

Modified: pypy/branch/jit-unroll-loops/pypy/jit/metainterp/virtualref.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/jit/metainterp/virtualref.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/jit/metainterp/virtualref.py	Sat Oct 30 16:41:17 2010
@@ -16,7 +16,8 @@
             ('virtualref_index', lltype.Signed),
             ('forced', rclass.OBJECTPTR))
         self.jit_virtual_ref_vtable = lltype.malloc(rclass.OBJECT_VTABLE,
-                                                    zero=True, flavor='raw')
+                                                    zero=True, flavor='raw',
+                                                    immortal=True)
         self.jit_virtual_ref_vtable.name = rclass.alloc_array_name(
             'jit_virtual_ref')
         # build some constants

Modified: pypy/branch/jit-unroll-loops/pypy/jit/metainterp/warmspot.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/jit/metainterp/warmspot.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/jit/metainterp/warmspot.py	Sat Oct 30 16:41:17 2010
@@ -67,9 +67,16 @@
 def jittify_and_run(interp, graph, args, repeat=1,
                     backendopt=False, trace_limit=sys.maxint,
                     debug_level=DEBUG_STEPS, inline=False, **kwds):
+    from pypy.config.config import ConfigError
     translator = interp.typer.annotator.translator
-    translator.config.translation.gc = "boehm"
-    translator.config.translation.list_comprehension_operations = True
+    try:
+        translator.config.translation.gc = "boehm"
+    except ConfigError:
+        pass
+    try:
+        translator.config.translation.list_comprehension_operations = True
+    except ConfigError:
+        pass
     warmrunnerdesc = WarmRunnerDesc(translator, backendopt=backendopt, **kwds)
     for jd in warmrunnerdesc.jitdrivers_sd:
         jd.warmstate.set_param_threshold(3)          # for tests
@@ -103,15 +110,16 @@
             for i in range(len(block.operations)):
                 op = block.operations[i]
                 if (op.opname == 'jit_marker' and
-                    op.args[0].value == marker_name):
+                    op.args[0].value == marker_name and
+                    op.args[1].value.active):   # the jitdriver
                     results.append((graph, block, i))
     return results
 
 def find_can_enter_jit(graphs):
-    results = _find_jit_marker(graphs, 'can_enter_jit')
-    if not results:
-        raise Exception("no can_enter_jit found!")
-    return results
+    return _find_jit_marker(graphs, 'can_enter_jit')
+
+def find_loop_headers(graphs):
+    return _find_jit_marker(graphs, 'loop_header')
 
 def find_jit_merge_points(graphs):
     results = _find_jit_marker(graphs, 'jit_merge_point')
@@ -204,9 +212,9 @@
                 "there are multiple jit_merge_points with the same jitdriver"
 
     def split_graph_and_record_jitdriver(self, graph, block, pos):
-        jd = JitDriverStaticData()
-        jd._jit_merge_point_pos = (graph, block, pos)
         op = block.operations[pos]
+        jd = JitDriverStaticData()
+        jd._jit_merge_point_pos = (graph, op)
         args = op.args[2:]
         s_binding = self.translator.annotator.binding
         jd._portal_args_s = [s_binding(v) for v in args]
@@ -279,10 +287,20 @@
     def make_virtualizable_infos(self):
         vinfos = {}
         for jd in self.jitdrivers_sd:
+            #
+            jd.greenfield_info = None
+            for name in jd.jitdriver.greens:
+                if '.' in name:
+                    from pypy.jit.metainterp.greenfield import GreenFieldInfo
+                    jd.greenfield_info = GreenFieldInfo(self.cpu, jd)
+                    break
+            #
             if not jd.jitdriver.virtualizables:
                 jd.virtualizable_info = None
                 jd.index_of_virtualizable = -1
                 continue
+            else:
+                assert jd.greenfield_info is None, "XXX not supported yet"
             #
             jitdriver = jd.jitdriver
             assert len(jitdriver.virtualizables) == 1    # for now
@@ -450,8 +468,7 @@
             self.make_args_specification(jd)
 
     def make_args_specification(self, jd):
-        graph, block, index = jd._jit_merge_point_pos
-        op = block.operations[index]
+        graph, op = jd._jit_merge_point_pos
         greens_v, reds_v = support.decode_hp_hint_args(op)
         ALLARGS = [v.concretetype for v in (greens_v + reds_v)]
         jd._green_args_spec = [v.concretetype for v in greens_v]
@@ -467,26 +484,37 @@
             [lltype.Signed, llmemory.GCREF], RESTYPE)
 
     def rewrite_can_enter_jits(self):
-        can_enter_jits = find_can_enter_jit(self.translator.graphs)
         sublists = {}
         for jd in self.jitdrivers_sd:
-            sublists[jd.jitdriver] = []
+            sublists[jd.jitdriver] = jd, []
+            jd.no_loop_header = True
+        #
+        loop_headers = find_loop_headers(self.translator.graphs)
+        for graph, block, index in loop_headers:
+            op = block.operations[index]
+            jitdriver = op.args[1].value
+            assert jitdriver in sublists, \
+                   "loop_header with no matching jit_merge_point"
+            jd, sublist = sublists[jitdriver]
+            jd.no_loop_header = False
+        #
+        can_enter_jits = find_can_enter_jit(self.translator.graphs)
         for graph, block, index in can_enter_jits:
             op = block.operations[index]
             jitdriver = op.args[1].value
             assert jitdriver in sublists, \
                    "can_enter_jit with no matching jit_merge_point"
+            jd, sublist = sublists[jitdriver]
             origportalgraph = jd._jit_merge_point_pos[0]
             if graph is not origportalgraph:
-                sublists[jitdriver].append((graph, block, index))
+                sublist.append((graph, block, index))
+                jd.no_loop_header = False
             else:
                 pass   # a 'can_enter_jit' before the 'jit-merge_point', but
                        # originally in the same function: we ignore it here
                        # see e.g. test_jitdriver.test_simple
         for jd in self.jitdrivers_sd:
-            sublist = sublists[jd.jitdriver]
-            assert len(sublist) > 0, \
-                   "found no can_enter_jit for %r" % (jd.jitdriver,)
+            _, sublist = sublists[jd.jitdriver]
             self.rewrite_can_enter_jit(jd, sublist)
 
     def rewrite_can_enter_jit(self, jd, can_enter_jits):
@@ -494,6 +522,19 @@
         FUNCPTR = jd._PTR_JIT_ENTER_FUNCTYPE
         jit_enter_fnptr = self.helper_func(FUNCPTR, jd._maybe_enter_jit_fn)
 
+        if len(can_enter_jits) == 0:
+            # see test_warmspot.test_no_loop_at_all
+            operations = jd.portal_graph.startblock.operations
+            op1 = operations[0]
+            assert (op1.opname == 'jit_marker' and
+                    op1.args[0].value == 'jit_merge_point')
+            op0 = SpaceOperation(
+                'jit_marker',
+                [Constant('can_enter_jit', lltype.Void)] + op1.args[1:],
+                None)
+            operations.insert(0, op0)
+            can_enter_jits = [(jd.portal_graph, jd.portal_graph.startblock, 0)]
+
         for graph, block, index in can_enter_jits:
             if graph is jd._jit_merge_point_pos[0]:
                 continue
@@ -702,8 +743,14 @@
         # ____________________________________________________________
         # Now mutate origportalgraph to end with a call to portal_runner_ptr
         #
-        _, origblock, origindex = jd._jit_merge_point_pos
-        op = origblock.operations[origindex]
+        _, op = jd._jit_merge_point_pos
+        for origblock in origportalgraph.iterblocks():
+            if op in origblock.operations:
+                break
+        else:
+            assert False, "lost the operation %r in the graph %r" % (
+                op, origportalgraph)
+        origindex = origblock.operations.index(op)
         assert op.opname == 'jit_marker'
         assert op.args[0].value == 'jit_merge_point'
         greens_v, reds_v = support.decode_hp_hint_args(op)

Modified: pypy/branch/jit-unroll-loops/pypy/jit/metainterp/warmstate.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/jit/metainterp/warmstate.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/jit/metainterp/warmstate.py	Sat Oct 30 16:41:17 2010
@@ -1,5 +1,5 @@
 import sys
-from pypy.rpython.lltypesystem import lltype, llmemory, rstr
+from pypy.rpython.lltypesystem import lltype, llmemory, rstr, rffi
 from pypy.rpython.ootypesystem import ootype
 from pypy.rpython.annlowlevel import hlstr, llstr, cast_base_ptr_to_instance
 from pypy.rpython.annlowlevel import cast_object_to_ptr
@@ -24,7 +24,11 @@
     """
     INPUT = lltype.typeOf(x)
     if INPUT is lltype.Signed:
-        return lltype.cast_primitive(TYPE, x)    # XXX missing: Ptr(non-gc)
+        if isinstance(TYPE, lltype.Ptr) and TYPE.TO._gckind == 'raw':
+            # non-gc pointer
+            return rffi.cast(TYPE, x)
+        else:
+            return lltype.cast_primitive(TYPE, x)
     elif INPUT is lltype.Float:
         assert TYPE is lltype.Float
         return x
@@ -172,6 +176,9 @@
             meth(default_value)
 
     def set_param_threshold(self, threshold):
+        if threshold < 0:
+            self.increment_threshold = 0   # never reach the THRESHOLD_LIMIT
+            return
         if threshold < 2:
             threshold = 2
         self.increment_threshold = (self.THRESHOLD_LIMIT // threshold) + 1

Modified: pypy/branch/jit-unroll-loops/pypy/jit/tl/pypyjit.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/jit/tl/pypyjit.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/jit/tl/pypyjit.py	Sat Oct 30 16:41:17 2010
@@ -40,8 +40,10 @@
 config.objspace.usemodules.array = True
 config.objspace.usemodules._weakref = False
 config.objspace.usemodules._sre = False
+#
+config.objspace.usemodules._ffi = True
+#
 set_pypy_opt_level(config, level='jit')
-config.objspace.std.withinlineddict = True
 
 if BACKEND == 'c':
     config.objspace.std.multimethods = 'mrd'

Modified: pypy/branch/jit-unroll-loops/pypy/jit/tl/pypyjit_child.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/jit/tl/pypyjit_child.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/jit/tl/pypyjit_child.py	Sat Oct 30 16:41:17 2010
@@ -16,7 +16,7 @@
     interp.heap.malloc_nonmovable = returns_null     # XXX
 
     from pypy.jit.backend.llgraph.runner import LLtypeCPU
-    LLtypeCPU.supports_floats = False    # for now
+    #LLtypeCPU.supports_floats = False    # for now
     apply_jit(interp, graph, LLtypeCPU)
 
 

Modified: pypy/branch/jit-unroll-loops/pypy/jit/tl/spli/interpreter.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/jit/tl/spli/interpreter.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/jit/tl/spli/interpreter.py	Sat Oct 30 16:41:17 2010
@@ -1,12 +1,14 @@
 import os
-from pypy.tool import stdlib_opcode as opcode
+from pypy.tool import stdlib_opcode
 from pypy.jit.tl.spli import objects, pycode
-from pypy.tool.stdlib_opcode import unrolling_opcode_descs
-from pypy.tool.stdlib_opcode import opcode_method_names
 from pypy.rlib.unroll import unrolling_iterable
 from pypy.rlib.jit import JitDriver, hint, dont_look_inside
 from pypy.rlib.objectmodel import we_are_translated
 
+opcode_method_names = stdlib_opcode.host_bytecode_spec.method_names
+unrolling_opcode_descs = unrolling_iterable(
+    stdlib_opcode.host_bytecode_spec.ordered_opdescs)
+HAVE_ARGUMENT = stdlib_opcode.host_HAVE_ARGUMENT
 
 compare_ops = [
     "cmp_lt",   # "<"
@@ -79,7 +81,7 @@
             self.stack_depth = hint(self.stack_depth, promote=True)
             op = ord(code[instr_index])
             instr_index += 1
-            if op >= opcode.HAVE_ARGUMENT:
+            if op >= HAVE_ARGUMENT:
                 low = ord(code[instr_index])
                 hi = ord(code[instr_index + 1])
                 oparg = (hi << 8) | low
@@ -183,6 +185,12 @@
             next_instr += arg
         return next_instr
 
+    def POP_JUMP_IF_FALSE(self, arg, next_instr, code):
+        w_cond = self.pop()
+        if not w_cond.is_true():
+            next_instr = arg
+        return next_instr
+
     def JUMP_FORWARD(self, arg, next_instr, code):
         return next_instr + arg
 

Modified: pypy/branch/jit-unroll-loops/pypy/jit/tl/tla/test_tla.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/jit/tl/tla/test_tla.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/jit/tl/tla/test_tla.py	Sat Oct 30 16:41:17 2010
@@ -156,7 +156,7 @@
 # ____________________________________________________________ 
 
 from pypy.jit.metainterp.test.test_basic import LLJitMixin
-from pypy.rlib.jit import OPTIMIZER_FULL
+from pypy.rlib.jit import OPTIMIZER_FULL, OPTIMIZER_NO_PERFECTSPEC
 
 class TestLLtype(LLJitMixin):
     def test_loop(self):
@@ -178,5 +178,5 @@
             assert isinstance(w_result, tla.W_IntObject)
             return w_result.intvalue
         res = self.meta_interp(interp_w, [42], listops=True,
-                               optimizer=OPTIMIZER_FULL)
+                               optimizer=OPTIMIZER_NO_PERFECTSPEC)
         assert res == 0

Modified: pypy/branch/jit-unroll-loops/pypy/jit/tool/loopviewer.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/jit/tool/loopviewer.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/jit/tool/loopviewer.py	Sat Oct 30 16:41:17 2010
@@ -9,7 +9,7 @@
 import optparse
 from pprint import pprint
 from pypy.tool import logparser
-from pypy.jit.metainterp.test.oparser import parse
+from pypy.jit.tool.oparser import parse
 from pypy.jit.metainterp.history import ConstInt
 from pypy.rpython.lltypesystem import llmemory, lltype
 

Modified: pypy/branch/jit-unroll-loops/pypy/jit/tool/showstats.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/jit/tool/showstats.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/jit/tool/showstats.py	Sat Oct 30 16:41:17 2010
@@ -4,15 +4,15 @@
 import autopath
 import sys, py
 from pypy.tool import logparser
-from pypy.jit.metainterp.test.oparser import parse
+from pypy.jit.tool.oparser import parse
 from pypy.jit.metainterp.resoperation import rop
 from pypy.rpython.lltypesystem import lltype, llmemory
 
 def main(argv):
     log = logparser.parse_log_file(argv[0])
-    parts = logparser.extract_category(log, "jit-log-opt-")
+    parts = logparser.extract_category(log, "jit-log-noopt-")
     for i, oplist in enumerate(parts):
-        loop = parse(oplist, no_namespace=True)
+        loop = parse(oplist, no_namespace=True, nonstrict=True)
         num_ops = 0
         num_dmp = 0
         num_guards = 0
@@ -23,7 +23,10 @@
                 num_ops += 1
             if op.is_guard():
                 num_guards += 1
-        print "Loop #%d, length: %d, opcodes: %d, guards: %d, %f" % (i, num_ops, num_dmp, num_guards, num_ops/num_dmp)
+        if num_dmp == 0:
+            print "Loop #%d, length: %d, opcodes: %d, guards: %d" % (i, num_ops, num_dmp, num_guards)
+        else:
+            print "Loop #%d, length: %d, opcodes: %d, guards: %d, %f" % (i, num_ops, num_dmp, num_guards, num_ops/num_dmp)
 
 if __name__ == '__main__':
     main(sys.argv[1:])

Modified: pypy/branch/jit-unroll-loops/pypy/jit/tool/traceviewer.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/jit/tool/traceviewer.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/jit/tool/traceviewer.py	Sat Oct 30 16:41:17 2010
@@ -253,10 +253,10 @@
 def main(loopfile, use_threshold, view=True):
     countname = py.path.local(loopfile + '.count')
     if countname.check():
-        counts = [re.split('(<code)|(<loop)', line, maxsplit=1)
-                  for line in countname.readlines()]
-        counts = Counts([('<code' + k.strip("\n"), int(v.strip('\n').strip()))
-                         for v, _, _, k in counts])
+        #counts = [line.split(':', 1) for line in countname.readlines()]
+        #counts = Counts([('<code' + k.strip("\n"), int(v.strip('\n').strip()))
+        #                 for v, k in counts])
+        counts = Counts([])
         l = list(sorted(counts.values()))
         if len(l) > 20 and use_threshold:
             counts.threshold = l[-20]

Modified: pypy/branch/jit-unroll-loops/pypy/module/__builtin__/interp_classobj.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/module/__builtin__/interp_classobj.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/module/__builtin__/interp_classobj.py	Sat Oct 30 16:41:17 2010
@@ -2,9 +2,11 @@
 from pypy.interpreter.error import OperationError, operationerrfmt
 from pypy.interpreter.gateway import ObjSpace, W_Root, NoneNotWrapped, applevel
 from pypy.interpreter.gateway import interp2app, ObjSpace
-from pypy.interpreter.typedef import TypeDef, make_weakref_descr
+from pypy.interpreter.typedef import TypeDef
 from pypy.interpreter.argument import Arguments
 from pypy.interpreter.baseobjspace import Wrappable
+from pypy.interpreter.typedef import GetSetProperty, descr_get_dict
+from pypy.interpreter.typedef import descr_set_dict
 from pypy.rlib.rarithmetic import r_uint, intmask
 from pypy.rlib.objectmodel import compute_identity_hash
 from pypy.rlib.debug import make_sure_not_resized
@@ -57,6 +59,14 @@
         self.bases_w = bases
         self.w_dict = w_dict
  
+    def instantiate(self, space):
+        cache = space.fromcache(Cache)
+        if self.lookup(space, '__del__') is not None:
+            w_inst = cache.cls_with_del(space, self)
+        else:
+            w_inst = cache.cls_without_del(space, self)
+        return w_inst
+
     def getdict(self):
         return self.w_dict
 
@@ -100,15 +110,15 @@
         return False
 
     @jit.unroll_safe
-    def lookup(self, space, w_attr):
+    def lookup(self, space, attr):
         # returns w_value or interplevel None
-        w_result = space.finditem(self.w_dict, w_attr)
+        w_result = space.finditem_str(self.w_dict, attr)
         if w_result is not None:
             return w_result
         for base in self.bases_w:
             # XXX fix annotation of bases_w to be a list of W_ClassObjects
             assert isinstance(base, W_ClassObject)
-            w_result = base.lookup(space, w_attr)
+            w_result = base.lookup(space, attr)
             if w_result is not None:
                 return w_result
         return None
@@ -122,7 +132,7 @@
                 return space.wrap(self.name)
             elif name == "__bases__":
                 return space.newtuple(self.bases_w)
-        w_value = self.lookup(space, w_attr)
+        w_value = self.lookup(space, name)
         if w_value is None:
             raise operationerrfmt(
                 space.w_AttributeError,
@@ -147,7 +157,7 @@
                 self.setbases(space, w_value)
                 return
             elif name == "__del__":
-                if self.lookup(space, w_attr) is None:
+                if self.lookup(space, name) is None:
                     msg = ("a __del__ method added to an existing class "
                            "will not be called")
                     space.warn(msg, space.w_RuntimeWarning)
@@ -195,13 +205,20 @@
         # NOT_RPYTHON
         return '<W_ClassObject(%s)>' % self.name
 
+class Cache:
+    def __init__(self, space):
+        from pypy.interpreter.typedef import _usersubclswithfeature
+        # evil
+        self.cls_without_del = _usersubclswithfeature(
+                space.config, W_InstanceObject, "dict", "weakref")
+        self.cls_with_del = _usersubclswithfeature(
+                space.config, self.cls_without_del, "del")
+
+
 def class_descr_call(space, w_self, __args__):
     self = space.interp_w(W_ClassObject, w_self)
-    if self.lookup(space, space.wrap('__del__')) is not None:
-        w_inst = W_InstanceObjectWithDel(space, self)
-    else:
-        w_inst = W_InstanceObject(space, self)
-    w_init = w_inst.getattr_from_class(space, space.wrap('__init__'))
+    w_inst = self.instantiate(space)
+    w_init = w_inst.getattr_from_class(space, '__init__')
     if w_init is not None:
         w_result = space.call_args(w_init, __args__)
         if not space.is_w(w_result, space.w_None):
@@ -234,7 +251,7 @@
 
 def make_unary_instance_method(name):
     def unaryop(self, space):
-        w_meth = self.getattr(space, space.wrap(name), True)
+        w_meth = self.getattr(space, name, True)
         return space.call_function(w_meth)
     unaryop.func_name = name
     return unaryop
@@ -242,7 +259,7 @@
 def make_binary_returning_notimplemented_instance_method(name):
     def binaryop(self, space, w_other):
         try:
-            w_meth = self.getattr(space, space.wrap(name), False)
+            w_meth = self.getattr(space, name, False)
         except OperationError, e:
             if e.match(space, space.w_AttributeError):
                 return space.w_NotImplemented
@@ -267,7 +284,7 @@
             w_a = self
             w_b = w_other
         if w_a is self:
-            w_meth = self.getattr(space, space.wrap(specialname), False)
+            w_meth = self.getattr(space, specialname, False)
             if w_meth is None:
                 return space.w_NotImplemented
             return space.call_function(w_meth, w_b)
@@ -278,7 +295,7 @@
     def rbinaryop(self, space, w_other):
         w_a, w_b = _coerce_helper(space, self, w_other)
         if w_a is None or w_a is self:
-            w_meth = self.getattr(space, space.wrap(rspecialname), False)
+            w_meth = self.getattr(space, rspecialname, False)
             if w_meth is None:
                 return space.w_NotImplemented
             return space.call_function(w_meth, w_other)
@@ -302,46 +319,34 @@
         raise OperationError(
             space.w_TypeError,
             space.wrap("instance() first arg must be class"))
-    if space.is_w(w_dict, space.w_None):
-        w_dict = None
-    elif not space.is_true(space.isinstance(w_dict, space.w_dict)):
-        raise OperationError(
-            space.w_TypeError,
-            space.wrap("instance() second arg must be dictionary or None"))
-    return W_InstanceObject(space, w_class, w_dict)
+    w_result = w_class.instantiate(space)
+    if not space.is_w(w_dict, space.w_None):
+        w_result.setdict(space, w_dict)
+    return w_result
 
 class W_InstanceObject(Wrappable):
-    def __init__(self, space, w_class, w_dict=None):
-        if w_dict is None:
-            w_dict = space.newdict(instance=True)
+    def __init__(self, space, w_class):
+        # note that user_setup is overridden by the typedef.py machinery
+        self.user_setup(space, space.gettypeobject(self.typedef))
         assert isinstance(w_class, W_ClassObject)
         self.w_class = w_class
-        self.w_dict = w_dict
-        self.space = space
-
-    def getdict(self):
-        return self.w_dict
 
-    def setdict(self, space, w_dict):
-        if (w_dict is None or
-            not space.is_true(space.isinstance(w_dict, space.w_dict))):
-            raise OperationError(
-                space.w_TypeError,
-                space.wrap("__dict__ must be a dictionary object"))
-        self.w_dict = w_dict
+    def user_setup(self, space, w_subtype):
+        self.space = space
 
-    def setclass(self, space, w_class):
+    def set_oldstyle_class(self, space, w_class):
         if w_class is None or not isinstance(w_class, W_ClassObject):
             raise OperationError(
                 space.w_TypeError,
                 space.wrap("__class__ must be set to a class"))
         self.w_class = w_class
 
-    def getattr_from_class(self, space, w_name):
+    def getattr_from_class(self, space, name):
         # Look up w_name in the class dict, and call its __get__.
         # This method ignores the instance dict and the __getattr__.
         # Returns None if not found.
-        w_value = self.w_class.lookup(space, w_name)
+        assert isinstance(name, str)
+        w_value = self.w_class.lookup(space, name)
         if w_value is None:
             return None
         w_descr_get = space.lookup(w_value, '__get__')
@@ -349,19 +354,20 @@
             return w_value
         return space.call_function(w_descr_get, w_value, self, self.w_class)
 
-    def getattr(self, space, w_name, exc=True):
+    def getattr(self, space, name, exc=True):
         # Normal getattr rules: look up w_name in the instance dict,
         # in the class dict, and then via a call to __getatttr__.
-        w_result = space.finditem(self.w_dict, w_name)
+        assert isinstance(name, str)
+        w_result = self.getdictvalue(space, name)
         if w_result is not None:
             return w_result
-        w_result = self.getattr_from_class(space, w_name)
+        w_result = self.getattr_from_class(space, name)
         if w_result is not None:
             return w_result
-        w_meth = self.getattr_from_class(space, space.wrap('__getattr__'))
+        w_meth = self.getattr_from_class(space, '__getattr__')
         if w_meth is not None:
             try:
-                return space.call_function(w_meth, w_name)
+                return space.call_function(w_meth, space.wrap(name))
             except OperationError, e:
                 if not exc and e.match(space, space.w_AttributeError):
                     return None     # eat the AttributeError
@@ -371,7 +377,7 @@
             raise operationerrfmt(
                 space.w_AttributeError,
                 "%s instance has no attribute '%s'",
-                self.w_class.name, space.str_w(w_name))
+                self.w_class.name, name)
         else:
             return None
 
@@ -379,24 +385,25 @@
         name = space.str_w(w_attr)
         if len(name) >= 8 and name[0] == '_':
             if name == "__dict__":
-                return self.w_dict
+                return self.getdict()
             elif name == "__class__":
                 return self.w_class
-        return self.getattr(space, w_attr)
+        return self.getattr(space, name)
 
     def descr_setattr(self, space, w_name, w_value):
         name = unwrap_attr(space, w_name)
-        w_meth = self.getattr_from_class(space, space.wrap('__setattr__'))
+        w_meth = self.getattr_from_class(space, '__setattr__')
         if name and name[0] == "_":
             if name == '__dict__':
                 self.setdict(space, w_value)
                 return
             if name == '__class__':
-                self.setclass(space, w_value)
+                self.set_oldstyle_class(space, w_value)
                 return
             if name == '__del__' and w_meth is None:
-                if (not isinstance(self, W_InstanceObjectWithDel)
-                    and space.finditem(self.w_dict, w_name) is None):
+                cache = space.fromcache(Cache)
+                if (not isinstance(self, cache.cls_with_del)
+                    and self.getdictvalue(space, '__del__') is None):
                     msg = ("a __del__ method added to an instance "
                            "with no __del__ in the class will not be called")
                     space.warn(msg, space.w_RuntimeWarning)
@@ -410,13 +417,13 @@
         if name and name[0] == "_":
             if name == '__dict__':
                 # use setdict to raise the error
-                self.setdict(space, None)
+                self.setdict(space, space.w_None)
                 return
             elif name == '__class__':
-                # use setclass to raise the error
-                self.setclass(space, None)
+                # use set_oldstyle_class to raise the error
+                self.set_oldstyle_class(space, None)
                 return
-        w_meth = self.getattr_from_class(space, space.wrap('__delattr__'))
+        w_meth = self.getattr_from_class(space, '__delattr__')
         if w_meth is not None:
             space.call_function(w_meth, w_name)
         else:
@@ -427,7 +434,7 @@
                     self.w_class.name, name)
 
     def descr_repr(self, space):
-        w_meth = self.getattr(space, space.wrap('__repr__'), False)
+        w_meth = self.getattr(space, '__repr__', False)
         if w_meth is None:
             w_class = self.w_class
             mod = w_class.get_module_string(space)
@@ -435,19 +442,19 @@
         return space.call_function(w_meth)
 
     def descr_str(self, space):
-        w_meth = self.getattr(space, space.wrap('__str__'), False)
+        w_meth = self.getattr(space, '__str__', False)
         if w_meth is None:
             return self.descr_repr(space)
         return space.call_function(w_meth)
 
     def descr_unicode(self, space):
-        w_meth = self.getattr(space, space.wrap('__unicode__'), False)
+        w_meth = self.getattr(space, '__unicode__', False)
         if w_meth is None:
             return self.descr_str(space)
         return space.call_function(w_meth)
 
     def descr_len(self, space):
-        w_meth = self.getattr(space, space.wrap('__len__'))
+        w_meth = self.getattr(space, '__len__')
         w_result = space.call_function(w_meth)
         if space.is_true(space.isinstance(w_result, space.w_int)):
             if space.is_true(space.lt(w_result, space.wrap(0))):
@@ -460,22 +467,22 @@
             space.wrap("__len__() should return an int"))
 
     def descr_getitem(self, space, w_key):
-        w_meth = self.getattr(space, space.wrap('__getitem__'))
+        w_meth = self.getattr(space, '__getitem__')
         return space.call_function(w_meth, w_key)
 
     def descr_setitem(self, space, w_key, w_value):
-        w_meth = self.getattr(space, space.wrap('__setitem__'))
+        w_meth = self.getattr(space, '__setitem__')
         space.call_function(w_meth, w_key, w_value)
 
     def descr_delitem(self, space, w_key):
-        w_meth = self.getattr(space, space.wrap('__delitem__'))
+        w_meth = self.getattr(space, '__delitem__')
         space.call_function(w_meth, w_key)
 
     def descr_iter(self, space):
-        w_meth = self.getattr(space, space.wrap('__iter__'), False)
+        w_meth = self.getattr(space, '__iter__', False)
         if w_meth is not None:
             return space.call_function(w_meth)
-        w_meth = self.getattr(space, space.wrap('__getitem__'), False)
+        w_meth = self.getattr(space, '__getitem__', False)
         if w_meth is None:
             raise OperationError(
                 space.w_TypeError,
@@ -485,14 +492,14 @@
     # don't see the point
 
     def descr_getslice(self, space, w_i, w_j):
-        w_meth = self.getattr(space, space.wrap('__getslice__'), False)
+        w_meth = self.getattr(space, '__getslice__', False)
         if w_meth is not None:
             return space.call_function(w_meth, w_i, w_j)
         else:
             return space.getitem(self, space.newslice(w_i, w_j, space.w_None))
 
     def descr_setslice(self, space, w_i, w_j, w_sequence):
-        w_meth = self.getattr(space, space.wrap('__setslice__'), False)
+        w_meth = self.getattr(space, '__setslice__', False)
         if w_meth is not None:
             space.call_function(w_meth, w_i, w_j, w_sequence)
         else:
@@ -500,20 +507,20 @@
                           w_sequence)
 
     def descr_delslice(self, space, w_i, w_j):
-        w_meth = self.getattr(space, space.wrap('__delslice__'), False)
+        w_meth = self.getattr(space, '__delslice__', False)
         if w_meth is not None:
             space.call_function(w_meth, w_i, w_j)
         else:
             return space.delitem(self, space.newslice(w_i, w_j, space.w_None))
 
     def descr_call(self, space, __args__):
-        w_meth = self.getattr(space, space.wrap('__call__'))
+        w_meth = self.getattr(space, '__call__')
         return space.call_args(w_meth, __args__)
 
     def descr_nonzero(self, space):
-        w_func = self.getattr(space, space.wrap('__nonzero__'), False)
+        w_func = self.getattr(space, '__nonzero__', False)
         if w_func is None:
-            w_func = self.getattr(space, space.wrap('__len__'), False)
+            w_func = self.getattr(space, '__len__', False)
             if w_func is None:
                 return space.w_True
         w_result = space.call_function(w_func)
@@ -537,7 +544,7 @@
                 not isinstance(w_b, W_InstanceObject)):
                 return space.cmp(w_a, w_b)
         if isinstance(w_a, W_InstanceObject):
-            w_func = w_a.getattr(space, space.wrap('__cmp__'), False)
+            w_func = w_a.getattr(space, '__cmp__', False)
             if w_func is not None:
                 w_res = space.call_function(w_func, w_b)
                 if space.is_w(w_res, space.w_NotImplemented):
@@ -556,7 +563,7 @@
                     return space.wrap(-1)
                 return space.wrap(0)
         if isinstance(w_b, W_InstanceObject):
-            w_func = w_b.getattr(space, space.wrap('__cmp__'), False)
+            w_func = w_b.getattr(space, '__cmp__', False)
             if w_func is not None:
                 w_res = space.call_function(w_func, w_a)
                 if space.is_w(w_res, space.w_NotImplemented):
@@ -577,10 +584,10 @@
         return space.w_NotImplemented
 
     def descr_hash(self, space):
-        w_func = self.getattr(space, space.wrap('__hash__'), False)
+        w_func = self.getattr(space, '__hash__', False)
         if w_func is None:
-            w_eq =  self.getattr(space, space.wrap('__eq__'), False)
-            w_cmp =  self.getattr(space, space.wrap('__cmp__'), False)
+            w_eq =  self.getattr(space, '__eq__', False)
+            w_cmp =  self.getattr(space, '__cmp__', False)
             if w_eq is not None or w_cmp is not None:
                 raise OperationError(space.w_TypeError,
                                      space.wrap("unhashable instance"))
@@ -595,7 +602,7 @@
         return w_ret
 
     def descr_index(self, space):
-        w_func = self.getattr(space, space.wrap('__index__'), False)
+        w_func = self.getattr(space, '__index__', False)
         if w_func is not None:
             return space.call_function(w_func)
         raise OperationError(
@@ -603,7 +610,7 @@
             space.wrap("object cannot be interpreted as an index"))
 
     def descr_contains(self, space, w_obj):
-        w_func = self.getattr(space, space.wrap('__contains__'), False)
+        w_func = self.getattr(space, '__contains__', False)
         if w_func is not None:
             return space.wrap(space.is_true(space.call_function(w_func, w_obj)))
         # now do it ourselves
@@ -626,7 +633,7 @@
                 w_a = self
                 w_b = w_other
             if w_a is self:
-                w_func = self.getattr(space, space.wrap('__pow__'), False)
+                w_func = self.getattr(space, '__pow__', False)
                 if w_func is not None:
                     return space.call_function(w_func, w_other)
                 return space.w_NotImplemented
@@ -634,7 +641,7 @@
                 return space.pow(w_a, w_b, space.w_None)
         else:
             # CPython also doesn't try coercion in this case
-            w_func = self.getattr(space, space.wrap('__pow__'), False)
+            w_func = self.getattr(space, '__pow__', False)
             if w_func is not None:
                 return space.call_function(w_func, w_other, w_modulo)
             return space.w_NotImplemented
@@ -646,7 +653,7 @@
                 w_a = self
                 w_b = w_other
             if w_a is self:
-                w_func = self.getattr(space, space.wrap('__rpow__'), False)
+                w_func = self.getattr(space, '__rpow__', False)
                 if w_func is not None:
                     return space.call_function(w_func, w_other)
                 return space.w_NotImplemented
@@ -654,13 +661,13 @@
                 return space.pow(w_b, w_a, space.w_None)
         else:
             # CPython also doesn't try coercion in this case
-            w_func = self.getattr(space, space.wrap('__rpow__'), False)
+            w_func = self.getattr(space, '__rpow__', False)
             if w_func is not None:
                 return space.call_function(w_func, w_other, w_modulo)
             return space.w_NotImplemented
 
     def descr_next(self, space):
-        w_func = self.getattr(space, space.wrap('next'), False)
+        w_func = self.getattr(space, 'next', False)
         if w_func is None:
             raise OperationError(space.w_TypeError,
                                  space.wrap("instance has no next() method"))
@@ -669,10 +676,9 @@
     def descr_del(self, space):
         # Note that this is called from executioncontext.UserDelAction
         # via the space.userdel() method.
-        w_name = space.wrap('__del__')
-        w_func = space.finditem(self.w_dict, w_name)
+        w_func = self.getdictvalue(space, '__del__')
         if w_func is None:
-            w_func = self.getattr_from_class(space, w_name)
+            w_func = self.getattr_from_class(space, '__del__')
         if w_func is not None:
             space.call_function(w_func)
 
@@ -717,6 +723,14 @@
         rmeth,
         unwrap_spec=["self", ObjSpace, W_Root])
 
+
+def descr_del_dict(space, w_inst):
+    # use setdict to raise the error
+    w_inst.setdict(space, space.w_None)
+
+dict_descr = GetSetProperty(descr_get_dict, descr_set_dict, descr_del_dict)
+dict_descr.name = '__dict__'
+
 W_InstanceObject.typedef = TypeDef("instance",
     __new__ = interp2app(descr_instance_new),
     __getattribute__ = interp2app(W_InstanceObject.descr_getattribute,
@@ -766,12 +780,9 @@
                          unwrap_spec=['self', ObjSpace, W_Root, W_Root]),
     next = interp2app(W_InstanceObject.descr_next,
                       unwrap_spec=['self', ObjSpace]),
-    __weakref__ = make_weakref_descr(W_InstanceObject),
     __del__ = interp2app(W_InstanceObject.descr_del,
                          unwrap_spec=['self', ObjSpace]),
+    __dict__ = dict_descr,
     **rawdict
 )
-
-class W_InstanceObjectWithDel(W_InstanceObject):
-    def __del__(self):
-        self._enqueue_for_destruction(self.space)
+W_InstanceObject.typedef.acceptable_as_base_class = False

Modified: pypy/branch/jit-unroll-loops/pypy/module/__builtin__/test/test_classobj.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/module/__builtin__/test/test_classobj.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/module/__builtin__/test/test_classobj.py	Sat Oct 30 16:41:17 2010
@@ -928,29 +928,33 @@
         assert x is b
         assert y == 5
 
-
-class AppTestOldStyleSharing(AppTestOldstyle):
-    def setup_class(cls):
-        cls.space = gettestobjspace(**{"objspace.std.withsharingdict": True})
-        if option.runappdirect:
-            py.test.skip("can only be run on py.py")
-        def is_sharing(space, w_inst):
-            from pypy.objspace.std.sharingdict import SharedDictImplementation
-            w_d = w_inst.getdict()
-            return space.wrap(isinstance(w_d, SharedDictImplementation) and w_d.r_dict_content is None)
-        cls.w_is_sharing = cls.space.wrap(gateway.interp2app(is_sharing))
-
-
-    def test_real_sharing(self):
+    def test_cant_subclass_instance(self):
         class A:
-            def __init__(self):
-                self.x = 42
-        A1, A2, A3 = A(), A(), A()
-        assert self.is_sharing(A3)
-        assert self.is_sharing(A2)
-        assert self.is_sharing(A1)
+            pass
+        try:
+            class B(type(A())):
+                pass
+        except TypeError:
+            pass
+        else:
+            assert 0, "should have raised"
+
+    def test_dict_descriptor(self):
+        import sys
+        if not hasattr(sys, 'pypy_objspaceclass'):
+            skip("on CPython old-style instances don't have a __dict__ descriptor")
+        class A:
+            pass
+        a = A()
+        a.x = 1
+        descr = type(a).__dict__['__dict__']
+        assert descr.__get__(a) == {'x': 1}
+        descr.__set__(a, {'x': 2})
+        assert a.x == 2
+        raises(TypeError, descr.__delete__, a)
+
 
-class AppTestOldStyleModDict(object):
+class AppTestOldStyleClassStrDict(object):
     def setup_class(cls):
         if option.runappdirect:
             py.test.skip("can only be run on py.py")
@@ -966,3 +970,22 @@
             a = 1
             b = 2
         assert self.is_strdict(A)
+
+class AppTestOldStyleMapDict(AppTestOldstyle):
+    def setup_class(cls):
+        cls.space = gettestobjspace(**{"objspace.std.withmapdict": True})
+        if option.runappdirect:
+            py.test.skip("can only be run on py.py")
+        def has_mapdict(space, w_inst):
+            return space.wrap(w_inst._get_mapdict_map() is not None)
+        cls.w_has_mapdict = cls.space.wrap(gateway.interp2app(has_mapdict))
+
+
+    def test_has_mapdict(self):
+        class A:
+            def __init__(self):
+                self.x = 42
+        a = A()
+        assert a.x == 42
+        assert self.has_mapdict(a)
+

Modified: pypy/branch/jit-unroll-loops/pypy/module/_rawffi/__init__.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/module/_rawffi/__init__.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/module/_rawffi/__init__.py	Sat Oct 30 16:41:17 2010
@@ -1,5 +1,5 @@
 
-""" Low-level interface to libffi
+""" Low-level interface to clibffi
 """
 
 from pypy.interpreter.mixedmodule import MixedModule
@@ -39,11 +39,11 @@
         if hasattr(interp_rawffi, 'check_HRESULT'):
             Module.interpleveldefs['check_HRESULT'] = 'interp_rawffi.check_HRESULT'
 
-        from pypy.rlib import libffi
+        from pypy.rlib import clibffi
         for name in ['FUNCFLAG_STDCALL', 'FUNCFLAG_CDECL', 'FUNCFLAG_PYTHONAPI',
                      ]:
-            if hasattr(libffi, name):
-                Module.interpleveldefs[name] = "space.wrap(%r)" % getattr(libffi, name)
+            if hasattr(clibffi, name):
+                Module.interpleveldefs[name] = "space.wrap(%r)" % getattr(clibffi, name)
                 
         super(Module, cls).buildloaders()
     buildloaders = classmethod(buildloaders)

Modified: pypy/branch/jit-unroll-loops/pypy/module/_rawffi/array.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/module/_rawffi/array.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/module/_rawffi/array.py	Sat Oct 30 16:41:17 2010
@@ -97,7 +97,15 @@
 
 class W_ArrayInstance(W_DataInstance):
     def __init__(self, space, shape, length, address=r_uint(0)):
-        W_DataInstance.__init__(self, space, shape.size * length, address)
+        # Workaround for a strange behavior of libffi: make sure that
+        # we always have at least 8 bytes.  For W_ArrayInstances that are
+        # used as the result value of a function call, ffi_call() writes
+        # 8 bytes into it even if the function's result type asks for less.
+        # This strange behavior is documented.
+        memsize = shape.size * length
+        if memsize < 8:
+            memsize = 8
+        W_DataInstance.__init__(self, space, memsize, address)
         self.length = length
         self.shape = shape
 

Modified: pypy/branch/jit-unroll-loops/pypy/module/_rawffi/callback.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/module/_rawffi/callback.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/module/_rawffi/callback.py	Sat Oct 30 16:41:17 2010
@@ -8,8 +8,8 @@
 from pypy.module._rawffi.array import get_elem, push_elem
 from pypy.module._rawffi.interp_rawffi import W_DataInstance, letter2tp, \
      wrap_value, unwrap_value, unwrap_truncate_int
-from pypy.rlib.libffi import USERDATA_P, CallbackFuncPtr, FUNCFLAG_CDECL
-from pypy.rlib.libffi import ffi_type_void
+from pypy.rlib.clibffi import USERDATA_P, CallbackFuncPtr, FUNCFLAG_CDECL
+from pypy.rlib.clibffi import ffi_type_void
 from pypy.module._rawffi.tracker import tracker
 from pypy.interpreter.error import OperationError
 from pypy.interpreter import gateway

Modified: pypy/branch/jit-unroll-loops/pypy/module/_rawffi/interp_rawffi.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/module/_rawffi/interp_rawffi.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/module/_rawffi/interp_rawffi.py	Sat Oct 30 16:41:17 2010
@@ -5,7 +5,7 @@
 from pypy.interpreter.gateway import interp2app, NoneNotWrapped
 from pypy.interpreter.typedef import TypeDef, GetSetProperty
 
-from pypy.rlib.libffi import *
+from pypy.rlib.clibffi import *
 from pypy.rpython.lltypesystem import lltype, rffi
 from pypy.rlib.unroll import unrolling_iterable
 

Modified: pypy/branch/jit-unroll-loops/pypy/module/_rawffi/structure.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/module/_rawffi/structure.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/module/_rawffi/structure.py	Sat Oct 30 16:41:17 2010
@@ -15,7 +15,7 @@
 from pypy.module._rawffi.interp_rawffi import wrap_value, unwrap_value
 from pypy.module._rawffi.interp_rawffi import unpack_shape_with_length
 from pypy.module._rawffi.interp_rawffi import size_alignment
-from pypy.rlib import libffi
+from pypy.rlib import clibffi
 from pypy.rlib.rarithmetic import intmask, r_uint
 
 def unpack_fields(space, w_fields):
@@ -34,7 +34,7 @@
 def round_up(size, alignment):
     return (size + alignment - 1) & -alignment
 
-def size_alignment_pos(fields):
+def size_alignment_pos(fields, is_union=False):
     size = 0
     alignment = 1
     pos = []
@@ -42,16 +42,20 @@
         # fieldtype is a W_Array
         fieldsize = fieldtype.size
         fieldalignment = fieldtype.alignment
-        size = round_up(size, fieldalignment)
         alignment = max(alignment, fieldalignment)
-        pos.append(size)
-        size += intmask(fieldsize)
+        if is_union:
+            pos.append(0)
+            size = max(size, fieldsize)
+        else:
+            size = round_up(size, fieldalignment)
+            pos.append(size)
+            size += intmask(fieldsize)
     size = round_up(size, alignment)
     return size, alignment, pos
 
 
 class W_Structure(W_DataShape):
-    def __init__(self, space, fields, size, alignment):
+    def __init__(self, space, fields, size, alignment, is_union=False):
         name_to_index = {}
         if fields is not None:
             for i in range(len(fields)):
@@ -60,7 +64,7 @@
                     raise operationerrfmt(space.w_ValueError,
                         "duplicate field name %s", name)
                 name_to_index[name] = i
-            size, alignment, pos = size_alignment_pos(fields)
+            size, alignment, pos = size_alignment_pos(fields, is_union)
         else: # opaque case
             fields = []
             pos = []
@@ -104,14 +108,14 @@
     descr_fieldoffset.unwrap_spec = ['self', ObjSpace, str]
 
     # get the corresponding ffi_type
-    ffi_struct = lltype.nullptr(libffi.FFI_STRUCT_P.TO)
+    ffi_struct = lltype.nullptr(clibffi.FFI_STRUCT_P.TO)
 
     def get_basic_ffi_type(self):
         if not self.ffi_struct:
             # Repeated fields are delicate.  Consider for example
             #     struct { int a[5]; }
             # or  struct { struct {int x;} a[5]; }
-            # Seeing no corresponding doc in libffi, let's just repeat
+            # Seeing no corresponding doc in clibffi, let's just repeat
             # the field 5 times...
             fieldtypes = []
             for name, tp in self.fields:
@@ -122,7 +126,7 @@
                 while count + basic_size <= total_size:
                     fieldtypes.append(basic_ffi_type)
                     count += basic_size
-            self.ffi_struct = libffi.make_struct_ffitype_e(self.size,
+            self.ffi_struct = clibffi.make_struct_ffitype_e(self.size,
                                                            self.alignment,
                                                            fieldtypes)
         return self.ffi_struct.ffistruct
@@ -133,15 +137,17 @@
     
 
 
-def descr_new_structure(space, w_type, w_shapeinfo):
+def descr_new_structure(space, w_type, w_shapeinfo, union=0):
+    is_union = bool(union)
     if space.is_true(space.isinstance(w_shapeinfo, space.w_tuple)):
         w_size, w_alignment = space.fixedview(w_shapeinfo, expected_length=2)
         S = W_Structure(space, None, space.int_w(w_size),
-                                     space.int_w(w_alignment))
+                                     space.int_w(w_alignment), is_union)
     else:
         fields = unpack_fields(space, w_shapeinfo)
-        S = W_Structure(space, fields, 0, 0)
+        S = W_Structure(space, fields, 0, 0, is_union)
     return space.wrap(S)
+descr_new_structure.unwrap_spec = [ObjSpace, W_Root, W_Root, int]
 
 W_Structure.typedef = TypeDef(
     'Structure',

Modified: pypy/branch/jit-unroll-loops/pypy/module/_rawffi/test/test__rawffi.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/module/_rawffi/test/test__rawffi.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/module/_rawffi/test/test__rawffi.py	Sat Oct 30 16:41:17 2010
@@ -70,7 +70,7 @@
            return s[num];
         }
 
-        char *char_check(char x, char y)
+        const char *char_check(char x, char y)
         {
            if (y == static_str[0])
               return static_str;
@@ -185,13 +185,14 @@
                      sum_x_y
                      give perturb get_s2a check_s2a
                      AAA_first_ordinal_function
+                     ret_un_func
                   """.split()
         eci = ExternalCompilationInfo(export_symbols=symbols)
         return str(platform.compile([c_file], eci, 'x', standalone=False))
     prepare_c_example = staticmethod(prepare_c_example)
     
     def setup_class(cls):
-        from pypy.rlib.libffi import get_libc_name
+        from pypy.rlib.clibffi import get_libc_name
         space = gettestobjspace(usemodules=('_rawffi', 'struct'))
         cls.space = space
         cls.w_lib_name = space.wrap(cls.prepare_c_example())
@@ -945,14 +946,15 @@
         assert a[4] == 't'
 
     def test_union(self):
-        skip("segfaulting")
         import _rawffi
         longsize = _rawffi.sizeof('l')
-        S = _rawffi.Structure((longsize, longsize))
+        S = _rawffi.Structure([('x', 'h'), ('y', 'l')], union=True)
         s = S(autofree=False)
+        s.x = 12345
         lib = _rawffi.CDLL(self.lib_name)
         f = lib.ptr('ret_un_func', [(S, 1)], (S, 1))
         ret = f(s)
+        assert ret.y == 1234500, "ret.y == %d" % (ret.y,)
         s.free()
 
 class AppTestAutoFree:

Modified: pypy/branch/jit-unroll-loops/pypy/module/_socket/test/test_sock_app.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/module/_socket/test/test_sock_app.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/module/_socket/test/test_sock_app.py	Sat Oct 30 16:41:17 2010
@@ -254,6 +254,7 @@
     s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
     fd = s.fileno()
     w_obj = rsocket.make_address(c_addr, addrlen).as_object(fd, space)
+    lltype.free(c_addr_ll, flavor='raw')
     assert space.is_true(space.eq(w_obj, space.newtuple([
         space.wrap('lo'),
         space.wrap(socket.ntohs(8)),

Modified: pypy/branch/jit-unroll-loops/pypy/module/_sre/interp_sre.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/module/_sre/interp_sre.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/module/_sre/interp_sre.py	Sat Oct 30 16:41:17 2010
@@ -290,10 +290,8 @@
 def SRE_Pattern__new__(space, w_subtype, w_pattern, flags, w_code,
               groups=0, w_groupindex=None, w_indexgroup=None):
     n = space.int_w(space.len(w_code))
-    code = [0] * n
-    for i in range(n):
-        x = space.uint_w(space.getitem(w_code, space.wrap(i)))
-        code[i] = intmask(x)
+    code = [intmask(space.uint_w(space.getitem(w_code, space.wrap(i))))
+            for i in range(n)]
     #
     w_srepat = space.allocate_instance(W_SRE_Pattern, w_subtype)
     srepat = space.interp_w(W_SRE_Pattern, w_srepat)

Modified: pypy/branch/jit-unroll-loops/pypy/module/_weakref/interp__weakref.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/module/_weakref/interp__weakref.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/module/_weakref/interp__weakref.py	Sat Oct 30 16:41:17 2010
@@ -7,7 +7,7 @@
 import weakref
 
 
-class WeakrefLifeline(object):
+class WeakrefLifeline(W_Root):
     def __init__(self, space):
         self.space = space       # this is here for W_Root.clear_all_weakrefs()
         self.refs_weak = []

Modified: pypy/branch/jit-unroll-loops/pypy/module/_winreg/interp_winreg.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/module/_winreg/interp_winreg.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/module/_winreg/interp_winreg.py	Sat Oct 30 16:41:17 2010
@@ -1,3 +1,4 @@
+from __future__ import with_statement
 from pypy.interpreter.baseobjspace import Wrappable
 from pypy.interpreter.baseobjspace import ObjSpace, W_Root
 from pypy.interpreter.gateway import interp2app
@@ -212,13 +213,10 @@
         subkey = None
     else:
         subkey = space.str_w(w_subkey)
-    dataptr = rffi.str2charp(value)
-    try:
+    with rffi.scoped_str2charp(value) as dataptr:
         ret = rwinreg.RegSetValue(hkey, subkey, rwinreg.REG_SZ, dataptr, len(value))
-    finally:
-        rffi.free_charp(dataptr)
-    if ret != 0:
-        raiseWindowsError(space, ret, 'RegSetValue')
+        if ret != 0:
+            raiseWindowsError(space, ret, 'RegSetValue')
 SetValue.unwrap_spec = [ObjSpace, W_Root, W_Root, int, str]
 
 def QueryValue(space, w_hkey, w_subkey):
@@ -237,23 +235,15 @@
         subkey = None
     else:
         subkey = space.str_w(w_subkey)
-    bufsize_p = lltype.malloc(rwin32.PLONG.TO, 1, flavor='raw')
-    try:
+    with lltype.scoped_alloc(rwin32.PLONG.TO, 1) as bufsize_p:
         ret = rwinreg.RegQueryValue(hkey, subkey, None, bufsize_p)
         if ret != 0:
             raiseWindowsError(space, ret, 'RegQueryValue')
-        buf = lltype.malloc(rffi.CCHARP.TO, bufsize_p[0], flavor='raw')
-        try:
+        with lltype.scoped_alloc(rffi.CCHARP.TO, bufsize_p[0]) as buf:
             ret = rwinreg.RegQueryValue(hkey, subkey, buf, bufsize_p)
             if ret != 0:
                 raiseWindowsError(space, ret, 'RegQueryValue')
             return space.wrap(rffi.charp2strn(buf, bufsize_p[0] - 1))
-        finally:
-            lltype.free(buf, flavor='raw')
-    finally:
-        lltype.free(bufsize_p, flavor='raw')
-    if ret != 0:
-        raiseWindowsError(space, ret, 'RegQueryValue')
 QueryValue.unwrap_spec = [ObjSpace, W_Root, W_Root]
 
 def convert_to_regdata(space, w_value, typ):
@@ -412,16 +402,14 @@
 value_name is a string indicating the value to query"""
     hkey = hkey_w(w_hkey, space)
     null_dword = lltype.nullptr(rwin32.LPDWORD.TO)
-    retDataSize = lltype.malloc(rwin32.LPDWORD.TO, 1, flavor='raw')
-    try:
+    with lltype.scoped_alloc(rwin32.LPDWORD.TO, 1) as retDataSize:
         ret = rwinreg.RegQueryValueEx(hkey, subkey, null_dword, null_dword,
                                       None, retDataSize)
         if ret != 0:
             raiseWindowsError(space, ret, 'RegQueryValueEx')
-        databuf = lltype.malloc(rffi.CCHARP.TO, retDataSize[0], flavor='raw')
-        try:
-            retType = lltype.malloc(rwin32.LPDWORD.TO, 1, flavor='raw')
-            try:
+
+        with lltype.scoped_alloc(rffi.CCHARP.TO, retDataSize[0]) as databuf:
+            with lltype.scoped_alloc(rwin32.LPDWORD.TO, 1) as retType:
 
                 ret = rwinreg.RegQueryValueEx(hkey, subkey, null_dword,
                                               retType, databuf, retDataSize)
@@ -432,12 +420,6 @@
                                          retDataSize[0], retType[0]),
                     space.wrap(retType[0]),
                     ])
-            finally:
-                lltype.free(retType, flavor='raw')
-        finally:
-            lltype.free(databuf, flavor='raw')
-    finally:
-        lltype.free(retDataSize, flavor='raw')
 
 QueryValueEx.unwrap_spec = [ObjSpace, W_Root, str]
 
@@ -454,14 +436,11 @@
 The return value is the handle of the opened key.
 If the function fails, an exception is raised."""
     hkey = hkey_w(w_hkey, space)
-    rethkey = lltype.malloc(rwinreg.PHKEY.TO, 1, flavor='raw')
-    try:
+    with lltype.scoped_alloc(rwinreg.PHKEY.TO, 1) as rethkey:
         ret = rwinreg.RegCreateKey(hkey, subkey, rethkey)
         if ret != 0:
             raiseWindowsError(space, ret, 'CreateKey')
         return space.wrap(W_HKEY(rethkey[0]))
-    finally:
-        lltype.free(rethkey, flavor='raw')
 CreateKey.unwrap_spec = [ObjSpace, W_Root, str]
 
 def DeleteKey(space, w_hkey, subkey):
@@ -504,14 +483,11 @@
 The result is a new handle to the specified key
 If the function fails, an EnvironmentError exception is raised."""
     hkey = hkey_w(w_hkey, space)
-    rethkey = lltype.malloc(rwinreg.PHKEY.TO, 1, flavor='raw')
-    try:
+    with lltype.scoped_alloc(rwinreg.PHKEY.TO, 1) as rethkey:
         ret = rwinreg.RegOpenKeyEx(hkey, subkey, res, sam, rethkey)
         if ret != 0:
             raiseWindowsError(space, ret, 'RegOpenKeyEx')
         return space.wrap(W_HKEY(rethkey[0]))
-    finally:
-        lltype.free(rethkey, flavor='raw')
 OpenKey.unwrap_spec = [ObjSpace, W_Root, str, int, rffi.r_uint]
 
 def EnumValue(space, w_hkey, index):
@@ -531,10 +507,8 @@
     hkey = hkey_w(w_hkey, space)
     null_dword = lltype.nullptr(rwin32.LPDWORD.TO)
 
-    retValueSize = lltype.malloc(rwin32.LPDWORD.TO, 1, flavor='raw')
-    try:
-        retDataSize = lltype.malloc(rwin32.LPDWORD.TO, 1, flavor='raw')
-        try:
+    with lltype.scoped_alloc(rwin32.LPDWORD.TO, 1) as retValueSize:
+        with lltype.scoped_alloc(rwin32.LPDWORD.TO, 1) as retDataSize:
             ret = rwinreg.RegQueryInfoKey(
                 hkey, None, null_dword, null_dword,
                 null_dword, null_dword, null_dword,
@@ -546,14 +520,9 @@
             retValueSize[0] += 1
             retDataSize[0] += 1
 
-            valuebuf = lltype.malloc(rffi.CCHARP.TO, retValueSize[0],
-                                     flavor='raw')
-            try:
-                databuf = lltype.malloc(rffi.CCHARP.TO, retDataSize[0],
-                                        flavor='raw')
-                try:
-                    retType = lltype.malloc(rwin32.LPDWORD.TO, 1, flavor='raw')
-                    try:
+            with lltype.scoped_alloc(rffi.CCHARP.TO, retValueSize[0]) as valuebuf:
+                with lltype.scoped_alloc(rffi.CCHARP.TO, retDataSize[0]) as databuf:
+                    with lltype.scoped_alloc(rwin32.LPDWORD.TO, 1) as retType:
                         ret = rwinreg.RegEnumValue(
                             hkey, index, valuebuf, retValueSize,
                             null_dword, retType, databuf, retDataSize)
@@ -566,16 +535,6 @@
                                                  retDataSize[0], retType[0]),
                             space.wrap(retType[0]),
                             ])
-                    finally:
-                        lltype.free(retType, flavor='raw')
-                finally:
-                    lltype.free(databuf, flavor='raw')
-            finally:
-                lltype.free(valuebuf, flavor='raw')
-        finally:
-            lltype.free(retDataSize, flavor='raw')
-    finally:
-        lltype.free(retValueSize, flavor='raw')
 
 EnumValue.unwrap_spec = [ObjSpace, W_Root, int]
 
@@ -592,10 +551,8 @@
     null_dword = lltype.nullptr(rwin32.LPDWORD.TO)
 
     # max key name length is 255
-    buf = lltype.malloc(rffi.CCHARP.TO, 256, flavor='raw')
-    try:
-        retValueSize = lltype.malloc(rwin32.LPDWORD.TO, 1, flavor='raw')
-        try:
+    with lltype.scoped_alloc(rffi.CCHARP.TO, 256) as buf:
+        with lltype.scoped_alloc(rwin32.LPDWORD.TO, 1) as retValueSize:
             retValueSize[0] = 256 # includes NULL terminator
             ret = rwinreg.RegEnumKeyEx(hkey, index, buf, retValueSize,
                                        null_dword, None, null_dword,
@@ -603,10 +560,6 @@
             if ret != 0:
                 raiseWindowsError(space, ret, 'RegEnumKeyEx')
             return space.wrap(rffi.charp2str(buf))
-        finally:
-            lltype.free(retValueSize, flavor='raw')
-    finally:
-        lltype.free(buf, flavor='raw')
 
 EnumKey.unwrap_spec = [ObjSpace, W_Root, int]
 
@@ -621,12 +574,9 @@
 A long integer that identifies when the key was last modified (if available)
  as 100's of nanoseconds since Jan 1, 1600."""
     hkey = hkey_w(w_hkey, space)
-    nSubKeys = lltype.malloc(rwin32.LPDWORD.TO, 1, flavor='raw')
-    try:
-        nValues = lltype.malloc(rwin32.LPDWORD.TO, 1, flavor='raw')
-        try:
-            ft = lltype.malloc(rwin32.PFILETIME.TO, 1, flavor='raw')
-            try:
+    with lltype.scoped_alloc(rwin32.LPDWORD.TO, 1) as nSubKeys:
+        with lltype.scoped_alloc(rwin32.LPDWORD.TO, 1) as nValues:
+            with lltype.scoped_alloc(rwin32.PFILETIME.TO, 1) as ft:
                 null_dword = lltype.nullptr(rwin32.LPDWORD.TO)
                 ret = rwinreg.RegQueryInfoKey(
                     hkey, None, null_dword, null_dword,
@@ -640,12 +590,6 @@
                 return space.newtuple([space.wrap(nSubKeys[0]),
                                        space.wrap(nValues[0]),
                                        space.wrap(l)])
-            finally:
-                lltype.free(ft, flavor='raw')
-        finally:
-            lltype.free(nValues, flavor='raw')
-    finally:
-        lltype.free(nSubKeys, flavor='raw')
 QueryInfoKey.unwrap_spec = [ObjSpace, W_Root]
 
 def str_or_None_w(space, w_obj):
@@ -666,12 +610,9 @@
 If the function fails, an EnvironmentError exception is raised."""
     machine = str_or_None_w(space, w_machine)
     hkey = hkey_w(w_hkey, space)
-    rethkey = lltype.malloc(rwinreg.PHKEY.TO, 1, flavor='raw')
-    try:
+    with lltype.scoped_alloc(rwinreg.PHKEY.TO, 1) as rethkey:
         ret = rwinreg.RegConnectRegistry(machine, hkey, rethkey)
         if ret != 0:
             raiseWindowsError(space, ret, 'RegConnectRegistry')
         return space.wrap(W_HKEY(rethkey[0]))
-    finally:
-        lltype.free(rethkey, flavor='raw')
 ConnectRegistry.unwrap_spec = [ObjSpace, W_Root, W_Root]

Modified: pypy/branch/jit-unroll-loops/pypy/module/array/interp_array.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/module/array/interp_array.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/module/array/interp_array.py	Sat Oct 30 16:41:17 2010
@@ -192,32 +192,30 @@
                           mytype.bytes
                     raise OperationError(space.w_OverflowError,
                                          space.wrap(msg))
-            elif mytype.unwrap == 'str_w' or mytype.unwrap == 'unicode_w':
+                return rffi.cast(mytype.itemtype, item)
+            if mytype.unwrap == 'str_w' or mytype.unwrap == 'unicode_w':
                 if len(item) != 1:
                     msg = 'array item must be char'
                     raise OperationError(space.w_TypeError, space.wrap(msg))
                 item = item[0]
-
+                return rffi.cast(mytype.itemtype, item)
+            #
+            # "regular" case: it fits in an rpython integer (lltype.Signed)
+            result = rffi.cast(mytype.itemtype, item)
             if mytype.canoverflow:
-                msg = None
-                if mytype.signed:
-                    if item < -1 << (mytype.bytes * 8 - 1):
+                if rffi.cast(lltype.Signed, result) != item:
+                    # overflow.  build the correct message
+                    if item < 0:
                         msg = ('signed %d-byte integer is less than minimum' %
                                mytype.bytes)
-                    elif item > (1 << (mytype.bytes * 8 - 1)) - 1:
+                    else:
                         msg = ('signed %d-byte integer is greater than maximum'
                                % mytype.bytes)
-                else:
-                    if item < 0:
-                        msg = ('unsigned %d-byte integer is less than minimum'
-                               % mytype.bytes)
-                    elif item > (1 << (mytype.bytes * 8)) - 1:
-                        msg = ('unsigned %d-byte integer is greater'
-                               ' than maximum' % mytype.bytes)
-                if msg is not None:
+                    if not mytype.signed:
+                        msg = 'un' + msg      # 'signed' => 'unsigned'
                     raise OperationError(space.w_OverflowError,
                                          space.wrap(msg))
-            return rffi.cast(mytype.itemtype, item)
+            return result
 
         def __del__(self):
             self.setlen(0)

Modified: pypy/branch/jit-unroll-loops/pypy/module/bz2/interp_bz2.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/module/bz2/interp_bz2.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/module/bz2/interp_bz2.py	Sat Oct 30 16:41:17 2010
@@ -1,3 +1,4 @@
+from __future__ import with_statement
 from pypy.rpython.tool import rffi_platform as platform
 from pypy.rpython.lltypesystem import rffi
 from pypy.rpython.lltypesystem import lltype
@@ -225,6 +226,11 @@
         if self.current_size > 0:
             rffi.keep_buffer_alive_until_here(self.raw_buf, self.gc_buf)
 
+    def __enter__(self):
+        return self
+    def __exit__(self, *args):
+        self.free()
+
 # ____________________________________________________________
 #
 # Make the BZ2File type by internally inheriting from W_File.
@@ -531,33 +537,30 @@
         if not self.running:
             raise OperationError(self.space.w_ValueError,
                 self.space.wrap("this object was already flushed"))
-        
-        out = OutBuffer(self.bzs)
+
         in_bufsize = datasize
-        in_buf = lltype.malloc(rffi.CCHARP.TO, in_bufsize, flavor='raw')
-        for i in range(datasize):
-            in_buf[i] = data[i]
 
-        try:
-        
-            self.bzs.c_next_in = in_buf
-            rffi.setintfield(self.bzs, 'c_avail_in', in_bufsize)
+        with OutBuffer(self.bzs) as out:
+            with lltype.scoped_alloc(rffi.CCHARP.TO, in_bufsize) as in_buf:
 
-            while True:
-                bzerror = BZ2_bzCompress(self.bzs, BZ_RUN)
-                if bzerror != BZ_RUN_OK:
-                    _catch_bz2_error(self.space, bzerror)
+                for i in range(datasize):
+                    in_buf[i] = data[i]
 
-                if rffi.getintfield(self.bzs, 'c_avail_in') == 0:
-                    break
-                elif rffi.getintfield(self.bzs, 'c_avail_out') == 0:
-                    out.prepare_next_chunk()
+                self.bzs.c_next_in = in_buf
+                rffi.setintfield(self.bzs, 'c_avail_in', in_bufsize)
 
-            res = out.make_result_string()
-            return self.space.wrap(res)
-        finally:
-            lltype.free(in_buf, flavor='raw')
-            out.free()
+                while True:
+                    bzerror = BZ2_bzCompress(self.bzs, BZ_RUN)
+                    if bzerror != BZ_RUN_OK:
+                        _catch_bz2_error(self.space, bzerror)
+
+                    if rffi.getintfield(self.bzs, 'c_avail_in') == 0:
+                        break
+                    elif rffi.getintfield(self.bzs, 'c_avail_out') == 0:
+                        out.prepare_next_chunk()
+
+                res = out.make_result_string()
+                return self.space.wrap(res)
 
     compress.unwrap_spec = ['self', 'bufferstr']
     
@@ -566,9 +569,8 @@
             raise OperationError(self.space.w_ValueError,
                 self.space.wrap("this object was already flushed"))
         self.running = False
-        
-        out = OutBuffer(self.bzs)
-        try:
+
+        with OutBuffer(self.bzs) as out:
             while True:
                 bzerror = BZ2_bzCompress(self.bzs, BZ_FINISH)
                 if bzerror == BZ_STREAM_END:
@@ -581,8 +583,6 @@
 
             res = out.make_result_string()
             return self.space.wrap(res)
-        finally:
-            out.free()
     flush.unwrap_spec = ['self']
 
 W_BZ2Compressor.typedef = TypeDef("BZ2Compressor",
@@ -641,38 +641,37 @@
         if not self.running:
             raise OperationError(self.space.w_EOFError,
                 self.space.wrap("end of stream was already found"))
-        
+
         in_bufsize = len(data)
-        in_buf = lltype.malloc(rffi.CCHARP.TO, in_bufsize, flavor='raw')
-        for i in range(in_bufsize):
-            in_buf[i] = data[i]
 
-        out = OutBuffer(self.bzs)
-        try:
+        with lltype.scoped_alloc(rffi.CCHARP.TO, in_bufsize) as in_buf:
+            for i in range(in_bufsize):
+                in_buf[i] = data[i]
             self.bzs.c_next_in = in_buf
             rffi.setintfield(self.bzs, 'c_avail_in', in_bufsize)
 
-            while True:
-                bzerror = BZ2_bzDecompress(self.bzs)
-                if bzerror == BZ_STREAM_END:
-                    if rffi.getintfield(self.bzs, 'c_avail_in') != 0:
-                        unused = [self.bzs.c_next_in[i] for i in range(rffi.getintfield(self.bzs, 'c_avail_in'))]
-                        self.unused_data = "".join(unused)
-                    self.running = False
-                    break
-                if bzerror != BZ_OK:
-                    _catch_bz2_error(self.space, bzerror)
-
-                if rffi.getintfield(self.bzs, 'c_avail_in') == 0:
-                    break
-                elif rffi.getintfield(self.bzs, 'c_avail_out') == 0:
-                    out.prepare_next_chunk()
+            with OutBuffer(self.bzs) as out:
+                while True:
+                    bzerror = BZ2_bzDecompress(self.bzs)
+                    if bzerror == BZ_STREAM_END:
+                        if rffi.getintfield(self.bzs, 'c_avail_in') != 0:
+                            unused = [self.bzs.c_next_in[i]
+                                      for i in range(
+                                          rffi.getintfield(self.bzs,
+                                                           'c_avail_in'))]
+                            self.unused_data = "".join(unused)
+                        self.running = False
+                        break
+                    if bzerror != BZ_OK:
+                        _catch_bz2_error(self.space, bzerror)
+
+                    if rffi.getintfield(self.bzs, 'c_avail_in') == 0:
+                        break
+                    elif rffi.getintfield(self.bzs, 'c_avail_out') == 0:
+                        out.prepare_next_chunk()
 
-            res = out.make_result_string()
-            return self.space.wrap(res)
-        finally:
-            lltype.free(in_buf, flavor='raw')
-            out.free()
+                res = out.make_result_string()
+                return self.space.wrap(res)
 
     decompress.unwrap_spec = ['self', 'bufferstr']
 
@@ -695,43 +694,39 @@
     if compresslevel < 1 or compresslevel > 9:
         raise OperationError(space.w_ValueError,
             space.wrap("compresslevel must be between 1 and 9"))
-            
-    bzs = lltype.malloc(bz_stream.TO, flavor='raw', zero=True)
-    in_bufsize = len(data)
-    # conforming to bz2 manual, this is large enough to fit compressed
-    # data in one shot. We will check it later anyway.
-    out = OutBuffer(bzs, in_bufsize + (in_bufsize / 100 + 1) + 600)
-
-    in_buf = lltype.malloc(rffi.CCHARP.TO, in_bufsize, flavor='raw')
-    for i in range(in_bufsize):
-        in_buf[i] = data[i]
-
-    try:
-        bzs.c_next_in = in_buf
-        rffi.setintfield(bzs, 'c_avail_in', in_bufsize)
 
-        bzerror = BZ2_bzCompressInit(bzs, compresslevel, 0, 0)
-        if bzerror != BZ_OK:
-            _catch_bz2_error(space, bzerror)
+    with lltype.scoped_alloc(bz_stream.TO, zero=True) as bzs:
+        in_bufsize = len(data)
+
+        with lltype.scoped_alloc(rffi.CCHARP.TO, in_bufsize) as in_buf:
+            for i in range(in_bufsize):
+                in_buf[i] = data[i]
+            bzs.c_next_in = in_buf
+            rffi.setintfield(bzs, 'c_avail_in', in_bufsize)
+
+            # conforming to bz2 manual, this is large enough to fit compressed
+            # data in one shot. We will check it later anyway.
+            with OutBuffer(bzs,
+                           in_bufsize + (in_bufsize / 100 + 1) + 600) as out:
+
+                bzerror = BZ2_bzCompressInit(bzs, compresslevel, 0, 0)
+                if bzerror != BZ_OK:
+                    _catch_bz2_error(space, bzerror)
 
-        while True:
-            bzerror = BZ2_bzCompress(bzs, BZ_FINISH)
-            if bzerror == BZ_STREAM_END:
-                break
-            elif bzerror != BZ_FINISH_OK:
+                while True:
+                    bzerror = BZ2_bzCompress(bzs, BZ_FINISH)
+                    if bzerror == BZ_STREAM_END:
+                        break
+                    elif bzerror != BZ_FINISH_OK:
+                        BZ2_bzCompressEnd(bzs)
+                        _catch_bz2_error(space, bzerror)
+
+                    if rffi.getintfield(bzs, 'c_avail_out') == 0:
+                        out.prepare_next_chunk()
+
+                res = out.make_result_string()
                 BZ2_bzCompressEnd(bzs)
-                _catch_bz2_error(space, bzerror)
-            
-            if rffi.getintfield(bzs, 'c_avail_out') == 0:
-                out.prepare_next_chunk()
-
-        res = out.make_result_string()
-        BZ2_bzCompressEnd(bzs)
-        return space.wrap(res)
-    finally:
-        lltype.free(bzs, flavor='raw')
-        lltype.free(in_buf, flavor='raw')
-        out.free()
+                return space.wrap(res)
 compress.unwrap_spec = [ObjSpace, 'bufferstr', int]
 
 def decompress(space, data):
@@ -744,40 +739,34 @@
     if in_bufsize == 0:
         return space.wrap("")
 
-    bzs = lltype.malloc(bz_stream.TO, flavor='raw', zero=True)
-    in_buf = lltype.malloc(rffi.CCHARP.TO, in_bufsize, flavor='raw')
-    for i in range(in_bufsize):
-        in_buf[i] = data[i]
-
-    out = OutBuffer(bzs)
-    try:
-        bzs.c_next_in = in_buf
-        rffi.setintfield(bzs, 'c_avail_in', in_bufsize)
-    
-        bzerror = BZ2_bzDecompressInit(bzs, 0, 0)
-        if bzerror != BZ_OK:
-            _catch_bz2_error(space, bzerror)
-        
-        while True:
-            bzerror = BZ2_bzDecompress(bzs)
-            if bzerror == BZ_STREAM_END:
-                break
-            if bzerror != BZ_OK:
-                BZ2_bzDecompressEnd(bzs)
-                _catch_bz2_error(space, bzerror)
-        
-            if rffi.getintfield(bzs, 'c_avail_in') == 0:
+    with lltype.scoped_alloc(bz_stream.TO, zero=True) as bzs:
+        with lltype.scoped_alloc(rffi.CCHARP.TO, in_bufsize) as in_buf:
+            for i in range(in_bufsize):
+                in_buf[i] = data[i]
+            bzs.c_next_in = in_buf
+            rffi.setintfield(bzs, 'c_avail_in', in_bufsize)
+
+            with OutBuffer(bzs) as out:
+                bzerror = BZ2_bzDecompressInit(bzs, 0, 0)
+                if bzerror != BZ_OK:
+                    _catch_bz2_error(space, bzerror)
+
+                while True:
+                    bzerror = BZ2_bzDecompress(bzs)
+                    if bzerror == BZ_STREAM_END:
+                        break
+                    if bzerror != BZ_OK:
+                        BZ2_bzDecompressEnd(bzs)
+                    _catch_bz2_error(space, bzerror)
+
+                    if rffi.getintfield(bzs, 'c_avail_in') == 0:
+                        BZ2_bzDecompressEnd(bzs)
+                        raise OperationError(space.w_ValueError, space.wrap(
+                            "couldn't find end of stream"))
+                    elif rffi.getintfield(bzs, 'c_avail_out') == 0:
+                        out.prepare_next_chunk()
+
+                res = out.make_result_string()
                 BZ2_bzDecompressEnd(bzs)
-                raise OperationError(space.w_ValueError,
-                                     space.wrap("couldn't find end of stream"))
-            elif rffi.getintfield(bzs, 'c_avail_out') == 0:
-                out.prepare_next_chunk()
-
-        res = out.make_result_string()
-        BZ2_bzDecompressEnd(bzs)
-        return space.wrap(res)
-    finally:
-        lltype.free(bzs, flavor='raw')
-        lltype.free(in_buf, flavor='raw')
-        out.free()
+                return space.wrap(res)
 decompress.unwrap_spec = [ObjSpace, 'bufferstr']

Modified: pypy/branch/jit-unroll-loops/pypy/module/cpyext/classobject.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/module/cpyext/classobject.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/module/cpyext/classobject.py	Sat Oct 30 16:41:17 2010
@@ -15,16 +15,20 @@
     class is the class of new object.  The dict parameter will be used as the
     object's __dict__; if NULL, a new dictionary will be created for the
     instance."""
-    if not PyClass_Check(space, w_class):
+    if not isinstance(w_class, W_ClassObject):
         return PyErr_BadInternalCall(space)
-    return W_InstanceObject(space, w_class, w_dict)
+    w_result = w_class.instantiate(space)
+    if w_dict is not None:
+        w_result.setdict(space, w_dict)
+    return w_result
 
 @cpython_api([PyObject, PyObject], PyObject, error=CANNOT_FAIL)
 def _PyInstance_Lookup(space, w_instance, w_name):
+    name = space.str_w(w_name)
     assert isinstance(w_instance, W_InstanceObject)
-    w_result = space.finditem(w_instance.w_dict, w_name)
+    w_result = w_instance.getdictvalue(space, name)
     if w_result is not None:
         return w_result
-    return w_instance.w_class.lookup(space, w_name)
+    return w_instance.w_class.lookup(space, name)
 
 

Modified: pypy/branch/jit-unroll-loops/pypy/module/cpyext/test/test_cpyext.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/module/cpyext/test/test_cpyext.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/module/cpyext/test/test_cpyext.py	Sat Oct 30 16:41:17 2010
@@ -16,6 +16,7 @@
 from pypy.module.cpyext.pyobject import Py_DecRef, InvalidPointerException
 from pypy.translator.goal import autopath
 from pypy.tool.identity_dict import identity_dict
+from pypy.tool import leakfinder
 
 @api.cpython_api([], api.PyObject)
 def PyPy_Crash1(space):
@@ -78,7 +79,6 @@
         self.frozen_refcounts[w_obj] = obj.c_ob_refcnt
     #state.print_refcounts()
     self.frozen_ll2callocations = set(ll2ctypes.ALLOCATED.values())
-    lltype.start_tracking_allocations()
 
 class LeakCheckingTest(object):
     def check_and_print_leaks(self):
@@ -126,17 +126,8 @@
         for w_obj in lost_objects_w:
             print >>sys.stderr, "Lost object %r" % (w_obj, )
             leaking = True
-        for llvalue in set(ll2ctypes.ALLOCATED.values()) - self.frozen_ll2callocations:
-            if getattr(llvalue, "_traceback", None): # this means that the allocation should be tracked
-                leaking = True
-                print >>sys.stderr, "Did not deallocate %r (ll2ctypes)" % (llvalue, )
-                print >>sys.stderr, "\t" + "\n\t".join(llvalue._traceback.splitlines())
-        for llvalue in lltype.ALLOCATED.keys():
-            leaking = True
-            print >>sys.stderr, "Did not deallocate %r (llvalue)" % (llvalue, )
-            print >>sys.stderr, "\t" + "\n\t".join(llvalue._traceback.splitlines())
-
-        lltype.stop_tracking_allocations()
+        # the actual low-level leak checking is done by pypy.tool.leakfinder,
+        # enabled automatically by pypy.conftest.
         return leaking
 
 class AppTestCpythonExtensionBase(LeakCheckingTest):

Modified: pypy/branch/jit-unroll-loops/pypy/module/cpyext/test/test_unicodeobject.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/module/cpyext/test/test_unicodeobject.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/module/cpyext/test/test_unicodeobject.py	Sat Oct 30 16:41:17 2010
@@ -177,13 +177,14 @@
             encoded_charp = rffi.str2charp(encoded)
             strict_charp = rffi.str2charp("strict")
             if endian is not None:
-                pendian = lltype.malloc(rffi.INTP.TO, 1, flavor='raw')
                 if endian < 0:
-                    pendian[0] = -1
+                    value = -1
                 elif endian > 0:
-                    pendian[0] = 1
+                    value = 1
                 else:
-                    pendian[0] = 0
+                    value = 0
+                pendian = lltype.malloc(rffi.INTP.TO, 1, flavor='raw')
+                pendian[0] = rffi.cast(rffi.INT, value)
             else:
                 pendian = None
 

Modified: pypy/branch/jit-unroll-loops/pypy/module/gc/interp_gc.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/module/gc/interp_gc.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/module/gc/interp_gc.py	Sat Oct 30 16:41:17 2010
@@ -5,6 +5,11 @@
 
 def collect(space):
     "Run a full collection."
+    # First clear the method cache.  See test_gc for an example of why.
+    if space.config.objspace.std.withmethodcache:
+        from pypy.objspace.std.typeobject import MethodCache
+        cache = space.fromcache(MethodCache)
+        cache.clear()
     rgc.collect()
     return space.wrap(0)
     

Modified: pypy/branch/jit-unroll-loops/pypy/module/gc/referents.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/module/gc/referents.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/module/gc/referents.py	Sat Oct 30 16:41:17 2010
@@ -15,8 +15,16 @@
 
 def try_cast_gcref_to_w_root(gcref):
     w_obj = rgc.try_cast_gcref_to_instance(W_Root, gcref)
-    if not we_are_translated() and not hasattr(w_obj, 'typedef'):
-        w_obj = None
+    # Ignore the instances of W_Root that are not really valid as Python
+    # objects.  There is e.g. WeakrefLifeline in module/_weakref that
+    # inherits from W_Root for internal reasons.  Such instances don't
+    # have a typedef at all (or have a null typedef after translation).
+    if not we_are_translated():
+        if not hasattr(w_obj, 'typedef'):
+            return None
+    else:
+        if w_obj is None or not w_obj.typedef:
+            return None
     return w_obj
 
 def wrap(space, gcref):

Modified: pypy/branch/jit-unroll-loops/pypy/module/gc/test/test_gc.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/module/gc/test/test_gc.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/module/gc/test/test_gc.py	Sat Oct 30 16:41:17 2010
@@ -103,3 +103,22 @@
         import gc
         gc.dump_heap_stats(self.fname)
 
+
+class AppTestGcMethodCache(object):
+    def setup_class(cls):
+        cls.space = gettestobjspace(**{"objspace.std.withmethodcache": True})
+
+    def test_clear_method_cache(self):
+        import gc, weakref
+        rlist = []
+        def f():
+            class C(object):
+                def f(self):
+                    pass
+            C().f()    # Fill the method cache
+            rlist.append(weakref.ref(C))
+        for i in range(5):
+            f()
+        gc.collect()    # the classes C should all go away here
+        for r in rlist:
+            assert r() is None

Modified: pypy/branch/jit-unroll-loops/pypy/module/imp/importing.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/module/imp/importing.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/module/imp/importing.py	Sat Oct 30 16:41:17 2010
@@ -122,7 +122,7 @@
                     n = len(ctxt_name_prefix_parts)-level+1
                     assert n>=0
                     ctxt_name_prefix_parts = ctxt_name_prefix_parts[:n]
-                if ctxt_w_path is None: # plain module
+                if ctxt_name_prefix_parts and ctxt_w_path is None: # plain module
                     ctxt_name_prefix_parts.pop()
                 if ctxt_name_prefix_parts:
                     rel_modulename = '.'.join(ctxt_name_prefix_parts)

Modified: pypy/branch/jit-unroll-loops/pypy/module/imp/test/test_import.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/module/imp/test/test_import.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/module/imp/test/test_import.py	Sat Oct 30 16:41:17 2010
@@ -360,6 +360,12 @@
         """.rstrip()
         raises(ValueError, imp)
 
+    def test_future_relative_import_error_when_in_non_package2(self):
+        exec """def imp():
+                    from .. import inpackage
+        """.rstrip()
+        raises(ValueError, imp)
+
     def test_relative_import_with___name__(self):
         import sys
         mydict = {'__name__': 'sys.foo'}
@@ -784,6 +790,7 @@
     extrapath = udir.ensure("pythonpath", dir=1) 
     extrapath.join("urllib.py").write("print 42\n")
     old = os.environ.get('PYTHONPATH', None)
+    oldlang = os.environ.pop('LANG', None)
     try: 
         os.environ['PYTHONPATH'] = str(extrapath)
         output = py.process.cmdexec('''"%s" "%s" -c "import urllib"''' % 
@@ -792,6 +799,8 @@
     finally: 
         if old: 
             os.environ['PYTHONPATH'] = old 
+        if oldlang:
+            os.environ['LANG'] = oldlang
 
 class AppTestImportHooks(object):
     def test_meta_path(self):

Modified: pypy/branch/jit-unroll-loops/pypy/module/parser/test/test_parser.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/module/parser/test/test_parser.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/module/parser/test/test_parser.py	Sat Oct 30 16:41:17 2010
@@ -10,6 +10,9 @@
         cls.w_m = space.appexec([], """():
     import parser
     return parser""")
+        cls.w_symbol = space.appexec([], """():
+    import symbol
+    return symbol""")
 
 
 class AppTestParser(ParserModuleTest):
@@ -36,7 +39,7 @@
             seq = getattr(s, meth)()
             assert isinstance(seq, tp)
             assert len(seq) == 4
-            assert seq[0] == 286
+            assert seq[0] == self.symbol.file_input
             assert len(seq[2]) == 2
             assert len(seq[3]) == 2
             assert seq[2][0] == 4

Modified: pypy/branch/jit-unroll-loops/pypy/module/pypyjit/__init__.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/module/pypyjit/__init__.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/module/pypyjit/__init__.py	Sat Oct 30 16:41:17 2010
@@ -6,6 +6,7 @@
 
     interpleveldefs = {
         'set_param':    'interp_jit.set_param',
+        'residual_call': 'interp_jit.residual_call',
     }
 
     def setup_after_space_initialization(self):

Modified: pypy/branch/jit-unroll-loops/pypy/module/pypyjit/interp_jit.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/module/pypyjit/interp_jit.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/module/pypyjit/interp_jit.py	Sat Oct 30 16:41:17 2010
@@ -5,10 +5,10 @@
 
 from pypy.tool.pairtype import extendabletype
 from pypy.rlib.rarithmetic import r_uint, intmask
-from pypy.rlib.jit import JitDriver, hint, we_are_jitted
+from pypy.rlib.jit import JitDriver, hint, we_are_jitted, dont_look_inside
 import pypy.interpreter.pyopcode   # for side-effects
 from pypy.interpreter.error import OperationError, operationerrfmt
-from pypy.interpreter.gateway import ObjSpace, Arguments
+from pypy.interpreter.gateway import ObjSpace, Arguments, W_Root
 from pypy.interpreter.pycode import PyCode, CO_GENERATOR
 from pypy.interpreter.pyframe import PyFrame
 from pypy.interpreter.pyopcode import ExitFrame
@@ -131,3 +131,10 @@
                                   "no JIT parameter '%s'", key)
 
 set_param.unwrap_spec = [ObjSpace, Arguments]
+
+ at dont_look_inside
+def residual_call(space, w_callable, args):
+    '''For testing.  Invokes callable(...), but without letting
+    the JIT follow the call.'''
+    return space.call_args(w_callable, args)
+residual_call.unwrap_spec = [ObjSpace, W_Root, Arguments]

Modified: pypy/branch/jit-unroll-loops/pypy/module/pypyjit/policy.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/module/pypyjit/policy.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/module/pypyjit/policy.py	Sat Oct 30 16:41:17 2010
@@ -11,7 +11,7 @@
         if '.' in modname:
             modname, _ = modname.split('.', 1)
         if modname in ['pypyjit', 'signal', 'micronumpy', 'math', 'exceptions',
-                       'imp', 'sys', 'array']:
+                       'imp', 'sys', 'array', '_ffi']:
             return True
         return False
 

Modified: pypy/branch/jit-unroll-loops/pypy/module/pypyjit/test/test_pypy_c.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/module/pypyjit/test/test_pypy_c.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/module/pypyjit/test/test_pypy_c.py	Sat Oct 30 16:41:17 2010
@@ -79,8 +79,11 @@
 
 
 class PyPyCJITTests(object):
-    def run_source(self, source, expected_max_ops, *testcases):
+    def run_source(self, source, expected_max_ops, *testcases, **kwds):
         assert isinstance(expected_max_ops, int)
+        threshold = kwds.pop('threshold', 3)
+        if kwds:
+            raise TypeError, 'Unsupported keyword arguments: %s' % kwds.keys()
         source = py.code.Source(source)
         filepath = self.tmpdir.join('case%d.py' % self.counter)
         logfilepath = filepath.new(ext='.log')
@@ -92,7 +95,7 @@
             import sys
             try: # make the file runnable by CPython
                 import pypyjit
-                pypyjit.set_param(threshold=3)
+                pypyjit.set_param(threshold=%d)
             except ImportError:
                 pass
 
@@ -102,7 +105,7 @@
                 print >> sys.stderr, 'got:', repr(result)
                 assert result == expected
                 assert type(result) is type(expected)
-        """)
+        """ % threshold)
         for testcase in testcases * 2:
             print >> f, "check(%r, %r)" % testcase
         print >> f, "print 'OK :-)'"
@@ -116,6 +119,8 @@
         result = child_stdout.read()
         child_stdout.close()
         assert result
+        if result.strip().startswith('SKIP:'):
+            py.test.skip(result.strip())
         assert result.splitlines()[-1].strip() == 'OK :-)'
         self.parse_loops(logfilepath)
         self.print_loops()
@@ -123,16 +128,18 @@
         if self.total_ops > expected_max_ops:
             assert 0, "too many operations: got %d, expected maximum %d" % (
                 self.total_ops, expected_max_ops)
+        return result
 
     def parse_loops(self, opslogfile):
-        from pypy.jit.metainterp.test.oparser import parse
+        from pypy.jit.tool.oparser import parse
         from pypy.tool import logparser
         assert opslogfile.check()
         log = logparser.parse_log_file(str(opslogfile))
         parts = logparser.extract_category(log, 'jit-log-opt-')
+        self.rawloops = [part for part in parts
+                         if not from_entry_bridge(part, parts)]
         # skip entry bridges, they can contain random things
-        self.loops = [parse(part, no_namespace=True) for part in parts
-                          if not from_entry_bridge(part, parts)]
+        self.loops = [parse(part, no_namespace=True) for part in self.rawloops]
         self.sliced_loops = [] # contains all bytecodes of all loops
         self.total_ops = 0
         for loop in self.loops:
@@ -156,12 +163,11 @@
         return [ops for ops in self.sliced_loops if ops.bytecode == name]
 
     def print_loops(self):
-        for loop in self.loops:
+        for rawloop in self.rawloops:
             print
             print '@' * 79
             print
-            for op in loop.operations:
-                print op
+            print rawloop.rstrip()
         print
         print '@' * 79
 
@@ -272,7 +278,7 @@
         assert len(ops) == 2
         assert not ops[0].get_opnames("call")
         assert not ops[0].get_opnames("new")
-        assert len(ops[0].get_opnames("guard")) <= 7
+        assert len(ops[0].get_opnames("guard")) <= 2
         assert not ops[1] # second LOOKUP_METHOD folded away
 
         ops = self.get_by_bytecode("CALL_METHOD")
@@ -283,12 +289,16 @@
             else:
                 assert not bytecode.get_opnames("call")
             assert not bytecode.get_opnames("new")
-            assert len(bytecode.get_opnames("guard")) <= 9
+            assert len(bytecode.get_opnames("guard")) <= 6
         assert len(ops[1]) < len(ops[0])
 
         ops = self.get_by_bytecode("LOAD_ATTR")
         assert len(ops) == 2
-        assert ops[0].get_opnames() == ["getfield_gc", "getarrayitem_gc",
+        # With mapdict, we get fast access to (so far) the 5 first
+        # attributes, which means it is done with only the following
+        # operations.  (For the other attributes there is additionally
+        # a getarrayitem_gc.)
+        assert ops[0].get_opnames() == ["getfield_gc",
                                         "guard_nonnull_class"]
         assert not ops[1] # second LOAD_ATTR folded away
 
@@ -317,8 +327,8 @@
         assert len(ops) == 2
         assert not ops[0].get_opnames("call")
         assert not ops[0].get_opnames("new")
-        assert len(ops[0].get_opnames("guard")) <= 7
-        assert len(ops[0].get_opnames("getfield")) < 6
+        assert len(ops[0].get_opnames("guard")) <= 2
+        assert len(ops[0].get_opnames("getfield")) <= 4
         assert not ops[1] # second LOOKUP_METHOD folded away
 
     def test_default_and_kw(self):
@@ -382,7 +392,7 @@
                     a.x = 2
                     i = i + a.x
                 return i
-        ''', 67,
+        ''', 69,
                    ([20], 20),
                    ([31], 32))
 
@@ -390,7 +400,7 @@
                 self.get_by_bytecode("CALL_FUNCTION"))
         assert not callA.get_opnames("call")
         assert not callA.get_opnames("new")
-        assert len(callA.get_opnames("guard")) <= 8
+        assert len(callA.get_opnames("guard")) <= 2
         assert not callisinstance1.get_opnames("call")
         assert not callisinstance1.get_opnames("new")
         assert len(callisinstance1.get_opnames("guard")) <= 2
@@ -554,17 +564,13 @@
 
     def test_blockstack_virtualizable(self):
         self.run_source('''
-        def g(k):
-            s = 0
-            for i in range(k, k+2):
-                s += 1
-            return s
+        from pypyjit import residual_call
 
         def main():
             i = 0
             while i < 100:
                 try:
-                    g(i)
+                    residual_call(len, [])
                 except:
                     pass
                 i += 1
@@ -606,16 +612,17 @@
         #     call that can raise is not exchanged into getarrayitem_gc
 
     def test_overflow_checking(self):
+        startvalue = sys.maxint - 2147483647
         self.run_source('''
         def main():
             def f(a,b):
                 if a < 0: return -1
                 return a-b
-            total = 0
+            total = %d
             for i in range(100000):
                 total += f(i, 5)
             return total
-        ''', 170, ([], 4999450000L))
+        ''' % startvalue, 170, ([], startvalue + 4999450000L))
 
     def test_boolrewrite_invers(self):
         for a, b, res, ops in (('2000', '2000', 20001000, 51),
@@ -742,6 +749,8 @@
                     '''%(op1, float(a)/4.0, float(b)/4.0, op2), 109, ([], res))
 
     def test_boolrewrite_ptr(self):
+        # XXX this test is way too imprecise in what it is actually testing
+        # it should count the number of guards instead
         compares = ('a == b', 'b == a', 'a != b', 'b != a', 'a == c', 'c != b')
         for e1 in compares:
             for e2 in compares:
@@ -765,7 +774,7 @@
                 print
                 print 'Test:', e1, e2, n, res
                 self.run_source('''
-                class tst:
+                class tst(object):
                     pass
                 def main():
                     a = tst()
@@ -781,24 +790,6 @@
                     return sa
                 '''%(e1, e2), n, ([], res))
 
-    def test_boolrewrite_ptr_single(self):
-        self.run_source('''
-            class tst:
-                pass
-            def main():
-                a = tst()
-                b = tst()
-                c = tst()
-                sa = 0
-                for i in range(1000):
-                    if a == b: sa += 1
-                    else: sa += 2
-                    if a != b: sa += 10000
-                    else: sa += 20000
-                    if i > 750: a = b
-                return sa
-            ''', 215, ([], 12481752))
-
     def test_array_sum(self):
         for tc, maxops in zip('bhilBHILfd', (38,) * 6 + (40, 40, 41, 38)):
             res = 19352859
@@ -847,7 +838,12 @@
             ''', 65, ([], 122880))
 
     def test_array_intimg(self):
-        for tc, maxops in zip('ilILd', (67, 67, 69, 69, 61)):
+        # XXX this test is way too imprecise in what it is actually testing
+        # it should count the number of guards instead
+        for tc, maxops in zip('ilILd', (67, 67, 70, 70, 61)):
+            print
+            print '='*65
+            print '='*20, 'running test for tc=%r' % (tc,), '='*20
             res = 73574560
             if tc in 'IL':
                 res = long(res)
@@ -1130,6 +1126,44 @@
             return sa
         ''', 88, ([], 1997001))
 
+    def test__ffi_call(self):
+        from pypy.rlib.test.test_libffi import get_libm_name
+        libm_name = get_libm_name(sys.platform)
+        out = self.run_source('''
+        def main():
+            try:
+                from _ffi import CDLL, types
+            except ImportError:
+                sys.stdout.write('SKIP: cannot import _ffi')
+                return 0
+
+            libm = CDLL('%(libm_name)s')
+            pow = libm.getfunc('pow', [types.double, types.double],
+                               types.double)
+            print pow.getaddr()
+            i = 0
+            res = 0
+            while i < 2000:
+                res += pow(2, 3)
+                i += 1
+            return res
+        ''' % locals(),
+                              76, ([], 8.0*2000), threshold=1000)
+        pow_addr = int(out.splitlines()[0])
+        ops = self.get_by_bytecode('CALL_FUNCTION')
+        assert len(ops) == 2 # we get two loops, because of specialization
+        call_function = ops[0]
+        last_ops = [op.getopname() for op in call_function[-5:]]
+        assert last_ops == ['force_token',
+                            'setfield_gc',
+                            'call_may_force',
+                            'guard_not_forced',
+                            'guard_no_exception']
+        call = call_function[-3]
+        assert call.getarg(0).value == pow_addr
+        assert call.getarg(1).value == 2.0
+        assert call.getarg(2).value == 3.0
+
     # test_circular
 
 class AppTestJIT(PyPyCJITTests):
@@ -1155,6 +1189,17 @@
         cls.pypy_c = option.pypy_c
 
 
+def test_interface_residual_call():
+    space = gettestobjspace(usemodules=['pypyjit'])
+    space.appexec([], """():
+        import pypyjit
+        def f(*args, **kwds):
+            return (args, kwds)
+        res = pypyjit.residual_call(f, 4, x=6)
+        assert res == ((4,), {'x': 6})
+    """)
+
+
 def has_info(pypy_c, option):
     g = os.popen('"%s" --info' % pypy_c, 'r')
     lines = g.readlines()

Modified: pypy/branch/jit-unroll-loops/pypy/module/signal/interp_signal.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/module/signal/interp_signal.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/module/signal/interp_signal.py	Sat Oct 30 16:41:17 2010
@@ -1,7 +1,6 @@
 from pypy.interpreter.error import OperationError
 from pypy.interpreter.baseobjspace import W_Root, ObjSpace
 from pypy.interpreter.executioncontext import AsyncAction, AbstractActionFlag
-from pypy.rlib.rarithmetic import LONG_BIT, intmask
 import signal as cpy_signal
 from pypy.rpython.lltypesystem import lltype, rffi
 from pypy.translator.tool.cbuild import ExternalCompilationInfo
@@ -64,8 +63,8 @@
 class CheckSignalAction(AsyncAction):
     """An action that is automatically invoked when a signal is received."""
 
-    # The C-level signal handler sets the highest bit of pypysig_occurred:
-    bitmask = intmask(1 << (LONG_BIT-1))
+    # The C-level signal handler sets the bit 30 of pypysig_occurred:
+    bitmask = 1 << 30
 
     def __init__(self, space):
         AsyncAction.__init__(self, space)

Modified: pypy/branch/jit-unroll-loops/pypy/module/sys/__init__.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/module/sys/__init__.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/module/sys/__init__.py	Sat Oct 30 16:41:17 2010
@@ -7,13 +7,15 @@
     """Sys Builtin Module. """
     def __init__(self, space, w_name):
         """NOT_RPYTHON""" # because parent __init__ isn't
+        if space.config.translating:
+            del self.__class__.interpleveldefs['pypy_getudir']
         super(Module, self).__init__(space, w_name) 
         self.checkinterval = 100
         self.recursionlimit = 100
         self.w_default_encoder = None
         self.defaultencoding = "ascii"
         self.filesystemencoding = None
-        
+
     interpleveldefs = {
         '__name__'              : '(space.wrap("sys"))', 
         '__doc__'               : '(space.wrap("PyPy sys module"))', 
@@ -37,7 +39,7 @@
         'argv'                  : 'state.get(space).w_argv', 
         'warnoptions'           : 'state.get(space).w_warnoptions', 
         'builtin_module_names'  : 'state.w_None',
-        'pypy_getudir'          : 'state.pypy_getudir', 
+        'pypy_getudir'          : 'state.pypy_getudir',    # not translated
         'pypy_initial_path'     : 'state.pypy_initial_path',
 
         '_getframe'             : 'vm._getframe', 

Modified: pypy/branch/jit-unroll-loops/pypy/module/sys/state.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/module/sys/state.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/module/sys/state.py	Sat Oct 30 16:41:17 2010
@@ -95,15 +95,8 @@
 def getio(space):
     return space.fromcache(IOState)
 
-def _pypy_getudir(space):
-    """NOT_RPYTHON"""
+def pypy_getudir(space):
+    """NOT_RPYTHON
+    (should be removed from interpleveldefs before translation)"""
     from pypy.tool.udir import udir
     return space.wrap(str(udir))
-_pypy_getudir._annspecialcase_ = "override:ignore"
-
-# we need the indirection because this function will live in a dictionary with other 
-# RPYTHON functions and share call sites with them. Better it not be a special-case
-# directly. 
-def pypy_getudir(space):
-    return _pypy_getudir(space)
-

Modified: pypy/branch/jit-unroll-loops/pypy/module/test_lib_pypy/ctypes_tests/_ctypes_test.c
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/module/test_lib_pypy/ctypes_tests/_ctypes_test.c	(original)
+++ pypy/branch/jit-unroll-loops/pypy/module/test_lib_pypy/ctypes_tests/_ctypes_test.c	Sat Oct 30 16:41:17 2010
@@ -533,3 +533,7 @@
 	return inp;
 }
 
+int my_unused_function(void)
+{
+    return 42;
+}

Modified: pypy/branch/jit-unroll-loops/pypy/module/test_lib_pypy/ctypes_tests/test_funcptr.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/module/test_lib_pypy/ctypes_tests/test_funcptr.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/module/test_lib_pypy/ctypes_tests/test_funcptr.py	Sat Oct 30 16:41:17 2010
@@ -148,3 +148,7 @@
         # but it segfaults for some reason.
         if sys.platform == 'win32':
             assert f() == 0x12345678
+
+    def test_restype(self):
+        foo = lib.my_unused_function
+        assert foo.restype is c_int     # by default

Modified: pypy/branch/jit-unroll-loops/pypy/module/test_lib_pypy/ctypes_tests/test_functions.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/module/test_lib_pypy/ctypes_tests/test_functions.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/module/test_lib_pypy/ctypes_tests/test_functions.py	Sat Oct 30 16:41:17 2010
@@ -29,6 +29,7 @@
 class RECT(Structure):
     _fields_ = [("left", c_int), ("top", c_int),
                 ("right", c_int), ("bottom", c_int)]
+
 class TestFunctions(BaseCTypesTestChecker):
 
     def test_mro(self):
@@ -392,6 +393,18 @@
         result = f("abcd", ord("b"))
         assert result == "bcd"
 
+    def test_caching_bug_1(self):
+        # the same test as test_call_some_args, with two extra lines
+        # in the middle that trigger caching in f._ptr, which then
+        # makes the last two lines fail
+        f = dll.my_strchr
+        f.argtypes = [c_char_p, c_int]
+        f.restype = c_char_p
+        result = f("abcd", ord("b"))
+        assert result == "bcd"
+        result = f("abcd", ord("b"), 42)
+        assert result == "bcd"
+
     def test_sf1651235(self):
         py.test.skip("we are less strict in checking callback parameters")
         # see http://www.python.org/sf/1651235

Modified: pypy/branch/jit-unroll-loops/pypy/module/test_lib_pypy/ctypes_tests/test_keepalive.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/module/test_lib_pypy/ctypes_tests/test_keepalive.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/module/test_lib_pypy/ctypes_tests/test_keepalive.py	Sat Oct 30 16:41:17 2010
@@ -10,7 +10,7 @@
     """
     def test_array_of_pointers(self):
         # tests array item assignements & pointer.contents = ...
-        A = POINTER(c_int) * 24
+        A = POINTER(c_long) * 24
         a = A()
         l = c_long(2)
         p = pointer(l)

Modified: pypy/branch/jit-unroll-loops/pypy/module/thread/ll_thread.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/module/thread/ll_thread.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/module/thread/ll_thread.py	Sat Oct 30 16:41:17 2010
@@ -111,7 +111,7 @@
             c_thread_releaselock(self._lock)
 
     def __del__(self):
-        lltype.free(self._lock, flavor='raw')
+        lltype.free(self._lock, flavor='raw', track_allocation=False)
 
 # ____________________________________________________________
 #
@@ -128,10 +128,13 @@
 null_ll_lock = lltype.nullptr(TLOCKP.TO)
 
 def allocate_ll_lock():
-    ll_lock = lltype.malloc(TLOCKP.TO, flavor='raw')
+    # track_allocation=False here; be careful to lltype.free() it.  The
+    # reason it is set to False is that we get it from all app-level
+    # lock objects, as well as from the GIL, which exists at shutdown.
+    ll_lock = lltype.malloc(TLOCKP.TO, flavor='raw', track_allocation=False)
     res = c_thread_lock_init(ll_lock)
     if res == -1:
-        lltype.free(ll_lock, flavor='raw')
+        lltype.free(ll_lock, flavor='raw', track_allocation=False)
         raise error("out of resources")
     return ll_lock
 

Modified: pypy/branch/jit-unroll-loops/pypy/objspace/descroperation.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/objspace/descroperation.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/objspace/descroperation.py	Sat Oct 30 16:41:17 2010
@@ -51,7 +51,7 @@
     return space.is_w(w_typ1, w_typ2)
 
 
-class Object:
+class Object(object):
     def descr__getattribute__(space, w_obj, w_name):
         name = space.str_w(w_name)
         w_descr = space.lookup(w_obj, name)
@@ -64,9 +64,7 @@
                     w_type = space.type(w_obj)
                     return space.get_and_call_function(w_get, w_descr, w_obj,
                                                        w_type)
-            w_value = w_obj.getdictvalue_attr_is_in_class(space, name)
-        else:
-            w_value = w_obj.getdictvalue(space, name)
+        w_value = w_obj.getdictvalue(space, name)
         if w_value is not None:
             return w_value
         if w_descr is not None:
@@ -76,13 +74,11 @@
     def descr__setattr__(space, w_obj, w_name, w_value):
         name = space.str_w(w_name)
         w_descr = space.lookup(w_obj, name)
-        shadows_type = False
         if w_descr is not None:
             if space.is_data_descr(w_descr):
                 space.set(w_descr, w_obj, w_value)
                 return
-            shadows_type = True
-        if w_obj.setdictvalue(space, name, w_value, shadows_type):
+        if w_obj.setdictvalue(space, name, w_value):
             return
         raiseattrerror(space, w_obj, name, w_descr)
 
@@ -100,7 +96,7 @@
     def descr__init__(space, w_obj, __args__):
         pass
 
-class DescrOperation:
+class DescrOperation(object):
     _mixin_ = True
 
     def is_data_descr(space, w_obj):
@@ -545,7 +541,7 @@
 
 # what is the maximum value slices can get on CPython?
 # we need to stick to that value, because fake.py etc.
-class Temp:
+class Temp(object):
     def __getslice__(self, i, j):
         return j
 slice_max = Temp()[:]

Modified: pypy/branch/jit-unroll-loops/pypy/objspace/flow/flowcontext.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/objspace/flow/flowcontext.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/objspace/flow/flowcontext.py	Sat Oct 30 16:41:17 2010
@@ -460,7 +460,22 @@
         else:
             v = self.peekvalue(oparg - 1)
         self.space.call_method(v, 'append', w)
-    
+
+    # `with` statement
+
+    def SETUP_WITH(self, offsettoend, next_instr):
+        # A simpler version than the 'real' 2.7 one:
+        # directly call manager.__enter__(), don't use special lookup functions
+        # which don't make sense on the RPython type system.
+        from pypy.interpreter.pyopcode import WithBlock
+        w_manager = self.peekvalue()
+        w_exit = self.space.getattr(w_manager, self.space.wrap("__exit__"))
+        self.settopvalue(w_exit)
+        w_result = self.space.call_method(w_manager, "__enter__")
+        block = WithBlock(self, next_instr + offsettoend)
+        self.append_block(block)
+        self.pushvalue(w_result)
+
     # XXX Unimplemented 2.7 opcodes ----------------
 
     # Set literals, set comprehensions
@@ -476,12 +491,6 @@
     def MAP_ADD(self, oparg, next_instr):
         raise NotImplementedError("MAP_ADD")
 
-    # `with` statement
-
-    def SETUP_WITH(self, oparg, next_instr):
-        raise NotImplementedError("SETUP_WITH")
-
-    
     def make_arguments(self, nargs):
         return ArgumentsForTranslation(self.space, self.peekvalues(nargs))
     def argument_factory(self, *args):
@@ -493,3 +502,12 @@
             raise operr
         return pyframe.PyFrame.handle_operation_error(self, ec, operr,
                                                       *args, **kwds)
+
+    def call_contextmanager_exit_function(self, w_func, w_typ, w_val, w_tb):
+        if w_typ is not self.space.w_None:
+            # The annotator won't allow to merge exception types with None.
+            # Replace it with an object which will break translation when used
+            # (except maybe with 'exc_typ is None')
+            w_typ = self.space.wrap(self.space)
+        return self.space.call_function(w_func, w_typ, w_val, w_tb)
+

Modified: pypy/branch/jit-unroll-loops/pypy/objspace/flow/test/test_objspace.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/objspace/flow/test/test_objspace.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/objspace/flow/test/test_objspace.py	Sat Oct 30 16:41:17 2010
@@ -1,3 +1,4 @@
+from __future__ import with_statement
 import new
 import py
 from pypy.objspace.flow.model import Constant, Block, Link, Variable, traverse
@@ -828,6 +829,25 @@
         simplify_graph(graph)
         assert self.all_operations(graph) == {'getitem': 1}
 
+    def test_context_manager(self):
+        def f(c, x):
+            with x:
+                pass
+        graph = self.codetest(f)
+        # 2 method calls: x.__enter__() and x.__exit__(None, None, None)
+        assert self.all_operations(graph) == {'getattr': 2,
+                                              'simple_call': 2}
+        #
+        def g(): pass
+        def f(c, x):
+            with x:
+                g()
+        graph = self.codetest(f)
+        assert self.all_operations(graph) == {
+            'getattr': 2,     # __enter__ and __exit__
+            'simple_call': 4, # __enter__, g and 2 possible calls to __exit__
+            'is_true': 1}     # check the result of __exit__()
+
     def monkey_patch_code(self, code, stacksize, flags, codestring, names, varnames):
         c = code
         return new.code(c.co_argcount, c.co_nlocals, stacksize, flags,

Modified: pypy/branch/jit-unroll-loops/pypy/objspace/std/callmethod.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/objspace/std/callmethod.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/objspace/std/callmethod.py	Sat Oct 30 16:41:17 2010
@@ -44,7 +44,7 @@
         else:
             typ = type(w_descr)
             if typ is function.Function or typ is function.FunctionWithFixedCode:
-                w_value = w_obj.getdictvalue_attr_is_in_class(space, name)
+                w_value = w_obj.getdictvalue(space, name)
                 if w_value is None:
                     # fast method path: a function object in the class,
                     # nothing in the instance
@@ -103,7 +103,7 @@
         w_descr = space.lookup(w_obj, methname)
         typ = type(w_descr)
         if typ is function.Function or typ is function.FunctionWithFixedCode:
-            w_value = w_obj.getdictvalue_attr_is_in_class(space, methname)
+            w_value = w_obj.getdictvalue(space, methname)
             if w_value is None:
                 # fast method path: a function object in the class,
                 # nothing in the instance

Modified: pypy/branch/jit-unroll-loops/pypy/objspace/std/celldict.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/objspace/std/celldict.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/objspace/std/celldict.py	Sat Oct 30 16:41:17 2010
@@ -45,9 +45,9 @@
         if space.is_w(space.type(w_key), space.w_str):
             self.impl_setitem_str(self.space.str_w(w_key), w_value)
         else:
-            self._as_rdict().setitem(w_key, w_value)
+            self._as_rdict().impl_fallback_setitem(w_key, w_value)
 
-    def impl_setitem_str(self, name, w_value, shadows_type=True):
+    def impl_setitem_str(self, name, w_value):
         self.getcell(name, True).w_value = w_value
 
     def impl_delitem(self, w_key):
@@ -66,7 +66,7 @@
         elif _is_sane_hash(space, w_key_type):
             raise KeyError
         else:
-            self._as_rdict().delitem(w_key)
+            self._as_rdict().impl_fallback_delitem(w_key)
         
     def impl_length(self):
         # inefficient, but do we care?
@@ -85,7 +85,7 @@
         elif _is_sane_hash(space, w_lookup_type):
             return None
         else:
-            return self._as_rdict().getitem(w_lookup)
+            return self._as_rdict().impl_fallback_getitem(w_lookup)
 
     def impl_getitem_str(self, lookup):
         res = self.getcell(lookup, False)

Modified: pypy/branch/jit-unroll-loops/pypy/objspace/std/dictmultiobject.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/objspace/std/dictmultiobject.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/objspace/std/dictmultiobject.py	Sat Oct 30 16:41:17 2010
@@ -49,14 +49,6 @@
         elif space.config.objspace.std.withdictmeasurement:
             assert w_type is None
             return MeasuringDictImplementation(space)
-        elif space.config.objspace.std.withsharingdict and instance:
-            from pypy.objspace.std.sharingdict import SharedDictImplementation
-            assert w_type is None
-            return SharedDictImplementation(space)
-        elif (space.config.objspace.std.withshadowtracking and instance and
-                classofinstance is not None):
-            assert w_type is None
-            return ShadowDetectingDictImplementation(space, classofinstance)
         elif instance or strdict or module:
             assert w_type is None
             return StrDictImplementation(space)
@@ -102,17 +94,17 @@
         else:
             return None
 
-    # _________________________________________________________________ 
+    # _________________________________________________________________
     # implementation methods
     def impl_getitem(self, w_key):
         #return w_value or None
         raise NotImplementedError("abstract base class")
 
-    def impl_getitem_str(self, w_key):
+    def impl_getitem_str(self, key):
         #return w_value or None
         raise NotImplementedError("abstract base class")
 
-    def impl_setitem_str(self,  key, w_value, shadows_type=True):
+    def impl_setitem_str(self, key, w_value):
         raise NotImplementedError("abstract base class")
 
     def impl_setitem(self,  w_key, w_value):
@@ -120,7 +112,7 @@
 
     def impl_delitem(self, w_key):
         raise NotImplementedError("abstract base class")
- 
+
     def impl_length(self):
         raise NotImplementedError("abstract base class")
 
@@ -165,12 +157,15 @@
         key = OPTIMIZED_BUILTINS[i]
         return self.impl_getitem_str(key)
 
-    # this method will only be seen whan a certain config option is used
-    def impl_shadows_anything(self):
-        return True
-
-    def impl_set_shadows_anything(self):
-        pass
+    def impl_popitem(self):
+        # default implementation
+        space = self.space
+        iterator = self.impl_iter()
+        w_key, w_value = iterator.next()
+        if w_key is None:
+            raise KeyError
+        self.impl_delitem(w_key)
+        return w_key, w_value
 
     # _________________________________________________________________
     # fallback implementation methods
@@ -178,7 +173,7 @@
     def impl_fallback_setitem(self, w_key, w_value):
         self.r_dict_content[w_key] = w_value
 
-    def impl_fallback_setitem_str(self, key, w_value, shadows_type=True):
+    def impl_fallback_setitem_str(self, key, w_value):
         return self.impl_fallback_setitem(self.space.wrap(key), w_value)
 
     def impl_fallback_delitem(self, w_key):
@@ -211,18 +206,15 @@
         key = OPTIMIZED_BUILTINS[i]
         return self.impl_fallback_getitem_str(key)
 
-    def impl_fallback_shadows_anything(self):
-        return True
-
-    def impl_fallback_set_shadows_anything(self):
-        pass
+    def impl_fallback_popitem(self):
+        return self.r_dict_content.popitem()
 
 
 implementation_methods = [
     ("getitem", 1),
     ("getitem_str", 1),
     ("length", 0),
-    ("setitem_str", 3),
+    ("setitem_str", 2),
     ("setitem", 2),
     ("delitem", 1),
     ("iter", 0),
@@ -231,8 +223,7 @@
     ("keys", 0),
     ("clear", 0),
     ("get_builtin_indexed", 1),
-    ("shadows_anything", 0),
-    ("set_shadows_anything", 0),
+    ("popitem", 0),
 ]
 
 
@@ -310,9 +301,9 @@
         if space.is_w(space.type(w_key), space.w_str):
             self.impl_setitem_str(self.space.str_w(w_key), w_value)
         else:
-            self._as_rdict().setitem(w_key, w_value)
+            self._as_rdict().impl_fallback_setitem(w_key, w_value)
 
-    def impl_setitem_str(self, key, w_value, shadows_type=True):
+    def impl_setitem_str(self, key, w_value):
         self.content[key] = w_value
 
     def impl_delitem(self, w_key):
@@ -324,7 +315,7 @@
         elif _is_sane_hash(space, w_key_type):
             raise KeyError
         else:
-            self._as_rdict().delitem(w_key)
+            self._as_rdict().impl_fallback_delitem(w_key)
         
     def impl_length(self):
         return len(self.content)
@@ -344,7 +335,7 @@
         elif _is_sane_hash(space, w_lookup_type):
             return None
         else:
-            return self._as_rdict().getitem(w_key)
+            return self._as_rdict().impl_fallback_getitem(w_key)
 
     def impl_iter(self):
         return StrIteratorImplementation(self.space, self)
@@ -388,47 +379,12 @@
             return None, None
 
 
-class ShadowDetectingDictImplementation(StrDictImplementation):
-    def __init__(self, space, w_type):
-        StrDictImplementation.__init__(self, space)
-        self.w_type = w_type
-        self.original_version_tag = w_type.version_tag()
-        if self.original_version_tag is None:
-            self._shadows_anything = True
-        else:
-            self._shadows_anything = False
-
-    def impl_setitem_str(self, key, w_value, shadows_type=True):
-        if shadows_type:
-            self._shadows_anything = True
-        StrDictImplementation.impl_setitem_str(
-            self, key, w_value, shadows_type)
-
-    def impl_setitem(self, w_key, w_value):
-        space = self.space
-        if space.is_w(space.type(w_key), space.w_str):
-            if not self._shadows_anything:
-                w_obj = self.w_type.lookup(space.str_w(w_key))
-                if w_obj is not None:
-                    self._shadows_anything = True
-            StrDictImplementation.impl_setitem_str(
-                self, self.space.str_w(w_key), w_value, False)
-        else:
-            self._as_rdict().setitem(w_key, w_value)
-
-    def impl_shadows_anything(self):
-        return (self._shadows_anything or 
-                self.w_type.version_tag() is not self.original_version_tag)
-
-    def impl_set_shadows_anything(self):
-        self._shadows_anything = True
-
 class WaryDictImplementation(StrDictImplementation):
     def __init__(self, space):
         StrDictImplementation.__init__(self, space)
         self.shadowed = [None] * len(BUILTIN_TO_INDEX)
 
-    def impl_setitem_str(self, key, w_value, shadows_type=True):
+    def impl_setitem_str(self, key, w_value):
         i = BUILTIN_TO_INDEX.get(key, -1)
         if i != -1:
             self.shadowed[i] = w_value
@@ -446,7 +402,7 @@
         elif _is_sane_hash(space, w_key_type):
             raise KeyError
         else:
-            self._as_rdict().delitem(w_key)
+            self._as_rdict().impl_fallback_delitem(w_key)
 
     def impl_get_builtin_indexed(self, i):
         return self.shadowed[i]
@@ -558,7 +514,7 @@
         self.info.writes += 1
         self.content[w_key] = w_value
         self.info.maxcontents = max(self.info.maxcontents, len(self.content))
-    def impl_setitem_str(self, key, w_value, shadows_type=True):
+    def impl_setitem_str(self, key, w_value):
         self.info.setitem_strs += 1
         self.impl_setitem(self.space.wrap(key), w_value)
     def impl_delitem(self, w_key):
@@ -641,30 +597,50 @@
 init_signature = Signature(['seq_or_map'], None, 'kwargs')
 init_defaults = [None]
 
-def init__DictMulti(space, w_dict, __args__):
-    w_src, w_kwds = __args__.parse_obj(
-            None, 'dict',
-            init_signature, # signature
-            init_defaults)                           # default argument
-    if w_src is None:
-        pass
-    elif space.findattr(w_src, space.wrap("keys")) is None:
-        list_of_w_pairs = space.listview(w_src)
-        for w_pair in list_of_w_pairs:
+def update1(space, w_dict, w_data):
+    if space.findattr(w_data, space.wrap("keys")) is None:
+        # no 'keys' method, so we assume it is a sequence of pairs
+        for w_pair in space.listview(w_data):
             pair = space.fixedview(w_pair)
-            if len(pair)!=2:
+            if len(pair) != 2:
                 raise OperationError(space.w_ValueError,
-                             space.wrap("dict() takes a sequence of pairs"))
-            w_k, w_v = pair
-            w_dict.setitem(w_k, w_v)
+                             space.wrap("sequence of pairs expected"))
+            w_key, w_value = pair
+            w_dict.setitem(w_key, w_value)
     else:
-        if space.is_true(w_src):
-            from pypy.objspace.std.dicttype import update1
-            update1(space, w_dict, w_src)
+        if isinstance(w_data, W_DictMultiObject):    # optimization case only
+            update1_dict_dict(space, w_dict, w_data)
+        else:
+            # general case -- "for k in o.keys(): dict.__setitem__(d, k, o[k])"
+            w_keys = space.call_method(w_data, "keys")
+            for w_key in space.listview(w_keys):
+                w_value = space.getitem(w_data, w_key)
+                w_dict.setitem(w_key, w_value)
+
+def update1_dict_dict(space, w_dict, w_data):
+    iterator = w_data.iter()
+    while 1:
+        w_key, w_value = iterator.next()
+        if w_key is None:
+            break
+        w_dict.setitem(w_key, w_value)
+
+def init_or_update(space, w_dict, __args__, funcname):
+    w_src, w_kwds = __args__.parse_obj(
+            None, funcname,
+            init_signature, # signature
+            init_defaults)  # default argument
+    if w_src is not None:
+        update1(space, w_dict, w_src)
     if space.is_true(w_kwds):
-        from pypy.objspace.std.dicttype import update1
         update1(space, w_dict, w_kwds)
 
+def init__DictMulti(space, w_dict, __args__):
+    init_or_update(space, w_dict, __args__, 'dict')
+
+def dict_update__DictMulti(space, w_dict, __args__):
+    init_or_update(space, w_dict, __args__, 'dict.update')
+
 def getitem__DictMulti_ANY(space, w_dict, w_key):
     w_value = w_dict.getitem(w_key)
     if w_value is not None:
@@ -758,9 +734,8 @@
     return w_res
 
 def dict_copy__DictMulti(space, w_self):
-    from pypy.objspace.std.dicttype import update1
     w_new = W_DictMultiObject.allocate_and_init_instance(space)
-    update1(space, w_new, w_self)
+    update1_dict_dict(space, w_new, w_self)
     return w_new
 
 def dict_items__DictMulti(space, w_self):
@@ -791,6 +766,15 @@
     else:
         return w_default
 
+def dict_setdefault__DictMulti_ANY_ANY(space, w_dict, w_key, w_default):
+    # XXX should be more efficient, with only one dict lookup
+    w_value = w_dict.getitem(w_key)
+    if w_value is not None:
+        return w_value
+    else:
+        w_dict.setitem(w_key, w_default)
+        return w_default
+
 def dict_pop__DictMulti_ANY(space, w_dict, w_key, w_defaults):
     defaults = space.listview(w_defaults)
     len_defaults = len(defaults)
@@ -808,6 +792,14 @@
         w_dict.delitem(w_key)
         return w_item
 
+def dict_popitem__DictMulti(space, w_dict):
+    try:
+        w_key, w_value = w_dict.popitem()
+    except KeyError:
+        raise OperationError(space.w_KeyError,
+                             space.wrap("popitem(): dictionary is empty"))
+    return space.newtuple([w_key, w_value])
+
 app = gateway.applevel('''
     def dictrepr(currently_in_repr, d):
         # Now we only handle one implementation of dicts, this one.

Modified: pypy/branch/jit-unroll-loops/pypy/objspace/std/dicttype.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/objspace/std/dicttype.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/objspace/std/dicttype.py	Sat Oct 30 16:41:17 2010
@@ -53,106 +53,21 @@
 # This can return when multimethods have been fixed
 #dict_str        = StdObjSpace.str
 
-# default application-level implementations for some operations
-# most of these (notably not popitem and update*) are overwritten
-# in dictmultiobject
-# gateway is imported in the stdtypedef module
-app = gateway.applevel('''
-
-    # in the following functions we use dict.__setitem__ instead of
-    # d[k]=...  because when a subclass of dict override __setitem__,
-    # CPython does not call it when doing builtin operations.  The
-    # same for other operations.
-
-    def update1(d, o):
-        if hasattr(o, 'keys'):
-            for k in o.keys():
-                dict.__setitem__(d, k, o[k])
-        else:
-            for k,v in o:
-                dict.__setitem__(d, k, v)
-
-    def update(d, *args, **kwargs):
-        len_args = len(args)
-        if len_args == 1:
-            update1(d, args[0])
-        elif len_args > 1:
-            raise TypeError("update takes at most 1 (non-keyword) argument")
-        if kwargs:
-            update1(d, kwargs)
-
-    def popitem(d):
-        for k in dict.iterkeys(d):
-            break
-        else:
-            raise KeyError("popitem(): dictionary is empty")
-        v = dict.__getitem__(d, k)
-        dict.__delitem__(d, k)
-        return k, v
-
-    def get(d, k, v=None):
-        if k in d:
-            return dict.__getitem__(d, k)
-        else:
-            return v
-
-    def setdefault(d, k, v=None):
-        if k in d:
-            return dict.__getitem__(d, k)
-        else:
-            dict.__setitem__(d, k, v)
-            return v
-
-    def pop(d, k, defaults):     # XXX defaults is actually *defaults
-        if len(defaults) > 1:
-            raise TypeError, "pop expected at most 2 arguments, got %d" % (
-                1 + len(defaults))
-        try:
-            v = dict.__getitem__(d, k)
-            dict.__delitem__(d, k)
-        except KeyError, e:
-            if defaults:
-                return defaults[0]
-            else:
-                raise e
-        return v
-
-    def iteritems(d):
-        return iter(dict.items(d))
-
-    def iterkeys(d):
-        return iter(dict.keys(d))
-
-    def itervalues(d):
-        return iter(dict.values(d))
-''', filename=__file__)
-
-dict_update__ANY             = app.interphook("update")
-dict_popitem__ANY            = app.interphook("popitem")
-dict_get__ANY_ANY_ANY        = app.interphook("get")
-dict_setdefault__ANY_ANY_ANY = app.interphook("setdefault")
-dict_pop__ANY_ANY            = app.interphook("pop")
-dict_iteritems__ANY          = app.interphook("iteritems")
-dict_iterkeys__ANY           = app.interphook("iterkeys")
-dict_itervalues__ANY         = app.interphook("itervalues")
-update1                      = app.interphook("update1")
-
 register_all(vars(), globals())
 
 @gateway.unwrap_spec(ObjSpace, W_Root, W_Root, W_Root)
 def descr_fromkeys(space, w_type, w_keys, w_fill=None):
+    from pypy.objspace.std.dictmultiobject import W_DictMultiObject
     if w_fill is None:
         w_fill = space.w_None
-    w_dict = space.call_function(w_type)
-    w_iter = space.iter(w_keys)
-    while True:
-        try:
-            w_key = space.next(w_iter)
-        except OperationError, e:
-            if not e.match(space, space.w_StopIteration):
-                raise
-            break
-        space.setitem(w_dict, w_key, w_fill)
+    if w_type is space.w_dict:
+        w_dict = W_DictMultiObject.allocate_and_init_instance(space, w_type)
+        for w_key in space.listview(w_keys):
+            w_dict.setitem(w_key, w_fill)
+    else:
+        w_dict = space.call_function(w_type)
+        for w_key in space.listview(w_keys):
+            space.setitem(w_dict, w_key, w_fill)
     return w_dict
 
 

Modified: pypy/branch/jit-unroll-loops/pypy/objspace/std/fake.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/objspace/std/fake.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/objspace/std/fake.py	Sat Oct 30 16:41:17 2010
@@ -21,7 +21,6 @@
     #debug_print("faking obj %s" % x)
     ft = fake_type(type(x))
     return ft(space, x)
-fake_object._annspecialcase_ = "override:fake_object"
 
 import sys
 
@@ -47,7 +46,6 @@
         w_exc = space.wrap(exc)
         w_value = space.wrap(value)
     raise OperationError, OperationError(w_exc, w_value), tb
-wrap_exception._annspecialcase_ = "override:ignore"
 
 def fake_type(cpy_type):
     assert type(cpy_type) is type

Modified: pypy/branch/jit-unroll-loops/pypy/objspace/std/frozensettype.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/objspace/std/frozensettype.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/objspace/std/frozensettype.py	Sat Oct 30 16:41:17 2010
@@ -39,13 +39,13 @@
 def descr__frozenset__new__(space, w_frozensettype,
                             w_iterable=gateway.NoneNotWrapped):
     from pypy.objspace.std.setobject import W_FrozensetObject
-    from pypy.objspace.std.setobject import _is_frozenset_exact
+    from pypy.objspace.std.setobject import make_setdata_from_w_iterable
     if (space.is_w(w_frozensettype, space.w_frozenset) and
-        _is_frozenset_exact(w_iterable)):
+        w_iterable is not None and type(w_iterable) is W_FrozensetObject):
         return w_iterable
     w_obj = space.allocate_instance(W_FrozensetObject, w_frozensettype)
-    W_FrozensetObject.__init__(w_obj, space, None)
-
+    data = make_setdata_from_w_iterable(space, w_iterable)
+    W_FrozensetObject.__init__(w_obj, space, data)
     return w_obj
 
 frozenset_typedef = StdTypeDef("frozenset",

Modified: pypy/branch/jit-unroll-loops/pypy/objspace/std/inttype.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/objspace/std/inttype.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/objspace/std/inttype.py	Sat Oct 30 16:41:17 2010
@@ -1,7 +1,7 @@
 from pypy.interpreter import gateway
 from pypy.interpreter.error import OperationError
 from pypy.objspace.std.stdtypedef import StdTypeDef
-from pypy.objspace.std.strutil import (string_to_int, string_to_w_long,
+from pypy.objspace.std.strutil import (string_to_int, string_to_bigint,
                                        ParseStringError,
                                        ParseStringOverflowError)
 from pypy.rlib.rarithmetic import r_uint
@@ -45,10 +45,12 @@
 def retry_to_w_long(space, parser, base=0):
     parser.rewind()
     try:
-        return string_to_w_long(space, None, base=base, parser=parser)
+        bigint = string_to_bigint(None, base=base, parser=parser)
     except ParseStringError, e:
         raise OperationError(space.w_ValueError,
                              space.wrap(e.msg))
+    from pypy.objspace.std.longobject import W_LongObject
+    return W_LongObject(bigint)
 
 def descr__new__(space, w_inttype, w_x=0, w_base=gateway.NoneNotWrapped):
     from pypy.objspace.std.intobject import W_IntObject

Modified: pypy/branch/jit-unroll-loops/pypy/objspace/std/listobject.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/objspace/std/listobject.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/objspace/std/listobject.py	Sat Oct 30 16:41:17 2010
@@ -283,7 +283,7 @@
         elif start >= 0:
             del items[start:start+delta]
         else:
-            assert delta==0
+            assert delta==0   # start<0 is only possible with slicelength==0
     elif len2 != slicelength:  # No resize for extended slices
         raise operationerrfmt(space.w_ValueError, "attempt to "
               "assign sequence of size %d to extended slice of size %d",

Modified: pypy/branch/jit-unroll-loops/pypy/objspace/std/longtype.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/objspace/std/longtype.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/objspace/std/longtype.py	Sat Oct 30 16:41:17 2010
@@ -1,7 +1,7 @@
 from pypy.interpreter.error import OperationError
 from pypy.interpreter import gateway
 from pypy.objspace.std.stdtypedef import StdTypeDef
-from pypy.objspace.std.strutil import string_to_w_long, ParseStringError
+from pypy.objspace.std.strutil import string_to_bigint, ParseStringError
 
 def descr__new__(space, w_longtype, w_x=0, w_base=gateway.NoneNotWrapped):
     from pypy.objspace.std.longobject import W_LongObject
@@ -9,10 +9,10 @@
     if w_base is None:
         # check for easy cases
         if type(w_value) is W_LongObject:
-            pass
+            bigint = w_value.num
         elif space.is_true(space.isinstance(w_value, space.w_str)):
             try:
-                w_value = string_to_w_long(space, space.str_w(w_value))
+                bigint = string_to_bigint(space.str_w(w_value))
             except ParseStringError, e:
                 raise OperationError(space.w_ValueError,
                                      space.wrap(e.msg))
@@ -22,7 +22,7 @@
                     from pypy.objspace.std.ropeunicodeobject import unicode_to_decimal_w
                 else:
                     from pypy.objspace.std.unicodeobject import unicode_to_decimal_w
-                w_value = string_to_w_long(space, unicode_to_decimal_w(space, w_value))
+                bigint = string_to_bigint(unicode_to_decimal_w(space, w_value))
             except ParseStringError, e:
                 raise OperationError(space.w_ValueError,
                                      space.wrap(e.msg))
@@ -35,10 +35,11 @@
             if space.is_true(space.isinstance(w_obj, space.w_long)):
                 assert isinstance(w_obj, W_LongObject)  # XXX this could fail!
                 # XXX find a way to do that even if w_obj is not a W_LongObject
-                w_value = w_obj
+                bigint = w_obj.num
             elif space.is_true(space.isinstance(w_obj, space.w_int)):
+                from pypy.rlib.rbigint import rbigint
                 intval = space.int_w(w_obj)
-                w_value = W_LongObject.fromint(space, intval)
+                bigint = rbigint.fromint(intval)
             else:
                 raise OperationError(space.w_ValueError,
                                     space.wrap("value can't be converted to long"))
@@ -56,13 +57,13 @@
                                      space.wrap("long() can't convert non-string "
                                                 "with explicit base"))
         try:
-            w_value = string_to_w_long(space, s, base)
+            bigint = string_to_bigint(s, base)
         except ParseStringError, e:
             raise OperationError(space.w_ValueError,
                                  space.wrap(e.msg))
 
     w_obj = space.allocate_instance(W_LongObject, w_longtype)
-    W_LongObject.__init__(w_obj, w_value.num)
+    W_LongObject.__init__(w_obj, bigint)
     return w_obj
 
 # ____________________________________________________________

Modified: pypy/branch/jit-unroll-loops/pypy/objspace/std/model.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/objspace/std/model.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/objspace/std/model.py	Sat Oct 30 16:41:17 2010
@@ -18,6 +18,7 @@
     "withsmallint"   : ["smallintobject.W_SmallIntObject"],
     "withstrslice"   : ["strsliceobject.W_StringSliceObject"],
     "withstrjoin"    : ["strjoinobject.W_StringJoinObject"],
+    "withstrbuf"     : ["strbufobject.W_StringBufferObject"],
     "withrope"       : ["ropeobject.W_RopeObject",
                         "ropeobject.W_RopeIterObject"],
     "withropeunicode": ["ropeunicodeobject.W_RopeUnicodeObject",
@@ -75,6 +76,7 @@
         from pypy.objspace.std import ropeunicodeobject
         from pypy.objspace.std import strsliceobject
         from pypy.objspace.std import strjoinobject
+        from pypy.objspace.std import strbufobject
         from pypy.objspace.std import typeobject
         from pypy.objspace.std import sliceobject
         from pypy.objspace.std import longobject
@@ -222,6 +224,13 @@
                 (unicodeobject.W_UnicodeObject,
                                        strjoinobject.delegate_join2unicode)
                 ]
+        elif config.objspace.std.withstrbuf:
+            self.typeorder[strbufobject.W_StringBufferObject] += [
+                (stringobject.W_StringObject,
+                                       strbufobject.delegate_buf2str),
+                (unicodeobject.W_UnicodeObject,
+                                       strbufobject.delegate_buf2unicode)
+                ]
         if config.objspace.std.withrangelist:
             self.typeorder[rangeobject.W_RangeListObject] += [
                 (listobject.W_ListObject,

Modified: pypy/branch/jit-unroll-loops/pypy/objspace/std/objspace.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/objspace/std/objspace.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/objspace/std/objspace.py	Sat Oct 30 16:41:17 2010
@@ -23,6 +23,7 @@
 from pypy.objspace.std.listobject import W_ListObject
 from pypy.objspace.std.longobject import W_LongObject
 from pypy.objspace.std.noneobject import W_NoneObject
+from pypy.objspace.std.objectobject import W_ObjectObject
 from pypy.objspace.std.ropeobject import W_RopeObject
 from pypy.objspace.std.iterobject import W_SeqIterObject
 from pypy.objspace.std.setobject import W_SetObject, W_FrozensetObject
@@ -242,7 +243,6 @@
             w_result = getattr(self, 'w_' + x.__name__)
             return w_result
         return None
-    wrap_exception_cls._annspecialcase_ = "override:wrap_exception_cls"
 
     def unwrap(self, w_obj):
         if isinstance(w_obj, Wrappable):
@@ -318,9 +318,14 @@
             w_subtype = w_type.check_user_subclass(w_subtype)
             if cls.typedef.applevel_subclasses_base is not None:
                 cls = cls.typedef.applevel_subclasses_base
-            subcls = get_unique_interplevel_subclass(
-                    self.config, cls, w_subtype.hasdict, w_subtype.nslots != 0,
-                    w_subtype.needsdel, w_subtype.weakrefable)
+            if (self.config.objspace.std.withmapdict and cls is W_ObjectObject
+                    and not w_subtype.needsdel):
+                from pypy.objspace.std.mapdict import get_subclass_of_correct_size
+                subcls = get_subclass_of_correct_size(self, cls, w_subtype)
+            else:
+                subcls = get_unique_interplevel_subclass(
+                        self.config, cls, w_subtype.hasdict, w_subtype.nslots != 0,
+                        w_subtype.needsdel, w_subtype.weakrefable)
             instance = instantiate(subcls)
             assert isinstance(instance, cls)
             instance.user_setup(self, w_subtype)
@@ -432,7 +437,7 @@
             if is_data:
                 w_get = self.lookup(w_descr, "__get__")
             if w_get is None:
-                w_value = w_obj.getdictvalue_attr_is_in_class(self, name)
+                w_value = w_obj.getdictvalue(self, name)
                 if w_value is not None:
                     return w_value
                 if not is_data:
@@ -484,14 +489,12 @@
             return w_obj.getitem(w_key)
         return ObjSpace.finditem(self, w_obj, w_key)
 
-    def setitem_str(self, w_obj, key, w_value, shadows_type=True):
+    def setitem_str(self, w_obj, key, w_value):
         """ Same as setitem, but takes string instead of any wrapped object
-
-        XXX what shadows_type means???
         """
         if (isinstance(w_obj, W_DictMultiObject) and
                 not w_obj.user_overridden_class):
-            w_obj.setitem_str(key, w_value, shadows_type)
+            w_obj.setitem_str(key, w_value)
         else:
             self.setitem(w_obj, self.wrap(key), w_value)
 

Modified: pypy/branch/jit-unroll-loops/pypy/objspace/std/proxyobject.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/objspace/std/proxyobject.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/objspace/std/proxyobject.py	Sat Oct 30 16:41:17 2010
@@ -43,7 +43,7 @@
                     raise
                 return None
         
-        def setdictvalue(self, space, attr, w_value, shadows_type=True):
+        def setdictvalue(self, space, attr, w_value):
             try:
                 space.call_function(self.w_controller, space.wrap('__setattr__'),
                    space.wrap(attr), w_value)

Modified: pypy/branch/jit-unroll-loops/pypy/objspace/std/setobject.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/objspace/std/setobject.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/objspace/std/setobject.py	Sat Oct 30 16:41:17 2010
@@ -21,11 +21,10 @@
         return False
 
 
-    def __init__(w_self, space, setdata=None):
-        if setdata is None:
-            w_self.setdata = r_dict(space.eq_w, space.hash_w)
-        else:
-            w_self.setdata = setdata.copy()
+    def __init__(w_self, space, setdata):
+        """Initialize the set by taking ownership of 'setdata'."""
+        assert setdata is not None
+        w_self.setdata = setdata
 
     def __repr__(w_self):
         """representation for debugging purposes"""
@@ -33,6 +32,7 @@
         return "<%s(%s)>" % (w_self.__class__.__name__, ', '.join(reprlist))
 
     def _newobj(w_self, space, rdict_w=None):
+        """Make a new set or frozenset by taking ownership of 'rdict_w'."""
         #return space.call(space.type(w_self),W_SetIterObject(rdict_w))
         objtype = type(w_self)
         if objtype is W_SetObject:
@@ -55,10 +55,7 @@
 
 class W_FrozensetObject(W_BaseSetObject):
     from pypy.objspace.std.frozensettype import frozenset_typedef as typedef
-
-    def __init__(w_self, space, setdata):
-        W_BaseSetObject.__init__(w_self, space, setdata)
-        w_self.hash = -1
+    hash = 0
 
 registerimplementation(W_BaseSetObject)
 registerimplementation(W_SetObject)
@@ -109,8 +106,14 @@
 
 # some helper functions
 
+def newset(space):
+    return r_dict(space.eq_w, space.hash_w)
+
 def make_setdata_from_w_iterable(space, w_iterable=None):
-    data = r_dict(space.eq_w, space.hash_w)
+    """Return a new r_dict with the content of w_iterable."""
+    if isinstance(w_iterable, W_BaseSetObject):
+        return w_iterable.setdata.copy()
+    data = newset(space)
     if w_iterable is not None:
         for w_item in space.listview(w_iterable):
             data[w_item] = None
@@ -119,7 +122,7 @@
 def _initialize_set(space, w_obj, w_iterable=None):
     w_obj.setdata.clear()
     if w_iterable is not None:
-        w_obj.setdata.update(make_setdata_from_w_iterable(space, w_iterable))
+        w_obj.setdata = make_setdata_from_w_iterable(space, w_iterable)
 
 def _convert_set_to_frozenset(space, w_obj):
     if space.is_true(space.isinstance(w_obj, space.w_set)):
@@ -130,12 +133,6 @@
 
 # helper functions for set operation on dicts
 
-def _is_frozenset_exact(w_obj):
-    if (w_obj is not None) and (type(w_obj) is W_FrozensetObject):
-        return True
-    else:
-        return False
-
 def _is_eq(ld, rd):
     if len(ld) != len(rd):
         return False
@@ -144,66 +141,41 @@
             return False
     return True
 
-def _union_dict(ldict, rdict, isupdate):
-    if isupdate:
-        ld = ldict
-    else:
-        ld = ldict.copy()
-    ld.update(rdict)
-    return ld, rdict
-
-def _difference_dict(ldict, rdict, isupdate):
-    if isupdate:
-        ld = ldict
-    else:
-        ld = ldict.copy()
-    del_list_w = []
+def _difference_dict(space, ld, rd):
+    result = newset(space)
     for w_key in ld:
-        if w_key in rdict:
-            del_list_w.append(w_key)
-    for w_key in del_list_w:
-        del ld[w_key]
-
-    return ld, rdict
-
-def _intersection_dict(ldict, rdict, isupdate):
-    if isupdate:
-        ld = ldict
-    else:
-        ld = ldict.copy()
-    del_list_w = []
-    for w_key in ld:
-        if w_key not in rdict:
-            del_list_w.append(w_key)
-
-    for w_key in del_list_w:
-        del ld[w_key]
-
-    return ld, rdict
-
+        if w_key not in rd:
+            result[w_key] = None
+    return result
 
-def _symmetric_difference_dict(ldict, rdict, isupdate):
-    if isupdate:
-        ld = ldict
+def _difference_dict_update(space, ld, rd):
+    if ld is rd:
+        ld.clear()     # for the case 'a.difference_update(a)'
     else:
-        ld = ldict.copy()
-    del_list_w = []
-    add_list_w = []
+        for w_key in rd:
+            try:
+                del ld[w_key]
+            except KeyError:
+                pass
+
+def _intersection_dict(space, ld, rd):
+    result = newset(space)
+    if len(ld) > len(rd):
+        ld, rd = rd, ld     # loop over the smaller dict
     for w_key in ld:
-        if w_key in rdict:
-            del_list_w.append(w_key)
+        if w_key in rd:
+            result[w_key] = None
+    return result
 
-    for w_key in rdict:
+def _symmetric_difference_dict(space, ld, rd):
+    result = newset(space)
+    for w_key in ld:
+        if w_key not in rd:
+            result[w_key] = None
+    for w_key in rd:
         if w_key not in ld:
-            add_list_w.append(w_key)
-
-    for w_key in del_list_w:
-        del ld[w_key]
-
-    for w_key in add_list_w:
-        ld[w_key] = None
-
-    return ld, rdict
+            result[w_key] = None
+    return result
 
 def _issubset_dict(ldict, rdict):
     if len(ldict) > len(rdict):
@@ -220,14 +192,13 @@
 def set_update__Set_BaseSet(space, w_left, w_other):
     # optimization only (the general case works too)
     ld, rd = w_left.setdata, w_other.setdata
-    new_ld, rd = _union_dict(ld, rd, True)
-    return space.w_None
+    ld.update(rd)
 
 def set_update__Set_ANY(space, w_left, w_other):
     """Update a set with the union of itself and another."""
-    ld, rd = w_left.setdata, make_setdata_from_w_iterable(space, w_other)
-    new_ld, rd = _union_dict(ld, rd, True)
-    return space.w_None
+    ld = w_left.setdata
+    for w_item in space.listview(w_other):
+        ld[w_item] = None
 
 def inplace_or__Set_Set(space, w_left, w_other):
     set_update__Set_BaseSet(space, w_left, w_other)
@@ -241,25 +212,23 @@
     This has no effect if the element is already present.
     """
     w_left.setdata[w_other] = None
-    return space.w_None
 
 def set_copy__Set(space, w_set):
-    return w_set._newobj(space,w_set.setdata)
+    return w_set._newobj(space, w_set.setdata.copy())
 
 def frozenset_copy__Frozenset(space, w_left):
-    if _is_frozenset_exact(w_left):
+    if type(w_left) is W_FrozensetObject:
         return w_left
     else:
-        return set_copy__Set(space,w_left)
+        return set_copy__Set(space, w_left)
 
 def set_clear__Set(space, w_left):
     w_left.setdata.clear()
-    return space.w_None
 
 def set_difference__Set_Set(space, w_left, w_other):
     # optimization only (the general case works too)
     ld, rd = w_left.setdata, w_other.setdata
-    new_ld, rd = _difference_dict(ld, rd, False)
+    new_ld = _difference_dict(space, ld, rd)
     return w_left._newobj(space, new_ld)
 
 set_difference__Set_Frozenset = set_difference__Set_Set
@@ -272,7 +241,7 @@
 
 def set_difference__Set_ANY(space, w_left, w_other):
     ld, rd = w_left.setdata, make_setdata_from_w_iterable(space, w_other)
-    new_ld, rd = _difference_dict(ld, rd, False)
+    new_ld = _difference_dict(space, ld, rd)
     return w_left._newobj(space, new_ld)
 
 frozenset_difference__Frozenset_ANY = set_difference__Set_ANY
@@ -281,15 +250,17 @@
 def set_difference_update__Set_Set(space, w_left, w_other):
     # optimization only (the general case works too)
     ld, rd = w_left.setdata, w_other.setdata
-    new_ld, rd = _difference_dict(ld, rd, True)
-    return space.w_None
+    _difference_dict_update(space, ld, rd)
 
 set_difference_update__Set_Frozenset = set_difference_update__Set_Set
 
 def set_difference_update__Set_ANY(space, w_left, w_other):
-    ld, rd = w_left.setdata, make_setdata_from_w_iterable(space, w_other)
-    new_ld, rd = _difference_dict(ld, rd, True)
-    return space.w_None
+    ld = w_left.setdata
+    for w_key in space.listview(w_other):
+        try:
+            del ld[w_key]
+        except KeyError:
+            pass
 
 def inplace_sub__Set_Set(space, w_left, w_other):
     set_difference_update__Set_Set(space, w_left, w_other)
@@ -467,7 +438,7 @@
 
 def hash__Frozenset(space, w_set):
     multi = r_uint(1822399083) + r_uint(1822399083) + 1
-    if w_set.hash != -1:
+    if w_set.hash != 0:
         return space.wrap(w_set.hash)
     hash = 1927868237
     hash *= (len(w_set.setdata) + 1)
@@ -476,7 +447,7 @@
         value = ((h ^ (h << 16) ^ 89869747)  * multi)
         hash = intmask(hash ^ value)
     hash = hash * 69069 + 907133923
-    if hash == -1:
+    if hash == 0:
         hash = 590923713
     hash = intmask(hash)
     w_set.hash = hash
@@ -484,29 +455,31 @@
     return space.wrap(hash)
 
 def set_pop__Set(space, w_left):
-    if len(w_left.setdata) == 0:
+    for w_key in w_left.setdata:
+        break
+    else:
         raise OperationError(space.w_KeyError,
                                 space.wrap('pop from an empty set'))
-    w_keys = w_left.setdata.keys()
-    w_value = w_keys[0]
-    del w_left.setdata[w_value]
-
-    return w_value
+    del w_left.setdata[w_key]
+    return w_key
 
 def set_intersection__Set_Set(space, w_left, w_other):
     # optimization only (the general case works too)
     ld, rd = w_left.setdata, w_other.setdata
-    new_ld, rd = _intersection_dict(ld, rd, False)
-    return w_left._newobj(space,new_ld)
+    new_ld = _intersection_dict(space, ld, rd)
+    return w_left._newobj(space, new_ld)
 
 set_intersection__Set_Frozenset = set_intersection__Set_Set
 set_intersection__Frozenset_Frozenset = set_intersection__Set_Set
 set_intersection__Frozenset_Set = set_intersection__Set_Set
 
 def set_intersection__Set_ANY(space, w_left, w_other):
-    ld, rd = w_left.setdata, make_setdata_from_w_iterable(space, w_other)
-    new_ld, rd = _intersection_dict(ld, rd, False)
-    return w_left._newobj(space,new_ld)
+    result = newset(space)
+    ld = w_left.setdata
+    for w_key in space.listview(w_other):
+        if w_key in ld:
+            result[w_key] = None
+    return w_left._newobj(space, result)
 
 frozenset_intersection__Frozenset_ANY = set_intersection__Set_ANY
 
@@ -518,15 +491,18 @@
 def set_intersection_update__Set_Set(space, w_left, w_other):
     # optimization only (the general case works too)
     ld, rd = w_left.setdata, w_other.setdata
-    new_ld, rd = _intersection_dict(ld, rd, True)
-    return space.w_None
+    new_ld = _intersection_dict(space, ld, rd)
+    w_left.setdata = new_ld
 
 set_intersection_update__Set_Frozenset = set_intersection_update__Set_Set
 
 def set_intersection_update__Set_ANY(space, w_left, w_other):
-    ld, rd = w_left.setdata, make_setdata_from_w_iterable(space, w_other)
-    new_ld, rd = _intersection_dict(ld, rd, True)
-    return space.w_None
+    result = newset(space)
+    ld = w_left.setdata
+    for w_key in space.listview(w_other):
+        if w_key in ld:
+            result[w_key] = None
+    w_left.setdata = result
 
 def inplace_and__Set_Set(space, w_left, w_other):
     set_intersection_update__Set_Set(space, w_left, w_other)
@@ -537,7 +513,7 @@
 def set_symmetric_difference__Set_Set(space, w_left, w_other):
     # optimization only (the general case works too)
     ld, rd = w_left.setdata, w_other.setdata
-    new_ld, rd = _symmetric_difference_dict(ld, rd, False)
+    new_ld = _symmetric_difference_dict(space, ld, rd)
     return w_left._newobj(space, new_ld)
 
 set_symmetric_difference__Set_Frozenset = set_symmetric_difference__Set_Set
@@ -553,7 +529,7 @@
 
 def set_symmetric_difference__Set_ANY(space, w_left, w_other):
     ld, rd = w_left.setdata, make_setdata_from_w_iterable(space, w_other)
-    new_ld, rd = _symmetric_difference_dict(ld, rd, False)
+    new_ld = _symmetric_difference_dict(space, ld, rd)
     return w_left._newobj(space, new_ld)
 
 frozenset_symmetric_difference__Frozenset_ANY = \
@@ -562,16 +538,16 @@
 def set_symmetric_difference_update__Set_Set(space, w_left, w_other):
     # optimization only (the general case works too)
     ld, rd = w_left.setdata, w_other.setdata
-    new_ld, rd = _symmetric_difference_dict(ld, rd, True)
-    return space.w_None
+    new_ld = _symmetric_difference_dict(space, ld, rd)
+    w_left.setdata = new_ld
 
 set_symmetric_difference_update__Set_Frozenset = \
                                     set_symmetric_difference_update__Set_Set
 
 def set_symmetric_difference_update__Set_ANY(space, w_left, w_other):
     ld, rd = w_left.setdata, make_setdata_from_w_iterable(space, w_other)
-    new_ld, rd = _symmetric_difference_dict(ld, rd, True)
-    return space.w_None
+    new_ld = _symmetric_difference_dict(space, ld, rd)
+    w_left.setdata = new_ld
 
 def inplace_xor__Set_Set(space, w_left, w_other):
     set_symmetric_difference_update__Set_Set(space, w_left, w_other)
@@ -582,8 +558,9 @@
 def set_union__Set_Set(space, w_left, w_other):
     # optimization only (the general case works too)
     ld, rd = w_left.setdata, w_other.setdata
-    new_ld, rd = _union_dict(ld, rd, False)
-    return w_left._newobj(space, new_ld)
+    result = ld.copy()
+    result.update(rd)
+    return w_left._newobj(space, result)
 
 set_union__Set_Frozenset = set_union__Set_Set
 set_union__Frozenset_Set = set_union__Set_Set
@@ -595,9 +572,11 @@
 
 
 def set_union__Set_ANY(space, w_left, w_other):
-    ld, rd = w_left.setdata, make_setdata_from_w_iterable(space, w_other)
-    new_ld, rd = _union_dict(ld, rd, False)
-    return w_left._newobj(space, new_ld)
+    ld = w_left.setdata
+    result = ld.copy()
+    for w_key in space.listview(w_other):
+        result[w_key] = None
+    return w_left._newobj(space, result)
 
 frozenset_union__Frozenset_ANY = set_union__Set_ANY
 
@@ -629,15 +608,6 @@
             init_defaults)
     _initialize_set(space, w_set, w_iterable)
 
-def init__Frozenset(space, w_set, __args__):
-    w_iterable, = __args__.parse_obj(
-            None, 'set',
-            init_signature,
-            init_defaults)
-    if w_set.hash == -1:
-        _initialize_set(space, w_set, w_iterable)
-        hash__Frozenset(space, w_set)
-
 app = gateway.applevel("""
     def setrepr(currently_in_repr, s):
         'The app-level part of repr().'

Modified: pypy/branch/jit-unroll-loops/pypy/objspace/std/settype.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/objspace/std/settype.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/objspace/std/settype.py	Sat Oct 30 16:41:17 2010
@@ -66,9 +66,9 @@
 register_all(vars(), globals())
 
 def descr__new__(space, w_settype, __args__):
-    from pypy.objspace.std.setobject import W_SetObject
+    from pypy.objspace.std.setobject import W_SetObject, newset
     w_obj = space.allocate_instance(W_SetObject, w_settype)
-    W_SetObject.__init__(w_obj, space, None)
+    W_SetObject.__init__(w_obj, space, newset(space))
     return w_obj
 
 set_typedef = StdTypeDef("set",

Modified: pypy/branch/jit-unroll-loops/pypy/objspace/std/smallintobject.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/objspace/std/smallintobject.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/objspace/std/smallintobject.py	Sat Oct 30 16:41:17 2010
@@ -2,18 +2,13 @@
 Implementation of small ints, stored as odd-valued pointers in the
 translated PyPy.  To enable them, see inttype.py.
 """
-import types
-from pypy.interpreter.error import OperationError
 from pypy.objspace.std import intobject
 from pypy.objspace.std.model import registerimplementation, W_Object
 from pypy.objspace.std.register_all import register_all
-from pypy.objspace.std.multimethod import FailedToImplementArgs
 from pypy.objspace.std.noneobject import W_NoneObject
-from pypy.rlib.rarithmetic import ovfcheck, ovfcheck_lshift, LONG_BIT, r_uint
-from pypy.objspace.std.inttype import wrapint
-from pypy.objspace.std.intobject import W_IntObject, _impl_int_int_pow
+from pypy.objspace.std.intobject import W_IntObject
 from pypy.rlib.objectmodel import UnboxedValue
-from pypy.rlib.rbigint import rbigint
+from pypy.tool.sourcetools import func_with_new_name
 
 
 class W_SmallIntObject(W_Object, UnboxedValue):
@@ -46,9 +41,7 @@
             new_name = name.replace("Int", "SmallInt")
             # Copy the function, so the annotator specializes it for
             # W_SmallIntObject.
-            ns[new_name] = types.FunctionType(func.func_code, ns, new_name,
-                                              func.func_defaults,
-                                              func.func_closure)
+            ns[new_name] = func_with_new_name(func, new_name)
     ns["get_integer"] = ns["pos__SmallInt"] = ns["int__SmallInt"]
     ns["get_negint"] = ns["neg__SmallInt"]
 

Modified: pypy/branch/jit-unroll-loops/pypy/objspace/std/stringobject.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/objspace/std/stringobject.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/objspace/std/stringobject.py	Sat Oct 30 16:41:17 2010
@@ -14,7 +14,7 @@
 from pypy.rlib.rstring import StringBuilder, string_repeat
 from pypy.interpreter.buffer import StringBuffer
 
-from pypy.objspace.std.stringtype import sliced, joined, wrapstr, wrapchar, \
+from pypy.objspace.std.stringtype import sliced, wrapstr, wrapchar, \
      stringendswith, stringstartswith, joined2
 
 from pypy.objspace.std.formatting import mod_format

Modified: pypy/branch/jit-unroll-loops/pypy/objspace/std/stringtype.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/objspace/std/stringtype.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/objspace/std/stringtype.py	Sat Oct 30 16:41:17 2010
@@ -55,19 +55,14 @@
             return W_StringSliceObject(s, start, stop)
     return wrapstr(space, s[start:stop])
 
-def joined(space, strlist):
-    assert not space.config.objspace.std.withrope
-    if space.config.objspace.std.withstrjoin:
-        from pypy.objspace.std.strjoinobject import W_StringJoinObject
-        return W_StringJoinObject(strlist)
-    else:
-        return wrapstr(space, "".join(strlist))
-
 def joined2(space, str1, str2):
     assert not space.config.objspace.std.withrope
     if space.config.objspace.std.withstrjoin:
         from pypy.objspace.std.strjoinobject import W_StringJoinObject
         return W_StringJoinObject([str1, str2])
+    elif space.config.objspace.std.withstrbuf:
+        from pypy.objspace.std.strbufobject import joined2
+        return joined2(str1, str2)
     else:
         return wrapstr(space, str1 + str2)
 

Modified: pypy/branch/jit-unroll-loops/pypy/objspace/std/strutil.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/objspace/std/strutil.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/objspace/std/strutil.py	Sat Oct 30 16:41:17 2010
@@ -4,6 +4,7 @@
 
 from pypy.rlib.rarithmetic import ovfcheck, break_up_float, parts_to_float,\
      INFINITY, NAN
+from pypy.rlib.rbigint import rbigint, parse_digit_string
 from pypy.interpreter.error import OperationError
 import math
 
@@ -91,9 +92,10 @@
             return -1
 
 def string_to_int(s, base=10):
-    """Utility to converts a string to an integer (or possibly a long).
+    """Utility to converts a string to an integer.
     If base is 0, the proper base is guessed based on the leading
     characters of 's'.  Raises ParseStringError in case of error.
+    Raises ParseStringOverflowError in case the result does not fit.
     """
     s = literal = strip_spaces(s)
     p = NumberStringParser(s, literal, base, 'int')
@@ -113,11 +115,9 @@
         except OverflowError:
             raise ParseStringOverflowError(p)
 
-def string_to_long(space, s, base=10, parser=None):
-    return string_to_w_long(space, s, base, parser).longval()
-
-def string_to_w_long(space, s, base=10, parser=None):
-    """As string_to_int(), but ignores an optional 'l' or 'L' suffix."""
+def string_to_bigint(s, base=10, parser=None):
+    """As string_to_int(), but ignores an optional 'l' or 'L' suffix
+    and returns an rbigint."""
     if parser is None:
         s = literal = strip_spaces(s)
         if (s.endswith('l') or s.endswith('L')) and base < 22:
@@ -126,18 +126,7 @@
         p = NumberStringParser(s, literal, base, 'long')
     else:
         p = parser
-    w_base = space.newlong(p.base)
-    w_result = space.newlong(0)
-    while True:
-        digit = p.next_digit()
-        if digit == -1:
-            if p.sign == -1:
-                w_result = space.neg(w_result)
-            # XXX grumble
-            from pypy.objspace.std.longobject import W_LongObject
-            assert isinstance(w_result, W_LongObject)
-            return w_result
-        w_result = space.add(space.mul(w_result,w_base), space.newlong(digit))
+    return parse_digit_string(p)
 
 # Tim's comment:
 # 57 bits are more than needed in any case.

Modified: pypy/branch/jit-unroll-loops/pypy/objspace/std/test/test_dictmultiobject.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/objspace/std/test/test_dictmultiobject.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/objspace/std/test/test_dictmultiobject.py	Sat Oct 30 16:41:17 2010
@@ -4,7 +4,6 @@
      StrDictImplementation
 
 from pypy.objspace.std.celldict import ModuleDictImplementation
-from pypy.objspace.std.sharingdict import SharedDictImplementation
 from pypy.conftest import gettestobjspace
 
 
@@ -238,7 +237,17 @@
         it1 = d.popitem()
         assert len(d) == 0
         assert (it!=it1) and (it1==(1,2) or it1==(3,4))
-    
+        raises(KeyError, d.popitem)
+
+    def test_popitem_2(self):
+        class A(object):
+            pass
+        d = A().__dict__
+        d['x'] = 5
+        it1 = d.popitem()
+        assert it1 == ('x', 5)
+        raises(KeyError, d.popitem)
+
     def test_setdefault(self):
         d = {1:2, 3:4}
         dd = d.copy()
@@ -446,7 +455,9 @@
         d1 = {}
         d2 = D(a='foo')
         d1.update(d2)
-        assert d1['a'] == 42 # fails on CPython, d1['a'] == 'foo'
+        assert d1['a'] == 'foo'
+        # a bit of an obscure case: now (from r78295) we get the same result
+        # as CPython does
 
     def test_index_keyerror_unpacking(self):
         d = {}
@@ -510,32 +521,6 @@
         assert getattr(a, s) == 42
 
 
-class TestW_DictSharing(TestW_DictObject):
-    def setup_class(cls):
-        cls.space = gettestobjspace(**{"objspace.std.withsharingdict": True})
-
-class AppTest_DictSharing(AppTest_DictObject):
-    def setup_class(cls):
-        cls.space = gettestobjspace(**{"objspace.std.withsharingdict": True})
-
-    def test_values_does_not_share(self):
-        class A(object):
-            pass
-        a = A()
-        a.abc = 12
-        l = a.__dict__.values()
-        assert l == [12]
-        l[0] = 24
-        assert a.abc == 12
-
-    def test_items(self):
-        class A(object):
-            pass
-        a = A()
-        a.abc = 12
-        a.__dict__.items() == [("abc", 12)]
-
-
 class AppTestModuleDict(object):
     def setup_class(cls):
         cls.space = gettestobjspace(**{"objspace.std.withcelldict": True})
@@ -602,6 +587,15 @@
                 classofinstance=classofinstance,
                 from_strdict_shared=from_strdict_shared)
 
+    def finditem_str(self, w_dict, s):
+        return w_dict.getitem_str(s) # assume it's a multidict
+
+    def setitem_str(self, w_dict, s, w_value):
+        return w_dict.setitem_str(s, w_value) # assume it's a multidict
+
+    def delitem(self, w_dict, w_s):
+        return w_dict.delitem(w_s) # assume it's a multidict
+
     def allocate_instance(self, cls, type):
         return object.__new__(cls)
 
@@ -611,7 +605,7 @@
     w_StopIteration = StopIteration
     w_None = None
     StringObjectCls = FakeString
-    w_dict = None
+    w_dict = W_DictMultiObject
     iter = iter
     fixedview = list
     listview  = list
@@ -620,10 +614,8 @@
     class objspace:
         class std:
             withdictmeasurement = False
-            withsharingdict = False
             withsmalldicts = False
             withcelldict = False
-            withshadowtracking = False
         class opcodes:
             CALL_LIKELY_BUILTIN = False
 
@@ -687,6 +679,14 @@
         assert self.impl.length() == 0
         self.check_not_devolved()
 
+    def test_clear(self):
+        self.fill_impl()
+        assert self.impl.length() == 2
+        self.impl.clear()
+        assert self.impl.length() == 0
+        self.check_not_devolved()
+
+
     def test_keys(self):
         self.fill_impl()
         keys = self.impl.keys()
@@ -750,9 +750,6 @@
     string = "int"
     string2 = "isinstance"
 
-class TestSharedDictImplementation(BaseTestRDictImplementation):
-    ImplementionClass = SharedDictImplementation
-
 
 class BaseTestDevolvedDictImplementation(BaseTestRDictImplementation):
     def fill_impl(self):
@@ -774,8 +771,6 @@
     string = "int"
     string2 = "isinstance"
 
-class TestDevolvedSharedDictImplementation(BaseTestDevolvedDictImplementation):
-    ImplementionClass = SharedDictImplementation
 
 def test_module_uses_strdict():
     fakespace = FakeSpace()

Modified: pypy/branch/jit-unroll-loops/pypy/objspace/std/test/test_longobject.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/objspace/std/test/test_longobject.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/objspace/std/test/test_longobject.py	Sat Oct 30 16:41:17 2010
@@ -41,56 +41,64 @@
 
 class AppTestLong:
     def test_add(self):
-        assert int(123L + 12443L) == 123 + 12443
-        assert -20 + 2 + 3L + True == -14L
+        x = 123L
+        assert int(x + 12443L) == 123 + 12443
+        x = -20
+        assert x + 2 + 3L + True == -14L
 
     def test_sub(self):
-        assert int(58543L - 12332L) == 58543 - 12332
-        assert 237123838281233L * 12 == 237123838281233L * 12L
+        x = 58543L
+        assert int(x - 12332L) == 58543 - 12332
+        x = 237123838281233L
+        assert x * 12 == x * 12L
 
     def test_mul(self):
-        assert 363L * 2 ** 40 == 363L << 40
+        x = 363L
+        assert x * 2 ** 40 == x << 40
 
     def test_truediv(self):
         exec "from __future__ import division; a = 31415926L / 10000000L"
         assert a == 3.1415926
 
     def test_floordiv(self):
-        a = 31415926L // 10000000L
+        x = 31415926L
+        a = x // 10000000L
         assert a == 3L
 
     def test_compare(self):
+        Z = 0
+        ZL = 0L
         for BIG in (1L, 1L << 62, 1L << 9999):
-            assert 0 == 0L
-            assert not (0 != 0L)
-            assert 0L == 0
-            assert not (0L != 0)
-            assert not (0 == BIG)
-            assert 0 != BIG
-            assert not (BIG == 0)
-            assert BIG != 0
-            assert not (0L == BIG)
-            assert 0L != BIG
-            assert 0 <= 0L
-            assert not (0 < 0L)
-            assert 0 <= BIG
-            assert 0 < BIG
-            assert not (BIG <= 0)
-            assert not (BIG < 0)
-            assert 0L <= 0L
-            assert not (0L < 0L)
-            assert 0L <= BIG
-            assert 0L < BIG
-            assert not (BIG <= 0L)
-            assert not (BIG < 0L)
-            assert not (0 <= -BIG)
-            assert not (0 < -BIG)
-            assert -BIG <= 0
-            assert -BIG < 0
-            assert not (0L <= -BIG)
-            assert not (0L < -BIG)
-            assert -BIG <= 0L
-            assert -BIG < 0L
+            assert Z == ZL
+            assert not (Z != ZL)
+            assert ZL == Z
+            assert not (ZL != Z)
+            assert not (Z == BIG)
+            assert Z != BIG
+            assert not (BIG == Z)
+            assert BIG != Z
+            assert not (ZL == BIG)
+            assert ZL != BIG
+            assert Z <= ZL
+            assert not (Z < ZL)
+            assert Z <= BIG
+            assert Z < BIG
+            assert not (BIG <= Z)
+            assert not (BIG < Z)
+            assert ZL <= ZL
+            assert not (ZL < ZL)
+            assert ZL <= BIG
+            assert ZL < BIG
+            assert not (BIG <= ZL)
+            assert not (BIG < ZL)
+            assert not (Z <= -BIG)
+            assert not (Z < -BIG)
+            assert -BIG <= Z
+            assert -BIG < Z
+            assert not (ZL <= -BIG)
+            assert not (ZL < -BIG)
+            assert -BIG <= ZL
+            assert -BIG < ZL
             #
             assert not (BIG <  int(BIG))
             assert     (BIG <= int(BIG))
@@ -137,7 +145,8 @@
     def test_conversion(self):
         class long2(long):
             pass
-        x = long2(1L<<100)
+        x = 1L
+        x = long2(x<<100)
         y = int(x)
         assert type(y) == long
         assert type(+long2(5)) is long
@@ -152,7 +161,8 @@
         assert type(long2(5) // 1) is long
 
     def test_pow(self):
-        assert pow(0L, 0L, 1L) == 0L
+        x = 0L
+        assert pow(x, 0L, 1L) == 0L
 
     def test_getnewargs(self):
         assert  0L .__getnewargs__() == (0L,)
@@ -193,13 +203,14 @@
         assert oct(01234567012345670L) == '01234567012345670L'
 
     def test_bits(self):
-        assert 0xAAAAAAAAL | 0x55555555L == 0xFFFFFFFFL
-        assert 0xAAAAAAAAL & 0x55555555L == 0x00000000L
-        assert 0xAAAAAAAAL ^ 0x55555555L == 0xFFFFFFFFL
-        assert -0xAAAAAAAAL | 0x55555555L == -0xAAAAAAA9L
-        assert 0xAAAAAAAAL | 0x555555555L == 0x5FFFFFFFFL
-        assert 0xAAAAAAAAL & 0x555555555L == 0x000000000L
-        assert 0xAAAAAAAAL ^ 0x555555555L == 0x5FFFFFFFFL
+        x = 0xAAAAAAAAL
+        assert x | 0x55555555L == 0xFFFFFFFFL
+        assert x & 0x55555555L == 0x00000000L
+        assert x ^ 0x55555555L == 0xFFFFFFFFL
+        assert -x | 0x55555555L == -0xAAAAAAA9L
+        assert x | 0x555555555L == 0x5FFFFFFFFL
+        assert x & 0x555555555L == 0x000000000L
+        assert x ^ 0x555555555L == 0x5FFFFFFFFL
 
     def test_hash(self):
         # ints have the same hash as equal longs
@@ -229,7 +240,8 @@
 
     def test_huge_longs(self):
         import operator
-        huge = 1L << 40000L
+        x = 1L
+        huge = x << 40000L
         raises(OverflowError, float, huge)
         raises(OverflowError, operator.truediv, huge, 3)
         raises(OverflowError, operator.truediv, huge, 3L)
@@ -242,3 +254,7 @@
         class myotherlong(long):
             pass
         assert long(myotherlong(21)) == 21L
+
+    def test_negative_zero(self):
+        x = eval("-0L")
+        assert x == 0L

Modified: pypy/branch/jit-unroll-loops/pypy/objspace/std/test/test_setobject.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/objspace/std/test/test_setobject.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/objspace/std/test/test_setobject.py	Sat Oct 30 16:41:17 2010
@@ -10,6 +10,7 @@
 import py.test
 from pypy.objspace.std.setobject import W_SetObject, W_FrozensetObject
 from pypy.objspace.std.setobject import _initialize_set
+from pypy.objspace.std.setobject import newset, make_setdata_from_w_iterable
 from pypy.objspace.std.setobject import set_intersection__Set_Set
 from pypy.objspace.std.setobject import set_intersection__Set_ANY
 from pypy.objspace.std.setobject import eq__Set_Set
@@ -28,12 +29,12 @@
         self.false = self.space.w_False
 
     def test_and(self):
-        s = W_SetObject(self.space, None)
+        s = W_SetObject(self.space, newset(self.space))
         _initialize_set(self.space, s, self.word)
-        t0 = W_SetObject(self.space, None)
+        t0 = W_SetObject(self.space, newset(self.space))
         _initialize_set(self.space, t0, self.otherword)
-        t1 = W_FrozensetObject(self.space, None)
-        _initialize_set(self.space, t1, self.otherword)
+        t1 = W_FrozensetObject(self.space,
+                make_setdata_from_w_iterable(self.space, self.otherword))
         r0 = set_intersection__Set_Set(self.space, s, t0)
         r1 = set_intersection__Set_Set(self.space, s, t1)
         assert eq__Set_Set(self.space, r0, r1) == self.true
@@ -41,9 +42,9 @@
         assert eq__Set_Set(self.space, r0, sr) == self.true
 
     def test_compare(self):
-        s = W_SetObject(self.space, None)
+        s = W_SetObject(self.space, newset(self.space))
         _initialize_set(self.space, s, self.word)
-        t = W_SetObject(self.space, None)
+        t = W_SetObject(self.space, newset(self.space))
         _initialize_set(self.space, t, self.word)
         assert self.space.eq_w(s,t)
         u = self.space.wrap(set('simsalabim'))
@@ -56,6 +57,11 @@
         b = a | set('abc')
         assert type(b) is subset
 
+    def test_union(self):
+        a = set([4, 5])
+        b = a.union([5, 7])
+        assert sorted(b) == [4, 5, 7]
+
     def test_compare(self):
         raises(TypeError, cmp, set('abc'), set('abd'))
         assert set('abc') != 'abc'

Modified: pypy/branch/jit-unroll-loops/pypy/objspace/std/test/test_strutil.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/objspace/std/test/test_strutil.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/objspace/std/test/test_strutil.py	Sat Oct 30 16:41:17 2010
@@ -25,7 +25,7 @@
                  ]
         for s, expected in cases:
             assert string_to_int(s) == expected
-            assert string_to_w_long(space, s).longval() == expected
+            assert string_to_bigint(s).tolong() == expected
 
     def test_string_to_int_base(self):
         space = self.space        
@@ -119,17 +119,16 @@
             raises(ParseStringError, string_to_int, '+'+s, base)
             raises(ParseStringError, string_to_int, '-'+s, base)
 
-    def test_string_to_w_long(self):
-        space = self.space
-        assert string_to_w_long(space, '123L').longval() == 123
-        assert string_to_w_long(space, '123L  ').longval() == 123
-        raises(ParseStringError, string_to_w_long, space, 'L')
-        raises(ParseStringError, string_to_w_long, space, 'L  ')
-        assert string_to_w_long(space, '123L', 4).longval() == 27
-        assert string_to_w_long(space, '123L', 30).longval() == 27000 + 1800 + 90 + 21
-        assert string_to_w_long(space, '123L', 22).longval() == 10648 + 968 + 66 + 21
-        assert string_to_w_long(space, '123L', 21).longval() == 441 + 42 + 3
-        assert string_to_w_long(space, '1891234174197319').longval() == 1891234174197319
+    def test_string_to_bigint(self):
+        assert string_to_bigint('123L').tolong() == 123
+        assert string_to_bigint('123L  ').tolong() == 123
+        raises(ParseStringError, string_to_bigint, 'L')
+        raises(ParseStringError, string_to_bigint, 'L  ')
+        assert string_to_bigint('123L', 4).tolong() == 27
+        assert string_to_bigint('123L', 30).tolong() == 27000 + 1800 + 90 + 21
+        assert string_to_bigint('123L', 22).tolong() == 10648 + 968 + 66 + 21
+        assert string_to_bigint('123L', 21).tolong() == 441 + 42 + 3
+        assert string_to_bigint('1891234174197319').tolong() == 1891234174197319
 
     def test_string_to_float(self):
         def string_to_float(x):

Modified: pypy/branch/jit-unroll-loops/pypy/objspace/std/test/test_typeobject.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/objspace/std/test/test_typeobject.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/objspace/std/test/test_typeobject.py	Sat Oct 30 16:41:17 2010
@@ -1085,4 +1085,12 @@
 
         assert b == 1
 
-        
+    def test_slots_with_method_in_class(self):
+        # this works in cpython...
+        class A(object):
+            __slots__ = ["f"]
+            def f(self, x):
+                return x + 1
+        a = A()
+        assert a.f(1) == 2
+

Modified: pypy/branch/jit-unroll-loops/pypy/objspace/std/test/test_versionedtype.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/objspace/std/test/test_versionedtype.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/objspace/std/test/test_versionedtype.py	Sat Oct 30 16:41:17 2010
@@ -12,10 +12,12 @@
                 def f(self): pass
             class B(A):
                 pass
-            class metatype(type):
+            class X:
+                pass
+            class Y(object):
+                pass
+            class C(Y, X):
                 pass
-            class C(object):
-                __metaclass__ = metatype
             return A, B, C
         """)
         return space.unpackiterable(w_types)

Modified: pypy/branch/jit-unroll-loops/pypy/objspace/std/typeobject.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/objspace/std/typeobject.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/objspace/std/typeobject.py	Sat Oct 30 16:41:17 2010
@@ -60,6 +60,15 @@
             self.hits = {}
             self.misses = {}
 
+    def clear(self):
+        None_None = (None, None)
+        for i in range(len(self.versions)):
+            self.versions[i] = None
+        for i in range(len(self.names)):
+            self.names[i] = None
+        for i in range(len(self.lookup_where)):
+            self.lookup_where[i] = None_None
+
 
 class W_TypeObject(W_Object):
     from pypy.objspace.std.typetype import type_typedef as typedef
@@ -75,7 +84,9 @@
                           'weakrefable',
                           'hasdict',
                           'nslots',
-                          'instancetypedef']
+                          'instancetypedef',
+                          'terminator',
+                          ]
 
     # for config.objspace.std.getattributeshortcut
     # (False is a conservative default, fixed during real usage)
@@ -102,20 +113,24 @@
 
         if overridetypedef is not None:
             setup_builtin_type(w_self)
-            custom_metaclass = False
         else:
             setup_user_defined_type(w_self)
-            custom_metaclass = not space.is_w(space.type(w_self), space.w_type)
         w_self.w_same_layout_as = get_parent_layout(w_self)
 
         if space.config.objspace.std.withtypeversion:
-            if custom_metaclass or not is_mro_purely_of_types(w_self.mro_w):
+            if not is_mro_purely_of_types(w_self.mro_w):
                 pass
             else:
                 # the _version_tag should change, whenever the content of
                 # dict_w of any of the types in the mro changes, or if the mro
                 # itself changes
                 w_self._version_tag = VersionTag()
+        if space.config.objspace.std.withmapdict:
+            from pypy.objspace.std.mapdict import DictTerminator, NoDictTerminator
+            if w_self.hasdict:
+                w_self.terminator = DictTerminator(space, w_self)
+            else:
+                w_self.terminator = NoDictTerminator(space, w_self)
 
     def mutated(w_self):
         space = w_self.space
@@ -551,11 +566,13 @@
                              space.wrap('__slots__ must be identifiers'))
     # create member
     slot_name = _mangle(slot_name, w_self.name)
-    # Force interning of slot names.
-    slot_name = space.str_w(space.new_interned_str(slot_name))
-    member = Member(w_self.nslots, slot_name, w_self)
-    w_self.dict_w[slot_name] = space.wrap(member)
-    w_self.nslots += 1
+    if slot_name not in w_self.dict_w:
+        # Force interning of slot names.
+        slot_name = space.str_w(space.new_interned_str(slot_name))
+        # in cpython it is ignored less, but we probably don't care
+        member = Member(w_self.nslots, slot_name, w_self)
+        w_self.dict_w[slot_name] = space.wrap(member)
+        w_self.nslots += 1
 
 def create_dict_slot(w_self):
     if not w_self.hasdict:

Modified: pypy/branch/jit-unroll-loops/pypy/objspace/test/test_descroperation.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/objspace/test/test_descroperation.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/objspace/test/test_descroperation.py	Sat Oct 30 16:41:17 2010
@@ -400,7 +400,7 @@
         class D(object):
             def __init__(self, a):
                 self.a = a
-        
+
         assert A(1) == B(1)
         assert B(1) == A(1)
         assert A(1) == C(1)
@@ -457,6 +457,20 @@
         else:
             assert False, "did not raise"
 
+    def test_attribute_error(self):
+        class classmethodonly(classmethod):
+            def __get__(self, instance, type):
+                if instance is not None:
+                    raise AttributeError("Must be called on a class, not an instance.")
+                return super(classmethodonly, self).__get__(instance, type)
+
+        class A(object):
+            @classmethodonly
+            def a(cls):
+                return 3
+
+        raises(AttributeError, lambda: A().a)
+
 
 class AppTestWithBuiltinShortcut(AppTest_Descroperation):
     OPTIONS = {'objspace.std.builtinshortcut': True}

Modified: pypy/branch/jit-unroll-loops/pypy/rlib/_rsocket_rffi.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/rlib/_rsocket_rffi.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/rlib/_rsocket_rffi.py	Sat Oct 30 16:41:17 2010
@@ -324,10 +324,11 @@
                                ('sll_hatype', rffi.INT),
                                ('sll_addr', rffi.CFixedArray(rffi.CHAR, 8)),
                                ('sll_halen', rffi.INT)],
-                              )
+                              ifdef='AF_PACKET')
 
     CConfig.ifreq = platform.Struct('struct ifreq', [('ifr_ifindex', rffi.INT),
-                                 ('ifr_name', rffi.CFixedArray(rffi.CHAR, 8))])
+                                 ('ifr_name', rffi.CFixedArray(rffi.CHAR, 8))],
+                                    ifdef='AF_PACKET')
 
 if _WIN32:
     CConfig.WSAEVENT = platform.SimpleType('WSAEVENT', rffi.VOIDP)
@@ -532,8 +533,9 @@
     socketpair_t = rffi.CArray(socketfd_type)
     socketpair = external('socketpair', [rffi.INT, rffi.INT, rffi.INT,
                           lltype.Ptr(socketpair_t)], rffi.INT)
-    ioctl = external('ioctl', [socketfd_type, rffi.INT, lltype.Ptr(ifreq)],
-                     rffi.INT)
+    if ifreq is not None:
+        ioctl = external('ioctl', [socketfd_type, rffi.INT, lltype.Ptr(ifreq)],
+                         rffi.INT)
 
 if _WIN32:
     ioctlsocket = external('ioctlsocket',

Modified: pypy/branch/jit-unroll-loops/pypy/rlib/jit.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/rlib/jit.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/rlib/jit.py	Sat Oct 30 16:41:17 2010
@@ -77,6 +77,12 @@
         return result
     return decorator
 
+def oopspec(spec):
+    def decorator(func):
+        func.oopspec = spec
+        return func
+    return decorator
+
 class Entry(ExtRegistryEntry):
     _about_ = hint
 
@@ -139,6 +145,24 @@
         return hop.inputconst(lltype.Signed, _we_are_jitted)
 
 
+def jit_debug(string, arg1=-sys.maxint-1, arg2=-sys.maxint-1,
+                      arg3=-sys.maxint-1, arg4=-sys.maxint-1):
+    """When JITted, cause an extra operation DEBUG_MERGE_POINT to appear in
+    the graphs.  Should not be left after debugging."""
+    keepalive_until_here(string) # otherwise the whole function call is removed
+jit_debug.oopspec = 'jit.debug(string, arg1, arg2, arg3, arg4)'
+
+def assert_green(value):
+    """Very strong assert: checks that 'value' is a green
+    (a JIT compile-time constant)."""
+    keepalive_until_here(value)
+assert_green._annspecialcase_ = 'specialize:argtype(0)'
+assert_green.oopspec = 'jit.assert_green(value)'
+
+class AssertGreenFailed(Exception):
+    pass
+
+
 ##def force_virtualizable(virtualizable):
 ##    pass
 
@@ -251,8 +275,9 @@
     several independent JITting interpreters in it.
     """
 
+    active = True          # if set to False, this JitDriver is ignored
     virtualizables = []
-    
+
     def __init__(self, greens=None, reds=None, virtualizables=None,
                  get_jitcell_at=None, set_jitcell_at=None,
                  get_printable_location=None, confirm_enter_jit=None,
@@ -267,7 +292,8 @@
             self.virtualizables = virtualizables
         for v in self.virtualizables:
             assert v in self.reds
-        self._alllivevars = dict.fromkeys(self.greens + self.reds)
+        self._alllivevars = dict.fromkeys(
+            [name for name in self.greens + self.reds if '.' not in name])
         self._make_extregistryentries()
         self.get_jitcell_at = get_jitcell_at
         self.set_jitcell_at = set_jitcell_at
@@ -356,10 +382,16 @@
 
     def compute_result_annotation(self, **kwds_s):
         from pypy.annotation import model as annmodel
+
+        if self.instance.__name__ == 'jit_merge_point':
+            if not self.annotate_hooks(**kwds_s):
+                return None      # wrong order, try again later
+
         driver = self.instance.im_self
         keys = kwds_s.keys()
         keys.sort()
-        expected = ['s_' + name for name in driver.greens + driver.reds]
+        expected = ['s_' + name for name in driver.greens + driver.reds
+                                if '.' not in name]
         expected.sort()
         if keys != expected:
             raise JitHintError("%s expects the following keyword "
@@ -383,30 +415,35 @@
                                    key[2:])
             cache[key] = s_value
 
-        if self.instance.__name__ == 'jit_merge_point':
-            self.annotate_hooks(**kwds_s)
-            
         return annmodel.s_None
 
     def annotate_hooks(self, **kwds_s):
         driver = self.instance.im_self
         s_jitcell = self.bookkeeper.valueoftype(BaseJitCell)
-        self.annotate_hook(driver.get_jitcell_at, driver.greens, **kwds_s)
-        self.annotate_hook(driver.set_jitcell_at, driver.greens, [s_jitcell],
-                           **kwds_s)
-        self.annotate_hook(driver.get_printable_location, driver.greens, **kwds_s)
+        h = self.annotate_hook
+        return (h(driver.get_jitcell_at, driver.greens, **kwds_s)
+            and h(driver.set_jitcell_at, driver.greens, [s_jitcell], **kwds_s)
+            and h(driver.get_printable_location, driver.greens, **kwds_s))
 
     def annotate_hook(self, func, variables, args_s=[], **kwds_s):
         if func is None:
-            return
+            return True
         bk = self.bookkeeper
         s_func = bk.immutablevalue(func)
         uniquekey = 'jitdriver.%s' % func.func_name
         args_s = args_s[:]
         for name in variables:
-            s_arg = kwds_s['s_' + name]
+            if '.' not in name:
+                s_arg = kwds_s['s_' + name]
+            else:
+                objname, fieldname = name.split('.')
+                s_instance = kwds_s['s_' + objname]
+                s_arg = s_instance.classdef.about_attribute(fieldname)
+                if s_arg is None:
+                    return False     # wrong order, try again later
             args_s.append(s_arg)
         bk.emulate_pbc_call(uniquekey, s_func, args_s)
+        return True
 
     def specialize_call(self, hop, **kwds_i):
         # XXX to be complete, this could also check that the concretetype
@@ -417,9 +454,42 @@
         greens_v = []
         reds_v = []
         for name in driver.greens:
-            i = kwds_i['i_' + name]
-            r_green = hop.args_r[i]
-            v_green = hop.inputarg(r_green, arg=i)
+            if '.' not in name:
+                i = kwds_i['i_' + name]
+                r_green = hop.args_r[i]
+                v_green = hop.inputarg(r_green, arg=i)
+            else:
+                if hop.rtyper.type_system.name == 'ootypesystem':
+                    py.test.skip("lltype only")
+                objname, fieldname = name.split('.')   # see test_green_field
+                assert objname in driver.reds
+                i = kwds_i['i_' + objname]
+                s_red = hop.args_s[i]
+                r_red = hop.args_r[i]
+                while True:
+                    try:
+                        mangled_name, r_field = r_red._get_field(fieldname)
+                        break
+                    except KeyError:
+                        pass
+                    assert r_red.rbase is not None, (
+                        "field %r not found in %r" % (name,
+                                                      r_red.lowleveltype.TO))
+                    r_red = r_red.rbase
+                GTYPE = r_red.lowleveltype.TO
+                assert GTYPE._immutable_field(mangled_name), (
+                    "field %r must be declared as immutable" % name)
+                if not hasattr(driver, 'll_greenfields'):
+                    driver.ll_greenfields = {}
+                driver.ll_greenfields[name] = GTYPE, mangled_name
+                #
+                v_red = hop.inputarg(r_red, arg=i)
+                c_llname = hop.inputconst(lltype.Void, mangled_name)
+                v_green = hop.genop('getfield', [v_red, c_llname],
+                                    resulttype = r_field)
+                s_green = s_red.classdef.about_attribute(fieldname)
+                assert s_green is not None
+                hop.rtyper.annotator.setbinding(v_green, s_green)
             greens_v.append(v_green)
         for name in driver.reds:
             i = kwds_i['i_' + name]

Modified: pypy/branch/jit-unroll-loops/pypy/rlib/objectmodel.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/rlib/objectmodel.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/rlib/objectmodel.py	Sat Oct 30 16:41:17 2010
@@ -475,6 +475,10 @@
     def setdefault(self, key, default):
         return self._dict.setdefault(_r_dictkey(self, key), default)
 
+    def popitem(self):
+        dk, value = self._dict.popitem()
+        return dk.key, value
+
     def copy(self):
         result = r_dict(self.key_eq, self.key_hash)
         result.update(self)

Modified: pypy/branch/jit-unroll-loops/pypy/rlib/rbigint.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/rlib/rbigint.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/rlib/rbigint.py	Sat Oct 30 16:41:17 2010
@@ -1596,11 +1596,16 @@
 
 # a few internal helpers
 
-DEC_PER_DIGIT = 1
-while int('9' * DEC_PER_DIGIT) < MASK:
-    DEC_PER_DIGIT += 1
-DEC_PER_DIGIT -= 1
-DEC_MAX = 10 ** DEC_PER_DIGIT
+def digits_max_for_base(base):
+    dec_per_digit = 1
+    while base ** dec_per_digit < MASK:
+        dec_per_digit += 1
+    dec_per_digit -= 1
+    return base ** dec_per_digit
+
+BASE_MAX = [0, 0] + [digits_max_for_base(_base) for _base in range(2, 37)]
+DEC_MAX = digits_max_for_base(10)
+assert DEC_MAX == BASE_MAX[10]
 
 def _decimalstr_to_bigint(s):
     # a string that has been already parsed to be decimal and valid,
@@ -1615,7 +1620,6 @@
         p += 1
 
     a = rbigint.fromint(0)
-    cnt = DEC_PER_DIGIT
     tens = 1
     dig = 0
     ord0 = ord('0')
@@ -1627,8 +1631,26 @@
             a = _muladd1(a, tens, dig)
             tens = 1
             dig = 0
-    if sign:
+    if sign and a.sign == 1:
         a.sign = -1
     return a
 
-
+def parse_digit_string(parser):
+    # helper for objspace.std.strutil
+    a = rbigint.fromint(0)
+    base = parser.base
+    digitmax = BASE_MAX[base]
+    tens, dig = 1, 0
+    while True:
+        digit = parser.next_digit()
+        if tens == digitmax or digit < 0:
+            a = _muladd1(a, tens, dig)
+            if digit < 0:
+                break
+            dig = digit
+            tens = base
+        else:
+            dig = dig * base + digit
+            tens *= base
+    a.sign *= parser.sign
+    return a

Modified: pypy/branch/jit-unroll-loops/pypy/rlib/rgc.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/rlib/rgc.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/rlib/rgc.py	Sat Oct 30 16:41:17 2010
@@ -170,7 +170,14 @@
         return hop.genop('gc_set_max_heap_size', [v_nbytes],
                          resulttype=lltype.Void)
 
-def can_move(p):    # NB. must not be called with NULL pointers
+def can_move(p):
+    """Check if the GC object 'p' is at an address that can move.
+    Must not be called with None.  With non-moving GCs, it is always False.
+    With some moving GCs like the SemiSpace GC, it is always True.
+    With other moving GCs like the MiniMark GC, it can be True for some
+    time, then False for the same object, when we are sure that it won't
+    move any more.
+    """
     return True
 
 class CanMoveEntry(ExtRegistryEntry):

Modified: pypy/branch/jit-unroll-loops/pypy/rlib/rmmap.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/rlib/rmmap.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/rlib/rmmap.py	Sat Oct 30 16:41:17 2010
@@ -50,7 +50,7 @@
     constant_names = ['MAP_SHARED', 'MAP_PRIVATE',
                       'PROT_READ', 'PROT_WRITE',
                       'MS_SYNC']
-    opt_constant_names = ['MAP_ANON', 'MAP_ANONYMOUS',
+    opt_constant_names = ['MAP_ANON', 'MAP_ANONYMOUS', 'MAP_NORESERVE',
                           'PROT_EXEC',
                           'MAP_DENYWRITE', 'MAP_EXECUTABLE']
     for name in constant_names:

Modified: pypy/branch/jit-unroll-loops/pypy/rlib/rsre/rsre_char.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/rlib/rsre/rsre_char.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/rlib/rsre/rsre_char.py	Sat Oct 30 16:41:17 2010
@@ -4,6 +4,7 @@
 import sys
 from pypy.rlib.rlocale import tolower, isalnum
 from pypy.rlib.unroll import unrolling_iterable
+from pypy.rlib import jit
 
 # Note: the unicode parts of this module require you to call
 # rsre_char.set_unicode_db() first, to select one of the modules
@@ -43,6 +44,7 @@
 # XXX can we import those safely from sre_constants?
 SRE_INFO_PREFIX = 1
 SRE_INFO_LITERAL = 2
+SRE_INFO_CHARSET = 4
 SRE_FLAG_LOCALE = 4 # honour system locale
 SRE_FLAG_UNICODE = 32 # use unicode locale
 OPCODE_INFO = 17
@@ -64,33 +66,27 @@
 
 #### Category helpers
 
-ascii_char_info = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 6, 2,
-2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0,
-0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 25, 25, 25, 25, 25, 25, 25,
-25, 25, 0, 0, 0, 0, 0, 0, 0, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
-24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 0, 0,
-0, 0, 16, 0, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
-24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 0, 0, 0, 0, 0 ]
-
+is_a_word = [(chr(i).isalnum() or chr(i) == '_') for i in range(256)]
 linebreak = ord("\n")
 underline = ord("_")
 
 def is_digit(code):
-    return code < 128 and (ascii_char_info[code] & 1 != 0)
+    return code <= 57 and code >= 48
 
 def is_uni_digit(code):
     assert unicodedb is not None
     return unicodedb.isdigit(code)
 
 def is_space(code):
-    return code < 128 and (ascii_char_info[code] & 2 != 0)
+    return code == 32 or (code <= 13 and code >= 9)
 
 def is_uni_space(code):
     assert unicodedb is not None
     return unicodedb.isspace(code)
 
 def is_word(code):
-    return code < 128 and (ascii_char_info[code] & 16 != 0)
+    assert code >= 0
+    return code < 256 and is_a_word[code]
 
 def is_uni_word(code):
     assert unicodedb is not None
@@ -142,6 +138,7 @@
 SET_OK = -1
 SET_NOT_OK = -2
 
+ at jit.unroll_safe
 def check_charset(pattern, ppos, char_code):
     """Checks whether a character matches set of arbitrary length.
     The set starts at pattern[ppos]."""

Modified: pypy/branch/jit-unroll-loops/pypy/rlib/rsre/rsre_core.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/rlib/rsre/rsre_core.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/rlib/rsre/rsre_core.py	Sat Oct 30 16:41:17 2010
@@ -1,9 +1,11 @@
 import sys
-from pypy.rlib.debug import check_nonneg
+from pypy.rlib.debug import check_nonneg, make_sure_not_modified
 from pypy.rlib.unroll import unrolling_iterable
 from pypy.rlib.rsre import rsre_char
 from pypy.tool.sourcetools import func_with_new_name
 from pypy.rlib.objectmodel import we_are_translated
+from pypy.rlib import jit
+from pypy.rlib.rsre.rsre_jit import install_jitdriver, install_jitdriver_spec
 
 
 OPCODE_FAILURE            = 0
@@ -56,16 +58,19 @@
     _seen_specname[specname] = True
     # Install a copy of the function under the name '_spec_funcname' in each
     # concrete subclass
+    specialized_methods = []
     for prefix, concreteclass in [('str', StrMatchContext),
                                   ('uni', UnicodeMatchContext)]:
         newfunc = func_with_new_name(func, prefix + specname)
         assert not hasattr(concreteclass, specname)
         setattr(concreteclass, specname, newfunc)
+        specialized_methods.append(newfunc)
     # Return a dispatcher function, specialized on the exact type of 'ctx'
     def dispatch(ctx, *args):
         return getattr(ctx, specname)(*args)
     dispatch._annspecialcase_ = 'specialize:argtype(0)'
-    return dispatch
+    dispatch._specialized_methods_ = specialized_methods
+    return func_with_new_name(dispatch, specname)
 
 # ____________________________________________________________
 
@@ -75,6 +80,7 @@
 
 class AbstractMatchContext(object):
     """Abstract base class"""
+    _immutable_fields_ = ['pattern[*]', 'flags', 'end']
     match_start = 0
     match_end = 0
     match_marks = None
@@ -164,6 +170,8 @@
     def __init__(self, pattern, string, match_start, end, flags):
         AbstractMatchContext.__init__(self, pattern, match_start, end, flags)
         self._string = string
+        if not we_are_translated() and isinstance(string, unicode):
+            self.flags |= rsre_char.SRE_FLAG_UNICODE   # for rsre_re.py
 
     def str(self, index):
         check_nonneg(index)
@@ -238,8 +246,9 @@
         self.start_ptr = ptr
         self.start_marks = marks
 
+    @jit.unroll_safe
     def find_first_result(self, ctx):
-        ppos = self.ppos
+        ppos = jit.hint(self.ppos, promote=True)
         while ctx.pat(ppos):
             result = sre_match(ctx, ppos + 1, self.start_ptr, self.start_marks)
             ppos += ctx.pat(ppos)
@@ -250,6 +259,10 @@
     find_next_result = find_first_result
 
 class RepeatOneMatchResult(MatchResult):
+    install_jitdriver('RepeatOne',
+                      greens=['nextppos', 'ctx.pattern'],
+                      reds=['ptr', 'self', 'ctx'],
+                      debugprint=(1, 0))   # indices in 'greens'
 
     def __init__(self, nextppos, minptr, ptr, marks):
         self.nextppos = nextppos
@@ -259,8 +272,11 @@
 
     def find_first_result(self, ctx):
         ptr = self.start_ptr
+        nextppos = self.nextppos
         while ptr >= self.minptr:
-            result = sre_match(ctx, self.nextppos, ptr, self.start_marks)
+            ctx.jitdriver_RepeatOne.jit_merge_point(
+                self=self, ptr=ptr, ctx=ctx, nextppos=nextppos)
+            result = sre_match(ctx, nextppos, ptr, self.start_marks)
             ptr -= 1
             if result is not None:
                 self.subresult = result
@@ -270,6 +286,10 @@
 
 
 class MinRepeatOneMatchResult(MatchResult):
+    install_jitdriver('MinRepeatOne',
+                      greens=['nextppos', 'ppos3', 'ctx.pattern'],
+                      reds=['ptr', 'self', 'ctx'],
+                      debugprint=(2, 0))   # indices in 'greens'
 
     def __init__(self, nextppos, ppos3, maxptr, ptr, marks):
         self.nextppos = nextppos
@@ -280,29 +300,32 @@
 
     def find_first_result(self, ctx):
         ptr = self.start_ptr
+        nextppos = self.nextppos
+        ppos3 = self.ppos3
         while ptr <= self.maxptr:
-            result = sre_match(ctx, self.nextppos, ptr, self.start_marks)
+            ctx.jitdriver_MinRepeatOne.jit_merge_point(
+                self=self, ptr=ptr, ctx=ctx, nextppos=nextppos, ppos3=ppos3)
+            result = sre_match(ctx, nextppos, ptr, self.start_marks)
             if result is not None:
                 self.subresult = result
                 self.start_ptr = ptr
                 return self
-            if not self.next_char_ok(ctx, ptr):
+            if not self.next_char_ok(ctx, ptr, ppos3):
                 break
             ptr += 1
 
     def find_next_result(self, ctx):
         ptr = self.start_ptr
-        if not self.next_char_ok(ctx, ptr):
+        if not self.next_char_ok(ctx, ptr, self.ppos3):
             return
         self.start_ptr = ptr + 1
         return self.find_first_result(ctx)
 
-    def next_char_ok(self, ctx, ptr):
+    def next_char_ok(self, ctx, ptr, ppos):
         if ptr == ctx.end:
             return False
-        ppos = self.ppos3
         op = ctx.pat(ppos)
-        for op1, (checkerfn, _) in unroll_char_checker:
+        for op1, checkerfn in unroll_char_checker:
             if op1 == op:
                 return checkerfn(ctx, ptr, ppos)
         raise Error("next_char_ok[%d]" % op)
@@ -325,41 +348,34 @@
         self.next = next     # chained list
 
 class MaxUntilMatchResult(AbstractUntilMatchResult):
+    install_jitdriver('MaxUntil',
+                      greens=['ppos', 'tailppos', 'match_more', 'ctx.pattern'],
+                      reds=['ptr', 'marks', 'self', 'ctx'],
+                      debugprint=(3, 0, 2))
 
     def find_first_result(self, ctx):
-        enum = sre_match(ctx, self.ppos + 3, self.cur_ptr, self.cur_marks)
-        return self.search_next(ctx, enum, resume=False)
+        return self.search_next(ctx, match_more=True)
 
     def find_next_result(self, ctx):
-        return self.search_next(ctx, None, resume=True)
+        return self.search_next(ctx, match_more=False)
 
-    def search_next(self, ctx, enum, resume):
+    def search_next(self, ctx, match_more):
         ppos = self.ppos
-        min = ctx.pat(ppos+1)
-        max = ctx.pat(ppos+2)
+        tailppos = self.tailppos
         ptr = self.cur_ptr
         marks = self.cur_marks
         while True:
-            while True:
-                if (enum is not None and
-                    (ptr != ctx.match_end or self.num_pending < min)):
-                    #               ^^^^^^^^^^ zero-width match protection
-                    # matched one more 'item'.  record it and continue.
-                    self.pending = Pending(ptr, marks, enum, self.pending)
-                    self.num_pending += 1
-                    ptr = ctx.match_end
-                    marks = ctx.match_marks
-                    break
-                # 'item' no longer matches.
-                if not resume and self.num_pending >= min:
-                    # try to match 'tail' if we have enough 'item'
-                    result = sre_match(ctx, self.tailppos, ptr, marks)
-                    if result is not None:
-                        self.subresult = result
-                        self.cur_ptr = ptr
-                        self.cur_marks = marks
-                        return self
-                resume = False
+            ctx.jitdriver_MaxUntil.jit_merge_point(
+                ppos=ppos, tailppos=tailppos, match_more=match_more,
+                ptr=ptr, marks=marks, self=self, ctx=ctx)
+            if match_more:
+                max = ctx.pat(ppos+2)
+                if max == 65535 or self.num_pending < max:
+                    # try to match one more 'item'
+                    enum = sre_match(ctx, ppos + 3, ptr, marks)
+                else:
+                    enum = None    # 'max' reached, no more matches
+            else:
                 p = self.pending
                 if p is None:
                     return
@@ -369,11 +385,27 @@
                 marks = p.marks
                 enum = p.enum.move_to_next_result(ctx)
             #
-            if max == 65535 or self.num_pending < max:
-                # try to match one more 'item'
-                enum = sre_match(ctx, ppos + 3, ptr, marks)
+            min = ctx.pat(ppos+1)
+            if (enum is not None and
+                (ptr != ctx.match_end or self.num_pending < min)):
+                #               ^^^^^^^^^^ zero-width match protection
+                # matched one more 'item'.  record it and continue.
+                self.pending = Pending(ptr, marks, enum, self.pending)
+                self.num_pending += 1
+                ptr = ctx.match_end
+                marks = ctx.match_marks
+                match_more = True
             else:
-                enum = None    # 'max' reached, no more matches
+                # 'item' no longer matches.
+                if self.num_pending >= min:
+                    # try to match 'tail' if we have enough 'item'
+                    result = sre_match(ctx, tailppos, ptr, marks)
+                    if result is not None:
+                        self.subresult = result
+                        self.cur_ptr = ptr
+                        self.cur_marks = marks
+                        return self
+                match_more = False
 
 class MinUntilMatchResult(AbstractUntilMatchResult):
 
@@ -384,6 +416,7 @@
         return self.search_next(ctx, resume=True)
 
     def search_next(self, ctx, resume):
+        # XXX missing jit support here
         ppos = self.ppos
         min = ctx.pat(ppos+1)
         max = ctx.pat(ppos+2)
@@ -429,6 +462,7 @@
 # ____________________________________________________________
 
 @specializectx
+ at jit.unroll_safe
 def sre_match(ctx, ppos, ptr, marks):
     """Returns either None or a MatchResult object.  Usually we only need
     the first result, but there is the case of REPEAT...UNTIL where we
@@ -437,6 +471,13 @@
     while True:
         op = ctx.pat(ppos)
         ppos += 1
+        make_sure_not_modified(ctx.pattern)
+
+        #jit.jit_debug("sre_match", op, ppos, ptr)
+        #
+        # When using the JIT, calls to sre_match() must always have a constant
+        # (green) argument for 'ppos'.  If not, the following assert fails.
+        jit.assert_green(op)
 
         if op == OPCODE_FAILURE:
             return
@@ -712,13 +753,23 @@
 @specializectx
 def find_repetition_end(ctx, ppos, ptr, maxcount):
     end = ctx.end
-    # adjust end
-    if maxcount != 65535:
+    if maxcount <= 1:
+        if maxcount == 1 and ptr < end:
+            # Relatively common case: maxcount == 1.  If we are not at the
+            # end of the string, it's done by a single direct check.
+            op = ctx.pat(ppos)
+            for op1, checkerfn in unroll_char_checker:
+                if op1 == op:
+                    if checkerfn(ctx, ptr, ppos):
+                        return ptr + 1
+        return ptr
+    elif maxcount != 65535:
+        # adjust end
         end1 = ptr + maxcount
         if end1 <= end:
             end = end1
     op = ctx.pat(ppos)
-    for op1, (_, fre) in unroll_char_checker:
+    for op1, fre in unroll_fre_checker:
         if op1 == op:
             return fre(ctx, ptr, end, ppos)
     raise Error("rsre.find_repetition_end[%d]" % op)
@@ -751,23 +802,60 @@
     if checkerfn == match_ANY_ALL:
         def fre(ctx, ptr, end, ppos):
             return end
+    elif checkerfn == match_IN:
+        install_jitdriver_spec('MatchIn', 
+                               greens=['ppos', 'ctx.pattern'],
+                               reds=['ptr', 'end', 'ctx'],
+                               debugprint=(1, 0))
+        @specializectx
+        def fre(ctx, ptr, end, ppos):
+            while True:
+                ctx.jitdriver_MatchIn.jit_merge_point(ctx=ctx, ptr=ptr,
+                                                      end=end, ppos=ppos)
+                if ptr < end and checkerfn(ctx, ptr, ppos):
+                    ptr += 1
+                else:
+                    return ptr
+    elif checkerfn == match_IN_IGNORE:
+        install_jitdriver_spec('MatchInIgnore', 
+                               greens=['ppos', 'ctx.pattern'],
+                               reds=['ptr', 'end', 'ctx'],
+                               debugprint=(1, 0))
+        @specializectx
+        def fre(ctx, ptr, end, ppos):
+            while True:
+                ctx.jitdriver_MatchInIgnore.jit_merge_point(ctx=ctx, ptr=ptr,
+                                                            end=end, ppos=ppos)
+                if ptr < end and checkerfn(ctx, ptr, ppos):
+                    ptr += 1
+                else:
+                    return ptr
     else:
+        # in the other cases, the fre() function is not JITted at all
+        # and is present as a residual call.
+        @specializectx
         def fre(ctx, ptr, end, ppos):
             while ptr < end and checkerfn(ctx, ptr, ppos):
                 ptr += 1
             return ptr
-    return checkerfn, fre
+    fre = func_with_new_name(fre, 'fre_' + checkerfn.__name__)
+    return fre
+
+unroll_char_checker = [
+    (OPCODE_ANY,                match_ANY),
+    (OPCODE_ANY_ALL,            match_ANY_ALL),
+    (OPCODE_IN,                 match_IN),
+    (OPCODE_IN_IGNORE,          match_IN_IGNORE),
+    (OPCODE_LITERAL,            match_LITERAL),
+    (OPCODE_LITERAL_IGNORE,     match_LITERAL_IGNORE),
+    (OPCODE_NOT_LITERAL,        match_NOT_LITERAL),
+    (OPCODE_NOT_LITERAL_IGNORE, match_NOT_LITERAL_IGNORE),
+    ]
+unroll_fre_checker = [(_op, _make_fre(_fn))
+                      for (_op, _fn) in unroll_char_checker]
 
-unroll_char_checker = unrolling_iterable([
-    (OPCODE_ANY,                _make_fre(match_ANY)),
-    (OPCODE_ANY_ALL,            _make_fre(match_ANY_ALL)),
-    (OPCODE_IN,                 _make_fre(match_IN)),
-    (OPCODE_IN_IGNORE,          _make_fre(match_IN_IGNORE)),
-    (OPCODE_LITERAL,            _make_fre(match_LITERAL)),
-    (OPCODE_LITERAL_IGNORE,     _make_fre(match_LITERAL_IGNORE)),
-    (OPCODE_NOT_LITERAL,        _make_fre(match_NOT_LITERAL)),
-    (OPCODE_NOT_LITERAL_IGNORE, _make_fre(match_NOT_LITERAL_IGNORE)),
-    ])
+unroll_char_checker = unrolling_iterable(unroll_char_checker)
+unroll_fre_checker  = unrolling_iterable(unroll_fre_checker)
 
 ##### At dispatch
 
@@ -873,74 +961,139 @@
     else:
         return None
 
+install_jitdriver('Match',
+                  greens=['ctx.pattern'], reds=['ctx'],
+                  debugprint=(0,))
+
 def match_context(ctx):
     ctx.original_pos = ctx.match_start
     if ctx.end < ctx.match_start:
         return False
+    ctx.jitdriver_Match.jit_merge_point(ctx=ctx)
     return sre_match(ctx, 0, ctx.match_start, None) is not None
 
 def search_context(ctx):
     ctx.original_pos = ctx.match_start
     if ctx.end < ctx.match_start:
         return False
-    if ctx.pat(0) == OPCODE_INFO:
-        if ctx.pat(2) & rsre_char.SRE_INFO_PREFIX and ctx.pat(5) > 1:
-            return fast_search(ctx)
-    return regular_search(ctx)
+    base = 0
+    charset = False
+    if ctx.pat(base) == OPCODE_INFO:
+        flags = ctx.pat(2)
+        if flags & rsre_char.SRE_INFO_PREFIX:
+            if ctx.pat(5) > 1:
+                return fast_search(ctx)
+        else:
+            charset = (flags & rsre_char.SRE_INFO_CHARSET)
+        base += 1 + ctx.pat(1)
+    if ctx.pat(base) == OPCODE_LITERAL:
+        return literal_search(ctx, base)
+    if charset:
+        return charset_search(ctx, base)
+    return regular_search(ctx, base)
+
+install_jitdriver('RegularSearch',
+                  greens=['base', 'ctx.pattern'],
+                  reds=['start', 'ctx'],
+                  debugprint=(1, 0))
 
-def regular_search(ctx):
+def regular_search(ctx, base):
     start = ctx.match_start
     while start <= ctx.end:
-        if sre_match(ctx, 0, start, None) is not None:
+        ctx.jitdriver_RegularSearch.jit_merge_point(ctx=ctx, start=start,
+                                                    base=base)
+        if sre_match(ctx, base, start, None) is not None:
             ctx.match_start = start
             return True
         start += 1
     return False
 
+install_jitdriver_spec("LiteralSearch",
+                       greens=['base', 'character', 'ctx.pattern'],
+                       reds=['start', 'ctx'],
+                       debugprint=(2, 0, 1))
+ at specializectx
+def literal_search(ctx, base):
+    # pattern starts with a literal character.  this is used
+    # for short prefixes, and if fast search is disabled
+    character = ctx.pat(base + 1)
+    base += 2
+    start = ctx.match_start
+    while start < ctx.end:
+        ctx.jitdriver_LiteralSearch.jit_merge_point(ctx=ctx, start=start,
+                                          base=base, character=character)
+        if ctx.str(start) == character:
+            if sre_match(ctx, base, start + 1, None) is not None:
+                ctx.match_start = start
+                return True
+        start += 1
+    return False
+
+install_jitdriver_spec("CharsetSearch",
+                       greens=['base', 'ctx.pattern'],
+                       reds=['start', 'ctx'],
+                       debugprint=(1, 0))
+ at specializectx
+def charset_search(ctx, base):
+    # pattern starts with a character from a known set
+    start = ctx.match_start
+    while start < ctx.end:
+        ctx.jitdriver_CharsetSearch.jit_merge_point(ctx=ctx, start=start,
+                                                    base=base)
+        if rsre_char.check_charset(ctx.pattern, 5, ctx.str(start)):
+            if sre_match(ctx, base, start, None) is not None:
+                ctx.match_start = start
+                return True
+        start += 1
+    return False
+
+install_jitdriver_spec('FastSearch',
+                       greens=['i', 'prefix_len', 'ctx.pattern'],
+                       reds=['string_position', 'ctx'],
+                       debugprint=(2, 0))
 @specializectx
 def fast_search(ctx):
     # skips forward in a string as fast as possible using information from
     # an optimization info block
     # <INFO> <1=skip> <2=flags> <3=min> <4=...>
     #        <5=length> <6=skip> <7=prefix data> <overlap data>
-    flags = ctx.pat(2)
+    string_position = ctx.match_start
+    if string_position >= ctx.end:
+        return False
     prefix_len = ctx.pat(5)
     assert prefix_len >= 0
-    prefix_skip = ctx.pat(6)
-    assert prefix_skip >= 0
-    overlap_offset = 7 + prefix_len - 1
-    assert overlap_offset >= 0
-    pattern_offset = ctx.pat(1) + 1
-    ppos_start = pattern_offset + 2 * prefix_skip
-    assert ppos_start >= 0
     i = 0
-    string_position = ctx.match_start
-    end = ctx.end
-    while string_position < end:
-        while True:
-            char_ord = ctx.str(string_position)
-            if char_ord != ctx.pat(7 + i):
-                if i == 0:
-                    break
-                else:
-                    i = ctx.pat(overlap_offset + i)
-            else:
-                i += 1
-                if i == prefix_len:
-                    # found a potential match
-                    start = string_position + 1 - prefix_len
-                    assert start >= 0
-                    ptr = start + prefix_skip
-                    if flags & rsre_char.SRE_INFO_LITERAL:
-                        # matched all of pure literal pattern
-                        ctx.match_start = start
-                        ctx.match_end = ptr
-                        ctx.match_marks = None
-                        return True
-                    if sre_match(ctx, ppos_start, ptr, None) is not None:
-                        ctx.match_start = start
-                        return True
-                    i = ctx.pat(overlap_offset + i)
-                break
+    while True:
+        ctx.jitdriver_FastSearch.jit_merge_point(ctx=ctx,
+                string_position=string_position, i=i, prefix_len=prefix_len)
+        char_ord = ctx.str(string_position)
+        if char_ord != ctx.pat(7 + i):
+            if i > 0:
+                overlap_offset = prefix_len + (7 - 1)
+                i = ctx.pat(overlap_offset + i)
+                continue
+        else:
+            i += 1
+            if i == prefix_len:
+                # found a potential match
+                start = string_position + 1 - prefix_len
+                assert start >= 0
+                prefix_skip = ctx.pat(6)
+                ptr = start + prefix_skip
+                #flags = ctx.pat(2)
+                #if flags & rsre_char.SRE_INFO_LITERAL:
+                #    # matched all of pure literal pattern
+                #    ctx.match_start = start
+                #    ctx.match_end = ptr
+                #    ctx.match_marks = None
+                #    return True
+                pattern_offset = ctx.pat(1) + 1
+                ppos_start = pattern_offset + 2 * prefix_skip
+                if sre_match(ctx, ppos_start, ptr, None) is not None:
+                    ctx.match_start = start
+                    return True
+                overlap_offset = prefix_len + (7 - 1)
+                i = ctx.pat(overlap_offset + i)
         string_position += 1
-    return False
+        if string_position >= ctx.end:
+            return False

Modified: pypy/branch/jit-unroll-loops/pypy/rlib/rsre/test/test_match.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/rlib/rsre/test/test_match.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/rlib/rsre/test/test_match.py	Sat Oct 30 16:41:17 2010
@@ -1,24 +1,49 @@
-import _sre, re, sre_compile
-from pypy.rlib.rsre import rsre_core
+import re
+from pypy.rlib.rsre import rsre_core, rsre_char
 
 
-def get_code(regexp, flags=0, allargs=False):
-    class GotIt(Exception):
-        pass
-    def my_compile(pattern, flags, code, *args):
-        print code
-        raise GotIt(code, flags, args)
-    saved = _sre.compile
-    try:
-        _sre.compile = my_compile
-        try:
-            sre_compile.compile(regexp, flags)
-        except GotIt, e:
-            pass
+def get_hacked_sre_compile(my_compile):
+    """Return a copy of the sre_compile module for which the _sre
+    module is a custom module that has _sre.compile == my_compile
+    and CODESIZE == rsre_char.CODESIZE.
+    """
+    import sre_compile, __builtin__, new
+    sre_hacked = new.module("_sre_hacked")
+    sre_hacked.compile = my_compile
+    sre_hacked.MAGIC = sre_compile.MAGIC
+    sre_hacked.CODESIZE = rsre_char.CODESIZE
+    sre_hacked.getlower = rsre_char.getlower
+    def my_import(name, *args):
+        if name == '_sre':
+            return sre_hacked
         else:
-            raise ValueError("did not reach _sre.compile()!")
+            return default_import(name, *args)
+    src = sre_compile.__file__
+    if src.lower().endswith('.pyc') or src.lower().endswith('.pyo'):
+        src = src[:-1]
+    mod = new.module("sre_compile_hacked")
+    default_import = __import__
+    try:
+        __builtin__.__import__ = my_import
+        execfile(src, mod.__dict__)
     finally:
-        _sre.compile = saved
+        __builtin__.__import__ = default_import
+    return mod
+
+class GotIt(Exception):
+    pass
+def my_compile(pattern, flags, code, *args):
+    print code
+    raise GotIt(code, flags, args)
+sre_compile_hacked = get_hacked_sre_compile(my_compile)
+
+def get_code(regexp, flags=0, allargs=False):
+    try:
+        sre_compile_hacked.compile(regexp, flags)
+    except GotIt, e:
+        pass
+    else:
+        raise ValueError("did not reach _sre.compile()!")
     if allargs:
         return e.args
     else:

Modified: pypy/branch/jit-unroll-loops/pypy/rlib/rstring.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/rlib/rstring.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/rlib/rstring.py	Sat Oct 30 16:41:17 2010
@@ -54,6 +54,7 @@
         self.l = []
 
     def append(self, s):
+        assert isinstance(s, self._type)
         self.l.append(s)
 
     def append_slice(self, s, start, end):
@@ -63,11 +64,16 @@
     def append_multiple_char(self, c, times):
         self.l.append(c * times)
 
+    def getlength(self):
+        return len(self.build())
+
 class StringBuilder(AbstractStringBuilder):
+    _type = str
     def build(self):
         return "".join(self.l)
 
 class UnicodeBuilder(AbstractStringBuilder):
+    _type = unicode
     def build(self):
         return u''.join(self.l)
 
@@ -121,9 +127,12 @@
         assert s_times.nonneg
         return s_None
 
+    def method_getlength(self):
+        return SomeInteger(nonneg=True)
+
     def method_build(self):
         return SomeString()
-    
+
     def rtyper_makerepr(self, rtyper):
         return rtyper.type_system.rbuilder.stringbuilder_repr
 
@@ -146,6 +155,9 @@
         assert s_times.nonneg
         return s_None
 
+    def method_getlength(self):
+        return SomeInteger(nonneg=True)
+
     def method_build(self):
         return SomeUnicodeString()
     

Modified: pypy/branch/jit-unroll-loops/pypy/rlib/test/test_jit.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/rlib/test/test_jit.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/rlib/test/test_jit.py	Sat Oct 30 16:41:17 2010
@@ -1,10 +1,17 @@
 import py
+from pypy.conftest import option
 from pypy.rlib.jit import hint, we_are_jitted, JitDriver, purefunction_promote
-from pypy.rlib.jit import JitHintError
+from pypy.rlib.jit import JitHintError, oopspec
 from pypy.translator.translator import TranslationContext, graphof
 from pypy.rpython.test.tool import BaseRtypingTest, LLRtypeMixin, OORtypeMixin
 from pypy.rpython.lltypesystem import lltype
 
+def test_oopspec():
+    @oopspec('foobar')
+    def fn():
+        pass
+    assert fn.oopspec == 'foobar'
+    
 class BaseTestJIT(BaseRtypingTest):
     def test_hint(self):
         def f():
@@ -104,6 +111,26 @@
             return n
         py.test.raises(JitHintError, self.gengraph, fn, [int])
 
+    def test_green_field(self):
+        def get_printable_location(xfoo):
+            return str(ord(xfoo))   # xfoo must be annotated as a character
+        myjitdriver = JitDriver(greens=['x.foo'], reds=['n', 'x'],
+                                get_printable_location=get_printable_location)
+        class A(object):
+            _immutable_fields_ = ['foo']
+        def fn(n):
+            x = A()
+            x.foo = chr(n)
+            while n > 0:
+                myjitdriver.can_enter_jit(x=x, n=n)
+                myjitdriver.jit_merge_point(x=x, n=n)
+                n -= 1
+            return n
+        t = self.gengraph(fn, [int])[0]
+        if option.view:
+            t.view()
+        # assert did not raise
+
 
 class TestJITLLtype(BaseTestJIT, LLRtypeMixin):
     pass

Modified: pypy/branch/jit-unroll-loops/pypy/rlib/test/test_rbigint.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/rlib/test/test_rbigint.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/rlib/test/test_rbigint.py	Sat Oct 30 16:41:17 2010
@@ -112,6 +112,23 @@
         assert rbigint.fromrarith_int(r_uint(2*sys.maxint+1)).eq(
             rbigint.fromlong(2*sys.maxint+1))
 
+    def test_fromdecimalstr(self):
+        x = rbigint.fromdecimalstr("12345678901234567890523897987")
+        assert x.tolong() == 12345678901234567890523897987L
+        assert x.tobool() is True
+        x = rbigint.fromdecimalstr("+12345678901234567890523897987")
+        assert x.tolong() == 12345678901234567890523897987L
+        assert x.tobool() is True
+        x = rbigint.fromdecimalstr("-12345678901234567890523897987")
+        assert x.tolong() == -12345678901234567890523897987L
+        assert x.tobool() is True
+        x = rbigint.fromdecimalstr("+0")
+        assert x.tolong() == 0
+        assert x.tobool() is False
+        x = rbigint.fromdecimalstr("-0")
+        assert x.tolong() == 0
+        assert x.tobool() is False
+
     def test_add(self):
         x = 123456789123456789000000L
         y = 123858582373821923936744221L
@@ -448,6 +465,35 @@
         assert (rbigint.fromlong(-9**50).ulonglongmask() ==
                 r_ulonglong(-9**50))
 
+    def test_parse_digit_string(self):
+        from pypy.rlib.rbigint import parse_digit_string
+        class Parser:
+            def __init__(self, base, sign, digits):
+                self.base = base
+                self.sign = sign
+                self.next_digit = iter(digits + [-1]).next
+        x = parse_digit_string(Parser(10, 1, [6]))
+        assert x.eq(rbigint.fromint(6))
+        x = parse_digit_string(Parser(10, 1, [6, 2, 3]))
+        assert x.eq(rbigint.fromint(623))
+        x = parse_digit_string(Parser(10, -1, [6, 2, 3]))
+        assert x.eq(rbigint.fromint(-623))
+        x = parse_digit_string(Parser(16, 1, [0xA, 0x4, 0xF]))
+        assert x.eq(rbigint.fromint(0xA4F))
+        num = 0
+        for i in range(36):
+            x = parse_digit_string(Parser(36, 1, range(i)))
+            assert x.eq(rbigint.fromlong(num))
+            num = num * 36 + i
+        x = parse_digit_string(Parser(16, -1, range(15,-1,-1)*99))
+        assert x.eq(rbigint.fromlong(long('-0x' + 'FEDCBA9876543210'*99, 16)))
+        assert x.tobool() is True
+        x = parse_digit_string(Parser(7, 1, [0, 0, 0]))
+        assert x.tobool() is False
+        x = parse_digit_string(Parser(7, -1, [0, 0, 0]))
+        assert x.tobool() is False
+
+
 BASE = 2 ** SHIFT
 
 class TestTranslatable(object):

Modified: pypy/branch/jit-unroll-loops/pypy/rlib/test/test_rdynload.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/rlib/test/test_rdynload.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/rlib/test/test_rdynload.py	Sat Oct 30 16:41:17 2010
@@ -1,15 +1,22 @@
 from pypy.rlib.rdynload import *
-from pypy.rlib.libffi import get_libc_name
+from pypy.rlib.clibffi import get_libc_name
 from pypy.rpython.lltypesystem import rffi, lltype
 import py
 
 class TestDLOperations:
     def test_dlopen(self):
-        py.test.raises(DLOpenError, "dlopen(rffi.str2charp('xxxxxxxxxxxx'))")
-        assert dlopen(rffi.str2charp(get_libc_name()))
+        s = rffi.str2charp('xxxxxxxxxxxx')
+        py.test.raises(DLOpenError, "dlopen(s)")
+        rffi.free_charp(s)
+        #
+        s = rffi.str2charp(get_libc_name())
+        assert dlopen(s)
+        rffi.free_charp(s)
 
     def test_dlsym(self):
-        lib = dlopen(rffi.str2charp(get_libc_name()))
+        s = rffi.str2charp(get_libc_name())
+        lib = dlopen(s)
+        rffi.free_charp(s)
         handle = rffi.cast(lltype.Ptr(lltype.FuncType([lltype.Signed],
                            lltype.Signed)), dlsym(lib, 'abs'))
         assert 1 == handle(1)

Modified: pypy/branch/jit-unroll-loops/pypy/rlib/test/test_rsocket.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/rlib/test/test_rsocket.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/rlib/test/test_rsocket.py	Sat Oct 30 16:41:17 2010
@@ -437,3 +437,31 @@
             foo = self.serv.accept()
         py.test.raises(SocketError, raise_error)
 
+def _test_cond_include(cond):
+    # Test that _rsocket_rffi is importable even on platforms where
+    # AF_PACKET or AF_NETLINK is not defined.
+    import re
+    from pypy.rlib import _rsocket_rffi
+    srcfile = _rsocket_rffi.__file__
+    if srcfile.lower().endswith('c') or srcfile.lower().endswith('o'):
+        srcfile = srcfile[:-1]      # .pyc => .py
+    assert srcfile.lower().endswith('.py')
+    sourcelines = open(srcfile, 'rb').read().splitlines()
+    found = False
+    for i, line in enumerate(sourcelines):
+        line2 = re.sub(r"(\s*COND_HEADER\s*=)",
+                      r"\1'#undef %s\\n'+" % cond,
+                      line)
+        if line2 != line:
+            found = True
+            sourcelines[i] = line2
+    assert found
+    d = {}
+    sourcelines.append('')
+    exec '\n'.join(sourcelines) in d
+
+def test_no_AF_PACKET():
+    _test_cond_include('AF_PACKET')
+
+def test_no_AF_NETLINK():
+    _test_cond_include('AF_NETLINK')

Modified: pypy/branch/jit-unroll-loops/pypy/rlib/test/test_rstring.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/rlib/test/test_rstring.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/rlib/test/test_rstring.py	Sat Oct 30 16:41:17 2010
@@ -29,6 +29,7 @@
     s = StringBuilder()
     s.append("a")
     s.append("abc")
+    assert s.getlength() == len('aabc')
     s.append("a")
     s.append_slice("abc", 1, 2)
     s.append_multiple_char('d', 4)
@@ -39,6 +40,7 @@
     s.append(u'a')
     s.append(u'abc')
     s.append_slice(u'abcdef', 1, 2)
+    assert s.getlength() == len('aabcb')
     s.append_multiple_char('d', 4)
     assert s.build() == 'aabcbdddd'
     assert isinstance(s.build(), unicode)

Modified: pypy/branch/jit-unroll-loops/pypy/rlib/test/test_runicode.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/rlib/test/test_runicode.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/rlib/test/test_runicode.py	Sat Oct 30 16:41:17 2010
@@ -76,7 +76,7 @@
                 assert start == startingpos
                 assert stop == endingpos
                 return u"42424242", stop
-            return "", endingpos
+            return u"", endingpos
         decoder = self.getdecoder(encoding)
         if addstuff:
             s += "some rest in ascii"

Modified: pypy/branch/jit-unroll-loops/pypy/rlib/test/test_rzlib.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/rlib/test/test_rzlib.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/rlib/test/test_rzlib.py	Sat Oct 30 16:41:17 2010
@@ -189,6 +189,8 @@
     assert unused3 == len('more_garbage')
     assert data3 == ''
 
+    rzlib.deflateEnd(stream)
+
 
 def test_decompress_max_length():
     """
@@ -205,6 +207,8 @@
     assert finished2 is True
     assert unused2 == 0
 
+    rzlib.deflateEnd(stream)
+
 
 def test_cornercases():
     """
@@ -215,6 +219,7 @@
     bytes += rzlib.compress(stream, "")
     bytes += rzlib.compress(stream, "", rzlib.Z_FINISH)
     assert zlib.decompress(bytes) == ""
+    rzlib.deflateEnd(stream)
 
     stream = rzlib.inflateInit()
     data, finished, unused = rzlib.decompress(stream, "")
@@ -228,3 +233,4 @@
         assert finished is False
         assert unused > 0
         buf = buf[-unused:]
+    rzlib.deflateEnd(stream)

Modified: pypy/branch/jit-unroll-loops/pypy/rpython/llinterp.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/rpython/llinterp.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/rpython/llinterp.py	Sat Oct 30 16:41:17 2010
@@ -48,8 +48,7 @@
 
     current_interpreter = None
 
-    def __init__(self, typer, tracing=True, exc_data_ptr=None,
-                 malloc_check=True):
+    def __init__(self, typer, tracing=True, exc_data_ptr=None):
         self.bindings = {}
         self.typer = typer
         # 'heap' is module or object that provides malloc, etc for lltype ops
@@ -57,9 +56,7 @@
         self.exc_data_ptr = exc_data_ptr
         self.frame_stack = []
         self.tracer = None
-        self.malloc_check = malloc_check
         self.frame_class = LLFrame
-        self.mallocs = {}
         if tracing:
             self.tracer = Tracer()
 
@@ -163,24 +160,6 @@
             return self.exc_data_ptr
         return None
 
-    def remember_malloc(self, ptr, llframe):
-        # err....
-        self.mallocs[ptr._obj] = llframe
-
-    def remember_free(self, ptr):
-        try:
-            del self.mallocs[ptr._obj]
-        except KeyError:
-            self._rehash_mallocs()
-            del self.mallocs[ptr._obj]
-
-    def _rehash_mallocs(self):
-        # rehashing is needed because some objects' hash may change
-        # when being turned to <C object>
-        items = self.mallocs.items()
-        self.mallocs = {}
-        self.mallocs.update(items)
-
     def _store_exception(self, exc):
         raise PleaseOverwriteStoreException("You just invoked ll2ctypes callback without overwriting _store_exception on llinterpreter")
 
@@ -726,23 +705,23 @@
     def op_malloc(self, obj, flags):
         flavor = flags['flavor']
         zero = flags.get('zero', False)
+        track_allocation = flags.get('track_allocation', True)
         if flavor == "stack":
             result = self.heap.malloc(obj, zero=zero, flavor='raw')
             self.alloca_objects.append(result)
             return result
-        ptr = self.heap.malloc(obj, zero=zero, flavor=flavor)
-        if flavor == 'raw' and self.llinterpreter.malloc_check:
-            self.llinterpreter.remember_malloc(ptr, self)
+        ptr = self.heap.malloc(obj, zero=zero, flavor=flavor,
+                               track_allocation=track_allocation)
         return ptr
 
     def op_malloc_varsize(self, obj, flags, size):
         flavor = flags['flavor']
         zero = flags.get('zero', False)
+        track_allocation = flags.get('track_allocation', True)
         assert flavor in ('gc', 'raw')
         try:
-            ptr = self.heap.malloc(obj, size, zero=zero, flavor=flavor)
-            if flavor == 'raw' and self.llinterpreter.malloc_check:
-                self.llinterpreter.remember_malloc(ptr, self)
+            ptr = self.heap.malloc(obj, size, zero=zero, flavor=flavor,
+                                   track_allocation=track_allocation)
             return ptr
         except MemoryError:
             self.make_llexception()
@@ -759,11 +738,10 @@
         zero = flags.get('zero', False)
         return self.heap.malloc_nonmovable(TYPE, size, zero=zero)
 
-    def op_free(self, obj, flavor):
-        assert isinstance(flavor, str)
-        if flavor == 'raw' and self.llinterpreter.malloc_check:
-            self.llinterpreter.remember_free(obj)
-        self.heap.free(obj, flavor=flavor)
+    def op_free(self, obj, flags):
+        assert flags['flavor'] == 'raw'
+        track_allocation = flags.get('track_allocation', True)
+        self.heap.free(obj, flavor='raw', track_allocation=track_allocation)
 
     def op_shrink_array(self, obj, smallersize):
         return self.heap.shrink_array(obj, smallersize)
@@ -1037,6 +1015,13 @@
     def op_stack_malloc(self, size): # mmh
         raise NotImplementedError("backend only")
 
+    def op_track_alloc_start(self, addr):
+        # we don't do tracking at this level
+        checkadr(addr)
+
+    def op_track_alloc_stop(self, addr):
+        checkadr(addr)
+
     # ____________________________________________________________
     # Overflow-detecting variants
 

Modified: pypy/branch/jit-unroll-loops/pypy/rpython/lltypesystem/ll2ctypes.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/rpython/lltypesystem/ll2ctypes.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/rpython/lltypesystem/ll2ctypes.py	Sat Oct 30 16:41:17 2010
@@ -69,7 +69,7 @@
                 PIECESIZE = 0x08000000
         PIECES = 10
         m = rmmap.mmap(-1, PIECES * PIECESIZE,
-                       rmmap.MAP_PRIVATE|rmmap.MAP_ANONYMOUS,
+                       rmmap.MAP_PRIVATE|rmmap.MAP_ANONYMOUS|rmmap.MAP_NORESERVE,
                        rmmap.PROT_READ|rmmap.PROT_WRITE)
         m.close = lambda : None    # leak instead of giving a spurious
                                    # error at CPython's shutdown
@@ -823,6 +823,8 @@
         except (ValueError, OverflowError):
             for tc in 'HIL':
                 if array(tc).itemsize == array('u').itemsize:
+                    import struct
+                    cobj &= 256 ** struct.calcsize(tc) - 1
                     llobj = array('u', array(tc, (cobj,)).tostring())[0]
                     break
             else:

Modified: pypy/branch/jit-unroll-loops/pypy/rpython/lltypesystem/llarena.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/rpython/lltypesystem/llarena.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/rpython/lltypesystem/llarena.py	Sat Oct 30 16:41:17 2010
@@ -440,7 +440,7 @@
                                    [rffi.INT],
                                    rffi.INT,
                                    sandboxsafe=True, _nowrapper=True)
-    _dev_zero = rffi.str2charp('/dev/zero')   # prebuilt
+    _dev_zero = rffi.str2charp_immortal('/dev/zero')   # prebuilt
 
     def clear_large_memory_chunk(baseaddr, size):
         # on some Unixy platforms, reading from /dev/zero is the fastest way

Modified: pypy/branch/jit-unroll-loops/pypy/rpython/lltypesystem/llmemory.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/rpython/lltypesystem/llmemory.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/rpython/lltypesystem/llmemory.py	Sat Oct 30 16:41:17 2010
@@ -105,11 +105,13 @@
         if (isinstance(self.TYPE, lltype.ContainerType)
             and self.TYPE._gckind == 'gc'):
             assert self.repeat == 1
-            p = lltype.malloc(self.TYPE, flavor='raw', zero=zero)
+            p = lltype.malloc(self.TYPE, flavor='raw', zero=zero,
+                              track_allocation=False)
             return cast_ptr_to_adr(p)
         else:
             T = lltype.FixedSizeArray(self.TYPE, self.repeat)
-            p = lltype.malloc(T, flavor='raw', zero=zero)
+            p = lltype.malloc(T, flavor='raw', zero=zero,
+                              track_allocation=False)
             array_adr = cast_ptr_to_adr(p)
             return array_adr + ArrayItemsOffset(T)
 
@@ -288,7 +290,8 @@
             count = 0
         p = lltype.malloc(parenttype or self.TYPE, count,
                           immortal = self.TYPE._gckind == 'raw',
-                          zero = zero)
+                          zero = zero,
+                          track_allocation = False)
         return cast_ptr_to_adr(p)
 
     def raw_memcopy(self, srcadr, dstadr):

Modified: pypy/branch/jit-unroll-loops/pypy/rpython/lltypesystem/lloperation.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/rpython/lltypesystem/lloperation.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/rpython/lltypesystem/lloperation.py	Sat Oct 30 16:41:17 2010
@@ -403,6 +403,8 @@
     'raw_load':             LLOp(sideeffects=False),
     'raw_store':            LLOp(),
     'stack_malloc':         LLOp(), # mmh
+    'track_alloc_start':    LLOp(),
+    'track_alloc_stop':     LLOp(),
     'adr_add':              LLOp(canfold=True),
     'adr_sub':              LLOp(canfold=True),
     'adr_delta':            LLOp(canfold=True),

Modified: pypy/branch/jit-unroll-loops/pypy/rpython/lltypesystem/lltype.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/rpython/lltypesystem/lltype.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/rpython/lltypesystem/lltype.py	Sat Oct 30 16:41:17 2010
@@ -1,7 +1,3 @@
-import StringIO
-import traceback
-import sys
-
 import py
 from pypy.rlib.rarithmetic import (r_int, r_uint, intmask, r_singlefloat,
                                    r_ulonglong, r_longlong, base_int,
@@ -10,25 +6,13 @@
 from pypy.tool.uid import Hashable
 from pypy.tool.tls import tlsobject
 from pypy.tool.identity_dict import identity_dict
+from pypy.tool import leakfinder
 from types import NoneType
 from sys import maxint
 import weakref
 
 TLS = tlsobject()
 
-# Track allocations to detect memory leaks
-# Don't track 'gc' and immortal mallocs
-TRACK_ALLOCATIONS = False
-ALLOCATED = identity_dict()
-
-def start_tracking_allocations():
-    global TRACK_ALLOCATIONS
-    TRACK_ALLOCATIONS = True
-    ALLOCATED.clear()
-
-def stop_tracking_allocations():
-    global TRACK_ALLOCATIONS
-    TRACK_ALLOCATIONS = False
 
 class _uninitialized(object):
     def __init__(self, TYPE):
@@ -794,6 +778,8 @@
             return llmemory.cast_adr_to_ptr(value, TGT)
     elif TGT == llmemory.Address and isinstance(ORIG, Ptr):
         return llmemory.cast_ptr_to_adr(value)
+    elif TGT == Signed and isinstance(ORIG, Ptr) and ORIG.TO._gckind == 'raw':
+        return llmemory.cast_adr_to_int(llmemory.cast_ptr_to_adr(value), 'symbolic')
     raise TypeError("don't know how to cast from %r to %r" % (ORIG, TGT))
 
 
@@ -1380,41 +1366,21 @@
     __slots__ = ('_TYPE',
                  '_parent_type', '_parent_index', '_keepparent',
                  '_wrparent',
-                 '__weakref__', '_traceback',
-                 '__storage')
+                 '__weakref__',
+                 '_storage')
 
-    def __init__(self, TYPE, track_allocation=None):
+    def __init__(self, TYPE):
         self._wrparent = None
         self._TYPE = TYPE
         self._storage = True    # means "use default storage", as opposed to:
                                 #    None            - container was freed
                                 #    <ctypes object> - using ctypes
                                 #                      (see ll2ctypes.py)
-        if track_allocation is not False and TRACK_ALLOCATIONS:
-            self._traceback = self._get_traceback()
-            ALLOCATED[self] = None
-        else:
-            self._traceback = None
-
-    def _get_traceback(self):
-        frame = sys._getframe().f_back.f_back.f_back.f_back
-        sio = StringIO.StringIO()
-        traceback.print_stack(frame, file=sio)
-        return sio.getvalue()
 
     def _free(self):
         self._check()   # no double-frees
         self._storage = None
 
-    def _storage_get(self):
-        return self.__storage
-
-    def _storage_set(self, value):
-        self.__storage = value
-        if value is not True and self in ALLOCATED:
-            del ALLOCATED[self]
-    _storage = property(_storage_get, _storage_set)
-
     def _was_freed(self):
         if self._storage is None:
             return True
@@ -1493,12 +1459,12 @@
 
     __slots__ = ('_hash_cache_', '_compilation_info')
 
-    def __new__(self, TYPE, n=None, initialization=None, parent=None, parentindex=None, track_allocation=None):
+    def __new__(self, TYPE, n=None, initialization=None, parent=None, parentindex=None):
         my_variety = _struct_variety(TYPE._names)
         return object.__new__(my_variety)
 
-    def __init__(self, TYPE, n=None, initialization=None, parent=None, parentindex=None, track_allocation=None):
-        _parentable.__init__(self, TYPE, track_allocation)
+    def __init__(self, TYPE, n=None, initialization=None, parent=None, parentindex=None):
+        _parentable.__init__(self, TYPE)
         if n is not None and TYPE._arrayfld is None:
             raise TypeError("%r is not variable-sized" % (TYPE,))
         if n is None and TYPE._arrayfld is not None:
@@ -1506,8 +1472,7 @@
         first, FIRSTTYPE = TYPE._first_struct()
         for fld, typ in TYPE._flds.items():
             if fld == TYPE._arrayfld:
-                value = _array(typ, n, initialization=initialization, parent=self, parentindex=fld,
-                               track_allocation=track_allocation)
+                value = _array(typ, n, initialization=initialization, parent=self, parentindex=fld)
             else:
                 value = typ._allocate(initialization=initialization, parent=self, parentindex=fld)
             setattr(self, fld, value)
@@ -1568,12 +1533,12 @@
 
     __slots__ = ('items',)
 
-    def __init__(self, TYPE, n, initialization=None, parent=None, parentindex=None, track_allocation=None):
+    def __init__(self, TYPE, n, initialization=None, parent=None, parentindex=None):
         if not isinstance(n, int):
             raise TypeError, "array length must be an int"
         if n < 0:
             raise ValueError, "negative array length"
-        _parentable.__init__(self, TYPE, track_allocation)
+        _parentable.__init__(self, TYPE)
         try:
             myrange = range(n)
         except OverflowError:
@@ -1640,7 +1605,7 @@
     _cache = weakref.WeakKeyDictionary()  # parentarray -> {subarrays}
 
     def __init__(self, TYPE, parent, baseoffset_or_fieldname):
-        _parentable.__init__(self, TYPE, track_allocation=False)
+        _parentable.__init__(self, TYPE)
         self._setparentstructure(parent, baseoffset_or_fieldname)
         # Keep the parent array alive, we share the same allocation.
         # Don't do it if we are inside a GC object, though -- it's someone
@@ -1648,6 +1613,13 @@
         if typeOf(top_container(parent))._gckind == 'raw':
             self._keepparent = parent
 
+    def __str__(self):
+        parent = self._wrparent()
+        if parent is None:
+            return '_subarray at %s in already freed' % (self._parent_index,)
+        return '_subarray at %r in %s' % (self._parent_index,
+                                          parent._TYPE)
+
     def __repr__(self):
         parent = self._wrparent()
         if parent is None:
@@ -1861,8 +1833,9 @@
         return id(self.value)
 
 
-def malloc(T, n=None, flavor='gc', immortal=False, zero=False):
-    assert flavor != 'cpy'
+def malloc(T, n=None, flavor='gc', immortal=False, zero=False,
+           track_allocation=True):
+    assert flavor in ('gc', 'raw')
     if zero or immortal:
         initialization = 'example'
     elif flavor == 'raw':
@@ -1870,9 +1843,9 @@
     else:
         initialization = 'malloc'
     if isinstance(T, Struct):
-        o = _struct(T, n, initialization=initialization, track_allocation=flavor == "raw" and not immortal)
+        o = _struct(T, n, initialization=initialization)
     elif isinstance(T, Array):
-        o = _array(T, n, initialization=initialization, track_allocation=flavor == "raw" and not immortal)
+        o = _array(T, n, initialization=initialization)
     elif isinstance(T, OpaqueType):
         assert n is None
         o = _opaque(T, initialization=initialization)
@@ -1880,17 +1853,50 @@
         raise TypeError, "malloc for Structs and Arrays only"
     if T._gckind != 'gc' and not immortal and flavor.startswith('gc'):
         raise TypeError, "gc flavor malloc of a non-GC non-immortal structure"
+    if flavor == "raw" and not immortal and track_allocation:
+        leakfinder.remember_malloc(o, framedepth=2)
     solid = immortal or not flavor.startswith('gc') # immortal or non-gc case
     return _ptr(Ptr(T), o, solid)
 
-def free(p, flavor):
+def free(p, flavor, track_allocation=True):
     if flavor.startswith('gc'):
         raise TypeError, "gc flavor free"
     T = typeOf(p)
     if not isinstance(T, Ptr) or p._togckind() != 'raw':
         raise TypeError, "free(): only for pointers to non-gc containers"
+    if track_allocation:
+        leakfinder.remember_free(p._obj0)
     p._obj0._free()
 
+def _make_scoped_allocator(T):
+    class ScopedAlloc:
+        def __init__(self, n=None, zero=False):
+            if n is None:
+                self.buf = malloc(T, flavor='raw', zero=zero)
+            else:
+                self.buf = malloc(T, n, flavor='raw', zero=zero)
+
+        def __enter__(self):
+            return self.buf
+
+        def __exit__(self, *args):
+            free(self.buf, flavor='raw')
+
+    ScopedAlloc.__name__ = 'ScopedAlloc_%s' % (T,)
+    return ScopedAlloc
+_make_scoped_allocator._annspecialcase_ = 'specialize:memo'
+
+def scoped_alloc(T, n=None, zero=False):
+    """Returns a context manager which handles allocation and
+    deallocation of temporary memory. Use it in a with statement::
+
+        with scoped_alloc(Array(Signed), 1) as array:
+            ...use array...
+        ...it's freed now.
+    """
+    return _make_scoped_allocator(T)(n=n, zero=zero)
+scoped_alloc._annspecialcase_ = 'specialize:arg(0)'
+
 def functionptr(TYPE, name, **attrs):
     if not isinstance(TYPE, FuncType):
         raise TypeError, "functionptr() for FuncTypes only"

Modified: pypy/branch/jit-unroll-loops/pypy/rpython/lltypesystem/rbuilder.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/rpython/lltypesystem/rbuilder.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/rpython/lltypesystem/rbuilder.py	Sat Oct 30 16:41:17 2010
@@ -100,6 +100,10 @@
         ll_builder.used = used
 
     @staticmethod
+    def ll_getlength(ll_builder):
+        return ll_builder.used
+
+    @staticmethod
     def ll_build(ll_builder):
         final_size = ll_builder.used
         assert final_size >= 0

Modified: pypy/branch/jit-unroll-loops/pypy/rpython/lltypesystem/rclass.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/rpython/lltypesystem/rclass.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/rpython/lltypesystem/rclass.py	Sat Oct 30 16:41:17 2010
@@ -329,16 +329,33 @@
             fields['__class__'] = 'typeptr', get_type_repr(self.rtyper)
         else:
             # instance attributes
-            if llfields is None:
-                llfields = []
             attrs = self.classdef.attrs.items()
             attrs.sort()
+            myllfields = []
             for name, attrdef in attrs:
                 if not attrdef.readonly:
                     r = self.rtyper.getrepr(attrdef.s_value)
                     mangled_name = 'inst_' + name
                     fields[name] = mangled_name, r
-                    llfields.append((mangled_name, r.lowleveltype))
+                    myllfields.append((mangled_name, r.lowleveltype))
+
+            # Sort the instance attributes by decreasing "likely size",
+            # as reported by rffi.sizeof(), to minimize padding holes in C.
+            # Fields of the same size are sorted by name (by attrs.sort()
+            # above) just to minimize randomness.
+            def keysize((_, T)):
+                if T is lltype.Void:
+                    return None
+                from pypy.rpython.lltypesystem.rffi import sizeof
+                try:
+                    return -sizeof(T)
+                except StandardError:
+                    return None
+            myllfields.sort(key = keysize)
+            if llfields is None:
+                llfields = myllfields
+            else:
+                llfields = llfields + myllfields
 
             self.rbase = getinstancerepr(self.rtyper, self.classdef.basedef,
                                          self.gcflavor)
@@ -403,7 +420,7 @@
         return cast_pointer(self.lowleveltype, result)
 
     def create_instance(self):
-        return malloc(self.object_type, flavor=self.gcflavor)
+        return malloc(self.object_type, flavor=self.gcflavor, immortal=True)
 
     def initialize_prebuilt_data(self, value, classdef, result):
         if self.classdef is not None:

Modified: pypy/branch/jit-unroll-loops/pypy/rpython/lltypesystem/rdict.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/rpython/lltypesystem/rdict.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/rpython/lltypesystem/rdict.py	Sat Oct 30 16:41:17 2010
@@ -306,6 +306,13 @@
         hop.exception_cannot_occur()
         return hop.gendirectcall(ll_clear, v_dict)
 
+    def rtype_method_popitem(self, hop):
+        v_dict, = hop.inputargs(self)
+        r_tuple = hop.r_result
+        cTUPLE = hop.inputconst(lltype.Void, r_tuple.lowleveltype)
+        hop.exception_is_here()
+        return hop.gendirectcall(ll_popitem, cTUPLE, v_dict)
+
 class __extend__(pairtype(DictRepr, rmodel.Repr)): 
 
     def rtype_getitem((r_dict, r_key), hop):
@@ -465,6 +472,10 @@
     i = ll_dict_lookup(d, key, d.keyhash(key))
     if not d.entries.valid(i):
         raise KeyError
+    _ll_dict_del(d, i)
+ll_dict_delitem.oopspec = 'dict.delitem(d, key)'
+
+def _ll_dict_del(d, i):
     d.entries.mark_deleted(i)
     d.num_items -= 1
     # clear the key and the value if they are GC pointers
@@ -481,7 +492,6 @@
     num_entries = len(d.entries)
     if num_entries > DICT_INITSIZE and d.num_items < num_entries / 4:
         ll_dict_resize(d)
-ll_dict_delitem.oopspec = 'dict.delitem(d, key)'
 
 def ll_dict_resize(d):
     old_entries = d.entries
@@ -810,3 +820,26 @@
     i = ll_dict_lookup(d, key, d.keyhash(key))
     return d.entries.valid(i)
 ll_contains.oopspec = 'dict.contains(d, key)'
+
+POPITEMINDEX = lltype.Struct('PopItemIndex', ('nextindex', lltype.Signed))
+global_popitem_index = lltype.malloc(POPITEMINDEX, zero=True, immortal=True)
+
+def ll_popitem(ELEM, dic):
+    entries = dic.entries
+    dmask = len(entries) - 1
+    base = global_popitem_index.nextindex
+    counter = 0
+    while counter <= dmask:
+        i = (base + counter) & dmask
+        counter += 1
+        if entries.valid(i):
+            break
+    else:
+        raise KeyError
+    global_popitem_index.nextindex += counter
+    entry = entries[i]
+    r = lltype.malloc(ELEM.TO)
+    r.item0 = recast(ELEM.TO.item0, entry.key)
+    r.item1 = recast(ELEM.TO.item1, entry.value)
+    _ll_dict_del(dic, i)
+    return r

Modified: pypy/branch/jit-unroll-loops/pypy/rpython/lltypesystem/rffi.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/rpython/lltypesystem/rffi.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/rpython/lltypesystem/rffi.py	Sat Oct 30 16:41:17 2010
@@ -607,6 +607,15 @@
         return array
     str2charp._annenforceargs_ = [strtype]
 
+    def str2charp_immortal(s):
+        "NOT_RPYTHON"
+        array = lltype.malloc(TYPEP.TO, len(s) + 1, flavor='raw',
+                              immortal=True)
+        for i in range(len(s)):
+            array[i] = s[i]
+        array[len(s)] = lastchar
+        return array
+
     def free_charp(cp):
         lltype.free(cp, flavor='raw')
 
@@ -644,10 +653,18 @@
         """
         Either free a non-moving buffer or keep the original storage alive.
         """
-        if rgc.can_move(data):
+        # We cannot rely on rgc.can_move(data) here, because its result
+        # might have changed since get_nonmovingbuffer().  Instead we check
+        # if 'buf' points inside 'data'.  This is only possible if we
+        # followed the 2nd case in get_nonmovingbuffer(); in the first case,
+        # 'buf' points to its own raw-malloced memory.
+        data = llstrtype(data)
+        data_start = cast_ptr_to_adr(data) + \
+            offsetof(STRTYPE, 'chars') + itemoffsetof(STRTYPE.chars, 0)
+        followed_2nd_path = (buf == cast(TYPEP, data_start))
+        keepalive_until_here(data)
+        if not followed_2nd_path:
             lltype.free(buf, flavor='raw')
-        else:
-            keepalive_until_here(data)
 
     # int -> (char*, str)
     def alloc_buffer(count):
@@ -717,19 +734,19 @@
         l = [cp[i] for i in range(size)]
         return emptystr.join(l)
 
-    return (str2charp, free_charp, charp2str,
+    return (str2charp, str2charp_immortal, free_charp, charp2str,
             get_nonmovingbuffer, free_nonmovingbuffer,
             alloc_buffer, str_from_buffer, keep_buffer_alive_until_here,
             charp2strn, charpsize2str,
             )
 
-(str2charp, free_charp, charp2str,
+(str2charp, str2charp_immortal, free_charp, charp2str,
  get_nonmovingbuffer, free_nonmovingbuffer,
  alloc_buffer, str_from_buffer, keep_buffer_alive_until_here,
  charp2strn, charpsize2str,
  ) = make_string_mappings(str)
 
-(unicode2wcharp, free_wcharp, wcharp2unicode,
+(unicode2wcharp, unicode2wcharp_immortal, free_wcharp, wcharp2unicode,
  get_nonmoving_unicodebuffer, free_nonmoving_unicodebuffer,
  alloc_unicodebuffer, unicode_from_buffer, keep_unicodebuffer_alive_until_here,
  wcharp2unicoden, wcharpsize2unicode,
@@ -916,3 +933,11 @@
     """
     return cast(lltype.Signed, getattr(pdst, fieldname))
 getintfield._annspecialcase_ = 'specialize:ll_and_arg(1)'
+
+class scoped_str2charp:
+    def __init__(self, value):
+        self.buf = str2charp(value)
+    def __enter__(self):
+        return self.buf
+    def __exit__(self, *args):
+        free_charp(self.buf)

Modified: pypy/branch/jit-unroll-loops/pypy/rpython/lltypesystem/test/test_ll2ctypes.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/rpython/lltypesystem/test/test_ll2ctypes.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/rpython/lltypesystem/test/test_ll2ctypes.py	Sat Oct 30 16:41:17 2010
@@ -765,6 +765,7 @@
         assert abs(float(b[1]) - 1.1) < 1E-6
         assert isinstance(b[2], rffi.r_singlefloat)
         assert abs(float(b[2]) - 2.2) < 1E-6
+        lltype.free(a, flavor='raw')
 
     def test_different_signatures(self):
         if sys.platform=='win32':
@@ -879,6 +880,7 @@
         qsort(rffi.cast(rffi.VOIDP, a), 5, rffi.sizeof(rffi.INT), compare)
         for i in range(5):
             assert a[i] == i + 1
+        lltype.free(a, flavor='raw')
 
     def test_array_type_bug(self):
         A = lltype.Array(lltype.Signed)

Modified: pypy/branch/jit-unroll-loops/pypy/rpython/lltypesystem/test/test_llmemory.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/rpython/lltypesystem/test/test_llmemory.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/rpython/lltypesystem/test/test_llmemory.py	Sat Oct 30 16:41:17 2010
@@ -324,12 +324,14 @@
     p_t = lltype.malloc(T)
     assert p_t.s == lltype.nullptr(S)
     # raw malloc does not
-    p_raw_t = lltype.malloc(T, flavor="raw")
-    py.test.raises(lltype.UninitializedMemoryAccess, "p_raw_t.s")
+    U = lltype.Struct("U", ('x', lltype.Signed))
+    p_raw_t = lltype.malloc(U, flavor="raw")
+    py.test.raises(lltype.UninitializedMemoryAccess, "p_raw_t.x")
+    lltype.free(p_raw_t, flavor="raw")
     # this sort of raw_malloc too
-    p_raw_t = cast_adr_to_ptr(raw_malloc(sizeof(T)), lltype.Ptr(T))
-    py.test.raises(lltype.UninitializedMemoryAccess, "p_raw_t.s")
-    
+    p_raw_t = cast_adr_to_ptr(raw_malloc(sizeof(U)), lltype.Ptr(U))
+    py.test.raises(lltype.UninitializedMemoryAccess, "p_raw_t.x")
+
 
 def test_raw_malloc_signed_bunch():
     adr = raw_malloc(sizeof(lltype.Signed) * 50)
@@ -601,7 +603,8 @@
     a = lltype.malloc(A, flavor='raw')
     src = cast_ptr_to_adr(a) + itemoffsetof(A, 0)
     raw_memclear(src, sizeof(lltype.Signed) * 0)
-    
+    lltype.free(a, flavor="raw")
+
 def test_nonneg():
     S1 = lltype.GcStruct('S1', ('x', lltype.Float))
     A1 = lltype.GcArray(lltype.Float)

Modified: pypy/branch/jit-unroll-loops/pypy/rpython/lltypesystem/test/test_lltype.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/rpython/lltypesystem/test/test_lltype.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/rpython/lltypesystem/test/test_lltype.py	Sat Oct 30 16:41:17 2010
@@ -1,7 +1,9 @@
+from __future__ import with_statement
 import py
 from pypy.rpython.lltypesystem.lltype import *
 from pypy.rpython.lltypesystem import lltype, rffi
 from pypy.tool.identity_dict import identity_dict
+from pypy.tool import leakfinder
 
 def isweak(p, T):
     try:
@@ -804,22 +806,20 @@
 
 
 class TestTrackAllocation:
-    def setup_method(self, func):
-        start_tracking_allocations()
-
-    def teardown_method(self, func):
-        assert not lltype.ALLOCATED, "Memory was not correctly freed"
-        stop_tracking_allocations()
+    def test_automatic_tracking(self):
+        # calls to start_tracking_allocations/stop_tracking_allocations
+        # should occur automatically from pypy/conftest.py.  Check that.
+        assert leakfinder.TRACK_ALLOCATIONS
 
     def test_track_allocation(self):
         """A malloc'd buffer fills the ALLOCATED dictionary"""
-        assert lltype.TRACK_ALLOCATIONS
-        assert not lltype.ALLOCATED
+        assert leakfinder.TRACK_ALLOCATIONS
+        assert not leakfinder.ALLOCATED
         buf = malloc(Array(Signed), 1, flavor="raw")
-        assert len(lltype.ALLOCATED) == 1
-        assert lltype.ALLOCATED.keys() == [buf._obj]
+        assert len(leakfinder.ALLOCATED) == 1
+        assert leakfinder.ALLOCATED.keys() == [buf._obj]
         free(buf, flavor="raw")
-        assert not lltype.ALLOCATED
+        assert not leakfinder.ALLOCATED
 
     def test_str_from_buffer(self):
         """gc-managed memory does not need to be freed"""
@@ -828,16 +828,28 @@
         for i in range(size): raw_buf[i] = 'a'
         rstr = rffi.str_from_buffer(raw_buf, gc_buf, size, size)
         rffi.keep_buffer_alive_until_here(raw_buf, gc_buf)
-        assert not lltype.ALLOCATED
+        assert not leakfinder.ALLOCATED
 
     def test_leak_traceback(self):
         """Test info stored for allocated items"""
         buf = malloc(Array(Signed), 1, flavor="raw")
-        traceback = lltype.ALLOCATED.keys()[0]._traceback
+        traceback = leakfinder.ALLOCATED.values()[0]
         lines = traceback.splitlines()
         assert 'malloc(' in lines[-1] and 'flavor="raw")' in lines[-1]
 
-        # XXX The traceback should not be too long
+        # The traceback should not be too long
         print traceback
 
         free(buf, flavor="raw")
+
+    def test_no_tracking(self):
+        p1 = malloc(Array(Signed), 1, flavor='raw', track_allocation=False)
+        p2 = malloc(Array(Signed), 1, flavor='raw', track_allocation=False)
+        free(p2, flavor='raw', track_allocation=False)
+        # p1 is not freed
+
+    def test_scoped_allocator(self):
+        with scoped_alloc(Array(Signed), 1) as array:
+            array[0] = -42
+            x = array[0]
+        assert x == -42

Modified: pypy/branch/jit-unroll-loops/pypy/rpython/lltypesystem/test/test_rffi.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/rpython/lltypesystem/test/test_rffi.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/rpython/lltypesystem/test/test_rffi.py	Sat Oct 30 16:41:17 2010
@@ -9,7 +9,7 @@
 from pypy.rpython.lltypesystem.rstr import STR
 from pypy.rpython.lltypesystem import lltype
 from pypy.tool.udir import udir
-from pypy.rpython.test.test_llinterp import interpret, MallocMismatch
+from pypy.rpython.test.test_llinterp import interpret
 from pypy.rpython.test.tool import BaseRtypingTest, LLRtypeMixin, OORtypeMixin
 from pypy.annotation.annrpython import RPythonAnnotator
 from pypy.rpython.rtyper import RPythonTyper
@@ -787,3 +787,10 @@
     mixann.getgraph(f2, [], s_None)
     mixann.finish()
 
+def test_force_cast_unichar():
+    x = cast(lltype.UniChar, -1)
+    assert isinstance(x, unicode)
+    if sys.maxunicode == 65535:
+        assert cast(LONG, x) == 65535
+    else:
+        assert cast(LONG, cast(INT, x)) == -1

Modified: pypy/branch/jit-unroll-loops/pypy/rpython/memory/gc/base.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/rpython/memory/gc/base.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/rpython/memory/gc/base.py	Sat Oct 30 16:41:17 2010
@@ -20,12 +20,15 @@
     prebuilt_gc_objects_are_static_roots = True
     object_minimal_size = 0
 
-    def __init__(self, config, chunk_size=DEFAULT_CHUNK_SIZE):
+    def __init__(self, config, chunk_size=DEFAULT_CHUNK_SIZE,
+                 translated_to_c=True):
         self.gcheaderbuilder = GCHeaderBuilder(self.HDR)
         self.AddressStack = get_address_stack(chunk_size)
         self.AddressDeque = get_address_deque(chunk_size)
         self.AddressDict = AddressDict
         self.config = config
+        assert isinstance(translated_to_c, bool)
+        self.translated_to_c = translated_to_c
 
     def setup(self):
         # all runtime mutable values' setup should happen here
@@ -79,7 +82,7 @@
     def set_root_walker(self, root_walker):
         self.root_walker = root_walker
 
-    def write_barrier(self, addr_struct):
+    def write_barrier(self, newvalue, addr_struct):
         pass
 
     def statistics(self, index):

Modified: pypy/branch/jit-unroll-loops/pypy/rpython/memory/gc/generation.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/rpython/memory/gc/generation.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/rpython/memory/gc/generation.py	Sat Oct 30 16:41:17 2010
@@ -5,7 +5,6 @@
 from pypy.rpython.memory.gc.base import read_from_env
 from pypy.rpython.lltypesystem.llmemory import NULL, raw_malloc_usage
 from pypy.rpython.lltypesystem import lltype, llmemory, llarena
-from pypy.rpython.memory.support import DEFAULT_CHUNK_SIZE
 from pypy.rlib.objectmodel import free_non_gc_object
 from pypy.rlib.debug import ll_assert
 from pypy.rlib.debug import debug_print, debug_start, debug_stop
@@ -49,15 +48,17 @@
 
     nursery_hash_base = -1
 
-    def __init__(self, config, chunk_size=DEFAULT_CHUNK_SIZE,
+    def __init__(self, config,
                  nursery_size=32*WORD,
                  min_nursery_size=32*WORD,
                  auto_nursery_size=False,
                  space_size=1024*WORD,
-                 max_space_size=sys.maxint//2+1):
-        SemiSpaceGC.__init__(self, config, chunk_size = chunk_size,
+                 max_space_size=sys.maxint//2+1,
+                 **kwds):
+        SemiSpaceGC.__init__(self, config,
                              space_size = space_size,
-                             max_space_size = max_space_size)
+                             max_space_size = max_space_size,
+                             **kwds)
         assert min_nursery_size <= nursery_size <= space_size // 2
         self.initial_nursery_size = nursery_size
         self.auto_nursery_size = auto_nursery_size
@@ -157,6 +158,14 @@
                   "odd-valued (i.e. tagged) pointer unexpected here")
         return self.nursery <= addr < self.nursery_top
 
+    def appears_to_be_in_nursery(self, addr):
+        # same as is_in_nursery(), but may return True accidentally if
+        # 'addr' is a tagged pointer with just the wrong value.
+        if not self.translated_to_c:
+            if not self.is_valid_gc_object(addr):
+                return False
+        return self.nursery <= addr < self.nursery_top
+
     def malloc_fixedsize_clear(self, typeid, size, can_collect,
                                has_finalizer=False, contains_weakptr=False):
         if (has_finalizer or not can_collect or
@@ -326,7 +335,7 @@
         addr = pointer.address[0]
         newaddr = self.copy(addr)
         pointer.address[0] = newaddr
-        self.write_into_last_generation_obj(obj)
+        self.write_into_last_generation_obj(obj, newaddr)
 
     # ____________________________________________________________
     # Implementation of nursery-only collections
@@ -457,9 +466,9 @@
     #  "if addr_struct.int0 & JIT_WB_IF_FLAG: remember_young_pointer()")
     JIT_WB_IF_FLAG = GCFLAG_NO_YOUNG_PTRS
 
-    def write_barrier(self, addr_struct):
-        if self.header(addr_struct).tid & GCFLAG_NO_YOUNG_PTRS:
-            self.remember_young_pointer(addr_struct)
+    def write_barrier(self, newvalue, addr_struct):
+         if self.header(addr_struct).tid & GCFLAG_NO_YOUNG_PTRS:
+            self.remember_young_pointer(addr_struct, newvalue)
 
     def _setup_wb(self):
         DEBUG = self.DEBUG
@@ -470,23 +479,33 @@
         # For x86, there is also an extra requirement: when the JIT calls
         # remember_young_pointer(), it assumes that it will not touch the SSE
         # registers, so it does not save and restore them (that's a *hack*!).
-        def remember_young_pointer(addr_struct):
+        def remember_young_pointer(addr_struct, addr):
             #llop.debug_print(lltype.Void, "\tremember_young_pointer",
             #                 addr_struct, "<-", addr)
             if DEBUG:
                 ll_assert(not self.is_in_nursery(addr_struct),
                           "nursery object with GCFLAG_NO_YOUNG_PTRS")
-            self.old_objects_pointing_to_young.append(addr_struct)
-            self.header(addr_struct).tid &= ~GCFLAG_NO_YOUNG_PTRS
-            self.write_into_last_generation_obj(addr_struct)
+            #
+            # What is important in this function is that it *must*
+            # clear the flag GCFLAG_NO_YOUNG_PTRS from 'addr_struct'
+            # if 'addr' is in the nursery.  It is ok if, accidentally,
+            # it also clears the flag in some more rare cases, like
+            # 'addr' being a tagged pointer whose value happens to be
+            # a large integer that fools is_in_nursery().
+            if self.appears_to_be_in_nursery(addr):
+                self.old_objects_pointing_to_young.append(addr_struct)
+                self.header(addr_struct).tid &= ~GCFLAG_NO_YOUNG_PTRS
+            self.write_into_last_generation_obj(addr_struct, addr)
         remember_young_pointer._dont_inline_ = True
         self.remember_young_pointer = remember_young_pointer
 
-    def write_into_last_generation_obj(self, addr_struct):
+    def write_into_last_generation_obj(self, addr_struct, addr):
         objhdr = self.header(addr_struct)
         if objhdr.tid & GCFLAG_NO_HEAP_PTRS:
-            objhdr.tid &= ~GCFLAG_NO_HEAP_PTRS
-            self.last_generation_root_objects.append(addr_struct)
+            if (self.is_valid_gc_object(addr) and
+                    not self.is_last_generation(addr)):
+                objhdr.tid &= ~GCFLAG_NO_HEAP_PTRS
+                self.last_generation_root_objects.append(addr_struct)
     write_into_last_generation_obj._always_inline_ = True
 
     def assume_young_pointers(self, addr_struct):

Modified: pypy/branch/jit-unroll-loops/pypy/rpython/memory/gc/markcompact.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/rpython/memory/gc/markcompact.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/rpython/memory/gc/markcompact.py	Sat Oct 30 16:41:17 2010
@@ -2,7 +2,6 @@
 from pypy.rpython.memory.gc.base import MovingGCBase, read_from_env
 from pypy.rlib.debug import ll_assert, have_debug_prints
 from pypy.rlib.debug import debug_print, debug_start, debug_stop
-from pypy.rpython.memory.support import DEFAULT_CHUNK_SIZE
 from pypy.rpython.memory.support import get_address_stack, get_address_deque
 from pypy.rpython.memory.support import AddressDict
 from pypy.rpython.lltypesystem.llmemory import NULL, raw_malloc_usage
@@ -86,9 +85,9 @@
     free = NULL
     next_collect_after = -1
 
-    def __init__(self, config, chunk_size=DEFAULT_CHUNK_SIZE, space_size=4096,
-                 min_next_collect_after=128):
-        MovingGCBase.__init__(self, config, chunk_size)
+    def __init__(self, config, space_size=4096,
+                 min_next_collect_after=128, **kwds):
+        MovingGCBase.__init__(self, config, **kwds)
         self.space_size = space_size
         self.min_next_collect_after = min_next_collect_after
 

Modified: pypy/branch/jit-unroll-loops/pypy/rpython/memory/gc/marksweep.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/rpython/memory/gc/marksweep.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/rpython/memory/gc/marksweep.py	Sat Oct 30 16:41:17 2010
@@ -1,7 +1,6 @@
 from pypy.rpython.lltypesystem.llmemory import raw_malloc, raw_free
 from pypy.rpython.lltypesystem.llmemory import raw_memcopy, raw_memclear
 from pypy.rpython.lltypesystem.llmemory import NULL, raw_malloc_usage
-from pypy.rpython.memory.support import DEFAULT_CHUNK_SIZE
 from pypy.rpython.memory.support import get_address_stack
 from pypy.rpython.memory.gcheader import GCHeaderBuilder
 from pypy.rpython.lltypesystem import lltype, llmemory, rffi, llgroup
@@ -48,9 +47,9 @@
     # translating to a real backend.
     TRANSLATION_PARAMS = {'start_heap_size': 8*1024*1024} # XXX adjust
 
-    def __init__(self, config, chunk_size=DEFAULT_CHUNK_SIZE, start_heap_size=4096):
+    def __init__(self, config, start_heap_size=4096, **kwds):
         self.param_start_heap_size = start_heap_size
-        GCBase.__init__(self, config, chunk_size)
+        GCBase.__init__(self, config, **kwds)
 
     def setup(self):
         GCBase.setup(self)
@@ -714,8 +713,8 @@
     _alloc_flavor_ = "raw"
     COLLECT_EVERY = 2000
 
-    def __init__(self, chunk_size=DEFAULT_CHUNK_SIZE, start_heap_size=4096):
-        MarkSweepGC.__init__(self, chunk_size, start_heap_size)
+    def __init__(self, config, **kwds):
+        MarkSweepGC.__init__(self, config, **kwds)
         self.count_mallocs = 0
 
     def maybe_collect(self):

Modified: pypy/branch/jit-unroll-loops/pypy/rpython/memory/gc/minimark.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/rpython/memory/gc/minimark.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/rpython/memory/gc/minimark.py	Sat Oct 30 16:41:17 2010
@@ -4,7 +4,6 @@
 from pypy.rpython.lltypesystem.llmemory import raw_malloc_usage
 from pypy.rpython.memory.gc.base import GCBase, MovingGCBase
 from pypy.rpython.memory.gc import minimarkpage, base, generation
-from pypy.rpython.memory.support import DEFAULT_CHUNK_SIZE
 from pypy.rlib.rarithmetic import ovfcheck, LONG_BIT, intmask, r_uint
 from pypy.rlib.rarithmetic import LONG_BIT_SHIFT
 from pypy.rlib.debug import ll_assert, debug_print, debug_start, debug_stop
@@ -140,7 +139,7 @@
         "large_object_gcptrs": 8250*WORD,
         }
 
-    def __init__(self, config, chunk_size=DEFAULT_CHUNK_SIZE,
+    def __init__(self, config,
                  read_from_env=False,
                  nursery_size=32*WORD,
                  page_size=16*WORD,
@@ -150,8 +149,9 @@
                  card_page_indices=0,
                  large_object=8*WORD,
                  large_object_gcptrs=10*WORD,
-                 ArenaCollectionClass=None):
-        MovingGCBase.__init__(self, config, chunk_size)
+                 ArenaCollectionClass=None,
+                 **kwds):
+        MovingGCBase.__init__(self, config, **kwds)
         assert small_request_threshold % WORD == 0
         self.read_from_env = read_from_env
         self.nursery_size = nursery_size
@@ -636,6 +636,14 @@
                   "odd-valued (i.e. tagged) pointer unexpected here")
         return self.nursery <= addr < self.nursery_top
 
+    def appears_to_be_in_nursery(self, addr):
+        # same as is_in_nursery(), but may return True accidentally if
+        # 'addr' is a tagged pointer with just the wrong value.
+        if not self.translated_to_c:
+            if not self.is_valid_gc_object(addr):
+                return False
+        return self.nursery <= addr < self.nursery_top
+
     def is_forwarded(self, obj):
         """Returns True if the nursery obj is marked as forwarded.
         Implemented a bit obscurely by checking an unrelated flag
@@ -726,16 +734,16 @@
     def JIT_max_size_of_young_obj(cls):
         return cls.TRANSLATION_PARAMS['large_object']
 
-    def write_barrier(self, addr_struct):
+    def write_barrier(self, newvalue, addr_struct):
         if self.header(addr_struct).tid & GCFLAG_NO_YOUNG_PTRS:
-            self.remember_young_pointer(addr_struct)
+            self.remember_young_pointer(addr_struct, newvalue)
 
-    def write_barrier_from_array(self, addr_array, index):
+    def write_barrier_from_array(self, newvalue, addr_array, index):
         if self.header(addr_array).tid & GCFLAG_NO_YOUNG_PTRS:
             if self.card_page_indices > 0:     # <- constant-folded
                 self.remember_young_pointer_from_array(addr_array, index)
             else:
-                self.remember_young_pointer(addr_array)
+                self.remember_young_pointer(addr_array, newvalue)
 
     def _init_writebarrier_logic(self):
         DEBUG = self.DEBUG
@@ -746,27 +754,28 @@
         # For x86, there is also an extra requirement: when the JIT calls
         # remember_young_pointer(), it assumes that it will not touch the SSE
         # registers, so it does not save and restore them (that's a *hack*!).
-        def remember_young_pointer(addr_struct):
+        def remember_young_pointer(addr_struct, newvalue):
             # 'addr_struct' is the address of the object in which we write.
+            # 'newvalue' is the address that we are going to write in there.
             if DEBUG:
                 ll_assert(not self.is_in_nursery(addr_struct),
                           "nursery object with GCFLAG_NO_YOUNG_PTRS")
             #
-            # We assume that what we are writing is a pointer to the nursery
-            # (and don't care for the fact that this new pointer may not
-            # actually point to the nursery, which seems ok).  What we need is
+            # If it seems that what we are writing is a pointer to the nursery
+            # (as checked with appears_to_be_in_nursery()), then we need
             # to remove the flag GCFLAG_NO_YOUNG_PTRS and add the old object
             # to the list 'old_objects_pointing_to_young'.  We know that
             # 'addr_struct' cannot be in the nursery, because nursery objects
             # never have the flag GCFLAG_NO_YOUNG_PTRS to start with.
-            self.old_objects_pointing_to_young.append(addr_struct)
             objhdr = self.header(addr_struct)
-            objhdr.tid &= ~GCFLAG_NO_YOUNG_PTRS
+            if self.appears_to_be_in_nursery(newvalue):
+                self.old_objects_pointing_to_young.append(addr_struct)
+                objhdr.tid &= ~GCFLAG_NO_YOUNG_PTRS
             #
             # Second part: if 'addr_struct' is actually a prebuilt GC
             # object and it's the first time we see a write to it, we
             # add it to the list 'prebuilt_root_objects'.  Note that we
-            # do it even in the (rare?) case of 'addr' being another
+            # do it even in the (rare?) case of 'addr' being NULL or another
             # prebuilt object, to simplify code.
             if objhdr.tid & GCFLAG_NO_HEAP_PTRS:
                 objhdr.tid &= ~GCFLAG_NO_HEAP_PTRS
@@ -780,16 +789,24 @@
 
 
     def _init_writebarrier_with_card_marker(self):
+        DEBUG = self.DEBUG
         def remember_young_pointer_from_array(addr_array, index):
             # 'addr_array' is the address of the object in which we write,
             # which must have an array part;  'index' is the index of the
             # item that is (or contains) the pointer that we write.
+            if DEBUG:
+                ll_assert(not self.is_in_nursery(addr_array),
+                          "nursery array with GCFLAG_NO_YOUNG_PTRS")
             objhdr = self.header(addr_array)
             if objhdr.tid & GCFLAG_HAS_CARDS == 0:
                 #
-                # no cards, use default logic.  The 'nocard_logic()' is just
-                # 'remember_young_pointer()', but forced to be inlined here.
-                nocard_logic(addr_array)
+                # no cards, use default logic.  Mostly copied from above.
+                self.old_objects_pointing_to_young.append(addr_array)
+                objhdr = self.header(addr_array)
+                objhdr.tid &= ~GCFLAG_NO_YOUNG_PTRS
+                if objhdr.tid & GCFLAG_NO_HEAP_PTRS:
+                    objhdr.tid &= ~GCFLAG_NO_HEAP_PTRS
+                    self.prebuilt_root_objects.append(addr_array)
                 return
             #
             # 'addr_array' is a raw_malloc'ed array with card markers
@@ -807,17 +824,15 @@
                 return
             #
             # We set the flag (even if the newly written address does not
-            # actually point to the nursery -- like remember_young_pointer()).
+            # actually point to the nursery, which seems to be ok -- actually
+            # it seems more important that remember_young_pointer_from_array()
+            # does not take 3 arguments).
             addr_byte.char[0] = chr(byte | bitmask)
             #
             if objhdr.tid & GCFLAG_CARDS_SET == 0:
                 self.old_objects_with_cards_set.append(addr_array)
                 objhdr.tid |= GCFLAG_CARDS_SET
 
-        nocard_logic = func_with_new_name(self.remember_young_pointer,
-                                          'remember_young_pointer_nocard')
-        del nocard_logic._dont_inline_
-        nocard_logic._always_inline_ = True
         remember_young_pointer_from_array._dont_inline_ = True
         self.remember_young_pointer_from_array = (
             remember_young_pointer_from_array)

Modified: pypy/branch/jit-unroll-loops/pypy/rpython/memory/gc/minimarkpage.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/rpython/memory/gc/minimarkpage.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/rpython/memory/gc/minimarkpage.py	Sat Oct 30 16:41:17 2010
@@ -100,11 +100,14 @@
         # allocation of the given size.
         length = small_request_threshold / WORD + 1
         self.page_for_size = lltype.malloc(rffi.CArray(PAGE_PTR), length,
-                                           flavor='raw', zero=True)
+                                           flavor='raw', zero=True,
+                                           immortal=True)
         self.full_page_for_size = lltype.malloc(rffi.CArray(PAGE_PTR), length,
-                                                flavor='raw', zero=True)
+                                                flavor='raw', zero=True,
+                                                immortal=True)
         self.nblocks_for_size = lltype.malloc(rffi.CArray(lltype.Signed),
-                                              length, flavor='raw')
+                                              length, flavor='raw',
+                                              immortal=True)
         self.hdrsize = llmemory.raw_malloc_usage(llmemory.sizeof(PAGE_HEADER))
         assert page_size > self.hdrsize
         self.nblocks_for_size[0] = 0    # unused
@@ -114,11 +117,13 @@
         self.max_pages_per_arena = arena_size // page_size
         self.arenas_lists = lltype.malloc(rffi.CArray(ARENA_PTR),
                                           self.max_pages_per_arena,
-                                          flavor='raw', zero=True)
+                                          flavor='raw', zero=True,
+                                          immortal=True)
         # this is used in mass_free() only
         self.old_arenas_lists = lltype.malloc(rffi.CArray(ARENA_PTR),
                                               self.max_pages_per_arena,
-                                              flavor='raw', zero=True)
+                                              flavor='raw', zero=True,
+                                              immortal=True)
         #
         # the arena currently consumed; it must have at least one page
         # available, or be NULL.  The arena object that we point to is
@@ -281,7 +286,7 @@
         npages = (arena_end - firstpage) // self.page_size
         #
         # Allocate an ARENA object and initialize it
-        arena = lltype.malloc(ARENA, flavor='raw')
+        arena = lltype.malloc(ARENA, flavor='raw', track_allocation=False)
         arena.base = arena_base
         arena.nfreepages = 0        # they are all uninitialized pages
         arena.totalpages = npages
@@ -332,7 +337,7 @@
                     #
                     # The whole arena is empty.  Free it.
                     llarena.arena_free(arena.base)
-                    lltype.free(arena, flavor='raw')
+                    lltype.free(arena, flavor='raw', track_allocation=False)
                     #
                 else:
                     # Insert 'arena' in the correct arenas_lists[n]

Modified: pypy/branch/jit-unroll-loops/pypy/rpython/memory/gc/semispace.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/rpython/memory/gc/semispace.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/rpython/memory/gc/semispace.py	Sat Oct 30 16:41:17 2010
@@ -1,7 +1,6 @@
 from pypy.rpython.lltypesystem.llmemory import raw_malloc, raw_free
 from pypy.rpython.lltypesystem.llmemory import raw_memcopy, raw_memclear
 from pypy.rpython.lltypesystem.llmemory import NULL, raw_malloc_usage
-from pypy.rpython.memory.support import DEFAULT_CHUNK_SIZE
 from pypy.rpython.memory.support import get_address_stack, get_address_deque
 from pypy.rpython.memory.support import AddressDict
 from pypy.rpython.lltypesystem import lltype, llmemory, llarena, rffi, llgroup
@@ -59,11 +58,11 @@
     # translating to a real backend.
     TRANSLATION_PARAMS = {'space_size': 8*1024*1024} # XXX adjust
 
-    def __init__(self, config, chunk_size=DEFAULT_CHUNK_SIZE, space_size=4096,
-                 max_space_size=sys.maxint//2+1):
+    def __init__(self, config, space_size=4096, max_space_size=sys.maxint//2+1,
+                 **kwds):
         self.param_space_size = space_size
         self.param_max_space_size = max_space_size
-        MovingGCBase.__init__(self, config, chunk_size)
+        MovingGCBase.__init__(self, config, **kwds)
 
     def setup(self):
         #self.total_collection_time = 0.0

Modified: pypy/branch/jit-unroll-loops/pypy/rpython/memory/gc/test/test_direct.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/rpython/memory/gc/test/test_direct.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/rpython/memory/gc/test/test_direct.py	Sat Oct 30 16:41:17 2010
@@ -70,6 +70,7 @@
         GC_PARAMS = self.GC_PARAMS.copy()
         if hasattr(meth, 'GC_PARAMS'):
             GC_PARAMS.update(meth.GC_PARAMS)
+        GC_PARAMS['translated_to_c'] = False
         self.gc = self.GCClass(config, **GC_PARAMS)
         self.gc.DEBUG = True
         self.rootwalker = DirectRootWalker(self)
@@ -86,17 +87,19 @@
 
     def write(self, p, fieldname, newvalue):
         if self.gc.needs_write_barrier:
+            newaddr = llmemory.cast_ptr_to_adr(newvalue)
             addr_struct = llmemory.cast_ptr_to_adr(p)
-            self.gc.write_barrier(addr_struct)
+            self.gc.write_barrier(newaddr, addr_struct)
         setattr(p, fieldname, newvalue)
 
     def writearray(self, p, index, newvalue):
         if self.gc.needs_write_barrier:
+            newaddr = llmemory.cast_ptr_to_adr(newvalue)
             addr_struct = llmemory.cast_ptr_to_adr(p)
             if hasattr(self.gc, 'write_barrier_from_array'):
-                self.gc.write_barrier_from_array(addr_struct, index)
+                self.gc.write_barrier_from_array(newaddr, addr_struct, index)
             else:
-                self.gc.write_barrier(addr_struct)
+                self.gc.write_barrier(newaddr, addr_struct)
         p[index] = newvalue
 
     def malloc(self, TYPE, n=None):

Modified: pypy/branch/jit-unroll-loops/pypy/rpython/memory/gctransform/asmgcroot.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/rpython/memory/gctransform/asmgcroot.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/rpython/memory/gctransform/asmgcroot.py	Sat Oct 30 16:41:17 2010
@@ -75,7 +75,8 @@
             key = (TYPE, num)
             if key not in sradict:
                 CONTAINER = lltype.FixedSizeArray(TYPE, 1)
-                p = lltype.malloc(CONTAINER, flavor='raw', zero=True)
+                p = lltype.malloc(CONTAINER, flavor='raw', zero=True,
+                                  immortal=True)
                 sradict[key] = Constant(p, lltype.Ptr(CONTAINER))
             sra.append(sradict[key])
         #

Modified: pypy/branch/jit-unroll-loops/pypy/rpython/memory/gctransform/framework.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/rpython/memory/gctransform/framework.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/rpython/memory/gctransform/framework.py	Sat Oct 30 16:41:17 2010
@@ -426,6 +426,7 @@
         if GCClass.needs_write_barrier:
             self.write_barrier_ptr = getfn(GCClass.write_barrier.im_func,
                                            [s_gc,
+                                            annmodel.SomeAddress(),
                                             annmodel.SomeAddress()],
                                            annmodel.s_None,
                                            inline=True)
@@ -434,13 +435,15 @@
                 # func should not be a bound method, but a real function
                 assert isinstance(func, types.FunctionType)
                 self.write_barrier_failing_case_ptr = getfn(func,
-                                               [annmodel.SomeAddress()],
+                                               [annmodel.SomeAddress(),
+                                                annmodel.SomeAddress()],
                                                annmodel.s_None)
             func = getattr(GCClass, 'write_barrier_from_array', None)
             if func is not None:
                 self.write_barrier_from_array_ptr = getfn(func.im_func,
                                            [s_gc,
                                             annmodel.SomeAddress(),
+                                            annmodel.SomeAddress(),
                                             annmodel.SomeInteger()],
                                            annmodel.s_None,
                                            inline=True)
@@ -1021,6 +1024,8 @@
             and not isinstance(v_newvalue, Constant)
             and v_struct.concretetype.TO._gckind == "gc"
             and hop.spaceop not in self.clean_sets):
+            v_newvalue = hop.genop("cast_ptr_to_adr", [v_newvalue],
+                                   resulttype = llmemory.Address)
             v_structaddr = hop.genop("cast_ptr_to_adr", [v_struct],
                                      resulttype = llmemory.Address)
             if (self.write_barrier_from_array_ptr is not None and
@@ -1030,12 +1035,14 @@
                 assert v_index.concretetype == lltype.Signed
                 hop.genop("direct_call", [self.write_barrier_from_array_ptr,
                                           self.c_const_gc,
+                                          v_newvalue,
                                           v_structaddr,
                                           v_index])
             else:
                 self.write_barrier_calls += 1
                 hop.genop("direct_call", [self.write_barrier_ptr,
                                           self.c_const_gc,
+                                          v_newvalue,
                                           v_structaddr])
         hop.rename('bare_' + opname)
 

Modified: pypy/branch/jit-unroll-loops/pypy/rpython/memory/gctransform/transform.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/rpython/memory/gctransform/transform.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/rpython/memory/gctransform/transform.py	Sat Oct 30 16:41:17 2010
@@ -430,7 +430,8 @@
         return self.parenttransformer.gct_malloc_varsize(hop)
     
     def gct_free(self, hop):
-        flavor = hop.spaceop.args[1].value
+        flags = hop.spaceop.args[1].value
+        flavor = flags['flavor']
         assert flavor == 'raw'
         return self.parenttransformer.gct_free(hop)
 
@@ -532,6 +533,8 @@
                           resulttype=llmemory.Address)
         if flags.get('zero'):
             hop.genop("raw_memclear", [v_raw, c_size])
+        if flags.get('track_allocation', True):
+            hop.genop("track_alloc_start", [v_raw])
         return v_raw
 
     def gct_fv_stack_malloc(self, hop, flags, TYPE, c_size):
@@ -602,15 +605,20 @@
                                [self.raw_malloc_varsize_ptr, v_length,
                                 c_const_size, c_item_size, c_offset_to_length],
                                resulttype=llmemory.Address)
+        if flags.get('track_allocation', True):
+            hop.genop("track_alloc_start", [v_raw])
         return v_raw
 
     def gct_free(self, hop):
         op = hop.spaceop
-        flavor = op.args[1].value
+        flags = op.args[1].value
+        flavor = flags['flavor']
         v = op.args[0]
         assert flavor != 'cpy', "cannot free CPython objects directly"
         if flavor == 'raw':
             v = hop.genop("cast_ptr_to_adr", [v], resulttype=llmemory.Address)
+            if flags.get('track_allocation', True):
+                hop.genop("track_alloc_stop", [v])
             hop.genop('raw_free', [v])
         else:
             assert False, "%s has no support for free with flavor %r" % (self, flavor)           

Modified: pypy/branch/jit-unroll-loops/pypy/rpython/memory/gcwrapper.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/rpython/memory/gcwrapper.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/rpython/memory/gcwrapper.py	Sat Oct 30 16:41:17 2010
@@ -9,7 +9,10 @@
     def __init__(self, llinterp, flowgraphs, gc_class, GC_PARAMS={}):
         translator = llinterp.typer.annotator.translator
         config = translator.config.translation
-        self.gc = gc_class(config, chunk_size = 10, **GC_PARAMS)
+        self.gc = gc_class(config,
+                           chunk_size      = 10,
+                           translated_to_c = False,
+                           **GC_PARAMS)
         self.gc.set_root_walker(LLInterpRootWalker(self))
         self.gc.DEBUG = True
         self.llinterp = llinterp
@@ -39,7 +42,8 @@
     #
     # Interface for the llinterp
     #
-    def malloc(self, TYPE, n=None, flavor='gc', zero=False):
+    def malloc(self, TYPE, n=None, flavor='gc', zero=False,
+               track_allocation=True):
         if flavor == 'gc':
             typeid = self.get_type_id(TYPE)
             addr = self.gc.malloc(typeid, n, zero=zero)
@@ -48,7 +52,8 @@
                 gctypelayout.zero_gc_pointers(result)
             return result
         else:
-            return lltype.malloc(TYPE, n, flavor=flavor, zero=zero)
+            return lltype.malloc(TYPE, n, flavor=flavor, zero=zero,
+                                 track_allocation=track_allocation)
 
     def malloc_nonmovable(self, TYPE, n=None, zero=False):
         typeid = self.get_type_id(TYPE)
@@ -66,9 +71,10 @@
             return self.gc.shrink_array(addr, smallersize)
         return False
 
-    def free(self, TYPE, flavor='gc'):
+    def free(self, TYPE, flavor='gc', track_allocation=True):
         assert flavor != 'gc'
-        return lltype.free(TYPE, flavor=flavor)
+        return lltype.free(TYPE, flavor=flavor,
+                           track_allocation=track_allocation)
 
     def setfield(self, obj, fieldname, fieldvalue):
         STRUCT = lltype.typeOf(obj).TO
@@ -94,6 +100,7 @@
                         assert (type(index) is int    # <- fast path
                                 or lltype.typeOf(index) == lltype.Signed)
                         self.gc.write_barrier_from_array(
+                            llmemory.cast_ptr_to_adr(newvalue),
                             llmemory.cast_ptr_to_adr(toplevelcontainer),
                             index)
                         wb = False
@@ -101,6 +108,7 @@
             #
             if wb:
                 self.gc.write_barrier(
+                    llmemory.cast_ptr_to_adr(newvalue),
                     llmemory.cast_ptr_to_adr(toplevelcontainer))
         llheap.setinterior(toplevelcontainer, inneraddr, INNERTYPE, newvalue)
 

Modified: pypy/branch/jit-unroll-loops/pypy/rpython/memory/support.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/rpython/memory/support.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/rpython/memory/support.py	Sat Oct 30 16:41:17 2010
@@ -30,7 +30,8 @@
                 # we zero-initialize the chunks to make the translation
                 # backends happy, but we don't need to do it at run-time.
                 zero = not we_are_translated()
-                return lltype.malloc(CHUNK, flavor="raw", zero=zero)
+                return lltype.malloc(CHUNK, flavor="raw", zero=zero,
+                                     track_allocation=False)
                 
             result = self.free_list
             self.free_list = result.next
@@ -44,7 +45,7 @@
                 # Don't cache the old chunks but free them immediately.
                 # Helps debugging, and avoids that old chunks full of
                 # addresses left behind by a test end up in genc...
-                lltype.free(chunk, flavor="raw")
+                lltype.free(chunk, flavor="raw", track_allocation=False)
 
     unused_chunks = FreeList()
     cache[chunk_size] = unused_chunks, null_chunk

Modified: pypy/branch/jit-unroll-loops/pypy/rpython/memory/test/test_gc.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/rpython/memory/test/test_gc.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/rpython/memory/test/test_gc.py	Sat Oct 30 16:41:17 2010
@@ -368,6 +368,14 @@
         res = self.interpret(f, [4, 42])
         assert res == 12
 
+    def test_print_leak(self):
+        def f(n):
+            for i in range(n):
+                print i
+            return 42
+        res = self.interpret(f, [10])
+        assert res == 42
+
     def test_weakref_across_minor_collection(self):
         import weakref
         class A:

Modified: pypy/branch/jit-unroll-loops/pypy/rpython/memory/test/test_transformed_gc.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/rpython/memory/test/test_transformed_gc.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/rpython/memory/test/test_transformed_gc.py	Sat Oct 30 16:41:17 2010
@@ -906,7 +906,8 @@
     gcname = "marksweep"
     class gcpolicy(gc.FrameworkGcPolicy):
         class transformerclass(framework.FrameworkGCTransformer):
-            GC_PARAMS = {'start_heap_size': 1024*WORD }
+            GC_PARAMS = {'start_heap_size': 1024*WORD,
+                         'translated_to_c': False}
             root_stack_depth = 200
 
 
@@ -1144,7 +1145,8 @@
     class gcpolicy(gc.FrameworkGcPolicy):
         class transformerclass(framework.FrameworkGCTransformer):
             from pypy.rpython.memory.gc.marksweep import PrintingMarkSweepGC as GCClass
-            GC_PARAMS = {'start_heap_size': 1024*WORD }
+            GC_PARAMS = {'start_heap_size': 1024*WORD,
+                         'translated_to_c': False}
             root_stack_depth = 200
 
 class TestSemiSpaceGC(GenericMovingGCTests):
@@ -1154,7 +1156,8 @@
     class gcpolicy(gc.FrameworkGcPolicy):
         class transformerclass(framework.FrameworkGCTransformer):
             from pypy.rpython.memory.gc.semispace import SemiSpaceGC as GCClass
-            GC_PARAMS = {'space_size': 512*WORD}
+            GC_PARAMS = {'space_size': 512*WORD,
+                         'translated_to_c': False}
             root_stack_depth = 200
 
 class TestMarkCompactGC(GenericMovingGCTests):
@@ -1163,7 +1166,8 @@
     class gcpolicy(gc.FrameworkGcPolicy):
         class transformerclass(framework.FrameworkGCTransformer):
             from pypy.rpython.memory.gc.markcompact import MarkCompactGC as GCClass
-            GC_PARAMS = {'space_size': 4096*WORD}
+            GC_PARAMS = {'space_size': 4096*WORD,
+                         'translated_to_c': False}
             root_stack_depth = 200
 
 class TestGenerationGC(GenericMovingGCTests):
@@ -1175,7 +1179,8 @@
             from pypy.rpython.memory.gc.generation import GenerationGC as \
                                                           GCClass
             GC_PARAMS = {'space_size': 512*WORD,
-                         'nursery_size': 32*WORD}
+                         'nursery_size': 32*WORD,
+                         'translated_to_c': False}
             root_stack_depth = 200
 
     def define_weakref_across_minor_collection(cls):
@@ -1372,7 +1377,8 @@
                 GenerationGC._teardown(self)
                 
             GC_PARAMS = {'space_size': 512*WORD,
-                         'nursery_size': 128*WORD}
+                         'nursery_size': 128*WORD,
+                         'translated_to_c': False}
             root_stack_depth = 200
 
     def define_working_nursery(cls):
@@ -1404,7 +1410,8 @@
             from pypy.rpython.memory.gc.hybrid import HybridGC as GCClass
             GC_PARAMS = {'space_size': 512*WORD,
                          'nursery_size': 32*WORD,
-                         'large_object': 8*WORD}
+                         'large_object': 8*WORD,
+                         'translated_to_c': False}
             root_stack_depth = 200
 
     def define_ref_from_rawmalloced_to_regular(cls):
@@ -1477,6 +1484,7 @@
                          'large_object': 8*WORD,
                          'large_object_gcptrs': 10*WORD,
                          'card_page_indices': 4,
+                         'translated_to_c': False,
                          }
             root_stack_depth = 200
 
@@ -1585,7 +1593,8 @@
     gcname = "marksweep"
     class gcpolicy(gc.FrameworkGcPolicy):
         class transformerclass(framework.FrameworkGCTransformer):
-            GC_PARAMS = {'start_heap_size': 1024*WORD }
+            GC_PARAMS = {'start_heap_size': 1024*WORD,
+                         'translated_to_c': False}
             root_stack_depth = 200
 
 class TestHybridTaggedPointerGC(TaggedPointerGCTests):
@@ -1596,7 +1605,8 @@
             from pypy.rpython.memory.gc.generation import GenerationGC as \
                                                           GCClass
             GC_PARAMS = {'space_size': 512*WORD,
-                         'nursery_size': 32*WORD}
+                         'nursery_size': 32*WORD,
+                         'translated_to_c': False}
             root_stack_depth = 200
 
 class TestMarkCompactTaggedpointerGC(TaggedPointerGCTests):
@@ -1605,5 +1615,6 @@
     class gcpolicy(gc.FrameworkGcPolicy):
         class transformerclass(framework.FrameworkGCTransformer):
             from pypy.rpython.memory.gc.markcompact import MarkCompactGC as GCClass
-            GC_PARAMS = {'space_size': 4096*WORD}
+            GC_PARAMS = {'space_size': 4096*WORD,
+                         'translated_to_c': False}
             root_stack_depth = 200

Modified: pypy/branch/jit-unroll-loops/pypy/rpython/module/ll_time.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/rpython/module/ll_time.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/rpython/module/ll_time.py	Sat Oct 30 16:41:17 2010
@@ -108,7 +108,7 @@
 
                 errcode = -1
                 if self.GETTIMEOFDAY_NO_TZ:
-                    errcode = g_gettimeofday(t)
+                    errcode = c_gettimeofday(t)
                 else:
                     errcode = c_gettimeofday(t, void)
 

Modified: pypy/branch/jit-unroll-loops/pypy/rpython/rbuilder.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/rpython/rbuilder.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/rpython/rbuilder.py	Sat Oct 30 16:41:17 2010
@@ -36,8 +36,12 @@
         hop.exception_cannot_occur()
         return hop.gendirectcall(self.ll_append_multiple_char, *vlist)
 
+    def rtype_method_getlength(self, hop):
+        vlist = hop.inputargs(self)
+        hop.exception_cannot_occur()
+        return hop.gendirectcall(self.ll_getlength, *vlist)
+
     def rtype_method_build(self, hop):
         vlist = hop.inputargs(self)
         hop.exception_cannot_occur()
         return hop.gendirectcall(self.ll_build, *vlist)
-

Modified: pypy/branch/jit-unroll-loops/pypy/rpython/rbuiltin.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/rpython/rbuiltin.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/rpython/rbuiltin.py	Sat Oct 30 16:41:17 2010
@@ -345,17 +345,22 @@
 BUILTIN_TYPER[object.__init__] = rtype_object__init__
 # annotation of low-level types
 
-def rtype_malloc(hop, i_flavor=None, i_zero=None):
+def rtype_malloc(hop, i_flavor=None, i_zero=None, i_track_allocation=None):
     assert hop.args_s[0].is_constant()
     vlist = [hop.inputarg(lltype.Void, arg=0)]
     opname = 'malloc'
-    v_flavor, v_zero = parse_kwds(hop, (i_flavor, lltype.Void), (i_zero, None))
+    v_flavor, v_zero, v_track_allocation = parse_kwds(hop,
+        (i_flavor, lltype.Void),
+        (i_zero, None),
+        (i_track_allocation, None))
 
     flags = {'flavor': 'gc'}
     if v_flavor is not None:
         flags['flavor'] = v_flavor.value
     if i_zero is not None:
         flags['zero'] = v_zero.value
+    if i_track_allocation is not None:
+        flags['track_allocation'] = v_track_allocation.value
     vlist.append(hop.inputconst(lltype.Void, flags))
         
     if hop.nb_args == 2:
@@ -366,10 +371,19 @@
     hop.exception_is_here()
     return hop.genop(opname, vlist, resulttype = hop.r_result.lowleveltype)
 
-def rtype_free(hop, i_flavor):
-    assert i_flavor == 1
+def rtype_free(hop, i_flavor, i_track_allocation=None):
+    vlist = [hop.inputarg(hop.args_r[0], arg=0)]
+    v_flavor, v_track_allocation = parse_kwds(hop,
+        (i_flavor, lltype.Void),
+        (i_track_allocation, None))
+    #
+    assert v_flavor is not None and v_flavor.value == 'raw'
+    flags = {'flavor': 'raw'}
+    if i_track_allocation is not None:
+        flags['track_allocation'] = v_track_allocation.value
+    vlist.append(hop.inputconst(lltype.Void, flags))
+    #
     hop.exception_cannot_occur()
-    vlist = hop.inputargs(hop.args_r[0], lltype.Void)
     hop.genop('free', vlist)
 
 def rtype_const_result(hop):
@@ -584,8 +598,9 @@
     vinst, = hop.inputargs(hop.args_r[0])
     flavor = hop.args_r[0].gcflavor
     assert flavor != 'gc'
-    cflavor = hop.inputconst(lltype.Void, flavor)
-    return hop.genop('free', [vinst, cflavor])
+    flags = {'flavor': flavor}
+    cflags = hop.inputconst(lltype.Void, flags)
+    return hop.genop('free', [vinst, cflags])
     
 BUILTIN_TYPER[objectmodel.free_non_gc_object] = rtype_free_non_gc_object
 

Modified: pypy/branch/jit-unroll-loops/pypy/rpython/rpbc.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/rpython/rpbc.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/rpython/rpbc.py	Sat Oct 30 16:41:17 2010
@@ -256,6 +256,8 @@
     def convert_const(self, value):
         if isinstance(value, types.MethodType) and value.im_self is None:
             value = value.im_func   # unbound method -> bare function
+        elif isinstance(value, staticmethod):
+            value = value.__get__(42) # hackish, get the function wrapped by staticmethod
         if self.lowleveltype is Void:
             return None
         if value is None:

Modified: pypy/branch/jit-unroll-loops/pypy/rpython/rtyper.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/rpython/rtyper.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/rpython/rtyper.py	Sat Oct 30 16:41:17 2010
@@ -421,7 +421,7 @@
             assert noexclink.exitcase is None
             if pos == "removed":
                 # the exception cannot actually occur at all.
-                # See for example rspecialcase.rtype_call_specialcase().
+                # This is set by calling exception_cannot_occur().
                 # We just remove all exception links.
                 block.exitswitch = None
                 block.exits = block.exits[:1]
@@ -1019,7 +1019,7 @@
 from pypy.rpython import rint, rbool, rfloat
 from pypy.rpython import rrange
 from pypy.rpython import rstr, rdict, rlist
-from pypy.rpython import rclass, rbuiltin, rpbc, rspecialcase
+from pypy.rpython import rclass, rbuiltin, rpbc
 from pypy.rpython import rexternalobj
 from pypy.rpython import rptr
 from pypy.rpython import rgeneric

Modified: pypy/branch/jit-unroll-loops/pypy/rpython/test/test_llinterp.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/rpython/test/test_llinterp.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/rpython/test/test_llinterp.py	Sat Oct 30 16:41:17 2010
@@ -1,3 +1,4 @@
+from __future__ import with_statement
 import py
 import sys
 from pypy.rpython.lltypesystem.lltype import typeOf, pyobjectptr, Ptr,\
@@ -5,6 +6,7 @@
 from pypy.rpython.lltypesystem.lloperation import llop
 from pypy.rpython.llinterp import LLInterpreter, LLException, log
 from pypy.rpython.rmodel import inputconst
+from pypy.rpython.annlowlevel import hlstr
 from pypy.translator.translator import TranslationContext, graphof
 from pypy.rpython.rint import signed_repr
 from pypy.rpython.lltypesystem import rstr, lltype
@@ -12,13 +14,11 @@
 from pypy.annotation.model import lltype_to_annotation
 from pypy.rlib.rarithmetic import r_uint, ovfcheck
 from pypy.rpython.ootypesystem import ootype
+from pypy.tool import leakfinder
 from pypy import conftest
 
 # switch on logging of interp to show more info on failing tests
 
-class MallocMismatch(Exception):
-    pass
-
 def setup_module(mod):
     mod.logstate = py.log._getstate()
     py.log.setconsumer("llinterp", py.log.STDOUT)
@@ -72,7 +72,7 @@
 
 def get_interpreter(func, values, view='auto', viewbefore='auto', policy=None,
                     someobjects=False, type_system="lltype", backendopt=False,
-                    config=None, malloc_check=True, **extraconfigopts):
+                    config=None, **extraconfigopts):
     extra_key = [(key, value) for key, value in extraconfigopts.iteritems()]
     extra_key.sort()
     extra_key = tuple(extra_key)
@@ -97,7 +97,7 @@
                                    viewbefore, policy, type_system=type_system,
                                    backendopt=backendopt, config=config,
                                    **extraconfigopts)
-        interp = LLInterpreter(typer, malloc_check=malloc_check)
+        interp = LLInterpreter(typer)
         _tcache[key] = (t, interp, graph)
         # keep the cache small 
         _lastinterpreted.append(key) 
@@ -115,10 +115,17 @@
     interp, graph = get_interpreter(func, values, view, viewbefore, policy,
                                     someobjects, type_system=type_system,
                                     backendopt=backendopt, config=config,
-                                    malloc_check=malloc_check, **kwargs)
-    result = interp.eval_graph(graph, values)
-    if malloc_check and interp.mallocs:
-        raise MallocMismatch(interp.mallocs)
+                                    **kwargs)
+    if not malloc_check:
+        result = interp.eval_graph(graph, values)
+    else:
+        prev = leakfinder.start_tracking_allocations()
+        try:
+            result = interp.eval_graph(graph, values)
+        finally:
+            leaks = leakfinder.stop_tracking_allocations(False, prev)
+        if leaks:
+            raise leakfinder.MallocMismatch(leaks)
     return result
 
 def interpret_raises(exc, func, values, view='auto', viewbefore='auto',
@@ -418,6 +425,7 @@
             assert result
 
 def test_stack_malloc():
+    py.test.skip("stack-flavored mallocs no longer supported")
     class A(object):
         pass
     def f():
@@ -430,6 +438,7 @@
     assert result == 1
 
 def test_invalid_stack_access():
+    py.test.skip("stack-flavored mallocs no longer supported")
     class A(object):
         pass
     globala = A()
@@ -605,7 +614,7 @@
         if x:
             free(t, flavor='raw')
     interpret(f, [1])
-    py.test.raises(MallocMismatch, "interpret(f, [0])")
+    py.test.raises(leakfinder.MallocMismatch, "interpret(f, [0])")
     
     def f():
         t1 = malloc(T, flavor='raw')
@@ -615,3 +624,37 @@
 
     interpret(f, [])
 
+def test_context_manager():
+    state = []
+    class C:
+        def __enter__(self):
+            state.append('acquire')
+            return self
+        def __exit__(self, *args):
+            if args[1] is not None:
+                state.append('raised')
+            state.append('release')
+    def f():
+        try:
+            with C() as c:
+                state.append('use')
+                raise ValueError
+        except ValueError:
+            pass
+        return ', '.join(state)
+    res = interpret(f, [])
+    assert hlstr(res) == 'acquire, use, raised, release'
+
+
+def test_scoped_allocator():
+    from pypy.rpython.lltypesystem.lltype import scoped_alloc, Array, Signed
+    T = Array(Signed)
+    
+    def f():
+        x = 0
+        with scoped_alloc(T, 1) as array:
+            array[0] = -42
+            x = array[0]
+        assert x == -42
+
+    res = interpret(f, [])

Modified: pypy/branch/jit-unroll-loops/pypy/rpython/test/test_nongc.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/rpython/test/test_nongc.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/rpython/test/test_nongc.py	Sat Oct 30 16:41:17 2010
@@ -79,7 +79,7 @@
     py.test.raises(TypeError,rtyper.specialize) # results in an invalid cast
 
 def test_isinstance():
-    class A:
+    class A(object):
         _alloc_flavor_ = "raw"
     class B(A):
         pass
@@ -95,7 +95,24 @@
             o = B()
         else:
             o = C()
-        return 100*isinstance(o, A)+10*isinstance(o, B)+1*isinstance(o ,C)
+        res = 100*isinstance(o, A) + 10*isinstance(o, B) + 1*isinstance(o, C)
+        if i == 0:
+            pass
+        elif i == 1:
+            assert isinstance(o, A)
+            free_non_gc_object(o)
+        elif i == 2:
+            assert isinstance(o, B)
+            free_non_gc_object(o)
+        else:
+            assert isinstance(o, C)
+            free_non_gc_object(o)
+        return res
+
+    assert f(1) == 100
+    assert f(2) == 110
+    assert f(3) == 111
+    assert f(0) == 0
 
     a = RPythonAnnotator()
     #does not raise:
@@ -131,10 +148,14 @@
             d = b
         elif i == 2:
             e = c
-        return (0x0001*(a is b) | 0x0002*(a is c) | 0x0004*(a is d) |
+        res =  (0x0001*(a is b) | 0x0002*(a is c) | 0x0004*(a is d) |
                 0x0008*(a is e) | 0x0010*(b is c) | 0x0020*(b is d) |
                 0x0040*(b is e) | 0x0080*(c is d) | 0x0100*(c is e) |
                 0x0200*(d is e))
+        free_non_gc_object(a)
+        free_non_gc_object(b)
+        free_non_gc_object(c)
+        return res
     a = RPythonAnnotator()
     #does not raise:
     s = a.build_types(f, [int])
@@ -169,10 +190,13 @@
             d = b
         elif i == 2:
             e = c
-        return (0x0001*(a is b) | 0x0002*(a is c) | 0x0004*(a is d) |
+        res =  (0x0001*(a is b) | 0x0002*(a is c) | 0x0004*(a is d) |
                 0x0008*(a is e) | 0x0010*(b is c) | 0x0020*(b is d) |
                 0x0040*(b is e) | 0x0080*(c is d) | 0x0100*(c is e) |
                 0x0200*(d is e))
+        free_non_gc_object(a)
+        free_non_gc_object(b)
+        return res
     a = RPythonAnnotator()
     #does not raise:
     s = a.build_types(f, [int])

Modified: pypy/branch/jit-unroll-loops/pypy/rpython/test/test_rbuilder.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/rpython/test/test_rbuilder.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/rpython/test/test_rbuilder.py	Sat Oct 30 16:41:17 2010
@@ -1,4 +1,4 @@
-
+import py
 from pypy.rpython.test.tool import BaseRtypingTest, LLRtypeMixin, OORtypeMixin
 from pypy.rpython.lltypesystem.rbuilder import *
 from pypy.rpython.annlowlevel import llstr, hlstr
@@ -55,8 +55,29 @@
         assert res == 'aabcabcdefbuuuu'
         assert isinstance(res, unicode)
 
+    def test_string_getlength(self):
+        def func():
+            s = StringBuilder()
+            s.append("a")
+            s.append("abc")
+            return s.getlength()
+        res = self.interpret(func, [])
+        assert res == 4
+
+    def test_unicode_getlength(self):
+        def func():
+            s = UnicodeBuilder()
+            s.append(u"a")
+            s.append(u"abc")
+            return s.getlength()
+        res = self.interpret(func, [])
+        assert res == 4
+
 class TestLLtype(BaseTestStringBuilder, LLRtypeMixin):
     pass
 
 class TestOOtype(BaseTestStringBuilder, OORtypeMixin):
-    pass
+    def test_string_getlength(self):
+        py.test.skip("getlength(): not implemented on ootype")
+    def test_unicode_getlength(self):
+        py.test.skip("getlength(): not implemented on ootype")

Modified: pypy/branch/jit-unroll-loops/pypy/rpython/test/test_rclass.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/rpython/test/test_rclass.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/rpython/test/test_rclass.py	Sat Oct 30 16:41:17 2010
@@ -3,7 +3,7 @@
 from pypy.translator.translator import TranslationContext, graphof
 from pypy.rpython.lltypesystem.lltype import *
 from pypy.rpython.ootypesystem import ootype
-from pypy.rlib.rarithmetic import intmask
+from pypy.rlib.rarithmetic import intmask, r_longlong
 from pypy.rpython.test.tool import BaseRtypingTest, LLRtypeMixin, OORtypeMixin
 from pypy.objspace.flow.model import summary
 
@@ -319,6 +319,17 @@
         res = self.interpret(f, [])
         assert res == 42
 
+    def test_staticmethod2(self):
+        class A(object):
+            f = staticmethod(lambda x, y: x*y)
+        class B(A):
+            f = staticmethod(lambda x, y: x+y)
+        def f():
+            b = B()
+            return b.f(6, 7)
+        res = self.interpret(f, [])
+        assert res == 13
+
     def test_is(self):
         class A: pass
         class B(A): pass
@@ -1001,6 +1012,40 @@
         res = self.interpret(f, [5])
         assert res == 0
 
+    def test_order_of_fields(self):
+        class A(object):
+            pass
+        def f(n):
+            a = A()
+            a.as_int = n
+            a.as_char = chr(n)
+            a.as_unichar = unichr(n)
+            a.as_double = n + 0.5
+            a.as_bool = bool(n)
+            a.as_void = None
+            a.as_longlong = r_longlong(n)
+            a.as_reference = A()
+            return a
+
+        res = self.interpret(f, [5])
+        names = list(typeOf(res).TO._names)
+        i = names.index('inst_as_int')
+        c = names.index('inst_as_char')
+        u = names.index('inst_as_unichar')
+        d = names.index('inst_as_double')
+        b = names.index('inst_as_bool')
+        v = names.index('inst_as_void')
+        l = names.index('inst_as_longlong')
+        r = names.index('inst_as_reference')
+        assert v == 1      # void fields are first
+        assert sorted([c, b]) == [7, 8]
+        if sys.maxint == 2147483647:
+            assert sorted([u, i, r]) == [4, 5, 6]        # 32-bit types
+            assert sorted([d, l]) == [2, 3]              # 64-bit types
+        else:
+            assert sorted([u]) == [6]                    # 32-bit types
+            assert sorted([i, r, d, l]) == [2, 3, 4, 5]  # 64-bit types
+
 
 class TestOOtype(BaseTestRclass, OORtypeMixin):
 

Modified: pypy/branch/jit-unroll-loops/pypy/rpython/test/test_rdict.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/rpython/test/test_rdict.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/rpython/test/test_rdict.py	Sat Oct 30 16:41:17 2010
@@ -682,6 +682,26 @@
         # if it does not crash, we are fine. It crashes if you forget the hash field.
         self.interpret(func, [])
 
+    def test_dict_popitem(self):
+        def func():
+            d = {}
+            d[5] = 2
+            d[6] = 3
+            k1, v1 = d.popitem()
+            assert len(d) == 1
+            k2, v2 = d.popitem()
+            try:
+                d.popitem()
+            except KeyError:
+                pass
+            else:
+                assert 0, "should have raised KeyError"
+            assert len(d) == 0
+            return k1*1000 + v1*100 + k2*10 + v2
+
+        res = self.interpret(func, [])
+        assert res in [5263, 6352]
+
     # ____________________________________________________________
 
     def test_opt_nullkeymarker(self):

Modified: pypy/branch/jit-unroll-loops/pypy/rpython/test/test_rptr.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/rpython/test/test_rptr.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/rpython/test/test_rptr.py	Sat Oct 30 16:41:17 2010
@@ -212,10 +212,31 @@
 
     S = Struct('S', ('x', Signed))
     def fn(n):
-        p = malloc(S, flavor='whatever')
+        p = malloc(S, flavor='raw')
         p.x = n
         result = p.x
-        free(p, flavor='whatever')
+        free(p, flavor='raw')
+        return n
+
+    res = interpret(fn, [23])
+    assert res == 23
+
+    S = Struct('S', ('x', Signed))
+    def fn(n):
+        p = malloc(S, flavor='raw', track_allocation=False)
+        p.x = n
+        result = p.x
+        return n
+
+    res = interpret(fn, [23])
+    assert res == 23
+
+    S = Struct('S', ('x', Signed))
+    def fn(n):
+        p = malloc(S, flavor='raw', track_allocation=False)
+        p.x = n
+        result = p.x
+        free(p, flavor='raw', track_allocation=False)
         return n
 
     res = interpret(fn, [23])

Modified: pypy/branch/jit-unroll-loops/pypy/translator/c/funcgen.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/translator/c/funcgen.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/translator/c/funcgen.py	Sat Oct 30 16:41:17 2010
@@ -427,7 +427,7 @@
         r = self.expr(op.result)
         return 'OP_CALL_ARGS((%s), %s);' % (', '.join(args), r)
 
-    def generic_call(self, FUNC, fnexpr, args_v, v_result):
+    def generic_call(self, FUNC, fnexpr, args_v, v_result, targets=None):
         args = []
         assert len(args_v) == len(FUNC.TO.ARGS)
         for v, ARGTYPE in zip(args_v, FUNC.TO.ARGS):
@@ -444,17 +444,26 @@
             # skip assignment of 'void' return value
             r = self.expr(v_result)
             line = '%s = %s' % (r, line)
+        if targets:
+            for graph in targets:
+                if getattr(graph, 'inhibit_tail_call', False):
+                    line += '\nPYPY_INHIBIT_TAIL_CALL();'
+                    break
         return line
 
     def OP_DIRECT_CALL(self, op):
         fn = op.args[0]
+        try:
+            targets = [fn.value._obj.graph]
+        except AttributeError:
+            targets = None
         return self.generic_call(fn.concretetype, self.expr(fn),
-                                 op.args[1:], op.result)
+                                 op.args[1:], op.result, targets)
 
     def OP_INDIRECT_CALL(self, op):
         fn = op.args[0]
         return self.generic_call(fn.concretetype, self.expr(fn),
-                                 op.args[1:-1], op.result)
+                                 op.args[1:-1], op.result, op.args[-1].value)
 
     def OP_ADR_CALL(self, op):
         ARGTYPES = [v.concretetype for v in op.args[1:]]

Modified: pypy/branch/jit-unroll-loops/pypy/translator/c/gcc/instruction.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/translator/c/gcc/instruction.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/translator/c/gcc/instruction.py	Sat Oct 30 16:41:17 2010
@@ -82,6 +82,11 @@
     def all_sources_of(self, localvar):
         return [localvar]
 
+class InsnCondJump(Insn):     # only for debugging; not used internally
+    _args_ = ['label']
+    def __init__(self, label):
+        self.label = label
+
 class Label(Insn):
     _args_ = ['label', 'lineno']
     def __init__(self, label, lineno):
@@ -170,9 +175,12 @@
         self.delta = -7     # use an odd value as marker
 
 class InsnStop(Insn):
-    pass
+    _args_ = ['reason']
+    def __init__(self, reason='?'):
+        self.reason = reason
 
 class InsnRet(InsnStop):
+    _args_ = []
     framesize = 0
     def __init__(self, registers):
         self.registers = registers

Modified: pypy/branch/jit-unroll-loops/pypy/translator/c/gcc/test/elf/track5.s
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/translator/c/gcc/test/elf/track5.s	(original)
+++ pypy/branch/jit-unroll-loops/pypy/translator/c/gcc/test/elf/track5.s	Sat Oct 30 16:41:17 2010
@@ -44,7 +44,7 @@
 	addl	%eax, %ebx
 	jmp	.L1221
 .L1227:
-	call	RPyAbort
+	;;call	RPyAbort
 	cmpl	12(%esi), %ebx
 	jb	.L1229
 	addl	$20, %esp

Modified: pypy/branch/jit-unroll-loops/pypy/translator/c/gcc/test/test_trackgcroot.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/translator/c/gcc/test/test_trackgcroot.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/translator/c/gcc/test/test_trackgcroot.py	Sat Oct 30 16:41:17 2010
@@ -109,7 +109,7 @@
  
 def test_computegcmaptable():
     tests = []
-    for format in ('elf', 'darwin', 'msvc', 'elf64'):
+    for format in ('elf', 'elf64', 'darwin', 'darwin64', 'msvc'):
         for path in this_dir.join(format).listdir("track*.s"):
             n = path.purebasename[5:]
             try:

Modified: pypy/branch/jit-unroll-loops/pypy/translator/c/gcc/trackgcroot.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/translator/c/gcc/trackgcroot.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/translator/c/gcc/trackgcroot.py	Sat Oct 30 16:41:17 2010
@@ -6,7 +6,7 @@
 from pypy.translator.c.gcc.instruction import InsnFunctionStart, InsnStop
 from pypy.translator.c.gcc.instruction import InsnSetLocal, InsnCopyLocal
 from pypy.translator.c.gcc.instruction import InsnPrologue, InsnEpilogue
-from pypy.translator.c.gcc.instruction import InsnGCROOT
+from pypy.translator.c.gcc.instruction import InsnGCROOT, InsnCondJump
 from pypy.translator.c.gcc.instruction import InsnStackAdjust
 from pypy.translator.c.gcc.instruction import InsnCannotFollowEsp
 from pypy.translator.c.gcc.instruction import LocalVar, somenewvalue
@@ -46,6 +46,7 @@
         self.findlabels()
         self.parse_instructions()
         try:
+            self.trim_unreachable_instructions()
             self.find_noncollecting_calls()
             if not self.list_collecting_call_insns():
                 return []
@@ -122,19 +123,36 @@
                 assert label not in self.labels, "duplicate label: %s" % label
                 self.labels[label] = Label(label, lineno)
 
+    def trim_unreachable_instructions(self):
+        reached = set([self.insns[0]])
+        prevlen = 0
+        while len(reached) > prevlen:
+            prevlen = len(reached)
+            for insn in self.insns:
+                if insn not in reached:
+                    for previnsn in insn.previous_insns:
+                        if previnsn in reached:
+                            # this instruction is reachable too
+                            reached.add(insn)
+                            break
+        # now kill all unreachable instructions
+        i = 0
+        while i < len(self.insns):
+            if self.insns[i] in reached:
+                i += 1
+            else:
+                del self.insns[i]
+
     def find_noncollecting_calls(self):
-        cannot_collect = self.CANNOT_COLLECT.copy()
+        cannot_collect = {}
         for line in self.lines:
             match = self.r_gcnocollect_marker.search(line)
             if match:
                 name = match.group(1)
                 cannot_collect[name] = True
         #
-        if self.format in ('darwin', 'mingw32', 'msvc'):
-            self.cannot_collect = dict.fromkeys(
-                ['_' + name for name in cannot_collect])
-        else:
-            self.cannot_collect = cannot_collect
+        self.cannot_collect = dict.fromkeys(
+            [self.function_names_prefix + name for name in cannot_collect])
 
     def append_instruction(self, insn):
         # Add the instruction to the list, and link it to the previous one.
@@ -410,7 +428,8 @@
         return result
     # ____________________________________________________________
 
-    CANNOT_COLLECT = {    # some of the most used functions that cannot collect
+    BASE_FUNCTIONS_NOT_RETURNING = {
+        'abort': None,
         'pypy_debug_catch_fatal_exception': None,
         'RPyAbort': None,
         'RPyAssertFailed': None,
@@ -427,6 +446,7 @@
     IGNORE_OPS_WITH_PREFIXES = dict.fromkeys([
         'cmp', 'test', 'set', 'sahf', 'lahf', 'cltd', 'cld', 'std',
         'rep', 'movs', 'lods', 'stos', 'scas', 'cwtl', 'cwde', 'prefetch',
+        'pslld', 
         # floating-point operations cannot produce GC pointers
         'f',
         'cvt', 'ucomi', 'comi', 'subs', 'subp' , 'adds', 'addp', 'xorp',
@@ -438,7 +458,7 @@
         'bswap', 'bt', 'rdtsc',
         'punpck', 'pshufd', 
         # zero-extending moves should not produce GC pointers
-        'movz',
+        'movz', 
         ])
 
     visit_movb = visit_nop
@@ -644,7 +664,7 @@
                 if label != '0':
                     self.register_jump_to(label)
                 tablelin += 1
-            return InsnStop()
+            return InsnStop("jump table")
         if self.r_unaryinsn_star.match(line):
             # that looks like an indirect tail-call.
             # tail-calls are equivalent to RET for us
@@ -658,7 +678,7 @@
             assert not target.startswith('.')
             # tail-calls are equivalent to RET for us
             return InsnRet(self.CALLEE_SAVE_REGISTERS)
-        return InsnStop()
+        return InsnStop("jump")
     
     def register_jump_to(self, label):
         if not isinstance(self.insns[-1], InsnStop):
@@ -682,7 +702,7 @@
         else:
             label = match.group(1)
         self.register_jump_to(label)
-        return []
+        return [InsnCondJump(label)]
 
     visit_jmpl = visit_jmp
     visit_je = conditional_jump
@@ -754,7 +774,7 @@
                     target, = sources
 
         if target in self.FUNCTIONS_NOT_RETURNING:
-            return [InsnStop(), InsnCannotFollowEsp()]
+            return [InsnStop(target)]
         if self.format == 'mingw32' and target == '__alloca':
             # in functions with large stack requirements, windows
             # needs a call to _alloca(), to turn reserved pages
@@ -885,7 +905,7 @@
             # statically known pointer to a register
 
             # %eax -> %rax
-            new_line = re.sub(r"%e(ax|bx|cx|dx|di|si)$", r"%r\1", line)
+            new_line = re.sub(r"%e(ax|bx|cx|dx|di|si|bp)$", r"%r\1", line)
             # %r10d -> %r10
             new_line = re.sub(r"%r(\d+)d$", r"%r\1", new_line)
             return func(self, new_line)
@@ -951,6 +971,7 @@
 
 class ElfFunctionGcRootTracker32(FunctionGcRootTracker32):
     format = 'elf'
+    function_names_prefix = ''
 
     ESP     = '%esp'
     EBP     = '%ebp'
@@ -984,13 +1005,14 @@
     r_bottom_marker = re.compile(r"\t/[*] GC_STACK_BOTTOM [*]/")
 
     FUNCTIONS_NOT_RETURNING = {
-        'abort': None,
         '_exit': None,
         '__assert_fail': None,
         '___assert_rtn': None,
         'L___assert_rtn$stub': None,
         'L___eprintf$stub': None,
         }
+    for _name in FunctionGcRootTracker.BASE_FUNCTIONS_NOT_RETURNING:
+        FUNCTIONS_NOT_RETURNING[_name] = None
 
     def __init__(self, lines, filetag=0):
         match = self.r_functionstart.match(lines[0])
@@ -1010,6 +1032,8 @@
 
 class ElfFunctionGcRootTracker64(FunctionGcRootTracker64):
     format = 'elf64'
+    function_names_prefix = ''
+
     ESP = '%rsp'
     EBP = '%rbp'
     EAX = '%rax'
@@ -1042,13 +1066,14 @@
     r_bottom_marker = re.compile(r"\t/[*] GC_STACK_BOTTOM [*]/")
 
     FUNCTIONS_NOT_RETURNING = {
-        'abort': None,
         '_exit': None,
         '__assert_fail': None,
         '___assert_rtn': None,
         'L___assert_rtn$stub': None,
         'L___eprintf$stub': None,
         }
+    for _name in FunctionGcRootTracker.BASE_FUNCTIONS_NOT_RETURNING:
+        FUNCTIONS_NOT_RETURNING[_name] = None
 
     def __init__(self, lines, filetag=0):
         match = self.r_functionstart.match(lines[0])
@@ -1066,8 +1091,9 @@
 
 ElfFunctionGcRootTracker64.init_regexp()
 
-class DarwinFunctionGcRootTracker(ElfFunctionGcRootTracker32):
+class DarwinFunctionGcRootTracker32(ElfFunctionGcRootTracker32):
     format = 'darwin'
+    function_names_prefix = '_'
 
     r_functionstart = re.compile(r"_(\w+):\s*$")
     OFFSET_LABELS   = 0
@@ -1077,17 +1103,36 @@
         funcname = '_' + match.group(1)
         FunctionGcRootTracker32.__init__(self, funcname, lines, filetag)
 
-class Mingw32FunctionGcRootTracker(DarwinFunctionGcRootTracker):
+class DarwinFunctionGcRootTracker64(ElfFunctionGcRootTracker64):
+    format = 'darwin64'
+    function_names_prefix = '_'
+
+    LABEL = ElfFunctionGcRootTracker32.LABEL
+    r_jmptable_item = re.compile(r"\t.(?:long|quad)\t"+LABEL+"(-\"?[A-Za-z0-9$]+\"?)?\s*$")
+
+    r_functionstart = re.compile(r"_(\w+):\s*$")
+    OFFSET_LABELS   = 0
+
+    def __init__(self, lines, filetag=0):
+        match = self.r_functionstart.match(lines[0])
+        funcname = '_' + match.group(1)
+        FunctionGcRootTracker64.__init__(self, funcname, lines, filetag)
+
+class Mingw32FunctionGcRootTracker(DarwinFunctionGcRootTracker32):
     format = 'mingw32'
+    function_names_prefix = '_'
 
     FUNCTIONS_NOT_RETURNING = {
-        '_abort': None,
         '_exit': None,
         '__assert': None,
         }
+    for _name in FunctionGcRootTracker.BASE_FUNCTIONS_NOT_RETURNING:
+        FUNCTIONS_NOT_RETURNING['_' + _name] = None
 
 class MsvcFunctionGcRootTracker(FunctionGcRootTracker32):
     format = 'msvc'
+    function_names_prefix = '_'
+
     ESP = 'esp'
     EBP = 'ebp'
     EAX = 'eax'
@@ -1127,7 +1172,6 @@
     r_bottom_marker = re.compile(r"; .+\tpypy_asm_stack_bottom\(\);")
 
     FUNCTIONS_NOT_RETURNING = {
-        '_abort': None,
         '__exit': None,
         '__assert': None,
         '__wassert': None,
@@ -1136,6 +1180,8 @@
         'DWORD PTR __imp__abort': None,
         'DWORD PTR __imp___wassert': None,
         }
+    for _name in FunctionGcRootTracker.BASE_FUNCTIONS_NOT_RETURNING:
+        FUNCTIONS_NOT_RETURNING['_' + _name] = None
 
     @classmethod
     def init_regexp(cls):
@@ -1343,7 +1389,7 @@
 
 class DarwinAssemblerParser(AssemblerParser):
     format = "darwin"
-    FunctionGcRootTracker = DarwinFunctionGcRootTracker
+    FunctionGcRootTracker = DarwinFunctionGcRootTracker32
 
     r_textstart = re.compile(r"\t.text\s*$")
 
@@ -1389,6 +1435,10 @@
         return super(DarwinAssemblerParser, self).process_function(
             lines, entrypoint, filename)
 
+class DarwinAssemblerParser64(DarwinAssemblerParser):
+    format = "darwin64"
+    FunctionGcRootTracker = DarwinFunctionGcRootTracker64
+
 class Mingw32AssemblerParser(DarwinAssemblerParser):
     format = "mingw32"
     FunctionGcRootTracker = Mingw32FunctionGcRootTracker
@@ -1512,6 +1562,7 @@
     'elf': ElfAssemblerParser,
     'elf64': ElfAssemblerParser64,
     'darwin': DarwinAssemblerParser,
+    'darwin64': DarwinAssemblerParser64,
     'mingw32': Mingw32AssemblerParser,
     'msvc': MsvcAssemblerParser,
     }
@@ -1543,15 +1594,13 @@
         assert self.seen_main
 
         def _globalname(name, disp=""):
-            if self.format in ('darwin', 'mingw32', 'msvc'):
-                name = '_' + name
-            return name
+            return tracker_cls.function_names_prefix + name
 
         def _variant(**kwargs):
             txt = kwargs[self.format]
             print >> output, "\t%s" % txt
 
-        if self.format == 'elf64':
+        if self.format in ('elf64', 'darwin64'):
             word_decl = '.quad'
         else:
             word_decl = '.long'
@@ -1604,10 +1653,11 @@
                }
             }
             """
-        elif self.format == 'elf64':
+        elif self.format in ('elf64', 'darwin64'):
             print >> output, "\t.text"
             print >> output, "\t.globl %s" % _globalname('pypy_asm_stackwalk')
-            print >> output, "\t.type pypy_asm_stackwalk, @function"
+            _variant(elf64='.type pypy_asm_stackwalk, @function',
+                     darwin64='')
             print >> output, "%s:" % _globalname('pypy_asm_stackwalk')
 
             print >> output, """\
@@ -1652,8 +1702,9 @@
             /* the return value is the one of the 'call' above, */
             /* because %rax (and possibly %rdx) are unmodified  */
             ret
-            .size pypy_asm_stackwalk, .-pypy_asm_stackwalk
             """
+            _variant(elf64='.size pypy_asm_stackwalk, .-pypy_asm_stackwalk',
+                     darwin64='')
         else:
             print >> output, "\t.text"
             print >> output, "\t.globl %s" % _globalname('pypy_asm_stackwalk')
@@ -1780,6 +1831,7 @@
             _variant(elf='.section\t.rodata',
                      elf64='.section\t.rodata',
                      darwin='.const',
+                     darwin64='.const',
                      mingw32='')
 
             print >> output, """\
@@ -1857,7 +1909,10 @@
     shuffle = False
     output_raw_table = False
     if sys.platform == 'darwin':
-        format = 'darwin'
+        if sys.maxint > 2147483647:
+            format = 'darwin64'
+        else:
+            format = 'darwin'
     elif sys.platform == 'win32':
         format = 'mingw32'
     else:

Modified: pypy/branch/jit-unroll-loops/pypy/translator/c/src/g_include.h
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/translator/c/src/g_include.h	(original)
+++ pypy/branch/jit-unroll-loops/pypy/translator/c/src/g_include.h	Sat Oct 30 16:41:17 2010
@@ -53,6 +53,7 @@
 #  include "src/rtyper.h"
 #  include "src/debug_print.h"
 #  include "src/debug_traceback.h"
+#  include "src/debug_alloc.h"
 #ifndef AVR
 #  include "src/ll_os.h"
 #  include "src/ll_strtod.h"

Modified: pypy/branch/jit-unroll-loops/pypy/translator/c/src/main.h
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/translator/c/src/main.h	(original)
+++ pypy/branch/jit-unroll-loops/pypy/translator/c/src/main.h	Sat Oct 30 16:41:17 2010
@@ -53,10 +53,16 @@
     }
 
     exitcode = STANDALONE_ENTRY_POINT(list);
+
+#ifdef RPY_ASSERT
+    pypy_debug_alloc_results();
+#endif
+
     if (RPyExceptionOccurred()) {
         /* print the RPython traceback */
         pypy_debug_catch_fatal_exception();
     }
+
     return exitcode;
 
  memory_out:

Modified: pypy/branch/jit-unroll-loops/pypy/translator/c/src/signals.h
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/translator/c/src/signals.h	(original)
+++ pypy/branch/jit-unroll-loops/pypy/translator/c/src/signals.h	Sat Oct 30 16:41:17 2010
@@ -6,20 +6,6 @@
 
 #include <limits.h>
 
-#ifndef LONG_MAX
-#if SIZEOF_LONG == 4
-#define LONG_MAX 0X7FFFFFFFL
-#elif SIZEOF_LONG == 8
-#define LONG_MAX 0X7FFFFFFFFFFFFFFFL
-#else
-#error "could not set LONG_MAX in pyport.h"
-#endif
-#endif
-
-#ifndef LONG_MIN
-#define LONG_MIN (-LONG_MAX-1)
-#endif
-
 #include <stdlib.h>
 
 #ifdef MS_WINDOWS
@@ -28,10 +14,6 @@
 
 #include <signal.h>
 
-#ifndef SIG_ERR
-#define SIG_ERR ((PyOS_sighandler_t)(-1))
-#endif
-
 #if defined(PYOS_OS2) && !defined(PYCC_GCC)
 #define NSIG 12
 #include <process.h>
@@ -65,11 +47,11 @@
 /* utility to poll for signals that arrived */
 int pypysig_poll(void);   /* => signum or -1 */
 
-/* When a signal is received, the high bit of pypysig_occurred is set.
-   After all signals are processed by pypysig_poll(), the high bit is
+/* When a signal is received, the bit 30 of pypysig_occurred is set.
+   After all signals are processed by pypysig_poll(), the bit 30 is
    cleared again.  The variable is exposed and RPython code is free to
    use the other bits in any way. */
-#define PENDING_SIGNAL_BIT   (LONG_MIN)   /* high bit */
+#define PENDING_SIGNAL_BIT   (1 << 30)
 /* This is a struct for the JIT. See interp_signal.py. */
 struct pypysig_long_struct {
     long value;

Modified: pypy/branch/jit-unroll-loops/pypy/translator/c/src/stack.h
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/translator/c/src/stack.h	(original)
+++ pypy/branch/jit-unroll-loops/pypy/translator/c/src/stack.h	Sat Oct 30 16:41:17 2010
@@ -33,6 +33,12 @@
 		&& LL_stack_too_big_slowpath());
 }
 
+#ifdef __GNUC__
+#  define PYPY_INHIBIT_TAIL_CALL()   asm("/* inhibit_tail_call */")
+#else
+#  define PYPY_INHIBIT_TAIL_CALL()   /* add hints for other compilers here */
+#endif
+
 
 #ifndef PYPY_NOT_MAIN_FILE
 #include <stdio.h>

Modified: pypy/branch/jit-unroll-loops/pypy/translator/c/test/test_genc.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/translator/c/test/test_genc.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/translator/c/test/test_genc.py	Sat Oct 30 16:41:17 2010
@@ -426,6 +426,7 @@
     if py.test.config.option.view:
         t.view()
     assert ' BarStruct ' in t.driver.cbuilder.c_source_filename.read()
+    free(foo, flavor="raw")
 
 def test_recursive_llhelper():
     from pypy.rpython.annlowlevel import llhelper
@@ -473,7 +474,27 @@
         return f(s)
     a_f = A(f, "f")
     a_g = A(g, "g")
-    t = lltype.malloc(STRUCT, flavor="raw")
+    t = lltype.malloc(STRUCT, flavor="raw", immortal=True)
     t.bar = llhelper(FTPTR, a_f.make_func())
     fn = compile(chooser, [bool])
     assert fn(True)
+
+def test_inhibit_tail_call():
+    from pypy.rpython.lltypesystem import lltype
+    def foobar_fn(n):
+        return 42
+    foobar_fn._dont_inline_ = True
+    def main(n):
+        return foobar_fn(n)
+    #
+    t = Translation(main, [int], backend="c")
+    t.rtype()
+    t.context._graphof(foobar_fn).inhibit_tail_call = True
+    t.source_c()
+    lines = t.driver.cbuilder.c_source_filename.readlines()
+    for i, line in enumerate(lines):
+        if '= pypy_g_foobar_fn' in line:
+            break
+    else:
+        assert 0, "the call was not found in the C source"
+    assert 'PYPY_INHIBIT_TAIL_CALL();' in lines[i+1]

Modified: pypy/branch/jit-unroll-loops/pypy/translator/c/test/test_lltyped.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/translator/c/test/test_lltyped.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/translator/c/test/test_lltyped.py	Sat Oct 30 16:41:17 2010
@@ -401,6 +401,7 @@
             for i in range(n):
                 p = malloc(S, flavor='raw', zero=True)
                 if p.x != 0 or p.y != 0:
+                    free(p, flavor='raw')
                     return -1
                 p.x = i
                 p.y = i
@@ -418,14 +419,16 @@
         def f(n):
             for length in range(n-1, -1, -1):
                 p = malloc(S, length, flavor='raw', zero=True)
-                if p.x != 0:
-                    return -1
-                p.x = n
-                for j in range(length):
-                    if p.y[j] != 0:
-                        return -3
-                    p.y[j] = n^j
-                free(p, flavor='raw')
+                try:
+                    if p.x != 0:
+                        return -1
+                    p.x = n
+                    for j in range(length):
+                        if p.y[j] != 0:
+                            return -3
+                        p.y[j] = n^j
+                finally:
+                    free(p, flavor='raw')
             return 42
 
         fn = self.getcompiled(f, [int])
@@ -655,7 +658,7 @@
     def test_prebuilt_ll2ctypes_array(self):
         from pypy.rpython.lltypesystem import rffi, ll2ctypes
         A = rffi.CArray(Char)
-        a = malloc(A, 6, flavor='raw')
+        a = malloc(A, 6, flavor='raw', immortal=True)
         a[0] = 'a'
         a[1] = 'b'
         a[2] = 'c'
@@ -676,7 +679,7 @@
     def test_ll2ctypes_array_from_c(self):
         from pypy.rpython.lltypesystem import rffi, ll2ctypes
         A = rffi.CArray(Char)
-        a = malloc(A, 6, flavor='raw')
+        a = malloc(A, 6, flavor='raw', immortal=True)
         a[0] = 'a'
         a[1] = 'b'
         a[2] = 'c'

Modified: pypy/branch/jit-unroll-loops/pypy/translator/c/test/test_newgc.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/translator/c/test/test_newgc.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/translator/c/test/test_newgc.py	Sat Oct 30 16:41:17 2010
@@ -624,13 +624,13 @@
         os.unlink(self.filename)
 
     def define_callback_with_collect(cls):
-        from pypy.rlib.libffi import ffi_type_pointer, cast_type_to_ffitype,\
+        from pypy.rlib.clibffi import ffi_type_pointer, cast_type_to_ffitype,\
              CDLL, ffi_type_void, CallbackFuncPtr, ffi_type_sint
         from pypy.rpython.lltypesystem import rffi, ll2ctypes
         import gc
         ffi_size_t = cast_type_to_ffitype(rffi.SIZE_T)
 
-        from pypy.rlib.libffi import get_libc_name
+        from pypy.rlib.clibffi import get_libc_name
 
         def callback(ll_args, ll_res, stuff):
             gc.collect()

Modified: pypy/branch/jit-unroll-loops/pypy/translator/c/test/test_standalone.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/translator/c/test/test_standalone.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/translator/c/test/test_standalone.py	Sat Oct 30 16:41:17 2010
@@ -16,11 +16,16 @@
 class StandaloneTests(object):
     config = None
 
-    def compile(self, entry_point, debug=True, shared=False):
+    def compile(self, entry_point, debug=True, shared=False,
+                stackcheck=False):
         t = TranslationContext(self.config)
         t.buildannotator().build_types(entry_point, [s_list_of_strings])
         t.buildrtyper().specialize()
 
+        if stackcheck:
+            from pypy.translator.transform import insert_ll_stackcheck
+            insert_ll_stackcheck(t)
+
         t.config.translation.shared = shared
 
         cbuilder = CStandaloneBuilder(t, entry_point, t.config)
@@ -630,6 +635,22 @@
             else:
                 os.environ['CC'] = old_cc
 
+    def test_inhibit_tail_call(self):
+        # the point is to check that the f()->f() recursion stops
+        from pypy.rlib.rstackovf import StackOverflow
+        def f(n):
+            if n <= 0:
+                return 42
+            return f(n+1)
+        def entry_point(argv):
+            try:
+                return f(1)
+            except StackOverflow:
+                print 'hi!'
+                return 0
+        t, cbuilder = self.compile(entry_point, stackcheck=True)
+        out = cbuilder.cmdexec("")
+        assert out.strip() == "hi!"
 
 class TestMaemo(TestStandalone):
     def setup_class(cls):

Modified: pypy/branch/jit-unroll-loops/pypy/translator/c/test/test_typed.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/translator/c/test/test_typed.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/translator/c/test/test_typed.py	Sat Oct 30 16:41:17 2010
@@ -1,3 +1,4 @@
+from __future__ import with_statement
 import autopath
 import sys
 import math
@@ -823,3 +824,41 @@
             while int(x + frac) >= -sys.maxint-1:
                 x -= 1
             assert f(x + frac) == -666
+
+    def test_context_manager(self):
+        state = []
+        class C:
+            def __init__(self, name):
+                self.name = name
+            def __enter__(self):
+                state.append('acquire')
+                return self
+            def __exit__(self, typ, value, tb):
+                if typ is not None:
+                    if value is None:
+                        raise RuntimeError('test failed')
+                    state.append('raised')
+                else:
+                    if value is not None:
+                        raise RuntimeError('test failed')
+                state.append('release')
+
+        def func(n):
+            del state[:]
+            try:
+                with C('hello') as c:
+                    state.append(c.name)
+                    if n == 1:
+                        raise ValueError
+                    elif n == 2:
+                        raise TypeError
+            except (ValueError, TypeError):
+                pass
+            return ', '.join(state)
+        f = self.getcompiled(func, [int])
+        res = f(0)
+        assert res == 'acquire, hello, release'
+        res = f(1)
+        assert res == 'acquire, hello, raised, release'
+        res = f(2)
+        assert res == 'acquire, hello, raised, release'

Modified: pypy/branch/jit-unroll-loops/pypy/translator/driver.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/translator/driver.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/translator/driver.py	Sat Oct 30 16:41:17 2010
@@ -426,6 +426,22 @@
                                   [OOTYPE],
                                   "JIT compiler generation")
 
+    def task_jittest_lltype(self):
+        """ Run with the JIT on top of the llgraph backend
+        """
+        # parent process loop: spawn a child, wait for the child to finish,
+        # print a message, and restart
+        from pypy.translator.goal import unixcheckpoint
+        unixcheckpoint.restartable_point(auto='run')
+        # load the module pypy/jit/tl/jittest.py, which you can hack at
+        # and restart without needing to restart the whole translation process
+        from pypy.jit.tl import jittest
+        jittest.jittest(self)
+    #
+    task_jittest_lltype = taskdef(task_jittest_lltype,
+                                  [RTYPE],
+                                  "test of the JIT on the llgraph backend")
+
     def task_backendopt_lltype(self):
         """ Run all backend optimizations - lltype version
         """
@@ -433,7 +449,8 @@
         backend_optimizations(self.translator)
     #
     task_backendopt_lltype = taskdef(task_backendopt_lltype,
-                                     [RTYPE, '??pyjitpl_lltype'],
+                                     [RTYPE, '??pyjitpl_lltype',
+                                             '??jittest_lltype'],
                                      "lltype back-end optimisations")
     BACKENDOPT = 'backendopt_lltype'
 

Modified: pypy/branch/jit-unroll-loops/pypy/translator/goal/ann_override.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/translator/goal/ann_override.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/translator/goal/ann_override.py	Sat Oct 30 16:41:17 2010
@@ -27,21 +27,6 @@
         pol.pypytypes = {}
         pol.single_space = single_space
 
-    #def override__wrap_exception_cls(pol, space, x):
-    #    import pypy.objspace.std.typeobject as typeobject
-    #    clsdef = getbookkeeper().getuniqueclassdef(typeobject.W_TypeObject)
-    #    return annmodel.SomeInstance(clsdef, can_be_None=True)
-    #
-    #def override__fake_object(pol, space, x):
-    #    from pypy.interpreter import typedef
-    #    clsdef = getbookkeeper().getuniqueclassdef(typedef.W_Root)
-    #    return annmodel.SomeInstance(clsdef)    
-    #
-    #def override__cpy_compile(pol, self, source, filename, mode, flags):
-    #    from pypy.interpreter import pycode
-    #    clsdef = getbookkeeper().getuniqueclassdef(pycode.PyCode)
-    #    return annmodel.SomeInstance(clsdef)    
-
     def specialize__wrap(pol,  funcdesc, args_s):
         from pypy.interpreter.baseobjspace import Wrappable
         from pypy.annotation.classdef import ClassDef

Modified: pypy/branch/jit-unroll-loops/pypy/translator/goal/app_main.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/translator/goal/app_main.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/translator/goal/app_main.py	Sat Oct 30 16:41:17 2010
@@ -255,7 +255,7 @@
             break
         elif arg == '-u':
             unbuffered = True
-        elif arg == '-O':
+        elif arg == '-O' or arg == '-OO':
             pass
         elif arg == '--version' or arg == '-V':
             print "Python", sys.version
@@ -385,9 +385,12 @@
                 python_startup = os.getenv('PYTHONSTARTUP')
                 if python_startup:
                     try:
-                        startup = open(python_startup).read()
-                    except IOError:
-                        pass
+                        f = open(python_startup)
+                        startup = f.read()
+                        f.close()
+                    except IOError, e:
+                        print >> sys.stderr, "Could not open PYTHONSTARTUP"
+                        print >> sys.stderr, "IOError:", e
                     else:
                         def run_it():
                             co_python_startup = compile(startup,

Modified: pypy/branch/jit-unroll-loops/pypy/translator/goal/translate.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/translator/goal/translate.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/translator/goal/translate.py	Sat Oct 30 16:41:17 2010
@@ -27,6 +27,7 @@
         ("annotate", "do type inference", "-a --annotate", ""),
         ("rtype", "do rtyping", "-t --rtype", ""),
         ("pyjitpl", "JIT generation step", "--pyjitpl", ""),
+        ("jittest", "JIT test with llgraph backend", "--jittest", ""),
         ("backendopt", "do backend optimizations", "--backendopt", ""),
         ("source", "create source", "-s --source", ""),
         ("compile", "compile", "-c --compile", " (default goal)"),

Modified: pypy/branch/jit-unroll-loops/pypy/translator/jvm/test/test_class.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/translator/jvm/test/test_class.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/translator/jvm/test/test_class.py	Sat Oct 30 16:41:17 2010
@@ -1,6 +1,6 @@
 import py
 from pypy.translator.jvm.test.runtest import JvmTest
-from pypy.translator.oosupport.test_template.class_ import BaseTestClass, BaseTestSpecialcase
+from pypy.translator.oosupport.test_template.class_ import BaseTestClass
 
 class TestJvmClass(JvmTest, BaseTestClass):    
     def test_overridden_classattr_as_defaults(self):
@@ -26,6 +26,3 @@
             
     def test_specialize_methods(self):
         py.test.skip('ABSTRACT METHOD FIX: RE-TEST AFTER MERGE')
-
-class TestJvmSpecialCase(JvmTest, BaseTestSpecialcase):
-    pass

Modified: pypy/branch/jit-unroll-loops/pypy/translator/oosupport/test_template/class_.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/translator/oosupport/test_template/class_.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/translator/oosupport/test_template/class_.py	Sat Oct 30 16:41:17 2010
@@ -1,6 +1,5 @@
 import py
 from pypy.rpython.test import test_rclass
-from pypy.rpython.test.test_rspecialcase import BaseTestRspecialcase
 
 class BaseTestClass(test_rclass.TestOOtype):
     def test_abstract_method(self):
@@ -66,6 +65,3 @@
 
     def test_cast_object_mix_null(self):
         py.test.skip('cannot return ootype.NULL from translated functions')
-
-class BaseTestSpecialcase(BaseTestRspecialcase):
-    pass

Modified: pypy/branch/jit-unroll-loops/pypy/translator/platform/darwin.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/translator/platform/darwin.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/translator/platform/darwin.py	Sat Oct 30 16:41:17 2010
@@ -14,7 +14,10 @@
     
     def __init__(self, cc=None):
         if cc is None:
-            cc = 'gcc'
+            try:
+                cc = os.environ['CC']
+            except KeyError:
+                cc = 'gcc'
         self.cc = cc
 
     def _args_for_shared(self, args):

Modified: pypy/branch/jit-unroll-loops/pypy/translator/transform.py
==============================================================================
--- pypy/branch/jit-unroll-loops/pypy/translator/transform.py	(original)
+++ pypy/branch/jit-unroll-loops/pypy/translator/transform.py	Sat Oct 30 16:41:17 2010
@@ -221,15 +221,19 @@
     stack_check_ptr_const = Constant(stack_check_ptr, lltype.typeOf(stack_check_ptr))
     edges = set()
     insert_in = set()
+    block2graph = {}
     for caller in translator.graphs:
         for block, callee in find_calls_from(translator, caller):
             if getattr(getattr(callee, 'func', None),
                        'insert_stack_check_here', False):
                 insert_in.add(callee.startblock)
+                block2graph[callee.startblock] = callee
                 continue
             if block is not caller.startblock:
                 edges.add((caller.startblock, block))
+                block2graph[caller.startblock] = caller
             edges.add((block, callee.startblock))
+            block2graph[block] = caller
 
     edgelist = [Edge(block1, block2) for (block1, block2) in edges]
     edgedict = make_edge_dict(edgelist)
@@ -241,6 +245,10 @@
         v.concretetype = lltype.Void
         unwind_op = SpaceOperation('direct_call', [stack_check_ptr_const], v)
         block.operations.insert(0, unwind_op)
+        # prevents cycles of tail calls from occurring -- such cycles would
+        # not consume any stack, so would turn into potentially infinite loops
+        graph = block2graph[block]
+        graph.inhibit_tail_call = True
     return len(insert_in)
 
 



More information about the Pypy-commit mailing list