[pypy-svn] r79935 - in pypy/branch/out-of-line-guards: . ctypes_configure lib-python lib-python/modified-2.5.2/distutils lib-python/modified-2.5.2/distutils/tests lib-python/modified-2.5.2/encodings lib-python/modified-2.5.2/test lib-python/modified-2.5.2/test/output lib_pypy lib_pypy/_ctypes lib_pypy/pypy_test pypy pypy/annotation pypy/annotation/test pypy/config pypy/doc pypy/doc/config pypy/doc/statistic pypy/interpreter pypy/interpreter/pyparser pypy/interpreter/pyparser/test pypy/interpreter/test pypy/jit pypy/jit/backend pypy/jit/backend/llgraph pypy/jit/backend/llsupport pypy/jit/backend/llsupport/test pypy/jit/backend/test pypy/jit/backend/x86 pypy/jit/backend/x86/test pypy/jit/codewriter pypy/jit/codewriter/test pypy/jit/metainterp pypy/jit/metainterp/optimizeopt pypy/jit/metainterp/test pypy/jit/tl pypy/jit/tl/spli pypy/jit/tool pypy/jit/tool/test pypy/module/__pypy__ pypy/module/__pypy__/test pypy/module/_lsprof pypy/module/_lsprof/test pypy/module/_minimal_curses pypy/module/_pickle_support pypy/module/_stackless pypy/module/array/benchmark pypy/module/array/test pypy/module/binascii pypy/module/binascii/test pypy/module/cpyext pypy/module/cpyext/include pypy/module/cpyext/src pypy/module/cpyext/test pypy/module/exceptions pypy/module/fcntl/test pypy/module/imp pypy/module/itertools pypy/module/posix pypy/module/posix/test pypy/module/pyexpat pypy/module/pyexpat/test pypy/module/pypyjit pypy/module/pypyjit/test pypy/module/sys pypy/module/sys/test pypy/module/test_lib_pypy/ctypes_tests pypy/objspace/std pypy/objspace/std/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/gc pypy/rpython/memory/gc/test pypy/rpython/memory/gctransform pypy/rpython/module pypy/rpython/ootypesystem pypy/rpython/test pypy/tool pypy/tool/release pypy/tool/release/test pypy/translator pypy/translator/c pypy/translator/c/gcc pypy/translator/c/gcc/test pypy/translator/c/src pypy/translator/c/test pypy/translator/goal pypy/translator/goal/test2 pypy/translator/platform pypy/translator/sandbox/test pypy/translator/tool site-packages
fijal at codespeak.net
fijal at codespeak.net
Thu Dec 9 16:34:16 CET 2010
Author: fijal
Date: Thu Dec 9 16:33:59 2010
New Revision: 79935
Added:
pypy/branch/out-of-line-guards/lib-python/modified-2.5.2/test/test_eof.py
- copied unchanged from r79934, pypy/trunk/lib-python/modified-2.5.2/test/test_eof.py
pypy/branch/out-of-line-guards/pypy/jit/backend/x86/codebuf.py
- copied unchanged from r79934, pypy/trunk/pypy/jit/backend/x86/codebuf.py
pypy/branch/out-of-line-guards/pypy/module/binascii/ (props changed)
- copied from r79934, pypy/trunk/pypy/module/binascii/
Removed:
pypy/branch/out-of-line-guards/lib-python/modified-2.5.2/encodings/
pypy/branch/out-of-line-guards/pypy/doc/config/translation.jit_debug.txt
pypy/branch/out-of-line-guards/pypy/translator/platform/freebsd7.py
Modified:
pypy/branch/out-of-line-guards/ (props changed)
pypy/branch/out-of-line-guards/ctypes_configure/configure.py
pypy/branch/out-of-line-guards/lib-python/conftest.py
pypy/branch/out-of-line-guards/lib-python/modified-2.5.2/distutils/msvccompiler.py
pypy/branch/out-of-line-guards/lib-python/modified-2.5.2/distutils/tests/test_msvccompiler.py
pypy/branch/out-of-line-guards/lib-python/modified-2.5.2/distutils/unixccompiler.py
pypy/branch/out-of-line-guards/lib-python/modified-2.5.2/test/output/test_cProfile
pypy/branch/out-of-line-guards/lib-python/modified-2.5.2/test/test_genexps.py
pypy/branch/out-of-line-guards/lib_pypy/_ctypes/array.py
pypy/branch/out-of-line-guards/lib_pypy/_ctypes/basics.py
pypy/branch/out-of-line-guards/lib_pypy/_ctypes/builtin.py
pypy/branch/out-of-line-guards/lib_pypy/_ctypes/function.py
pypy/branch/out-of-line-guards/lib_pypy/_ctypes/pointer.py
pypy/branch/out-of-line-guards/lib_pypy/_ctypes/primitive.py
pypy/branch/out-of-line-guards/lib_pypy/_ctypes/structure.py
pypy/branch/out-of-line-guards/lib_pypy/_hashlib.py
pypy/branch/out-of-line-guards/lib_pypy/_locale.py
pypy/branch/out-of-line-guards/lib_pypy/_marshal.py
pypy/branch/out-of-line-guards/lib_pypy/_minimal_curses.py
pypy/branch/out-of-line-guards/lib_pypy/_pypy_interact.py
pypy/branch/out-of-line-guards/lib_pypy/binascii.py
pypy/branch/out-of-line-guards/lib_pypy/cPickle.py
pypy/branch/out-of-line-guards/lib_pypy/cmath.py
pypy/branch/out-of-line-guards/lib_pypy/ctypes_support.py
pypy/branch/out-of-line-guards/lib_pypy/grp.py
pypy/branch/out-of-line-guards/lib_pypy/hashlib.py
pypy/branch/out-of-line-guards/lib_pypy/itertools.py
pypy/branch/out-of-line-guards/lib_pypy/msvcrt.py
pypy/branch/out-of-line-guards/lib_pypy/pwd.py
pypy/branch/out-of-line-guards/lib_pypy/pyexpat.py
pypy/branch/out-of-line-guards/lib_pypy/pypy_test/test_hashlib.py
pypy/branch/out-of-line-guards/lib_pypy/pypy_test/test_structseq.py
pypy/branch/out-of-line-guards/lib_pypy/readline.py
pypy/branch/out-of-line-guards/lib_pypy/resource.py
pypy/branch/out-of-line-guards/lib_pypy/syslog.py
pypy/branch/out-of-line-guards/pypy/ (props changed)
pypy/branch/out-of-line-guards/pypy/annotation/annrpython.py
pypy/branch/out-of-line-guards/pypy/annotation/binaryop.py
pypy/branch/out-of-line-guards/pypy/annotation/bookkeeper.py
pypy/branch/out-of-line-guards/pypy/annotation/description.py
pypy/branch/out-of-line-guards/pypy/annotation/listdef.py
pypy/branch/out-of-line-guards/pypy/annotation/model.py
pypy/branch/out-of-line-guards/pypy/annotation/specialize.py
pypy/branch/out-of-line-guards/pypy/annotation/test/test_annrpython.py
pypy/branch/out-of-line-guards/pypy/annotation/unaryop.py
pypy/branch/out-of-line-guards/pypy/config/pypyoption.py
pypy/branch/out-of-line-guards/pypy/config/translationoption.py
pypy/branch/out-of-line-guards/pypy/conftest.py
pypy/branch/out-of-line-guards/pypy/doc/cpython_differences.txt
pypy/branch/out-of-line-guards/pypy/doc/faq.txt
pypy/branch/out-of-line-guards/pypy/doc/index.txt
pypy/branch/out-of-line-guards/pypy/doc/release-1.4.0.txt
pypy/branch/out-of-line-guards/pypy/doc/sprint-reports.txt
pypy/branch/out-of-line-guards/pypy/doc/statistic/release_dates.dat
pypy/branch/out-of-line-guards/pypy/doc/statistic/sprint_dates.dat
pypy/branch/out-of-line-guards/pypy/interpreter/argument.py
pypy/branch/out-of-line-guards/pypy/interpreter/baseobjspace.py
pypy/branch/out-of-line-guards/pypy/interpreter/executioncontext.py
pypy/branch/out-of-line-guards/pypy/interpreter/function.py
pypy/branch/out-of-line-guards/pypy/interpreter/gateway.py
pypy/branch/out-of-line-guards/pypy/interpreter/generator.py
pypy/branch/out-of-line-guards/pypy/interpreter/mixedmodule.py
pypy/branch/out-of-line-guards/pypy/interpreter/pycode.py
pypy/branch/out-of-line-guards/pypy/interpreter/pyparser/error.py
pypy/branch/out-of-line-guards/pypy/interpreter/pyparser/pytokenizer.py
pypy/branch/out-of-line-guards/pypy/interpreter/pyparser/test/test_pyparse.py
pypy/branch/out-of-line-guards/pypy/interpreter/test/test_argument.py
pypy/branch/out-of-line-guards/pypy/interpreter/test/test_compiler.py
pypy/branch/out-of-line-guards/pypy/interpreter/test/test_executioncontext.py
pypy/branch/out-of-line-guards/pypy/interpreter/test/test_function.py
pypy/branch/out-of-line-guards/pypy/interpreter/test/test_gateway.py
pypy/branch/out-of-line-guards/pypy/jit/backend/detect_cpu.py
pypy/branch/out-of-line-guards/pypy/jit/backend/llgraph/llimpl.py
pypy/branch/out-of-line-guards/pypy/jit/backend/llgraph/runner.py
pypy/branch/out-of-line-guards/pypy/jit/backend/llsupport/gc.py
pypy/branch/out-of-line-guards/pypy/jit/backend/llsupport/llmodel.py
pypy/branch/out-of-line-guards/pypy/jit/backend/llsupport/test/test_gc.py
pypy/branch/out-of-line-guards/pypy/jit/backend/model.py
pypy/branch/out-of-line-guards/pypy/jit/backend/test/runner_test.py
pypy/branch/out-of-line-guards/pypy/jit/backend/test/test_random.py
pypy/branch/out-of-line-guards/pypy/jit/backend/x86/assembler.py
pypy/branch/out-of-line-guards/pypy/jit/backend/x86/regalloc.py
pypy/branch/out-of-line-guards/pypy/jit/backend/x86/regloc.py
pypy/branch/out-of-line-guards/pypy/jit/backend/x86/runner.py
pypy/branch/out-of-line-guards/pypy/jit/backend/x86/rx86.py
pypy/branch/out-of-line-guards/pypy/jit/backend/x86/support.py
pypy/branch/out-of-line-guards/pypy/jit/backend/x86/test/test_assembler.py
pypy/branch/out-of-line-guards/pypy/jit/backend/x86/test/test_gc_integration.py
pypy/branch/out-of-line-guards/pypy/jit/backend/x86/test/test_regalloc.py
pypy/branch/out-of-line-guards/pypy/jit/backend/x86/test/test_regalloc2.py
pypy/branch/out-of-line-guards/pypy/jit/backend/x86/test/test_regloc.py
pypy/branch/out-of-line-guards/pypy/jit/backend/x86/test/test_runner.py
pypy/branch/out-of-line-guards/pypy/jit/backend/x86/test/test_rx86.py
pypy/branch/out-of-line-guards/pypy/jit/backend/x86/test/test_zll_random.py
pypy/branch/out-of-line-guards/pypy/jit/backend/x86/test/test_zmath.py
pypy/branch/out-of-line-guards/pypy/jit/backend/x86/valgrind.py
pypy/branch/out-of-line-guards/pypy/jit/codewriter/call.py
pypy/branch/out-of-line-guards/pypy/jit/codewriter/jtransform.py
pypy/branch/out-of-line-guards/pypy/jit/codewriter/regalloc.py
pypy/branch/out-of-line-guards/pypy/jit/codewriter/support.py
pypy/branch/out-of-line-guards/pypy/jit/codewriter/test/test_codewriter.py
pypy/branch/out-of-line-guards/pypy/jit/codewriter/test/test_list.py
pypy/branch/out-of-line-guards/pypy/jit/codewriter/test/test_regalloc.py
pypy/branch/out-of-line-guards/pypy/jit/codewriter/test/test_void_list.py
pypy/branch/out-of-line-guards/pypy/jit/conftest.py
pypy/branch/out-of-line-guards/pypy/jit/metainterp/compile.py
pypy/branch/out-of-line-guards/pypy/jit/metainterp/history.py
pypy/branch/out-of-line-guards/pypy/jit/metainterp/jitprof.py
pypy/branch/out-of-line-guards/pypy/jit/metainterp/optimizefindnode.py
pypy/branch/out-of-line-guards/pypy/jit/metainterp/optimizeopt/__init__.py
pypy/branch/out-of-line-guards/pypy/jit/metainterp/optimizeopt/optimizer.py (contents, props changed)
pypy/branch/out-of-line-guards/pypy/jit/metainterp/pyjitpl.py
pypy/branch/out-of-line-guards/pypy/jit/metainterp/test/test_basic.py
pypy/branch/out-of-line-guards/pypy/jit/metainterp/test/test_compile.py
pypy/branch/out-of-line-guards/pypy/jit/metainterp/test/test_exception.py
pypy/branch/out-of-line-guards/pypy/jit/metainterp/test/test_fficall.py
pypy/branch/out-of-line-guards/pypy/jit/metainterp/test/test_list.py
pypy/branch/out-of-line-guards/pypy/jit/metainterp/test/test_logger.py
pypy/branch/out-of-line-guards/pypy/jit/metainterp/test/test_optimizefficall.py
pypy/branch/out-of-line-guards/pypy/jit/metainterp/test/test_optimizeopt.py
pypy/branch/out-of-line-guards/pypy/jit/metainterp/test/test_pyjitpl.py
pypy/branch/out-of-line-guards/pypy/jit/metainterp/test/test_recursive.py
pypy/branch/out-of-line-guards/pypy/jit/metainterp/test/test_virtualizable.py
pypy/branch/out-of-line-guards/pypy/jit/metainterp/test/test_warmspot.py
pypy/branch/out-of-line-guards/pypy/jit/metainterp/test/test_warmstate.py
pypy/branch/out-of-line-guards/pypy/jit/metainterp/warmspot.py
pypy/branch/out-of-line-guards/pypy/jit/metainterp/warmstate.py
pypy/branch/out-of-line-guards/pypy/jit/tl/spli/interpreter.py
pypy/branch/out-of-line-guards/pypy/jit/tl/tl.py
pypy/branch/out-of-line-guards/pypy/jit/tool/jitoutput.py
pypy/branch/out-of-line-guards/pypy/jit/tool/test/test_jitoutput.py
pypy/branch/out-of-line-guards/pypy/module/__pypy__/__init__.py
pypy/branch/out-of-line-guards/pypy/module/__pypy__/interp_magic.py
pypy/branch/out-of-line-guards/pypy/module/__pypy__/test/test_special.py
pypy/branch/out-of-line-guards/pypy/module/_lsprof/interp_lsprof.py
pypy/branch/out-of-line-guards/pypy/module/_lsprof/test/test_cprofile.py
pypy/branch/out-of-line-guards/pypy/module/_minimal_curses/__init__.py
pypy/branch/out-of-line-guards/pypy/module/_pickle_support/maker.py
pypy/branch/out-of-line-guards/pypy/module/_stackless/interp_coroutine.py
pypy/branch/out-of-line-guards/pypy/module/array/benchmark/Makefile (props changed)
pypy/branch/out-of-line-guards/pypy/module/array/benchmark/intimg.c (props changed)
pypy/branch/out-of-line-guards/pypy/module/array/benchmark/intimgtst.c (props changed)
pypy/branch/out-of-line-guards/pypy/module/array/benchmark/intimgtst.py (props changed)
pypy/branch/out-of-line-guards/pypy/module/array/benchmark/loop.c (props changed)
pypy/branch/out-of-line-guards/pypy/module/array/benchmark/sum.c (props changed)
pypy/branch/out-of-line-guards/pypy/module/array/benchmark/sumtst.c (props changed)
pypy/branch/out-of-line-guards/pypy/module/array/benchmark/sumtst.py (props changed)
pypy/branch/out-of-line-guards/pypy/module/array/test/test_array.py
pypy/branch/out-of-line-guards/pypy/module/array/test/test_array_old.py (props changed)
pypy/branch/out-of-line-guards/pypy/module/binascii/test/ (props changed)
pypy/branch/out-of-line-guards/pypy/module/cpyext/__init__.py
pypy/branch/out-of-line-guards/pypy/module/cpyext/api.py
pypy/branch/out-of-line-guards/pypy/module/cpyext/cdatetime.py
pypy/branch/out-of-line-guards/pypy/module/cpyext/include/Python.h
pypy/branch/out-of-line-guards/pypy/module/cpyext/intobject.py
pypy/branch/out-of-line-guards/pypy/module/cpyext/object.py
pypy/branch/out-of-line-guards/pypy/module/cpyext/pyerrors.py
pypy/branch/out-of-line-guards/pypy/module/cpyext/pythonrun.py
pypy/branch/out-of-line-guards/pypy/module/cpyext/sequence.py
pypy/branch/out-of-line-guards/pypy/module/cpyext/slotdefs.py
pypy/branch/out-of-line-guards/pypy/module/cpyext/src/getargs.c
pypy/branch/out-of-line-guards/pypy/module/cpyext/state.py
pypy/branch/out-of-line-guards/pypy/module/cpyext/stubs.py
pypy/branch/out-of-line-guards/pypy/module/cpyext/test/test_arraymodule.py
pypy/branch/out-of-line-guards/pypy/module/cpyext/test/test_cpyext.py
pypy/branch/out-of-line-guards/pypy/module/cpyext/test/test_datetime.py
pypy/branch/out-of-line-guards/pypy/module/cpyext/test/test_intobject.py
pypy/branch/out-of-line-guards/pypy/module/cpyext/test/test_object.py
pypy/branch/out-of-line-guards/pypy/module/cpyext/test/test_pyerrors.py
pypy/branch/out-of-line-guards/pypy/module/cpyext/test/test_sequence.py
pypy/branch/out-of-line-guards/pypy/module/cpyext/test/test_typeobject.py
pypy/branch/out-of-line-guards/pypy/module/cpyext/typeobject.py
pypy/branch/out-of-line-guards/pypy/module/exceptions/interp_exceptions.py
pypy/branch/out-of-line-guards/pypy/module/fcntl/test/test_fcntl.py
pypy/branch/out-of-line-guards/pypy/module/imp/importing.py
pypy/branch/out-of-line-guards/pypy/module/itertools/interp_itertools.py
pypy/branch/out-of-line-guards/pypy/module/posix/__init__.py
pypy/branch/out-of-line-guards/pypy/module/posix/interp_posix.py
pypy/branch/out-of-line-guards/pypy/module/posix/test/test_posix2.py
pypy/branch/out-of-line-guards/pypy/module/pyexpat/interp_pyexpat.py
pypy/branch/out-of-line-guards/pypy/module/pyexpat/test/test_parser.py
pypy/branch/out-of-line-guards/pypy/module/pypyjit/policy.py
pypy/branch/out-of-line-guards/pypy/module/pypyjit/test/test_policy.py
pypy/branch/out-of-line-guards/pypy/module/pypyjit/test/test_pypy_c.py
pypy/branch/out-of-line-guards/pypy/module/sys/__init__.py
pypy/branch/out-of-line-guards/pypy/module/sys/state.py
pypy/branch/out-of-line-guards/pypy/module/sys/test/test_initialpath.py
pypy/branch/out-of-line-guards/pypy/module/sys/vm.py
pypy/branch/out-of-line-guards/pypy/module/test_lib_pypy/ctypes_tests/test_guess_argtypes.py
pypy/branch/out-of-line-guards/pypy/module/test_lib_pypy/ctypes_tests/test_keepalive.py
pypy/branch/out-of-line-guards/pypy/objspace/std/complexobject.py
pypy/branch/out-of-line-guards/pypy/objspace/std/complextype.py
pypy/branch/out-of-line-guards/pypy/objspace/std/floattype.py
pypy/branch/out-of-line-guards/pypy/objspace/std/longobject.py
pypy/branch/out-of-line-guards/pypy/objspace/std/mapdict.py
pypy/branch/out-of-line-guards/pypy/objspace/std/objspace.py
pypy/branch/out-of-line-guards/pypy/objspace/std/strutil.py
pypy/branch/out-of-line-guards/pypy/objspace/std/test/test_complexobject.py
pypy/branch/out-of-line-guards/pypy/objspace/std/test/test_strutil.py
pypy/branch/out-of-line-guards/pypy/rlib/debug.py
pypy/branch/out-of-line-guards/pypy/rlib/jit.py
pypy/branch/out-of-line-guards/pypy/rlib/libffi.py
pypy/branch/out-of-line-guards/pypy/rlib/rarithmetic.py
pypy/branch/out-of-line-guards/pypy/rlib/rdynload.py
pypy/branch/out-of-line-guards/pypy/rlib/rerased.py (contents, props changed)
pypy/branch/out-of-line-guards/pypy/rlib/rmmap.py
pypy/branch/out-of-line-guards/pypy/rlib/rsre/rsre_core.py
pypy/branch/out-of-line-guards/pypy/rlib/rsre/test/test_zjit.py
pypy/branch/out-of-line-guards/pypy/rlib/test/test_debug.py
pypy/branch/out-of-line-guards/pypy/rlib/test/test_libffi.py
pypy/branch/out-of-line-guards/pypy/rlib/test/test_rerased.py (props changed)
pypy/branch/out-of-line-guards/pypy/rpython/extfunc.py
pypy/branch/out-of-line-guards/pypy/rpython/lltypesystem/ll2ctypes.py
pypy/branch/out-of-line-guards/pypy/rpython/lltypesystem/llarena.py
pypy/branch/out-of-line-guards/pypy/rpython/lltypesystem/llmemory.py
pypy/branch/out-of-line-guards/pypy/rpython/lltypesystem/lltype.py
pypy/branch/out-of-line-guards/pypy/rpython/lltypesystem/rbuiltin.py
pypy/branch/out-of-line-guards/pypy/rpython/lltypesystem/rclass.py
pypy/branch/out-of-line-guards/pypy/rpython/lltypesystem/rdict.py
pypy/branch/out-of-line-guards/pypy/rpython/lltypesystem/rpbc.py
pypy/branch/out-of-line-guards/pypy/rpython/lltypesystem/test/test_llarena.py
pypy/branch/out-of-line-guards/pypy/rpython/memory/gc/base.py
pypy/branch/out-of-line-guards/pypy/rpython/memory/gc/generation.py
pypy/branch/out-of-line-guards/pypy/rpython/memory/gc/inspector.py
pypy/branch/out-of-line-guards/pypy/rpython/memory/gc/markcompact.py
pypy/branch/out-of-line-guards/pypy/rpython/memory/gc/minimark.py
pypy/branch/out-of-line-guards/pypy/rpython/memory/gc/semispace.py
pypy/branch/out-of-line-guards/pypy/rpython/memory/gc/test/test_direct.py
pypy/branch/out-of-line-guards/pypy/rpython/memory/gctransform/asmgcroot.py
pypy/branch/out-of-line-guards/pypy/rpython/memory/gctransform/boehm.py
pypy/branch/out-of-line-guards/pypy/rpython/memory/gctransform/framework.py
pypy/branch/out-of-line-guards/pypy/rpython/memory/gctransform/refcounting.py
pypy/branch/out-of-line-guards/pypy/rpython/memory/gctransform/support.py
pypy/branch/out-of-line-guards/pypy/rpython/module/ll_os.py
pypy/branch/out-of-line-guards/pypy/rpython/module/ll_time.py
pypy/branch/out-of-line-guards/pypy/rpython/ootypesystem/rpbc.py
pypy/branch/out-of-line-guards/pypy/rpython/rlist.py
pypy/branch/out-of-line-guards/pypy/rpython/rpbc.py
pypy/branch/out-of-line-guards/pypy/rpython/test/test_rclass.py
pypy/branch/out-of-line-guards/pypy/rpython/test/test_rint.py
pypy/branch/out-of-line-guards/pypy/rpython/test/test_rlist.py
pypy/branch/out-of-line-guards/pypy/tool/ansi_print.py
pypy/branch/out-of-line-guards/pypy/tool/error.py
pypy/branch/out-of-line-guards/pypy/tool/logparser.py
pypy/branch/out-of-line-guards/pypy/tool/release/force-builds.py
pypy/branch/out-of-line-guards/pypy/tool/release/make_release.py
pypy/branch/out-of-line-guards/pypy/tool/release/package.py
pypy/branch/out-of-line-guards/pypy/tool/release/test/test_package.py
pypy/branch/out-of-line-guards/pypy/translator/c/funcgen.py
pypy/branch/out-of-line-guards/pypy/translator/c/gcc/test/test_trackgcroot.py
pypy/branch/out-of-line-guards/pypy/translator/c/gcc/trackgcroot.py
pypy/branch/out-of-line-guards/pypy/translator/c/src/debug_alloc.h
pypy/branch/out-of-line-guards/pypy/translator/c/src/debug_print.h
pypy/branch/out-of-line-guards/pypy/translator/c/src/mem.h
pypy/branch/out-of-line-guards/pypy/translator/c/test/test_newgc.py
pypy/branch/out-of-line-guards/pypy/translator/c/test/test_standalone.py
pypy/branch/out-of-line-guards/pypy/translator/driver.py
pypy/branch/out-of-line-guards/pypy/translator/goal/app_main.py
pypy/branch/out-of-line-guards/pypy/translator/goal/test2/test_app_main.py
pypy/branch/out-of-line-guards/pypy/translator/platform/__init__.py
pypy/branch/out-of-line-guards/pypy/translator/platform/darwin.py
pypy/branch/out-of-line-guards/pypy/translator/platform/linux.py
pypy/branch/out-of-line-guards/pypy/translator/platform/posix.py
pypy/branch/out-of-line-guards/pypy/translator/sandbox/test/test_sandbox.py
pypy/branch/out-of-line-guards/pypy/translator/tool/cbuild.py
pypy/branch/out-of-line-guards/pypy/translator/tool/reftracker.py
pypy/branch/out-of-line-guards/site-packages/ (props changed)
Log:
Merge from trunk r79309:HEAD
Modified: pypy/branch/out-of-line-guards/ctypes_configure/configure.py
==============================================================================
--- pypy/branch/out-of-line-guards/ctypes_configure/configure.py (original)
+++ pypy/branch/out-of-line-guards/ctypes_configure/configure.py Thu Dec 9 16:33:59 2010
@@ -559,6 +559,7 @@
C_HEADER = """
#include <stdio.h>
#include <stddef.h> /* for offsetof() */
+#include <stdint.h> /* FreeBSD: for uint64_t */
void dump(char* key, int value) {
printf("%s: %d\\n", key, value);
Modified: pypy/branch/out-of-line-guards/lib-python/conftest.py
==============================================================================
--- pypy/branch/out-of-line-guards/lib-python/conftest.py (original)
+++ pypy/branch/out-of-line-guards/lib-python/conftest.py Thu Dec 9 16:33:59 2010
@@ -139,7 +139,7 @@
RegrTest('test_augassign.py', core=True),
RegrTest('test_base64.py'),
RegrTest('test_bastion.py'),
- RegrTest('test_binascii.py'),
+ RegrTest('test_binascii.py', usemodules='binascii'),
RegrTest('test_binhex.py'),
Modified: pypy/branch/out-of-line-guards/lib-python/modified-2.5.2/distutils/msvccompiler.py
==============================================================================
--- pypy/branch/out-of-line-guards/lib-python/modified-2.5.2/distutils/msvccompiler.py (original)
+++ pypy/branch/out-of-line-guards/lib-python/modified-2.5.2/distutils/msvccompiler.py Thu Dec 9 16:33:59 2010
@@ -25,17 +25,20 @@
from distutils import log
from distutils.util import get_platform
-import _winreg
-
-RegOpenKeyEx = _winreg.OpenKeyEx
-RegEnumKey = _winreg.EnumKey
-RegEnumValue = _winreg.EnumValue
-RegError = _winreg.error
-
-HKEYS = (_winreg.HKEY_USERS,
- _winreg.HKEY_CURRENT_USER,
- _winreg.HKEY_LOCAL_MACHINE,
- _winreg.HKEY_CLASSES_ROOT)
+try:
+ import _winreg
+except ImportError:
+ pass
+else:
+ RegOpenKeyEx = _winreg.OpenKeyEx
+ RegEnumKey = _winreg.EnumKey
+ RegEnumValue = _winreg.EnumValue
+ RegError = _winreg.error
+
+ HKEYS = (_winreg.HKEY_USERS,
+ _winreg.HKEY_CURRENT_USER,
+ _winreg.HKEY_LOCAL_MACHINE,
+ _winreg.HKEY_CLASSES_ROOT)
VS_BASE = r"Software\Microsoft\VisualStudio\%0.1f"
VSEXPRESS_BASE = r"Software\Microsoft\VCExpress\%0.1f"
Modified: pypy/branch/out-of-line-guards/lib-python/modified-2.5.2/distutils/tests/test_msvccompiler.py
==============================================================================
--- pypy/branch/out-of-line-guards/lib-python/modified-2.5.2/distutils/tests/test_msvccompiler.py (original)
+++ pypy/branch/out-of-line-guards/lib-python/modified-2.5.2/distutils/tests/test_msvccompiler.py Thu Dec 9 16:33:59 2010
@@ -11,11 +11,15 @@
else:
self.fail("could not find a suitable manifest")
+class MsvcCompilerSimplerTestCase(unittest.TestCase):
+ def test_import_module(self):
+ from distutils.msvccompiler import MSVCCompiler
+
def test_suite():
if sys.platform == 'win32':
return unittest.makeSuite(MsvcCompilerTestCase)
else:
- return unittest.TestSuite([])
+ return unittest.makeSuite(MsvcCompilerSimplerTestCase)
if __name__ == "__main__":
unittest.main(defaultTest="test_suite")
Modified: pypy/branch/out-of-line-guards/lib-python/modified-2.5.2/distutils/unixccompiler.py
==============================================================================
--- pypy/branch/out-of-line-guards/lib-python/modified-2.5.2/distutils/unixccompiler.py (original)
+++ pypy/branch/out-of-line-guards/lib-python/modified-2.5.2/distutils/unixccompiler.py Thu Dec 9 16:33:59 2010
@@ -121,7 +121,22 @@
}
if sys.platform[:6] == "darwin":
+ import platform
+ if platform.machine() == 'i386':
+ if platform.architecture()[0] == '32bit':
+ arch = 'i386'
+ else:
+ arch = 'x86_64'
+ else:
+ # just a guess
+ arch = platform.machine()
executables['ranlib'] = ["ranlib"]
+ executables['linker_so'] += ['-undefined', 'dynamic_lookup']
+
+ for k, v in executables.iteritems():
+ if v and v[0] == 'cc':
+ v += ['-arch', arch]
+
# Needed for the filename generation methods provided by the base
# class, CCompiler. NB. whoever instantiates/uses a particular
Modified: pypy/branch/out-of-line-guards/lib-python/modified-2.5.2/test/output/test_cProfile
==============================================================================
--- pypy/branch/out-of-line-guards/lib-python/modified-2.5.2/test/output/test_cProfile (original)
+++ pypy/branch/out-of-line-guards/lib-python/modified-2.5.2/test/output/test_cProfile Thu Dec 9 16:33:59 2010
@@ -14,66 +14,66 @@
4 0.116 0.029 0.120 0.030 test_cProfile.py:78(helper1)
2 0.000 0.000 0.140 0.070 test_cProfile.py:89(helper2_indirect)
8 0.312 0.039 0.400 0.050 test_cProfile.py:93(helper2)
- 4 0.000 0.000 0.000 0.000 {append}
- 1 0.000 0.000 0.000 0.000 {disable}
12 0.000 0.000 0.012 0.001 {hasattr}
+ 4 0.000 0.000 0.000 0.000 {method 'append' of 'list' objects}
+ 1 0.000 0.000 0.000 0.000 {method 'disable' of 'Profile' objects}
8 0.000 0.000 0.000 0.000 {range}
4 0.000 0.000 0.000 0.000 {sys.exc_info}
Ordered by: standard name
-Function called...
- ncalls tottime cumtime
-<string>:1(<module>) -> 1 0.270 1.000 test_cProfile.py:30(testfunc)
-test_cProfile.py:103(subhelper) -> 16 0.016 0.016 test_cProfile.py:115(__getattr__)
- 8 0.000 0.000 {range}
-test_cProfile.py:115(__getattr__) ->
-test_cProfile.py:30(testfunc) -> 1 0.014 0.130 test_cProfile.py:40(factorial)
- 2 0.040 0.600 test_cProfile.py:60(helper)
-test_cProfile.py:40(factorial) -> 20/3 0.130 0.147 test_cProfile.py:40(factorial)
- 20 0.020 0.020 test_cProfile.py:53(mul)
-test_cProfile.py:53(mul) ->
-test_cProfile.py:60(helper) -> 4 0.116 0.120 test_cProfile.py:78(helper1)
- 2 0.000 0.140 test_cProfile.py:89(helper2_indirect)
- 6 0.234 0.300 test_cProfile.py:93(helper2)
-test_cProfile.py:78(helper1) -> 4 0.000 0.000 {append}
- 4 0.000 0.004 {hasattr}
- 4 0.000 0.000 {sys.exc_info}
-test_cProfile.py:89(helper2_indirect) -> 2 0.006 0.040 test_cProfile.py:40(factorial)
- 2 0.078 0.100 test_cProfile.py:93(helper2)
-test_cProfile.py:93(helper2) -> 8 0.064 0.080 test_cProfile.py:103(subhelper)
- 8 0.000 0.008 {hasattr}
-{append} ->
-{disable} ->
-{hasattr} -> 12 0.012 0.012 test_cProfile.py:115(__getattr__)
-{range} ->
-{sys.exc_info} ->
+Function called...
+ ncalls tottime cumtime
+<string>:1(<module>) -> 1 0.270 1.000 test_cProfile.py:30(testfunc)
+test_cProfile.py:103(subhelper) -> 16 0.016 0.016 test_cProfile.py:115(__getattr__)
+ 8 0.000 0.000 {range}
+test_cProfile.py:115(__getattr__) ->
+test_cProfile.py:30(testfunc) -> 1 0.014 0.130 test_cProfile.py:40(factorial)
+ 2 0.040 0.600 test_cProfile.py:60(helper)
+test_cProfile.py:40(factorial) -> 20/3 0.130 0.147 test_cProfile.py:40(factorial)
+ 20 0.020 0.020 test_cProfile.py:53(mul)
+test_cProfile.py:53(mul) ->
+test_cProfile.py:60(helper) -> 4 0.116 0.120 test_cProfile.py:78(helper1)
+ 2 0.000 0.140 test_cProfile.py:89(helper2_indirect)
+ 6 0.234 0.300 test_cProfile.py:93(helper2)
+test_cProfile.py:78(helper1) -> 4 0.000 0.004 {hasattr}
+ 4 0.000 0.000 {method 'append' of 'list' objects}
+ 4 0.000 0.000 {sys.exc_info}
+test_cProfile.py:89(helper2_indirect) -> 2 0.006 0.040 test_cProfile.py:40(factorial)
+ 2 0.078 0.100 test_cProfile.py:93(helper2)
+test_cProfile.py:93(helper2) -> 8 0.064 0.080 test_cProfile.py:103(subhelper)
+ 8 0.000 0.008 {hasattr}
+{hasattr} -> 12 0.012 0.012 test_cProfile.py:115(__getattr__)
+{method 'append' of 'list' objects} ->
+{method 'disable' of 'Profile' objects} ->
+{range} ->
+{sys.exc_info} ->
Ordered by: standard name
-Function was called by...
- ncalls tottime cumtime
-<string>:1(<module>) <-
-test_cProfile.py:103(subhelper) <- 8 0.064 0.080 test_cProfile.py:93(helper2)
-test_cProfile.py:115(__getattr__) <- 16 0.016 0.016 test_cProfile.py:103(subhelper)
- 12 0.012 0.012 {hasattr}
-test_cProfile.py:30(testfunc) <- 1 0.270 1.000 <string>:1(<module>)
-test_cProfile.py:40(factorial) <- 1 0.014 0.130 test_cProfile.py:30(testfunc)
- 20/3 0.130 0.147 test_cProfile.py:40(factorial)
- 2 0.006 0.040 test_cProfile.py:89(helper2_indirect)
-test_cProfile.py:53(mul) <- 20 0.020 0.020 test_cProfile.py:40(factorial)
-test_cProfile.py:60(helper) <- 2 0.040 0.600 test_cProfile.py:30(testfunc)
-test_cProfile.py:78(helper1) <- 4 0.116 0.120 test_cProfile.py:60(helper)
-test_cProfile.py:89(helper2_indirect) <- 2 0.000 0.140 test_cProfile.py:60(helper)
-test_cProfile.py:93(helper2) <- 6 0.234 0.300 test_cProfile.py:60(helper)
- 2 0.078 0.100 test_cProfile.py:89(helper2_indirect)
-{append} <- 4 0.000 0.000 test_cProfile.py:78(helper1)
-{disable} <-
-{hasattr} <- 4 0.000 0.004 test_cProfile.py:78(helper1)
- 8 0.000 0.008 test_cProfile.py:93(helper2)
-{range} <- 8 0.000 0.000 test_cProfile.py:103(subhelper)
-{sys.exc_info} <- 4 0.000 0.000 test_cProfile.py:78(helper1)
+Function was called by...
+ ncalls tottime cumtime
+<string>:1(<module>) <-
+test_cProfile.py:103(subhelper) <- 8 0.064 0.080 test_cProfile.py:93(helper2)
+test_cProfile.py:115(__getattr__) <- 16 0.016 0.016 test_cProfile.py:103(subhelper)
+ 12 0.012 0.012 {hasattr}
+test_cProfile.py:30(testfunc) <- 1 0.270 1.000 <string>:1(<module>)
+test_cProfile.py:40(factorial) <- 1 0.014 0.130 test_cProfile.py:30(testfunc)
+ 20/3 0.130 0.147 test_cProfile.py:40(factorial)
+ 2 0.006 0.040 test_cProfile.py:89(helper2_indirect)
+test_cProfile.py:53(mul) <- 20 0.020 0.020 test_cProfile.py:40(factorial)
+test_cProfile.py:60(helper) <- 2 0.040 0.600 test_cProfile.py:30(testfunc)
+test_cProfile.py:78(helper1) <- 4 0.116 0.120 test_cProfile.py:60(helper)
+test_cProfile.py:89(helper2_indirect) <- 2 0.000 0.140 test_cProfile.py:60(helper)
+test_cProfile.py:93(helper2) <- 6 0.234 0.300 test_cProfile.py:60(helper)
+ 2 0.078 0.100 test_cProfile.py:89(helper2_indirect)
+{hasattr} <- 4 0.000 0.004 test_cProfile.py:78(helper1)
+ 8 0.000 0.008 test_cProfile.py:93(helper2)
+{method 'append' of 'list' objects} <- 4 0.000 0.000 test_cProfile.py:78(helper1)
+{method 'disable' of 'Profile' objects} <-
+{range} <- 8 0.000 0.000 test_cProfile.py:103(subhelper)
+{sys.exc_info} <- 4 0.000 0.000 test_cProfile.py:78(helper1)
Modified: pypy/branch/out-of-line-guards/lib-python/modified-2.5.2/test/test_genexps.py
==============================================================================
--- pypy/branch/out-of-line-guards/lib-python/modified-2.5.2/test/test_genexps.py (original)
+++ pypy/branch/out-of-line-guards/lib-python/modified-2.5.2/test/test_genexps.py Thu Dec 9 16:33:59 2010
@@ -77,10 +77,10 @@
Verify that parenthesis are required in a statement
>>> def f(n):
- ... return i*i for i in xrange(n)
+ ... return i*i for i in xrange(n) #doctest: +ELLIPSIS
Traceback (most recent call last):
...
- SyntaxError: invalid syntax
+ SyntaxError: invalid syntax...
Verify that parenthesis are required when used as a keyword argument value
Modified: pypy/branch/out-of-line-guards/lib_pypy/_ctypes/array.py
==============================================================================
--- pypy/branch/out-of-line-guards/lib_pypy/_ctypes/array.py (original)
+++ pypy/branch/out-of-line-guards/lib_pypy/_ctypes/array.py Thu Dec 9 16:33:59 2010
@@ -99,6 +99,9 @@
if len(value) > self._length_:
raise ValueError("Invalid length")
value = self(*value)
+ elif not isinstance(value, self):
+ raise TypeError("expected string or Unicode object, %s found"
+ % (value.__class__.__name__,))
else:
if isinstance(value, tuple):
if len(value) > self._length_:
@@ -107,22 +110,43 @@
return _CDataMeta.from_param(self, value)
def array_get_slice_params(self, index):
- if index.step is not None:
- raise TypeError("3 arg slices not supported (for no reason)")
- start = index.start or 0
- stop = index.stop or self._length_
- return start, stop
+ if hasattr(self, '_length_'):
+ start, stop, step = index.indices(self._length_)
+ else:
+ step = index.step
+ if step is None:
+ step = 1
+ start = index.start
+ stop = index.stop
+ if start is None:
+ if step > 0:
+ start = 0
+ else:
+ raise ValueError("slice start is required for step < 0")
+ if stop is None:
+ raise ValueError("slice stop is required")
+
+ return start, stop, step
def array_slice_setitem(self, index, value):
- start, stop = self._get_slice_params(index)
- if stop - start != len(value):
+ start, stop, step = self._get_slice_params(index)
+
+ if ((step < 0 and stop >= start) or
+ (step > 0 and start >= stop)):
+ slicelength = 0
+ elif step < 0:
+ slicelength = (stop - start + 1) / step + 1
+ else:
+ slicelength = (stop - start - 1) / step + 1;
+
+ if slicelength != len(value):
raise ValueError("Can only assign slices of the same length")
- for i in range(start, stop):
- self[i] = value[i - start]
+ for i, j in enumerate(range(start, stop, step)):
+ self[j] = value[i]
def array_slice_getitem(self, index):
- start, stop = self._get_slice_params(index)
- l = [self[i] for i in range(start, stop)]
+ start, stop, step = self._get_slice_params(index)
+ l = [self[i] for i in range(start, stop, step)]
letter = getattr(self._type_, '_type_', None)
if letter == 'c':
return "".join(l)
@@ -135,7 +159,8 @@
_ffiargshape = 'P'
def __init__(self, *args):
- self._buffer = self._ffiarray(self._length_, autofree=True)
+ if not hasattr(self, '_buffer'):
+ self._buffer = self._ffiarray(self._length_, autofree=True)
for i, arg in enumerate(args):
self[i] = arg
@@ -162,9 +187,10 @@
self._slice_setitem(index, value)
return
index = self._fix_index(index)
- if ensure_objects(value) is not None:
- store_reference(self, index, value._objects)
- arg = self._type_._CData_value(value)
+ cobj = self._type_.from_param(value)
+ if ensure_objects(cobj) is not None:
+ store_reference(self, index, cobj._objects)
+ arg = cobj._get_buffer_value()
if self._type_._fficompositesize is None:
self._buffer[index] = arg
# something more sophisticated, cannot set field directly
@@ -183,7 +209,7 @@
return self._length_
def _get_buffer_for_param(self):
- return CArgObject(self._buffer.byptr())
+ return CArgObject(self, self._buffer.byptr())
def _get_buffer_value(self):
return self._buffer.buffer
Modified: pypy/branch/out-of-line-guards/lib_pypy/_ctypes/basics.py
==============================================================================
--- pypy/branch/out-of-line-guards/lib_pypy/_ctypes/basics.py (original)
+++ pypy/branch/out-of-line-guards/lib_pypy/_ctypes/basics.py Thu Dec 9 16:33:59 2010
@@ -46,21 +46,6 @@
else:
return self.from_param(as_parameter)
- def _CData_input(self, value):
- """Used when data enters into ctypes from user code. 'value' is
- some user-specified Python object, which is converted into a _rawffi
- array of length 1 containing the same value according to the
- type 'self'.
- """
- cobj = self.from_param(value)
- return cobj, cobj._get_buffer_for_param()
-
- def _CData_value(self, value):
- cobj = self.from_param(value)
- # we don't care here if this stuff will live afterwards, as we're
- # interested only in value anyway
- return cobj._get_buffer_value()
-
def _CData_output(self, resbuffer, base=None, index=-1):
#assert isinstance(resbuffer, _rawffi.ArrayInstance)
"""Used when data exits ctypes and goes into user code.
@@ -92,13 +77,23 @@
""" simple wrapper around buffer, just for the case of freeing
it afterwards
"""
- def __init__(self, buffer):
+ def __init__(self, obj, buffer):
+ self._obj = obj
self._buffer = buffer
def __del__(self):
self._buffer.free()
self._buffer = None
+ def __repr__(self):
+ return '<CArgObject %r>' % (self._obj,)
+
+ def __eq__(self, other):
+ return self._obj == other
+
+ def __ne__(self, other):
+ return self._obj != other
+
class _CData(object):
""" The most basic object for all ctypes types
"""
@@ -128,7 +123,7 @@
return buffer(self._buffer)
def _get_b_base(self):
- return self._objects
+ return self._base
_b_base_ = property(_get_b_base)
_b_needsfree_ = False
Modified: pypy/branch/out-of-line-guards/lib_pypy/_ctypes/builtin.py
==============================================================================
--- pypy/branch/out-of-line-guards/lib_pypy/_ctypes/builtin.py (original)
+++ pypy/branch/out-of-line-guards/lib_pypy/_ctypes/builtin.py Thu Dec 9 16:33:59 2010
@@ -11,7 +11,8 @@
def _string_at(addr, lgt):
# address here can be almost anything
import ctypes
- arg = ctypes.c_void_p._CData_value(addr)
+ cobj = ctypes.c_void_p.from_param(addr)
+ arg = cobj._get_buffer_value()
return _rawffi.charp2rawstring(arg, lgt)
def set_conversion_mode(encoding, errors):
@@ -22,7 +23,8 @@
def _wstring_at(addr, lgt):
import ctypes
- arg = ctypes.c_void_p._CData_value(addr)
+ cobj = ctypes.c_void_p.from_param(addr)
+ arg = cobj._get_buffer_value()
# XXX purely applevel
if lgt == -1:
lgt = sys.maxint
Modified: pypy/branch/out-of-line-guards/lib_pypy/_ctypes/function.py
==============================================================================
--- pypy/branch/out-of-line-guards/lib_pypy/_ctypes/function.py (original)
+++ pypy/branch/out-of-line-guards/lib_pypy/_ctypes/function.py Thu Dec 9 16:33:59 2010
@@ -35,6 +35,7 @@
_argtypes_ = None
_restype_ = None
+ _errcheck_ = None
_flags_ = 0
_ffiargshape = 'P'
_ffishape = 'P'
@@ -53,7 +54,15 @@
return self._argtypes_
def _setargtypes(self, argtypes):
self._ptr = None
- self._argtypes_ = argtypes
+ if argtypes is None:
+ self._argtypes_ = None
+ else:
+ for i, argtype in enumerate(argtypes):
+ if not hasattr(argtype, 'from_param'):
+ raise TypeError(
+ "item %d in _argtypes_ has no from_param method" % (
+ i + 1,))
+ self._argtypes_ = argtypes
argtypes = property(_getargtypes, _setargtypes)
def _getrestype(self):
@@ -72,9 +81,24 @@
del self._restype_
restype = property(_getrestype, _setrestype, _delrestype)
+ def _geterrcheck(self):
+ return getattr(self, '_errcheck_', None)
+ def _seterrcheck(self, errcheck):
+ if not callable(errcheck):
+ raise TypeError("The errcheck attribute must be callable")
+ self._errcheck_ = errcheck
+ def _delerrcheck(self):
+ try:
+ del self._errcheck_
+ except AttributeError:
+ pass
+ errcheck = property(_geterrcheck, _seterrcheck, _delerrcheck)
+
def _ffishapes(self, args, restype):
argtypes = [arg._ffiargshape for arg in args]
if restype is not None:
+ if not isinstance(restype, _CDataMeta):
+ raise TypeError("invalid result type for callback function")
restype = restype._ffiargshape
else:
restype = 'O' # void
@@ -140,6 +164,7 @@
def __call__(self, *args):
if self.callable is not None:
+ args = args[:len(self._argtypes_)]
try:
res = self.callable(*args)
except:
@@ -162,13 +187,29 @@
thisarg = None
if argtypes is None:
- argtypes = self._guess_argtypes(args)
- argtypes, argsandobjs = self._wrap_args(argtypes, args)
+ argtypes = []
+ args = self._convert_args(argtypes, args)
+ argtypes = [type(arg) for arg in args]
restype = self._restype_
funcptr = self._getfuncptr(argtypes, restype, thisarg)
- resbuffer = funcptr(*[arg._buffer for _, arg in argsandobjs])
- return self._build_result(restype, resbuffer, argtypes, argsandobjs)
+ resbuffer = funcptr(*[arg._get_buffer_for_param()._buffer
+ for arg in args])
+ result = self._build_result(restype, resbuffer, argtypes, args)
+
+ # The 'errcheck' protocol
+ if self._errcheck_:
+ v = self._errcheck_(result, self, args)
+ # If the errcheck funtion failed, let it throw
+ # If the errcheck function returned callargs unchanged,
+ # continue normal processing.
+ # If the errcheck function returned something else,
+ # use that as result.
+ if v is not args:
+ result = v
+
+ return result
+
def _getfuncptr(self, argtypes, restype, thisarg=None):
if self._ptr is not None and argtypes is self._argtypes_:
@@ -212,31 +253,33 @@
raise
@staticmethod
- def _guess_argtypes(args):
+ def _conv_param(argtype, arg, index):
from ctypes import c_char_p, c_wchar_p, c_void_p, c_int
- res = []
- for arg in args:
- if hasattr(arg, '_as_parameter_'):
- arg = arg._as_parameter_
- if isinstance(arg, str):
- res.append(c_char_p)
- elif isinstance(arg, unicode):
- res.append(c_wchar_p)
- elif isinstance(arg, _CData):
- res.append(type(arg))
- elif arg is None:
- res.append(c_void_p)
- #elif arg == 0:
- # res.append(c_void_p)
- elif isinstance(arg, (int, long)):
- res.append(c_int)
- else:
- raise TypeError("Don't know how to handle %s" % (arg,))
- return res
+ if argtype is not None:
+ arg = argtype.from_param(arg)
+ if hasattr(arg, '_as_parameter_'):
+ arg = arg._as_parameter_
+
+ if isinstance(arg, _CData):
+ # The usual case when argtype is defined
+ cobj = arg
+ elif isinstance(arg, str):
+ cobj = c_char_p(arg)
+ elif isinstance(arg, unicode):
+ cobj = c_wchar_p(arg)
+ elif arg is None:
+ cobj = c_void_p()
+ elif isinstance(arg, (int, long)):
+ cobj = c_int(arg)
+ else:
+ raise TypeError("Don't know how to handle %s" % (arg,))
- def _wrap_args(self, argtypes, args):
+ return cobj
+
+ def _convert_args(self, argtypes, args):
wrapped_args = []
consumed = 0
+
for i, argtype in enumerate(argtypes):
defaultvalue = None
if i > 0 and self._paramflags is not None:
@@ -263,7 +306,7 @@
val = defaultvalue
if val is None:
val = 0
- wrapped = argtype._CData_input(val)
+ wrapped = self._conv_param(argtype, val, consumed)
wrapped_args.append(wrapped)
continue
else:
@@ -278,23 +321,22 @@
raise TypeError("Not enough arguments")
try:
- wrapped = argtype._CData_input(arg)
- except (UnicodeError, TypeError), e:
+ wrapped = self._conv_param(argtype, arg, consumed)
+ except (UnicodeError, TypeError, ValueError), e:
raise ArgumentError(str(e))
wrapped_args.append(wrapped)
consumed += 1
if len(wrapped_args) < len(args):
extra = args[len(wrapped_args):]
- extra_types = self._guess_argtypes(extra)
- for arg, argtype in zip(extra, extra_types):
+ argtypes = list(argtypes)
+ for i, arg in enumerate(extra):
try:
- wrapped = argtype._CData_input(arg)
- except (UnicodeError, TypeError), e:
+ wrapped = self._conv_param(None, arg, i)
+ except (UnicodeError, TypeError, ValueError), e:
raise ArgumentError(str(e))
wrapped_args.append(wrapped)
- argtypes = list(argtypes) + extra_types
- return argtypes, wrapped_args
+ return wrapped_args
def _build_result(self, restype, resbuffer, argtypes, argsandobjs):
"""Build the function result:
@@ -307,7 +349,7 @@
if self._com_index:
if resbuffer[0] & 0x80000000:
raise get_com_error(resbuffer[0],
- self._com_iid, argsandobjs[0][0])
+ self._com_iid, argsandobjs[0])
else:
retval = int(resbuffer[0])
elif restype is not None:
@@ -326,8 +368,8 @@
results = []
if self._paramflags:
- for argtype, (obj, _), paramflag in zip(argtypes[1:], argsandobjs[1:],
- self._paramflags):
+ for argtype, obj, paramflag in zip(argtypes[1:], argsandobjs[1:],
+ self._paramflags):
if len(paramflag) == 2:
idlflag, name = paramflag
elif len(paramflag) == 3:
Modified: pypy/branch/out-of-line-guards/lib_pypy/_ctypes/pointer.py
==============================================================================
--- pypy/branch/out-of-line-guards/lib_pypy/_ctypes/pointer.py (original)
+++ pypy/branch/out-of-line-guards/lib_pypy/_ctypes/pointer.py Thu Dec 9 16:33:59 2010
@@ -1,7 +1,8 @@
import _rawffi
from _ctypes.basics import _CData, _CDataMeta, cdata_from_address
-from _ctypes.basics import sizeof, byref, keepalive_key
+from _ctypes.basics import keepalive_key, store_reference, ensure_objects
+from _ctypes.basics import sizeof, byref
from _ctypes.array import Array, array_get_slice_params, array_slice_getitem,\
array_slice_setitem
@@ -55,7 +56,8 @@
def set_type(self, TP):
ffiarray = _rawffi.Array('P')
def __init__(self, value=None):
- self._buffer = ffiarray(1, autofree=True)
+ if not hasattr(self, '_buffer'):
+ self._buffer = ffiarray(1, autofree=True)
if value is not None:
self.contents = value
self._ffiarray = ffiarray
@@ -99,7 +101,10 @@
return self._type_._CData_output(self._subarray(index), self, index)
def __setitem__(self, index, value):
- self._subarray(index)[0] = self._type_._CData_value(value)
+ cobj = self._type_.from_param(value)
+ if ensure_objects(cobj) is not None:
+ store_reference(self, index, cobj._objects)
+ self._subarray(index)[0] = cobj._get_buffer_value()
def __nonzero__(self):
return self._buffer[0] != 0
@@ -110,29 +115,32 @@
if not (isinstance(tp, _CDataMeta) and tp._is_pointer_like()):
raise TypeError("cast() argument 2 must be a pointer type, not %s"
% (tp,))
- if isinstance(obj, Array):
- ptr = tp.__new__(tp)
- ptr._buffer = tp._ffiarray(1, autofree=True)
- ptr._buffer[0] = obj._buffer
- return ptr
if isinstance(obj, (int, long)):
result = tp()
result._buffer[0] = obj
return result
- if obj is None:
+ elif obj is None:
result = tp()
return result
- if not (isinstance(obj, _CData) and type(obj)._is_pointer_like()):
+ elif isinstance(obj, Array):
+ ptr = tp.__new__(tp)
+ ptr._buffer = tp._ffiarray(1, autofree=True)
+ ptr._buffer[0] = obj._buffer
+ result = ptr
+ elif not (isinstance(obj, _CData) and type(obj)._is_pointer_like()):
raise TypeError("cast() argument 1 must be a pointer, not %s"
% (type(obj),))
- result = tp()
+ else:
+ result = tp()
+ result._buffer[0] = obj._buffer[0]
# The casted objects '_objects' member:
- # It must certainly contain the source objects one.
+ # From now on, both objects will use the same dictionary
+ # It must certainly contain the source objects
# It must contain the source object itself.
if obj._ensure_objects() is not None:
- result._objects = {keepalive_key(0): obj._objects,
- keepalive_key(1): obj}
+ result._objects = obj._objects
+ if isinstance(obj._objects, dict):
+ result._objects[id(obj)] = obj
- result._buffer[0] = obj._buffer[0]
return result
Modified: pypy/branch/out-of-line-guards/lib_pypy/_ctypes/primitive.py
==============================================================================
--- pypy/branch/out-of-line-guards/lib_pypy/_ctypes/primitive.py (original)
+++ pypy/branch/out-of-line-guards/lib_pypy/_ctypes/primitive.py Thu Dec 9 16:33:59 2010
@@ -132,8 +132,8 @@
ConvMode.errors)
#self._objects = value
array = _rawffi.Array('c')(len(value)+1, value)
+ self._objects = CArgObject(value, array)
value = array.buffer
- self._objects = {'0': CArgObject(array)}
elif value is None:
value = 0
self._buffer[0] = value
@@ -155,8 +155,8 @@
ConvMode.errors)
#self._objects = value
array = _rawffi.Array('u')(len(value)+1, value)
+ self._objects = CArgObject(value, array)
value = array.buffer
- self._objects = {'0': CArgObject(array)}
elif value is None:
value = 0
self._buffer[0] = value
@@ -174,8 +174,8 @@
def _setvalue(self, value):
if isinstance(value, str):
array = _rawffi.Array('c')(len(value)+1, value)
+ self._objects = CArgObject(value, array)
value = array.buffer
- self._objects = {'0': CArgObject(array)}
elif value is None:
value = 0
self._buffer[0] = value
@@ -271,7 +271,9 @@
def _CData_output(self, resbuffer, base=None, index=-1):
output = super(SimpleType, self)._CData_output(resbuffer, base, index)
- return output.value
+ if self.__bases__[0] is _SimpleCData:
+ return output.value
+ return output
def _sizeofinstances(self):
return _rawffi.sizeof(self._type_)
@@ -287,7 +289,8 @@
_type_ = 'i'
def __init__(self, value=DEFAULT_VALUE):
- self._buffer = self._ffiarray(1, autofree=True)
+ if not hasattr(self, '_buffer'):
+ self._buffer = self._ffiarray(1, autofree=True)
if value is not DEFAULT_VALUE:
self.value = value
@@ -312,7 +315,11 @@
return self.value
def __repr__(self):
- return "%s(%r)" % (type(self).__name__, self.value)
+ if type(self).__bases__[0] is _SimpleCData:
+ return "%s(%r)" % (type(self).__name__, self.value)
+ else:
+ return "<%s object at 0x%x>" % (type(self).__name__,
+ id(self))
def __nonzero__(self):
return self._buffer[0] not in (0, '\x00')
Modified: pypy/branch/out-of-line-guards/lib_pypy/_ctypes/structure.py
==============================================================================
--- pypy/branch/out-of-line-guards/lib_pypy/_ctypes/structure.py (original)
+++ pypy/branch/out-of-line-guards/lib_pypy/_ctypes/structure.py Thu Dec 9 16:33:59 2010
@@ -34,9 +34,11 @@
if not isinstance(tp, _CDataMeta):
raise TypeError("Expected CData subclass, got %s" % (tp,))
import ctypes
- all_fields = _fields_[:]
- for cls in inspect.getmro(superclass):
- all_fields += getattr(cls, '_fields_', [])
+ all_fields = []
+ for cls in reversed(inspect.getmro(superclass)):
+ # The first field comes from the most base class
+ all_fields.extend(getattr(cls, '_fields_', []))
+ all_fields.extend(_fields_)
names = [name for name, ctype in all_fields]
rawfields = [(name, ctype._ffishape)
for name, ctype in all_fields]
@@ -168,7 +170,7 @@
def __init__(self, *args, **kwds):
if len(args) > len(self._names):
- raise TypeError("too many arguments")
+ raise TypeError("too many initializers")
for name, arg in zip(self._names, args):
if name in kwds:
raise TypeError("duplicate value for argument %r" % (
Modified: pypy/branch/out-of-line-guards/lib_pypy/_hashlib.py
==============================================================================
--- pypy/branch/out-of-line-guards/lib_pypy/_hashlib.py (original)
+++ pypy/branch/out-of-line-guards/lib_pypy/_hashlib.py Thu Dec 9 16:33:59 2010
@@ -148,21 +148,29 @@
return hash(ctx, name)
# shortcut functions
+try: from __pypy__ import builtinify
+except ImportError: builtinify = lambda f: f
+
+ at builtinify
def openssl_md5(string=''):
return new('md5', string)
+ at builtinify
def openssl_sha1(string=''):
return new('sha1', string)
+ at builtinify
def openssl_sha224(string=''):
return new('sha224', string)
+ at builtinify
def openssl_sha256(string=''):
return new('sha256', string)
+ at builtinify
def openssl_sha384(string=''):
return new('sha384', string)
+ at builtinify
def openssl_sha512(string=''):
return new('sha512', string)
-
Modified: pypy/branch/out-of-line-guards/lib_pypy/_locale.py
==============================================================================
--- pypy/branch/out-of-line-guards/lib_pypy/_locale.py (original)
+++ pypy/branch/out-of-line-guards/lib_pypy/_locale.py Thu Dec 9 16:33:59 2010
@@ -11,6 +11,9 @@
# load the platform-specific cache made by running locale.ctc.py
from ctypes_config_cache._locale_cache import *
+try: from __pypy__ import builtinify
+except ImportError: builtinify = lambda f: f
+
# Ubuntu Gusty i386 structure
class lconv(Structure):
@@ -158,6 +161,7 @@
ul = ''.join(ul)
string.letters = ul
+ at builtinify
def setlocale(category, locale=None):
"(integer,string=None) -> string. Activates/queries locale processing."
if locale:
@@ -182,6 +186,7 @@
groups.append(0)
return groups
+ at builtinify
def localeconv():
"() -> dict. Returns numeric and monetary locale-specific parameters."
@@ -215,6 +220,7 @@
}
return result
+ at builtinify
def strcoll(s1, s2):
"string,string -> int. Compares two strings according to the locale."
@@ -233,6 +239,7 @@
# Collate the strings.
return _wcscoll(s1, s2)
+ at builtinify
def strxfrm(s):
"string -> string. Returns a string that behaves for cmp locale-aware."
@@ -246,6 +253,7 @@
_strxfrm(buf, s, n2)
return buf.value
+ at builtinify
def getdefaultlocale():
# TODO: Port code from CPython for Windows and Mac OS
raise NotImplementedError()
@@ -267,26 +275,31 @@
raise ValueError("unsupported langinfo constant")
if HAS_LIBINTL:
+ @builtinify
def gettext(msg):
"""gettext(msg) -> string
Return translation of msg."""
return _gettext(msg)
+ @builtinify
def dgettext(domain, msg):
"""dgettext(domain, msg) -> string
Return translation of msg in domain."""
return _dgettext(domain, msg)
+ @builtinify
def dcgettext(domain, msg, category):
"""dcgettext(domain, msg, category) -> string
Return translation of msg in domain and category."""
return _dcgettext(domain, msg, category)
+ @builtinify
def textdomain(domain):
"""textdomain(domain) -> string
Set the C library's textdomain to domain, returning the new domain."""
return _textdomain(domain)
+ @builtinify
def bindtextdomain(domain, dir):
"""bindtextdomain(domain, dir) -> string
Bind the C library's domain to dir."""
@@ -297,6 +310,7 @@
return dirname
if HAS_BIND_TEXTDOMAIN_CODESET:
+ @builtinify
def bind_textdomain_codeset(domain, codeset):
"""bind_textdomain_codeset(domain, codeset) -> string
Bind the C library's domain to codeset."""
Modified: pypy/branch/out-of-line-guards/lib_pypy/_marshal.py
==============================================================================
--- pypy/branch/out-of-line-guards/lib_pypy/_marshal.py (original)
+++ pypy/branch/out-of-line-guards/lib_pypy/_marshal.py Thu Dec 9 16:33:59 2010
@@ -6,6 +6,10 @@
import types
from _codecs import utf_8_decode, utf_8_encode
+try: from __pypy__ import builtinify
+except ImportError: builtinify = lambda f: f
+
+
TYPE_NULL = '0'
TYPE_NONE = 'N'
TYPE_FALSE = 'F'
@@ -645,15 +649,18 @@
version = 1
+ at builtinify
def dump(x, f, version=version):
# XXX 'version' is ignored, we always dump in a version-0-compatible format
m = _Marshaller(f.write)
m.dump(x)
+ at builtinify
def load(f):
um = _Unmarshaller(f.read)
return um.load()
+ at builtinify
def dumps(x, version=version):
# XXX 'version' is ignored, we always dump in a version-0-compatible format
buffer = []
@@ -661,6 +668,7 @@
m.dump(x)
return ''.join(buffer)
+ at builtinify
def loads(s):
um = _FastUnmarshaller(s)
return um.load()
Modified: pypy/branch/out-of-line-guards/lib_pypy/_minimal_curses.py
==============================================================================
--- pypy/branch/out-of-line-guards/lib_pypy/_minimal_curses.py (original)
+++ pypy/branch/out-of-line-guards/lib_pypy/_minimal_curses.py Thu Dec 9 16:33:59 2010
@@ -35,18 +35,24 @@
# ____________________________________________________________
+try: from __pypy__ import builtinify
+except ImportError: builtinify = lambda f: f
+
+ at builtinify
def setupterm(termstr, fd):
err = ctypes.c_int(0)
result = clib.setupterm(termstr, fd, ctypes.byref(err))
if result == ERR:
raise error("setupterm() failed (err=%d)" % err.value)
+ at builtinify
def tigetstr(cap):
result = clib.tigetstr(cap)
if ctypes.cast(result, ctypes.c_void_p).value == ERR:
return None
return ctypes.cast(result, ctypes.c_char_p).value
+ at builtinify
def tparm(str, i1=0, i2=0, i3=0, i4=0, i5=0, i6=0, i7=0, i8=0, i9=0):
result = clib.tparm(str, i1, i2, i3, i4, i5, i6, i7, i8, i9)
if result is None:
Modified: pypy/branch/out-of-line-guards/lib_pypy/_pypy_interact.py
==============================================================================
--- pypy/branch/out-of-line-guards/lib_pypy/_pypy_interact.py (original)
+++ pypy/branch/out-of-line-guards/lib_pypy/_pypy_interact.py Thu Dec 9 16:33:59 2010
@@ -4,6 +4,13 @@
def interactive_console(mainmodule=None):
+ # set sys.{ps1,ps2} just before invoking the interactive interpreter. This
+ # mimics what CPython does in pythonrun.c
+ if not hasattr(sys, 'ps1'):
+ sys.ps1 = '>>>> '
+ if not hasattr(sys, 'ps2'):
+ sys.ps2 = '.... '
+ #
try:
from _pypy_irc_topic import some_topic
text = "And now for something completely different: ``%s''" % (
@@ -15,6 +22,7 @@
print text
except ImportError:
pass
+ #
try:
from pyrepl.simple_interact import check
if not check():
Modified: pypy/branch/out-of-line-guards/lib_pypy/binascii.py
==============================================================================
--- pypy/branch/out-of-line-guards/lib_pypy/binascii.py (original)
+++ pypy/branch/out-of-line-guards/lib_pypy/binascii.py Thu Dec 9 16:33:59 2010
@@ -1,3 +1,9 @@
+"""A pure Python implementation of binascii.
+
+Rather slow and buggy in corner cases.
+PyPy provides an RPython version too.
+"""
+
class Error(Exception):
pass
@@ -277,7 +283,7 @@
if (c > '~' or
c == '=' or
(header and c == '_') or
- (c == '.' and linelen == 0 and (inp == len(data) or
+ (c == '.' and linelen == 0 and (inp+1 == len(data) or
data[inp+1] == '\n' or
data[inp+1] == '\r')) or
(not istext and (c == '\r' or c == '\n')) or
Modified: pypy/branch/out-of-line-guards/lib_pypy/cPickle.py
==============================================================================
--- pypy/branch/out-of-line-guards/lib_pypy/cPickle.py (original)
+++ pypy/branch/out-of-line-guards/lib_pypy/cPickle.py Thu Dec 9 16:33:59 2010
@@ -5,6 +5,10 @@
from pickle import *
from pickle import __doc__, __version__, format_version, compatible_formats
+try: from __pypy__ import builtinify
+except ImportError: builtinify = lambda f: f
+
+
BadPickleGet = KeyError
UnpickleableError = PicklingError
@@ -31,9 +35,11 @@
def getvalue(self):
return self.__f and self.__f.getvalue()
+ at builtinify
def dump(obj, file, protocol=None):
Pickler(file, protocol).dump(obj)
+ at builtinify
def dumps(obj, protocol=None):
file = StringIO()
Pickler(file, protocol).dump(obj)
Modified: pypy/branch/out-of-line-guards/lib_pypy/cmath.py
==============================================================================
--- pypy/branch/out-of-line-guards/lib_pypy/cmath.py (original)
+++ pypy/branch/out-of-line-guards/lib_pypy/cmath.py Thu Dec 9 16:33:59 2010
@@ -7,7 +7,10 @@
import math
from math import e, pi
-
+
+try: from __pypy__ import builtinify
+except ImportError: builtinify = lambda f: f
+
# constants
_one = complex(1., 0.)
@@ -24,6 +27,7 @@
return complex(real, imag)
+ at builtinify
def acos(x):
"""acos(x)
@@ -32,6 +36,7 @@
return -(_prodi(log((x+(_i*sqrt((_one-(x*x))))))))
+ at builtinify
def acosh(x):
"""acosh(x)
@@ -41,6 +46,7 @@
return z+z
+ at builtinify
def asin(x):
"""asin(x)
@@ -52,6 +58,7 @@
return -(_prodi(log((sqrt_1_minus_x_sq+_prodi(x)))))
+ at builtinify
def asinh(x):
"""asinh(x)
@@ -61,6 +68,7 @@
return z+z
+ at builtinify
def atan(x):
"""atan(x)
@@ -69,6 +77,7 @@
return _halfi*log(((_i+x)/(_i-x)))
+ at builtinify
def atanh(x):
"""atanh(x)
@@ -77,6 +86,7 @@
return _half*log((_one+x)/(_one-x))
+ at builtinify
def cos(x):
"""cos(x)
@@ -88,6 +98,7 @@
return complex(real, imag)
+ at builtinify
def cosh(x):
"""cosh(x)
@@ -99,6 +110,7 @@
return complex(real, imag)
+ at builtinify
def exp(x):
"""exp(x)
@@ -111,6 +123,7 @@
return complex(real, imag)
+ at builtinify
def log(x, base=None):
"""log(x)
@@ -125,6 +138,7 @@
return complex(real, imag)
+ at builtinify
def log10(x):
"""log10(x)
@@ -137,6 +151,7 @@
return complex(real, imag)
+ at builtinify
def sin(x):
"""sin(x)
@@ -148,6 +163,7 @@
return complex(real, imag)
+ at builtinify
def sinh(x):
"""sinh(x)
@@ -159,6 +175,7 @@
return complex(real, imag)
+ at builtinify
def sqrt(x):
"""sqrt(x)
@@ -184,6 +201,7 @@
_sqrt_half = sqrt(_half)
+ at builtinify
def tan(x):
"""tan(x)
@@ -204,6 +222,7 @@
return complex(real, imag)
+ at builtinify
def tanh(x):
"""tanh(x)
Modified: pypy/branch/out-of-line-guards/lib_pypy/ctypes_support.py
==============================================================================
--- pypy/branch/out-of-line-guards/lib_pypy/ctypes_support.py (original)
+++ pypy/branch/out-of-line-guards/lib_pypy/ctypes_support.py Thu Dec 9 16:33:59 2010
@@ -25,7 +25,7 @@
def _where_is_errno():
return standard_c_lib.__errno_location()
-elif sys.platform == 'darwin':
+elif sys.platform in ('darwin', 'freebsd7', 'freebsd8', 'freebsd9'):
standard_c_lib.__error.restype = ctypes.POINTER(ctypes.c_int)
def _where_is_errno():
return standard_c_lib.__error()
Modified: pypy/branch/out-of-line-guards/lib_pypy/grp.py
==============================================================================
--- pypy/branch/out-of-line-guards/lib_pypy/grp.py (original)
+++ pypy/branch/out-of-line-guards/lib_pypy/grp.py Thu Dec 9 16:33:59 2010
@@ -9,6 +9,10 @@
from ctypes import Structure, c_char_p, c_int, POINTER
from ctypes_support import standard_c_lib as libc
+try: from __pypy__ import builtinify
+except ImportError: builtinify = lambda f: f
+
+
gid_t = c_int
class GroupStruct(Structure):
@@ -64,6 +68,7 @@
return Group(res.contents.gr_name, res.contents.gr_passwd,
res.contents.gr_gid, mem)
+ at builtinify
def getgrgid(gid):
res = libc.getgrgid(gid)
if not res:
@@ -71,6 +76,7 @@
raise KeyError(gid)
return _group_from_gstruct(res)
+ at builtinify
def getgrnam(name):
if not isinstance(name, str):
raise TypeError("expected string")
@@ -79,6 +85,7 @@
raise KeyError(name)
return _group_from_gstruct(res)
+ at builtinify
def getgrall():
libc.setgrent()
lst = []
Modified: pypy/branch/out-of-line-guards/lib_pypy/hashlib.py
==============================================================================
--- pypy/branch/out-of-line-guards/lib_pypy/hashlib.py (original)
+++ pypy/branch/out-of-line-guards/lib_pypy/hashlib.py Thu Dec 9 16:33:59 2010
@@ -50,53 +50,30 @@
'a4337bc45a8fc544c03f52dc550cd6e1e87021bc896588bd79e901e2'
"""
+import sys
try:
import _hashlib
except ImportError:
_hashlib = None
-def __get_builtin_constructor(name):
- if name in ('SHA1', 'sha1'):
- import sha
- return sha.new
- elif name in ('MD5', 'md5'):
- import md5
- return md5.new
- elif name in ('SHA256', 'sha256'):
- import _sha256
- return _sha256.sha256
- elif name in ('SHA224', 'sha224'):
- import _sha256
- return _sha256.sha224
- elif name in ('SHA512', 'sha512'):
- import _sha512
- return _sha512.sha512
- elif name in ('SHA384', 'sha384'):
- import _sha512
- return _sha512.sha384
- raise ValueError, "unsupported hash type"
-
def __hash_new(name, string=''):
"""new(name, string='') - Return a new hashing object using the named algorithm;
optionally initialized with a string.
"""
try:
- if _hashlib:
- return _hashlib.new(name, string)
- except ValueError:
- # If the _hashlib module (OpenSSL) doesn't support the named
- # hash, try using our builtin implementations.
- # This allows for SHA224/256 and SHA384/512 support even though
- # the OpenSSL library prior to 0.9.8 doesn't provide them.
- pass
-
- return __get_builtin_constructor(name)(string)
+ new = __byname[name]
+ except KeyError:
+ raise ValueError("unsupported hash type")
+ return new(string)
new = __hash_new
-def _setfuncs():
- # use the wrapper of the C implementation
+# ____________________________________________________________
+
+__byname = {}
+def __use_openssl_funcs():
+ # use the wrapper of the C implementation
sslprefix = 'openssl_'
for opensslfuncname, func in vars(_hashlib).items():
if not opensslfuncname.startswith(sslprefix):
@@ -106,23 +83,41 @@
# try them all, some may not work due to the OpenSSL
# version not supporting that algorithm.
func()
- # Use the C function directly (very fast)
- globals()[funcname] = func
+ # Use the C function directly (very fast, but with ctypes overhead)
+ __byname[funcname] = func
except ValueError:
- try:
- # Use the builtin implementation directly (fast)
- globals()[funcname] = __get_builtin_constructor(funcname)
- except ValueError:
- # this one has no builtin implementation, don't define it
- pass
+ pass
+
+def __use_builtin_funcs():
+ # look up the built-in versions (written in Python or RPython),
+ # and use the fastest one:
+ # 1. the one in RPython
+ # 2. the one from openssl (slower due to ctypes calling overhead)
+ # 3. the one in pure Python
+ if 'sha1' not in __byname or 'sha' in sys.builtin_module_names:
+ import sha
+ __byname['sha1'] = sha.new
+ if 'md5' not in __byname or 'md5' in sys.builtin_module_names:
+ import md5
+ __byname['md5'] = md5.new
+ if 'sha256' not in __byname:
+ import _sha256
+ __byname['sha256'] = _sha256.sha256
+ if 'sha224' not in __byname:
+ import _sha256
+ __byname['sha224'] = _sha256.sha224
+ if 'sha512' not in __byname:
+ import _sha512
+ __byname['sha512'] = _sha512.sha512
+ if 'sha384' not in __byname:
+ import _sha512
+ __byname['sha384'] = _sha512.sha384
+
+def __export_funcs():
+ for key, value in __byname.items():
+ globals()[key] = __byname[key.upper()] = value
if _hashlib:
- _setfuncs()
-else:
- # lookup the C function to use directly for the named constructors
- md5 = __get_builtin_constructor('md5')
- sha1 = __get_builtin_constructor('sha1')
- sha224 = __get_builtin_constructor('sha224')
- sha256 = __get_builtin_constructor('sha256')
- sha384 = __get_builtin_constructor('sha384')
- sha512 = __get_builtin_constructor('sha512')
+ __use_openssl_funcs()
+__use_builtin_funcs()
+__export_funcs()
Modified: pypy/branch/out-of-line-guards/lib_pypy/itertools.py
==============================================================================
--- pypy/branch/out-of-line-guards/lib_pypy/itertools.py (original)
+++ pypy/branch/out-of-line-guards/lib_pypy/itertools.py Thu Dec 9 16:33:59 2010
@@ -27,6 +27,9 @@
'ifilterfalse', 'imap', 'islice', 'izip', 'repeat', 'starmap',
'takewhile', 'tee']
+try: from __pypy__ import builtinify
+except ImportError: builtinify = lambda f: f
+
class chain(object):
"""Make an iterator that returns elements from the first iterable
@@ -565,7 +568,8 @@
def __iter__(self):
return self
-
+
+ at builtinify
def tee(iterable, n=2):
"""Return n independent iterators from a single iterable.
Note : once tee() has made a split, the original iterable
Modified: pypy/branch/out-of-line-guards/lib_pypy/msvcrt.py
==============================================================================
--- pypy/branch/out-of-line-guards/lib_pypy/msvcrt.py (original)
+++ pypy/branch/out-of-line-guards/lib_pypy/msvcrt.py Thu Dec 9 16:33:59 2010
@@ -17,6 +17,10 @@
except AttributeError: # we are not on windows
raise ImportError
+try: from __pypy__ import builtinify
+except ImportError: builtinify = lambda f: f
+
+
open_osfhandle.argtypes = [ctypes.c_int, ctypes.c_int]
open_osfhandle.restype = ctypes.c_int
@@ -34,6 +38,7 @@
_locking.argtypes = [ctypes.c_int, ctypes.c_int, ctypes.c_int]
_locking.restype = ctypes.c_int
+ at builtinify
def locking(fd, mode, nbytes):
'''lock or unlock a number of bytes in a file.'''
rv = _locking(fd, mode, nbytes)
Modified: pypy/branch/out-of-line-guards/lib_pypy/pwd.py
==============================================================================
--- pypy/branch/out-of-line-guards/lib_pypy/pwd.py (original)
+++ pypy/branch/out-of-line-guards/lib_pypy/pwd.py Thu Dec 9 16:33:59 2010
@@ -17,6 +17,10 @@
from ctypes_support import standard_c_lib as libc
from ctypes import Structure, POINTER, c_int, c_char_p
+try: from __pypy__ import builtinify
+except ImportError: builtinify = lambda f: f
+
+
uid_t = c_int
gid_t = c_int
@@ -79,10 +83,12 @@
_endpwent.argtypes = None
_endpwent.restype = None
+ at builtinify
def mkpwent(pw):
pw = pw.contents
return struct_passwd(pw)
+ at builtinify
def getpwuid(uid):
"""
getpwuid(uid) -> (pw_name,pw_passwd,pw_uid,
@@ -95,6 +101,7 @@
raise KeyError("getpwuid(): uid not found: %s" % uid)
return mkpwent(pw)
+ at builtinify
def getpwnam(name):
"""
getpwnam(name) -> (pw_name,pw_passwd,pw_uid,
@@ -109,9 +116,10 @@
raise KeyError("getpwname(): name not found: %s" % name)
return mkpwent(pw)
+ at builtinify
def getpwall():
"""
- "getpwall() -> list_of_entries
+ getpwall() -> list_of_entries
Return a list of all available password database entries, in arbitrary order.
See pwd.__doc__ for more on password database entries.
"""
Modified: pypy/branch/out-of-line-guards/lib_pypy/pyexpat.py
==============================================================================
--- pypy/branch/out-of-line-guards/lib_pypy/pyexpat.py (original)
+++ pypy/branch/out-of-line-guards/lib_pypy/pyexpat.py Thu Dec 9 16:33:59 2010
@@ -7,6 +7,9 @@
# load the platform-specific cache made by running pyexpat.ctc.py
from ctypes_config_cache._pyexpat_cache import *
+try: from __pypy__ import builtinify
+except ImportError: builtinify = lambda f: f
+
lib = ctypes.CDLL(ctypes.util.find_library('expat'))
@@ -425,9 +428,11 @@
new_parser._set_unknown_encoding_handler()
return new_parser
+ at builtinify
def ErrorString(errno):
return XML_ErrorString(errno)[:200]
+ at builtinify
def ParserCreate(encoding=None, namespace_separator=None, intern=None):
if (not isinstance(encoding, str) and
not encoding is None):
Modified: pypy/branch/out-of-line-guards/lib_pypy/pypy_test/test_hashlib.py
==============================================================================
--- pypy/branch/out-of-line-guards/lib_pypy/pypy_test/test_hashlib.py (original)
+++ pypy/branch/out-of-line-guards/lib_pypy/pypy_test/test_hashlib.py Thu Dec 9 16:33:59 2010
@@ -2,10 +2,20 @@
from ..ctypes_config_cache import rebuild
rebuild.rebuild_one('hashlib.ctc.py')
+from . import hack___pypy__
from .. import hashlib, _hashlib
def test_unicode():
- assert isinstance(hashlib.new('sha1', u'xxx'), _hashlib.hash)
+ assert isinstance(hashlib.new('sha256', u'xxx'), _hashlib.hash)
+
+pure_python_version = {
+ 'md5': 'md5.new',
+ 'sha1': 'sha.new',
+ 'sha224': '_sha256.sha224',
+ 'sha256': '_sha256.sha256',
+ 'sha384': '_sha512.sha384',
+ 'sha512': '_sha512.sha512',
+ }
def test_attributes():
for name, expected_size in {'md5': 16,
@@ -30,7 +40,10 @@
assert hexdigest == h.hexdigest()
# also test the pure Python implementation
- h = hashlib.__get_builtin_constructor(name)('')
+ modname, constructor = pure_python_version[name].split('.')
+ mod = __import__('lib_pypy.' + modname, None, None, ['__doc__'])
+ builder = getattr(mod, constructor)
+ h = builder('')
assert h.digest_size == expected_size
assert h.digestsize == expected_size
#
Modified: pypy/branch/out-of-line-guards/lib_pypy/pypy_test/test_structseq.py
==============================================================================
--- pypy/branch/out-of-line-guards/lib_pypy/pypy_test/test_structseq.py (original)
+++ pypy/branch/out-of-line-guards/lib_pypy/pypy_test/test_structseq.py Thu Dec 9 16:33:59 2010
@@ -1,6 +1,6 @@
from __future__ import absolute_import
import py
-from .._structseq import *
+from .._structseq import structseqfield, structseqtype
class mydata:
Modified: pypy/branch/out-of-line-guards/lib_pypy/readline.py
==============================================================================
--- pypy/branch/out-of-line-guards/lib_pypy/readline.py (original)
+++ pypy/branch/out-of-line-guards/lib_pypy/readline.py Thu Dec 9 16:33:59 2010
@@ -6,8 +6,4 @@
are only stubs at the moment.
"""
-# Note that PyPy contains also a built-in module 'readline' which will hide
-# this one if compiled in. However the built-in module is incomplete;
-# don't use it.
-
from pyrepl.readline import *
Modified: pypy/branch/out-of-line-guards/lib_pypy/resource.py
==============================================================================
--- pypy/branch/out-of-line-guards/lib_pypy/resource.py (original)
+++ pypy/branch/out-of-line-guards/lib_pypy/resource.py Thu Dec 9 16:33:59 2010
@@ -11,6 +11,10 @@
from errno import EINVAL, EPERM
import _structseq
+try: from __pypy__ import builtinify
+except ImportError: builtinify = lambda f: f
+
+
class error(Exception):
pass
@@ -77,6 +81,7 @@
ru_nvcsw = _structseq.structseqfield(14)
ru_nivcsw = _structseq.structseqfield(15)
+ at builtinify
def rlimit_check_bounds(rlim_cur, rlim_max):
if rlim_cur > rlim_t_max:
raise ValueError("%d does not fit into rlim_t" % rlim_cur)
@@ -89,6 +94,7 @@
("rlim_max", rlim_t),
)
+ at builtinify
def getrusage(who):
ru = _struct_rusage()
ret = _getrusage(who, byref(ru))
@@ -116,6 +122,7 @@
ru.ru_nivcsw,
))
+ at builtinify
def getrlimit(resource):
if not(0 <= resource < RLIM_NLIMITS):
return ValueError("invalid resource specified")
@@ -127,6 +134,7 @@
raise error(errno)
return (rlim.rlim_cur, rlim.rlim_max)
+ at builtinify
def setrlimit(resource, rlim):
if not(0 <= resource < RLIM_NLIMITS):
return ValueError("invalid resource specified")
@@ -143,6 +151,7 @@
else:
raise error(errno)
+ at builtinify
def getpagesize():
pagesize = 0
if _getpagesize:
Modified: pypy/branch/out-of-line-guards/lib_pypy/syslog.py
==============================================================================
--- pypy/branch/out-of-line-guards/lib_pypy/syslog.py (original)
+++ pypy/branch/out-of-line-guards/lib_pypy/syslog.py Thu Dec 9 16:33:59 2010
@@ -15,6 +15,10 @@
from ctypes_support import standard_c_lib as libc
from ctypes import c_int, c_char_p
+try: from __pypy__ import builtinify
+except ImportError: builtinify = lambda f: f
+
+
# Real prototype is:
# void syslog(int priority, const char *format, ...);
# But we also need format ("%s") and one format argument (message)
@@ -34,9 +38,11 @@
_setlogmask.argtypes = (c_int,)
_setlogmask.restype = c_int
+ at builtinify
def openlog(ident, option, facility):
_openlog(ident, option, facility)
+ at builtinify
def syslog(arg1, arg2=None):
if arg2 is not None:
priority, message = arg1, arg2
@@ -44,15 +50,19 @@
priority, message = LOG_INFO, arg1
_syslog(priority, "%s", message)
+ at builtinify
def closelog():
_closelog()
+ at builtinify
def setlogmask(mask):
return _setlogmask(mask)
+ at builtinify
def LOG_MASK(pri):
return (1 << pri)
+ at builtinify
def LOG_UPTO(pri):
return (1 << (pri + 1)) - 1
Modified: pypy/branch/out-of-line-guards/pypy/annotation/annrpython.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/annotation/annrpython.py (original)
+++ pypy/branch/out-of-line-guards/pypy/annotation/annrpython.py Thu Dec 9 16:33:59 2010
@@ -145,7 +145,7 @@
classdef.add_source_for_attribute(attr, classdef.classdesc)
self.bookkeeper
assert isinstance(s_result, annmodel.SomePBC)
- olddesc = s_result.descriptions.iterkeys().next()
+ olddesc = s_result.any_description()
desc = olddesc.bind_self(classdef)
args = self.bookkeeper.build_args("simple_call", args_s[:])
desc.consider_call_site(self.bookkeeper, desc.getcallfamily(), [desc],
Modified: pypy/branch/out-of-line-guards/pypy/annotation/binaryop.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/annotation/binaryop.py (original)
+++ pypy/branch/out-of-line-guards/pypy/annotation/binaryop.py Thu Dec 9 16:33:59 2010
@@ -861,7 +861,7 @@
def getitem((p, obj)):
assert False,"ptr %r getitem index not an int: %r" % (p.ll_ptrtype, obj)
- def setitem((p, obj)):
+ def setitem((p, obj), s_value):
assert False,"ptr %r setitem index not an int: %r" % (p.ll_ptrtype, obj)
class __extend__(pairtype(SomeObject, SomePtr)):
Modified: pypy/branch/out-of-line-guards/pypy/annotation/bookkeeper.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/annotation/bookkeeper.py (original)
+++ pypy/branch/out-of-line-guards/pypy/annotation/bookkeeper.py Thu Dec 9 16:33:59 2010
@@ -262,7 +262,7 @@
args_s, s_result)
def consider_call_site_for_pbc(self, s_callable, opname, args_s, s_result):
- descs = s_callable.descriptions.keys()
+ descs = list(s_callable.descriptions)
if not descs:
return
family = descs[0].getcallfamily()
@@ -590,7 +590,7 @@
assert s_attr.is_constant()
attr = s_attr.const
- descs = pbc.descriptions.keys()
+ descs = list(pbc.descriptions)
if not descs:
return s_ImpossibleValue
@@ -633,7 +633,7 @@
"""Analyse a call to a SomePBC() with the given args (list of
annotations).
"""
- descs = pbc.descriptions.keys()
+ descs = list(pbc.descriptions)
if not descs:
return s_ImpossibleValue
first = descs[0]
Modified: pypy/branch/out-of-line-guards/pypy/annotation/description.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/annotation/description.py (original)
+++ pypy/branch/out-of-line-guards/pypy/annotation/description.py Thu Dec 9 16:33:59 2010
@@ -636,6 +636,24 @@
return self
return None
+ def maybe_return_immutable_list(self, attr, s_result):
+ # hack: 'x.lst' where lst is listed in _immutable_fields_ as 'lst[*]'
+ # should really return an immutable list as a result. Implemented
+ # by changing the result's annotation (but not, of course, doing an
+ # actual copy in the rtyper). Tested in pypy.rpython.test.test_rlist,
+ # test_immutable_list_out_of_instance.
+ search = '%s[*]' % (attr,)
+ cdesc = self
+ while cdesc is not None:
+ if '_immutable_fields_' in cdesc.classdict:
+ if search in cdesc.classdict['_immutable_fields_'].value:
+ s_result.listdef.never_resize()
+ s_copy = s_result.listdef.offspring()
+ s_copy.listdef.mark_as_immutable()
+ return s_copy
+ cdesc = cdesc.basedesc
+ return s_result # common case
+
def consider_call_site(bookkeeper, family, descs, args, s_result):
from pypy.annotation.model import SomeInstance, SomePBC, s_None
if len(descs) == 1:
@@ -654,7 +672,7 @@
if isinstance(s_init, SomePBC):
assert len(s_init.descriptions) == 1, (
"unexpected dynamic __init__?")
- initfuncdesc = s_init.descriptions.keys()[0]
+ initfuncdesc, = s_init.descriptions
if isinstance(initfuncdesc, FunctionDesc):
initmethdesc = bookkeeper.getmethoddesc(initfuncdesc,
classdef,
@@ -782,8 +800,8 @@
desc.selfclassdef,
desc.name,
commonflags)
- del descs[desc]
- descs[newdesc] = None
+ descs.remove(desc)
+ descs.add(newdesc)
# --- case 1 ---
groups = {}
@@ -798,7 +816,7 @@
for desc2 in group:
cdef2 = desc2.selfclassdef
if cdef1 is not cdef2 and cdef1.issubclass(cdef2):
- del descs[desc1]
+ descs.remove(desc1)
break
simplify_desc_set = staticmethod(simplify_desc_set)
Modified: pypy/branch/out-of-line-guards/pypy/annotation/listdef.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/annotation/listdef.py (original)
+++ pypy/branch/out-of-line-guards/pypy/annotation/listdef.py Thu Dec 9 16:33:59 2010
@@ -6,11 +6,16 @@
class TooLateForChange(Exception):
pass
+class ListChangeUnallowed(Exception):
+ pass
+
class ListItem(object):
mutated = False # True for lists mutated after creation
resized = False # True for lists resized after creation
range_step = None # the step -- only for lists only created by a range()
dont_change_any_more = False # set to True when too late for changes
+ immutable = False # for getattr out of _immutable_fields_ = ['attr[*]']
+ must_not_resize = False # make_sure_not_resized()
# what to do if range_step is different in merge.
# - if one is a list (range_step is None), unify to a list.
@@ -26,7 +31,6 @@
self.bookkeeper = bookkeeper
self.itemof = {} # set of all ListDefs using this ListItem
self.read_locations = {}
- self.dont_resize = False
if bookkeeper is None:
self.dont_change_any_more = True
@@ -34,12 +38,15 @@
if not self.mutated:
if self.dont_change_any_more:
raise TooLateForChange
+ self.immutable = False
self.mutated = True
def resize(self):
if not self.resized:
- if self.dont_change_any_more or self.dont_resize:
+ if self.dont_change_any_more:
raise TooLateForChange
+ if self.must_not_resize:
+ raise ListChangeUnallowed("resizing list")
self.resized = True
def setrangestep(self, step):
@@ -63,11 +70,13 @@
# things more general
self, other = other, self
- if other.dont_resize:
- if self.resized:
- raise TooLateForChange()
- self.dont_resize = True
- if other.mutated: self.mutate()
+ self.immutable &= other.immutable
+ if other.must_not_resize:
+ if self.resized:
+ raise ListChangeUnallowed("list merge with a resized")
+ self.must_not_resize = True
+ if other.mutated:
+ self.mutate()
if other.resized:
self.resize()
if other.range_step != self.range_step:
@@ -176,9 +185,11 @@
self.listitem.generalize(s_value)
def __repr__(self):
- return '<[%r]%s%s>' % (self.listitem.s_value,
+ return '<[%r]%s%s%s%s>' % (self.listitem.s_value,
self.listitem.mutated and 'm' or '',
- self.listitem.resized and 'r' or '')
+ self.listitem.resized and 'r' or '',
+ self.listitem.immutable and 'I' or '',
+ self.listitem.must_not_resize and '!R' or '')
def mutate(self):
self.listitem.mutate()
@@ -189,13 +200,20 @@
def never_resize(self):
if self.listitem.resized:
- raise TooLateForChange()
- self.listitem.dont_resize = True
+ raise ListChangeUnallowed("list already resized")
+ self.listitem.must_not_resize = True
- def never_mutate(self):
- if self.listitem.resized or self.listitem.mutated:
- raise TooLateForChange()
- self.listitem.dont_change_any_more = True
+ def mark_as_immutable(self):
+ # Sets the 'immutable' flag. Note that unlike "never resized",
+ # the immutable flag is only a hint. It is cleared again e.g.
+ # when we merge with a "normal" list that doesn't have it. It
+ # is thus expected to live only shortly, mostly for the case
+ # of writing 'x.list[n]'.
+ self.never_resize()
+ if not self.listitem.mutated:
+ self.listitem.immutable = True
+ #else: it's fine, don't set immutable=True at all (see
+ # test_can_merge_immutable_list_with_regular_list)
MOST_GENERAL_LISTDEF = ListDef(None, SomeObject())
Modified: pypy/branch/out-of-line-guards/pypy/annotation/model.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/annotation/model.py (original)
+++ pypy/branch/out-of-line-guards/pypy/annotation/model.py Thu Dec 9 16:33:59 2010
@@ -356,8 +356,8 @@
immutable = True
def __init__(self, descriptions, can_be_None=False, subset_of=None):
- # descriptions is a set of Desc instances.
- descriptions = dict.fromkeys(descriptions)
+ # descriptions is a set of Desc instances
+ descriptions = set(descriptions)
self.descriptions = descriptions
self.can_be_None = can_be_None
self.subset_of = subset_of
@@ -379,6 +379,9 @@
if desc.pyobj is not None:
self.const = desc.pyobj
+ def any_description(self):
+ return iter(self.descriptions).next()
+
def getKind(self):
"Return the common Desc class of all descriptions in this PBC."
kinds = {}
Modified: pypy/branch/out-of-line-guards/pypy/annotation/specialize.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/annotation/specialize.py (original)
+++ pypy/branch/out-of-line-guards/pypy/annotation/specialize.py Thu Dec 9 16:33:59 2010
@@ -345,7 +345,8 @@
key.append(s.const)
elif isinstance(s, SomePBC) and len(s.descriptions) == 1:
# for test_specialize_arg_bound_method
- key.append(s.descriptions.keys()[0])
+ desc, = s.descriptions
+ key.append(desc)
else:
raise Exception("specialize:arg(%d): argument not constant: %r"
% (i, s))
Modified: pypy/branch/out-of-line-guards/pypy/annotation/test/test_annrpython.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/annotation/test/test_annrpython.py (original)
+++ pypy/branch/out-of-line-guards/pypy/annotation/test/test_annrpython.py Thu Dec 9 16:33:59 2010
@@ -10,7 +10,7 @@
from pypy.translator.translator import graphof as tgraphof
from pypy.annotation import policy
from pypy.annotation import specialize
-from pypy.annotation.listdef import ListDef, TooLateForChange
+from pypy.annotation.listdef import ListDef, ListChangeUnallowed
from pypy.annotation.dictdef import DictDef
from pypy.objspace.flow.model import *
from pypy.rlib.rarithmetic import r_uint, base_int, r_longlong, r_ulonglong
@@ -1010,7 +1010,7 @@
bookkeeper = a.bookkeeper
def getmdesc(bmeth):
- return bookkeeper.immutablevalue(bmeth).descriptions.keys()[0]
+ return bookkeeper.immutablevalue(bmeth).any_description()
mdescA_m = getmdesc(A().m)
mdescC_m = getmdesc(C().m)
@@ -2862,7 +2862,7 @@
assert s.items[0].flags == {'access_directly': True}
assert isinstance(s.items[1], annmodel.SomePBC)
assert len(s.items[1].descriptions) == 1
- assert s.items[1].descriptions.keys()[0].flags == {'access_directly':
+ assert s.items[1].any_description().flags == {'access_directly':
True}
assert isinstance(s.items[2], annmodel.SomeInstance)
assert s.items[2].flags == {'access_directly': True}
@@ -3206,7 +3206,7 @@
l.append(4)
a = self.RPythonAnnotator()
- py.test.raises(TooLateForChange, a.build_types, g, [])
+ py.test.raises(ListChangeUnallowed, a.build_types, g, [])
assert called
def test_listitem_no_mutating2(self):
@@ -3229,7 +3229,7 @@
a = self.RPythonAnnotator()
a.translator.config.translation.list_comprehension_operations = True
- py.test.raises(TooLateForChange, a.build_types, fn, [int])
+ py.test.raises(ListChangeUnallowed, a.build_types, fn, [int])
def test_listitem_never_resize(self):
from pypy.rlib.debug import check_annotation
@@ -3243,7 +3243,7 @@
check_annotation(l, checker)
a = self.RPythonAnnotator()
- py.test.raises(TooLateForChange, a.build_types, f, [])
+ py.test.raises(ListChangeUnallowed, a.build_types, f, [])
def test_len_of_empty_list(self):
@@ -3357,6 +3357,87 @@
# not a constant: both __enter__ and __exit__ have been annotated
assert not s.is_constant()
+ def test_make_sure_not_resized(self):
+ from pypy.rlib.debug import make_sure_not_resized
+
+ def pycode(consts):
+ make_sure_not_resized(consts)
+ def build1():
+ return pycode(consts=[1])
+ def build2():
+ return pycode(consts=[0])
+ def fn():
+ build1()
+ build2()
+
+ a = self.RPythonAnnotator()
+ a.translator.config.translation.list_comprehension_operations = True
+ a.build_types(fn, [])
+ # assert did not raise ListChangeUnallowed
+
+ def test_return_immutable_list(self):
+ class A:
+ _immutable_fields_ = 'lst[*]'
+ def f(n):
+ a = A()
+ l1 = [n, 0]
+ l1[1] = n+1
+ a.lst = l1
+ return a.lst
+
+ a = self.RPythonAnnotator()
+ s = a.build_types(f, [int])
+ assert s.listdef.listitem.immutable
+
+ def test_immutable_list_is_actually_resized(self):
+ class A:
+ _immutable_fields_ = 'lst[*]'
+ def f(n):
+ a = A()
+ l1 = [n]
+ l1.append(n+1)
+ a.lst = l1
+ return a.lst
+
+ a = self.RPythonAnnotator()
+ py.test.raises(ListChangeUnallowed, a.build_types, f, [int])
+
+ def test_can_merge_immutable_list_with_regular_list(self):
+ class A:
+ _immutable_fields_ = 'lst[*]'
+ def foo(lst):
+ pass
+
+ def f(n):
+ a = A()
+ l1 = [n, 0]
+ l1[1] = n+1
+ a.lst = l1
+ if n > 0:
+ foo(a.lst)
+ else:
+ lst = [0]
+ lst[0] = n
+ foo(lst)
+
+ a = self.RPythonAnnotator()
+ a.build_types(f, [int])
+
+ def f(n):
+ a = A()
+ l1 = [n, 0]
+ l1[1] = n+1
+ a.lst = l1
+ if n > 0:
+ lst = [0]
+ lst[0] = n
+ foo(lst)
+ else:
+ foo(a.lst)
+
+ a = self.RPythonAnnotator()
+ a.build_types(f, [int])
+
def g(n):
return [0,1,2,n]
Modified: pypy/branch/out-of-line-guards/pypy/annotation/unaryop.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/annotation/unaryop.py (original)
+++ pypy/branch/out-of-line-guards/pypy/annotation/unaryop.py Thu Dec 9 16:33:59 2010
@@ -615,6 +615,9 @@
if basedef.classdesc.all_enforced_attrs is not None:
if attr in basedef.classdesc.all_enforced_attrs:
raise HarmlesslyBlocked("get enforced attr")
+ elif isinstance(s_result, SomeList):
+ s_result = ins.classdef.classdesc.maybe_return_immutable_list(
+ attr, s_result)
return s_result
return SomeObject()
getattr.can_only_throw = []
Modified: pypy/branch/out-of-line-guards/pypy/config/pypyoption.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/config/pypyoption.py (original)
+++ pypy/branch/out-of-line-guards/pypy/config/pypyoption.py Thu Dec 9 16:33:59 2010
@@ -31,7 +31,7 @@
"crypt", "signal", "_rawffi", "termios", "zlib",
"struct", "md5", "sha", "bz2", "_minimal_curses", "cStringIO",
"thread", "itertools", "pyexpat", "_ssl", "cpyext", "array",
- "_bisect"]
+ "_bisect", "binascii"]
))
translation_modules = default_modules.copy()
@@ -76,6 +76,7 @@
"_rawffi": [("objspace.usemodules.struct", True)],
"cpyext": [("translation.secondaryentrypoints", "cpyext"),
("translation.shared", sys.platform == "win32")],
+ "_ffi": [("translation.jit_ffi", True)],
}
module_import_dependencies = {
@@ -161,7 +162,6 @@
suggests=[("objspace.allworkingmodules", False)]),
BoolOption("geninterp", "specify whether geninterp should be used",
- cmdline=None,
default=True),
BoolOption("logbytecodes",
Modified: pypy/branch/out-of-line-guards/pypy/config/translationoption.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/config/translationoption.py (original)
+++ pypy/branch/out-of-line-guards/pypy/config/translationoption.py Thu Dec 9 16:33:59 2010
@@ -3,6 +3,7 @@
from pypy.config.config import OptionDescription, BoolOption, IntOption, ArbitraryOption, FloatOption
from pypy.config.config import ChoiceOption, StrOption, to_optparse, Config
from pypy.config.config import ConfigError
+from pypy.config.support import detect_number_of_processors
DEFL_INLINE_THRESHOLD = 32.4 # just enough to inline add__Int_Int()
# and just small enough to prevend inlining of some rlist functions.
@@ -113,13 +114,10 @@
ChoiceOption("jit_backend", "choose the backend for the JIT",
["auto", "x86", "x86-without-sse2", "llvm"],
default="auto", cmdline="--jit-backend"),
- ChoiceOption("jit_debug", "the amount of debugging dumps made by the JIT",
- ["off", "profile", "steps", "detailed"],
- default="profile", # XXX for now
- cmdline="--jit-debug"),
ChoiceOption("jit_profiler", "integrate profiler support into the JIT",
["off", "oprofile"],
default="off"),
+ BoolOption("jit_ffi", "optimize libffi calls", default=False),
# misc
BoolOption("verbose", "Print extra information", default=False),
@@ -171,7 +169,7 @@
default=False, negation=False),
IntOption("make_jobs", "Specify -j argument to make for compilation"
" (C backend only)",
- cmdline="--make-jobs", default=1),
+ cmdline="--make-jobs", default=detect_number_of_processors()),
# Flags of the TranslationContext:
BoolOption("simplifying", "Simplify flow graphs", default=True),
Modified: pypy/branch/out-of-line-guards/pypy/conftest.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/conftest.py (original)
+++ pypy/branch/out-of-line-guards/pypy/conftest.py Thu Dec 9 16:33:59 2010
@@ -336,13 +336,15 @@
self.runtest_finish()
def runtest_open(self):
- leakfinder.start_tracking_allocations()
+ if not getattr(self.obj, 'dont_track_allocations', False):
+ leakfinder.start_tracking_allocations()
def runtest_perform(self):
super(PyPyTestFunction, self).runtest()
def runtest_close(self):
- if leakfinder.TRACK_ALLOCATIONS:
+ if (not getattr(self.obj, 'dont_track_allocations', False)
+ and leakfinder.TRACK_ALLOCATIONS):
self._pypytest_leaks = leakfinder.stop_tracking_allocations(False)
else: # stop_tracking_allocations() already called
self._pypytest_leaks = None
Modified: pypy/branch/out-of-line-guards/pypy/doc/cpython_differences.txt
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/doc/cpython_differences.txt (original)
+++ pypy/branch/out-of-line-guards/pypy/doc/cpython_differences.txt Thu Dec 9 16:33:59 2010
@@ -20,16 +20,21 @@
__builtin__
`__pypy__`_
+ _ast
+ _bisect
_codecs
_lsprof
`_minimal_curses`_
_random
`_rawffi`_
+ _ssl
_socket
_sre
_weakref
+ array
bz2
cStringIO
+ `cpyext`_
crypt
errno
exceptions
@@ -72,7 +77,7 @@
* Supported by being rewritten in pure Python (possibly using ``ctypes``):
see the `lib_pypy/`_ directory. Examples of modules that we
- support this way: ``ctypes``, ``array``, ``cPickle``,
+ support this way: ``ctypes``, ``cPickle``,
``cStringIO``, ``cmath``, ``dbm`` (?), ``datetime``, ``binascii``...
Note that some modules are both in there and in the list above;
by default, the built-in module is used (but can be disabled
@@ -80,11 +85,13 @@
The extension modules (i.e. modules written in C, in the standard CPython)
that are neither mentioned above nor in `lib_pypy/`_ are not available in PyPy.
+(You may have a chance to use them anyway with `cpyext`_.)
.. the nonstandard modules are listed below...
.. _`__pypy__`: __pypy__-module.html
.. _`_rawffi`: ctypes-implementation.html
.. _`_minimal_curses`: config/objspace.usemodules._minimal_curses.html
+.. _`cpyext`: http://morepypy.blogspot.com/2010/04/using-cpython-extension-modules-with.html
.. _Stackless: stackless.html
@@ -129,12 +136,10 @@
.. __: http://morepypy.blogspot.com/2008/02/python-finalizers-semantics-part-1.html
.. __: http://morepypy.blogspot.com/2008/02/python-finalizers-semantics-part-2.html
-The built-in function ``id()`` returns numbers that are not addresses
-for most of PyPy's garbage collectors.
-This is most visible in the default repr: a typical PyPy object can
-pretend to be located ``at 0x00000009``. This is just its ``id()``, not
-its real address (because an object can move around in some GCs). Calling
-``id`` a lot can lead to performance problem.
+Using the default GC called ``minimark``, the built-in function ``id()``
+works like it does in CPython. With other GCs it returns numbers that
+are not real addresses (because an object can move around several times)
+and calling it a lot can lead to performance problem.
Note that if you have a long chain of objects, each with a reference to
the next one, and each with a __del__, PyPy's GC will perform badly. On
Modified: pypy/branch/out-of-line-guards/pypy/doc/faq.txt
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/doc/faq.txt (original)
+++ pypy/branch/out-of-line-guards/pypy/doc/faq.txt Thu Dec 9 16:33:59 2010
@@ -47,7 +47,7 @@
There is also an experimental support for CPython extension modules, so
they'll run without change (from current observation, rather with little
-change) on trunk. It has been a part of 1.3 release, but support is still
+change) on trunk. It has been a part of 1.4 release, but support is still
in alpha phase.
.. _`extension modules`: cpython_differences.html#extension-modules
Modified: pypy/branch/out-of-line-guards/pypy/doc/index.txt
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/doc/index.txt (original)
+++ pypy/branch/out-of-line-guards/pypy/doc/index.txt Thu Dec 9 16:33:59 2010
@@ -8,7 +8,7 @@
Getting into PyPy ...
=============================================
-* `Release 1.3`_: the latest official release
+* `Release 1.4`_: the latest official release
* `PyPy Blog`_: news and status info about PyPy
@@ -56,4 +56,4 @@
.. _`Documentation`: docindex.html
.. _`Getting Started`: getting-started.html
.. _papers: extradoc.html
-.. _`Release 1.3`: http://pypy.org/download.html
+.. _`Release 1.4`: http://pypy.org/download.html
Modified: pypy/branch/out-of-line-guards/pypy/doc/release-1.4.0.txt
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/doc/release-1.4.0.txt (original)
+++ pypy/branch/out-of-line-guards/pypy/doc/release-1.4.0.txt Thu Dec 9 16:33:59 2010
@@ -2,27 +2,58 @@
PyPy 1.4: Ouroboros in practice
===============================
-Hello.
-
We're pleased to announce the 1.4 release of PyPy. This is a major breakthrough
in our long journey, as PyPy 1.4 is the first PyPy release that can translate
-itself faster than CPython. Starting today, we plan to start using PyPy for our
-own development.
+itself faster than CPython. Starting today, we are using PyPy more for
+our every-day development. So may you :) You can download it here:
+
+ http://pypy.org/download.html
+
+What is PyPy
+============
+
+PyPy is a very compliant Python interpreter, almost a drop-in replacement
+for CPython. It's fast (`pypy 1.4 and cpython 2.6`_ comparison)
-Among other features, this release includes numerous performance improvements
+Among its new features, this release includes numerous performance improvements
(which made fast self-hosting possible), a 64-bit JIT backend, as well
as serious stabilization. As of now, we can consider the 32-bit and 64-bit
-linux versions of PyPy stable enoughto run in production.
+linux versions of PyPy stable enough to run `in production`_.
+
+Numerous speed achievements are described on `our blog`_. Normalized speed
+charts comparing `pypy 1.4 and pypy 1.3`_ as well as `pypy 1.4 and cpython 2.6`_
+are available on benchmark website. For the impatient: yes, we got a lot faster!
More highlights
===============
-* Virtualenv support: now PyPy is fully compatible with virtualenv_: note that
+* PyPy's built-in Just-in-Time compiler is fully transparent and
+ automatically generated; it now also has very reasonable memory
+ requirements. The total memory used by a very complex and
+ long-running process (translating PyPy itself) is within 1.5x to
+ at most 2x the memory needed by CPython, for a speed-up of 2x.
+
+* More compact instances. All instances are as compact as if
+ they had ``__slots__``. This can give programs a big gain in
+ memory. (In the example of translation above, we already have
+ carefully placed ``__slots__``, so there is no extra win.)
+
+* `Virtualenv support`_: now PyPy is fully compatible with virtualenv_: note that
to use it, you need a recent version of virtualenv (>= 1.5).
* Faster (and JITted) regular expressions - huge boost in speeding up
- sre module.
+ the `re` module.
-* Faster (and JITted) calls to functions like map().
+* Other speed improvements, like JITted calls to functions like map().
.. _virtualenv: http://pypi.python.org/pypi/virtualenv
+.. _`Virtualenv support`: http://morepypy.blogspot.com/2010/08/using-virtualenv-with-pypy.html
+.. _`in production`: http://morepypy.blogspot.com/2010/11/running-large-radio-telescope-software.html
+.. _`our blog`: http://morepypy.blogspot.com
+.. _`pypy 1.4 and pypy 1.3`: http://speed.pypy.org/comparison/?exe=1%2B41,1%2B172&ben=1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20&env=1&hor=false&bas=1%2B41&chart=normal+bars
+.. _`pypy 1.4 and cpython 2.6`: http://speed.pypy.org/comparison/?exe=2%2B35,1%2B172&ben=1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20&env=1&hor=false&bas=2%2B35&chart=normal+bars
+
+Cheers,
+
+Carl Friedrich Bolz, Antonio Cuni, Maciej Fijalkowski,
+Amaury Forgeot d'Arc, Armin Rigo and the PyPy team
Modified: pypy/branch/out-of-line-guards/pypy/doc/sprint-reports.txt
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/doc/sprint-reports.txt (original)
+++ pypy/branch/out-of-line-guards/pypy/doc/sprint-reports.txt Thu Dec 9 16:33:59 2010
@@ -30,6 +30,17 @@
* `Düsseldorf (October 2006)`_
* `Leysin (January 2007)`_
* `Hildesheim (Feb 2007)`_ (also `EU report writing sprint`_)
+ * `Göteborg (November 2007)`_
+ * `Leysin (January 2008)`_
+ * `Berlin (May 2008)`_
+ * `Vilnius after EuroPython (July 2008)`_
+ * `Düsseldorf (August 2008)`_
+ * `Wroclaw (February 2009)`_
+ * `Leysin (April 2009)`_
+ * `Göteborg (August 2009)`_
+ * `Düsseldorf (November 2009)`_
+ * `CERN (July 2010)`_
+ * `Düsseldorf (October 2010)`_
.. _Hildesheim (Feb 2003): http://codespeak.net/pypy/extradoc/sprintinfo/HildesheimReport.html
.. _Gothenburg (May 2003): http://codespeak.net/pypy/extradoc/sprintinfo/gothenburg-2003-sprintreport.txt
@@ -55,3 +66,15 @@
.. _Hildesheim (Feb 2007): http://codespeak.net/pypy/extradoc/sprintinfo/trillke-2007/sprint-report.txt
.. _`EU report writing sprint`: http://codespeak.net/pypy/extradoc/sprintinfo/trillke-2007/eu-report-sprint-report.txt
.. _`PyCon/Dallas (Feb 2006)`: http://codespeak.net/pypy/extradoc/sprintinfo/pycon06/sprint-report.txt
+ .. _`Göteborg (November 2007)`: http://morepypy.blogspot.com/2007_11_01_archive.html
+ .. _`Leysin (January 2008)`: http://morepypy.blogspot.com/2008/01/leysin-winter-sport-sprint-started.html
+ .. _`Berlin (May 2008)`: http://morepypy.blogspot.com/2008_05_01_archive.html
+ .. _`Vilnius after EuroPython (July 2008)`: http://morepypy.blogspot.com/2008/07/europython-2008-pypy-talks-and-sprint.html
+ .. _`Düsseldorf (August 2008)`: http://morepypy.blogspot.com/2008_10_01_archive.html
+ .. _`Wroclaw (February 2009)`: http://morepypy.blogspot.com/2009/02/wroclaw-2009-sprint-progress-report.html
+ .. _`Leysin (April 2009)`: http://morepypy.blogspot.com/2009/04/leysin-sprint-report.html
+ .. _`Göteborg (August 2009)`: http://morepypy.blogspot.com/2009/08/gothenburg-jit-sprint-report.html
+ .. _`Düsseldorf (November 2009)`: http://morepypy.blogspot.com/2009/11/dusseldorf-sprint-report.html
+ .. _`CERN (July 2010)`: http://morepypy.blogspot.com/2010/07/cern-sprint-report-wrapping-c-libraries.html
+ .. _`Düsseldorf (October 2010)`: http://morepypy.blogspot.com/2010/10/dusseldorf-sprint-report-2010.html
+
Modified: pypy/branch/out-of-line-guards/pypy/doc/statistic/release_dates.dat
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/doc/statistic/release_dates.dat (original)
+++ pypy/branch/out-of-line-guards/pypy/doc/statistic/release_dates.dat Thu Dec 9 16:33:59 2010
@@ -7,3 +7,7 @@
2006-06-25,"PyPy 0.9"
2007-02-17,"PyPy 0.99"
2007-03-27,"PyPy 1.0"
+2009-04-28,"PyPy 1.1"
+2010-03-12,"PyPy 1.2"
+2010-06-26,"PyPy 1.3"
+2010-11-26,"PyPy 1.4"
Modified: pypy/branch/out-of-line-guards/pypy/doc/statistic/sprint_dates.dat
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/doc/statistic/sprint_dates.dat (original)
+++ pypy/branch/out-of-line-guards/pypy/doc/statistic/sprint_dates.dat Thu Dec 9 16:33:59 2010
@@ -1,26 +1,39 @@
PyPy sprints
location, begin, end
"Hildesheim",2003-02-17,2003-02-23
-"Gothenburg",2003-05-24,2003-05-31
-"LovainLaNeuve",2003-06-21,2003-06-24
+"Göteborg",2003-05-24,2003-05-31
+"Louvain-la-Neuve",2003-06-21,2003-06-24
"Berlin",2003-09-29,2003-10-04
"Amsterdam",2003-12-14,2003-12-21
-"Europython/Gothenburg",2004-06-01,2004-06-07
+"Europython/Göteborg",2004-06-01,2004-06-07
"Vilnius",2004-11-15,2004-11-23
"Leysin",2005-01-22,2005-01-29
"PyCon/Washington",2005-03-19,2005-03-22
-"Europython/Gothenburg",2005-07-01,2005-07-07
+"Europython/Göteborg",2005-07-01,2005-07-07
"Hildesheim",2005-07-25,2005-07-31
"Heidelberg",2005-08-22,2005-08-29
"Paris",2005-10-10,2005-10-16
-"Gothenburg",2005-12-05,2005-12-11
+"Göteborg",2005-12-05,2005-12-11
"Mallorca",2006-01-23,2006-01-29
"Pycon/Dallas",2006-02-27,2006-03-02
"Louvain-la-Neuve",2006-03-06,2006-03-10
"Japan",2006-04-23,2006-04-29
-"Duesseldorf",2006-06-02,2006-06-09
+"Düsseldorf",2006-06-02,2006-06-09
"Europython/Genf",2006-07-06,2006-07-09
"Limerick",2006-08-21,2006-08-27
-"Duesseldorf",2006-10-30,2006-11-05
+"Düsseldorf",2006-10-30,2006-11-05
"Leysin",2007-01-08,2007-01-14
"Hildesheim",2007-03-01,2007-03-05
+"Hildesheim",2007-03-18,2007-03-23
+"Bern",2007-10-22,2007-10-26
+"Göteborg",2007-11-19,2007-11-25
+"Leysin",2008-01-12,2008-01-19
+"Berlin",2008-05-17,2008-05-22
+"EuroPython/Vilnius",2008-07-10,2008-07-12
+"Düsseldorf",2008-08-05,2008-08-13
+"Wroclaw",2009-02-07,2009-02-14
+"Leysin",2009-04-14,2009-04-21
+"Göteborg",2009-08-18,2009-08-25
+"Düsseldorf",2009-11-06,2009-11-13
+"CERN",2010-07-05,2010-07-09
+"Düsseldorf",2010-10-25,2010-10-31
Modified: pypy/branch/out-of-line-guards/pypy/interpreter/argument.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/interpreter/argument.py (original)
+++ pypy/branch/out-of-line-guards/pypy/interpreter/argument.py Thu Dec 9 16:33:59 2010
@@ -402,9 +402,10 @@
space = self.space
w_args = space.newtuple(self.arguments_w)
w_kwds = space.newdict()
- for i in range(len(self.keywords)):
- space.setitem(w_kwds, space.wrap(self.keywords[i]),
- self.keywords_w[i])
+ if self.keywords is not None:
+ for i in range(len(self.keywords)):
+ space.setitem(w_kwds, space.wrap(self.keywords[i]),
+ self.keywords_w[i])
return w_args, w_kwds
class ArgumentsForTranslation(Arguments):
Modified: pypy/branch/out-of-line-guards/pypy/interpreter/baseobjspace.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/interpreter/baseobjspace.py (original)
+++ pypy/branch/out-of-line-guards/pypy/interpreter/baseobjspace.py Thu Dec 9 16:33:59 2010
@@ -147,7 +147,7 @@
__already_enqueued_for_destruction = False
- def _enqueue_for_destruction(self, space):
+ def _enqueue_for_destruction(self, space, call_user_del=True):
"""Put the object in the destructor queue of the space.
At a later, safe point in time, UserDelAction will use
space.userdel() to call the object's app-level __del__ method.
@@ -160,7 +160,8 @@
return
self.__already_enqueued_for_destruction = True
self.clear_all_weakrefs()
- space.user_del_action.register_dying_object(self)
+ if call_user_del:
+ space.user_del_action.register_dying_object(self)
def _call_builtin_destructor(self):
pass # method overridden in typedef.py
@@ -861,14 +862,14 @@
def call_args_and_c_profile(self, frame, w_func, args):
ec = self.getexecutioncontext()
- ec.c_call_trace(frame, w_func)
+ ec.c_call_trace(frame, w_func, args)
try:
w_res = self.call_args(w_func, args)
except OperationError, e:
w_value = e.get_w_value(self)
ec.c_exception_trace(frame, w_value)
raise
- ec.c_return_trace(frame, w_func)
+ ec.c_return_trace(frame, w_func, args)
return w_res
def call_method(self, w_obj, methname, *arg_w):
Modified: pypy/branch/out-of-line-guards/pypy/interpreter/executioncontext.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/interpreter/executioncontext.py (original)
+++ pypy/branch/out-of-line-guards/pypy/interpreter/executioncontext.py Thu Dec 9 16:33:59 2010
@@ -27,7 +27,6 @@
def __init__(self, space):
self.space = space
self.topframeref = jit.vref_None
- self.framestackdepth = 0
# tracing: space.frame_trace_action.fire() must be called to ensure
# that tracing occurs whenever self.w_tracefunc or self.is_tracing
# is modified.
@@ -54,9 +53,6 @@
return frame
def enter(self, frame):
- if self.framestackdepth > self.space.sys.recursionlimit:
- raise self.space.prebuilt_recursion_error
- self.framestackdepth += 1
frame.f_backref = self.topframeref
self.topframeref = jit.virtual_ref(frame)
@@ -66,7 +62,6 @@
self._trace(frame, 'leaveframe', self.space.w_None)
finally:
self.topframeref = frame.f_backref
- self.framestackdepth -= 1
jit.virtual_ref_finish(frame)
if self.w_tracefunc is not None and not frame.hide():
@@ -80,7 +75,6 @@
def __init__(self):
self.topframe = None
- self.framestackdepth = 0
self.w_tracefunc = None
self.profilefunc = None
self.w_profilefuncarg = None
@@ -88,7 +82,6 @@
def enter(self, ec):
ec.topframeref = jit.non_virtual_ref(self.topframe)
- ec.framestackdepth = self.framestackdepth
ec.w_tracefunc = self.w_tracefunc
ec.profilefunc = self.profilefunc
ec.w_profilefuncarg = self.w_profilefuncarg
@@ -97,7 +90,6 @@
def leave(self, ec):
self.topframe = ec.gettopframe()
- self.framestackdepth = ec.framestackdepth
self.w_tracefunc = ec.w_tracefunc
self.profilefunc = ec.profilefunc
self.w_profilefuncarg = ec.w_profilefuncarg
@@ -105,7 +97,6 @@
def clear_framestack(self):
self.topframe = None
- self.framestackdepth = 0
# the following interface is for pickling and unpickling
def getstate(self, space):
@@ -121,33 +112,41 @@
self.topframe = space.interp_w(PyFrame, frames_w[-1])
else:
self.topframe = None
- self.framestackdepth = len(frames_w)
def getframestack(self):
- index = self.framestackdepth
- lst = [None] * index
+ lst = []
f = self.topframe
- while index > 0:
- index -= 1
- lst[index] = f
+ while f is not None:
+ lst.append(f)
f = f.f_backref()
- assert f is None
+ lst.reverse()
return lst
# coroutine: I think this is all, folks!
- def c_call_trace(self, frame, w_func):
+ def c_call_trace(self, frame, w_func, args=None):
"Profile the call of a builtin function"
- if self.profilefunc is None:
- frame.is_being_profiled = False
- else:
- self._trace(frame, 'c_call', w_func)
+ self._c_call_return_trace(frame, w_func, args, 'c_call')
- def c_return_trace(self, frame, w_retval):
+ def c_return_trace(self, frame, w_func, args=None):
"Profile the return from a builtin function"
+ self._c_call_return_trace(frame, w_func, args, 'c_return')
+
+ def _c_call_return_trace(self, frame, w_func, args, event):
if self.profilefunc is None:
frame.is_being_profiled = False
else:
- self._trace(frame, 'c_return', w_retval)
+ # undo the effect of the CALL_METHOD bytecode, which would be
+ # that even on a built-in method call like '[].append()',
+ # w_func is actually the unbound function 'append'.
+ from pypy.interpreter.function import FunctionWithFixedCode
+ if isinstance(w_func, FunctionWithFixedCode) and args is not None:
+ w_firstarg = args.firstarg()
+ if w_firstarg is not None:
+ from pypy.interpreter.function import descr_function_get
+ w_func = descr_function_get(self.space, w_func, w_firstarg,
+ self.space.type(w_firstarg))
+ #
+ self._trace(frame, event, w_func)
def c_exception_trace(self, frame, w_exc):
"Profile function called upon OperationError."
Modified: pypy/branch/out-of-line-guards/pypy/interpreter/function.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/interpreter/function.py (original)
+++ pypy/branch/out-of-line-guards/pypy/interpreter/function.py Thu Dec 9 16:33:59 2010
@@ -619,11 +619,9 @@
self.w_func_dict = func.w_func_dict
self.w_module = func.w_module
- def descr_builtinfunction__new__(space, w_subtype, w_func):
- func = space.interp_w(Function, w_func)
- bltin = space.allocate_instance(BuiltinFunction, w_subtype)
- BuiltinFunction.__init__(bltin, func)
- return space.wrap(bltin)
+ def descr_builtinfunction__new__(space, w_subtype):
+ raise OperationError(space.w_TypeError,
+ space.wrap("cannot create 'builtin_function' instances"))
def descr_function_repr(self):
return self.space.wrap('<built-in function %s>' % (self.name,))
Modified: pypy/branch/out-of-line-guards/pypy/interpreter/gateway.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/interpreter/gateway.py (original)
+++ pypy/branch/out-of-line-guards/pypy/interpreter/gateway.py Thu Dec 9 16:33:59 2010
@@ -1083,7 +1083,7 @@
# these decorators are known to return the same function
# object, we may ignore them
assert '\n' in source
- source = source[source.find('\n') + 1:]
+ source = source[source.find('\n') + 1:].lstrip()
assert source.startswith("def "), "can only transform functions"
source = source[4:]
p = source.find('(')
Modified: pypy/branch/out-of-line-guards/pypy/interpreter/generator.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/interpreter/generator.py (original)
+++ pypy/branch/out-of-line-guards/pypy/interpreter/generator.py Thu Dec 9 16:33:59 2010
@@ -10,7 +10,7 @@
def __init__(self, frame):
self.space = frame.space
- self.frame = frame
+ self.frame = frame # turned into None when frame_finished_execution
self.running = False
def descr__reduce__(self, space):
@@ -19,9 +19,13 @@
mod = space.interp_w(MixedModule, w_mod)
new_inst = mod.get('generator_new')
w = space.wrap
+ if self.frame:
+ w_frame = w(self.frame)
+ else:
+ w_frame = space.w_None
tup = [
- w(self.frame),
+ w_frame,
w(self.running),
]
@@ -41,7 +45,8 @@
if self.running:
raise OperationError(space.w_ValueError,
space.wrap('generator already executing'))
- if self.frame.frame_finished_execution:
+ frame = self.frame
+ if frame is None:
# xxx a bit ad-hoc, but we don't want to go inside
# execute_generator_frame() if the frame is actually finished
if operr is None:
@@ -49,7 +54,7 @@
raise operr
# XXX it's not clear that last_instr should be promoted at all
# but as long as it is necessary for call_assembler, let's do it early
- last_instr = jit.hint(self.frame.last_instr, promote=True)
+ last_instr = jit.hint(frame.last_instr, promote=True)
if last_instr == -1:
if w_arg and not space.is_w(w_arg, space.w_None):
msg = "can't send non-None value to a just-started generator"
@@ -60,18 +65,19 @@
self.running = True
try:
try:
- w_result = self.frame.execute_generator_frame(w_arg, operr)
+ w_result = frame.execute_generator_frame(w_arg, operr)
except OperationError:
# errors finish a frame
- self.frame.frame_finished_execution = True
+ self.frame = None
raise
# if the frame is now marked as finished, it was RETURNed from
- if self.frame.frame_finished_execution:
+ if frame.frame_finished_execution:
+ self.frame = None
raise OperationError(space.w_StopIteration, space.w_None)
else:
return w_result # YIELDed
finally:
- self.frame.f_backref = jit.vref_None
+ frame.f_backref = jit.vref_None
self.running = False
def descr_throw(self, w_type, w_val=None, w_tb=None):
@@ -115,7 +121,7 @@
raise OperationError(space.w_RuntimeError, space.wrap(msg))
def descr_gi_frame(space, self):
- if not self.frame.frame_finished_execution:
+ if self.frame is not None and not self.frame.frame_finished_execution:
return self.frame
else:
return space.w_None
@@ -125,15 +131,17 @@
applevel __del__, which is called at a safe point after the
interp-level __del__ enqueued the object for destruction
"""
- # Only bother raising an exception if the frame is still not
- # finished and finally or except blocks are present.
- if not self.frame.frame_finished_execution:
+ self.descr_close()
+
+ def __del__(self):
+ # Only bother enqueuing self to raise an exception if the frame is
+ # still not finished and finally or except blocks are present.
+ must_call_close = False
+ if self.frame is not None:
block = self.frame.lastblock
while block is not None:
if not isinstance(block, LoopBlock):
- self.descr_close()
- return
+ must_call_close = True
+ break
block = block.previous
-
- def __del__(self):
- self._enqueue_for_destruction(self.space)
+ self._enqueue_for_destruction(self.space, must_call_close)
Modified: pypy/branch/out-of-line-guards/pypy/interpreter/mixedmodule.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/interpreter/mixedmodule.py (original)
+++ pypy/branch/out-of-line-guards/pypy/interpreter/mixedmodule.py Thu Dec 9 16:33:59 2010
@@ -13,6 +13,10 @@
applevel_name = None
expose__file__attribute = True
+
+ # The following attribute is None as long as the module has not been
+ # imported yet, and when it has been, it is mod.__dict__.items() just
+ # after startup().
w_initialdict = None
def __init__(self, space, w_name):
@@ -26,8 +30,14 @@
"""This is called each time the module is imported or reloaded
"""
if self.w_initialdict is not None:
+ # the module was already imported. Refresh its content with
+ # the saved dict, as done with built-in and extension modules
+ # on CPython.
space.call_method(self.w_dict, 'update', self.w_initialdict)
- Module.init(self, space)
+ else:
+ Module.init(self, space)
+ if not self.lazy and self.w_initialdict is None:
+ self.w_initialdict = space.call_method(self.w_dict, 'items')
def get_applevel_name(cls):
""" NOT_RPYTHON """
@@ -96,6 +106,7 @@
def _freeze_(self):
self.getdict()
+ self.w_initialdict = None
self.startup_called = False
# hint for the annotator: Modules can hold state, so they are
# not constant
Modified: pypy/branch/out-of-line-guards/pypy/interpreter/pycode.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/interpreter/pycode.py (original)
+++ pypy/branch/out-of-line-guards/pypy/interpreter/pycode.py Thu Dec 9 16:33:59 2010
@@ -15,7 +15,7 @@
CO_OPTIMIZED, CO_NEWLOCALS, CO_VARARGS, CO_VARKEYWORDS, CO_NESTED,
CO_GENERATOR, CO_CONTAINSGLOBALS)
from pypy.rlib.rarithmetic import intmask
-from pypy.rlib.debug import make_sure_not_resized, make_sure_not_modified
+from pypy.rlib.debug import make_sure_not_resized
from pypy.rlib import jit
from pypy.rlib.objectmodel import compute_hash
from pypy.tool.stdlib_opcode import opcodedesc, HAVE_ARGUMENT
@@ -69,7 +69,7 @@
self.co_stacksize = stacksize
self.co_flags = flags
self.co_code = code
- self.co_consts_w = make_sure_not_modified(consts)
+ self.co_consts_w = consts
self.co_names_w = [space.new_interned_str(aname) for aname in names]
self.co_varnames = varnames
self.co_freevars = freevars
@@ -269,7 +269,7 @@
dis.dis(co)
def fget_co_consts(space, self):
- return space.newtuple(self.co_consts_w[:])
+ return space.newtuple(self.co_consts_w)
def fget_co_names(space, self):
return space.newtuple(self.co_names_w)
@@ -383,7 +383,7 @@
w(self.co_stacksize),
w(self.co_flags),
w(self.co_code),
- space.newtuple(self.co_consts_w[:]),
+ space.newtuple(self.co_consts_w),
space.newtuple(self.co_names_w),
space.newtuple([w(v) for v in self.co_varnames]),
w(self.co_filename),
Modified: pypy/branch/out-of-line-guards/pypy/interpreter/pyparser/error.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/interpreter/pyparser/error.py (original)
+++ pypy/branch/out-of-line-guards/pypy/interpreter/pyparser/error.py Thu Dec 9 16:33:59 2010
@@ -2,19 +2,22 @@
class SyntaxError(Exception):
"""Base class for exceptions raised by the parser."""
- def __init__(self, msg, lineno=0, offset=0, text=None, filename=None):
+ def __init__(self, msg, lineno=0, offset=0, text=None, filename=None,
+ lastlineno=0):
self.msg = msg
self.lineno = lineno
self.offset = offset
self.text = text
self.filename = filename
+ self.lastlineno = lastlineno
def wrap_info(self, space):
return space.newtuple([space.wrap(self.msg),
space.newtuple([space.wrap(self.filename),
space.wrap(self.lineno),
space.wrap(self.offset),
- space.wrap(self.text)])])
+ space.wrap(self.text),
+ space.wrap(self.lastlineno)])])
def __str__(self):
return "%s at pos (%d, %d) in %r" % (self.__class__.__name__,
@@ -33,8 +36,9 @@
class TokenError(SyntaxError):
- def __init__(self, msg, line, lineno, column, tokens):
- SyntaxError.__init__(self, msg, lineno, column, line)
+ def __init__(self, msg, line, lineno, column, tokens, lastlineno=0):
+ SyntaxError.__init__(self, msg, lineno, column, line,
+ lastlineno=lastlineno)
self.tokens = tokens
class TokenIndentationError(IndentationError):
Modified: pypy/branch/out-of-line-guards/pypy/interpreter/pyparser/pytokenizer.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/interpreter/pyparser/pytokenizer.py (original)
+++ pypy/branch/out-of-line-guards/pypy/interpreter/pyparser/pytokenizer.py Thu Dec 9 16:33:59 2010
@@ -78,6 +78,7 @@
contline = None
indents = [0]
last_comment = ''
+ parenlevstart = (0, 0, "")
# make the annotator happy
endDFA = automata.DFA([], [])
@@ -85,7 +86,7 @@
line = ''
pos = 0
lines.append("")
- strstart = (0, 0)
+ strstart = (0, 0, "")
for line in lines:
lnum = lnum + 1
pos, max = 0, len(line)
@@ -93,7 +94,8 @@
if contstr:
if not line:
raise TokenError("EOF while scanning triple-quoted string",
- line, lnum-1, 0, token_list)
+ strstart[2], strstart[0], strstart[1]+1,
+ token_list, lnum)
endmatch = endDFA.recognize(line)
if endmatch >= 0:
pos = end = endmatch
@@ -146,6 +148,10 @@
else: # continued statement
if not line:
+ if parenlev > 0:
+ lnum1, start1, line1 = parenlevstart
+ raise TokenError("parenthesis is never closed", line1,
+ lnum1, start1 + 1, token_list, lnum)
raise TokenError("EOF in multi-line statement", line,
lnum, 0, token_list)
continued = 0
@@ -187,7 +193,7 @@
token_list.append(tok)
last_comment = ''
else:
- strstart = (lnum, start)
+ strstart = (lnum, start, line)
contstr = line[start:]
contline = line
break
@@ -195,7 +201,7 @@
token[:2] in single_quoted or \
token[:3] in single_quoted:
if token[-1] == '\n': # continued string
- strstart = (lnum, start)
+ strstart = (lnum, start, line)
endDFA = (endDFAs[initial] or endDFAs[token[1]] or
endDFAs[token[2]])
contstr, needcont = line[start:], 1
@@ -212,6 +218,8 @@
continued = 1
else:
if initial in '([{':
+ if parenlev == 0:
+ parenlevstart = (lnum, start, line)
parenlev = parenlev + 1
elif initial in ')]}':
parenlev = parenlev - 1
@@ -230,7 +238,7 @@
start = pos
if start<max and line[start] in single_quoted:
raise TokenError("EOL while scanning single-quoted string",
- line, lnum, start, token_list)
+ line, lnum, start+1, token_list)
tok = (tokens.ERRORTOKEN, line[pos], lnum, pos, line)
token_list.append(tok)
last_comment = ''
Modified: pypy/branch/out-of-line-guards/pypy/interpreter/pyparser/test/test_pyparse.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/interpreter/pyparser/test/test_pyparse.py (original)
+++ pypy/branch/out-of-line-guards/pypy/interpreter/pyparser/test/test_pyparse.py Thu Dec 9 16:33:59 2010
@@ -64,12 +64,21 @@
assert exc.lineno == 1
assert exc.offset == 5
assert exc.text.startswith("name another for")
- exc = py.test.raises(SyntaxError, parse, "\"blah").value
+ exc = py.test.raises(SyntaxError, parse, "x = \"blah\n\n\n").value
assert exc.msg == "EOL while scanning single-quoted string"
- exc = py.test.raises(SyntaxError, parse, "'''\n").value
+ assert exc.lineno == 1
+ assert exc.offset == 5
+ exc = py.test.raises(SyntaxError, parse, "x = '''\n\n\n").value
assert exc.msg == "EOF while scanning triple-quoted string"
+ assert exc.lineno == 1
+ assert exc.offset == 5
for input in ("())", "(()", "((", "))"):
py.test.raises(SyntaxError, parse, input)
+ exc = py.test.raises(SyntaxError, parse, "x = (\n\n(),\n(),").value
+ assert exc.msg == "parenthesis is never closed"
+ assert exc.lineno == 1
+ assert exc.offset == 5
+ assert exc.lastlineno == 5
def test_is(self):
self.parse("x is y")
@@ -91,6 +100,7 @@
input = "def f():\n pass\n next_stmt"
exc = py.test.raises(IndentationError, parse, input).value
assert exc.msg == "unindent does not match any outer indentation level"
+ assert exc.lineno == 3
def test_mac_newline(self):
self.parse("this_is\ra_mac\rfile")
Modified: pypy/branch/out-of-line-guards/pypy/interpreter/test/test_argument.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/interpreter/test/test_argument.py (original)
+++ pypy/branch/out-of-line-guards/pypy/interpreter/test/test_argument.py Thu Dec 9 16:33:59 2010
@@ -453,7 +453,11 @@
assert set(args.keywords) == set(['a', 'b'])
assert args.keywords_w[args.keywords.index('a')] == 2
assert args.keywords_w[args.keywords.index('b')] == 3
-
+
+ args = Arguments(space, [1])
+ w_args, w_kwds = args.topacked()
+ assert w_args == (1, )
+ assert not w_kwds
class TestErrorHandling(object):
def test_missing_args(self):
Modified: pypy/branch/out-of-line-guards/pypy/interpreter/test/test_compiler.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/interpreter/test/test_compiler.py (original)
+++ pypy/branch/out-of-line-guards/pypy/interpreter/test/test_compiler.py Thu Dec 9 16:33:59 2010
@@ -68,6 +68,17 @@
space.raises_w(space.w_SyntaxError, self.compiler.compile_command,
'if 1:\n x\n y\n', '?', 'exec', 0)
+ def test_syntaxerror_attrs(self):
+ w_args = self.space.appexec([], r"""():
+ try:
+ exec 'if 1:\n x\n y\n'
+ except SyntaxError, e:
+ return e.args
+ """)
+ assert self.space.unwrap(w_args) == (
+ 'unindent does not match any outer indentation level',
+ (None, 3, 0, ' y\n'))
+
def test_getcodeflags(self):
code = self.compiler.compile('from __future__ import division\n',
'<hello>', 'exec', 0)
Modified: pypy/branch/out-of-line-guards/pypy/interpreter/test/test_executioncontext.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/interpreter/test/test_executioncontext.py (original)
+++ pypy/branch/out-of-line-guards/pypy/interpreter/test/test_executioncontext.py Thu Dec 9 16:33:59 2010
@@ -7,6 +7,10 @@
class TestExecutionContext:
+ keywords = {}
+
+ def setup_class(cls):
+ cls.space = gettestobjspace(**cls.keywords)
def test_action(self):
@@ -77,29 +81,43 @@
assert l == ['call', 'return', 'call', 'return']
def test_llprofile_c_call(self):
+ from pypy.interpreter.function import Function, Method
l = []
+ seen = []
+ space = self.space
- def profile_func(space, w_arg, frame, event, w_aarg):
+ def profile_func(space, w_arg, frame, event, w_func):
assert w_arg is space.w_None
l.append(event)
+ if event == 'c_call':
+ seen.append(w_func)
- space = self.space
- space.getexecutioncontext().setllprofile(profile_func, space.w_None)
-
- def check_snippet(snippet):
+ def check_snippet(snippet, expected_c_call):
+ del l[:]
+ del seen[:]
+ space.getexecutioncontext().setllprofile(profile_func,
+ space.w_None)
space.appexec([], """():
%s
return
""" % snippet)
space.getexecutioncontext().setllprofile(None, None)
assert l == ['call', 'return', 'call', 'c_call', 'c_return', 'return']
-
- check_snippet('l = []; l.append(42)')
- check_snippet('max(1, 2)')
- check_snippet('args = (1, 2); max(*args)')
- check_snippet('max(1, 2, **{})')
- check_snippet('args = (1, 2); max(*args, **{})')
- check_snippet('abs(val=0)')
+ if isinstance(seen[0], Method):
+ found = 'method %s of %s' % (
+ seen[0].w_function.name,
+ seen[0].w_class.getname(space, '?'))
+ else:
+ assert isinstance(seen[0], Function)
+ found = 'builtin %s' % seen[0].name
+ assert found == expected_c_call
+
+ check_snippet('l = []; l.append(42)', 'method append of list')
+ check_snippet('max(1, 2)', 'builtin max')
+ check_snippet('args = (1, 2); max(*args)', 'builtin max')
+ check_snippet('max(1, 2, **{})', 'builtin max')
+ check_snippet('args = (1, 2); max(*args, **{})', 'builtin max')
+ check_snippet('abs(val=0)', 'builtin abs')
def test_llprofile_c_exception(self):
l = []
@@ -243,6 +261,13 @@
""")
+class TestExecutionContextWithCallLikelyBuiltin(TestExecutionContext):
+ keywords = {'objspace.opcodes.CALL_LIKELY_BUILTIN': True}
+
+class TestExecutionContextWithCallMethod(TestExecutionContext):
+ keywords = {'objspace.opcodes.CALL_METHOD': True}
+
+
class AppTestDelNotBlocked:
def setup_method(self, meth):
Modified: pypy/branch/out-of-line-guards/pypy/interpreter/test/test_function.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/interpreter/test/test_function.py (original)
+++ pypy/branch/out-of-line-guards/pypy/interpreter/test/test_function.py Thu Dec 9 16:33:59 2010
@@ -6,7 +6,7 @@
from pypy.interpreter.argument import Arguments
-class AppTestFunctionIntrospection:
+class AppTestFunctionIntrospection:
def test_attributes(self):
globals()['__name__'] = 'mymodulename'
def f(): pass
@@ -88,10 +88,10 @@
def f(*args):
return 42
raises(TypeError, "dir.func_code = f.func_code")
- raises(TypeError, "list.append.im_func.func_code = f.func_code")
+ raises(TypeError, "list.append.im_func.func_code = f.func_code")
-class AppTestFunction:
+class AppTestFunction:
def test_simple_call(self):
def func(arg1, arg2):
return arg1, arg2
@@ -116,7 +116,7 @@
assert res[2] == 333
raises(TypeError, func)
- raises(TypeError, func, 1, 2, 3, 4)
+ raises(TypeError, func, 1, 2, 3, 4)
def test_simple_varargs(self):
def func(arg1, *args):
@@ -127,7 +127,7 @@
res = func(23, *(42,))
assert res[0] == 23
- assert res[1] == (42,)
+ assert res[1] == (42,)
def test_simple_kwargs(self):
def func(arg1, **kwargs):
@@ -205,7 +205,7 @@
func(**{'self': 23})
assert False
except TypeError:
- pass
+ pass
def test_kwargs_confusing_name(self):
def func(self): # 'self' conflicts with the interp-level
@@ -287,7 +287,7 @@
# on function types
raises(ValueError, type(f).__setstate__, f, (1, 2, 3))
-class AppTestMethod:
+class AppTestMethod:
def test_simple_call(self):
class A(object):
def func(self, arg2):
@@ -308,7 +308,7 @@
res = a.func(*(42,))
assert res[0] is a
- assert res[1] == (42,)
+ assert res[1] == (42,)
def test_obscure_varargs(self):
class A(object):
@@ -321,14 +321,14 @@
res = a.func(*(42,))
assert res[0] is a
- assert res[1] == 42
+ assert res[1] == 42
def test_simple_kwargs(self):
class A(object):
def func(self, **kwargs):
return self, kwargs
a = A()
-
+
res = a.func(value=42)
assert res[0] is a
assert res[1] == {'value': 42}
@@ -382,19 +382,19 @@
assert hash(C.m) == hash(D.m)
assert hash(c.m) == hash(c.m)
- def test_method_repr(self):
- class A(object):
- def f(self):
+ def test_method_repr(self):
+ class A(object):
+ def f(self):
pass
assert repr(A.f) == "<unbound method A.f>"
- assert repr(A().f).startswith("<bound method A.f of <")
- assert repr(A().f).endswith(">>")
+ assert repr(A().f).startswith("<bound method A.f of <")
+ assert repr(A().f).endswith(">>")
class B:
def f(self):
pass
assert repr(B.f) == "<unbound method B.f>"
assert repr(B().f).startswith("<bound method B.f of <")
- assert repr(A().f).endswith(">>")
+ assert repr(A().f).endswith(">>")
def test_method_call(self):
@@ -487,14 +487,21 @@
def f(): pass
raises(TypeError, new.instancemethod, f, None)
+ def test_empty_arg_kwarg_call(self):
+ def f():
+ pass
-class TestMethod:
+ raises(TypeError, lambda: f(*0))
+ raises(TypeError, lambda: f(**0))
+
+
+class TestMethod:
def setup_method(self, method):
def c(self, bar):
return bar
code = PyCode._from_code(self.space, c.func_code)
self.fn = Function(self.space, code, self.space.newdict())
-
+
def test_get(self):
space = self.space
w_meth = descr_function_get(space, self.fn, space.wrap(5), space.type(space.wrap(5)))
@@ -552,7 +559,7 @@
def test_call_function(self):
space = self.space
-
+
d = {}
for i in range(10):
args = "(" + ''.join(["a%d," % a for a in range(i)]) + ")"
@@ -574,14 +581,14 @@
code.funcrun = bomb
code.funcrun_obj = bomb
- args_w = map(space.wrap, range(i))
+ args_w = map(space.wrap, range(i))
w_res = space.call_function(fn, *args_w)
check = space.is_true(space.eq(w_res, space.wrap(res)))
assert check
def test_flatcall(self):
space = self.space
-
+
def f(a):
return a
code = PyCode._from_code(self.space, f.func_code)
@@ -608,7 +615,7 @@
def test_flatcall_method(self):
space = self.space
-
+
def f(self, a):
return a
code = PyCode._from_code(self.space, f.func_code)
@@ -636,7 +643,7 @@
def test_flatcall_default_arg(self):
space = self.space
-
+
def f(a, b):
return a+b
code = PyCode._from_code(self.space, f.func_code)
@@ -665,7 +672,7 @@
def test_flatcall_default_arg_method(self):
space = self.space
-
+
def f(self, a, b):
return a+b
code = PyCode._from_code(self.space, f.func_code)
@@ -688,7 +695,7 @@
y = A().m(x)
b = A().m
z = b(x)
- return y+10*z
+ return y+10*z
""")
assert space.eq_w(w_res, space.wrap(44))
Modified: pypy/branch/out-of-line-guards/pypy/interpreter/test/test_gateway.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/interpreter/test/test_gateway.py (original)
+++ pypy/branch/out-of-line-guards/pypy/interpreter/test/test_gateway.py Thu Dec 9 16:33:59 2010
@@ -578,6 +578,11 @@
w_res = space.call_args(w_g, args)
assert space.eq_w(w_res, space.wrap((-1, 0)))
+class AppTestPyTestMark:
+ @py.test.mark.unlikely_to_exist
+ def test_anything(self):
+ pass
+
class TestPassThroughArguments:
Modified: pypy/branch/out-of-line-guards/pypy/jit/backend/detect_cpu.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/jit/backend/detect_cpu.py (original)
+++ pypy/branch/out-of-line-guards/pypy/jit/backend/detect_cpu.py Thu Dec 9 16:33:59 2010
@@ -31,7 +31,8 @@
'i86pc': 'x86', # Solaris/Intel
'x86': 'x86', # Apple
'Power Macintosh': 'ppc',
- 'x86_64': 'x86',
+ 'x86_64': 'x86',
+ 'amd64': 'x86' # freebsd
}[mach]
except KeyError:
return mach
Modified: pypy/branch/out-of-line-guards/pypy/jit/backend/llgraph/llimpl.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/jit/backend/llgraph/llimpl.py (original)
+++ pypy/branch/out-of-line-guards/pypy/jit/backend/llgraph/llimpl.py Thu Dec 9 16:33:59 2010
@@ -4,6 +4,7 @@
when executing on top of the llinterpreter.
"""
+import weakref
from pypy.objspace.flow.model import Variable, Constant
from pypy.annotation import model as annmodel
from pypy.jit.metainterp.history import (ConstInt, ConstPtr,
@@ -161,6 +162,8 @@
# ____________________________________________________________
class CompiledLoop(object):
+ has_been_freed = False
+
def __init__(self):
self.inputargs = []
self.operations = []
@@ -285,6 +288,11 @@
del _variables[:]
return _to_opaque(CompiledLoop())
+def mark_as_free(loop):
+ loop = _from_opaque(loop)
+ assert not loop.has_been_freed
+ loop.has_been_freed = True
+
def compile_start_int_var(loop):
return compile_start_ref_var(loop, lltype.Signed)
@@ -317,7 +325,7 @@
raise ValueError("CALL_ASSEMBLER not supported")
loop = _from_opaque(loop)
op = loop.operations[-1]
- op.descr = descr
+ op.descr = weakref.ref(descr)
def compile_add_var(loop, intvar):
loop = _from_opaque(loop)
@@ -429,6 +437,7 @@
verbose = True
self.opindex = 0
while True:
+ assert not self.loop.has_been_freed
op = self.loop.operations[self.opindex]
args = [self.getenv(v) for v in op.args]
if not op.is_final():
@@ -440,7 +449,10 @@
_stats.exec_conditional_jumps += 1
if op.jump_target is not None:
# a patched guard, pointing to further code
- args = [self.getenv(v) for v in op.fail_args if v]
+ if op.fail_args:
+ args = [self.getenv(v) for v in op.fail_args if v]
+ else:
+ args = []
assert len(op.jump_target.inputargs) == len(args)
self.env = dict(zip(op.jump_target.inputargs, args))
self.loop = op.jump_target
@@ -571,7 +583,12 @@
def op_debug_merge_point(self, _, value, recdepth):
from pypy.jit.metainterp.warmspot import get_stats
loc = ConstPtr(value)._get_str()
- get_stats().add_merge_point_location(loc)
+ try:
+ stats = get_stats()
+ except AttributeError:
+ pass
+ else:
+ stats.add_merge_point_location(loc)
def op_guard_true(self, _, value):
if not value:
@@ -839,14 +856,22 @@
finally:
self._may_force = -1
- def op_call_assembler(self, loop_token, *args):
+ def op_call_assembler(self, wref_loop_token, *args):
+ if we_are_translated():
+ raise ValueError("CALL_ASSEMBLER not supported")
+ return self._do_call_assembler(wref_loop_token, *args)
+
+ def _do_call_assembler(self, wref_loop_token, *args):
global _last_exception
+ loop_token = wref_loop_token()
+ assert loop_token, "CALL_ASSEMBLER to a target that already died"
+ ctl = loop_token.compiled_loop_token
+ if hasattr(ctl, 'redirected'):
+ return self._do_call_assembler(ctl.redirected, *args)
assert not self._forced
- loop_token = self.cpu._redirected_call_assembler.get(loop_token,
- loop_token)
self._may_force = self.opindex
try:
- inpargs = _from_opaque(loop_token._llgraph_compiled_version).inputargs
+ inpargs = _from_opaque(ctl.compiled_version).inputargs
for i, inparg in enumerate(inpargs):
TYPE = inparg.concretetype
if TYPE is lltype.Signed:
@@ -1539,10 +1564,13 @@
do_setfield_gc_int(vable, fielddescr.ofs, 0)
def redirect_call_assembler(cpu, oldlooptoken, newlooptoken):
- OLD = _from_opaque(oldlooptoken._llgraph_compiled_version).getargtypes()
- NEW = _from_opaque(newlooptoken._llgraph_compiled_version).getargtypes()
+ oldclt = oldlooptoken.compiled_loop_token
+ newclt = newlooptoken.compiled_loop_token
+ OLD = _from_opaque(oldclt.compiled_version).getargtypes()
+ NEW = _from_opaque(newclt.compiled_version).getargtypes()
assert OLD == NEW
- cpu._redirected_call_assembler[oldlooptoken] = newlooptoken
+ assert not hasattr(oldclt, 'redirected')
+ oldclt.redirected = weakref.ref(newlooptoken)
# ____________________________________________________________
@@ -1609,6 +1637,7 @@
setannotation(compile_add_fail, annmodel.SomeInteger())
setannotation(compile_add_fail_arg, annmodel.s_None)
setannotation(compile_redirect_fail, annmodel.s_None)
+setannotation(mark_as_free, annmodel.s_None)
setannotation(new_frame, s_Frame)
setannotation(frame_clear, annmodel.s_None)
Modified: pypy/branch/out-of-line-guards/pypy/jit/backend/llgraph/runner.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/jit/backend/llgraph/runner.py (original)
+++ pypy/branch/out-of-line-guards/pypy/jit/backend/llgraph/runner.py Thu Dec 9 16:33:59 2010
@@ -102,7 +102,6 @@
llimpl._llinterp = LLInterpreter(self.rtyper)
self._future_values = []
self._descrs = {}
- self._redirected_call_assembler = {}
def _freeze_(self):
assert self.translate_support_code
@@ -118,22 +117,34 @@
self._descrs[key] = descr
return descr
- def compile_bridge(self, faildescr, inputargs, operations, log=True):
+ def compile_bridge(self, faildescr, inputargs, operations,
+ original_loop_token, log=True):
c = llimpl.compile_start()
+ clt = original_loop_token.compiled_loop_token
+ clt.loop_and_bridges.append(c)
+ clt.compiling_a_bridge()
self._compile_loop_or_bridge(c, inputargs, operations)
old, oldindex = faildescr._compiled_fail
llimpl.compile_redirect_fail(old, oldindex, c)
- def compile_loop(self, inputargs, operations, loopdescr, log=True):
+ def compile_loop(self, inputargs, operations, looptoken, log=True):
"""In a real assembler backend, this should assemble the given
list of operations. Here we just generate a similar CompiledLoop
instance. The code here is RPython, whereas the code in llimpl
is not.
"""
c = llimpl.compile_start()
- loopdescr._llgraph_compiled_version = c
+ clt = model.CompiledLoopToken(self, looptoken.number)
+ clt.loop_and_bridges = [c]
+ clt.compiled_version = c
+ looptoken.compiled_loop_token = clt
self._compile_loop_or_bridge(c, inputargs, operations)
+ def free_loop_and_bridges(self, compiled_loop_token):
+ for c in compiled_loop_token.loop_and_bridges:
+ llimpl.mark_as_free(c)
+ model.AbstractCPU.free_loop_and_bridges(self, compiled_loop_token)
+
def _compile_loop_or_bridge(self, c, inputargs, operations):
var2index = {}
for box in inputargs:
@@ -207,7 +218,7 @@
if op.getopnum() == rop.JUMP:
targettoken = op.getdescr()
assert isinstance(targettoken, history.LoopToken)
- compiled_version = targettoken._llgraph_compiled_version
+ compiled_version = targettoken.compiled_loop_token.compiled_version
llimpl.compile_add_jump_target(c, compiled_version)
elif op.getopnum() == rop.FINISH:
faildescr = op.getdescr()
@@ -217,7 +228,7 @@
assert False, "unknown operation"
def _execute_token(self, loop_token):
- compiled_version = loop_token._llgraph_compiled_version
+ compiled_version = loop_token.compiled_loop_token.compiled_version
frame = llimpl.new_frame(self.is_oo, self)
# setup the frame
llimpl.frame_clear(frame, compiled_version)
Modified: pypy/branch/out-of-line-guards/pypy/jit/backend/llsupport/gc.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/jit/backend/llsupport/gc.py (original)
+++ pypy/branch/out-of-line-guards/pypy/jit/backend/llsupport/gc.py Thu Dec 9 16:33:59 2010
@@ -15,6 +15,7 @@
from pypy.jit.backend.llsupport.descr import GcCache, get_field_descr
from pypy.jit.backend.llsupport.descr import GcPtrFieldDescr
from pypy.jit.backend.llsupport.descr import get_call_descr
+from pypy.rpython.memory.gctransform import asmgcroot
# ____________________________________________________________
@@ -35,6 +36,8 @@
return False
def has_write_barrier_class(self):
return None
+ def freeing_block(self, start, stop):
+ pass
# ____________________________________________________________
@@ -218,50 +221,120 @@
LOC_EBP_PLUS = 2
LOC_EBP_MINUS = 3
- GCMAP_ARRAY = rffi.CArray(llmemory.Address)
- CALLSHAPE_ARRAY = rffi.CArray(rffi.UCHAR)
+ GCMAP_ARRAY = rffi.CArray(lltype.Signed)
+ CALLSHAPE_ARRAY_PTR = rffi.CArrayPtr(rffi.UCHAR)
def __init__(self):
+ # '_gcmap' is an array of length '_gcmap_maxlength' of addresses.
+ # '_gcmap_curlength' tells how full the array really is.
+ # The addresses are actually grouped in pairs:
+ # (addr-after-the-CALL-in-assembler, addr-of-the-call-shape).
+ # '_gcmap_deadentries' counts pairs marked dead (2nd item is NULL).
+ # '_gcmap_sorted' is True only if we know the array is sorted.
self._gcmap = lltype.nullptr(self.GCMAP_ARRAY)
self._gcmap_curlength = 0
self._gcmap_maxlength = 0
+ self._gcmap_deadentries = 0
+ self._gcmap_sorted = True
def initialize(self):
# hack hack hack. Remove these lines and see MissingRTypeAttribute
# when the rtyper tries to annotate these methods only when GC-ing...
self.gcmapstart()
self.gcmapend()
+ self.gcmarksorted()
def gcmapstart(self):
- return llmemory.cast_ptr_to_adr(self._gcmap)
+ return rffi.cast(llmemory.Address, self._gcmap)
def gcmapend(self):
addr = self.gcmapstart()
if self._gcmap_curlength:
- addr += llmemory.sizeof(llmemory.Address)*self._gcmap_curlength
+ addr += rffi.sizeof(lltype.Signed) * self._gcmap_curlength
+ if not we_are_translated() and type(addr) is long:
+ from pypy.rpython.lltypesystem import ll2ctypes
+ addr = ll2ctypes._lladdress(addr) # XXX workaround
return addr
+ def gcmarksorted(self):
+ # Called by the GC when it is about to sort [gcmapstart():gcmapend()].
+ # Returns the previous sortedness flag -- i.e. returns True if it
+ # is already sorted, False if sorting is needed.
+ sorted = self._gcmap_sorted
+ self._gcmap_sorted = True
+ return sorted
+
def put(self, retaddr, callshapeaddr):
"""'retaddr' is the address just after the CALL.
- 'callshapeaddr' is the address returned by encode_callshape()."""
+ 'callshapeaddr' is the address of the raw 'shape' marker.
+ Both addresses are actually integers here."""
index = self._gcmap_curlength
if index + 2 > self._gcmap_maxlength:
- self._enlarge_gcmap()
+ index = self._enlarge_gcmap()
self._gcmap[index] = retaddr
self._gcmap[index+1] = callshapeaddr
self._gcmap_curlength = index + 2
+ self._gcmap_sorted = False
+ @rgc.no_collect
def _enlarge_gcmap(self):
- newlength = 250 + self._gcmap_maxlength * 2
- newgcmap = lltype.malloc(self.GCMAP_ARRAY, newlength, flavor='raw',
- track_allocation=False)
oldgcmap = self._gcmap
- for i in range(self._gcmap_curlength):
- newgcmap[i] = oldgcmap[i]
- self._gcmap = newgcmap
- self._gcmap_maxlength = newlength
- if oldgcmap:
- lltype.free(oldgcmap, flavor='raw', track_allocation=False)
+ if self._gcmap_deadentries * 3 * 2 > self._gcmap_maxlength:
+ # More than 1/3rd of the entries are dead. Don't actually
+ # enlarge the gcmap table, but just clean up the dead entries.
+ newgcmap = oldgcmap
+ else:
+ # Normal path: enlarge the array.
+ newlength = 250 + (self._gcmap_maxlength // 3) * 4
+ newgcmap = lltype.malloc(self.GCMAP_ARRAY, newlength, flavor='raw',
+ track_allocation=False)
+ self._gcmap_maxlength = newlength
+ #
+ j = 0
+ i = 0
+ end = self._gcmap_curlength
+ while i < end:
+ if oldgcmap[i + 1]:
+ newgcmap[j] = oldgcmap[i]
+ newgcmap[j + 1] = oldgcmap[i + 1]
+ j += 2
+ i += 2
+ self._gcmap_curlength = j
+ self._gcmap_deadentries = 0
+ if oldgcmap != newgcmap:
+ self._gcmap = newgcmap
+ if oldgcmap:
+ lltype.free(oldgcmap, flavor='raw', track_allocation=False)
+ return j
+
+ @rgc.no_collect
+ def freeing_block(self, start, stop):
+ # if [start:stop] is a raw block of assembler, then look up the
+ # corresponding gcroot markers, and mark them as freed now in
+ # self._gcmap by setting the 2nd address of every entry to NULL.
+ gcmapstart = self.gcmapstart()
+ gcmapend = self.gcmapend()
+ if gcmapstart == gcmapend:
+ return
+ if not self.gcmarksorted():
+ asmgcroot.sort_gcmap(gcmapstart, gcmapend)
+ # A note about gcmarksorted(): the deletion we do here keeps the
+ # array sorted. This avoids needing too many sort_gcmap()s.
+ # Indeed, freeing_block() is typically called many times in a row,
+ # so it will call sort_gcmap() at most the first time.
+ startaddr = rffi.cast(llmemory.Address, start)
+ stopaddr = rffi.cast(llmemory.Address, stop)
+ item = asmgcroot.binary_search(gcmapstart, gcmapend, startaddr)
+ # 'item' points to one of the entries. Because the whole array
+ # is sorted, we know that it points either to the first entry we
+ # want to kill, or to the previous entry.
+ if item.address[0] < startaddr:
+ item += asmgcroot.arrayitemsize # go forward one entry
+ assert item == gcmapend or item.address[0] >= startaddr
+ while item != gcmapend and item.address[0] < stopaddr:
+ item.address[1] = llmemory.NULL
+ self._gcmap_deadentries += 1
+ item += asmgcroot.arrayitemsize
def get_basic_shape(self, is_64_bit=False):
# XXX: Should this code even really know about stack frame layout of
@@ -304,17 +377,15 @@
assert reg_index > 0
shape.append(chr(self.LOC_REG | (reg_index << 2)))
- def compress_callshape(self, shape):
+ def compress_callshape(self, shape, datablockwrapper):
# Similar to compress_callshape() in trackgcroot.py.
- # XXX so far, we always allocate a new small array (we could regroup
- # them inside bigger arrays) and we never try to share them.
+ # Returns an address to raw memory (as an integer).
length = len(shape)
- compressed = lltype.malloc(self.CALLSHAPE_ARRAY, length,
- flavor='raw',
- track_allocation=False) # memory leak
+ rawaddr = datablockwrapper.malloc_aligned(length, 1)
+ p = rffi.cast(self.CALLSHAPE_ARRAY_PTR, rawaddr)
for i in range(length):
- compressed[length-1-i] = rffi.cast(rffi.UCHAR, shape[i])
- return llmemory.cast_ptr_to_adr(compressed)
+ p[length-1-i] = rffi.cast(rffi.UCHAR, shape[i])
+ return rawaddr
class WriteBarrierDescr(AbstractDescr):
@@ -379,6 +450,7 @@
'layoutbuilder': self.layoutbuilder,
'gcmapstart': lambda: gcrootmap.gcmapstart(),
'gcmapend': lambda: gcrootmap.gcmapend(),
+ 'gcmarksorted': lambda: gcrootmap.gcmarksorted(),
}
self.GCClass = self.layoutbuilder.GCClass
self.moving_gc = self.GCClass.moving_gc
@@ -641,6 +713,9 @@
def has_write_barrier_class(self):
return WriteBarrierDescr
+ def freeing_block(self, start, stop):
+ self.gcrootmap.freeing_block(start, stop)
+
# ____________________________________________________________
def get_ll_description(gcdescr, translator=None, rtyper=None):
Modified: pypy/branch/out-of-line-guards/pypy/jit/backend/llsupport/llmodel.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/jit/backend/llsupport/llmodel.py (original)
+++ pypy/branch/out-of-line-guards/pypy/jit/backend/llsupport/llmodel.py Thu Dec 9 16:33:59 2010
@@ -17,7 +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.jit.backend.llsupport.asmmemmgr import AsmMemoryManager
from pypy.rpython.annlowlevel import cast_instance_to_base_ptr
@@ -52,6 +52,7 @@
else:
self._setup_exception_handling_untranslated()
self.saved_exc_value = lltype.nullptr(llmemory.GCREF.TO)
+ self.asmmemmgr = AsmMemoryManager()
self.setup()
if translate_support_code:
self._setup_on_leave_jitted_translated()
@@ -177,6 +178,15 @@
self.saved_exc_value = lltype.nullptr(llmemory.GCREF.TO)
return exc
+ def free_loop_and_bridges(self, compiled_loop_token):
+ AbstractCPU.free_loop_and_bridges(self, compiled_loop_token)
+ blocks = compiled_loop_token.asmmemmgr_blocks
+ if blocks is not None:
+ compiled_loop_token.asmmemmgr_blocks = None
+ for rawstart, rawstop in blocks:
+ self.gc_ll_descr.freeing_block(rawstart, rawstop)
+ self.asmmemmgr.free(rawstart, rawstop)
+
# ------------------- helpers and descriptions --------------------
@staticmethod
@@ -236,7 +246,9 @@
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)
+ from pypy.jit.backend.llsupport import ffisupport
+ return ffisupport.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)
Modified: pypy/branch/out-of-line-guards/pypy/jit/backend/llsupport/test/test_gc.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/jit/backend/llsupport/test/test_gc.py (original)
+++ pypy/branch/out-of-line-guards/pypy/jit/backend/llsupport/test/test_gc.py Thu Dec 9 16:33:59 2010
@@ -9,6 +9,7 @@
from pypy.jit.tool.oparser import parse
from pypy.rpython.lltypesystem.rclass import OBJECT, OBJECT_VTABLE
from pypy.jit.metainterp.test.test_optimizeopt import equaloplists
+from pypy.rpython.memory.gctransform import asmgcroot
def test_boehm():
gc_ll_descr = GcLLDescr_boehm(None, None, None)
@@ -62,58 +63,169 @@
for i in range(len(allocs)):
assert addrs[i].address[0] == llmemory.cast_ptr_to_adr(allocs[i])
-def test_GcRootMap_asmgcc():
- def frame_pos(n):
- return -4*(4+n)
- gcrootmap = GcRootMap_asmgcc()
- num1 = frame_pos(-5)
- num1a = num1|2
- num2 = frame_pos(55)
- num2a = ((-num2|3) >> 7) | 128
- num2b = (-num2|3) & 127
- shape = gcrootmap.get_basic_shape()
- gcrootmap.add_ebp_offset(shape, num1)
- gcrootmap.add_ebp_offset(shape, num2)
- assert shape == map(chr, [6, 7, 11, 15, 2, 0, num1a, num2b, num2a])
- gcrootmap.add_callee_save_reg(shape, 1)
- assert shape == map(chr, [6, 7, 11, 15, 2, 0, num1a, num2b, num2a,
- 4])
- gcrootmap.add_callee_save_reg(shape, 2)
- assert shape == map(chr, [6, 7, 11, 15, 2, 0, num1a, num2b, num2a,
- 4, 8])
- gcrootmap.add_callee_save_reg(shape, 3)
- assert shape == map(chr, [6, 7, 11, 15, 2, 0, num1a, num2b, num2a,
- 4, 8, 12])
- gcrootmap.add_callee_save_reg(shape, 4)
- assert shape == map(chr, [6, 7, 11, 15, 2, 0, num1a, num2b, num2a,
- 4, 8, 12, 16])
- #
- shapeaddr = gcrootmap.compress_callshape(shape)
- PCALLSHAPE = lltype.Ptr(GcRootMap_asmgcc.CALLSHAPE_ARRAY)
- p = llmemory.cast_adr_to_ptr(shapeaddr, PCALLSHAPE)
- for i, expected in enumerate([16, 12, 8, 4,
- num2a, num2b, num1a, 0, 2, 15, 11, 7, 6]):
- assert p[i] == expected
- #
- retaddr = rffi.cast(llmemory.Address, 1234567890)
- gcrootmap.put(retaddr, shapeaddr)
- assert gcrootmap._gcmap[0] == retaddr
- assert gcrootmap._gcmap[1] == shapeaddr
- assert gcrootmap.gcmapstart().address[0] == retaddr
- #
- # the same as before, but enough times to trigger a few resizes
- expected_shapeaddr = {}
- for i in range(1, 700):
+class TestGcRootMapAsmGcc:
+
+ def test_make_shapes(self):
+ def frame_pos(n):
+ return -4*(4+n)
+ gcrootmap = GcRootMap_asmgcc()
+ num1 = frame_pos(-5)
+ num1a = num1|2
+ num2 = frame_pos(55)
+ num2a = ((-num2|3) >> 7) | 128
+ num2b = (-num2|3) & 127
shape = gcrootmap.get_basic_shape()
- gcrootmap.add_ebp_offset(shape, frame_pos(i))
- shapeaddr = gcrootmap.compress_callshape(shape)
- expected_shapeaddr[i] = shapeaddr
- retaddr = rffi.cast(llmemory.Address, 123456789 + i)
+ gcrootmap.add_ebp_offset(shape, num1)
+ gcrootmap.add_ebp_offset(shape, num2)
+ assert shape == map(chr, [6, 7, 11, 15, 2, 0, num1a, num2b, num2a])
+ gcrootmap.add_callee_save_reg(shape, 1)
+ assert shape == map(chr, [6, 7, 11, 15, 2, 0, num1a, num2b, num2a,
+ 4])
+ gcrootmap.add_callee_save_reg(shape, 2)
+ assert shape == map(chr, [6, 7, 11, 15, 2, 0, num1a, num2b, num2a,
+ 4, 8])
+ gcrootmap.add_callee_save_reg(shape, 3)
+ assert shape == map(chr, [6, 7, 11, 15, 2, 0, num1a, num2b, num2a,
+ 4, 8, 12])
+ gcrootmap.add_callee_save_reg(shape, 4)
+ assert shape == map(chr, [6, 7, 11, 15, 2, 0, num1a, num2b, num2a,
+ 4, 8, 12, 16])
+
+ def test_compress_callshape(self):
+ class FakeDataBlockWrapper:
+ def malloc_aligned(self, size, alignment):
+ assert alignment == 1 # here
+ assert size == 4
+ return rffi.cast(lltype.Signed, p)
+ datablockwrapper = FakeDataBlockWrapper()
+ p = lltype.malloc(rffi.CArray(lltype.Char), 4, immortal=True)
+ gcrootmap = GcRootMap_asmgcc()
+ shape = ['a', 'b', 'c', 'd']
+ gcrootmap.compress_callshape(shape, datablockwrapper)
+ assert p[0] == 'd'
+ assert p[1] == 'c'
+ assert p[2] == 'b'
+ assert p[3] == 'a'
+
+ def test_put_basic(self):
+ gcrootmap = GcRootMap_asmgcc()
+ retaddr = 1234567890
+ shapeaddr = 51627384
gcrootmap.put(retaddr, shapeaddr)
- for i in range(1, 700):
- expected_retaddr = rffi.cast(llmemory.Address, 123456789 + i)
- assert gcrootmap._gcmap[i*2+0] == expected_retaddr
- assert gcrootmap._gcmap[i*2+1] == expected_shapeaddr[i]
+ assert gcrootmap._gcmap[0] == retaddr
+ assert gcrootmap._gcmap[1] == shapeaddr
+ p = rffi.cast(rffi.LONGP, gcrootmap.gcmapstart())
+ assert p[0] == retaddr
+ assert (gcrootmap.gcmapend() ==
+ gcrootmap.gcmapstart() + rffi.sizeof(lltype.Signed) * 2)
+
+ def test_put_resize(self):
+ # the same as before, but enough times to trigger a few resizes
+ gcrootmap = GcRootMap_asmgcc()
+ for i in range(700):
+ shapeaddr = i * 100 + 1
+ retaddr = 123456789 + i
+ gcrootmap.put(retaddr, shapeaddr)
+ for i in range(700):
+ assert gcrootmap._gcmap[i*2+0] == 123456789 + i
+ assert gcrootmap._gcmap[i*2+1] == i * 100 + 1
+
+ def test_remove_nulls(self):
+ expected = []
+ def check():
+ assert gcrootmap._gcmap_curlength == len(expected) * 2
+ for i, (a, b) in enumerate(expected):
+ assert gcrootmap._gcmap[i*2] == a
+ assert gcrootmap._gcmap[i*2+1] == b
+ #
+ gcrootmap = GcRootMap_asmgcc()
+ for i in range(700):
+ shapeaddr = i * 100 # 0 if i == 0
+ retaddr = 123456789 + i
+ gcrootmap.put(retaddr, shapeaddr)
+ if shapeaddr != 0:
+ expected.append((retaddr, shapeaddr))
+ # at the first resize, the 0 should be removed
+ check()
+ for repeat in range(10):
+ # now clear up half the entries
+ assert len(expected) == 699
+ for i in range(0, len(expected), 2):
+ gcrootmap._gcmap[i*2+1] = 0
+ gcrootmap._gcmap_deadentries += 1
+ expected = expected[1::2]
+ assert gcrootmap._gcmap_deadentries*6 > gcrootmap._gcmap_maxlength
+ # check that we can again insert 350 entries without a resize
+ oldgcmap = gcrootmap._gcmap
+ for i in range(0, 699, 2):
+ gcrootmap.put(515151 + i + repeat, 626262 + i)
+ expected.append((515151 + i + repeat, 626262 + i))
+ assert gcrootmap._gcmap == oldgcmap
+ check()
+
+ def test_freeing_block(self):
+ from pypy.jit.backend.llsupport import gc
+ class Asmgcroot:
+ arrayitemsize = 2 * llmemory.sizeof(llmemory.Address)
+ sort_count = 0
+ def sort_gcmap(self, gcmapstart, gcmapend):
+ self.sort_count += 1
+ def binary_search(self, gcmapstart, gcmapend, startaddr):
+ i = 0
+ while (i < gcrootmap._gcmap_curlength//2 and
+ gcrootmap._gcmap[i*2] < startaddr):
+ i += 1
+ if i > 0:
+ i -= 1
+ assert 0 <= i < gcrootmap._gcmap_curlength//2
+ p = rffi.cast(rffi.CArrayPtr(llmemory.Address), gcmapstart)
+ p = rffi.ptradd(p, 2*i)
+ return llmemory.cast_ptr_to_adr(p)
+ saved = gc.asmgcroot
+ try:
+ gc.asmgcroot = Asmgcroot()
+ #
+ gcrootmap = GcRootMap_asmgcc()
+ gcrootmap._gcmap = lltype.malloc(gcrootmap.GCMAP_ARRAY,
+ 1400, flavor='raw',
+ immortal=True)
+ for i in range(700):
+ gcrootmap._gcmap[i*2] = 1200000 + i
+ gcrootmap._gcmap[i*2+1] = i * 100 + 1
+ assert gcrootmap._gcmap_deadentries == 0
+ assert gc.asmgcroot.sort_count == 0
+ gcrootmap._gcmap_maxlength = 1400
+ gcrootmap._gcmap_curlength = 1400
+ gcrootmap._gcmap_sorted = False
+ #
+ gcrootmap.freeing_block(1200000 - 100, 1200000)
+ assert gcrootmap._gcmap_deadentries == 0
+ assert gc.asmgcroot.sort_count == 1
+ #
+ gcrootmap.freeing_block(1200000 + 100, 1200000 + 200)
+ assert gcrootmap._gcmap_deadentries == 100
+ assert gc.asmgcroot.sort_count == 1
+ for i in range(700):
+ if 100 <= i < 200:
+ expected = 0
+ else:
+ expected = i * 100 + 1
+ assert gcrootmap._gcmap[i*2] == 1200000 + i
+ assert gcrootmap._gcmap[i*2+1] == expected
+ #
+ gcrootmap.freeing_block(1200000 + 650, 1200000 + 750)
+ assert gcrootmap._gcmap_deadentries == 150
+ assert gc.asmgcroot.sort_count == 1
+ for i in range(700):
+ if 100 <= i < 200 or 650 <= i:
+ expected = 0
+ else:
+ expected = i * 100 + 1
+ assert gcrootmap._gcmap[i*2] == 1200000 + i
+ assert gcrootmap._gcmap[i*2+1] == expected
+ #
+ finally:
+ gc.asmgcroot = saved
class FakeLLOp(object):
Modified: pypy/branch/out-of-line-guards/pypy/jit/backend/model.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/jit/backend/model.py (original)
+++ pypy/branch/out-of-line-guards/pypy/jit/backend/model.py Thu Dec 9 16:33:59 2010
@@ -1,3 +1,4 @@
+from pypy.rlib.debug import debug_start, debug_print, debug_stop
from pypy.jit.metainterp import history, compile
@@ -7,17 +8,27 @@
done_with_this_frame_int_v = -1
done_with_this_frame_ref_v = -1
done_with_this_frame_float_v = -1
+ total_compiled_loops = 0
+ total_compiled_bridges = 0
+ total_freed_loops = 0
+ total_freed_bridges = 0
def __init__(self):
self.fail_descr_list = []
+ self.fail_descr_free_list = []
def get_fail_descr_number(self, descr):
assert isinstance(descr, history.AbstractFailDescr)
n = descr.index
if n < 0:
lst = self.fail_descr_list
- n = len(lst)
- lst.append(descr)
+ if len(self.fail_descr_free_list) > 0:
+ n = self.fail_descr_free_list.pop()
+ assert lst[n] is None
+ lst[n] = descr
+ else:
+ n = len(lst)
+ lst.append(descr)
descr.index = n
return n
@@ -35,12 +46,14 @@
def compile_loop(self, inputargs, operations, looptoken, log=True):
"""Assemble the given loop.
- Extra attributes should be put in the LoopToken to
- point to the compiled loop in assembler.
+ Should create and attach a fresh CompiledLoopToken to
+ looptoken.compiled_loop_token and stick extra attributes
+ on it to point to the compiled loop in assembler.
"""
raise NotImplementedError
- def compile_bridge(self, faildescr, inputargs, operations, log=True):
+ def compile_bridge(self, faildescr, inputargs, operations,
+ original_loop_token, log=True):
"""Assemble the bridge.
The FailDescr is the descr of the original guard that failed.
"""
@@ -113,6 +126,28 @@
oldlooptoken so that from now own they will call newlooptoken."""
raise NotImplementedError
+ def free_loop_and_bridges(self, compiled_loop_token):
+ """This method is called to free resources (machine code,
+ references to resume guards, etc.) allocated by the compilation
+ of a loop and all bridges attached to it. After this call, the
+ frontend cannot use this compiled loop any more; in fact, it
+ guarantees that at the point of the call to free_code_group(),
+ none of the corresponding assembler is currently running.
+ """
+ # The base class provides a limited implementation: freeing the
+ # resume descrs. This is already quite helpful, because the
+ # resume descrs are the largest consumers of memory (about 3x
+ # more than the assembler, in the case of the x86 backend).
+ lst = self.fail_descr_list
+ # We expect 'compiled_loop_token' to be itself garbage-collected soon,
+ # but better safe than sorry: be ready to handle several calls to
+ # free_loop_and_bridges() for the same compiled_loop_token.
+ faildescr_indices = compiled_loop_token.faildescr_indices
+ compiled_loop_token.faildescr_indices = []
+ for n in faildescr_indices:
+ lst[n] = None
+ self.fail_descr_free_list.extend(faildescr_indices)
+
@staticmethod
def sizeof(S):
raise NotImplementedError
@@ -237,3 +272,40 @@
def force(self, force_token):
raise NotImplementedError
+
+
+class CompiledLoopToken(object):
+ asmmemmgr_blocks = None
+ asmmemmgr_gcroots = 0
+
+ def __init__(self, cpu, number):
+ cpu.total_compiled_loops += 1
+ self.cpu = cpu
+ self.number = number
+ self.bridges_count = 0
+ # This growing list gives the 'descr_number' of all fail descrs
+ # that belong to this loop or to a bridge attached to it.
+ # Filled by the frontend calling record_faildescr_index().
+ self.faildescr_indices = []
+ debug_start("jit-mem-looptoken-alloc")
+ debug_print("allocating Loop #", self.number)
+ debug_stop("jit-mem-looptoken-alloc")
+
+ def record_faildescr_index(self, n):
+ self.faildescr_indices.append(n)
+
+ def compiling_a_bridge(self):
+ self.cpu.total_compiled_bridges += 1
+ self.bridges_count += 1
+ debug_start("jit-mem-looptoken-alloc")
+ debug_print("allocating Bridge #", self.bridges_count, "of Loop #", self.number)
+ debug_stop("jit-mem-looptoken-alloc")
+
+ def __del__(self):
+ debug_start("jit-mem-looptoken-free")
+ debug_print("freeing Loop #", self.number, 'with',
+ self.bridges_count, 'attached bridges')
+ self.cpu.free_loop_and_bridges(self)
+ self.cpu.total_freed_loops += 1
+ self.cpu.total_freed_bridges += self.bridges_count
+ debug_stop("jit-mem-looptoken-free")
Modified: pypy/branch/out-of-line-guards/pypy/jit/backend/test/runner_test.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/jit/backend/test/runner_test.py (original)
+++ pypy/branch/out-of-line-guards/pypy/jit/backend/test/runner_test.py Thu Dec 9 16:33:59 2010
@@ -174,6 +174,8 @@
assert not wr_i1() and not wr_guard()
def test_compile_bridge(self):
+ self.cpu.total_compiled_loops = 0
+ self.cpu.total_compiled_bridges = 0
i0 = BoxInt()
i1 = BoxInt()
i2 = BoxInt()
@@ -199,7 +201,7 @@
]
bridge[1].setfailargs([i1b])
- self.cpu.compile_bridge(faildescr1, [i1b], bridge)
+ self.cpu.compile_bridge(faildescr1, [i1b], bridge, looptoken)
self.cpu.set_future_value_int(0, 2)
fail = self.cpu.execute_token(looptoken)
@@ -207,6 +209,10 @@
res = self.cpu.get_latest_value_int(0)
assert res == 20
+ assert self.cpu.total_compiled_loops == 1
+ assert self.cpu.total_compiled_bridges == 1
+ return looptoken
+
def test_compile_bridge_with_holes(self):
i0 = BoxInt()
i1 = BoxInt()
@@ -233,7 +239,7 @@
]
bridge[1].setfailargs([i1b])
- self.cpu.compile_bridge(faildescr1, [i1b], bridge)
+ self.cpu.compile_bridge(faildescr1, [i1b], bridge, looptoken)
self.cpu.set_future_value_int(0, 2)
fail = self.cpu.execute_token(looptoken)
@@ -1050,7 +1056,7 @@
ResOperation(rop.JUMP, [f3] + fboxes2[1:], None, descr=looptoken),
]
- self.cpu.compile_bridge(faildescr1, fboxes2, bridge)
+ self.cpu.compile_bridge(faildescr1, fboxes2, bridge, looptoken)
for i in range(len(fboxes)):
self.cpu.set_future_value_float(i, 13.5 + 6.73 * i)
@@ -1197,6 +1203,13 @@
yield nan_and_infinity, rop.FLOAT_GT, operator.gt, all_cases_binary
yield nan_and_infinity, rop.FLOAT_GE, operator.ge, all_cases_binary
+ def test_noops(self):
+ c_box = self.alloc_string("hi there").constbox()
+ c_nest = ConstInt(0)
+ self.execute_operation(rop.DEBUG_MERGE_POINT, [c_box, c_nest], 'void')
+ self.execute_operation(rop.JIT_DEBUG, [c_box, c_nest, c_nest,
+ c_nest, c_nest], 'void')
+
class LLtypeBackendTest(BaseBackendTest):
@@ -2224,6 +2237,20 @@
assert res.value == expected, (
"%r: got %r, expected %r" % (RESTYPE, res.value, expected))
+ def test_free_loop_and_bridges(self):
+ from pypy.jit.backend.llsupport.llmodel import AbstractLLCPU
+ if not isinstance(self.cpu, AbstractLLCPU):
+ py.test.skip("not a subclass of llmodel.AbstractLLCPU")
+ if hasattr(self.cpu, 'setup_once'):
+ self.cpu.setup_once()
+ mem0 = self.cpu.asmmemmgr.total_mallocs
+ looptoken = self.test_compile_bridge()
+ mem1 = self.cpu.asmmemmgr.total_mallocs
+ self.cpu.free_loop_and_bridges(looptoken.compiled_loop_token)
+ mem2 = self.cpu.asmmemmgr.total_mallocs
+ assert mem2 < mem1
+ assert mem2 == mem0
+
class OOtypeBackendTest(BaseBackendTest):
Modified: pypy/branch/out-of-line-guards/pypy/jit/backend/test/test_random.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/jit/backend/test/test_random.py (original)
+++ pypy/branch/out-of-line-guards/pypy/jit/backend/test/test_random.py Thu Dec 9 16:33:59 2010
@@ -524,7 +524,7 @@
self.prebuilt_ptr_consts = []
self.r = r
self.build_random_loop(cpu, builder_factory, r, startvars)
-
+
def build_random_loop(self, cpu, builder_factory, r, startvars):
loop = TreeLoop('test_random_function')
@@ -685,11 +685,12 @@
subloop.operations[-1] = jump_op
self.guard_op = rl.guard_op
self.prebuilt_ptr_consts += rl.prebuilt_ptr_consts
+ self.loop.token.record_jump_to(rl.loop.token)
self.dont_generate_more = True
if r.random() < .05:
return False
self.builder.cpu.compile_bridge(fail_descr, fail_args,
- subloop.operations)
+ subloop.operations, self.loop.token)
return True
def check_random_function(cpu, BuilderClass, r, num=None, max=None):
Modified: pypy/branch/out-of-line-guards/pypy/jit/backend/x86/assembler.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/jit/backend/x86/assembler.py (original)
+++ pypy/branch/out-of-line-guards/pypy/jit/backend/x86/assembler.py Thu Dec 9 16:33:59 2010
@@ -1,12 +1,13 @@
import sys, os
from pypy.jit.backend.llsupport import symbolic
+from pypy.jit.backend.llsupport.asmmemmgr import MachineDataBlockWrapper
from pypy.jit.metainterp.history import Const, Box, BoxInt, BoxPtr, BoxFloat
from pypy.jit.metainterp.history import (AbstractFailDescr, INT, REF, FLOAT,
LoopToken)
from pypy.rpython.lltypesystem import lltype, rffi, rstr, llmemory
from pypy.rpython.lltypesystem.lloperation import llop
from pypy.rpython.annlowlevel import llhelper
-from pypy.tool.uid import fixid
+from pypy.jit.backend.model import CompiledLoopToken
from pypy.jit.backend.x86.regalloc import (RegAlloc, X86RegisterManager,
X86XMMRegisterManager, get_ebp_ofs,
_get_scale)
@@ -30,10 +31,11 @@
from pypy.jit.backend.x86 import rx86, regloc, codebuf
from pypy.jit.metainterp.resoperation import rop, ResOperation
from pypy.jit.backend.x86.support import values_array
-from pypy.rlib.debug import debug_print
+from pypy.jit.backend.x86 import support
+from pypy.rlib.debug import (debug_print, debug_start, debug_stop,
+ have_debug_prints)
from pypy.rlib import rgc
from pypy.jit.backend.x86.jump import remap_frame_layout
-from pypy.rlib.streamio import open_file_as_stream
from pypy.jit.metainterp.history import ConstInt, BoxInt
# darwin requires the stack to be 16 bytes aligned on calls. Same for gcc 4.5.0,
@@ -43,123 +45,17 @@
def align_stack_words(words):
return (words + CALL_ALIGN - 1) & ~(CALL_ALIGN-1)
-class MachineCodeBlockWrapper(object):
- MC_DEFAULT_SIZE = 1024*1024
-
- def __init__(self, assembler, bigsize, profile_agent=None):
- self.assembler = assembler
- self.old_mcs = [] # keepalive
- self.bigsize = bigsize
- self._mc = self._instantiate_mc()
- self.function_name = None
- self.profile_agent = profile_agent
- self.reset_reserved_bytes()
-
- def _instantiate_mc(self): # hook for testing
- return codebuf.MachineCodeBlock(self.bigsize)
-
- def ensure_bytes_available(self, num_bytes):
- if self.bytes_free() <= (self._reserved_bytes + num_bytes):
- self.make_new_mc()
-
- def reserve_bytes(self, num_bytes):
- self.ensure_bytes_available(num_bytes)
- self._reserved_bytes += num_bytes
-
- def reset_reserved_bytes(self):
- # XXX er.... pretty random number, just to be sure
- # not to write half-instruction
- self._reserved_bytes = 64
-
- def get_relative_pos(self):
- return self._mc.get_relative_pos()
-
- def overwrite(self, pos, listofchars):
- return self._mc.overwrite(pos, listofchars)
-
- def bytes_free(self):
- return self._mc._size - self._mc.get_relative_pos()
-
- def start_function(self, name):
- self.function_name = name
- self.start_pos = self._mc.get_relative_pos()
-
- def end_function(self, done=True):
- assert self.function_name is not None
- size = self._mc.get_relative_pos() - self.start_pos
- address = self.tell() - size
- if self.profile_agent is not None:
- self.profile_agent.native_code_written(self.function_name,
- address, size)
- if done:
- self.function_name = None
-
- def make_new_mc(self):
- new_mc = self._instantiate_mc()
- debug_print('[new machine code block at', new_mc.tell(), ']')
-
- if IS_X86_64:
- # The scratch register is sometimes used as a temporary
- # register, but the JMP below might clobber it. Rather than risk
- # subtle bugs, we preserve the scratch register across the jump.
- self._mc.PUSH_r(X86_64_SCRATCH_REG.value)
-
- self._mc.JMP(imm(new_mc.tell()))
-
- if IS_X86_64:
- # Restore scratch reg
- new_mc.POP_r(X86_64_SCRATCH_REG.value)
-
- if self.function_name is not None:
- self.end_function(done=False)
- self.start_pos = new_mc.get_relative_pos()
-
- self.assembler.write_pending_failure_recoveries()
-
- self._mc.done()
- self.old_mcs.append(self._mc)
- self._mc = new_mc
- make_new_mc._dont_inline_ = True
-
- def tell(self):
- return self._mc.tell()
-
- def done(self):
- self._mc.done()
-
-def _new_method(name):
- def method(self, *args):
- if self.bytes_free() < self._reserved_bytes:
- self.make_new_mc()
- getattr(self._mc, name)(*args)
- method.func_name = name
- return method
-
-for _name in rx86.all_instructions + regloc.all_extra_instructions:
- setattr(MachineCodeBlockWrapper, _name, _new_method(_name))
-
-for name in dir(codebuf.MachineCodeBlock):
- if name.upper() == name or name == "writechr":
- setattr(MachineCodeBlockWrapper, name, _new_method(name))
class GuardToken(object):
- def __init__(self, faildescr, failargs, fail_locs, exc, desc_bytes):
+ def __init__(self, faildescr, failargs, fail_locs, exc):
self.faildescr = faildescr
self.failargs = failargs
self.fail_locs = fail_locs
self.exc = exc
- self.desc_bytes = desc_bytes
-
- def recovery_stub_size(self):
- # XXX: 32 is pulled out of the air
- return 32 + len(self.desc_bytes)
DEBUG_COUNTER = lltype.Struct('DEBUG_COUNTER', ('i', lltype.Signed))
class Assembler386(object):
- mc = None
- mc_size = MachineCodeBlockWrapper.MC_DEFAULT_SIZE
- _float_constants = None
_regalloc = None
_output_loop_log = None
@@ -177,16 +73,18 @@
self.fail_boxes_float = values_array(lltype.Float, failargs_limit)
self.fail_ebp = 0
self.loop_run_counters = []
- # if we have 10000 loops, we have some other problems I guess
self.float_const_neg_addr = 0
self.float_const_abs_addr = 0
self.malloc_fixedsize_slowpath1 = 0
self.malloc_fixedsize_slowpath2 = 0
- self.pending_guard_tokens = None
self.memcpy_addr = 0
self.setup_failure_recovery()
self._debug = False
self.debug_counter_descr = cpu.fielddescrof(DEBUG_COUNTER, 'i')
+ self.fail_boxes_count = 0
+ self._current_depths_cache = (0, 0)
+ self.datablockwrapper = None
+ self.teardown()
def leave_jitted_hook(self):
ptrs = self.fail_boxes_ptr.ar
@@ -196,67 +94,65 @@
def set_debug(self, v):
self._debug = v
- def setup(self):
- if self.mc is None:
- # the address of the function called by 'new'
- gc_ll_descr = self.cpu.gc_ll_descr
- gc_ll_descr.initialize()
- ll_new = gc_ll_descr.get_funcptr_for_new()
- self.malloc_func_addr = rffi.cast(lltype.Signed, ll_new)
- if gc_ll_descr.get_funcptr_for_newarray is not None:
- ll_new_array = gc_ll_descr.get_funcptr_for_newarray()
- self.malloc_array_func_addr = rffi.cast(lltype.Signed,
- ll_new_array)
- if gc_ll_descr.get_funcptr_for_newstr is not None:
- ll_new_str = gc_ll_descr.get_funcptr_for_newstr()
- self.malloc_str_func_addr = rffi.cast(lltype.Signed,
- ll_new_str)
- if gc_ll_descr.get_funcptr_for_newunicode is not None:
- ll_new_unicode = gc_ll_descr.get_funcptr_for_newunicode()
- self.malloc_unicode_func_addr = rffi.cast(lltype.Signed,
- ll_new_unicode)
- self.memcpy_addr = self.cpu.cast_ptr_to_int(codebuf.memcpy_fn)
- self.mc = MachineCodeBlockWrapper(self, self.mc_size, self.cpu.profile_agent)
- self._build_failure_recovery(False)
- self._build_failure_recovery(True)
- if self.cpu.supports_floats:
- self._build_failure_recovery(False, withfloats=True)
- self._build_failure_recovery(True, withfloats=True)
- codebuf.ensure_sse2_floats()
- self._build_float_constants()
- if hasattr(gc_ll_descr, 'get_malloc_fixedsize_slowpath_addr'):
- self._build_malloc_fixedsize_slowpath()
- s = os.environ.get('PYPYLOG')
- if s:
- if s.find(':') != -1:
- s = s.split(':')[-1]
- self.set_debug(True)
- self._output_loop_log = s + ".count"
- # Intialize here instead of __init__ to prevent
- # pending_guard_tokens from being considered a prebuilt object,
- # which sometimes causes memory leaks since the prebuilt list is
- # still considered a GC root after we re-assign
- # pending_guard_tokens in write_pending_failure_recoveries
- self.pending_guard_tokens = []
+ def setup_once(self):
+ # the address of the function called by 'new'
+ gc_ll_descr = self.cpu.gc_ll_descr
+ gc_ll_descr.initialize()
+ ll_new = gc_ll_descr.get_funcptr_for_new()
+ self.malloc_func_addr = rffi.cast(lltype.Signed, ll_new)
+ if gc_ll_descr.get_funcptr_for_newarray is not None:
+ ll_new_array = gc_ll_descr.get_funcptr_for_newarray()
+ self.malloc_array_func_addr = rffi.cast(lltype.Signed,
+ ll_new_array)
+ if gc_ll_descr.get_funcptr_for_newstr is not None:
+ ll_new_str = gc_ll_descr.get_funcptr_for_newstr()
+ self.malloc_str_func_addr = rffi.cast(lltype.Signed,
+ ll_new_str)
+ if gc_ll_descr.get_funcptr_for_newunicode is not None:
+ ll_new_unicode = gc_ll_descr.get_funcptr_for_newunicode()
+ self.malloc_unicode_func_addr = rffi.cast(lltype.Signed,
+ ll_new_unicode)
+ self.memcpy_addr = self.cpu.cast_ptr_to_int(support.memcpy_fn)
+ self._build_failure_recovery(False)
+ self._build_failure_recovery(True)
+ if self.cpu.supports_floats:
+ self._build_failure_recovery(False, withfloats=True)
+ self._build_failure_recovery(True, withfloats=True)
+ support.ensure_sse2_floats()
+ self._build_float_constants()
+ if hasattr(gc_ll_descr, 'get_malloc_fixedsize_slowpath_addr'):
+ self._build_malloc_fixedsize_slowpath()
+ debug_start('jit-backend-counts')
+ self.set_debug(have_debug_prints())
+ debug_stop('jit-backend-counts')
+
+ def setup(self, looptoken):
+ assert self.memcpy_addr != 0, "setup_once() not called?"
+ self.pending_guard_tokens = []
+ self.mc = codebuf.MachineCodeBlockWrapper()
+ if self.datablockwrapper is None:
+ allblocks = self.get_asmmemmgr_blocks(looptoken)
+ self.datablockwrapper = MachineDataBlockWrapper(self.cpu.asmmemmgr,
+ allblocks)
+
+ def teardown(self):
+ self.pending_guard_tokens = None
+ self.mc = None
+ self.looppos = -1
+ self.currently_compiling_loop = None
def finish_once(self):
if self._debug:
- output_log = self._output_loop_log
- assert output_log is not None
- f = open_file_as_stream(output_log, "w")
+ debug_start('jit-backend-counts')
for i in range(len(self.loop_run_counters)):
- name, struct = self.loop_run_counters[i]
- f.write(str(name) + ":" + str(struct.i) + "\n")
- f.close()
+ struct = self.loop_run_counters[i]
+ debug_print(str(i) + ':' + str(struct.i))
+ debug_stop('jit-backend-counts')
def _build_float_constants(self):
- # 44 bytes: 32 bytes for the data, and up to 12 bytes for alignment
- addr = lltype.malloc(rffi.CArray(lltype.Char), 44, flavor='raw',
- track_allocation=False)
- if not we_are_translated():
- self._keepalive_malloced_float_consts = addr
- float_constants = rffi.cast(lltype.Signed, addr)
- float_constants = (float_constants + 15) & ~15 # align to 16 bytes
+ datablockwrapper = MachineDataBlockWrapper(self.cpu.asmmemmgr, [])
+ float_constants = datablockwrapper.malloc_aligned(32, alignment=16)
+ datablockwrapper.done()
addr = rffi.cast(rffi.CArrayPtr(lltype.Char), float_constants)
qword_padding = '\x00\x00\x00\x00\x00\x00\x00\x00'
# 0x8000000000000000
@@ -271,45 +167,56 @@
def _build_malloc_fixedsize_slowpath(self):
# ---------- first helper for the slow path of malloc ----------
- self.malloc_fixedsize_slowpath1 = self.mc.tell()
+ mc = codebuf.MachineCodeBlockWrapper()
if self.cpu.supports_floats: # save the XMM registers in
for i in range(self.cpu.NUM_REGS):# the *caller* frame, from esp+8
- self.mc.MOVSD_sx((WORD*2)+8*i, i)
- self.mc.SUB_rr(edx.value, eax.value) # compute the size we want
+ mc.MOVSD_sx((WORD*2)+8*i, i)
+ mc.SUB_rr(edx.value, eax.value) # compute the size we want
if IS_X86_32:
- self.mc.MOV_sr(WORD, edx.value) # save it as the new argument
+ mc.MOV_sr(WORD, edx.value) # save it as the new argument
elif IS_X86_64:
# rdi can be clobbered: its content was forced to the stack
# by _fastpath_malloc(), like all other save_around_call_regs.
- self.mc.MOV_rr(edi.value, edx.value)
+ mc.MOV_rr(edi.value, edx.value)
addr = self.cpu.gc_ll_descr.get_malloc_fixedsize_slowpath_addr()
- self.mc.JMP(imm(addr)) # tail call to the real malloc
+ mc.JMP(imm(addr)) # tail call to the real malloc
+ rawstart = mc.materialize(self.cpu.asmmemmgr, [])
+ self.malloc_fixedsize_slowpath1 = rawstart
# ---------- second helper for the slow path of malloc ----------
- self.malloc_fixedsize_slowpath2 = self.mc.tell()
+ mc = codebuf.MachineCodeBlockWrapper()
if self.cpu.supports_floats: # restore the XMM registers
for i in range(self.cpu.NUM_REGS):# from where they were saved
- self.mc.MOVSD_xs(i, (WORD*2)+8*i)
+ mc.MOVSD_xs(i, (WORD*2)+8*i)
nursery_free_adr = self.cpu.gc_ll_descr.get_nursery_free_addr()
- self.mc.MOV(edx, heap(nursery_free_adr)) # load this in EDX
- self.mc.RET()
- self.mc.done()
+ mc.MOV(edx, heap(nursery_free_adr)) # load this in EDX
+ mc.RET()
+ rawstart = mc.materialize(self.cpu.asmmemmgr, [])
+ self.malloc_fixedsize_slowpath2 = rawstart
def assemble_loop(self, inputargs, operations, looptoken, log):
- """adds the following attributes to looptoken:
+ '''adds the following attributes to looptoken:
_x86_loop_code (an integer giving an address)
_x86_bootstrap_code (an integer giving an address)
- _x86_direct_bootstrap_code
+ _x86_direct_bootstrap_code ( " " " " )
_x86_frame_depth
_x86_param_depth
_x86_arglocs
_x86_debug_checksum
- """
+ '''
+ # XXX this function is too longish and contains some code
+ # duplication with assemble_bridge(). Also, we should think
+ # about not storing on 'self' attributes that will live only
+ # for the duration of compiling one loop or a one bridge.
+
+ clt = CompiledLoopToken(self.cpu, looptoken.number)
+ looptoken.compiled_loop_token = clt
if not we_are_translated():
# Arguments should be unique
assert len(set(inputargs)) == len(inputargs)
- self.setup()
+ self.setup(looptoken)
+ self.currently_compiling_loop = looptoken
funcname = self._find_debug_merge_point(operations)
if log:
self._register_counter()
@@ -319,43 +226,61 @@
arglocs = regalloc.prepare_loop(inputargs, operations, looptoken)
looptoken._x86_arglocs = arglocs
- # profile support
- name = "Loop # %s: %s" % (looptoken.number, funcname)
- self.mc.start_function(name)
- looptoken._x86_bootstrap_code = self.mc.tell()
- adr_stackadjust = self._assemble_bootstrap_code(inputargs, arglocs)
- curadr = self.mc.tell()
- looptoken._x86_loop_code = curadr
+ bootstrappos = self.mc.get_relative_pos()
+ stackadjustpos = self._assemble_bootstrap_code(inputargs, arglocs)
+ self.looppos = self.mc.get_relative_pos()
looptoken._x86_frame_depth = -1 # temporarily
looptoken._x86_param_depth = -1 # temporarily
frame_depth, param_depth = self._assemble(regalloc, operations)
- self._patch_stackadjust(adr_stackadjust, frame_depth+param_depth)
looptoken._x86_frame_depth = frame_depth
looptoken._x86_param_depth = param_depth
- looptoken._x86_direct_bootstrap_code = self.mc.tell()
- self._assemble_bootstrap_direct_call(arglocs, curadr,
+ directbootstrappos = self.mc.get_relative_pos()
+ self._assemble_bootstrap_direct_call(arglocs, self.looppos,
frame_depth+param_depth)
- #
- debug_print("Loop #%d has address %x to %x" % (looptoken.number,
- looptoken._x86_loop_code,
- self.mc.tell()))
- self.mc.end_function()
self.write_pending_failure_recoveries()
-
- def assemble_bridge(self, faildescr, inputargs, operations, log):
+ fullsize = self.mc.get_relative_pos()
+ #
+ rawstart = self.materialize_loop(looptoken)
+ debug_print("Loop #%d (%s) has address %x to %x" % (
+ looptoken.number, funcname,
+ rawstart + self.looppos,
+ rawstart + directbootstrappos))
+ self._patch_stackadjust(rawstart + stackadjustpos,
+ frame_depth + param_depth)
+ self.patch_pending_failure_recoveries(rawstart)
+ #
+ looptoken._x86_bootstrap_code = rawstart + bootstrappos
+ looptoken._x86_loop_code = rawstart + self.looppos
+ looptoken._x86_direct_bootstrap_code = rawstart + directbootstrappos
+ self.teardown()
+ # oprofile support
+ if self.cpu.profile_agent is not None:
+ name = "Loop # %s: %s" % (looptoken.number, funcname)
+ self.cpu.profile_agent.native_code_written(name,
+ rawstart, fullsize)
+
+ def assemble_bridge(self, faildescr, inputargs, operations,
+ original_loop_token, log):
if not we_are_translated():
# Arguments should be unique
assert len(set(inputargs)) == len(inputargs)
- self.setup()
+ descr_number = self.cpu.get_fail_descr_number(faildescr)
+ try:
+ failure_recovery = self._find_failure_recovery_bytecode(faildescr)
+ except ValueError:
+ debug_print("Bridge out of guard", descr_number,
+ "was already compiled!")
+ return
+
+ self.setup(original_loop_token)
funcname = self._find_debug_merge_point(operations)
if log:
self._register_counter()
operations = self._inject_debugging_code(faildescr, operations)
- arglocs = self.rebuild_faillocs_from_descr(
- faildescr._x86_failure_recovery_bytecode)
+ arglocs = self.rebuild_faillocs_from_descr(failure_recovery)
if not we_are_translated():
assert ([loc.assembler() for loc in arglocs] ==
[loc.assembler() for loc in faildescr._x86_debug_faillocs])
@@ -364,37 +289,63 @@
regalloc.prepare_bridge(fail_depths, inputargs, arglocs,
operations)
- # oprofile support
- descr_number = self.cpu.get_fail_descr_number(faildescr)
- name = "Bridge # %s: %s" % (descr_number, funcname)
- self.mc.start_function(name)
-
- adr_bridge = self.mc.tell()
- adr_stackadjust = self._patchable_stackadjust()
+ stackadjustpos = self._patchable_stackadjust()
frame_depth, param_depth = self._assemble(regalloc, operations)
- self._patch_stackadjust(adr_stackadjust, frame_depth+param_depth)
+ codeendpos = self.mc.get_relative_pos()
+ self.write_pending_failure_recoveries()
+ fullsize = self.mc.get_relative_pos()
+ #
+ rawstart = self.materialize_loop(original_loop_token)
+
+ debug_print("Bridge out of guard %d (%s) has address %x to %x" %
+ (descr_number, funcname, rawstart, rawstart + codeendpos))
+ self._patch_stackadjust(rawstart + stackadjustpos,
+ frame_depth + param_depth)
+ self.patch_pending_failure_recoveries(rawstart)
if not we_are_translated():
# for the benefit of tests
faildescr._x86_bridge_frame_depth = frame_depth
faildescr._x86_bridge_param_depth = param_depth
# patch the jump from original guard
- self.patch_jump_for_descr(faildescr, adr_bridge)
- debug_print("Bridge out of guard %d has address %x to %x" %
- (descr_number, adr_bridge, self.mc.tell()))
- self.mc.end_function()
- self.write_pending_failure_recoveries()
+ self.patch_jump_for_descr(faildescr, rawstart)
+ self.teardown()
+ # oprofile support
+ if self.cpu.profile_agent is not None:
+ name = "Bridge # %s: %s" % (descr_number, funcname)
+ self.cpu.profile_agent.native_code_written(name,
+ rawstart, fullsize)
def write_pending_failure_recoveries(self):
+ # for each pending guard, generate the code of the recovery stub
+ # at the end of self.mc.
for tok in self.pending_guard_tokens:
- # Okay to write to _mc because we've already made sure that
- # there's enough space by "reserving" bytes.
- addr = self.generate_quick_failure(self.mc._mc, tok.faildescr, tok.failargs, tok.fail_locs, tok.exc, tok.desc_bytes)
- tok.faildescr._x86_adr_recovery_stub = addr
- self.patch_jump_for_descr(tok.faildescr, addr)
+ tok.pos_recovery_stub = self.generate_quick_failure(tok)
- self.pending_guard_tokens = []
- self.mc.reset_reserved_bytes()
- self.mc.done()
+ def patch_pending_failure_recoveries(self, rawstart):
+ # after we wrote the assembler to raw memory, set up
+ # tok.faildescr._x86_adr_jump_offset to contain the raw address of
+ # the 4-byte target field in the JMP/Jcond instruction, and patch
+ # the field in question to point (initially) to the recovery stub
+ for tok in self.pending_guard_tokens:
+ addr = rawstart + tok.pos_jump_offset
+ tok.faildescr._x86_adr_jump_offset = addr
+ relative_target = tok.pos_recovery_stub - (tok.pos_jump_offset + 4)
+ assert rx86.fits_in_32bits(relative_target)
+ p = rffi.cast(rffi.INTP, addr)
+ p[0] = rffi.cast(rffi.INT, relative_target)
+
+ def get_asmmemmgr_blocks(self, looptoken):
+ clt = looptoken.compiled_loop_token
+ if clt.asmmemmgr_blocks is None:
+ clt.asmmemmgr_blocks = []
+ return clt.asmmemmgr_blocks
+
+ def materialize_loop(self, looptoken):
+ self.datablockwrapper.done() # finish using cpu.asmmemmgr
+ self.datablockwrapper = None
+ allblocks = self.get_asmmemmgr_blocks(looptoken)
+ return self.mc.materialize(self.cpu.asmmemmgr, allblocks,
+ self.cpu.gc_ll_descr.gcrootmap)
def _find_debug_merge_point(self, operations):
@@ -409,29 +360,50 @@
def _register_counter(self):
if self._debug:
+ # YYY very minor leak -- we need the counters to stay alive
+ # forever, just because we want to report them at the end
+ # of the process
struct = lltype.malloc(DEBUG_COUNTER, flavor='raw',
- track_allocation=False) # known to leak
+ track_allocation=False)
struct.i = 0
- self.loop_run_counters.append((len(self.loop_run_counters), struct))
-
+ self.loop_run_counters.append(struct)
+
+ def _find_failure_recovery_bytecode(self, faildescr):
+ adr_jump_offset = faildescr._x86_adr_jump_offset
+ if adr_jump_offset == 0:
+ raise ValueError
+ # follow the JMP/Jcond
+ p = rffi.cast(rffi.INTP, adr_jump_offset)
+ adr_target = adr_jump_offset + 4 + rffi.cast(lltype.Signed, p[0])
+ # skip the CALL
+ if WORD == 4:
+ adr_target += 5 # CALL imm
+ else:
+ adr_target += 13 # MOV r11, imm; CALL *r11
+ return adr_target
+
def patch_jump_for_descr(self, faildescr, adr_new_target):
adr_jump_offset = faildescr._x86_adr_jump_offset
- adr_recovery_stub = faildescr._x86_adr_recovery_stub
+ assert adr_jump_offset != 0
offset = adr_new_target - (adr_jump_offset + 4)
# If the new target fits within a rel32 of the jump, just patch
# that. Otherwise, leave the original rel32 to the recovery stub in
# place, but clobber the recovery stub with a jump to the real
# target.
+ mc = codebuf.MachineCodeBlockWrapper()
if rx86.fits_in_32bits(offset):
- mc = codebuf.InMemoryCodeBuilder(adr_jump_offset, adr_jump_offset + 4)
mc.writeimm32(offset)
+ mc.copy_to_raw_memory(adr_jump_offset)
else:
- # "mov r11, addr; jmp r11" is 13 bytes
- mc = codebuf.InMemoryCodeBuilder(adr_recovery_stub, adr_recovery_stub + 13)
+ # "mov r11, addr; jmp r11" is 13 bytes, which fits in there
+ # because we always write "mov r11, addr; call *r11" in the
+ # first place.
mc.MOV_ri(X86_64_SCRATCH_REG.value, adr_new_target)
mc.JMP_r(X86_64_SCRATCH_REG.value)
-
- mc.done()
+ p = rffi.cast(rffi.INTP, adr_jump_offset)
+ adr_target = adr_jump_offset + 4 + rffi.cast(lltype.Signed, p[0])
+ mc.copy_to_raw_memory(adr_target)
+ faildescr._x86_adr_jump_offset = 0 # means "patched"
@specialize.argtype(1)
def _inject_debugging_code(self, looptoken, operations):
@@ -442,7 +414,7 @@
s += op.getopnum()
looptoken._x86_debug_checksum = s
c_adr = ConstInt(rffi.cast(lltype.Signed,
- self.loop_run_counters[-1][1]))
+ self.loop_run_counters[-1]))
box = BoxInt()
box2 = BoxInt()
ops = [ResOperation(rop.GETFIELD_RAW, [c_adr],
@@ -451,19 +423,11 @@
ResOperation(rop.SETFIELD_RAW, [c_adr, box2],
None, descr=self.debug_counter_descr)]
operations = ops + operations
- # # we need one register free (a bit of a hack, but whatever)
- # self.mc.PUSH(eax)
- # adr = rffi.cast(lltype.Signed, self.loop_run_counters[-1][1])
- # self.mc.MOV(eax, heap(adr))
- # self.mc.ADD(eax, imm1)
- # self.mc.MOV(heap(adr), eax)
- # self.mc.POP(eax)
return operations
def _assemble(self, regalloc, operations):
self._regalloc = regalloc
regalloc.walk_operations(operations)
- self.mc.done()
if we_are_translated() or self.cpu.dont_keepalive_stuff:
self._regalloc = None # else keep it around for debugging
frame_depth = regalloc.fm.frame_depth
@@ -479,30 +443,31 @@
def _patchable_stackadjust(self):
# stack adjustment LEA
self.mc.LEA32_rb(esp.value, 0)
- return self.mc.tell() - 4
+ return self.mc.get_relative_pos() - 4
- def _patch_stackadjust(self, adr_lea, reserved_depth):
+ def _patch_stackadjust(self, adr_lea, allocated_depth):
# patch stack adjustment LEA
- mc = codebuf.InMemoryCodeBuilder(adr_lea, adr_lea + 4)
- # Compute the correct offset for the instruction LEA ESP, [EBP-4*words].
+ mc = codebuf.MachineCodeBlockWrapper()
+ # Compute the correct offset for the instruction LEA ESP, [EBP-4*words]
+ mc.writeimm32(self._get_offset_of_ebp_from_esp(allocated_depth))
+ mc.copy_to_raw_memory(adr_lea)
+
+ def _get_offset_of_ebp_from_esp(self, allocated_depth):
# Given that [EBP] is where we saved EBP, i.e. in the last word
# of our fixed frame, then the 'words' value is:
- words = (self.cpu.FRAME_FIXED_SIZE - 1) + reserved_depth
- # align, e.g. for Mac OS X
+ words = (self.cpu.FRAME_FIXED_SIZE - 1) + allocated_depth
+ # align, e.g. for Mac OS X
aligned_words = align_stack_words(words+2)-2 # 2 = EIP+EBP
- mc.writeimm32(-WORD * aligned_words)
- mc.done()
+ return -WORD * aligned_words
def _call_header(self):
+ # NB. the shape of the frame is hard-coded in get_basic_shape() too.
+ # Also, make sure this is consistent with FRAME_FIXED_SIZE.
self.mc.PUSH_r(ebp.value)
self.mc.MOV_rr(ebp.value, esp.value)
for regloc in self.cpu.CALLEE_SAVE_REGISTERS:
self.mc.PUSH_r(regloc.value)
- # NB. the shape of the frame is hard-coded in get_basic_shape() too.
- # Also, make sure this is consistent with FRAME_FIXED_SIZE.
- return self._patchable_stackadjust()
-
def _call_footer(self):
self.mc.LEA_rb(esp.value, -len(self.cpu.CALLEE_SAVE_REGISTERS) * WORD)
@@ -512,17 +477,16 @@
self.mc.POP_r(ebp.value)
self.mc.RET()
- def _assemble_bootstrap_direct_call(self, arglocs, jmpadr, stackdepth):
+ def _assemble_bootstrap_direct_call(self, arglocs, jmppos, stackdepth):
if IS_X86_64:
- return self._assemble_bootstrap_direct_call_64(arglocs, jmpadr, stackdepth)
+ return self._assemble_bootstrap_direct_call_64(arglocs, jmppos, stackdepth)
# XXX pushing ebx esi and edi is a bit pointless, since we store
# all regsiters anyway, for the case of guard_not_forced
# XXX this can be improved greatly. Right now it'll behave like
# a normal call
nonfloatlocs, floatlocs = arglocs
- # XXX not to repeat the logic, a bit around
- adr_stackadjust = self._call_header()
- self._patch_stackadjust(adr_stackadjust, stackdepth)
+ self._call_header()
+ self.mc.LEA_rb(esp.value, self._get_offset_of_ebp_from_esp(stackdepth))
for i in range(len(nonfloatlocs)):
loc = nonfloatlocs[i]
if isinstance(loc, RegLoc):
@@ -544,9 +508,11 @@
self.mc.MOVSD_xb(xmmtmp.value, (1 + i) * 2 * WORD)
assert isinstance(loc, StackLoc)
self.mc.MOVSD_bx(loc.value, xmmtmp.value)
- self.mc.JMP_l(jmpadr)
+ endpos = self.mc.get_relative_pos() + 5
+ self.mc.JMP_l(jmppos - endpos)
+ assert endpos == self.mc.get_relative_pos()
- def _assemble_bootstrap_direct_call_64(self, arglocs, jmpadr, stackdepth):
+ def _assemble_bootstrap_direct_call_64(self, arglocs, jmppos, stackdepth):
# XXX: Very similar to _emit_call_64
src_locs = []
@@ -560,8 +526,8 @@
unused_xmm = [xmm7, xmm6, xmm5, xmm4, xmm3, xmm2, xmm1, xmm0]
nonfloatlocs, floatlocs = arglocs
- adr_stackadjust = self._call_header()
- self._patch_stackadjust(adr_stackadjust, stackdepth)
+ self._call_header()
+ self.mc.LEA_rb(esp.value, self._get_offset_of_ebp_from_esp(stackdepth))
# The lists are padded with Nones
assert len(nonfloatlocs) == len(floatlocs)
@@ -597,8 +563,9 @@
# clobber the scratch register
self.mc.MOV(loc, X86_64_SCRATCH_REG)
- finaljmp = self.mc.tell()
- self.mc.JMP(imm(jmpadr))
+ endpos = self.mc.get_relative_pos() + 5
+ self.mc.JMP_l(jmppos - endpos)
+ assert endpos == self.mc.get_relative_pos()
def redirect_call_assembler(self, oldlooptoken, newlooptoken):
# some minimal sanity checking
@@ -611,16 +578,17 @@
# Ideally we should rather patch all existing CALLs, but well.
oldadr = oldlooptoken._x86_direct_bootstrap_code
target = newlooptoken._x86_direct_bootstrap_code
- mc = codebuf.InMemoryCodeBuilder(oldadr, oldadr + 16)
+ mc = codebuf.MachineCodeBlockWrapper()
mc.JMP(imm(target))
- mc.done()
+ mc.copy_to_raw_memory(oldadr)
def _assemble_bootstrap_code(self, inputargs, arglocs):
nonfloatlocs, floatlocs = arglocs
- adr_stackadjust = self._call_header()
+ self._call_header()
+ stackadjustpos = self._patchable_stackadjust()
tmp = X86RegisterManager.all_regs[0]
xmmtmp = X86XMMRegisterManager.all_regs[0]
- self.mc._mc.begin_reuse_scratch_register()
+ self.mc.begin_reuse_scratch_register()
for i in range(len(nonfloatlocs)):
loc = nonfloatlocs[i]
if loc is None:
@@ -652,8 +620,8 @@
self.mc.MOVSD(xmmtmp, heap(adr))
assert isinstance(loc, StackLoc)
self.mc.MOVSD_bx(loc.value, xmmtmp.value)
- self.mc._mc.end_reuse_scratch_register()
- return adr_stackadjust
+ self.mc.end_reuse_scratch_register()
+ return stackadjustpos
def dump(self, text):
if not self.verbose:
@@ -661,7 +629,8 @@
_prev = Box._extended_display
try:
Box._extended_display = False
- print >> sys.stderr, ' 0x%x %s' % (fixid(self.mc.tell()), text)
+ pos = self.mc.get_relative_pos()
+ print >> sys.stderr, ' 0x%x %s' % (pos, text)
finally:
Box._extended_display = _prev
@@ -721,7 +690,7 @@
arglocs, resloc)
if not we_are_translated():
# must be added by the genop_guard_list[]()
- assert hasattr(faildescr, '_x86_adr_jump_offset')
+ assert guard_token is self.pending_guard_tokens[-1]
def regalloc_perform_guard(self, guard_op, faillocs, arglocs, resloc,
current_depths):
@@ -794,9 +763,6 @@
result_loc):
guard_opnum = guard_op.getopnum()
self.mc.UCOMISD(arglocs[0], arglocs[1])
- # 16 is enough space for the rel8 jumps below and the rel32
- # jump in implement_guard
- self.mc.ensure_bytes_available(16 + guard_token.recovery_stub_size())
if guard_opnum == rop.GUARD_FALSE:
if need_jp:
self.mc.J_il8(rx86.Conditions['P'], 6)
@@ -964,9 +930,6 @@
def genop_guard_float_ne(self, op, guard_op, guard_token, arglocs, result_loc):
guard_opnum = guard_op.getopnum()
self.mc.UCOMISD(arglocs[0], arglocs[1])
- # 16 is enough space for the rel8 jumps below and the rel32
- # jump in implement_guard
- self.mc.ensure_bytes_available(16 + guard_token.recovery_stub_size())
if guard_opnum == rop.GUARD_TRUE:
self.mc.J_il8(rx86.Conditions['P'], 6)
self.implement_guard(guard_token, 'E')
@@ -1290,13 +1253,11 @@
self.mc.CMP32_mi((locs[0].value, 0), expected_typeid)
def genop_guard_guard_class(self, ign_1, guard_op, guard_token, locs, ign_2):
- self.mc.ensure_bytes_available(256)
self._cmp_guard_class(locs)
self.implement_guard(guard_token, 'NE')
def genop_guard_guard_nonnull_class(self, ign_1, guard_op,
guard_token, locs, ign_2):
- self.mc.ensure_bytes_available(256)
self.mc.CMP(locs[0], imm1)
# Patched below
self.mc.J_il8(rx86.Conditions['B'], 0)
@@ -1305,7 +1266,7 @@
# patch the JB above
offset = self.mc.get_relative_pos() - jb_location
assert 0 < offset <= 127
- self.mc.overwrite(jb_location-1, [chr(offset)])
+ self.mc.overwrite(jb_location-1, chr(offset))
#
self.implement_guard(guard_token, 'NE')
@@ -1314,42 +1275,33 @@
exc = (guard_opnum == rop.GUARD_EXCEPTION or
guard_opnum == rop.GUARD_NO_EXCEPTION or
guard_opnum == rop.GUARD_NOT_FORCED)
- desc_bytes = self.failure_recovery_description(failargs, fail_locs)
- return GuardToken(faildescr, failargs, fail_locs, exc, desc_bytes)
+ return GuardToken(faildescr, failargs, fail_locs, exc)
- def generate_quick_failure(self, mc, faildescr, failargs, fail_locs, exc, desc_bytes):
+ def generate_quick_failure(self, guardtok):
"""Generate the initial code for handling a failure. We try to
- keep it as compact as possible. The idea is that this code is
- executed at most once (and very often, zero times); when
- executed, it generates a more complete piece of code which can
- really handle recovery from this particular failure.
+ keep it as compact as possible.
"""
- fail_index = self.cpu.get_fail_descr_number(faildescr)
- addr = mc.tell()
+ fail_index = self.cpu.get_fail_descr_number(guardtok.faildescr)
+ mc = self.mc
+ startpos = mc.get_relative_pos()
withfloats = False
- for box in failargs:
+ for box in guardtok.failargs:
if box is not None and box.type == FLOAT:
withfloats = True
break
+ exc = guardtok.exc
mc.CALL(imm(self.failure_recovery_code[exc + 2 * withfloats]))
# write tight data that describes the failure recovery
- faildescr._x86_failure_recovery_bytecode = mc.tell()
- for byte in desc_bytes:
- mc.writechr(ord(byte))
+ self.write_failure_recovery_description(mc, guardtok.failargs,
+ guardtok.fail_locs)
# write the fail_index too
mc.writeimm32(fail_index)
# for testing the decoding, write a final byte 0xCC
if not we_are_translated():
- mc.writechr(0xCC)
- faildescr._x86_debug_faillocs = [loc for loc in fail_locs
- if loc is not None]
-
- # Make sure the recovery stub is at least 16 bytes long (for the
- # case where we overwrite the recovery stub with a 64-bit absolute
- # jump)
- while mc.tell() - addr < 16:
- mc.writechr(0x00)
- return addr
+ mc.writechar('\xCC')
+ faillocs = [loc for loc in guardtok.fail_locs if loc is not None]
+ guardtok.faildescr._x86_debug_faillocs = faillocs
+ return startpos
DESCR_REF = 0x00
DESCR_INT = 0x01
@@ -1360,8 +1312,7 @@
CODE_STOP = 0 | DESCR_SPECIAL
CODE_HOLE = 4 | DESCR_SPECIAL
- def failure_recovery_description(self, failargs, locs):
- desc_bytes = []
+ def write_failure_recovery_description(self, mc, failargs, locs):
for i in range(len(failargs)):
arg = failargs[i]
if arg is not None:
@@ -1381,19 +1332,14 @@
n = loc.value
n = kind + 4*n
while n > 0x7F:
- desc_bytes.append(chr((n & 0x7F) | 0x80))
+ mc.writechar(chr((n & 0x7F) | 0x80))
n >>= 7
else:
n = self.CODE_HOLE
- desc_bytes.append(chr(n))
- desc_bytes.append(chr(self.CODE_STOP))
+ mc.writechar(chr(n))
+ mc.writechar(chr(self.CODE_STOP))
# assert that the fail_boxes lists are big enough
assert len(failargs) <= self.fail_boxes_int.SIZE
- return desc_bytes
-
- def write_failure_recovery_description(self, mc, failargs, locs):
- for byte in self.failure_recovery_description(failargs, locs):
- mc.writechr(ord(byte))
def rebuild_faillocs_from_descr(self, bytecode):
from pypy.jit.backend.x86.regalloc import X86FrameManager
@@ -1531,10 +1477,8 @@
self.failure_recovery_func)
failure_recovery_func = rffi.cast(lltype.Signed,
failure_recovery_func)
- mc = self.mc._mc
- # Assume that we are called at the beginning, when there is no risk
- # that 'mc' runs out of space. Checked by asserts in mc.write().
- recovery_addr = mc.tell()
+ mc = codebuf.MachineCodeBlockWrapper()
+ self.mc = mc
# Push all general purpose registers
for gpr in range(self.cpu.NUM_REGS-1, -1, -1):
@@ -1585,11 +1529,12 @@
# above.
self._call_footer()
- self.mc.done()
- self.failure_recovery_code[exc + 2 * withfloats] = recovery_addr
+ rawstart = mc.materialize(self.cpu.asmmemmgr, [])
+ self.failure_recovery_code[exc + 2 * withfloats] = rawstart
+ self.mc = None
def generate_failure(self, fail_index, locs, exc, locs_are_ref):
- self.mc._mc.begin_reuse_scratch_register()
+ self.mc.begin_reuse_scratch_register()
for i in range(len(locs)):
loc = locs[i]
if isinstance(loc, RegLoc):
@@ -1616,7 +1561,7 @@
adr = self.fail_boxes_int.get_addr_for_num(i)
self.mc.MOV(eax, loc)
self.mc.MOV(heap(adr), eax)
- self.mc._mc.end_reuse_scratch_register()
+ self.mc.end_reuse_scratch_register()
# we call a provided function that will
# - call our on_leave_jitted_hook which will mark
@@ -1632,17 +1577,13 @@
self._call_footer()
def implement_guard(self, guard_token, condition=None):
- self.mc.reserve_bytes(guard_token.recovery_stub_size())
- self.pending_guard_tokens.append(guard_token)
- # These jumps are patched later, the mc.tell() are just
- # dummy values. Also, use self.mc._mc to avoid triggering a
- # "buffer full" exactly here.
- mc = self.mc._mc
+ # These jumps are patched later.
if condition:
- mc.J_il(rx86.Conditions[condition], mc.tell())
+ self.mc.J_il(rx86.Conditions[condition], 0)
else:
- mc.JMP_l(mc.tell())
- guard_token.faildescr._x86_adr_jump_offset = mc.tell() - 4
+ self.mc.JMP_l(0)
+ guard_token.pos_jump_offset = self.mc.get_relative_pos() - 4
+ self.pending_guard_tokens.append(guard_token)
def genop_call(self, op, arglocs, resloc):
sizeloc = arglocs[0]
@@ -1697,7 +1638,6 @@
# Write a call to the direct_bootstrap_code of the target assembler
self._emit_call(imm(descr._x86_direct_bootstrap_code), arglocs, 2,
tmp=eax)
- self.mc.ensure_bytes_available(256)
if op.result is None:
assert result_loc is None
value = self.cpu.done_with_this_frame_void_v
@@ -1733,7 +1673,7 @@
# Path B: fast path. Must load the return value, and reset the token
offset = jmp_location - je_location
assert 0 < offset <= 127
- self.mc.overwrite(je_location - 1, [chr(offset)])
+ self.mc.overwrite(je_location - 1, chr(offset))
#
# Reset the vable token --- XXX really too much special logic here:-(
if jd.index_of_virtualizable >= 0:
@@ -1768,7 +1708,7 @@
# Here we join Path A and Path B again
offset = self.mc.get_relative_pos() - jmp_location
assert 0 <= offset <= 127
- self.mc.overwrite(jmp_location - 1, [chr(offset)])
+ self.mc.overwrite(jmp_location - 1, chr(offset))
self.mc.CMP_bi(FORCE_INDEX_OFS, 0)
self.implement_guard(guard_token, 'L')
@@ -1783,9 +1723,6 @@
cls = self.cpu.gc_ll_descr.has_write_barrier_class()
assert cls is not None and isinstance(descr, cls)
loc_base = arglocs[0]
- # ensure that enough bytes are available to write the whole
- # following piece of code atomically (for the JZ)
- self.mc.ensure_bytes_available(256)
self.mc.TEST8_mi((loc_base.value, descr.jit_wb_if_flag_byteofs),
descr.jit_wb_if_flag_singlebyte)
self.mc.J_il8(rx86.Conditions['Z'], 0) # patched later
@@ -1828,7 +1765,7 @@
# patch the JZ above
offset = self.mc.get_relative_pos() - jz_location
assert 0 < offset <= 127
- self.mc.overwrite(jz_location-1, [chr(offset)])
+ self.mc.overwrite(jz_location-1, chr(offset))
def genop_force_token(self, op, arglocs, resloc):
# RegAlloc.consider_force_token ensures this:
@@ -1851,18 +1788,21 @@
gcrootmap = self.cpu.gc_ll_descr.gcrootmap
if gcrootmap:
mark = self._regalloc.get_mark_gc_roots(gcrootmap)
- gcrootmap.put(rffi.cast(llmemory.Address, self.mc.tell()), mark)
+ self.mc.insert_gcroot_marker(mark)
def target_arglocs(self, loop_token):
return loop_token._x86_arglocs
def closing_jump(self, loop_token):
- self.mc.JMP(imm(loop_token._x86_loop_code))
+ if loop_token is self.currently_compiling_loop:
+ curpos = self.mc.get_relative_pos() + 5
+ self.mc.JMP_l(self.looppos - curpos)
+ else:
+ self.mc.JMP(imm(loop_token._x86_loop_code))
def malloc_cond_fixedsize(self, nursery_free_adr, nursery_top_adr,
size, tid):
size = max(size, self.cpu.gc_ll_descr.minimal_size_in_nursery)
- self.mc.ensure_bytes_available(256)
self.mc.MOV(eax, heap(nursery_free_adr))
self.mc.LEA_rm(edx.value, (eax.value, size))
self.mc.CMP(edx, heap(nursery_top_adr))
@@ -1890,7 +1830,7 @@
offset = self.mc.get_relative_pos() - jmp_adr
assert 0 < offset <= 127
- self.mc.overwrite(jmp_adr-1, [chr(offset)])
+ self.mc.overwrite(jmp_adr-1, chr(offset))
# on 64-bits, 'tid' is a value that fits in 31 bits
self.mc.MOV_mi((eax.value, 0), tid)
self.mc.MOV(heap(nursery_free_adr), edx)
Modified: pypy/branch/out-of-line-guards/pypy/jit/backend/x86/regalloc.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/jit/backend/x86/regalloc.py (original)
+++ pypy/branch/out-of-line-guards/pypy/jit/backend/x86/regalloc.py Thu Dec 9 16:33:59 2010
@@ -60,32 +60,6 @@
r15: 5,
}
-class FloatConstants(object):
- BASE_CONSTANT_SIZE = 1000
-
- def __init__(self):
- self.cur_array_free = 0
- self.const_id = 0
-
- def _get_new_array(self):
- n = self.BASE_CONSTANT_SIZE
- # known to leak
- self.cur_array = lltype.malloc(rffi.CArray(lltype.Float), n,
- flavor='raw', track_allocation=False)
- self.cur_array_free = n
- _get_new_array._dont_inline_ = True
-
- def record_float(self, floatval):
- if self.cur_array_free == 0:
- self._get_new_array()
- arr = self.cur_array
- n = self.cur_array_free - 1
- arr[n] = floatval
- self.cur_array_free = n
- self.const_id += 1
- return (self.const_id, rffi.cast(lltype.Signed, arr) + n * 8)
-
-
class X86XMMRegisterManager(RegisterManager):
box_types = [FLOAT]
@@ -93,20 +67,11 @@
# we never need lower byte I hope
save_around_call_regs = all_regs
- def __init__(self, longevity, frame_manager=None, assembler=None):
- RegisterManager.__init__(self, longevity, frame_manager=frame_manager,
- assembler=assembler)
- if assembler is None:
- self.float_constants = FloatConstants()
- else:
- if assembler._float_constants is None:
- assembler._float_constants = FloatConstants()
- self.float_constants = assembler._float_constants
-
def convert_to_imm(self, c):
- const_id, adr = self.float_constants.record_float(c.getfloat())
- return ConstFloatLoc(adr, const_id)
-
+ adr = self.assembler.datablockwrapper.malloc_aligned(8, 8)
+ rffi.cast(rffi.CArrayPtr(rffi.DOUBLE), adr)[0] = c.getfloat()
+ return ConstFloatLoc(adr)
+
def after_call(self, v):
# the result is stored in st0, but we don't have this around,
# so genop_call will move it to some frame location immediately
@@ -320,11 +285,22 @@
def locs_for_fail(self, guard_op):
return [self.loc(v) for v in guard_op.getfailargs()]
+ def get_current_depth(self):
+ # return (self.fm.frame_depth, self.param_depth), but trying to share
+ # the resulting tuple among several calls
+ arg0 = self.fm.frame_depth
+ arg1 = self.param_depth
+ result = self.assembler._current_depths_cache
+ if result[0] != arg0 or result[1] != arg1:
+ result = (arg0, arg1)
+ self.assembler._current_depths_cache = result
+ return result
+
def perform_with_guard(self, op, guard_op, arglocs, result_loc):
faillocs = self.locs_for_fail(guard_op)
self.rm.position += 1
self.xrm.position += 1
- current_depths = (self.fm.frame_depth, self.param_depth)
+ current_depths = self.get_current_depth()
self.assembler.regalloc_perform_with_guard(op, guard_op, faillocs,
arglocs, result_loc,
current_depths)
@@ -340,7 +316,7 @@
arglocs))
else:
self.assembler.dump('%s(%s)' % (guard_op, arglocs))
- current_depths = (self.fm.frame_depth, self.param_depth)
+ current_depths = self.get_current_depth()
self.assembler.regalloc_perform_guard(guard_op, faillocs, arglocs,
result_loc,
current_depths)
@@ -1097,7 +1073,8 @@
if (isinstance(v, BoxPtr) and self.rm.stays_alive(v)):
assert reg in self.rm.REGLOC_TO_GCROOTMAP_REG_INDEX
gcrootmap.add_callee_save_reg(shape, self.rm.REGLOC_TO_GCROOTMAP_REG_INDEX[reg])
- return gcrootmap.compress_callshape(shape)
+ return gcrootmap.compress_callshape(shape,
+ self.assembler.datablockwrapper)
def consider_force_token(self, op):
loc = self.rm.force_allocate_reg(op.result)
Modified: pypy/branch/out-of-line-guards/pypy/jit/backend/x86/regloc.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/jit/backend/x86/regloc.py (original)
+++ pypy/branch/out-of-line-guards/pypy/jit/backend/x86/regloc.py Thu Dec 9 16:33:59 2010
@@ -177,24 +177,15 @@
class ConstFloatLoc(AssemblerLocation):
# XXX: We have to use this class instead of just AddressLoc because
- # AddressLoc is "untyped" and also we to have need some sort of unique
- # identifier that we can use in _getregkey (for jump.py)
-
+ # we want a width of 8 (... I think. Check this!)
_immutable_ = True
-
width = 8
- def __init__(self, address, const_id):
+ def __init__(self, address):
self.value = address
- self.const_id = const_id
def __repr__(self):
- return '<ConstFloatLoc(%s, %s)>' % (self.value, self.const_id)
-
- def _getregkey(self):
- # XXX: 1000 is kind of magic: We just don't want to be confused
- # with any registers
- return 1000 + self.const_id
+ return '<ConstFloatLoc @%s>' % (self.value,)
def location_code(self):
return 'j'
@@ -334,9 +325,9 @@
if code == possible_code:
val = getattr(loc, "value_" + possible_code)()
if possible_code == 'i':
- offset = intmask(val - (self.tell() + 5))
- if rx86.fits_in_32bits(offset):
+ if self.WORD == 4:
_rx86_getattr(self, name + "_l")(val)
+ self.add_pending_relocation()
else:
assert self.WORD == 8
self._load_scratch(val)
Modified: pypy/branch/out-of-line-guards/pypy/jit/backend/x86/runner.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/jit/backend/x86/runner.py (original)
+++ pypy/branch/out-of-line-guards/pypy/jit/backend/x86/runner.py Thu Dec 9 16:33:59 2010
@@ -44,6 +44,7 @@
def setup_once(self):
self.profile_agent.startup()
+ self.assembler.setup_once()
def finish_once(self):
self.assembler.finish_once()
@@ -53,9 +54,12 @@
self.assembler.assemble_loop(inputargs, operations, looptoken,
log=log)
- def compile_bridge(self, faildescr, inputargs, operations, log=True):
+ def compile_bridge(self, faildescr, inputargs, operations,
+ original_loop_token, log=True):
+ clt = original_loop_token.compiled_loop_token
+ clt.compiling_a_bridge()
self.assembler.assemble_bridge(faildescr, inputargs, operations,
- log=log)
+ original_loop_token, log=log)
def set_future_value_int(self, index, intvalue):
self.assembler.fail_boxes_int.setitem(index, intvalue)
@@ -124,8 +128,8 @@
assert fail_index >= 0, "already forced!"
faildescr = self.get_fail_descr_from_number(fail_index)
rffi.cast(TP, addr_of_force_index)[0] = -1
- bytecode = rffi.cast(rffi.UCHARP,
- faildescr._x86_failure_recovery_bytecode)
+ frb = self.assembler._find_failure_recovery_bytecode(faildescr)
+ bytecode = rffi.cast(rffi.UCHARP, frb)
# start of "no gc operation!" block
fail_index_2 = self.assembler.grab_frame_values(
bytecode,
@@ -165,17 +169,12 @@
CPU = CPU386
# silence warnings
-
-history.LoopToken._x86_param_depth = 0
-history.LoopToken._x86_arglocs = (None, None)
-history.LoopToken._x86_frame_depth = 0
-history.LoopToken._x86_bootstrap_code = 0
-history.LoopToken._x86_direct_bootstrap_code = 0
-history.LoopToken._x86_failure_recovery_bytecode = 0
-history.LoopToken._x86_loop_code = 0
-history.LoopToken._x86_current_depths = (0, 0)
-
-compile._DoneWithThisFrameDescr._x86_current_depths = (0, 0)
-compile._DoneWithThisFrameDescr._x86_failure_recovery_bytecode = 0
-compile._DoneWithThisFrameDescr._x86_adr_jump_offset = 0
-
+##history.LoopToken._x86_param_depth = 0
+##history.LoopToken._x86_arglocs = (None, None)
+##history.LoopToken._x86_frame_depth = 0
+##history.LoopToken._x86_bootstrap_code = 0
+##history.LoopToken._x86_direct_bootstrap_code = 0
+##history.LoopToken._x86_loop_code = 0
+##history.LoopToken._x86_debug_checksum = 0
+##compile.AbstractFailDescr._x86_current_depths = (0, 0)
+##compile.AbstractFailDescr._x86_adr_jump_offset = 0
Modified: pypy/branch/out-of-line-guards/pypy/jit/backend/x86/rx86.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/jit/backend/x86/rx86.py (original)
+++ pypy/branch/out-of-line-guards/pypy/jit/backend/x86/rx86.py Thu Dec 9 16:33:59 2010
@@ -137,10 +137,9 @@
# ____________________________________________________________
# Emit an immediate displacement (relative to the cur insn)
-def encode_relative(mc, target, _, orbyte):
+def encode_relative(mc, relative_target, _, orbyte):
assert orbyte == 0
- offset = intmask(target - (mc.tell() + 4))
- mc.writeimm32(offset)
+ mc.writeimm32(relative_target)
return 0
def relative(argnum):
Modified: pypy/branch/out-of-line-guards/pypy/jit/backend/x86/support.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/jit/backend/x86/support.py (original)
+++ pypy/branch/out-of-line-guards/pypy/jit/backend/x86/support.py Thu Dec 9 16:33:59 2010
@@ -1,4 +1,7 @@
+import sys
from pypy.rpython.lltypesystem import lltype, rffi, llmemory
+from pypy.translator.tool.cbuild import ExternalCompilationInfo
+
def values_array(TP, size):
ATP = lltype.GcArray(TP)
@@ -23,3 +26,22 @@
return True
return ValuesArray()
+
+# ____________________________________________________________
+
+memcpy_fn = rffi.llexternal('memcpy', [llmemory.Address, llmemory.Address,
+ rffi.SIZE_T], lltype.Void,
+ sandboxsafe=True, _nowrapper=True)
+
+# ____________________________________________________________
+
+if sys.platform == 'win32':
+ ensure_sse2_floats = lambda : None
+else:
+ _sse2_eci = ExternalCompilationInfo(
+ compile_extra = ['-msse2', '-mfpmath=sse'],
+ separate_module_sources = ['void PYPY_NO_OP(void) {}'],
+ )
+ ensure_sse2_floats = rffi.llexternal('PYPY_NO_OP', [], lltype.Void,
+ compilation_info=_sse2_eci,
+ sandboxsafe=True)
Modified: pypy/branch/out-of-line-guards/pypy/jit/backend/x86/test/test_assembler.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/jit/backend/x86/test/test_assembler.py (original)
+++ pypy/branch/out-of-line-guards/pypy/jit/backend/x86/test/test_assembler.py Thu Dec 9 16:33:59 2010
@@ -1,5 +1,5 @@
from pypy.jit.backend.x86.regloc import *
-from pypy.jit.backend.x86.assembler import Assembler386, MachineCodeBlockWrapper
+from pypy.jit.backend.x86.assembler import Assembler386
from pypy.jit.backend.x86.regalloc import X86FrameManager, get_ebp_ofs
from pypy.jit.metainterp.history import BoxInt, BoxPtr, BoxFloat, INT, REF, FLOAT
from pypy.rlib.rarithmetic import intmask
@@ -19,28 +19,10 @@
return 42
class FakeMC:
- def __init__(self, base_address=0):
+ def __init__(self):
self.content = []
- self._size = 100
- self.base_address = base_address
- def writechr(self, n):
- self.content.append(n)
- def tell(self):
- return self.base_address + len(self.content)
- def get_relative_pos(self):
- return len(self.content)
- def JMP(self, *args):
- self.content.append(("JMP", args))
- def done(self):
- pass
- def PUSH_r(self, reg):
- pass
- def POP_r(self, reg):
- pass
-
-class FakeAssembler:
- def write_pending_failure_recoveries(self):
- pass
+ def writechar(self, char):
+ self.content.append(ord(char))
def test_write_failure_recovery_description():
assembler = Assembler386(FakeCPU())
@@ -255,41 +237,3 @@
assert assembler.fail_boxes_int.getitem(i) == expected_ints[i]
assert assembler.fail_boxes_ptr.getitem(i) == expected_ptrs[i]
assert assembler.fail_boxes_float.getitem(i) == expected_floats[i]
-
-class FakeProfileAgent(object):
- def __init__(self):
- self.functions = []
-
- def native_code_written(self, name, address, size):
- self.functions.append((name, address, size))
-
-class FakeMCWrapper(MachineCodeBlockWrapper):
- count = 0
- def _instantiate_mc(self):
- self.count += 1
- return FakeMC(200 * (self.count - 1))
-
-def test_mc_wrapper_profile_agent():
- agent = FakeProfileAgent()
- assembler = FakeAssembler()
- mc = FakeMCWrapper(assembler, 100, agent)
- mc.start_function("abc")
- mc.writechr("x")
- mc.writechr("x")
- mc.writechr("x")
- mc.writechr("x")
- mc.end_function()
- assert agent.functions == [("abc", 0, 4)]
- mc.writechr("x")
- mc.start_function("cde")
- mc.writechr("x")
- mc.writechr("x")
- mc.writechr("x")
- mc.writechr("x")
- mc.end_function()
- assert agent.functions == [("abc", 0, 4), ("cde", 5, 4)]
- mc.start_function("xyz")
- for i in range(50):
- mc.writechr("x")
- mc.end_function()
- assert agent.functions == [("abc", 0, 4), ("cde", 5, 4), ("xyz", 9, 29), ("xyz", 200, 22)]
Modified: pypy/branch/out-of-line-guards/pypy/jit/backend/x86/test/test_gc_integration.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/jit/backend/x86/test/test_gc_integration.py (original)
+++ pypy/branch/out-of-line-guards/pypy/jit/backend/x86/test/test_gc_integration.py Thu Dec 9 16:33:59 2010
@@ -33,7 +33,8 @@
def add_callee_save_reg(self, shape, reg_index):
index_to_name = { 1: 'ebx', 2: 'esi', 3: 'edi' }
shape.append(index_to_name[reg_index])
- def compress_callshape(self, shape):
+ def compress_callshape(self, shape, datablockwrapper):
+ assert datablockwrapper == 'fakedatablockwrapper'
assert shape[0] == 'shape'
return ['compressed'] + shape[1:]
@@ -58,7 +59,9 @@
def test_mark_gc_roots(self):
cpu = CPU(None, None)
+ cpu.setup_once()
regalloc = RegAlloc(MockAssembler(cpu, MockGcDescr(False)))
+ regalloc.assembler.datablockwrapper = 'fakedatablockwrapper'
boxes = [BoxPtr() for i in range(len(X86RegisterManager.all_regs))]
longevity = {}
for box in boxes:
@@ -90,6 +93,7 @@
cpu = CPU(None, None)
cpu.gc_ll_descr = MockGcDescr(False)
+ cpu.setup_once()
S = lltype.GcForwardReference()
S.become(lltype.GcStruct('S', ('field', lltype.Ptr(S)),
@@ -214,6 +218,7 @@
cpu = CPU(None, None)
cpu.vtable_offset = WORD
cpu.gc_ll_descr = GCDescrFastpathMalloc()
+ cpu.setup_once()
NODE = lltype.Struct('node', ('tid', lltype.Signed),
('value', lltype.Signed))
Modified: pypy/branch/out-of-line-guards/pypy/jit/backend/x86/test/test_regalloc.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/jit/backend/x86/test/test_regalloc.py (original)
+++ pypy/branch/out-of-line-guards/pypy/jit/backend/x86/test/test_regalloc.py Thu Dec 9 16:33:59 2010
@@ -9,7 +9,7 @@
from pypy.jit.backend.llsupport.descr import GcCache
from pypy.jit.backend.detect_cpu import getcpuclass
from pypy.jit.backend.x86.regalloc import RegAlloc, X86RegisterManager,\
- FloatConstants, is_comparison_or_ovf_op
+ is_comparison_or_ovf_op
from pypy.jit.backend.x86.arch import IS_X86_32, IS_X86_64
from pypy.jit.tool.oparser import parse
from pypy.rpython.lltypesystem import lltype, llmemory, rffi
@@ -41,7 +41,10 @@
self.movs = []
self.performs = []
self.lea = []
- self.cpu = cpu or CPU(None, None)
+ if cpu is None:
+ cpu = CPU(None, None)
+ cpu.setup_once()
+ self.cpu = cpu
if gc_ll_descr is None:
gc_ll_descr = MockGcDescr(False)
self.cpu.gc_ll_descr = gc_ll_descr
@@ -76,6 +79,7 @@
class BaseTestRegalloc(object):
cpu = CPU(None, None)
+ cpu.setup_once()
def raising_func(i):
if i:
@@ -166,7 +170,8 @@
assert ([box.type for box in bridge.inputargs] ==
[box.type for box in guard_op.getfailargs()])
faildescr = guard_op.getdescr()
- self.cpu.compile_bridge(faildescr, bridge.inputargs, bridge.operations)
+ self.cpu.compile_bridge(faildescr, bridge.inputargs, bridge.operations,
+ loop.token)
return bridge
def run(self, loop):
@@ -515,16 +520,6 @@
self.interpret(ops, [0.1, .2, .3, .4, .5, .6, .7, .8, .9])
assert self.getfloats(9) == [.1+.2, .9+3.5, .3, .4, .5, .6, .7, .8, .9]
- def test_float_overflow_const_list(self):
- ops = ['[f0]']
- BASE_CONSTANT_SIZE = FloatConstants.BASE_CONSTANT_SIZE
- for i in range(BASE_CONSTANT_SIZE * 2):
- ops.append('f%d = float_add(f%d, 3.5)' % (i + 1, i))
- ops.append('finish(f%d)' % (BASE_CONSTANT_SIZE * 2))
- ops = "\n".join(ops)
- self.interpret(ops, [0.1])
- assert abs(self.getfloat(0) - (BASE_CONSTANT_SIZE * 2) * 3.5 - 0.1) < 0.00001
-
def test_lt_const(self):
ops = '''
[f0]
Modified: pypy/branch/out-of-line-guards/pypy/jit/backend/x86/test/test_regalloc2.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/jit/backend/x86/test/test_regalloc2.py (original)
+++ pypy/branch/out-of-line-guards/pypy/jit/backend/x86/test/test_regalloc2.py Thu Dec 9 16:33:59 2010
@@ -19,6 +19,7 @@
ResOperation(rop.FINISH, [v4, v3], None, descr=BasicFailDescr()),
]
cpu = CPU(None, None)
+ cpu.setup_once()
looptoken = LoopToken()
cpu.compile_loop(inputargs, operations, looptoken)
cpu.set_future_value_int(0, 9)
@@ -41,6 +42,7 @@
ResOperation(rop.FINISH, [v4, v3, tmp5], None, descr=BasicFailDescr()),
]
cpu = CPU(None, None)
+ cpu.setup_once()
looptoken = LoopToken()
cpu.compile_loop(inputargs, operations, looptoken)
cpu.set_future_value_int(0, -10)
@@ -137,6 +139,7 @@
ResOperation(rop.FINISH, [v40, v36, v37, v31, v16, v34, v35, v23, v22, v29, v14, v39, v30, v38], None, descr=BasicFailDescr()),
]
cpu = CPU(None, None)
+ cpu.setup_once()
looptoken = LoopToken()
cpu.compile_loop(inputargs, operations, looptoken)
cpu.set_future_value_int(0, -13)
@@ -251,6 +254,7 @@
ResOperation(rop.FINISH, [v40, v10, v36, v26, v13, v30, v21, v33, v18, v25, v31, v32, v28, v29, v35, v38, v20, v39, v34, v23, v37], None, descr=BasicFailDescr()),
]
cpu = CPU(None, None)
+ cpu.setup_once()
looptoken = LoopToken()
cpu.compile_loop(inputargs, operations, looptoken)
cpu.set_future_value_int(0, 17)
Modified: pypy/branch/out-of-line-guards/pypy/jit/backend/x86/test/test_regloc.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/jit/backend/x86/test/test_regloc.py (original)
+++ pypy/branch/out-of-line-guards/pypy/jit/backend/x86/test/test_regloc.py Thu Dec 9 16:33:59 2010
@@ -1,4 +1,4 @@
-import struct
+import struct, sys
from pypy.jit.backend.x86.regloc import *
from pypy.jit.backend.x86.test.test_rx86 import CodeBuilder32, CodeBuilder64, assert_encodes_as
from pypy.jit.backend.x86.assembler import heap
@@ -37,26 +37,36 @@
assert_encodes_as(cb64, "CMP16", (ecx, ImmedLoc(12345)), '\x66\x81\xF9\x39\x30')
assert_encodes_as(cb64, "CMP16", (AddressLoc(r13, ImmedLoc(0), 0, 0), ImmedLoc(12345)), '\x66\x41\x81\x7D\x00\x39\x30')
-def test_jmp_wraparound():
- if not IS_X86_32:
- py.test.skip()
-
- pos_addr = intmask(0x7FFFFF00)
- neg_addr = intmask(0x800000BB)
-
- # JMP to "negative" address from "positive" address
- s = cb32()
- s.base_address = pos_addr
- s.JMP(ImmedLoc(neg_addr))
- expected_ofs = neg_addr - (pos_addr+5)
- assert s.getvalue() == '\xE9' + struct.pack("<i", expected_ofs)
-
- # JMP to a "positive" address from a "negative" address
- s = cb32()
- s.base_address = neg_addr
- s.JMP(ImmedLoc(pos_addr))
- expected_ofs = pos_addr - (neg_addr+5)
- assert s.getvalue() == '\xE9' + struct.pack("<i", expected_ofs)
+def test_relocation():
+ from pypy.rpython.lltypesystem import lltype, rffi
+ from pypy.jit.backend.x86 import codebuf
+ for target in [0x01020304, 0x0102030405060708]:
+ if target > sys.maxint:
+ continue
+ mc = codebuf.MachineCodeBlockWrapper()
+ mc.CALL(ImmedLoc(target))
+ length = mc.get_relative_pos()
+ buf = lltype.malloc(rffi.CCHARP.TO, length, flavor='raw')
+ rawstart = rffi.cast(lltype.Signed, buf)
+ if IS_X86_32:
+ assert length == 5
+ assert mc.relocations == [5]
+ expected = "\xE8" + struct.pack('<i', target - (rawstart + 5))
+ elif IS_X86_64:
+ assert mc.relocations == []
+ if target <= 0x7fffffff:
+ assert length == 10
+ expected = (
+ "\x49\xC7\xC3\x04\x03\x02\x01" # MOV %r11, target
+ "\x41\xFF\xD3") # CALL *%r11
+ else:
+ assert length == 13
+ expected = (
+ "\x49\xBB\x08\x07\x06\x05\x04\x03\x02\x01" # MOV %r11, targ
+ "\x41\xFF\xD3") # CALL *%r11
+ mc.copy_to_raw_memory(rawstart)
+ assert ''.join([buf[i] for i in range(length)]) == expected
+ lltype.free(buf, flavor='raw')
class Test64Bits:
Modified: pypy/branch/out-of-line-guards/pypy/jit/backend/x86/test/test_runner.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/jit/backend/x86/test/test_runner.py (original)
+++ pypy/branch/out-of-line-guards/pypy/jit/backend/x86/test/test_runner.py Thu Dec 9 16:33:59 2010
@@ -33,6 +33,7 @@
def setup_method(self, meth):
self.cpu = CPU(rtyper=None, stats=FakeStats())
+ self.cpu.setup_once()
def test_execute_ptr_operation(self):
cpu = self.cpu
@@ -81,7 +82,7 @@
# relative addressing to work properly.
addr = rffi.cast(lltype.Signed, addr)
- self.cpu.assembler.setup()
+ self.cpu.assembler.setup_once()
self.cpu.assembler.malloc_func_addr = addr
ofs = symbolic.get_field_token(rstr.STR, 'chars', False)[0]
@@ -329,7 +330,11 @@
assert result != expected
def test_compile_bridge_check_profile_info(self):
- from pypy.jit.backend.x86.test.test_assembler import FakeProfileAgent
+ class FakeProfileAgent(object):
+ def __init__(self):
+ self.functions = []
+ def native_code_written(self, name, address, size):
+ self.functions.append((name, address, size))
self.cpu.profile_agent = agent = FakeProfileAgent()
i0 = BoxInt()
@@ -338,6 +343,7 @@
faildescr1 = BasicFailDescr(1)
faildescr2 = BasicFailDescr(2)
looptoken = LoopToken()
+ looptoken.number = 17
class FakeString(object):
def __init__(self, val):
self.val = val
@@ -356,7 +362,7 @@
operations[3].setfailargs([i1])
self.cpu.compile_loop(inputargs, operations, looptoken)
name, loopaddress, loopsize = agent.functions[0]
- assert name == "Loop # 0: hello"
+ assert name == "Loop # 17: hello"
assert loopaddress <= looptoken._x86_loop_code
assert loopsize >= 40 # randomish number
@@ -370,7 +376,7 @@
]
bridge[1].setfailargs([i1b])
- self.cpu.compile_bridge(faildescr1, [i1b], bridge)
+ self.cpu.compile_bridge(faildescr1, [i1b], bridge, looptoken)
name, address, size = agent.functions[1]
assert name == "Bridge # 0: bye"
# Would be exactly ==, but there are some guard failure recovery
@@ -397,104 +403,15 @@
assert res.value == 4.0
-class TestX86OverflowMC(TestX86):
-
- def setup_method(self, meth):
- self.cpu = CPU(rtyper=None, stats=FakeStats())
- self.cpu.assembler.mc_size = 1024
-
- def test_overflow_mc(self):
- ops = []
- base_v = BoxInt()
- v = base_v
- for i in range(1024):
- next_v = BoxInt()
- ops.append(ResOperation(rop.INT_ADD, [v, ConstInt(1)], next_v))
- v = next_v
- ops.append(ResOperation(rop.FINISH, [v], None,
- descr=BasicFailDescr()))
- looptoken = LoopToken()
- self.cpu.assembler.setup()
- old_mc_mc = self.cpu.assembler.mc._mc
- self.cpu.compile_loop([base_v], ops, looptoken)
- assert self.cpu.assembler.mc._mc != old_mc_mc # overflowed
- self.cpu.set_future_value_int(0, base_v.value)
- self.cpu.execute_token(looptoken)
- assert self.cpu.get_latest_value_int(0) == 1024
-
- def test_overflow_guard_float_cmp(self):
- # The float comparisons on x86 tend to use small relative jumps,
- # which may run into trouble if they fall on the edge of a
- # MachineCodeBlock change.
- a = BoxFloat(1.0)
- b = BoxFloat(2.0)
- failed = BoxInt(41)
- finished = BoxInt(42)
-
- # We select guards that will always succeed, so that execution will
- # continue through the entire set of comparisions
- ops_to_test = (
- (rop.FLOAT_LT, [a, b], rop.GUARD_TRUE),
- (rop.FLOAT_LT, [b, a], rop.GUARD_FALSE),
-
- (rop.FLOAT_LE, [a, a], rop.GUARD_TRUE),
- (rop.FLOAT_LE, [a, b], rop.GUARD_TRUE),
- (rop.FLOAT_LE, [b, a], rop.GUARD_FALSE),
-
- (rop.FLOAT_EQ, [a, a], rop.GUARD_TRUE),
- (rop.FLOAT_EQ, [a, b], rop.GUARD_FALSE),
-
- (rop.FLOAT_NE, [a, b], rop.GUARD_TRUE),
- (rop.FLOAT_NE, [a, a], rop.GUARD_FALSE),
-
- (rop.FLOAT_GT, [b, a], rop.GUARD_TRUE),
- (rop.FLOAT_GT, [a, b], rop.GUARD_FALSE),
-
- (rop.FLOAT_GE, [a, a], rop.GUARD_TRUE),
- (rop.FLOAT_GE, [b, a], rop.GUARD_TRUE),
- (rop.FLOAT_GE, [a, b], rop.GUARD_FALSE),
- )
-
- for float_op, args, guard_op in ops_to_test:
- ops = []
-
- for i in range(200):
- cmp_result = BoxInt()
- ops.append(ResOperation(float_op, args, cmp_result))
- ops.append(ResOperation(guard_op, [cmp_result], None, descr=BasicFailDescr()))
- ops[-1].setfailargs([failed])
-
- ops.append(ResOperation(rop.FINISH, [finished], None, descr=BasicFailDescr()))
-
- looptoken = LoopToken()
- self.cpu.compile_loop([a, b, failed, finished], ops, looptoken)
- self.cpu.set_future_value_float(0, a.value)
- self.cpu.set_future_value_float(1, b.value)
- self.cpu.set_future_value_int(2, failed.value)
- self.cpu.set_future_value_int(3, finished.value)
- self.cpu.execute_token(looptoken)
-
- # Really just a sanity check. We're actually interested in
- # whether the test segfaults.
- assert self.cpu.get_latest_value_int(0) == finished.value
-
- def test_overflow_guard_exception(self):
- for i in range(50):
- self.test_exceptions()
-
-
class TestDebuggingAssembler(object):
def setup_method(self, meth):
- self.pypylog = os.environ.get('PYPYLOG', None)
- self.logfile = str(udir.join('x86_runner.log'))
- os.environ['PYPYLOG'] = "mumble:" + self.logfile
self.cpu = CPU(rtyper=None, stats=FakeStats())
-
- def teardown_method(self, meth):
- if self.pypylog is not None:
- os.environ['PYPYLOG'] = self.pypylog
+ self.cpu.setup_once()
def test_debugger_on(self):
+ from pypy.tool.logparser import parse_log_file, extract_category
+ from pypy.rlib import debug
+
loop = """
[i0]
debug_merge_point('xyz', 0)
@@ -504,17 +421,19 @@
jump(i1)
"""
ops = parse(loop)
- self.cpu.assembler.set_debug(True)
- self.cpu.compile_loop(ops.inputargs, ops.operations, ops.token)
- self.cpu.set_future_value_int(0, 0)
- self.cpu.execute_token(ops.token)
- # check debugging info
- name, struct = self.cpu.assembler.loop_run_counters[0]
- assert name == 0 # 'xyz'
- assert struct.i == 10
- self.cpu.finish_once()
- lines = py.path.local(self.logfile + ".count").readlines()
- assert lines[0] == '0:10\n' # '10 xyz\n'
+ debug._log = dlog = debug.DebugLog()
+ try:
+ self.cpu.assembler.set_debug(True)
+ self.cpu.compile_loop(ops.inputargs, ops.operations, ops.token)
+ self.cpu.set_future_value_int(0, 0)
+ self.cpu.execute_token(ops.token)
+ # check debugging info
+ struct = self.cpu.assembler.loop_run_counters[0]
+ assert struct.i == 10
+ self.cpu.finish_once()
+ finally:
+ debug._log = None
+ assert ('jit-backend-counts', [('debug_print', '0:10')]) in dlog
def test_debugger_checksum(self):
loop = """
Modified: pypy/branch/out-of-line-guards/pypy/jit/backend/x86/test/test_rx86.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/jit/backend/x86/test/test_rx86.py (original)
+++ pypy/branch/out-of-line-guards/pypy/jit/backend/x86/test/test_rx86.py Thu Dec 9 16:33:59 2010
@@ -5,7 +5,6 @@
class CodeBuilderMixin(object):
def __init__(self):
self.buffer = []
- self.base_address = 0x76543210
def writechar(self, c):
assert isinstance(c, str) and len(c) == 1
@@ -14,9 +13,6 @@
def getvalue(self):
return ''.join(self.buffer)
- def tell(self):
- return self.base_address + len(self.buffer)
-
def assert_encodes_as(code_builder_cls, insn_name, args, expected_encoding):
s = code_builder_cls()
getattr(s, insn_name)(*args)
@@ -104,21 +100,18 @@
def test_call_l(s=None):
s = s or CodeBuilder32()
- s.CALL_l(0x01234567)
- ofs = 0x01234567 - (0x76543210+5)
- assert s.getvalue() == '\xE8' + struct.pack("<i", ofs)
+ s.CALL_l(0x01234567) # relative offset
+ assert s.getvalue() == '\xE8' + struct.pack("<i", 0x01234567)
def test_jmp_l():
s = CodeBuilder32()
- s.JMP_l(0x01234567)
- ofs = 0x01234567 - (0x76543210+5)
- assert s.getvalue() == '\xE9' + struct.pack("<i", ofs)
+ s.JMP_l(0x01234567) # relative offset
+ assert s.getvalue() == '\xE9' + struct.pack("<i", 0x01234567)
def test_j_il():
s = CodeBuilder32()
- s.J_il(5, 0x01234567)
- ofs = 0x01234567 - (0x76543210+6)
- assert s.getvalue() == '\x0F\x85' + struct.pack("<i", ofs)
+ s.J_il(5, 0x01234567) # relative offset
+ assert s.getvalue() == '\x0F\x85' + struct.pack("<i", 0x01234567)
def test_set_ir():
s = CodeBuilder32()
Modified: pypy/branch/out-of-line-guards/pypy/jit/backend/x86/test/test_zll_random.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/jit/backend/x86/test/test_zll_random.py (original)
+++ pypy/branch/out-of-line-guards/pypy/jit/backend/x86/test/test_zll_random.py Thu Dec 9 16:33:59 2010
@@ -6,9 +6,7 @@
def test_stress():
cpu = CPU(None, None)
+ cpu.setup_once()
r = Random()
for i in range(1000):
check_random_function(cpu, LLtypeOperationBuilder, r, i, 1000)
-
-
-
Modified: pypy/branch/out-of-line-guards/pypy/jit/backend/x86/test/test_zmath.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/jit/backend/x86/test/test_zmath.py (original)
+++ pypy/branch/out-of-line-guards/pypy/jit/backend/x86/test/test_zmath.py Thu Dec 9 16:33:59 2010
@@ -4,7 +4,7 @@
import py, math
from pypy.module.math.test import test_direct
from pypy.translator.c.test.test_genc import compile
-from pypy.jit.backend.x86.codebuf import ensure_sse2_floats
+from pypy.jit.backend.x86.support import ensure_sse2_floats
def get_test_case((fnname, args, expected)):
Modified: pypy/branch/out-of-line-guards/pypy/jit/backend/x86/valgrind.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/jit/backend/x86/valgrind.py (original)
+++ pypy/branch/out-of-line-guards/pypy/jit/backend/x86/valgrind.py Thu Dec 9 16:33:59 2010
@@ -27,4 +27,4 @@
def discard_translations(data, size):
if we_are_translated() and VALGRIND_DISCARD_TRANSLATIONS is not None:
- VALGRIND_DISCARD_TRANSLATIONS(llmemory.cast_ptr_to_adr(data), size)
+ VALGRIND_DISCARD_TRANSLATIONS(llmemory.cast_int_to_adr(data), size)
Modified: pypy/branch/out-of-line-guards/pypy/jit/codewriter/call.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/jit/codewriter/call.py (original)
+++ pypy/branch/out-of-line-guards/pypy/jit/codewriter/call.py Thu Dec 9 16:33:59 2010
@@ -95,15 +95,8 @@
else:
v_obj = op.args[1].concretetype
graphs = v_obj._lookup_graphs(op.args[0].value)
- if graphs is not None:
- result = []
- for graph in graphs:
- if is_candidate(graph):
- result.append(graph)
- if result:
- return result # common case: look inside these graphs,
- # and ignore the others if there are any
- else:
+ #
+ if graphs is None:
# special case: handle the indirect call that goes to
# the 'instantiate' methods. This check is a bit imprecise
# but it's not too bad if we mistake a random indirect call
@@ -112,7 +105,16 @@
CALLTYPE = op.args[0].concretetype
if (op.opname == 'indirect_call' and len(op.args) == 2 and
CALLTYPE == rclass.OBJECT_VTABLE.instantiate):
- return list(self._graphs_of_all_instantiate())
+ graphs = list(self._graphs_of_all_instantiate())
+ #
+ if graphs is not None:
+ result = []
+ for graph in graphs:
+ if is_candidate(graph):
+ result.append(graph)
+ if result:
+ return result # common case: look inside these graphs,
+ # and ignore the others if there are any
# residual call case: we don't need to look into any graph
return None
Modified: pypy/branch/out-of-line-guards/pypy/jit/codewriter/jtransform.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/jit/codewriter/jtransform.py (original)
+++ pypy/branch/out-of-line-guards/pypy/jit/codewriter/jtransform.py Thu Dec 9 16:33:59 2010
@@ -26,6 +26,7 @@
class Transformer(object):
+ vable_array_vars = None
def __init__(self, cpu=None, callcontrol=None, portal_jd=None):
self.cpu = cpu
@@ -40,7 +41,6 @@
def optimize_block(self, block):
if block.operations == ():
return
- self.immutable_arrays = {}
self.vable_array_vars = {}
self.vable_flags = {}
renamings = {}
@@ -85,6 +85,7 @@
self.follow_constant_exit(block)
self.optimize_goto_if_not(block)
for link in block.exits:
+ self._check_no_vable_array(link.args)
self._do_renaming_on_link(renamings, link)
def _do_renaming(self, rename, op):
@@ -102,6 +103,28 @@
op.args[i] = ListOfKind(v.kind, newlst)
return op
+ def _check_no_vable_array(self, list):
+ if not self.vable_array_vars:
+ return
+ for v in list:
+ if v in self.vable_array_vars:
+ raise AssertionError(
+ "A virtualizable array is passed around; it should\n"
+ "only be used immediately after being read. Note\n"
+ "that a possible cause is indexing with an index not\n"
+ "known non-negative, or catching IndexError, or\n"
+ "not inlining at all (for tests: use listops=True).\n"
+ "Occurred in: %r" % self.graph)
+ # extra expanation: with the way things are organized in
+ # rpython/rlist.py, the ll_getitem becomes a function call
+ # that is typically meant to be inlined by the JIT, but
+ # this does not work with vable arrays because
+ # jtransform.py expects the getfield and the getarrayitem
+ # to be in the same basic block. It works a bit as a hack
+ # for simple cases where we performed the backendopt
+ # inlining before (even with a very low threshold, because
+ # there is _always_inline_ on the relevant functions).
+
def _do_renaming_on_link(self, rename, link):
for i, v in enumerate(link.args):
if isinstance(v, Variable):
@@ -172,9 +195,12 @@
else:
return rewrite(self, op)
- def rewrite_op_same_as(self, op): pass
- def rewrite_op_cast_pointer(self, op): pass
- def rewrite_op_cast_opaque_ptr(self, op): pass # rlib.rerased
+ def rewrite_op_same_as(self, op):
+ if op.args[0] in self.vable_array_vars:
+ self.vable_array_vars[op.result]= self.vable_array_vars[op.args[0]]
+
+ rewrite_op_cast_pointer = rewrite_op_same_as
+ rewrite_op_cast_opaque_ptr = rewrite_op_same_as # rlib.rerased
def rewrite_op_cast_primitive(self, op): pass
def rewrite_op_cast_bool_to_int(self, op): pass
def rewrite_op_cast_bool_to_uint(self, op): pass
@@ -259,6 +285,7 @@
The name is one of '{residual,direct}_call_{r,ir,irf}_{i,r,f,v}'."""
if args is None:
args = op.args[1:]
+ self._check_no_vable_array(args)
lst_i, lst_r, lst_f = self.make_three_lists(args)
reskind = getkind(op.result.concretetype)[0]
if lst_f or reskind == 'f': kinds = 'irf'
@@ -400,6 +427,7 @@
rewrite_op_int_lshift_ovf = _do_builtin_call
rewrite_op_int_abs = _do_builtin_call
rewrite_op_gc_identityhash = _do_builtin_call
+ rewrite_op_gc_id = _do_builtin_call
# ----------
# getfield/setfield/mallocs etc.
@@ -526,17 +554,14 @@
arrayfielddescr,
arraydescr)
return []
- # check for deepfrozen structures that force constant-folding
- immut = v_inst.concretetype.TO._immutable_field(c_fieldname.value)
- if immut:
+ # check for _immutable_fields_ hints
+ if v_inst.concretetype.TO._immutable_field(c_fieldname.value):
if (self.callcontrol is not None and
self.callcontrol.could_be_green_field(v_inst.concretetype.TO,
c_fieldname.value)):
pure = '_greenfield'
else:
pure = '_pure'
- if immut == "[*]":
- self.immutable_arrays[op.result] = True
else:
jit_inv = v_inst.concretetype.TO._hints.get('jit_invariant_fields')
if jit_inv and op.args[1].value in jit_inv.fields:
@@ -853,9 +878,16 @@
"general mix-up of jitdrivers?")
ops = self.promote_greens(op.args[2:], jitdriver)
num_green_args = len(jitdriver.greens)
+ redlists = self.make_three_lists(op.args[2+num_green_args:])
+ for redlist in redlists:
+ for v in redlist:
+ assert isinstance(v, Variable), (
+ "Constant specified red in jit_merge_point()")
+ assert len(dict.fromkeys(redlist)) == len(list(redlist)), (
+ "duplicate red variable on jit_merge_point()")
args = ([Constant(self.portal_jd.index, lltype.Signed)] +
self.make_three_lists(op.args[2:2+num_green_args]) +
- self.make_three_lists(op.args[2+num_green_args:]))
+ redlists)
op1 = SpaceOperation('jit_merge_point', args, None)
op2 = SpaceOperation('-live-', [], None)
# ^^^ we need a -live- for the case of do_recursive_call()
@@ -934,21 +966,19 @@
# base hints on the name of the ll function, which is a bit xxx-ish
# but which is safe for now
assert func.func_name.startswith('ll_')
+ # check that we have carefully placed the oopspec in
+ # pypy/rpython/rlist.py. There should not be an oopspec on
+ # a ll_getitem or ll_setitem that expects a 'func' argument.
+ # The idea is that a ll_getitem/ll_setitem with dum_checkidx
+ # should get inlined by the JIT, so that we see the potential
+ # 'raise IndexError'.
+ assert 'func' not in func.func_code.co_varnames
non_negative = '_nonneg' in func.func_name
fast = '_fast' in func.func_name
- if fast:
- can_raise = False
- non_negative = True
- else:
- tag = op.args[1].value
- assert tag in (rlist.dum_nocheck, rlist.dum_checkidx)
- can_raise = tag != rlist.dum_nocheck
- return non_negative, can_raise
+ return non_negative or fast
def _prepare_list_getset(self, op, descr, args, checkname):
- non_negative, can_raise = self._get_list_nonneg_canraise_flags(op)
- if can_raise:
- raise NotSupported("list operation can raise")
+ non_negative = self._get_list_nonneg_canraise_flags(op)
if non_negative:
return args[1], []
else:
@@ -960,9 +990,8 @@
return v_posindex, [op0, op1]
def _prepare_void_list_getset(self, op):
- non_negative, can_raise = self._get_list_nonneg_canraise_flags(op)
- if can_raise:
- raise NotSupported("list operation can raise")
+ # sanity check:
+ self._get_list_nonneg_canraise_flags(op)
def _get_initial_newlist_length(self, op, args):
# normalize number of arguments to the 'newlist' function
@@ -1007,7 +1036,7 @@
v_index, extraop = self._prepare_list_getset(op, arraydescr, args,
'check_neg_index')
extra = getkind(op.result.concretetype)[0]
- if pure or args[0] in self.immutable_arrays:
+ if pure:
extra = 'pure_' + extra
op = SpaceOperation('getarrayitem_gc_%s' % extra,
[args[0], arraydescr, v_index], op.result)
Modified: pypy/branch/out-of-line-guards/pypy/jit/codewriter/regalloc.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/jit/codewriter/regalloc.py (original)
+++ pypy/branch/out-of-line-guards/pypy/jit/codewriter/regalloc.py Thu Dec 9 16:33:59 2010
@@ -36,7 +36,7 @@
if isinstance(v1, Variable):
die_at[v1] = i
if op.result is not None:
- die_at[op.result] = i
+ die_at[op.result] = i + 1
if isinstance(block.exitswitch, tuple):
for x in block.exitswitch:
die_at.pop(x, None)
Modified: pypy/branch/out-of-line-guards/pypy/jit/codewriter/support.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/jit/codewriter/support.py (original)
+++ pypy/branch/out-of-line-guards/pypy/jit/codewriter/support.py Thu Dec 9 16:33:59 2010
@@ -168,6 +168,9 @@
def _ll_1_gc_identityhash(x):
return lltype.identityhash(x)
+def _ll_1_gc_id(ptr):
+ return llop.gc_id(lltype.Signed, ptr)
+
def _ll_1_jit_force_virtual(inst):
return llop.jit_force_virtual(lltype.typeOf(inst), inst)
@@ -548,6 +551,9 @@
def get_identityhash_oopspec(op):
return 'gc_identityhash', op.args
+def get_gcid_oopspec(op):
+ return 'gc_id', op.args
+
RENAMED_ADT_NAME = {
'list': {
@@ -578,6 +584,8 @@
return get_oostring_oopspec(op)
elif op.opname == 'gc_identityhash':
return get_identityhash_oopspec(op)
+ elif op.opname == 'gc_id':
+ return get_gcid_oopspec(op)
else:
raise ValueError(op.opname)
Modified: pypy/branch/out-of-line-guards/pypy/jit/codewriter/test/test_codewriter.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/jit/codewriter/test/test_codewriter.py (original)
+++ pypy/branch/out-of-line-guards/pypy/jit/codewriter/test/test_codewriter.py Thu Dec 9 16:33:59 2010
@@ -152,6 +152,42 @@
assert 'B2' in names
assert 'dont_look' in names
+def test_instantiate_with_unreasonable_attr():
+ # It is possible to have in real code the instantiate() function for
+ # a class be dont-look-inside. This is caused by the code that
+ # initialize the instance attributes: if one attribute has a strange
+ # type, the whole function is disabled. Check that it still works.
+ class MyFakePolicy:
+ def look_inside_graph(self, graph):
+ name = graph.name
+ return not (name.startswith('instantiate_') and
+ name.endswith('A2'))
+ class A1:
+ pass
+ class A2(A1):
+ pass
+ def f(n):
+ if n > 5:
+ x = A1
+ else:
+ x = A2
+ x()
+ rtyper = support.annotate(f, [35])
+ maingraph = rtyper.annotator.translator.graphs[0]
+ cw = CodeWriter(FakeCPU(rtyper), [FakeJitDriverSD(maingraph)])
+ cw.find_all_graphs(MyFakePolicy())
+ cw.make_jitcodes(verbose=True)
+ #
+ names = [jitcode.name for jitcode in cw.assembler.indirectcalltargets]
+ assert len(names) == 1
+ assert names[0].startswith('instantiate_') and names[0].endswith('A1')
+ #
+ print cw.assembler.list_of_addr2name
+ names = dict.fromkeys([value
+ for key, value in cw.assembler.list_of_addr2name])
+ assert 'A1' in names
+ assert 'A2' in names
+
def test_int_abs():
def f(n):
return abs(n)
Modified: pypy/branch/out-of-line-guards/pypy/jit/codewriter/test/test_list.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/jit/codewriter/test/test_list.py (original)
+++ pypy/branch/out-of-line-guards/pypy/jit/codewriter/test/test_list.py Thu Dec 9 16:33:59 2010
@@ -56,9 +56,8 @@
if '/' in oopspec_name:
oopspec_name, property = oopspec_name.split('/')
def force_flags(op):
- if property == 'NONNEG': return True, False
- if property == 'NEG': return False, False
- if property == 'CANRAISE': return False, True
+ if property == 'NONNEG': return True
+ if property == 'NEG': return False
raise ValueError(property)
tr._get_list_nonneg_canraise_flags = force_flags
op = SpaceOperation('direct_call',
@@ -122,9 +121,6 @@
check_neg_index %r0, <ArrayDescr>, %i0 -> %i1
getarrayitem_gc_i %r0, <ArrayDescr>, %i1 -> %i2
""")
- builtin_test('list.getitem/CANRAISE',
- [varoftype(FIXEDLIST), varoftype(lltype.Signed)],
- lltype.Signed, NotSupported)
def test_fixed_getitem_foldable():
builtin_test('list.getitem_foldable/NONNEG',
@@ -139,9 +135,6 @@
check_neg_index %r0, <ArrayDescr>, %i0 -> %i1
getarrayitem_gc_pure_i %r0, <ArrayDescr>, %i1 -> %i2
""")
- builtin_test('list.getitem_foldable/CANRAISE',
- [varoftype(FIXEDLIST), varoftype(lltype.Signed)],
- lltype.Signed, NotSupported)
def test_fixed_setitem():
builtin_test('list.setitem/NONNEG', [varoftype(FIXEDLIST),
@@ -158,10 +151,6 @@
check_neg_index %r0, <ArrayDescr>, %i0 -> %i1
setarrayitem_gc_i %r0, <ArrayDescr>, %i1, %i2
""")
- builtin_test('list.setitem/CANRAISE', [varoftype(FIXEDLIST),
- varoftype(lltype.Signed),
- varoftype(lltype.Signed)],
- lltype.Void, NotSupported)
def test_fixed_len():
builtin_test('list.len', [varoftype(FIXEDLIST)], lltype.Signed,
@@ -206,9 +195,6 @@
check_resizable_neg_index %r0, <FieldDescr length>, %i0 -> %i1
getlistitem_gc_i %r0, <FieldDescr items>, <ArrayDescr>, %i1 -> %i2
""")
- builtin_test('list.getitem/CANRAISE',
- [varoftype(VARLIST), varoftype(lltype.Signed)],
- lltype.Signed, NotSupported)
def test_resizable_setitem():
builtin_test('list.setitem/NONNEG', [varoftype(VARLIST),
@@ -225,10 +211,6 @@
check_resizable_neg_index %r0, <FieldDescr length>, %i0 -> %i1
setlistitem_gc_i %r0, <FieldDescr items>, <ArrayDescr>, %i1, %i2
""")
- builtin_test('list.setitem/CANRAISE', [varoftype(VARLIST),
- varoftype(lltype.Signed),
- varoftype(lltype.Signed)],
- lltype.Void, NotSupported)
def test_resizable_len():
builtin_test('list.len', [varoftype(VARLIST)], lltype.Signed,
Modified: pypy/branch/out-of-line-guards/pypy/jit/codewriter/test/test_regalloc.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/jit/codewriter/test/test_regalloc.py (original)
+++ pypy/branch/out-of-line-guards/pypy/jit/codewriter/test/test_regalloc.py Thu Dec 9 16:33:59 2010
@@ -281,22 +281,22 @@
# this used to produce bogus code, containing these two
# lines in the following broken order:
# last_exc_value -> %r0
- # ref_copy %r0 -> %r2 -- but expect to read the old value of %r0!
+ # ref_copy %r0 -> %r1 -- but expect to read the old value of %r0!
self.check_assembler(graph, """
residual_call_r_r $<* fn bar>, <Descr>, R[%r0] -> %r1
-live-
- residual_call_ir_r $<* fn g>, <Descr>, I[%i0], R[] -> %r2
+ residual_call_ir_r $<* fn g>, <Descr>, I[%i0], R[] -> %r1
-live-
catch_exception L1
- ref_return %r2
+ ref_return %r1
---
L1:
goto_if_exception_mismatch $<* struct object_vtable>, L2
- ref_copy %r0 -> %r2
+ ref_copy %r0 -> %r1
last_exc_value -> %r0
residual_call_r_r $<* fn foo>, <Descr>, R[%r0] -> %r0
-live-
- ref_return %r2
+ ref_return %r1
---
L2:
reraise
Modified: pypy/branch/out-of-line-guards/pypy/jit/codewriter/test/test_void_list.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/jit/codewriter/test/test_void_list.py (original)
+++ pypy/branch/out-of-line-guards/pypy/jit/codewriter/test/test_void_list.py Thu Dec 9 16:33:59 2010
@@ -51,9 +51,6 @@
builtin_test('list.getitem/NEG',
[varoftype(FIXEDLIST), varoftype(lltype.Signed)],
lltype.Void, "")
- builtin_test('list.getitem/CANRAISE',
- [varoftype(FIXEDLIST), varoftype(lltype.Signed)],
- lltype.Void, NotSupported)
def test_fixed_getitem_foldable():
builtin_test('list.getitem_foldable/NONNEG',
@@ -62,9 +59,6 @@
builtin_test('list.getitem_foldable/NEG',
[varoftype(FIXEDLIST), varoftype(lltype.Signed)],
lltype.Void, "")
- builtin_test('list.getitem_foldable/CANRAISE',
- [varoftype(FIXEDLIST), varoftype(lltype.Signed)],
- lltype.Void, NotSupported)
def test_fixed_setitem():
builtin_test('list.setitem/NONNEG', [varoftype(FIXEDLIST),
@@ -75,10 +69,6 @@
varoftype(lltype.Signed),
varoftype(lltype.Void)],
lltype.Void, "")
- builtin_test('list.setitem/CANRAISE', [varoftype(FIXEDLIST),
- varoftype(lltype.Signed),
- varoftype(lltype.Void)],
- lltype.Void, NotSupported)
def test_fixed_len():
builtin_test('list.len', [varoftype(FIXEDLIST)], lltype.Signed,
@@ -115,9 +105,6 @@
builtin_test('list.getitem/NEG',
[varoftype(VARLIST), varoftype(lltype.Signed)],
lltype.Void, "")
- builtin_test('list.getitem/CANRAISE',
- [varoftype(VARLIST), varoftype(lltype.Signed)],
- lltype.Void, NotSupported)
def test_resizable_setitem():
builtin_test('list.setitem/NONNEG', [varoftype(VARLIST),
@@ -128,10 +115,6 @@
varoftype(lltype.Signed),
varoftype(lltype.Void)],
lltype.Void, "")
- builtin_test('list.setitem/CANRAISE', [varoftype(VARLIST),
- varoftype(lltype.Signed),
- varoftype(lltype.Void)],
- lltype.Void, NotSupported)
def test_resizable_len():
builtin_test('list.len', [varoftype(VARLIST)], lltype.Signed,
Modified: pypy/branch/out-of-line-guards/pypy/jit/conftest.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/jit/conftest.py (original)
+++ pypy/branch/out-of-line-guards/pypy/jit/conftest.py Thu Dec 9 16:33:59 2010
@@ -1,7 +1,5 @@
import py
-option = py.test.config.option
-
def pytest_addoption(parser):
group = parser.getgroup("JIT options")
group.addoption('--slow', action="store_true",
Modified: pypy/branch/out-of-line-guards/pypy/jit/metainterp/compile.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/jit/metainterp/compile.py (original)
+++ pypy/branch/out-of-line-guards/pypy/jit/metainterp/compile.py Thu Dec 9 16:33:59 2010
@@ -1,4 +1,4 @@
-
+import weakref
from pypy.rpython.lltypesystem import lltype
from pypy.rpython.ootypesystem import ootype
from pypy.objspace.flow.model import Constant, Variable
@@ -48,6 +48,32 @@
loop_token.outermost_jitdriver_sd = jitdriver_sd
return loop_token
+def record_loop_or_bridge(loop):
+ """Do post-backend recordings and cleanups on 'loop'.
+ """
+ # get the original loop token (corresponding to 'loop', or if that is
+ # a bridge, to the loop that this bridge belongs to)
+ looptoken = loop.token
+ assert looptoken is not None
+ wref = weakref.ref(looptoken)
+ for op in loop.operations:
+ descr = op.getdescr()
+ if isinstance(descr, ResumeDescr):
+ descr.wref_original_loop_token = wref # stick it there
+ n = descr.index
+ if n >= 0: # we also record the resumedescr number
+ looptoken.compiled_loop_token.record_faildescr_index(n)
+ elif isinstance(descr, LoopToken):
+ # for a JUMP or a CALL_ASSEMBLER: record it as a potential jump.
+ # (the following test is not enough to prevent more complicated
+ # cases of cycles, but at least it helps in simple tests of
+ # test_memgr.py)
+ if descr is not looptoken:
+ looptoken.record_jump_to(descr)
+ op.setdescr(None) # clear reference, mostly for tests
+ # mostly for tests: make sure we don't keep a reference to the LoopToken
+ loop.token = None
+
# ____________________________________________________________
def compile_new_loop(metainterp, old_loop_tokens, start):
@@ -77,6 +103,7 @@
return old_loop_token
send_loop_to_backend(metainterp_sd, loop, "loop")
insert_loop_token(old_loop_tokens, loop_token)
+ record_loop_or_bridge(loop)
return loop_token
def insert_loop_token(old_loop_tokens, loop_token):
@@ -117,8 +144,11 @@
else:
loop._ignore_during_counting = True
metainterp_sd.log("compiled new " + type)
+ if metainterp_sd.warmrunnerdesc is not None: # for tests
+ metainterp_sd.warmrunnerdesc.memory_manager.keep_loop_alive(loop.token)
-def send_bridge_to_backend(metainterp_sd, faildescr, inputargs, operations):
+def send_bridge_to_backend(metainterp_sd, faildescr, inputargs, operations,
+ original_loop_token):
n = metainterp_sd.cpu.get_fail_descr_number(faildescr)
metainterp_sd.logger_ops.log_bridge(inputargs, operations, n)
if not we_are_translated():
@@ -127,7 +157,8 @@
metainterp_sd.profiler.start_backend()
debug_start("jit-backend")
try:
- metainterp_sd.cpu.compile_bridge(faildescr, inputargs, operations)
+ metainterp_sd.cpu.compile_bridge(faildescr, inputargs, operations,
+ original_loop_token)
finally:
debug_stop("jit-backend")
metainterp_sd.profiler.end_backend()
@@ -227,9 +258,6 @@
CNT_FLOAT = -0x60000000
CNT_MASK = 0x1FFFFFFF
- def __init__(self, metainterp_sd):
- self.metainterp_sd = metainterp_sd
-
def store_final_boxes(self, guard_op, boxes):
guard_op.setfailargs(boxes)
self.guard_opnum = guard_op.getopnum()
@@ -314,12 +342,14 @@
def compile_and_attach(self, metainterp, new_loop):
# We managed to create a bridge. Attach the new operations
- # to the corrsponding guard_op and compile from there
+ # to the corresponding guard_op and compile from there
+ assert metainterp.resumekey_original_loop_token is not None
+ new_loop.token = metainterp.resumekey_original_loop_token
inputargs = metainterp.history.inputargs
if not we_are_translated():
self._debug_suboperations = new_loop.operations
send_bridge_to_backend(metainterp.staticdata, self, inputargs,
- new_loop.operations)
+ new_loop.operations, new_loop.token)
def copy_all_attrbutes_into(self, res):
# XXX a bit ugly to have to list them all here
@@ -331,14 +361,14 @@
res.rd_pendingfields = self.rd_pendingfields
def _clone_if_mutable(self):
- res = ResumeGuardDescr(self.metainterp_sd)
+ res = ResumeGuardDescr()
self.copy_all_attrbutes_into(res)
return res
class ResumeGuardForcedDescr(ResumeGuardDescr):
def __init__(self, metainterp_sd, jitdriver_sd):
- ResumeGuardDescr.__init__(self, metainterp_sd)
+ self.metainterp_sd = metainterp_sd
self.jitdriver_sd = jitdriver_sd
def handle_fail(self, metainterp_sd, jitdriver_sd):
@@ -482,6 +512,8 @@
metainterp_sd = metainterp.staticdata
jitdriver_sd = metainterp.jitdriver_sd
redargs = new_loop.inputargs
+ # We make a new LoopToken for this entry bridge, and stick it
+ # to every guard in the loop.
new_loop_token = make_loop_token(len(redargs), jitdriver_sd)
new_loop.token = new_loop_token
send_loop_to_backend(metainterp_sd, new_loop, "entry bridge")
@@ -489,12 +521,14 @@
jitdriver_sd.warmstate.attach_unoptimized_bridge_from_interp(
self.original_greenkey,
new_loop_token)
- # store the new loop in compiled_merge_points too
+ # store the new loop in compiled_merge_points_wref too
old_loop_tokens = metainterp.get_compiled_merge_points(
self.original_greenkey)
# it always goes at the end of the list, as it is the most
# general loop token
old_loop_tokens.append(new_loop_token)
+ metainterp.set_compiled_merge_points(self.original_greenkey,
+ old_loop_tokens)
def reset_counter_from_failure(self):
pass
@@ -529,6 +563,7 @@
# know exactly what we must do (ResumeGuardDescr/ResumeFromInterpDescr)
prepare_last_operation(new_loop, target_loop_token)
resumekey.compile_and_attach(metainterp, new_loop)
+ record_loop_or_bridge(new_loop)
return target_loop_token
def prepare_last_operation(new_loop, target_loop_token):
@@ -555,7 +590,8 @@
propagate_exception_descr = PropagateExceptionDescr()
-def compile_tmp_callback(cpu, jitdriver_sd, greenboxes, redboxes):
+def compile_tmp_callback(cpu, jitdriver_sd, greenboxes, redboxes,
+ memory_manager=None):
"""Make a LoopToken that corresponds to assembler code that just
calls back the interpreter. Used temporarily: a fully compiled
version of the code may end up replacing it.
@@ -595,4 +631,6 @@
]
operations[1].setfailargs([])
cpu.compile_loop(inputargs, operations, loop_token, log=False)
+ if memory_manager is not None: # for tests
+ memory_manager.keep_loop_alive(loop_token)
return loop_token
Modified: pypy/branch/out-of-line-guards/pypy/jit/metainterp/history.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/jit/metainterp/history.py (original)
+++ pypy/branch/out-of-line-guards/pypy/jit/metainterp/history.py Thu Dec 9 16:33:59 2010
@@ -4,8 +4,7 @@
from pypy.rpython.ootypesystem import ootype
from pypy.rlib.objectmodel import we_are_translated, r_dict, Symbolic
from pypy.rlib.objectmodel import compute_hash, compute_unique_id
-from pypy.rlib.rarithmetic import intmask
-from pypy.tool.uid import uid
+from pypy.rlib.rarithmetic import intmask, r_int64
from pypy.conftest import option
from pypy.jit.metainterp.resoperation import ResOperation, rop
@@ -730,14 +729,28 @@
outermost_jitdriver_sd = None
# specnodes = ...
# and more data specified by the backend when the loop is compiled
- number = 0
+ number = -1
+ generation = r_int64(0)
+ # one purpose of LoopToken is to keep alive the CompiledLoopToken
+ # returned by the backend. When the LoopToken goes away, the
+ # CompiledLoopToken has its __del__ called, which frees the assembler
+ # memory and the ResumeGuards.
+ compiled_loop_token = None
- def __init__(self, number=0):
- self.number = number
+ def __init__(self):
+ # For memory management of assembled loops
+ self._keepalive_target_looktokens = {} # set of other LoopTokens
+
+ def record_jump_to(self, target_loop_token):
+ self._keepalive_target_looktokens[target_loop_token] = None
+
+ def __repr__(self):
+ return '<Loop %d, gen=%d>' % (self.number, self.generation)
def repr_of_descr(self):
return '<Loop%d>' % self.number
+
class TreeLoop(object):
inputargs = None
operations = None
Modified: pypy/branch/out-of-line-guards/pypy/jit/metainterp/jitprof.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/jit/metainterp/jitprof.py (original)
+++ pypy/branch/out-of-line-guards/pypy/jit/metainterp/jitprof.py Thu Dec 9 16:33:59 2010
@@ -2,9 +2,9 @@
""" A small helper module for profiling JIT
"""
-import os
import time
-from pypy.rlib.debug import debug_print
+from pypy.rlib.debug import debug_print, debug_start, debug_stop
+from pypy.rlib.debug import have_debug_prints
from pypy.jit.metainterp.jitexc import JitException
counters="""
@@ -24,6 +24,10 @@
NVIRTUALS
NVHOLES
NVREUSED
+TOTAL_COMPILED_LOOPS
+TOTAL_COMPILED_BRIDGES
+TOTAL_FREED_LOOPS
+TOTAL_FREED_BRIDGES
"""
def _setup():
@@ -35,6 +39,7 @@
_setup()
JITPROF_LINES = ncounters + 1 + 1 # one for TOTAL, 1 for calls, update if needed
+_CPU_LINES = 4 # the last 4 lines are stored on the cpu
class BaseProfiler(object):
pass
@@ -48,9 +53,6 @@
def finish(self):
pass
- def set_printing(self, printing):
- pass
-
def start_tracing(self):
pass
@@ -90,23 +92,19 @@
counters = None
calls = 0
current = None
- printing = True
+ cpu = None
def start(self):
self.starttime = self.timer()
self.t1 = self.starttime
self.times = [0, 0]
- self.counters = [0] * ncounters
+ self.counters = [0] * (ncounters - _CPU_LINES)
self.calls = 0
self.current = []
def finish(self):
self.tk = self.timer()
- if self.printing:
- self.print_stats()
-
- def set_printing(self, printing):
- self.printing = printing
+ self.print_stats()
def _start(self, event):
t0 = self.t1
@@ -154,6 +152,12 @@
self.calls += 1
def print_stats(self):
+ debug_start("jit-summary")
+ if have_debug_prints():
+ self._print_stats()
+ debug_stop("jit-summary")
+
+ def _print_stats(self):
cnt = self.counters
tim = self.times
calls = self.calls
@@ -161,8 +165,8 @@
self._print_line_time("Backend", cnt[BACKEND], tim[BACKEND])
self._print_intline("Running asm", cnt[RUNNING])
self._print_intline("Blackhole", cnt[BLACKHOLE])
- line = "TOTAL: \t\t%f\n" % (self.tk - self.starttime, )
- os.write(2, line)
+ line = "TOTAL: \t\t%f" % (self.tk - self.starttime, )
+ debug_print(line)
self._print_intline("ops", cnt[OPS])
self._print_intline("recorded ops", cnt[RECORDED_OPS])
self._print_intline(" calls", calls)
@@ -176,17 +180,26 @@
self._print_intline("nvirtuals", cnt[NVIRTUALS])
self._print_intline("nvholes", cnt[NVHOLES])
self._print_intline("nvreused", cnt[NVREUSED])
+ cpu = self.cpu
+ if cpu is not None: # for some tests
+ self._print_intline("Total # of loops",
+ cpu.total_compiled_loops)
+ self._print_intline("Total # of bridges",
+ cpu.total_compiled_bridges)
+ self._print_intline("Freed # of loops",
+ cpu.total_freed_loops)
+ self._print_intline("Freed # of bridges",
+ cpu.total_freed_bridges)
def _print_line_time(self, string, i, tim):
- final = "%s:%s\t%d\t%f\n" % (string, " " * max(0, 13-len(string)), i, tim)
- os.write(2, final)
+ final = "%s:%s\t%d\t%f" % (string, " " * max(0, 13-len(string)), i, tim)
+ debug_print(final)
def _print_intline(self, string, i):
final = string + ':' + " " * max(0, 16-len(string))
- final += '\t' + str(i) + '\n'
- os.write(2, final)
-
-
+ final += '\t' + str(i)
+ debug_print(final)
+
class BrokenProfilerData(JitException):
pass
Modified: pypy/branch/out-of-line-guards/pypy/jit/metainterp/optimizefindnode.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/jit/metainterp/optimizefindnode.py (original)
+++ pypy/branch/out-of-line-guards/pypy/jit/metainterp/optimizefindnode.py Thu Dec 9 16:33:59 2010
@@ -128,6 +128,7 @@
assert isinstance(constbox, Const)
node = InstanceNode()
node.unique = UNIQUE_NO
+ node.escaped = True
node.knownvaluebox = constbox
self.nodes[box] = node
return node
Modified: pypy/branch/out-of-line-guards/pypy/jit/metainterp/optimizeopt/__init__.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/jit/metainterp/optimizeopt/__init__.py (original)
+++ pypy/branch/out-of-line-guards/pypy/jit/metainterp/optimizeopt/__init__.py Thu Dec 9 16:33:59 2010
@@ -3,7 +3,6 @@
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
def optimize_loop_1(metainterp_sd, loop, virtuals=True):
@@ -17,6 +16,10 @@
OptVirtualize(),
OptString(),
OptHeap(),
+ ]
+ if metainterp_sd.jit_ffi:
+ from pypy.jit.metainterp.optimizeopt.fficall import OptFfiCall
+ optimizations = optimizations + [
OptFfiCall(),
]
optimizer = Optimizer(metainterp_sd, loop, optimizations, virtuals)
Modified: pypy/branch/out-of-line-guards/pypy/jit/metainterp/optimizeopt/optimizer.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/jit/metainterp/optimizeopt/optimizer.py (original)
+++ pypy/branch/out-of-line-guards/pypy/jit/metainterp/optimizeopt/optimizer.py Thu Dec 9 16:33:59 2010
@@ -301,7 +301,9 @@
return CVAL_ZERO
def propagate_all_forward(self):
- self.exception_might_have_happened = False
+ self.exception_might_have_happened = True
+ # ^^^ at least at the start of bridges. For loops, we could set
+ # it to False, but we probably don't care
self.newoperations = []
self.i = 0
while self.i < len(self.loop.operations):
Modified: pypy/branch/out-of-line-guards/pypy/jit/metainterp/pyjitpl.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/jit/metainterp/pyjitpl.py (original)
+++ pypy/branch/out-of-line-guards/pypy/jit/metainterp/pyjitpl.py Thu Dec 9 16:33:59 2010
@@ -14,11 +14,10 @@
from pypy.jit.metainterp.logger import Logger
from pypy.jit.metainterp.jitprof import EmptyProfiler
from pypy.jit.metainterp.jitprof import GUARDS, RECORDED_OPS, ABORT_ESCAPE
-from pypy.jit.metainterp.jitprof import ABORT_TOO_LONG
+from pypy.jit.metainterp.jitprof import ABORT_TOO_LONG, ABORT_BRIDGE
from pypy.jit.metainterp.jitexc import JitException, get_llexception
from pypy.rlib.rarithmetic import intmask
from pypy.rlib.objectmodel import specialize
-from pypy.rlib.jit import DEBUG_OFF, DEBUG_PROFILE, DEBUG_STEPS, DEBUG_DETAILED
from pypy.jit.codewriter.jitcode import JitCode, SwitchDictDescr
from pypy.jit.codewriter import heaptracker
@@ -94,6 +93,18 @@
else: raise AssertionError(argcode)
outvalue[startindex+i] = reg
+ def _put_back_list_of_boxes(self, outvalue, startindex, position):
+ code = self.bytecode
+ length = ord(code[position])
+ position += 1
+ for i in range(length):
+ index = ord(code[position+i])
+ box = outvalue[startindex+i]
+ if box.type == history.INT: self.registers_i[index] = box
+ elif box.type == history.REF: self.registers_r[index] = box
+ elif box.type == history.FLOAT: self.registers_f[index] = box
+ else: raise AssertionError(box.type)
+
def get_current_position_info(self):
return self.jitcode.get_live_vars_info(self.pc)
@@ -601,8 +612,10 @@
virtualizable = vinfo.unwrap_virtualizable_box(virtualizable_box)
arrayindex = vinfo.array_field_by_descrs[arrayfielddescr]
index = indexbox.getint()
- if index < 0:
- index += vinfo.get_array_length(virtualizable, arrayindex)
+ # Support for negative index: disabled
+ # (see codewriter/jtransform.py, _check_no_vable_array).
+ #if index < 0:
+ # index += vinfo.get_array_length(virtualizable, arrayindex)
assert 0 <= index < vinfo.get_array_length(virtualizable, arrayindex)
return vinfo.get_index_in_array(virtualizable, arrayindex, index)
@@ -814,8 +827,9 @@
for i in range(num_green_args):
assert isinstance(varargs[i], Const)
- @arguments("orgpc", "int", "boxes3", "boxes3")
- def opimpl_jit_merge_point(self, orgpc, jdindex, greenboxes, redboxes):
+ @arguments("orgpc", "int", "boxes3", "jitcode_position", "boxes3")
+ def opimpl_jit_merge_point(self, orgpc, jdindex, greenboxes,
+ jcposition, redboxes):
any_operation = len(self.metainterp.history.operations) > 0
jitdriver_sd = self.metainterp.staticdata.jitdrivers_sd[jdindex]
self.verify_green_args(jitdriver_sd, greenboxes)
@@ -843,6 +857,10 @@
self.pc = orgpc
self.metainterp.reached_loop_header(greenboxes, redboxes)
self.pc = saved_pc
+ # no exception, which means that the jit_merge_point did not
+ # close the loop. We have to put the possibly-modified list
+ # 'redboxes' back into the registers where it comes from.
+ put_back_list_of_boxes3(self, jcposition, redboxes)
else:
# warning! careful here. We have to return from the current
# frame containing the jit_merge_point, and then use
@@ -1052,7 +1070,7 @@
resumedescr = compile.ResumeGuardForcedDescr(metainterp_sd,
metainterp.jitdriver_sd)
else:
- resumedescr = compile.ResumeGuardDescr(metainterp_sd)
+ resumedescr = compile.ResumeGuardDescr()
guard_op = metainterp.history.record(opnum, moreargs, None,
descr=resumedescr)
virtualizable_boxes = None
@@ -1198,7 +1216,8 @@
logger_ops = None
def __init__(self, cpu, options,
- ProfilerClass=EmptyProfiler, warmrunnerdesc=None):
+ ProfilerClass=EmptyProfiler, warmrunnerdesc=None,
+ jit_ffi=True):
self.cpu = cpu
self.stats = self.cpu.stats
self.options = options
@@ -1206,7 +1225,9 @@
self.logger_ops = Logger(self, guard_number=True)
self.profiler = ProfilerClass()
+ self.profiler.cpu = cpu
self.warmrunnerdesc = warmrunnerdesc
+ self.jit_ffi = jit_ffi
backendmodule = self.cpu.__module__
backendmodule = backendmodule.split('.')[-2]
@@ -1324,6 +1345,11 @@
return jitcode
return None
+ def try_to_free_some_loops(self):
+ # Increase here the generation recorded by the memory manager.
+ if self.warmrunnerdesc is not None: # for tests
+ self.warmrunnerdesc.memory_manager.next_generation()
+
# ---------------- logging ------------------------
def log(self, msg):
@@ -1620,6 +1646,7 @@
self.staticdata._setup_once()
self.staticdata.profiler.start_tracing()
assert jitdriver_sd is self.jitdriver_sd
+ self.staticdata.try_to_free_some_loops()
self.create_empty_history()
try:
original_boxes = self.initialize_original_boxes(jitdriver_sd, *args)
@@ -1648,10 +1675,15 @@
debug_start('jit-tracing')
self.staticdata.profiler.start_tracing()
assert isinstance(key, compile.ResumeGuardDescr)
+ # store the resumekey.wref_original_loop_token() on 'self' to make
+ # sure that it stays alive as long as this MetaInterp
+ self.resumekey_original_loop_token = key.wref_original_loop_token()
+ self.staticdata.try_to_free_some_loops()
self.initialize_state_from_guard_failure(key)
try:
return self._handle_guard_failure(key)
finally:
+ self.resumekey_original_loop_token = None
self.staticdata.profiler.end_tracing()
debug_stop('jit-tracing')
@@ -1661,6 +1693,8 @@
self.seen_loop_header_for_jdindex = -1
try:
self.prepare_resume_from_failure(key.guard_opnum)
+ if self.resumekey_original_loop_token is None: # very rare case
+ raise SwitchToBlackhole(ABORT_BRIDGE)
self.interpret()
except GenerateMergePoint, gmp:
return self.designate_target_loop(gmp)
@@ -1782,10 +1816,15 @@
raise NotImplementedError(opname[opnum])
def get_compiled_merge_points(self, greenkey):
+ """Get the list of looptokens corresponding to the greenkey.
+ Turns the (internal) list of weakrefs into regular refs.
+ """
cell = self.jitdriver_sd.warmstate.jit_cell_at_key(greenkey)
- if cell.compiled_merge_points is None:
- cell.compiled_merge_points = []
- return cell.compiled_merge_points
+ return cell.get_compiled_merge_points()
+
+ def set_compiled_merge_points(self, greenkey, looptokens):
+ cell = self.jitdriver_sd.warmstate.jit_cell_at_key(greenkey)
+ cell.set_compiled_merge_points(looptokens)
def compile(self, original_boxes, live_arg_boxes, start):
num_green_args = self.jitdriver_sd.num_green_args
@@ -1795,6 +1834,7 @@
self.history.record(rop.JUMP, live_arg_boxes[num_green_args:], None)
loop_token = compile.compile_new_loop(self, old_loop_tokens, start)
if loop_token is not None: # raise if it *worked* correctly
+ self.set_compiled_merge_points(greenkey, old_loop_tokens)
raise GenerateMergePoint(live_arg_boxes, loop_token)
self.history.operations.pop() # remove the JUMP
@@ -2293,6 +2333,8 @@
else:
raise AssertionError("bad argcode")
position += 1
+ elif argtype == "jitcode_position":
+ value = position
else:
raise AssertionError("bad argtype: %r" % (argtype,))
args += (value,)
@@ -2337,3 +2379,15 @@
argtypes = unrolling_iterable(unboundmethod.argtypes)
handler.func_name = 'handler_' + name
return handler
+
+def put_back_list_of_boxes3(frame, position, newvalue):
+ code = frame.bytecode
+ length1 = ord(code[position])
+ position2 = position + 1 + length1
+ length2 = ord(code[position2])
+ position3 = position2 + 1 + length2
+ length3 = ord(code[position3])
+ assert len(newvalue) == length1 + length2 + length3
+ frame._put_back_list_of_boxes(newvalue, 0, position)
+ frame._put_back_list_of_boxes(newvalue, length1, position2)
+ frame._put_back_list_of_boxes(newvalue, length1 + length2, position3)
Modified: pypy/branch/out-of-line-guards/pypy/jit/metainterp/test/test_basic.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/jit/metainterp/test/test_basic.py (original)
+++ pypy/branch/out-of-line-guards/pypy/jit/metainterp/test/test_basic.py Thu Dec 9 16:33:59 2010
@@ -19,7 +19,11 @@
from pypy.jit.metainterp import simple_optimize
class FakeJitCell:
- compiled_merge_points = None
+ __compiled_merge_points = []
+ def get_compiled_merge_points(self):
+ return self.__compiled_merge_points[:]
+ def set_compiled_merge_points(self, lst):
+ self.__compiled_merge_points = lst
class FakeWarmRunnerState:
def attach_unoptimized_bridge_from_interp(self, greenkey, newloop):
@@ -35,7 +39,6 @@
optimize_bridge = staticmethod(simple_optimize.optimize_bridge)
trace_limit = sys.maxint
- debug_level = 2
func._jit_unroll_safe_ = True
rtyper = support.annotate(func, values, type_system=type_system)
@@ -1716,6 +1719,29 @@
res = self.meta_interp(f, [5, 2])
assert 4 < res < 14
+ def test_compute_identity_hash(self):
+ from pypy.rlib.objectmodel import compute_identity_hash
+ class A(object):
+ pass
+ def f():
+ a = A()
+ return compute_identity_hash(a) == compute_identity_hash(a)
+ res = self.interp_operations(f, [])
+ assert res
+ # a "did not crash" kind of test
+
+ def test_compute_unique_id(self):
+ from pypy.rlib.objectmodel import compute_unique_id
+ class A(object):
+ pass
+ def f():
+ a1 = A()
+ a2 = A()
+ return (compute_unique_id(a1) == compute_unique_id(a1) and
+ compute_unique_id(a1) != compute_unique_id(a2))
+ res = self.interp_operations(f, [])
+ assert res
+
class TestOOtype(BasicTests, OOJitMixin):
Modified: pypy/branch/out-of-line-guards/pypy/jit/metainterp/test/test_compile.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/jit/metainterp/test/test_compile.py (original)
+++ pypy/branch/out-of-line-guards/pypy/jit/metainterp/test/test_compile.py Thu Dec 9 16:33:59 2010
@@ -42,7 +42,6 @@
class FakeState:
optimize_loop = staticmethod(optimize.optimize_loop)
- debug_level = 0
class FakeGlobalData:
loopnumbering = 0
@@ -54,6 +53,8 @@
stats = Stats()
profiler = jitprof.EmptyProfiler()
+ warmrunnerdesc = None
+ jit_ffi = False
def log(self, msg, event_kind=None):
pass
@@ -207,14 +208,12 @@
class ExitFrameWithExceptionRef(Exception):
pass
FakeMetaInterpSD.cpu = cpu
- class FakeJitDriverSD:
- pass
cpu.set_future_value_int(0, -156)
cpu.set_future_value_int(1, -178)
cpu.set_future_value_int(2, -190)
fail_descr = cpu.execute_token(loop_token)
try:
- fail_descr.handle_fail(FakeMetaInterpSD(), FakeJitDriverSD())
+ fail_descr.handle_fail(FakeMetaInterpSD(), None)
except FakeMetaInterpSD.ExitFrameWithExceptionRef, e:
assert lltype.cast_opaque_ptr(lltype.Ptr(EXC), e.args[1]) == llexc
else:
Modified: pypy/branch/out-of-line-guards/pypy/jit/metainterp/test/test_exception.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/jit/metainterp/test/test_exception.py (original)
+++ pypy/branch/out-of-line-guards/pypy/jit/metainterp/test/test_exception.py Thu Dec 9 16:33:59 2010
@@ -1,6 +1,6 @@
import py, sys
from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin
-from pypy.rlib.jit import JitDriver, OPTIMIZER_SIMPLE
+from pypy.rlib.jit import JitDriver, OPTIMIZER_SIMPLE, dont_look_inside
from pypy.rlib.rarithmetic import ovfcheck, LONG_BIT, intmask
from pypy.jit.codewriter.policy import StopAtXPolicy
@@ -588,6 +588,33 @@
res = self.interp_operations(f, [99])
assert res == 21
+ def test_bug_exc1_noexc_exc2(self):
+ myjitdriver = JitDriver(greens=[], reds=['i'])
+ @dont_look_inside
+ def rescall(i):
+ if i < 10:
+ raise KeyError
+ if i < 20:
+ return None
+ raise ValueError
+ def f(i):
+ while i < 30:
+ myjitdriver.can_enter_jit(i=i)
+ myjitdriver.jit_merge_point(i=i)
+ try:
+ rescall(i)
+ except KeyError:
+ assert i < 10
+ except ValueError:
+ assert i >= 20
+ else:
+ assert 10 <= i < 20
+ i += 1
+ return i
+ res = self.meta_interp(f, [0], inline=True)
+ assert res == 30
+
+
class MyError(Exception):
def __init__(self, n):
self.n = n
Modified: pypy/branch/out-of-line-guards/pypy/jit/metainterp/test/test_fficall.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/jit/metainterp/test/test_fficall.py (original)
+++ pypy/branch/out-of-line-guards/pypy/jit/metainterp/test/test_fficall.py Thu Dec 9 16:33:59 2010
@@ -40,6 +40,6 @@
n += 1
return res
#
- res = self.meta_interp(f, [0])
+ res = self.meta_interp(f, [0], jit_ffi=True)
return res
Modified: pypy/branch/out-of-line-guards/pypy/jit/metainterp/test/test_list.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/jit/metainterp/test/test_list.py (original)
+++ pypy/branch/out-of-line-guards/pypy/jit/metainterp/test/test_list.py Thu Dec 9 16:33:59 2010
@@ -188,6 +188,26 @@
assert res == f(4)
self.check_loops(call=0, getfield_gc=0)
+ def test_fold_indexerror(self):
+ jitdriver = JitDriver(greens = [], reds = ['total', 'n', 'lst'])
+ def f(n):
+ lst = []
+ total = 0
+ while n > 0:
+ jitdriver.can_enter_jit(lst=lst, n=n, total=total)
+ jitdriver.jit_merge_point(lst=lst, n=n, total=total)
+ lst.append(n)
+ try:
+ total += lst[n]
+ except IndexError:
+ total += 1000
+ n -= 1
+ return total
+
+ res = self.meta_interp(f, [15], listops=True)
+ assert res == f(15)
+ self.check_loops(guard_exception=0)
+
class TestOOtype(ListTests, OOJitMixin):
pass
Modified: pypy/branch/out-of-line-guards/pypy/jit/metainterp/test/test_logger.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/jit/metainterp/test/test_logger.py (original)
+++ pypy/branch/out-of-line-guards/pypy/jit/metainterp/test/test_logger.py Thu Dec 9 16:33:59 2010
@@ -14,11 +14,20 @@
def capturing(func, *args, **kwds):
log_stream = StringIO()
- debug._stderr = log_stream
+ class MyDebugLog:
+ def debug_print(self, *args):
+ for arg in args:
+ print >> log_stream, arg,
+ print >> log_stream
+ def debug_start(self, *args):
+ pass
+ def debug_stop(self, *args):
+ pass
try:
+ debug._log = MyDebugLog()
func(*args, **kwds)
finally:
- debug._stderr = sys.stderr
+ debug._log = None
return log_stream.getvalue()
class Logger(logger.Logger):
@@ -112,7 +121,8 @@
equaloplists(loop.operations, oloop.operations)
def test_jump(self):
- namespace = {'target': LoopToken(3)}
+ namespace = {'target': LoopToken()}
+ namespace['target'].number = 3
inp = '''
[i0]
jump(i0, descr=target)
Modified: pypy/branch/out-of-line-guards/pypy/jit/metainterp/test/test_optimizefficall.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/jit/metainterp/test/test_optimizefficall.py (original)
+++ pypy/branch/out-of-line-guards/pypy/jit/metainterp/test/test_optimizefficall.py Thu Dec 9 16:33:59 2010
@@ -31,6 +31,7 @@
class TestFfiCall(BaseTestOptimizeOpt, LLtypeMixin):
+ jit_ffi = True
class namespace:
cpu = LLtypeMixin.cpu
Modified: pypy/branch/out-of-line-guards/pypy/jit/metainterp/test/test_optimizeopt.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/jit/metainterp/test/test_optimizeopt.py (original)
+++ pypy/branch/out-of-line-guards/pypy/jit/metainterp/test/test_optimizeopt.py Thu Dec 9 16:33:59 2010
@@ -28,11 +28,12 @@
class FakeMetaInterpStaticData(object):
- def __init__(self, cpu):
+ def __init__(self, cpu, jit_ffi=False):
self.cpu = cpu
self.profiler = EmptyProfiler()
self.options = Fake()
self.globaldata = Fake()
+ self.jit_ffi = jit_ffi
def test_store_final_boxes_in_guard():
from pypy.jit.metainterp.compile import ResumeGuardDescr
@@ -41,7 +42,7 @@
b1 = BoxInt()
opt = optimizeopt.Optimizer(FakeMetaInterpStaticData(LLtypeMixin.cpu),
None)
- fdescr = ResumeGuardDescr(None)
+ fdescr = ResumeGuardDescr()
op = ResOperation(rop.GUARD_TRUE, ['dummy'], None, descr=fdescr)
# setup rd data
fi0 = resume.FrameInfo(None, "code0", 11)
@@ -227,6 +228,7 @@
return sorted(boxes, key=lambda box: _kind2count[box.type])
class BaseTestOptimizeOpt(BaseTest):
+ jit_ffi = False
def invent_fail_descr(self, fail_args):
if fail_args is None:
@@ -261,7 +263,7 @@
loop.token.specnodes = self.unpack_specnodes(spectext)
#
self.loop = loop
- metainterp_sd = FakeMetaInterpStaticData(self.cpu)
+ metainterp_sd = FakeMetaInterpStaticData(self.cpu, self.jit_ffi)
if hasattr(self, 'vrefinfo'):
metainterp_sd.virtualref_info = self.vrefinfo
if hasattr(self, 'callinfocollection'):
@@ -805,8 +807,12 @@
i3 = call(i2, descr=nonwritedescr)
jump(i1) # the exception is considered lost when we loop back
"""
+ # note that 'guard_no_exception' at the very start must be kept
+ # around: bridges may start with one. (In case of loops we could
+ # remove it, but we probably don't care.)
expected = """
[i]
+ guard_no_exception() []
i1 = int_add(i, 3)
i2 = call(i1, descr=nonwritedescr)
guard_no_exception() [i1, i2]
@@ -1966,6 +1972,15 @@
"""
self.optimize_loop(ops, 'Virtual(node_vtable2, nextdescr=Not, otherdescr=Not)', expected)
+ def test_bug_4(self):
+ ops = """
+ [p9]
+ p30 = new_with_vtable(ConstClass(node_vtable))
+ setfield_gc(ConstPtr(myptr), p9, descr=nextdescr)
+ jump(p30)
+ """
+ self.optimize_loop(ops, 'Not', ops)
+
def test_invalid_loop_1(self):
ops = """
[p1]
Modified: pypy/branch/out-of-line-guards/pypy/jit/metainterp/test/test_pyjitpl.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/jit/metainterp/test/test_pyjitpl.py (original)
+++ pypy/branch/out-of-line-guards/pypy/jit/metainterp/test/test_pyjitpl.py Thu Dec 9 16:33:59 2010
@@ -17,6 +17,7 @@
portal.setup(None)
class FakeStaticData:
cpu = None
+ warmrunnerdesc = None
metainterp = pyjitpl.MetaInterp(FakeStaticData(), None)
metainterp.framestack = []
@@ -53,6 +54,7 @@
def test_remove_consts_and_duplicates():
class FakeStaticData:
cpu = None
+ warmrunnerdesc = None
def is_another_box_like(box, referencebox):
assert box is not referencebox
assert isinstance(box, referencebox.clonebox().__class__)
Modified: pypy/branch/out-of-line-guards/pypy/jit/metainterp/test/test_recursive.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/jit/metainterp/test/test_recursive.py (original)
+++ pypy/branch/out-of-line-guards/pypy/jit/metainterp/test/test_recursive.py Thu Dec 9 16:33:59 2010
@@ -927,12 +927,16 @@
x=x)
frame.s = hint(frame.s, promote=True)
n -= 1
- x += frame.l[frame.s]
+ s = frame.s
+ assert s >= 0
+ x += frame.l[s]
frame.s += 1
if codeno == 0:
subframe = Frame([n, n+1, n+2, n+3], 0)
x += f(1, 10, 1, subframe)
- x += frame.l[frame.s]
+ s = frame.s
+ assert s >= 0
+ x += frame.l[s]
x += len(frame.l)
frame.s -= 1
return x
@@ -1142,6 +1146,19 @@
res = self.meta_interp(main, [], inline=True, trace_limit=tlimit)
assert ''.join(res.chars) == 'ABCDEFGHIabcdefghijJ' * 5
+ def test_no_duplicates_bug(self):
+ driver = JitDriver(greens = ['codeno'], reds = ['i'],
+ get_printable_location = lambda codeno: str(codeno))
+ def portal(codeno, i):
+ while i > 0:
+ driver.can_enter_jit(codeno=codeno, i=i)
+ driver.jit_merge_point(codeno=codeno, i=i)
+ if codeno > 0:
+ break
+ portal(i, i)
+ i -= 1
+ self.meta_interp(portal, [0, 10], inline=True)
+
class TestLLtype(RecursiveTests, LLJitMixin):
pass
Modified: pypy/branch/out-of-line-guards/pypy/jit/metainterp/test/test_virtualizable.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/jit/metainterp/test/test_virtualizable.py (original)
+++ pypy/branch/out-of-line-guards/pypy/jit/metainterp/test/test_virtualizable.py Thu Dec 9 16:33:59 2010
@@ -480,9 +480,13 @@
myjitdriver.jit_merge_point(frame=frame, n=n, x=x)
frame.s = hint(frame.s, promote=True)
n -= 1
- x += frame.l[frame.s]
+ s = frame.s
+ assert s >= 0
+ x += frame.l[s]
frame.s += 1
- x += frame.l[frame.s]
+ s = frame.s
+ assert s >= 0
+ x += frame.l[s]
x += len(frame.l)
frame.s -= 1
return x
@@ -994,7 +998,9 @@
jitdriver.can_enter_jit(frame=frame, n=n)
jitdriver.jit_merge_point(frame=frame, n=n)
popped = frame.stack[frame.stackpos]
- frame.stackpos -= 1
+ sp = frame.stackpos - 1
+ assert sp >= 0
+ frame.stackpos = sp
to_push = intmask(popped * 3)
frame.stack[frame.stackpos] = to_push
frame.stackpos += 1
Modified: pypy/branch/out-of-line-guards/pypy/jit/metainterp/test/test_warmspot.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/jit/metainterp/test/test_warmspot.py (original)
+++ pypy/branch/out-of-line-guards/pypy/jit/metainterp/test/test_warmspot.py Thu Dec 9 16:33:59 2010
@@ -134,91 +134,6 @@
assert state.optimize_loop is optimize.optimize_loop
assert state.optimize_bridge is optimize.optimize_bridge
- def test_static_debug_level(self, capfd):
- py.test.skip("debug_level is being deprecated")
- from pypy.rlib.jit import DEBUG_PROFILE, DEBUG_OFF, DEBUG_STEPS
- from pypy.jit.metainterp.jitprof import EmptyProfiler, Profiler
-
- myjitdriver = JitDriver(greens = [], reds = ['n'])
- def f(n):
- while n > 0:
- myjitdriver.can_enter_jit(n=n)
- myjitdriver.jit_merge_point(n=n)
- n -= 1
- return n
-
- capfd.readouterr()
- self.meta_interp(f, [10], debug_level=DEBUG_OFF,
- ProfilerClass=Profiler)
- out, err = capfd.readouterr()
- assert not 'ENTER' in err
- assert not 'LEAVE' in err
- assert not "Running asm" in err
- self.meta_interp(f, [10], debug_level=DEBUG_PROFILE,
- ProfilerClass=Profiler)
- out, err = capfd.readouterr()
- assert not 'ENTER' in err
- assert not 'LEAVE' in err
- assert not 'compiled new' in err
- assert "Running asm" in err
-
- self.meta_interp(f, [10], debug_level=DEBUG_STEPS,
- ProfilerClass=Profiler)
- out, err = capfd.readouterr()
- assert 'ENTER' in err
- assert 'LEAVE' in err
- assert "Running asm" in err
-
- self.meta_interp(f, [10], debug_level=DEBUG_STEPS,
- ProfilerClass=EmptyProfiler)
- out, err = capfd.readouterr()
- assert 'ENTER' in err
- assert 'LEAVE' in err
- assert not "Running asm" in err
-
- def test_set_param_debug(self):
- py.test.skip("debug_level is being deprecated")
- from pypy.rlib.jit import DEBUG_PROFILE, DEBUG_OFF, DEBUG_STEPS
- from pypy.jit.metainterp.jitprof import EmptyProfiler, Profiler
-
- myjitdriver = JitDriver(greens = [], reds = ['n'])
- def f(n):
- while n > 0:
- myjitdriver.can_enter_jit(n=n)
- myjitdriver.jit_merge_point(n=n)
- n -= 1
- return n
-
- def main(n, debug):
- myjitdriver.set_param("debug", debug)
- print f(n)
-
- outerr = py.io.StdCaptureFD()
- self.meta_interp(main, [10, DEBUG_OFF], debug_level=DEBUG_STEPS,
- ProfilerClass=Profiler)
- out, errf = outerr.done()
- err = errf.read()
- assert not 'ENTER' in err
- assert not 'LEAVE' in err
- assert not "Running asm" in err
- outerr = py.io.StdCaptureFD()
- self.meta_interp(main, [10, DEBUG_PROFILE], debug_level=DEBUG_STEPS,
- ProfilerClass=Profiler)
- out, errf = outerr.done()
- err = errf.read()
- assert not 'ENTER' in err
- assert not 'LEAVE' in err
- assert not 'compiled new' in err
- assert "Running asm" in err
- outerr = py.io.StdCaptureFD()
- self.meta_interp(main, [10, DEBUG_STEPS], debug_level=DEBUG_OFF,
- ProfilerClass=Profiler)
- out, errf = outerr.done()
- err = errf.read()
- assert 'ENTER' in err
- assert 'LEAVE' in err
- assert "Running asm" in err
-
def test_unwanted_loops(self):
mydriver = JitDriver(reds = ['n', 'total', 'm'], greens = [])
@@ -377,23 +292,30 @@
exc_vtable = lltype.malloc(OBJECT_VTABLE, immortal=True)
cls.exc_vtable = exc_vtable
- class FakeFailDescr(object):
+ class FakeLoopToken:
def __init__(self, no):
self.no = no
+ self.generation = 0
+
+ class FakeFailDescr(object):
+ def __init__(self, looptoken):
+ assert isinstance(looptoken, FakeLoopToken)
+ self.looptoken = looptoken
def handle_fail(self, metainterp_sd, jitdrivers_sd):
- if self.no == 0:
+ no = self.looptoken.no
+ if no == 0:
raise metainterp_sd.warmrunnerdesc.DoneWithThisFrameInt(3)
- if self.no == 1:
+ if no == 1:
raise metainterp_sd.warmrunnerdesc.ContinueRunningNormally(
[0], [], [], [1], [], [])
- if self.no == 3:
+ if no == 3:
exc = lltype.malloc(OBJECT)
exc.typeptr = exc_vtable
raise metainterp_sd.warmrunnerdesc.ExitFrameWithExceptionRef(
metainterp_sd.cpu,
lltype.cast_opaque_ptr(llmemory.GCREF, exc))
- return self.no
+ return self.looptoken
class FakeDescr:
def as_vtable_size_descr(self):
@@ -418,11 +340,11 @@
sizeof = nodescr
def get_fail_descr_from_number(self, no):
- return FakeFailDescr(no)
+ return FakeFailDescr(FakeLoopToken(no))
def execute_token(self, token):
- assert token == 2
- return FakeFailDescr(1)
+ assert token.no == 2
+ return FakeFailDescr(FakeLoopToken(1))
driver = JitDriver(reds = ['red'], greens = ['green'])
Modified: pypy/branch/out-of-line-guards/pypy/jit/metainterp/test/test_warmstate.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/jit/metainterp/test/test_warmstate.py (original)
+++ pypy/branch/out-of-line-guards/pypy/jit/metainterp/test/test_warmstate.py Thu Dec 9 16:33:59 2010
@@ -99,6 +99,8 @@
lltype.Float], lltype.Void))
class FakeWarmRunnerDesc:
rtyper = FakeRTyper()
+ cpu = None
+ memory_manager = None
class FakeJitDriverSD:
_get_jitcell_at_ptr = llhelper(GETTER, getter)
_set_jitcell_at_ptr = llhelper(SETTER, setter)
@@ -126,6 +128,7 @@
future_values[j] = "float", value
class FakeWarmRunnerDesc:
cpu = FakeCPU()
+ memory_manager = None
class FakeJitDriverSD:
_red_args_types = ["int", "float"]
virtualizable_info = None
@@ -154,16 +157,20 @@
_get_jitcell_at_ptr = None
state = WarmEnterState(None, FakeJitDriverSD())
get_jitcell = state.make_jitcell_getter()
+ class FakeLoopToken(object):
+ pass
+ looptoken = FakeLoopToken()
state.attach_unoptimized_bridge_from_interp([ConstInt(5),
ConstFloat(2.25)],
- "entry loop token")
+ looptoken)
cell1 = get_jitcell(True, 5, 2.25)
assert cell1.counter < 0
- assert cell1.entry_loop_token == "entry loop token"
+ assert cell1.get_entry_loop_token() is looptoken
def test_make_jitdriver_callbacks_1():
class FakeWarmRunnerDesc:
cpu = None
+ memory_manager = None
class FakeJitDriverSD:
_green_args_spec = [lltype.Signed, lltype.Float]
_get_printable_location_ptr = None
@@ -189,6 +196,7 @@
class FakeWarmRunnerDesc:
rtyper = None
cpu = None
+ memory_manager = None
class FakeJitDriverSD:
_green_args_spec = [lltype.Signed, lltype.Float]
_get_printable_location_ptr = llhelper(GET_LOCATION, get_location)
@@ -211,6 +219,7 @@
class FakeWarmRunnerDesc:
rtyper = None
cpu = None
+ memory_manager = None
class FakeJitDriverSD:
_green_args_spec = [lltype.Signed, lltype.Float]
_get_printable_location_ptr = None
@@ -233,6 +242,7 @@
class FakeWarmRunnerDesc:
rtyper = None
cpu = None
+ memory_manager = None
class FakeJitDriverSD:
_green_args_spec = [lltype.Signed, lltype.Float]
_get_printable_location_ptr = None
Modified: pypy/branch/out-of-line-guards/pypy/jit/metainterp/warmspot.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/jit/metainterp/warmspot.py (original)
+++ pypy/branch/out-of-line-guards/pypy/jit/metainterp/warmspot.py Thu Dec 9 16:33:59 2010
@@ -12,11 +12,12 @@
from pypy.rlib.unroll import unrolling_iterable
from pypy.rlib.rarithmetic import r_uint, intmask
from pypy.rlib.debug import debug_print, fatalerror
+from pypy.rlib.debug import debug_start, debug_stop
from pypy.rpython.lltypesystem.lloperation import llop
from pypy.translator.simplify import get_funcobj, get_functype
from pypy.translator.unsimplify import call_final_function
-from pypy.jit.metainterp import history, pyjitpl, gc
+from pypy.jit.metainterp import history, pyjitpl, gc, memmgr
from pypy.jit.metainterp.pyjitpl import MetaInterpStaticData, MetaInterp
from pypy.jit.metainterp.typesystem import LLTypeHelper, OOTypeHelper
from pypy.jit.metainterp.jitprof import Profiler, EmptyProfiler
@@ -24,21 +25,17 @@
from pypy.jit.metainterp.jitdriver import JitDriverStaticData
from pypy.jit.codewriter import support, codewriter
from pypy.jit.codewriter.policy import JitPolicy
-from pypy.rlib.jit import DEBUG_STEPS, DEBUG_DETAILED, DEBUG_OFF, DEBUG_PROFILE
# ____________________________________________________________
# Bootstrapping
-def apply_jit(translator, backend_name="auto", debug_level=DEBUG_STEPS,
- inline=False,
- **kwds):
+def apply_jit(translator, backend_name="auto", inline=False, **kwds):
if 'CPUClass' not in kwds:
from pypy.jit.backend.detect_cpu import getcpuclass
kwds['CPUClass'] = getcpuclass(backend_name)
- if debug_level > DEBUG_OFF:
- ProfilerClass = Profiler
- else:
- ProfilerClass = EmptyProfiler
+ ProfilerClass = Profiler
+ # Always use Profiler here, which should have a very low impact.
+ # Otherwise you can try with ProfilerClass = EmptyProfiler.
warmrunnerdesc = WarmRunnerDesc(translator,
translate_support_code=True,
listops=True,
@@ -47,7 +44,6 @@
**kwds)
for jd in warmrunnerdesc.jitdrivers_sd:
jd.warmstate.set_param_inlining(inline)
- jd.warmstate.set_param_debug(debug_level)
warmrunnerdesc.finish()
translator.warmrunnerdesc = warmrunnerdesc # for later debugging
@@ -66,7 +62,7 @@
def jittify_and_run(interp, graph, args, repeat=1,
backendopt=False, trace_limit=sys.maxint,
- debug_level=DEBUG_STEPS, inline=False, **kwds):
+ inline=False, loop_longevity=0, **kwds):
from pypy.config.config import ConfigError
translator = interp.typer.annotator.translator
try:
@@ -83,7 +79,7 @@
jd.warmstate.set_param_trace_eagerness(2) # for tests
jd.warmstate.set_param_trace_limit(trace_limit)
jd.warmstate.set_param_inlining(inline)
- jd.warmstate.set_param_debug(debug_level)
+ jd.warmstate.set_param_loop_longevity(loop_longevity)
warmrunnerdesc.finish()
res = interp.eval_graph(graph, args)
if not kwds.get('translate_support_code', False):
@@ -158,9 +154,11 @@
class WarmRunnerDesc(object):
def __init__(self, translator, policy=None, backendopt=True, CPUClass=None,
- optimizer=None, ProfilerClass=EmptyProfiler, **kwds):
+ optimizer=None, ProfilerClass=EmptyProfiler,
+ jit_ffi=None, **kwds):
pyjitpl._warmrunnerdesc = self # this is a global for debugging only!
self.set_translator(translator)
+ self.memory_manager = memmgr.MemoryManager()
self.build_cpu(CPUClass, **kwds)
self.find_portals()
self.codewriter = codewriter.CodeWriter(self.cpu, self.jitdrivers_sd)
@@ -172,8 +170,10 @@
self.check_access_directly_sanity(graphs)
if backendopt:
self.prejit_optimizations(policy, graphs)
+ elif self.opt.listops:
+ self.prejit_optimizations_minimal_inline(policy, graphs)
- self.build_meta_interp(ProfilerClass)
+ self.build_meta_interp(ProfilerClass, jit_ffi)
self.make_args_specifications()
#
from pypy.jit.metainterp.virtualref import VirtualRefInfo
@@ -270,6 +270,10 @@
remove_asserts=True,
really_remove_asserts=True)
+ def prejit_optimizations_minimal_inline(self, policy, graphs):
+ from pypy.translator.backendopt.inline import auto_inline_graphs
+ auto_inline_graphs(self.translator, graphs, 0.01)
+
def build_cpu(self, CPUClass, translate_support_code=False,
no_stats=False, **kwds):
assert CPUClass is not None
@@ -288,11 +292,14 @@
translate_support_code, gcdescr=self.gcdescr)
self.cpu = cpu
- def build_meta_interp(self, ProfilerClass):
+ def build_meta_interp(self, ProfilerClass, jit_ffi=None):
+ if jit_ffi is None:
+ jit_ffi = self.translator.config.translation.jit_ffi
self.metainterp_sd = MetaInterpStaticData(self.cpu,
self.opt,
ProfilerClass=ProfilerClass,
- warmrunnerdesc=self)
+ warmrunnerdesc=self,
+ jit_ffi=jit_ffi)
def make_virtualizable_infos(self):
vinfos = {}
@@ -724,7 +731,7 @@
loop_token = fail_descr.handle_fail(self.metainterp_sd, jd)
except JitException, e:
return handle_jitexception(e)
- fail_descr = self.cpu.execute_token(loop_token)
+ fail_descr = self.execute_token(loop_token)
jd._assembler_call_helper = assembler_call_helper # for debugging
jd._assembler_helper_ptr = self.helper_func(
@@ -823,3 +830,10 @@
py.test.skip("rewrite_force_virtual: port it to ootype")
all_graphs = self.translator.graphs
vrefinfo.replace_force_virtual_with_call(all_graphs)
+
+ # ____________________________________________________________
+
+ def execute_token(self, loop_token):
+ fail_descr = self.cpu.execute_token(loop_token)
+ self.memory_manager.keep_loop_alive(loop_token)
+ return fail_descr
Modified: pypy/branch/out-of-line-guards/pypy/jit/metainterp/warmstate.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/jit/metainterp/warmstate.py (original)
+++ pypy/branch/out-of-line-guards/pypy/jit/metainterp/warmstate.py Thu Dec 9 16:33:59 2010
@@ -1,4 +1,4 @@
-import sys
+import sys, weakref
from pypy.rpython.lltypesystem import lltype, llmemory, rstr, rffi
from pypy.rpython.ootypesystem import ootype
from pypy.rpython.annlowlevel import hlstr, llstr, cast_base_ptr_to_instance
@@ -9,7 +9,6 @@
from pypy.rlib.unroll import unrolling_iterable
from pypy.rlib.jit import (PARAMETERS, OPTIMIZER_SIMPLE, OPTIMIZER_FULL,
OPTIMIZER_NO_PERFECTSPEC)
-from pypy.rlib.jit import DEBUG_PROFILE
from pypy.rlib.jit import BaseJitCell
from pypy.rlib.debug import debug_start, debug_stop, debug_print
from pypy.jit.metainterp import history
@@ -150,9 +149,34 @@
# counter == -1: there is an entry bridge for this cell
# counter == -2: tracing is currently going on for this cell
counter = 0
- compiled_merge_points = None
+ compiled_merge_points_wref = None # list of weakrefs to LoopToken
dont_trace_here = False
- entry_loop_token = None
+ wref_entry_loop_token = None # (possibly) one weakref to LoopToken
+
+ def get_compiled_merge_points(self):
+ result = []
+ if self.compiled_merge_points_wref is not None:
+ for wref in self.compiled_merge_points_wref:
+ looptoken = wref()
+ if looptoken is not None:
+ result.append(looptoken)
+ return result
+
+ def set_compiled_merge_points(self, looptokens):
+ self.compiled_merge_points_wref = [self._makeref(token)
+ for token in looptokens]
+
+ def get_entry_loop_token(self):
+ if self.wref_entry_loop_token is not None:
+ return self.wref_entry_loop_token()
+ return None
+
+ def set_entry_loop_token(self, looptoken):
+ self.wref_entry_loop_token = self._makeref(looptoken)
+
+ def _makeref(self, looptoken):
+ assert looptoken is not None
+ return weakref.ref(looptoken)
# ____________________________________________________________
@@ -165,6 +189,8 @@
"NOT_RPYTHON"
self.warmrunnerdesc = warmrunnerdesc
self.jitdriver_sd = jitdriver_sd
+ if warmrunnerdesc is not None: # for tests
+ self.cpu = warmrunnerdesc.cpu
try:
self.profiler = warmrunnerdesc.metainterp_sd.profiler
except AttributeError: # for tests
@@ -176,7 +202,7 @@
meth(default_value)
def set_param_threshold(self, threshold):
- if threshold < 0:
+ if threshold <= 0:
self.increment_threshold = 0 # never reach the THRESHOLD_LIMIT
return
if threshold < 2:
@@ -209,10 +235,11 @@
else:
raise ValueError("unknown optimizer")
- def set_param_debug(self, value):
- self.debug_level = value
- if self.profiler is not None:
- self.profiler.set_printing(value >= DEBUG_PROFILE)
+ def set_param_loop_longevity(self, value):
+ # note: it's a global parameter, not a per-jitdriver one
+ if (self.warmrunnerdesc is not None and
+ self.warmrunnerdesc.memory_manager is not None): # all for tests
+ self.warmrunnerdesc.memory_manager.set_max_age(value)
def disable_noninlinable_function(self, greenkey):
cell = self.jit_cell_at_key(greenkey)
@@ -225,12 +252,15 @@
def attach_unoptimized_bridge_from_interp(self, greenkey,
entry_loop_token):
cell = self.jit_cell_at_key(greenkey)
- cell.counter = -1
- old_token = cell.entry_loop_token
- cell.entry_loop_token = entry_loop_token
+ old_token = cell.get_entry_loop_token()
+ cell.set_entry_loop_token(entry_loop_token)
+ cell.counter = -1 # valid entry bridge attached
if old_token is not None:
- cpu = self.warmrunnerdesc.cpu
- cpu.redirect_call_assembler(old_token, entry_loop_token)
+ self.cpu.redirect_call_assembler(old_token, entry_loop_token)
+ # entry_loop_token is also kept alive by any loop that used
+ # to point to old_token. Actually freeing old_token early
+ # is a pointless optimization (it is tiny).
+ old_token.record_jump_to(entry_loop_token)
# ----------
@@ -239,7 +269,8 @@
if hasattr(self, 'maybe_compile_and_run'):
return self.maybe_compile_and_run
- metainterp_sd = self.warmrunnerdesc.metainterp_sd
+ warmrunnerdesc = self.warmrunnerdesc
+ metainterp_sd = warmrunnerdesc.metainterp_sd
jitdriver_sd = self.jitdriver_sd
vinfo = jitdriver_sd.virtualizable_info
index_of_virtualizable = jitdriver_sd.index_of_virtualizable
@@ -297,23 +328,27 @@
assert cell.counter == -1
if not confirm_enter_jit(*args):
return
+ loop_token = cell.get_entry_loop_token()
+ if loop_token is None: # it was a weakref that has been freed
+ cell.counter = 0
+ return
# machine code was already compiled for these greenargs
# get the assembler and fill in the boxes
set_future_values(*args[num_green_args:])
- loop_token = cell.entry_loop_token
# ---------- execute assembler ----------
while True: # until interrupted by an exception
metainterp_sd.profiler.start_running()
debug_start("jit-running")
- fail_descr = metainterp_sd.cpu.execute_token(loop_token)
+ fail_descr = warmrunnerdesc.execute_token(loop_token)
debug_stop("jit-running")
metainterp_sd.profiler.end_running()
+ loop_token = None # for test_memmgr
if vinfo is not None:
vinfo.reset_vable_token(virtualizable)
loop_token = fail_descr.handle_fail(metainterp_sd,
jitdriver_sd)
-
+
maybe_compile_and_run._dont_inline_ = True
self.maybe_compile_and_run = maybe_compile_and_run
return maybe_compile_and_run
@@ -459,7 +494,7 @@
warmrunnerdesc = self.warmrunnerdesc
jitdriver_sd = self.jitdriver_sd
- cpu = warmrunnerdesc.cpu
+ cpu = self.cpu
vinfo = jitdriver_sd.virtualizable_info
red_args_types = unrolling_iterable(jitdriver_sd._red_args_types)
#
@@ -508,10 +543,11 @@
if hasattr(self, 'get_location_str'):
return
#
+ warmrunnerdesc = self.warmrunnerdesc
unwrap_greenkey = self.make_unwrap_greenkey()
jit_getter = self.make_jitcell_getter()
jd = self.jitdriver_sd
- cpu = self.warmrunnerdesc.cpu
+ cpu = self.cpu
def can_inline_greenargs(*greenargs):
if can_never_inline(*greenargs):
@@ -529,11 +565,16 @@
def get_assembler_token(greenkey, redboxes):
# 'redboxes' is only used to know the types of red arguments
cell = self.jit_cell_at_key(greenkey)
- if cell.entry_loop_token is None:
+ entry_loop_token = cell.get_entry_loop_token()
+ if entry_loop_token is None:
from pypy.jit.metainterp.compile import compile_tmp_callback
- cell.entry_loop_token = compile_tmp_callback(cpu, jd, greenkey,
- redboxes)
- return cell.entry_loop_token
+ if cell.counter == -1: # used to be a valid entry bridge,
+ cell.counter = 0 # but was freed in the meantime.
+ memmgr = warmrunnerdesc.memory_manager
+ entry_loop_token = compile_tmp_callback(cpu, jd, greenkey,
+ redboxes, memmgr)
+ cell.set_entry_loop_token(entry_loop_token)
+ return entry_loop_token
self.get_assembler_token = get_assembler_token
#
Modified: pypy/branch/out-of-line-guards/pypy/jit/tl/spli/interpreter.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/jit/tl/spli/interpreter.py (original)
+++ pypy/branch/out-of-line-guards/pypy/jit/tl/spli/interpreter.py Thu Dec 9 16:33:59 2010
@@ -105,26 +105,32 @@
self.stack_depth += 1
def pop(self):
- self.stack_depth -= 1
- val = self.value_stack[self.stack_depth]
- self.value_stack[self.stack_depth] = None
+ sd = self.stack_depth - 1
+ assert sd >= 0
+ self.stack_depth = sd
+ val = self.value_stack[sd]
+ self.value_stack[sd] = None
return val
def pop_many(self, n):
return [self.pop() for i in range(n)]
def peek(self):
- return self.value_stack[self.stack_depth - 1]
+ sd = self.stack_depth - 1
+ assert sd >= 0
+ return self.value_stack[sd]
def POP_TOP(self, _, next_instr, code):
self.pop()
return next_instr
def LOAD_FAST(self, name_index, next_instr, code):
+ assert name_index >= 0
self.push(self.locals[name_index])
return next_instr
def STORE_FAST(self, name_index, next_instr, code):
+ assert name_index >= 0
self.locals[name_index] = self.pop()
return next_instr
Modified: pypy/branch/out-of-line-guards/pypy/jit/tl/tl.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/jit/tl/tl.py (original)
+++ pypy/branch/out-of-line-guards/pypy/jit/tl/tl.py Thu Dec 9 16:33:59 2010
@@ -16,32 +16,40 @@
def __init__(self, size):
self = hint(self, access_directly=True, fresh_virtualizable=True)
self.stack = [0] * size
- self.stackpos = 0
+ self.stackpos = 0 # always store a known-nonneg integer here
def append(self, elem):
self.stack[self.stackpos] = elem
self.stackpos += 1
def pop(self):
- self.stackpos -= 1
- if self.stackpos < 0:
+ stackpos = self.stackpos - 1
+ if stackpos < 0:
raise IndexError
- return self.stack[self.stackpos]
+ self.stackpos = stackpos # always store a known-nonneg integer here
+ return self.stack[stackpos]
def pick(self, i):
- self.append(self.stack[self.stackpos - i - 1])
+ n = self.stackpos - i - 1
+ assert n >= 0
+ self.append(self.stack[n])
def put(self, i):
elem = self.pop()
- self.stack[self.stackpos - i - 1] = elem
+ n = self.stackpos - i - 1
+ assert n >= 0
+ self.stack[n] = elem
def roll(self, r):
if r < -1:
i = self.stackpos + r
if i < 0:
raise IndexError
- elem = self.stack[self.stackpos - 1]
+ n = self.stackpos - 1
+ assert n >= 0
+ elem = self.stack[n]
for j in range(self.stackpos - 2, i - 1, -1):
+ assert j >= 0
self.stack[j + 1] = self.stack[j]
self.stack[i] = elem
elif r > 1:
@@ -51,7 +59,9 @@
elem = self.stack[i]
for j in range(i, self.stackpos - 1):
self.stack[j] = self.stack[j + 1]
- self.stack[self.stackpos - 1] = elem
+ n = self.stackpos - 1
+ assert n >= 0
+ self.stack[n] = elem
def make_interp(supports_call):
Modified: pypy/branch/out-of-line-guards/pypy/jit/tool/jitoutput.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/jit/tool/jitoutput.py (original)
+++ pypy/branch/out-of-line-guards/pypy/jit/tool/jitoutput.py Thu Dec 9 16:33:59 2010
@@ -27,6 +27,10 @@
(('nvirtuals',), '^nvirtuals:\s+(\d+)$'),
(('nvholes',), '^nvholes:\s+(\d+)$'),
(('nvreused',), '^nvreused:\s+(\d+)$'),
+ (('total_compiled_loops',), '^Total # of loops:\s+(\d+)$'),
+ (('total_compiled_bridges',), '^Total # of bridges:\s+(\d+)$'),
+ (('total_freed_loops',), '^Freed # of loops:\s+(\d+)$'),
+ (('total_freed_bridges',), '^Freed # of bridges:\s+(\d+)$'),
]
class Ops(object):
Modified: pypy/branch/out-of-line-guards/pypy/jit/tool/test/test_jitoutput.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/jit/tool/test/test_jitoutput.py (original)
+++ pypy/branch/out-of-line-guards/pypy/jit/tool/test/test_jitoutput.py Thu Dec 9 16:33:59 2010
@@ -1,10 +1,11 @@
import py
from pypy.jit.metainterp.warmspot import ll_meta_interp
-from pypy.rlib.jit import JitDriver, DEBUG_PROFILE
+from pypy.rlib.jit import JitDriver
from pypy.jit.backend.llgraph import runner
from pypy.jit.metainterp.jitprof import Profiler, JITPROF_LINES
from pypy.jit.tool.jitoutput import parse_prof
+from pypy.tool.logparser import parse_log, extract_category
def test_really_run():
""" This test checks whether output of jitprof did not change.
@@ -21,13 +22,15 @@
cap = py.io.StdCaptureFD()
try:
ll_meta_interp(f, [10], CPUClass=runner.LLtypeCPU, type_system='lltype',
- ProfilerClass=Profiler, debug_level=DEBUG_PROFILE)
+ ProfilerClass=Profiler)
finally:
out, err = cap.reset()
- err = "\n".join(err.splitlines()[-JITPROF_LINES:])
- print err
- assert err.count("\n") == JITPROF_LINES - 1
- info = parse_prof(err)
+
+ log = parse_log(err.splitlines(True))
+ err_sections = list(extract_category(log, 'jit-summary'))
+ [err1] = err_sections # there should be exactly one jit-summary
+ assert err1.count("\n") == JITPROF_LINES
+ info = parse_prof(err1)
# assert did not crash
# asserts below are a bit delicate, possibly they might be deleted
assert info.tracing_no == 1
@@ -60,6 +63,10 @@
nvirtuals: 13
nvholes: 14
nvreused: 15
+Total # of loops: 100
+Total # of bridges: 300
+Freed # of loops: 99
+Freed # of bridges: 299
'''
def test_parse():
Modified: pypy/branch/out-of-line-guards/pypy/module/__pypy__/__init__.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/module/__pypy__/__init__.py (original)
+++ pypy/branch/out-of-line-guards/pypy/module/__pypy__/__init__.py Thu Dec 9 16:33:59 2010
@@ -11,6 +11,11 @@
'internal_repr' : 'interp_magic.internal_repr',
'bytebuffer' : 'bytebuffer.bytebuffer',
'identity_dict' : 'interp_identitydict.W_IdentityDict',
+ 'debug_start' : 'interp_debug.debug_start',
+ 'debug_print' : 'interp_debug.debug_print',
+ 'debug_stop' : 'interp_debug.debug_stop',
+ 'debug_print_once' : 'interp_debug.debug_print_once',
+ 'builtinify' : 'interp_magic.builtinify',
}
def setup_after_space_initialization(self):
Modified: pypy/branch/out-of-line-guards/pypy/module/__pypy__/interp_magic.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/module/__pypy__/interp_magic.py (original)
+++ pypy/branch/out-of-line-guards/pypy/module/__pypy__/interp_magic.py Thu Dec 9 16:33:59 2010
@@ -51,3 +51,9 @@
return space.newtuple([space.newint(cache.hits.get(name, 0)),
space.newint(cache.misses.get(name, 0))])
mapdict_cache_counter.unwrap_spec = [ObjSpace, str]
+
+def builtinify(space, w_func):
+ from pypy.interpreter.function import Function, BuiltinFunction
+ func = space.interp_w(Function, w_func)
+ bltn = BuiltinFunction(func)
+ return space.wrap(bltn)
Modified: pypy/branch/out-of-line-guards/pypy/module/__pypy__/test/test_special.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/module/__pypy__/test/test_special.py (original)
+++ pypy/branch/out-of-line-guards/pypy/module/__pypy__/test/test_special.py Thu Dec 9 16:33:59 2010
@@ -21,3 +21,18 @@
def test_cpumodel(self):
import __pypy__
assert hasattr(__pypy__, 'cpumodel')
+
+ def test_builtinify(self):
+ import __pypy__
+ class A(object):
+ a = lambda *args: args
+ b = __pypy__.builtinify(a)
+ my = A()
+ assert my.a() == (my,)
+ assert my.b() == ()
+ assert A.a(my) == (my,)
+ assert A.b(my) == (my,)
+ assert A.a.im_func(my) == (my,)
+ assert not hasattr(A.b, 'im_func')
+ assert A.a is not A.__dict__['a']
+ assert A.b is A.__dict__['b']
Modified: pypy/branch/out-of-line-guards/pypy/module/_lsprof/interp_lsprof.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/module/_lsprof/interp_lsprof.py (original)
+++ pypy/branch/out-of-line-guards/pypy/module/_lsprof/interp_lsprof.py Thu Dec 9 16:33:59 2010
@@ -163,8 +163,11 @@
if isinstance(w_arg, Method):
w_function = w_arg.w_function
class_name = w_arg.w_class.getname(space, '?')
- assert isinstance(w_function, Function)
- return "{method '%s' of '%s' objects}" % (w_function.name, class_name)
+ if isinstance(w_function, Function):
+ name = w_function.name
+ else:
+ name = '?'
+ return "{method '%s' of '%s' objects}" % (name, class_name)
elif isinstance(w_arg, Function):
if w_arg.w_module is None:
module = ''
@@ -176,7 +179,8 @@
module += '.'
return '{%s%s}' % (module, w_arg.name)
else:
- return '{!!!unknown!!!}'
+ class_name = space.type(w_arg).getname(space, '?')
+ return "{'%s' object}" % (class_name,)
def lsprof_call(space, w_self, frame, event, w_arg):
assert isinstance(w_self, W_Profiler)
Modified: pypy/branch/out-of-line-guards/pypy/module/_lsprof/test/test_cprofile.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/module/_lsprof/test/test_cprofile.py (original)
+++ pypy/branch/out-of-line-guards/pypy/module/_lsprof/test/test_cprofile.py Thu Dec 9 16:33:59 2010
@@ -2,9 +2,10 @@
from pypy.conftest import gettestobjspace, option
class AppTestCProfile(object):
+ keywords = {}
def setup_class(cls):
- space = gettestobjspace(usemodules=('_lsprof',))
+ space = gettestobjspace(usemodules=('_lsprof',), **cls.keywords)
cls.w_expected_output = space.wrap(expected_output)
cls.space = space
cls.w_file = space.wrap(__file__)
@@ -148,6 +149,12 @@
finally:
sys.path.pop(0)
+
+class AppTestWithDifferentBytecodes(AppTestCProfile):
+ keywords = {'objspace.opcodes.CALL_LIKELY_BUILTIN': True,
+ 'objspace.opcodes.CALL_METHOD': True}
+
+
expected_output = {}
expected_output['print_stats'] = """\
126 function calls (106 primitive calls) in 1.000 CPU seconds
@@ -165,11 +172,11 @@
2 0.000 0.000 0.140 0.070 profilee.py:84(helper2_indirect)
8 0.312 0.039 0.400 0.050 profilee.py:88(helper2)
8 0.064 0.008 0.080 0.010 profilee.py:98(subhelper)
- 4 0.000 0.000 0.000 0.000 {.*append.*}
+ 4 0.000 0.000 0.000 0.000 {method 'append' of 'list' objects}
1 0.000 0.000 0.000 0.000 {.*disable.*}
- 12 0.000 0.000 0.012 0.001 {hasattr.*}
- 8 0.000 0.000 0.000 0.000 {range.*}
- 4 0.000 0.000 0.000 0.000 {sys.exc_info.*}
+ 12 0.000 0.000 0.012 0.001 {hasattr}
+ 8 0.000 0.000 0.000 0.000 {range}
+ 4 0.000 0.000 0.000 0.000 {sys.exc_info}
"""
Modified: pypy/branch/out-of-line-guards/pypy/module/_minimal_curses/__init__.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/module/_minimal_curses/__init__.py (original)
+++ pypy/branch/out-of-line-guards/pypy/module/_minimal_curses/__init__.py Thu Dec 9 16:33:59 2010
@@ -4,7 +4,7 @@
try:
import _minimal_curses as _curses # when running on top of pypy-c
except ImportError:
- import py; py.test.skip("no _curses module") # no _curses at all
+ raise ImportError("no _curses or _minimal_curses module") # no _curses at all
from pypy.interpreter.mixedmodule import MixedModule
from pypy.module._minimal_curses import fficurses
Modified: pypy/branch/out-of-line-guards/pypy/module/_pickle_support/maker.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/module/_pickle_support/maker.py (original)
+++ pypy/branch/out-of-line-guards/pypy/module/_pickle_support/maker.py Thu Dec 9 16:33:59 2010
@@ -67,11 +67,12 @@
return space.wrap(tb)
traceback_new.unwrap_spec = [ObjSpace]
-def generator_new(space, frame, running):
+def generator_new(space, w_frame, running):
+ frame = space.interp_w(PyFrame, w_frame, can_be_None=True)
new_generator = GeneratorIterator(frame)
new_generator.running = running
return space.wrap(new_generator)
-generator_new.unwrap_spec = [ObjSpace, PyFrame, int]
+generator_new.unwrap_spec = [ObjSpace, W_Root, int]
def xrangeiter_new(space, current, remaining, step):
from pypy.module.__builtin__.functional import W_XRangeIterator
Modified: pypy/branch/out-of-line-guards/pypy/module/_stackless/interp_coroutine.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/module/_stackless/interp_coroutine.py (original)
+++ pypy/branch/out-of-line-guards/pypy/module/_stackless/interp_coroutine.py Thu Dec 9 16:33:59 2010
@@ -304,16 +304,19 @@
def w_descr__framestack(space, self):
assert isinstance(self, AppCoroutine)
- index = self.subctx.framestackdepth
- if not index:
- return space.newtuple([])
- items = [None] * index
+ counter = 0
f = self.subctx.topframe
- while index > 0:
- index -= 1
- items[index] = space.wrap(f)
+ while f is not None:
+ counter += 1
f = f.f_backref()
- assert f is None
+ items = [None] * counter
+ f = self.subctx.topframe
+ while f is not None:
+ counter -= 1
+ assert counter >= 0
+ items[counter] = space.wrap(f)
+ f = f.f_backref()
+ assert counter == 0
return space.newtuple(items)
def makeStaticMethod(module, classname, funcname):
Modified: pypy/branch/out-of-line-guards/pypy/module/array/test/test_array.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/module/array/test/test_array.py (original)
+++ pypy/branch/out-of-line-guards/pypy/module/array/test/test_array.py Thu Dec 9 16:33:59 2010
@@ -64,6 +64,7 @@
raises(TypeError, self.array, tc, None)
def test_value_range(self):
+ import sys
values = (-129, 128, -128, 127, 0, 255, -1, 256,
-32768, 32767, -32769, 32768, 65535, 65536,
-2147483647, -2147483648, 2147483647, 4294967295, 4294967296,
@@ -88,7 +89,12 @@
a.append(v)
for i, v in enumerate(ok * 2):
assert a[i] == v
- assert type(a[i]) is pt
+ assert type(a[i]) is pt or (
+ # A special case: we return ints in Array('I') on 64-bits,
+ # whereas CPython returns longs. The difference is
+ # probably acceptable.
+ tc == 'I' and
+ sys.maxint > 2147483647 and type(a[i]) is int)
for v in ok:
a[1] = v
assert a[0] == ok[0]
Modified: pypy/branch/out-of-line-guards/pypy/module/cpyext/__init__.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/module/cpyext/__init__.py (original)
+++ pypy/branch/out-of-line-guards/pypy/module/cpyext/__init__.py Thu Dec 9 16:33:59 2010
@@ -69,6 +69,7 @@
import pypy.module.cpyext.weakrefobject
import pypy.module.cpyext.funcobject
import pypy.module.cpyext.classobject
+import pypy.module.cpyext.pypyintf
# now that all rffi_platform.Struct types are registered, configure them
api.configure_types()
Modified: pypy/branch/out-of-line-guards/pypy/module/cpyext/api.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/module/cpyext/api.py (original)
+++ pypy/branch/out-of-line-guards/pypy/module/cpyext/api.py Thu Dec 9 16:33:59 2010
@@ -321,6 +321,8 @@
'PyCObject_Type', 'init_pycobject',
'PyObject_AsReadBuffer', 'PyObject_AsWriteBuffer', 'PyObject_CheckReadBuffer',
+
+ 'PyStructSequence_InitType', 'PyStructSequence_New',
]
TYPES = {}
GLOBALS = { # this needs to include all prebuilt pto, otherwise segfaults occur
@@ -845,6 +847,7 @@
source_dir / "bufferobject.c",
source_dir / "object.c",
source_dir / "cobject.c",
+ source_dir / "structseq.c",
],
separate_module_sources = [code, struct_source],
export_symbols=export_symbols_eci,
Modified: pypy/branch/out-of-line-guards/pypy/module/cpyext/cdatetime.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/module/cpyext/cdatetime.py (original)
+++ pypy/branch/out-of-line-guards/pypy/module/cpyext/cdatetime.py Thu Dec 9 16:33:59 2010
@@ -4,8 +4,7 @@
from pypy.module.cpyext.api import (
cpython_api, CANNOT_FAIL, cpython_struct, PyObjectFields)
from pypy.module.cpyext.import_ import PyImport_Import
-from pypy.module.cpyext.typeobject import PyTypeObjectPtr, render_immortal
-from pypy.module.cpyext.state import State
+from pypy.module.cpyext.typeobject import PyTypeObjectPtr
from pypy.interpreter.error import OperationError
from pypy.tool.sourcetools import func_renamer
@@ -25,48 +24,26 @@
datetimeAPI = lltype.malloc(PyDateTime_CAPI, flavor='raw',
track_allocation=False)
- if not we_are_translated():
- datetimeAPI_dealloc(space)
- space.fromcache(State).datetimeAPI = datetimeAPI
-
w_datetime = PyImport_Import(space, space.wrap("datetime"))
w_type = space.getattr(w_datetime, space.wrap("date"))
datetimeAPI.c_DateType = rffi.cast(
PyTypeObjectPtr, make_ref(space, w_type))
- render_immortal(datetimeAPI.c_DateType, w_type)
w_type = space.getattr(w_datetime, space.wrap("datetime"))
datetimeAPI.c_DateTimeType = rffi.cast(
PyTypeObjectPtr, make_ref(space, w_type))
- render_immortal(datetimeAPI.c_DateTimeType, w_type)
w_type = space.getattr(w_datetime, space.wrap("time"))
datetimeAPI.c_TimeType = rffi.cast(
PyTypeObjectPtr, make_ref(space, w_type))
- render_immortal(datetimeAPI.c_TimeType, w_type)
w_type = space.getattr(w_datetime, space.wrap("timedelta"))
datetimeAPI.c_DeltaType = rffi.cast(
PyTypeObjectPtr, make_ref(space, w_type))
- render_immortal(datetimeAPI.c_DeltaType, w_type)
return datetimeAPI
-def datetimeAPI_dealloc(space):
- "Used in tests only, to please the refcount checker"
- if we_are_translated():
- return
- datetimeAPI = space.fromcache(State).datetimeAPI
- if datetimeAPI is None:
- return
- space.fromcache(State).datetimeAPI = None
- Py_DecRef(space, rffi.cast(PyObject, datetimeAPI.c_DateType))
- Py_DecRef(space, rffi.cast(PyObject, datetimeAPI.c_DateTimeType))
- Py_DecRef(space, rffi.cast(PyObject, datetimeAPI.c_TimeType))
- Py_DecRef(space, rffi.cast(PyObject, datetimeAPI.c_DeltaType))
- lltype.free(datetimeAPI, flavor='raw')
-
PyDateTime_Date = PyObject
PyDateTime_Time = PyObject
PyDateTime_DateTime = PyObject
Modified: pypy/branch/out-of-line-guards/pypy/module/cpyext/include/Python.h
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/module/cpyext/include/Python.h (original)
+++ pypy/branch/out-of-line-guards/pypy/module/cpyext/include/Python.h Thu Dec 9 16:33:59 2010
@@ -8,6 +8,8 @@
# include <stddef.h>
# include <limits.h>
# include <math.h>
+# include <errno.h>
+# include <unistd.h>
# define Py_DEPRECATED(VERSION_UNUSED) __attribute__((__deprecated__))
# define PyAPI_FUNC(RTYPE) RTYPE
# define PyAPI_DATA(RTYPE) extern RTYPE
@@ -103,6 +105,7 @@
#include "sliceobject.h"
#include "datetime.h"
#include "pystate.h"
+#include "fileobject.h"
// XXX This shouldn't be included here
#include "structmember.h"
@@ -120,4 +123,8 @@
#define PyDoc_STR(str) ""
#endif
+/* PyPy does not implement --with-fpectl */
+#define PyFPE_START_PROTECT(err_string, leave_stmt)
+#define PyFPE_END_PROTECT(v)
+
#endif
Modified: pypy/branch/out-of-line-guards/pypy/module/cpyext/intobject.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/module/cpyext/intobject.py (original)
+++ pypy/branch/out-of-line-guards/pypy/module/cpyext/intobject.py Thu Dec 9 16:33:59 2010
@@ -1,5 +1,6 @@
from pypy.rpython.lltypesystem import rffi, lltype
+from pypy.interpreter.error import OperationError
from pypy.module.cpyext.api import (cpython_api, PyObject, CANNOT_FAIL,
build_type_checkers, Py_ssize_t)
@@ -19,6 +20,9 @@
already one, and then return its value. If there is an error, -1 is
returned, and the caller should check PyErr_Occurred() to find out whether
there was an error, or whether the value just happened to be -1."""
+ if w_obj is None:
+ raise OperationError(space.w_TypeError,
+ space.wrap("an integer is required, got NULL"))
return space.int_w(space.int(w_obj))
@cpython_api([PyObject], lltype.Unsigned, error=-1)
@@ -26,6 +30,9 @@
"""Return a C unsigned long representation of the contents of pylong.
If pylong is greater than ULONG_MAX, an OverflowError is
raised."""
+ if w_obj is None:
+ raise OperationError(space.w_TypeError,
+ space.wrap("an integer is required, got NULL"))
return space.uint_w(space.int(w_obj))
@cpython_api([PyObject], lltype.Signed, error=CANNOT_FAIL)
@@ -39,6 +46,9 @@
PyLongObject, if it is not already one, and then return its value as
Py_ssize_t.
"""
+ if w_obj is None:
+ raise OperationError(space.w_TypeError,
+ space.wrap("an integer is required, got NULL"))
return space.int_w(w_obj) # XXX this is wrong on win64
@cpython_api([Py_ssize_t], PyObject)
@@ -48,4 +58,3 @@
returned.
"""
return space.wrap(ival) # XXX this is wrong on win64
-
Modified: pypy/branch/out-of-line-guards/pypy/module/cpyext/object.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/module/cpyext/object.py (original)
+++ pypy/branch/out-of-line-guards/pypy/module/cpyext/object.py Thu Dec 9 16:33:59 2010
@@ -2,12 +2,13 @@
from pypy.module.cpyext.api import (
cpython_api, generic_cpy_call, CANNOT_FAIL, Py_ssize_t, Py_ssize_tP,
PyVarObject, Py_TPFLAGS_HEAPTYPE, Py_LT, Py_LE, Py_EQ, Py_NE, Py_GT,
- Py_GE, CONST_STRING, FILEP, fwrite)
+ Py_GE, CONST_STRING, FILEP, fwrite, build_type_checkers)
from pypy.module.cpyext.pyobject import (
PyObject, PyObjectP, create_ref, from_ref, Py_IncRef, Py_DecRef,
track_reference, get_typedescr, RefcountState)
from pypy.module.cpyext.typeobject import PyTypeObjectPtr
from pypy.module.cpyext.pyerrors import PyErr_NoMemory, PyErr_BadInternalCall
+from pypy.module._file.interp_file import W_File
from pypy.objspace.std.objectobject import W_ObjectObject
from pypy.objspace.std.typeobject import W_TypeObject
from pypy.interpreter.error import OperationError
@@ -428,6 +429,34 @@
rffi.free_nonmovingbuffer(data, buf)
return 0
+PyFile_Check, PyFile_CheckExact = build_type_checkers("File", W_File)
+
+ at cpython_api([PyObject, rffi.INT_real], PyObject)
+def PyFile_GetLine(space, w_obj, n):
+ """
+ Equivalent to p.readline([n]), this function reads one line from the
+ object p. p may be a file object or any object with a readline()
+ method. If n is 0, exactly one line is read, regardless of the length of
+ the line. If n is greater than 0, no more than n bytes will be read
+ from the file; a partial line can be returned. In both cases, an empty string
+ is returned if the end of the file is reached immediately. If n is less than
+ 0, however, one line is read regardless of length, but EOFError is
+ raised if the end of the file is reached immediately."""
+ try:
+ w_readline = space.getattr(w_obj, space.wrap('readline'))
+ except OperationError:
+ raise OperationError(
+ space.w_TypeError, space.wrap(
+ "argument must be a file, or have a readline() method."))
+
+ n = rffi.cast(lltype.Signed, n)
+ if space.is_true(space.gt(space.wrap(n), space.wrap(0))):
+ return space.call_function(w_readline, space.wrap(n))
+ elif space.is_true(space.lt(space.wrap(n), space.wrap(0))):
+ return space.call_function(w_readline)
+ else:
+ # XXX Raise EOFError as specified
+ return space.call_function(w_readline)
@cpython_api([CONST_STRING, CONST_STRING], PyObject)
def PyFile_FromString(space, filename, mode):
"""
@@ -437,4 +466,3 @@
w_filename = space.wrap(rffi.charp2str(filename))
w_mode = space.wrap(rffi.charp2str(mode))
return space.call_method(space.builtin, 'file', w_filename, w_mode)
-
Modified: pypy/branch/out-of-line-guards/pypy/module/cpyext/pyerrors.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/module/cpyext/pyerrors.py (original)
+++ pypy/branch/out-of-line-guards/pypy/module/cpyext/pyerrors.py Thu Dec 9 16:33:59 2010
@@ -5,7 +5,7 @@
from pypy.module.cpyext.api import cpython_api, CANNOT_FAIL, CONST_STRING
from pypy.module.exceptions.interp_exceptions import W_RuntimeWarning
from pypy.module.cpyext.pyobject import (
- PyObject, PyObjectP, make_ref, Py_DecRef, borrow_from)
+ PyObject, PyObjectP, make_ref, from_ref, Py_DecRef, borrow_from)
from pypy.module.cpyext.state import State
from pypy.module.cpyext.import_ import PyImport_Import
from pypy.rlib.rposix import get_errno
@@ -80,6 +80,21 @@
Py_DecRef(space, w_value)
Py_DecRef(space, w_traceback)
+ at cpython_api([PyObjectP, PyObjectP, PyObjectP], lltype.Void)
+def PyErr_NormalizeException(space, exc_p, val_p, tb_p):
+ """Under certain circumstances, the values returned by PyErr_Fetch() below
+ can be "unnormalized", meaning that *exc is a class object but *val is
+ not an instance of the same class. This function can be used to instantiate
+ the class in that case. If the values are already normalized, nothing happens.
+ The delayed normalization is implemented to improve performance."""
+ operr = OperationError(from_ref(space, exc_p[0]),
+ from_ref(space, val_p[0]))
+ operr.normalize_exception(space)
+ Py_DecRef(space, exc_p[0])
+ Py_DecRef(space, val_p[0])
+ exc_p[0] = make_ref(space, operr.w_type)
+ val_p[0] = make_ref(space, operr.get_w_value(space))
+
@cpython_api([], lltype.Void)
def PyErr_BadArgument(space):
"""This is a shorthand for PyErr_SetString(PyExc_TypeError, message), where
@@ -114,10 +129,29 @@
function around a system call can write return PyErr_SetFromErrno(type);
when the system call returns an error.
Return value: always NULL."""
+ PyErr_SetFromErrnoWithFilename(space, w_type,
+ lltype.nullptr(rffi.CCHARP.TO))
+
+ at cpython_api([PyObject, rffi.CCHARP], PyObject)
+def PyErr_SetFromErrnoWithFilename(space, w_type, llfilename):
+ """Similar to PyErr_SetFromErrno(), with the additional behavior that if
+ filename is not NULL, it is passed to the constructor of type as a third
+ parameter. In the case of exceptions such as IOError and OSError,
+ this is used to define the filename attribute of the exception instance.
+ Return value: always NULL."""
# XXX Doesn't actually do anything with PyErr_CheckSignals.
errno = get_errno()
msg = os.strerror(errno)
- w_error = space.call_function(w_type, space.wrap(errno), space.wrap(msg))
+ if llfilename:
+ w_filename = rffi.charp2str(llfilename)
+ w_error = space.call_function(w_type,
+ space.wrap(errno),
+ space.wrap(msg),
+ space.wrap(w_filename))
+ else:
+ w_error = space.call_function(w_type,
+ space.wrap(errno),
+ space.wrap(msg))
raise OperationError(w_type, w_error)
@cpython_api([], rffi.INT_real, error=-1)
Modified: pypy/branch/out-of-line-guards/pypy/module/cpyext/pythonrun.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/module/cpyext/pythonrun.py (original)
+++ pypy/branch/out-of-line-guards/pypy/module/cpyext/pythonrun.py Thu Dec 9 16:33:59 2010
@@ -1,6 +1,16 @@
from pypy.rpython.lltypesystem import rffi, lltype
from pypy.module.cpyext.api import cpython_api, CANNOT_FAIL
+from pypy.module.cpyext.state import State
@cpython_api([], rffi.INT_real, error=CANNOT_FAIL)
def Py_IsInitialized(space):
return 1
+
+ at cpython_api([], rffi.CCHARP, error=CANNOT_FAIL)
+def Py_GetProgramName(space):
+ """
+ Return the program name set with Py_SetProgramName(), or the default.
+ The returned string points into static storage; the caller should not modify its
+ value."""
+ return space.fromcache(State).get_programname()
+
Modified: pypy/branch/out-of-line-guards/pypy/module/cpyext/sequence.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/module/cpyext/sequence.py (original)
+++ pypy/branch/out-of-line-guards/pypy/module/cpyext/sequence.py Thu Dec 9 16:33:59 2010
@@ -116,6 +116,14 @@
This is the equivalent of the Python expression o1 + o2."""
return space.add(w_o1, w_o2)
+ at cpython_api([PyObject, PyObject], rffi.INT_real, error=-1)
+def PySequence_Contains(space, w_obj, w_value):
+ """Determine if o contains value. If an item in o is equal to value,
+ return 1, otherwise return 0. On error, return -1. This is
+ equivalent to the Python expression value in o."""
+ w_res = space.contains(w_obj, w_value)
+ return space.int_w(w_res)
+
@cpython_api([PyObject], PyObject)
def PySeqIter_New(space, w_seq):
"""Return an iterator that works with a general sequence object, seq. The
Modified: pypy/branch/out-of-line-guards/pypy/module/cpyext/slotdefs.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/module/cpyext/slotdefs.py (original)
+++ pypy/branch/out-of-line-guards/pypy/module/cpyext/slotdefs.py Thu Dec 9 16:33:59 2010
@@ -6,7 +6,7 @@
unaryfunc, wrapperfunc, ternaryfunc, PyTypeObjectPtr, binaryfunc,
getattrfunc, setattrofunc, lenfunc, ssizeargfunc, ssizessizeargfunc,
ssizeobjargproc, iternextfunc, initproc, richcmpfunc, hashfunc,
- descrgetfunc, descrsetfunc)
+ descrgetfunc, descrsetfunc, objobjproc)
from pypy.module.cpyext.pyobject import from_ref
from pypy.module.cpyext.pyerrors import PyErr_Occurred
from pypy.module.cpyext.state import State
@@ -156,6 +156,15 @@
if rffi.cast(lltype.Signed, res) == -1:
space.fromcache(State).check_and_raise_exception(always=True)
+def wrap_objobjproc(space, w_self, w_args, func):
+ func_target = rffi.cast(objobjproc, func)
+ check_num_args(space, w_args, 1)
+ w_value, = space.fixedview(w_args)
+ res = generic_cpy_call(space, func_target, w_self, w_value)
+ if rffi.cast(lltype.Signed, res) == -1:
+ space.fromcache(State).check_and_raise_exception(always=True)
+ return space.wrap(res)
+
def wrap_ssizessizeargfunc(space, w_self, w_args, func):
func_target = rffi.cast(ssizessizeargfunc, func)
check_num_args(space, w_args, 2)
Modified: pypy/branch/out-of-line-guards/pypy/module/cpyext/src/getargs.c
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/module/cpyext/src/getargs.c (original)
+++ pypy/branch/out-of-line-guards/pypy/module/cpyext/src/getargs.c Thu Dec 9 16:33:59 2010
@@ -453,6 +453,7 @@
strncpy(msgbuf, "is not retrievable", bufsize);
return msgbuf;
}
+ PyPy_Borrow(arg, item);
msg = convertitem(item, &format, p_va, flags, levels+1,
msgbuf, bufsize, freelist);
/* PySequence_GetItem calls tp->sq_item, which INCREFs */
Modified: pypy/branch/out-of-line-guards/pypy/module/cpyext/state.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/module/cpyext/state.py (original)
+++ pypy/branch/out-of-line-guards/pypy/module/cpyext/state.py Thu Dec 9 16:33:59 2010
@@ -5,11 +5,10 @@
class State:
- datetimeAPI = None # used in tests
-
def __init__(self, space):
self.space = space
self.reset()
+ self.programname = lltype.nullptr(rffi.CCHARP.TO)
def reset(self):
from pypy.module.cpyext.modsupport import PyMethodDef
@@ -43,3 +42,16 @@
if always:
raise OperationError(self.space.w_SystemError, self.space.wrap(
"Function returned an error result without setting an exception"))
+
+ def get_programname(self):
+ if not self.programname:
+ space = self.space
+ argv = space.sys.get('argv')
+ if space.int_w(space.len(argv)):
+ argv0 = space.getitem(argv, space.wrap(0))
+ progname = space.str_w(argv0)
+ else:
+ progname = "pypy"
+ self.programname = rffi.str2charp(progname)
+ lltype.render_immortal(self.programname)
+ return self.programname
Modified: pypy/branch/out-of-line-guards/pypy/module/cpyext/stubs.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/module/cpyext/stubs.py (original)
+++ pypy/branch/out-of-line-guards/pypy/module/cpyext/stubs.py Thu Dec 9 16:33:59 2010
@@ -668,24 +668,6 @@
"""
raise NotImplementedError
- at cpython_api([PyObjectP, PyObjectP, PyObjectP], lltype.Void)
-def PyErr_NormalizeException(space, exc, val, tb):
- """Under certain circumstances, the values returned by PyErr_Fetch() below
- can be "unnormalized", meaning that *exc is a class object but *val is
- not an instance of the same class. This function can be used to instantiate
- the class in that case. If the values are already normalized, nothing happens.
- The delayed normalization is implemented to improve performance."""
- raise NotImplementedError
-
- at cpython_api([PyObject, rffi.CCHARP], PyObject)
-def PyErr_SetFromErrnoWithFilename(space, type, filename):
- """Similar to PyErr_SetFromErrno(), with the additional behavior that if
- filename is not NULL, it is passed to the constructor of type as a third
- parameter. In the case of exceptions such as IOError and OSError,
- this is used to define the filename attribute of the exception instance.
- Return value: always NULL."""
- raise NotImplementedError
-
@cpython_api([rffi.INT_real], PyObject)
def PyErr_SetFromWindowsErr(space, ierr):
"""This is a convenience function to raise WindowsError. If called with
@@ -809,21 +791,6 @@
successful invocation of Py_EnterRecursiveCall()."""
raise NotImplementedError
- at cpython_api([PyObject], rffi.INT_real, error=CANNOT_FAIL)
-def PyFile_Check(space, p):
- """Return true if its argument is a PyFileObject or a subtype of
- PyFileObject.
-
- Allowed subtypes to be accepted."""
- raise NotImplementedError
-
- at cpython_api([PyObject], rffi.INT_real, error=CANNOT_FAIL)
-def PyFile_CheckExact(space, p):
- """Return true if its argument is a PyFileObject, but not a subtype of
- PyFileObject.
- """
- raise NotImplementedError
-
@cpython_api([FILE, rffi.CCHARP, rffi.CCHARP, rffi.INT_real], PyObject)
def PyFile_FromFile(space, fp, name, mode, close):
"""Create a new PyFileObject from the already-open standard C file
@@ -857,22 +824,6 @@
"""
raise NotImplementedError
- at cpython_api([PyObject, rffi.INT_real], PyObject)
-def PyFile_GetLine(space, p, n):
- """
-
-
-
- Equivalent to p.readline([n]), this function reads one line from the
- object p. p may be a file object or any object with a readline()
- method. If n is 0, exactly one line is read, regardless of the length of
- the line. If n is greater than 0, no more than n bytes will be read
- from the file; a partial line can be returned. In both cases, an empty string
- is returned if the end of the file is reached immediately. If n is less than
- 0, however, one line is read regardless of length, but EOFError is
- raised if the end of the file is reached immediately."""
- raise NotImplementedError
-
@cpython_api([PyObject], PyObject)
def PyFile_Name(space, p):
"""Return the name of the file specified by p as a string object."""
@@ -1431,17 +1382,6 @@
raise NotImplementedError
@cpython_api([], rffi.CCHARP, error=CANNOT_FAIL)
-def Py_GetProgramName(space, ):
- """
-
-
-
- Return the program name set with Py_SetProgramName(), or the default.
- The returned string points into static storage; the caller should not modify its
- value."""
- raise NotImplementedError
-
- at cpython_api([], rffi.CCHARP, error=CANNOT_FAIL)
def Py_GetPrefix(space, ):
"""Return the prefix for installed platform-independent files. This is derived
through a number of complicated rules from the program name set with
@@ -2289,13 +2229,6 @@
in your code for properly supporting 64-bit systems."""
raise NotImplementedError
- at cpython_api([PyObject, PyObject], rffi.INT_real, error=-1)
-def PySequence_Contains(space, o, value):
- """Determine if o contains value. If an item in o is equal to value,
- return 1, otherwise return 0. On error, return -1. This is
- equivalent to the Python expression value in o."""
- raise NotImplementedError
-
@cpython_api([PyObject, PyObject], Py_ssize_t, error=-1)
def PySequence_Index(space, o, value):
"""Return the first index i for which o[i] == value. On error, return
Modified: pypy/branch/out-of-line-guards/pypy/module/cpyext/test/test_arraymodule.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/module/cpyext/test/test_arraymodule.py (original)
+++ pypy/branch/out-of-line-guards/pypy/module/cpyext/test/test_arraymodule.py Thu Dec 9 16:33:59 2010
@@ -14,6 +14,7 @@
arr.append(4)
assert arr.tolist() == [1, 2, 3, 4]
assert len(arr) == 4
+ self.cleanup_references()
def test_iter(self):
module = self.import_module(name='array')
@@ -22,6 +23,7 @@
for i in arr:
sum += i
assert sum == 6
+ self.cleanup_references()
def test_index(self):
module = self.import_module(name='array')
@@ -32,6 +34,7 @@
assert arr.tolist() == [1,2,4]
arr[2] = 99
assert arr.tolist() == [1,2,99]
+ self.cleanup_references()
def test_slice_get(self):
module = self.import_module(name='array')
@@ -40,3 +43,4 @@
assert arr[1:].tolist() == [2,3,4]
assert arr[:2].tolist() == [1,2]
assert arr[1:3].tolist() == [2,3]
+ self.cleanup_references()
Modified: pypy/branch/out-of-line-guards/pypy/module/cpyext/test/test_cpyext.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/module/cpyext/test/test_cpyext.py (original)
+++ pypy/branch/out-of-line-guards/pypy/module/cpyext/test/test_cpyext.py Thu Dec 9 16:33:59 2010
@@ -1,10 +1,12 @@
import sys
+import weakref
import os.path
import py
from pypy.conftest import gettestobjspace
from pypy.interpreter.error import OperationError
+from pypy.interpreter.gateway import interp2app
from pypy.rpython.lltypesystem import rffi, lltype, ll2ctypes
from pypy.translator.tool.cbuild import ExternalCompilationInfo
from pypy.translator import platform
@@ -79,6 +81,23 @@
self.frozen_ll2callocations = set(ll2ctypes.ALLOCATED.values())
class LeakCheckingTest(object):
+ @staticmethod
+ def cleanup_references(space):
+ state = space.fromcache(RefcountState)
+
+ import gc; gc.collect()
+ # Clear all lifelines, objects won't resurrect
+ for w_obj, obj in state.lifeline_dict._dict.items():
+ if w_obj not in state.py_objects_w2r:
+ state.lifeline_dict.set(w_obj, None)
+ del obj
+ import gc; gc.collect()
+
+ for w_obj in state.non_heaptypes_w:
+ Py_DecRef(space, w_obj)
+ state.non_heaptypes_w[:] = []
+ state.reset_borrowed_references()
+
def check_and_print_leaks(self):
# check for sane refcnts
import gc
@@ -89,13 +108,6 @@
lost_objects_w = identity_dict()
lost_objects_w.update((key, None) for key in self.frozen_refcounts.keys())
- # Clear all lifelines, objects won't resurrect
- for w_obj, obj in state.lifeline_dict._dict.items():
- if w_obj not in state.py_objects_w2r:
- state.lifeline_dict.set(w_obj, None)
- del obj
- gc.collect()
-
for w_obj, obj in state.py_objects_w2r.iteritems():
base_refcnt = self.frozen_refcounts.get(w_obj)
delta = obj.c_ob_refcnt
@@ -105,7 +117,12 @@
if delta != 0:
leaking = True
print >>sys.stderr, "Leaking %r: %i references" % (w_obj, delta)
- lifeline = state.lifeline_dict.get(w_obj)
+ try:
+ weakref.ref(w_obj)
+ except TypeError:
+ lifeline = None
+ else:
+ lifeline = state.lifeline_dict.get(w_obj)
if lifeline is not None:
refcnt = lifeline.pyo.c_ob_refcnt
if refcnt > 0:
@@ -137,6 +154,8 @@
state = cls.space.fromcache(RefcountState)
state.non_heaptypes_w[:] = []
+ cls.w_cleanup_references = cls.space.wrap(interp2app(cls.cleanup_references))
+
def compile_module(self, name, **kwds):
"""
Build an extension module linked against the cpyext api library.
@@ -256,13 +275,7 @@
def teardown_method(self, func):
for name in self.imported_module_names:
self.unimport_module(name)
- state = self.space.fromcache(RefcountState)
- for w_obj in state.non_heaptypes_w:
- Py_DecRef(self.space, w_obj)
- state.non_heaptypes_w[:] = []
- state.reset_borrowed_references()
- from pypy.module.cpyext import cdatetime
- cdatetime.datetimeAPI_dealloc(self.space)
+ self.cleanup_references(self.space)
if self.check_and_print_leaks():
assert False, "Test leaks or loses object(s)."
@@ -669,3 +682,19 @@
assert mod.get_names() == ('cell', 'module', 'property',
'staticmethod',
'builtin_function_or_method')
+
+ def test_get_programname(self):
+ mod = self.import_extension('foo', [
+ ('get_programname', 'METH_NOARGS',
+ '''
+ char* name1 = Py_GetProgramName();
+ char* name2 = Py_GetProgramName();
+ if (name1 != name2)
+ Py_RETURN_FALSE;
+ return PyString_FromString(name1);
+ '''
+ ),
+ ])
+ p = mod.get_programname()
+ print p
+ assert 'py' in p
Modified: pypy/branch/out-of-line-guards/pypy/module/cpyext/test/test_datetime.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/module/cpyext/test/test_datetime.py (original)
+++ pypy/branch/out-of-line-guards/pypy/module/cpyext/test/test_datetime.py Thu Dec 9 16:33:59 2010
@@ -92,9 +92,20 @@
PyDateTimeAPI->TimeType,
PyDateTimeAPI->DeltaType);
"""),
+ ("clear_types", "METH_NOARGS",
+ """
+ Py_DECREF(PyDateTimeAPI->DateType);
+ Py_DECREF(PyDateTimeAPI->DateTimeType);
+ Py_DECREF(PyDateTimeAPI->TimeType);
+ Py_DECREF(PyDateTimeAPI->DeltaType);
+ Py_RETURN_NONE;
+ """
+ )
])
import datetime
assert module.get_types() == (datetime.date,
datetime.datetime,
datetime.time,
datetime.timedelta)
+ module.clear_types()
+ self.cleanup_references()
Modified: pypy/branch/out-of-line-guards/pypy/module/cpyext/test/test_intobject.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/module/cpyext/test/test_intobject.py (original)
+++ pypy/branch/out-of-line-guards/pypy/module/cpyext/test/test_intobject.py Thu Dec 9 16:33:59 2010
@@ -19,6 +19,10 @@
assert api.PyErr_Occurred() is space.w_TypeError
api.PyErr_Clear()
+ assert api.PyInt_AsLong(None) == -1
+ assert api.PyErr_Occurred() is space.w_TypeError
+ api.PyErr_Clear()
+
assert api.PyInt_AsUnsignedLong(space.wrap(sys.maxint)) == sys.maxint
assert api.PyInt_AsUnsignedLong(space.wrap(-5)) == sys.maxint * 2 + 1
assert api.PyErr_Occurred() is space.w_ValueError
Modified: pypy/branch/out-of-line-guards/pypy/module/cpyext/test/test_object.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/module/cpyext/test/test_object.py (original)
+++ pypy/branch/out-of-line-guards/pypy/module/cpyext/test/test_object.py Thu Dec 9 16:33:59 2010
@@ -4,7 +4,7 @@
from pypy.module.cpyext.test.test_cpyext import AppTestCpythonExtensionBase
from pypy.rpython.lltypesystem import rffi, lltype
from pypy.module.cpyext.api import Py_LT, Py_LE, Py_NE, Py_EQ,\
- Py_GE, Py_GT
+ Py_GE, Py_GT, fopen, fclose, fwrite
from pypy.tool.udir import udir
class TestObject(BaseApiTest):
@@ -188,10 +188,45 @@
rffi.free_charp(filename)
rffi.free_charp(mode)
+ assert api.PyFile_Check(w_file)
+ assert api.PyFile_CheckExact(w_file)
+ assert not api.PyFile_Check(space.wrap("text"))
+
space.call_method(w_file, "write", space.wrap("text"))
space.call_method(w_file, "close")
assert (udir / "_test_file").read() == "text"
+ def test_file_getline(self, space, api):
+ filename = rffi.str2charp(str(udir / "_test_file"))
+
+ mode = rffi.str2charp("w")
+ w_file = api.PyFile_FromString(filename, mode)
+ space.call_method(w_file, "write",
+ space.wrap("line1\nline2\nline3\nline4"))
+ space.call_method(w_file, "close")
+
+ rffi.free_charp(mode)
+ mode = rffi.str2charp("r")
+ w_file = api.PyFile_FromString(filename, mode)
+ rffi.free_charp(filename)
+ rffi.free_charp(mode)
+
+ w_line = api.PyFile_GetLine(w_file, 0)
+ assert space.str_w(w_line) == "line1\n"
+
+ w_line = api.PyFile_GetLine(w_file, 4)
+ assert space.str_w(w_line) == "line"
+
+ w_line = api.PyFile_GetLine(w_file, 0)
+ assert space.str_w(w_line) == "2\n"
+
+ # XXX We ought to raise an EOFError here, but don't
+ w_line = api.PyFile_GetLine(w_file, -1)
+ # assert api.PyErr_Occurred() is space.w_EOFError
+ assert space.str_w(w_line) == "line3\n"
+
+ space.call_method(w_file, "close")
+
class AppTestObject(AppTestCpythonExtensionBase):
def setup_class(cls):
AppTestCpythonExtensionBase.setup_class.im_func(cls)
Modified: pypy/branch/out-of-line-guards/pypy/module/cpyext/test/test_pyerrors.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/module/cpyext/test/test_pyerrors.py (original)
+++ pypy/branch/out-of-line-guards/pypy/module/cpyext/test/test_pyerrors.py Thu Dec 9 16:33:59 2010
@@ -129,6 +129,41 @@
])
assert module.check_error()
+
+ def test_normalize(self):
+ module = self.import_extension('foo', [
+ ("check_error", "METH_NOARGS",
+ '''
+ PyObject *type, *val, *tb;
+ PyErr_SetString(PyExc_TypeError, "message");
+
+ PyErr_Fetch(&type, &val, &tb);
+ if (type != PyExc_TypeError)
+ Py_RETURN_FALSE;
+ if (!PyString_Check(val))
+ Py_RETURN_FALSE;
+ /* Normalize */
+ PyErr_NormalizeException(&type, &val, &tb);
+ if (type != PyExc_TypeError)
+ Py_RETURN_FALSE;
+ if (val->ob_type != PyExc_TypeError)
+ Py_RETURN_FALSE;
+
+ /* Normalize again */
+ PyErr_NormalizeException(&type, &val, &tb);
+ if (type != PyExc_TypeError)
+ Py_RETURN_FALSE;
+ if (val->ob_type != PyExc_TypeError)
+ Py_RETURN_FALSE;
+
+ PyErr_Restore(type, val, tb);
+ PyErr_Clear();
+ Py_RETURN_TRUE;
+ '''
+ ),
+ ])
+ assert module.check_error()
+
def test_SetFromErrno(self):
import sys
if sys.platform != 'win32':
@@ -149,3 +184,26 @@
except OSError, e:
assert e.errno == errno.EBADF
assert e.strerror == os.strerror(errno.EBADF)
+ assert e.filename == None
+
+ def test_SetFromErrnoWithFilename(self):
+ import sys
+ if sys.platform != 'win32':
+ skip("callbacks through ll2ctypes modify errno")
+ import errno, os
+
+ module = self.import_extension('foo', [
+ ("set_from_errno", "METH_NOARGS",
+ '''
+ errno = EBADF;
+ PyErr_SetFromErrnoWithFilename(PyExc_OSError, "blyf");
+ return NULL;
+ '''),
+ ],
+ prologue="#include <errno.h>")
+ try:
+ module.set_from_errno()
+ except OSError, e:
+ assert e.filename == "blyf"
+ assert e.errno == errno.EBADF
+ assert e.strerror == os.strerror(errno.EBADF)
Modified: pypy/branch/out-of-line-guards/pypy/module/cpyext/test/test_sequence.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/module/cpyext/test/test_sequence.py (original)
+++ pypy/branch/out-of-line-guards/pypy/module/cpyext/test/test_sequence.py Thu Dec 9 16:33:59 2010
@@ -70,3 +70,11 @@
assert space.unwrap(space.next(w_iter)) == 2
exc = raises(OperationError, space.next, w_iter)
assert exc.value.match(space, space.w_StopIteration)
+
+ def test_contains(self, space, api):
+ w_t = space.wrap((1, 'ha'))
+ assert api.PySequence_Contains(w_t, space.wrap(u'ha'))
+ assert not api.PySequence_Contains(w_t, space.wrap(2))
+ assert api.PySequence_Contains(space.w_None, space.wrap(2)) == -1
+ assert api.PyErr_Occurred()
+ api.PyErr_Clear()
Modified: pypy/branch/out-of-line-guards/pypy/module/cpyext/test/test_typeobject.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/module/cpyext/test/test_typeobject.py (original)
+++ pypy/branch/out-of-line-guards/pypy/module/cpyext/test/test_typeobject.py Thu Dec 9 16:33:59 2010
@@ -20,6 +20,7 @@
assert type(obj) is module.fooType
print "type of obj has type", type(type(obj))
print "type of type of obj has type", type(type(type(obj)))
+ self.cleanup_references()
def test_typeobject_method_descriptor(self):
module = self.import_module(name='foo')
@@ -38,6 +39,7 @@
print obj.foo
assert obj.foo == 42
assert obj.int_member == obj.foo
+ self.cleanup_references()
def test_typeobject_data_member(self):
module = self.import_module(name='foo')
@@ -54,6 +56,7 @@
raises(SystemError, "obj.broken_member = 42")
assert module.fooType.broken_member.__doc__ is None
assert module.fooType.object_member.__doc__ == "A Python object."
+ self.cleanup_references()
def test_typeobject_object_member(self):
module = self.import_module(name='foo')
@@ -74,6 +77,7 @@
obj.set_foo = 32
assert obj.foo == 32
+ self.cleanup_references()
def test_typeobject_string_member(self):
module = self.import_module(name='foo')
@@ -91,6 +95,7 @@
assert obj.char_member == "a"
raises(TypeError, "obj.char_member = 'spam'")
raises(TypeError, "obj.char_member = 42")
+ self.cleanup_references()
def test_staticmethod(self):
module = self.import_module(name="foo")
@@ -98,6 +103,7 @@
assert obj.foo == 42
obj2 = obj.create()
assert obj2.foo == 42
+ self.cleanup_references()
def test_new(self):
module = self.import_module(name='foo')
@@ -118,7 +124,8 @@
return self
assert fuu2(u"abc").baz().escape()
raises(TypeError, module.fooType.object_member.__get__, 1)
-
+ self.cleanup_references()
+
def test_init(self):
module = self.import_module(name="foo")
newobj = module.FuuType()
@@ -137,6 +144,7 @@
newobj = Fuu2()
assert newobj.get_val() == 42
assert newobj.foobar == 32
+ self.cleanup_references()
def test_metatype(self):
module = self.import_module(name='foo')
@@ -145,6 +153,7 @@
assert isinstance(x, type)
assert isinstance(x, module.MetaType)
x()
+ self.cleanup_references()
def test_metaclass_compatible(self):
# metaclasses should not conflict here
@@ -153,7 +162,9 @@
assert type(module.fooType).__mro__ == (type, object)
y = module.MetaType('other', (module.fooType,), {})
assert isinstance(y, module.MetaType)
- y()
+ x = y()
+ del x, y
+ self.cleanup_references()
def test_sre(self):
module = self.import_module(name='_sre')
@@ -172,17 +183,21 @@
assert "groupdict" in dir(m)
re._cache.clear()
re._cache_repl.clear()
+ del prog, m
+ self.cleanup_references()
def test_init_error(self):
module = self.import_module("foo")
raises(ValueError, module.InitErrType)
-
+ self.cleanup_references()
+
def test_cmps(self):
module = self.import_module("comparisons")
cmpr = module.CmpType()
assert cmpr == 3
assert cmpr != 42
-
+ self.cleanup_references()
+
def test_hash(self):
module = self.import_module("comparisons")
cmpr = module.CmpType()
@@ -191,6 +206,7 @@
d[cmpr] = 72
assert d[cmpr] == 72
assert d[3] == 72
+ self.cleanup_references()
def test_descriptor(self):
module = self.import_module("foo")
@@ -205,6 +221,7 @@
assert obj.y == (prop, 2)
del obj.x
assert obj.z == prop
+ self.cleanup_references()
def test_tp_dict(self):
foo = self.import_module("foo")
@@ -226,6 +243,7 @@
])
obj = foo.new()
assert module.read_tp_dict(obj) == foo.fooType.copy
+ self.cleanup_references()
class TestTypes(BaseApiTest):
Modified: pypy/branch/out-of-line-guards/pypy/module/cpyext/typeobject.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/module/cpyext/typeobject.py (original)
+++ pypy/branch/out-of-line-guards/pypy/module/cpyext/typeobject.py Thu Dec 9 16:33:59 2010
@@ -24,7 +24,7 @@
from pypy.module.cpyext.structmember import PyMember_GetOne, PyMember_SetOne
from pypy.module.cpyext.typeobjectdefs import (
PyTypeObjectPtr, PyTypeObject, PyGetSetDef, PyMemberDef, newfunc,
- PyNumberMethods)
+ PyNumberMethods, PySequenceMethods)
from pypy.module.cpyext.slotdefs import (
slotdefs_for_tp_slots, slotdefs_for_wrappers, get_slot_tp_function)
from pypy.interpreter.error import OperationError
@@ -136,6 +136,8 @@
if not struct:
if slot_names[0] == 'c_tp_as_number':
STRUCT_TYPE = PyNumberMethods
+ elif slot_names[0] == 'c_tp_as_sequence':
+ STRUCT_TYPE = PySequenceMethods
else:
raise AssertionError(
"Structure not allocated: %s" % (slot_names[0],))
@@ -392,6 +394,8 @@
lltype.free(obj_pto.c_tp_as_buffer, flavor='raw')
if obj_pto.c_tp_as_number:
lltype.free(obj_pto.c_tp_as_number, flavor='raw')
+ if obj_pto.c_tp_as_sequence:
+ lltype.free(obj_pto.c_tp_as_sequence, flavor='raw')
Py_DecRef(space, base_pyo)
rffi.free_charp(obj_pto.c_tp_name)
PyObject_dealloc(space, obj)
@@ -433,12 +437,6 @@
finish_type_1(space, pto)
finish_type_2(space, pto, w_type)
- if space.type(w_type).is_cpytype():
- # XXX Types with a C metatype are never freed, try to see why...
- render_immortal(pto, w_type)
- lltype.render_immortal(pto)
- lltype.render_immortal(pto.c_tp_name)
-
pto.c_tp_basicsize = rffi.sizeof(typedescr.basestruct)
if pto.c_tp_base:
if pto.c_tp_base.c_tp_basicsize > pto.c_tp_basicsize:
@@ -544,25 +542,12 @@
w_obj.ready()
finish_type_2(space, py_type, w_obj)
- render_immortal(py_type, w_obj)
state = space.fromcache(RefcountState)
state.non_heaptypes_w.append(w_obj)
return w_obj
-def render_immortal(py_type, w_obj):
- lltype.render_immortal(py_type.c_tp_bases)
- lltype.render_immortal(py_type.c_tp_mro)
-
- assert isinstance(w_obj, W_TypeObject)
- if w_obj.is_cpytype():
- lltype.render_immortal(py_type.c_tp_dict)
- else:
- lltype.render_immortal(py_type.c_tp_name)
- if not w_obj.is_cpytype() and w_obj.is_heaptype():
- lltype.render_immortal(py_type)
-
def finish_type_1(space, pto):
"""
Sets up tp_bases, necessary before creating the interpreter type.
@@ -599,7 +584,8 @@
if w_obj.is_cpytype():
Py_DecRef(space, pto.c_tp_dict)
- pto.c_tp_dict = make_ref(space, w_obj.getdict())
+ w_dict = space.newdict(from_strdict_shared=w_obj.dict_w)
+ pto.c_tp_dict = make_ref(space, w_dict)
@cpython_api([PyTypeObjectPtr, PyTypeObjectPtr], rffi.INT_real, error=CANNOT_FAIL)
def PyType_IsSubtype(space, a, b):
Modified: pypy/branch/out-of-line-guards/pypy/module/exceptions/interp_exceptions.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/module/exceptions/interp_exceptions.py (original)
+++ pypy/branch/out-of-line-guards/pypy/module/exceptions/interp_exceptions.py Thu Dec 9 16:33:59 2010
@@ -452,6 +452,7 @@
self.w_text = space.w_None
self.w_msg = space.wrap('')
self.w_print_file_and_line = space.w_None # what's that?
+ self.w_lastlineno = space.w_None # this is a pypy extension
W_BaseException.__init__(self, space)
def descr_init(self, space, args_w):
@@ -459,11 +460,16 @@
if len(args_w) > 0:
self.w_msg = args_w[0]
if len(args_w) == 2:
- values_w = space.fixedview(args_w[1], 4)
- self.w_filename = values_w[0]
- self.w_lineno = values_w[1]
- self.w_offset = values_w[2]
- self.w_text = values_w[3]
+ values_w = space.fixedview(args_w[1])
+ if len(values_w) > 0: self.w_filename = values_w[0]
+ if len(values_w) > 1: self.w_lineno = values_w[1]
+ if len(values_w) > 2: self.w_offset = values_w[2]
+ if len(values_w) > 3: self.w_text = values_w[3]
+ if len(values_w) > 4:
+ self.w_lastlineno = values_w[4] # PyPy extension
+ # kill the extra items from args_w to prevent undesired effects
+ args_w = args_w[:]
+ args_w[1] = space.newtuple(values_w[:4])
W_BaseException.descr_init(self, space, args_w)
descr_init.unwrap_spec = ['self', ObjSpace, 'args_w']
@@ -472,18 +478,24 @@
if type(self.msg) is not str:
return str(self.msg)
+ lineno = None
buffer = self.msg
have_filename = type(self.filename) is str
- have_lineno = type(self.lineno) is int
+ if type(self.lineno) is int:
+ if (type(self.lastlineno) is int and
+ self.lastlineno > self.lineno):
+ lineno = 'lines %d-%d' % (self.lineno, self.lastlineno)
+ else:
+ lineno = 'line %d' % (self.lineno,)
if have_filename:
import os
fname = os.path.basename(self.filename or "???")
- if have_lineno:
- buffer = "%s (%s, line %ld)" % (self.msg, fname, self.lineno)
+ if lineno:
+ buffer = "%s (%s, %s)" % (self.msg, fname, lineno)
else:
buffer ="%s (%s)" % (self.msg, fname)
- elif have_lineno:
- buffer = "%s (line %ld)" % (self.msg, self.lineno)
+ elif lineno:
+ buffer = "%s (%s)" % (self.msg, lineno)
return buffer
""")
@@ -504,6 +516,7 @@
text = readwrite_attrproperty_w('w_text', W_SyntaxError),
print_file_and_line = readwrite_attrproperty_w('w_print_file_and_line',
W_SyntaxError),
+ lastlineno = readwrite_attrproperty_w('w_lastlineno', W_SyntaxError),
)
W_FutureWarning = _new_exception('FutureWarning', W_Warning,
Modified: pypy/branch/out-of-line-guards/pypy/module/fcntl/test/test_fcntl.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/module/fcntl/test/test_fcntl.py (original)
+++ pypy/branch/out-of-line-guards/pypy/module/fcntl/test/test_fcntl.py Thu Dec 9 16:33:59 2010
@@ -63,7 +63,7 @@
if sys.platform in ('netbsd1', 'netbsd2', 'netbsd3',
'Darwin1.2', 'darwin',
'freebsd2', 'freebsd3', 'freebsd4', 'freebsd5',
- 'freebsd6', 'freebsd7',
+ 'freebsd6', 'freebsd7', 'freebsd8', 'freebsd9',
'bsdos2', 'bsdos3', 'bsdos4',
'openbsd', 'openbsd2', 'openbsd3'):
if struct.calcsize('l') == 8:
@@ -159,7 +159,7 @@
if "linux" in sys.platform:
TIOCGPGRP = 0x540f
- elif "darwin" in sys.platform or "freebsd6" == sys.platform:
+ elif "darwin" in sys.platform or "freebsd" in sys.platform:
TIOCGPGRP = 0x40047477
else:
skip("don't know how to test ioctl() on this platform")
Modified: pypy/branch/out-of-line-guards/pypy/module/imp/importing.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/module/imp/importing.py (original)
+++ pypy/branch/out-of-line-guards/pypy/module/imp/importing.py Thu Dec 9 16:33:59 2010
@@ -76,7 +76,7 @@
return SEARCH_ERROR, None, None
-if sys.platform in ['linux2', 'freebsd']:
+if sys.platform == 'linux2' or 'freebsd' in sys.platform:
def case_ok(filename):
return True
else:
@@ -529,7 +529,7 @@
space.sys.setmodule(w_module)
raise
finally:
- space.reloading_modules.clear()
+ del space.reloading_modules[modulename]
# __________________________________________________________________
Modified: pypy/branch/out-of-line-guards/pypy/module/itertools/interp_itertools.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/module/itertools/interp_itertools.py (original)
+++ pypy/branch/out-of-line-guards/pypy/module/itertools/interp_itertools.py Thu Dec 9 16:33:59 2010
@@ -391,7 +391,8 @@
self.iterators_w = iterators_w
self.current_iterator = 0
self.num_iterators = len(iterators_w)
- self.started = False
+ if self.num_iterators > 0:
+ self.w_it = iterators_w[0]
def iter_w(self):
return self.space.wrap(self)
@@ -399,26 +400,23 @@
def next_w(self):
if self.current_iterator >= self.num_iterators:
raise OperationError(self.space.w_StopIteration, self.space.w_None)
- if not self.started:
- self.current_iterator = 0
- self.w_it = self.iterators_w[self.current_iterator]
- self.started = True
+ try:
+ return self.space.next(self.w_it)
+ except OperationError, e:
+ return self._handle_error(e)
+ def _handle_error(self, e):
while True:
+ if not e.match(self.space, self.space.w_StopIteration):
+ raise e
+ self.current_iterator += 1
+ if self.current_iterator >= self.num_iterators:
+ raise e
+ self.w_it = self.iterators_w[self.current_iterator]
try:
- w_obj = self.space.next(self.w_it)
+ return self.space.next(self.w_it)
except OperationError, e:
- if e.match(self.space, self.space.w_StopIteration):
- self.current_iterator += 1
- if self.current_iterator >= self.num_iterators:
- raise OperationError(self.space.w_StopIteration, self.space.w_None)
- else:
- self.w_it = self.iterators_w[self.current_iterator]
- else:
- raise
- else:
- break
- return w_obj
+ pass # loop back to the start of _handle_error(e)
def W_Chain___new__(space, w_subtype, args_w):
return space.wrap(W_Chain(space, args_w))
@@ -446,8 +444,10 @@
def __init__(self, space, w_fun, args_w):
self.space = space
- self.identity_fun = (self.space.is_w(w_fun, space.w_None))
- self.w_fun = w_fun
+ if self.space.is_w(w_fun, space.w_None):
+ self.w_fun = None
+ else:
+ self.w_fun = w_fun
iterators_w = []
i = 0
@@ -470,12 +470,26 @@
return self.space.wrap(self)
def next_w(self):
- w_objects = self.space.newtuple([self.space.next(w_it) for w_it in self.iterators_w])
- if self.identity_fun:
+ # common case: 1 or 2 arguments
+ iterators_w = self.iterators_w
+ length = len(iterators_w)
+ if length == 1:
+ objects = [self.space.next(iterators_w[0])]
+ elif length == 2:
+ objects = [self.space.next(iterators_w[0]),
+ self.space.next(iterators_w[1])]
+ else:
+ objects = self._get_objects()
+ w_objects = self.space.newtuple(objects)
+ if self.w_fun is None:
return w_objects
else:
return self.space.call(self.w_fun, w_objects)
+ def _get_objects(self):
+ # the loop is out of the way of the JIT
+ return [self.space.next(w_elem) for w_elem in self.iterators_w]
+
def W_IMap___new__(space, w_subtype, w_fun, args_w):
if len(args_w) == 0:
@@ -769,15 +783,7 @@
raise OperationError(self.space.w_StopIteration, self.space.w_None)
if not self.new_group:
- # Consume unwanted input until we reach the next group
- try:
- while True:
- self.group_next(self.index)
-
- except StopIteration:
- pass
- if self.exhausted:
- raise OperationError(self.space.w_StopIteration, self.space.w_None)
+ self._consume_unwanted_input()
if not self.started:
self.started = True
@@ -799,6 +805,16 @@
w_iterator = self.space.wrap(W_GroupByIterator(self.space, self.index, self))
return self.space.newtuple([self.w_key, w_iterator])
+ def _consume_unwanted_input(self):
+ # Consume unwanted input until we reach the next group
+ try:
+ while True:
+ self.group_next(self.index)
+ except StopIteration:
+ pass
+ if self.exhausted:
+ raise OperationError(self.space.w_StopIteration, self.space.w_None)
+
def group_next(self, group_index):
if group_index < self.index:
raise StopIteration
Modified: pypy/branch/out-of-line-guards/pypy/module/posix/__init__.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/module/posix/__init__.py (original)
+++ pypy/branch/out-of-line-guards/pypy/module/posix/__init__.py Thu Dec 9 16:33:59 2010
@@ -96,6 +96,8 @@
interpleveldefs['fork'] = 'interp_posix.fork'
if hasattr(os, 'openpty'):
interpleveldefs['openpty'] = 'interp_posix.openpty'
+ if hasattr(os, 'forkpty'):
+ interpleveldefs['forkpty'] = 'interp_posix.forkpty'
if hasattr(os, 'waitpid'):
interpleveldefs['waitpid'] = 'interp_posix.waitpid'
if hasattr(os, 'execv'):
Modified: pypy/branch/out-of-line-guards/pypy/module/posix/interp_posix.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/module/posix/interp_posix.py (original)
+++ pypy/branch/out-of-line-guards/pypy/module/posix/interp_posix.py Thu Dec 9 16:33:59 2010
@@ -608,6 +608,14 @@
raise wrap_oserror(space, e)
return space.newtuple([space.wrap(master_fd), space.wrap(slave_fd)])
+def forkpty(space):
+ try:
+ pid, master_fd = os.forkpty()
+ except OSError, e:
+ raise wrap_oserror(space, e)
+ return space.newtuple([space.wrap(pid),
+ space.wrap(master_fd)])
+
def waitpid(space, pid, options):
""" waitpid(pid, options) -> (pid, status)
Modified: pypy/branch/out-of-line-guards/pypy/module/posix/test/test_posix2.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/module/posix/test/test_posix2.py (original)
+++ pypy/branch/out-of-line-guards/pypy/module/posix/test/test_posix2.py Thu Dec 9 16:33:59 2010
@@ -331,6 +331,22 @@
data = os.read(master_fd, 100)
assert data.startswith('x')
+ if hasattr(__import__(os.name), "forkpty"):
+ def test_forkpty(self):
+ import sys
+ os = self.posix
+ childpid, master_fd = os.forkpty()
+ assert isinstance(childpid, int)
+ assert isinstance(master_fd, int)
+ if childpid == 0:
+ data = os.read(0, 100)
+ if data.startswith('abc'):
+ os._exit(42)
+ else:
+ os._exit(43)
+ os.write(master_fd, 'abc\n')
+ _, status = os.waitpid(childpid, 0)
+ assert status >> 8 == 42
if hasattr(__import__(os.name), "execv"):
def test_execv(self):
Modified: pypy/branch/out-of-line-guards/pypy/module/pyexpat/interp_pyexpat.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/module/pyexpat/interp_pyexpat.py (original)
+++ pypy/branch/out-of-line-guards/pypy/module/pyexpat/interp_pyexpat.py Thu Dec 9 16:33:59 2010
@@ -329,7 +329,7 @@
if self.returns_unicode:
return space.call_function(
space.getattr(space.wrap(s), space.wrap("decode")),
- space.wrap(self.encoding),
+ space.wrap("utf-8"),
space.wrap("strict"))
else:
return space.wrap(s)
Modified: pypy/branch/out-of-line-guards/pypy/module/pyexpat/test/test_parser.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/module/pyexpat/test/test_parser.py (original)
+++ pypy/branch/out-of-line-guards/pypy/module/pyexpat/test/test_parser.py Thu Dec 9 16:33:59 2010
@@ -15,3 +15,17 @@
assert res == 1
raises(pyexpat.ExpatError, p.Parse, "3")
+
+ def test_encoding(self):
+ import pyexpat
+ for encoding_arg in (None, 'utf-8', 'iso-8859-1'):
+ for namespace_arg in (None, '{'):
+ print encoding_arg, namespace_arg
+ p = pyexpat.ParserCreate(encoding_arg, namespace_arg)
+ data = []
+ p.CharacterDataHandler = lambda s: data.append(s)
+ encoding = encoding_arg is None and 'utf-8' or encoding_arg
+
+ res = p.Parse(u"<xml>\u00f6</xml>".encode(encoding), isfinal=True)
+ assert res == 1
+ assert data == [u"\u00f6"]
Modified: pypy/branch/out-of-line-guards/pypy/module/pypyjit/policy.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/module/pypyjit/policy.py (original)
+++ pypy/branch/out-of-line-guards/pypy/module/pypyjit/policy.py Thu Dec 9 16:33:59 2010
@@ -12,19 +12,13 @@
if '.' in modname:
modname, _ = modname.split('.', 1)
if modname in ['pypyjit', 'signal', 'micronumpy', 'math', 'exceptions',
- 'imp', 'sys', 'array', '_ffi']:
+ 'imp', 'sys', 'array', '_ffi', 'itertools', 'operator']:
return True
return False
def look_inside_function(self, func):
- # this function should never actually return True directly
- # but instead call the base implementation
mod = func.__module__ or '?'
- if mod.startswith('pypy.objspace.'):
- # gc_id operation
- if func.__name__ == 'id__ANY':
- return False
if mod == 'pypy.rlib.rbigint' or mod == 'pypy.rlib.rlocale':
return False
if '_geninterp_' in func.func_globals: # skip all geninterped stuff
Modified: pypy/branch/out-of-line-guards/pypy/module/pypyjit/test/test_policy.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/module/pypyjit/test/test_policy.py (original)
+++ pypy/branch/out-of-line-guards/pypy/module/pypyjit/test/test_policy.py Thu Dec 9 16:33:59 2010
@@ -4,7 +4,7 @@
def test_id_any():
from pypy.objspace.std.default import id__ANY
- assert not pypypolicy.look_inside_function(id__ANY)
+ assert pypypolicy.look_inside_function(id__ANY)
def test_bigint():
from pypy.rlib.rbigint import rbigint
Modified: pypy/branch/out-of-line-guards/pypy/module/pypyjit/test/test_pypy_c.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/module/pypyjit/test/test_pypy_c.py (original)
+++ pypy/branch/out-of-line-guards/pypy/module/pypyjit/test/test_pypy_c.py Thu Dec 9 16:33:59 2010
@@ -630,6 +630,32 @@
''', 3000, ([0], 2000*3))
assert len(self.loops) == 1
+ def test_getattr_with_dynamic_attribute(self):
+ self.run_source('''
+ class A(object):
+ pass
+
+ l = ["x", "y"]
+
+ def main(arg):
+ sum = 0
+ a = A()
+ a.a1 = 0
+ a.a2 = 0
+ a.a3 = 0
+ a.a4 = 0
+ a.a5 = 0 # workaround, because the first five attributes need a promotion
+ a.x = 1
+ a.y = 2
+ i = 0
+ while i < 2000:
+ name = l[i % 2]
+ sum += getattr(a, name)
+ i += 1
+ return sum
+ ''', 3000, ([0], 3000))
+ assert len(self.loops) == 1
+
def test_blockstack_virtualizable(self):
self.run_source('''
from pypyjit import residual_call
@@ -673,11 +699,9 @@
i = t2[3]
del t2
return i
- ''', 100, ([], 100))
+ ''', 40, ([], 100))
bytecode, = self.get_by_bytecode('BINARY_SUBSCR')
- assert len(bytecode.get_opnames('new_array')) == 1
- # XXX I would like here to say that it's 0, but unfortunately
- # call that can raise is not exchanged into getarrayitem_gc
+ assert len(bytecode.get_opnames('new_array')) == 0
def test_overflow_checking(self):
startvalue = sys.maxint - 2147483647
@@ -861,11 +885,14 @@
def test_array_sum(self):
for tc, maxops in zip('bhilBHILfd', (38,) * 6 + (40, 40, 41, 38)):
res = 19352859
- if tc in 'IL':
+ if tc == 'L':
res = long(res)
elif tc in 'fd':
res = float(res)
-
+ elif tc == 'I' and sys.maxint == 2147483647:
+ res = long(res)
+ # note: in CPython we always get longs here, even on 64-bits
+
self.run_source('''
from array import array
@@ -913,11 +940,14 @@
print '='*65
print '='*20, 'running test for tc=%r' % (tc,), '='*20
res = 73574560
- if tc in 'IL':
+ if tc == 'L':
res = long(res)
elif tc in 'fd':
res = float(res)
-
+ elif tc == 'I' and sys.maxint == 2147483647:
+ res = long(res)
+ # note: in CPython we always get longs here, even on 64-bits
+
self.run_source('''
from array import array
Modified: pypy/branch/out-of-line-guards/pypy/module/sys/__init__.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/module/sys/__init__.py (original)
+++ pypy/branch/out-of-line-guards/pypy/module/sys/__init__.py Thu Dec 9 16:33:59 2010
@@ -63,8 +63,6 @@
'pypy_svn_url' : 'version.get_svn_url(space)',
'subversion' : 'version.get_subversion_info(space)',
'hexversion' : 'version.get_hexversion(space)',
- 'ps1' : 'space.wrap(">>>> ")',
- 'ps2' : 'space.wrap(".... ")',
'displayhook' : 'hook.displayhook',
'__displayhook__' : 'hook.__displayhook__',
Modified: pypy/branch/out-of-line-guards/pypy/module/sys/state.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/module/sys/state.py (original)
+++ pypy/branch/out-of-line-guards/pypy/module/sys/state.py Thu Dec 9 16:33:59 2010
@@ -33,6 +33,8 @@
raise OSError(errno.ENOTDIR, path)
+platform = sys.platform
+
def getinitialpath(prefix):
from pypy.module.sys.version import CPYTHON_VERSION
dirname = '%d.%d.%d' % (CPYTHON_VERSION[0],
@@ -51,6 +53,15 @@
importlist.append(lib_pypy)
importlist.append(python_std_lib_modified)
importlist.append(python_std_lib)
+ #
+ # List here the extra platform-specific paths.
+ if platform != 'win32':
+ importlist.append(os.path.join(python_std_lib, 'plat-'+platform))
+ if platform == 'darwin':
+ platmac = os.path.join(python_std_lib, 'plat-mac')
+ importlist.append(platmac)
+ importlist.append(os.path.join(platmac, 'lib-scriptpackages'))
+ #
return importlist
def pypy_initial_path(space, srcdir):
Modified: pypy/branch/out-of-line-guards/pypy/module/sys/test/test_initialpath.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/module/sys/test/test_initialpath.py (original)
+++ pypy/branch/out-of-line-guards/pypy/module/sys/test/test_initialpath.py Thu Dec 9 16:33:59 2010
@@ -15,4 +15,5 @@
def test_stdlib_in_prefix(tmpdir):
dirs = build_hierarchy(tmpdir)
path = getinitialpath(str(tmpdir))
- assert path == map(str, dirs)
+ # we get at least 'dirs', and maybe more (e.g. plat-linux2)
+ assert path[:len(dirs)] == map(str, dirs)
Modified: pypy/branch/out-of-line-guards/pypy/module/sys/vm.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/module/sys/vm.py (original)
+++ pypy/branch/out-of-line-guards/pypy/module/sys/vm.py Thu Dec 9 16:33:59 2010
@@ -42,28 +42,22 @@
f = ec.getnextframe_nohidden(f)
return space.wrap(f)
-# directly from the C code in ceval.c, might be moved somewhere else.
-
@jit.dont_look_inside
def setrecursionlimit(space, w_new_limit):
- """Set the maximum depth of the Python interpreter stack to n. This
-limit prevents infinite recursion from causing an overflow of the C
-stack and crashing Python. The highest possible limit is platform
-dependent."""
+ """DEPRECATED on PyPy. Will issue warning and not work
+ """
new_limit = space.int_w(w_new_limit)
if new_limit <= 0:
raise OperationError(space.w_ValueError,
space.wrap("recursion limit must be positive"))
# global recursion_limit
# we need to do it without writing globals.
+ space.warn('setrecursionlimit deprecated', space.w_DeprecationWarning)
space.sys.recursionlimit = new_limit
def getrecursionlimit(space):
- """Return the current value of the recursion limit, the maximum depth
- of the Python interpreter stack. This limit prevents infinite
- recursion from causing an overflow of the C stack and crashing Python.
+ """DEPRECATED on PyPy. Will issue warning and not work
"""
-
return space.wrap(space.sys.recursionlimit)
def setcheckinterval(space, interval):
Modified: pypy/branch/out-of-line-guards/pypy/module/test_lib_pypy/ctypes_tests/test_guess_argtypes.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/module/test_lib_pypy/ctypes_tests/test_guess_argtypes.py (original)
+++ pypy/branch/out-of-line-guards/pypy/module/test_lib_pypy/ctypes_tests/test_guess_argtypes.py Thu Dec 9 16:33:59 2010
@@ -11,21 +11,23 @@
py.test.skip("pypy white-box test")
from _ctypes.function import CFuncPtr
- guess = CFuncPtr._guess_argtypes
+ def guess(value):
+ cobj = CFuncPtr._conv_param(None, value, 0)
+ return type(cobj)
- assert guess([13]) == [c_int]
- assert guess([0]) == [c_int]
- assert guess(['xca']) == [c_char_p]
- assert guess([None]) == [c_void_p]
- assert guess([c_int(3)]) == [c_int]
- assert guess([u'xca']) == [c_wchar_p]
+ assert guess(13) == c_int
+ assert guess(0) == c_int
+ assert guess('xca') == c_char_p
+ assert guess(None) == c_void_p
+ assert guess(c_int(3)) == c_int
+ assert guess(u'xca') == c_wchar_p
class Stuff:
pass
s = Stuff()
s._as_parameter_ = None
- assert guess([s]) == [c_void_p]
+ assert guess(s) == c_void_p
def test_guess_unicode():
if not hasattr(sys, 'pypy_translation_info') and sys.platform != 'win32':
Modified: pypy/branch/out-of-line-guards/pypy/module/test_lib_pypy/ctypes_tests/test_keepalive.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/module/test_lib_pypy/ctypes_tests/test_keepalive.py (original)
+++ pypy/branch/out-of-line-guards/pypy/module/test_lib_pypy/ctypes_tests/test_keepalive.py Thu Dec 9 16:33:59 2010
@@ -99,7 +99,7 @@
def test_primitive(self):
if not hasattr(sys, 'pypy_translation_info'):
py.test.skip("pypy white-box test")
- assert c_char_p("abc")._objects['0']._buffer[0] == "a"
+ assert c_char_p("abc")._objects._buffer[0] == "a"
assert c_int(3)._objects is None
def test_pointer_to_pointer(self):
@@ -123,7 +123,7 @@
pass
cf = CFUNCTYPE(c_int, c_int)(f)
p1 = cast(cf, c_void_p)
- assert p1._objects == {'1': cf, '0': {'0': cf}}
+ assert p1._objects == {id(cf): cf, '0': cf}
def test_array_of_struct_with_pointer(self):
class S(Structure):
@@ -221,7 +221,7 @@
import gc; gc.collect()
print 'x =', repr(x)
assert x.value == 'hellohello'
- assert x._objects.keys() == ['0']
+ assert x._objects == 'hellohello'
#
class datum(Structure):
_fields_ = [
Modified: pypy/branch/out-of-line-guards/pypy/objspace/std/complexobject.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/objspace/std/complexobject.py (original)
+++ pypy/branch/out-of-line-guards/pypy/objspace/std/complexobject.py Thu Dec 9 16:33:59 2010
@@ -23,90 +23,92 @@
""" representation for debugging purposes """
return "<W_ComplexObject(%f,%f)>" % (w_self.realval, w_self.imagval)
-registerimplementation(W_ComplexObject)
-
-c_1 = (1.0, 0.0)
+ def sub(self, other):
+ return W_ComplexObject(self.realval - other.realval,
+ self.imagval - other.imagval)
+
+ def mul(self, other):
+ r = self.realval * other.realval - self.imagval * other.imagval
+ i = self.realval * other.imagval + self.imagval * other.realval
+ return W_ComplexObject(r, i)
+
+ def div(self, other):
+ r1, i1 = self.realval, self.imagval
+ r2, i2 = other.realval, other.imagval
+ if r2 < 0:
+ abs_r2 = - r2
+ else:
+ abs_r2 = r2
+ if i2 < 0:
+ abs_i2 = - i2
+ else:
+ abs_i2 = i2
+ if abs_r2 >= abs_i2:
+ if abs_r2 == 0.0:
+ raise ZeroDivisionError
+ else:
+ ratio = i2 / r2
+ denom = r2 + i2 * ratio
+ rr = (r1 + i1 * ratio) / denom
+ ir = (i1 - r1 * ratio) / denom
+ else:
+ ratio = r2 / i2
+ denom = r2 * ratio + i2
+ assert i2 != 0.0
+ rr = (r1 * ratio + i1) / denom
+ ir = (i1 * ratio - r1) / denom
+ return W_ComplexObject(rr,ir)
+
+ def divmod(self, other):
+ w_div = self.div(other)
+ div = math.floor(w_div.realval)
+ w_mod = self.sub(
+ W_ComplexObject(other.realval * div, other.imagval * div))
+ return (W_ComplexObject(div, 0), w_mod)
+
+ def pow(self, other):
+ r1, i1 = self.realval, self.imagval
+ r2, i2 = other.realval, other.imagval
+ if r2 == 0.0 and i2 == 0.0:
+ rr, ir = 1, 0
+ elif r1 == 0.0 and i1 == 0.0:
+ if i2 != 0.0 or r2 < 0.0:
+ raise ZeroDivisionError
+ rr, ir = (0.0, 0.0)
+ else:
+ vabs = math.hypot(r1,i1)
+ len = math.pow(vabs,r2)
+ at = math.atan2(i1,r1)
+ phase = at * r2
+ if i2 != 0.0:
+ len /= math.exp(at * i2)
+ phase += i2 * math.log(vabs)
+ rr = len * math.cos(phase)
+ ir = len * math.sin(phase)
+ return W_ComplexObject(rr, ir)
+
+ def pow_int(self, n):
+ if n > 100 or n < -100:
+ return self.pow(W_ComplexObject(1.0 * n, 0.0))
+ elif n > 0:
+ return self.pow_positive_int(n)
+ else:
+ return w_one.div(self.pow_positive_int(-n))
-def _sum(c1, c2):
- return (c1[0]+c2[0],c1[1]+c2[1])
+ def pow_positive_int(self, n):
+ mask = 1
+ w_result = w_one
+ while mask > 0 and n >= mask:
+ if n & mask:
+ w_result = w_result.mul(self)
+ mask <<= 1
+ self = self.mul(self)
-def _diff(c1, c2):
- return (c1[0]-c2[0],c1[1]-c2[1])
+ return w_result
-def _prod(c1, c2):
- r = c1[0]*c2[0] - c1[1]*c2[1]
- i = c1[0]*c2[1] + c1[1]*c2[0]
- return (r,i)
-
-def _quot(c1,c2):
- r1, i1 = c1
- r2, i2 = c2
- if r2 < 0:
- abs_r2 = - r2
- else:
- abs_r2 = r2
- if i2 < 0:
- abs_i2 = - i2
- else:
- abs_i2 = i2
- if abs_r2 >= abs_i2:
- if abs_r2 == 0.0:
- raise ZeroDivisionError
- else:
- ratio = i2 / r2
- denom = r2 + i2 * ratio
- rr = (r1 + i1 * ratio) / denom
- ir = (i1 - r1 * ratio) / denom
- else:
- ratio = r2 / i2
- denom = r2 * ratio + i2
- assert i2 != 0.0
- rr = (r1 * ratio + i1) / denom
- ir = (i1 * ratio - r1) / denom
- return (rr,ir)
-
-def _pow(c1,c2):
- r1, i1 = c1
- r2, i2 = c2
- if r2 == 0.0 and i2 == 0.0:
- rr, ir = c_1
- elif r1 == 0.0 and i1 == 0.0:
- if i2 != 0.0 or r2 < 0.0:
- raise ZeroDivisionError
- rr, ir = (0.0, 0.0)
- else:
- vabs = math.hypot(r1,i1)
- len = math.pow(vabs,r2)
- at = math.atan2(i1,r1)
- phase = at * r2
- if i2 != 0.0:
- len /= math.exp(at * i2)
- phase += i2 * math.log(vabs)
- rr = len * math.cos(phase)
- ir = len * math.sin(phase)
- return (rr, ir)
-
-def _powu(c,n):
- mask = 1;
- rr, ir = c_1
- rp = c[0]
- ip = c[1]
- while mask > 0 and n >= mask:
- if n & mask:
- rr, ir = _prod((rr, ir), (rp, ip))
- mask <<= 1
- rp, ip = _prod((rp, ip), (rp, ip))
-
- return (rr, ir)
-
-def _powi(c,n):
- if n > 100 or n < -100:
- return _pow(c,(1.0 * n, 0.0))
- elif n > 0:
- return _powu(c, n)
- else:
- return _quot(c_1, _powu(c, -n))
+registerimplementation(W_ComplexObject)
+w_one = W_ComplexObject(1, 0)
def delegate_Bool2Complex(space, w_bool):
@@ -126,38 +128,25 @@
return W_ComplexObject(w_float.floatval, 0.0)
def hash__Complex(space, w_value):
- #this is straight out of CPython complex implementation
-
hashreal = _hash_float(space, w_value.realval)
- if hashreal == -1:
- return space.newint(-1)
hashimg = _hash_float(space, w_value.imagval)
- if hashimg == -1:
- return space.newint(-1)
combined = hashreal + 1000003 * hashimg
- if (combined == -1):
- combined = -2
return space.newint(combined)
-def _w2t(space, w_complex):
- "convert an interplevel complex object to a tuple representation"
- return w_complex.realval, w_complex.imagval
-
-def _t2w(space, c):
- return W_ComplexObject(c[0], c[1])
-
def add__Complex_Complex(space, w_complex1, w_complex2):
- return _t2w(space, _sum(_w2t(space, w_complex1), _w2t(space, w_complex2)))
+ return W_ComplexObject(w_complex1.realval + w_complex2.realval,
+ w_complex1.imagval + w_complex2.imagval)
def sub__Complex_Complex(space, w_complex1, w_complex2):
- return _t2w(space, _diff(_w2t(space, w_complex1), _w2t(space, w_complex2)))
+ return W_ComplexObject(w_complex1.realval - w_complex2.realval,
+ w_complex1.imagval - w_complex2.imagval)
def mul__Complex_Complex(space, w_complex1, w_complex2):
- return _t2w(space, _prod(_w2t(space, w_complex1), _w2t(space, w_complex2)))
+ return w_complex1.mul(w_complex2)
def div__Complex_Complex(space, w_complex1, w_complex2):
try:
- return _t2w(space, _quot(_w2t(space, w_complex1), _w2t(space, w_complex2)))
+ return w_complex1.div(w_complex2)
except ZeroDivisionError, e:
raise OperationError(space.w_ZeroDivisionError, space.wrap(str(e)))
@@ -165,49 +154,38 @@
def mod__Complex_Complex(space, w_complex1, w_complex2):
try:
- div = _quot(_w2t(space, w_complex1), _w2t(space, w_complex2))
+ return w_complex1.divmod(w_complex2)[1]
except ZeroDivisionError, e:
- raise OperationError(space.w_ZeroDivisionError, space.wrap("complex remainder"))
- div = (math.floor(div[0]), 0.0)
- mod = _diff(_w2t(space, w_complex1), _prod(_w2t(space, w_complex2), div))
-
- return _t2w(space, mod)
+ raise OperationError(space.w_ZeroDivisionError, space.wrap(str(e)))
def divmod__Complex_Complex(space, w_complex1, w_complex2):
try:
- div = _quot(_w2t(space, w_complex1), _w2t(space, w_complex2))
+ div, mod = w_complex1.divmod(w_complex2)
except ZeroDivisionError, e:
- raise OperationError(space.w_ZeroDivisionError, space.wrap("complex divmod()"))
- div = (math.floor(div[0]), 0.0)
- mod = _diff(_w2t(space, w_complex1), _prod(_w2t(space, w_complex2), div))
- w_div = _t2w(space, div)
- w_mod = _t2w(space, mod)
- return space.newtuple([w_div, w_mod])
+ raise OperationError(space.w_ZeroDivisionError, space.wrap(str(e)))
+ return space.newtuple([div, mod])
def floordiv__Complex_Complex(space, w_complex1, w_complex2):
+ # don't care about the slight slowdown you get from using divmod
try:
- div = _quot(_w2t(space, w_complex1), _w2t(space, w_complex2))
+ return w_complex1.divmod(w_complex2)[0]
except ZeroDivisionError, e:
- raise OperationError(space.w_ZeroDivisionError, space.wrap("complex floordiv()"))
- div = (math.floor(div[0]), 0.0)
- return _t2w(space, div)
+ raise OperationError(space.w_ZeroDivisionError, space.wrap(str(e)))
-def pow__Complex_Complex_ANY(space, w_complex1, w_complex2, thirdArg):
+def pow__Complex_Complex_ANY(space, w_complex, w_exponent, thirdArg):
if not space.is_w(thirdArg, space.w_None):
raise OperationError(space.w_ValueError, space.wrap('complex modulo'))
+ int_exponent = int(w_exponent.realval)
try:
- v = _w2t(space, w_complex1)
- exponent = _w2t(space, w_complex2)
- int_exponent = int(exponent[0])
- if exponent[1] == 0.0 and exponent[0] == int_exponent:
- p = _powi(v, int_exponent)
+ if w_exponent.imagval == 0.0 and w_exponent.realval == int_exponent:
+ w_p = w_complex.pow_int(int_exponent)
else:
- p = _pow(v, exponent)
+ w_p = w_complex.pow(w_exponent)
except ZeroDivisionError:
raise OperationError(space.w_ZeroDivisionError, space.wrap("0.0 to a negative or complex power"))
except OverflowError:
raise OperationError(space.w_OverflowError, space.wrap("complex exponentiation"))
- return _t2w(space, p)
+ return w_p
def neg__Complex(space, w_complex):
return W_ComplexObject(-w_complex.realval, -w_complex.imagval)
Modified: pypy/branch/out-of-line-guards/pypy/objspace/std/complextype.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/objspace/std/complextype.py (original)
+++ pypy/branch/out-of-line-guards/pypy/objspace/std/complextype.py Thu Dec 9 16:33:59 2010
@@ -1,7 +1,7 @@
from pypy.interpreter import gateway
from pypy.interpreter.error import OperationError
from pypy.objspace.std.register_all import register_all
-from pypy.objspace.std.strutil import interp_string_to_float, ParseStringError
+from pypy.objspace.std.strutil import string_to_float, ParseStringError
from pypy.objspace.std.noneobject import W_NoneObject
from pypy.objspace.std.stdtypedef import GetSetProperty, StdTypeDef
from pypy.objspace.std.stdtypedef import StdObjSpaceMultiMethod
@@ -131,8 +131,8 @@
except ValueError:
raise OperationError(space.w_ValueError, space.wrap(ERR_MALFORMED))
try:
- realval = interp_string_to_float(space, realstr)
- imagval = interp_string_to_float(space, imagstr)
+ realval = string_to_float(realstr)
+ imagval = string_to_float(imagstr)
except ParseStringError:
raise OperationError(space.w_ValueError, space.wrap(ERR_MALFORMED))
else:
Modified: pypy/branch/out-of-line-guards/pypy/objspace/std/floattype.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/objspace/std/floattype.py (original)
+++ pypy/branch/out-of-line-guards/pypy/objspace/std/floattype.py Thu Dec 9 16:33:59 2010
@@ -2,7 +2,7 @@
from pypy.interpreter.error import OperationError
from pypy.objspace.std.stdtypedef import StdTypeDef
from pypy.objspace.std.strutil import ParseStringError
-from pypy.objspace.std.strutil import interp_string_to_float
+from pypy.objspace.std.strutil import string_to_float
def descr__new__(space, w_floattype, w_x=0.0):
from pypy.objspace.std.floatobject import W_FloatObject
@@ -10,7 +10,7 @@
if space.is_true(space.isinstance(w_value, space.w_str)):
strvalue = space.str_w(w_value)
try:
- value = interp_string_to_float(space, strvalue)
+ value = string_to_float(strvalue)
except ParseStringError, e:
raise OperationError(space.w_ValueError,
space.wrap(e.msg))
@@ -21,7 +21,7 @@
from unicodeobject import unicode_to_decimal_w
strvalue = unicode_to_decimal_w(space, w_value)
try:
- value = interp_string_to_float(space, strvalue)
+ value = string_to_float(strvalue)
except ParseStringError, e:
raise OperationError(space.w_ValueError,
space.wrap(e.msg))
Modified: pypy/branch/out-of-line-guards/pypy/objspace/std/longobject.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/objspace/std/longobject.py (original)
+++ pypy/branch/out-of-line-guards/pypy/objspace/std/longobject.py Thu Dec 9 16:33:59 2010
@@ -45,19 +45,6 @@
fromrarith_int._annspecialcase_ = "specialize:argtype(0)"
fromrarith_int = staticmethod(fromrarith_int)
- def fromdecimalstr(s):
- return W_LongObject(rbigint.fromdecimalstr(s))
- fromdecimalstr = staticmethod(fromdecimalstr)
-
- def _count_bits(self):
- return self.num._count_bits()
-
- def is_odd(self):
- return self.num.is_odd()
-
- def get_sign(self):
- return self.num.sign
-
registerimplementation(W_LongObject)
# bool-to-long
Modified: pypy/branch/out-of-line-guards/pypy/objspace/std/mapdict.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/objspace/std/mapdict.py (original)
+++ pypy/branch/out-of-line-guards/pypy/objspace/std/mapdict.py Thu Dec 9 16:33:59 2010
@@ -42,11 +42,23 @@
return None
def index(self, selector):
- if (self.space.config.objspace.std.withmethodcache and
- not jit.we_are_jitted()):
- return self._index_cache(selector)
+ if jit.we_are_jitted():
+ # hack for the jit:
+ # the _index method is pure too, but its argument is never
+ # constant, because it is always a new tuple
+ return self._index_jit_pure(selector[0], selector[1])
else:
- return self._index(selector)
+ return self._index_indirection(selector)
+
+ @jit.purefunction
+ def _index_jit_pure(self, name, index):
+ return self._index_indirection((name, index))
+
+ @jit.dont_look_inside
+ def _index_indirection(self, selector):
+ if (self.space.config.objspace.std.withmethodcache):
+ return self._index_cache(selector)
+ return self._index(selector)
@jit.dont_look_inside
def _index_cache(self, selector):
@@ -498,10 +510,11 @@
def _mapdict_read_storage(self, index):
assert index >= 0
- for i in rangenmin1:
- if index == i:
- erased = getattr(self, "_value%s" % i)
- return rerased.unerase(erased, W_Root)
+ if index < nmin1:
+ for i in rangenmin1:
+ if index == i:
+ erased = getattr(self, "_value%s" % i)
+ return rerased.unerase(erased, W_Root)
if self._has_storage_list():
return self._mapdict_get_storage_list()[index - nmin1]
erased = getattr(self, "_value%s" % nmin1)
Modified: pypy/branch/out-of-line-guards/pypy/objspace/std/objspace.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/objspace/std/objspace.py (original)
+++ pypy/branch/out-of-line-guards/pypy/objspace/std/objspace.py Thu Dec 9 16:33:59 2010
@@ -9,7 +9,7 @@
from pypy.objspace.descroperation import DescrOperation, raiseattrerror
from pypy.rlib.objectmodel import instantiate, r_dict, specialize
from pypy.rlib.debug import make_sure_not_resized
-from pypy.rlib.rarithmetic import base_int
+from pypy.rlib.rarithmetic import base_int, widen
from pypy.rlib.objectmodel import we_are_translated
from pypy.rlib.jit import hint
from pypy.tool.sourcetools import func_with_new_name
@@ -176,7 +176,11 @@
#print 'wrapping', x, '->', w_result
return w_result
if isinstance(x, base_int):
- return W_LongObject.fromrarith_int(x)
+ x = widen(x)
+ if isinstance(x, int):
+ return self.newint(x)
+ else:
+ return W_LongObject.fromrarith_int(x)
# _____ below here is where the annotator should not get _____
@@ -372,7 +376,7 @@
self, w_obj, expected_length)[:])
if expected_length != -1 and len(t) != expected_length:
raise self._wrap_expected_length(expected_length, len(t))
- return t
+ return make_sure_not_resized(t)
def fixedview_unroll(self, w_obj, expected_length=-1):
return self.fixedview(w_obj, expected_length, unroll=True)
Modified: pypy/branch/out-of-line-guards/pypy/objspace/std/strutil.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/objspace/std/strutil.py (original)
+++ pypy/branch/out-of-line-guards/pypy/objspace/std/strutil.py Thu Dec 9 16:33:59 2010
@@ -150,7 +150,7 @@
del calc_mantissa_bits
MANTISSA_DIGITS = len(str( (1L << MANTISSA_BITS)-1 )) + 1
-def interp_string_to_float(space, s):
+def string_to_float(s):
"""
Conversion of string to float.
This version tries to only raise on invalid literals.
@@ -162,10 +162,9 @@
s = strip_spaces(s)
if not s:
- raise OperationError(space.w_ValueError, space.wrap(
- "empty string for float()"))
+ raise ParseStringError("empty string for float()")
+
-
low = s.lower()
if low == "-inf":
return -INFINITY
@@ -204,68 +203,56 @@
if len(digits) == 0:
digits = '0'
- # a few abbreviations
- from pypy.objspace.std import longobject
- mklong = longobject.W_LongObject.fromint
- d2long = longobject.W_LongObject.fromdecimalstr
- adlong = longobject.add__Long_Long
- longup = longobject.pow__Long_Long_None
- multip = longobject.mul__Long_Long
- divide = longobject.div__Long_Long
- lshift = longobject.lshift__Long_Long
- rshift = longobject.rshift__Long_Long
-
# 4) compute the exponent and truncate to +-400
if not exponent:
exponent = '0'
- w_le = d2long(exponent)
- w_le = adlong(space, w_le, mklong(space, dexp))
+ long_exponent = rbigint.fromdecimalstr(exponent)
+ long_exponent = long_exponent.add(rbigint.fromint(dexp))
try:
- e = w_le.toint()
+ e = long_exponent.toint()
except OverflowError:
# XXX poking at internals
- e = w_le.num.sign * 400
- if e >= 400:
- e = 400
- elif e <= -400:
- e = -400
+ e = long_exponent.sign * 400
+ else:
+ if e >= 400:
+ e = 400
+ elif e <= -400:
+ e = -400
# 5) compute the value using long math and proper rounding.
- w_lr = d2long(digits)
- w_10 = mklong(space, 10)
- w_1 = mklong(space, 1)
+ b_digits = rbigint.fromdecimalstr(digits)
+ b_10 = rbigint.fromint(10)
+ b_1 = rbigint.fromint(1)
if e >= 0:
bits = 0
- w_pten = longup(space, w_10, mklong(space, e), space.w_None)
- w_m = multip(space, w_lr, w_pten)
+ b_power_of_ten = b_10.pow(rbigint.fromint(e))
+ b_mantissa = b_digits.mul(b_power_of_ten)
else:
# compute a sufficiently large scale
prec = MANTISSA_DIGITS * 2 + 22 # 128, maybe
bits = - (int(math.ceil(-e / math.log10(2.0) - 1e-10)) + prec)
- w_scale = lshift(space, w_1, mklong(space, -bits))
- w_pten = longup(space, w_10, mklong(space, -e), None)
- w_tmp = multip(space, w_lr, w_scale)
- w_m = divide(space, w_tmp, w_pten)
+ b_scale = b_1.lshift(-bits)
+ b_power_of_ten = b_10.pow(rbigint.fromint(-e))
+ b_mantissa = b_digits.mul(b_scale).div(b_power_of_ten)
# we now have a fairly large mantissa.
# Shift it and round the last bit.
# first estimate the bits and do a big shift
- mbits = w_m._count_bits()
+ mbits = b_mantissa._count_bits()
needed = MANTISSA_BITS
if mbits > needed:
if mbits > needed+1:
shifted = mbits - (needed+1)
- w_m = rshift(space, w_m, mklong(space, shifted))
+ b_mantissa = b_mantissa.rshift(shifted)
bits += shifted
# do the rounding
bits += 1
- round = w_m.is_odd()
- w_m = rshift(space, w_m, w_1)
- w_m = adlong(space, w_m, mklong(space, round))
+ round = b_mantissa.is_odd()
+ b_mantissa = b_mantissa.rshift(1).add(rbigint.fromint(round))
try:
- r = math.ldexp(w_m.tofloat(), bits)
+ r = math.ldexp(b_mantissa.tofloat(), bits)
# XXX I guess we do not check for overflow in ldexp as we agreed to!
if r == 2*r and r != 0.0:
raise OverflowError
Modified: pypy/branch/out-of-line-guards/pypy/objspace/std/test/test_complexobject.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/objspace/std/test/test_complexobject.py (original)
+++ pypy/branch/out-of-line-guards/pypy/objspace/std/test/test_complexobject.py Thu Dec 9 16:33:59 2010
@@ -1,5 +1,6 @@
import py
-from pypy.objspace.std import complexobject as cobj
+from pypy.objspace.std.complexobject import W_ComplexObject, \
+ pow__Complex_Complex_ANY
from pypy.objspace.std import complextype as cobjtype
from pypy.objspace.std.multimethod import FailedToImplement
from pypy.objspace.std.stringobject import W_StringObject
@@ -11,7 +12,7 @@
def _test_instantiation(self):
def _t_complex(r=0.0,i=0.0):
- c = cobj.W_ComplexObject(r, i)
+ c = W_ComplexObject(r, i)
assert c.real == float(r) and c.imag == float(i)
pairs = (
(1, 1),
@@ -38,21 +39,31 @@
test_cparse('.e+5', '.e+5', '0.0')
def test_pow(self):
- assert cobj._pow((0.0,2.0),(0.0,0.0)) == (1.0,0.0)
- assert cobj._pow((0.0,0.0),(2.0,0.0)) == (0.0,0.0)
- rr, ir = cobj._pow((0.0,1.0),(2.0,0.0))
+ def _pow((r1, i1), (r2, i2)):
+ w_res = W_ComplexObject(r1, i1).pow(W_ComplexObject(r2, i2))
+ return w_res.realval, w_res.imagval
+ assert _pow((0.0,2.0),(0.0,0.0)) == (1.0,0.0)
+ assert _pow((0.0,0.0),(2.0,0.0)) == (0.0,0.0)
+ rr, ir = _pow((0.0,1.0),(2.0,0.0))
assert abs(-1.0 - rr) < EPS
assert abs(0.0 - ir) < EPS
- assert cobj._powu((0.0,2.0),0) == (1.0,0.0)
- assert cobj._powu((0.0,0.0),2) == (0.0,0.0)
- assert cobj._powu((0.0,1.0),2) == (-1.0,0.0)
- assert cobj._powi((0.0,2.0),0) == (1.0,0.0)
- assert cobj._powi((0.0,0.0),2) == (0.0,0.0)
- assert cobj._powi((0.0,1.0),2) == (-1.0,0.0)
- c = cobj.W_ComplexObject(0.0,1.0)
- p = cobj.W_ComplexObject(2.0,0.0)
- r = cobj.pow__Complex_Complex_ANY(self.space,c,p,self.space.wrap(None))
+ def _powu((r1, i1), n):
+ w_res = W_ComplexObject(r1, i1).pow_positive_int(n)
+ return w_res.realval, w_res.imagval
+ assert _powu((0.0,2.0),0) == (1.0,0.0)
+ assert _powu((0.0,0.0),2) == (0.0,0.0)
+ assert _powu((0.0,1.0),2) == (-1.0,0.0)
+
+ def _powi((r1, i1), n):
+ w_res = W_ComplexObject(r1, i1).pow_int(n)
+ return w_res.realval, w_res.imagval
+ assert _powi((0.0,2.0),0) == (1.0,0.0)
+ assert _powi((0.0,0.0),2) == (0.0,0.0)
+ assert _powi((0.0,1.0),2) == (-1.0,0.0)
+ c = W_ComplexObject(0.0,1.0)
+ p = W_ComplexObject(2.0,0.0)
+ r = pow__Complex_Complex_ANY(self.space,c,p,self.space.wrap(None))
assert r.realval == -1.0
assert r.imagval == 0.0
Modified: pypy/branch/out-of-line-guards/pypy/objspace/std/test/test_strutil.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/objspace/std/test/test_strutil.py (original)
+++ pypy/branch/out-of-line-guards/pypy/objspace/std/test/test_strutil.py Thu Dec 9 16:33:59 2010
@@ -131,8 +131,6 @@
assert string_to_bigint('1891234174197319').tolong() == 1891234174197319
def test_string_to_float(self):
- def string_to_float(x):
- return interp_string_to_float(self.space, x)
assert string_to_float('0') == 0.0
assert string_to_float('1') == 1.0
assert string_to_float('-1.5') == -1.5
@@ -180,3 +178,4 @@
print repr(s)
if s.strip(): # empty s raises OperationError directly
py.test.raises(ParseStringError, string_to_float, s)
+ py.test.raises(ParseStringError, string_to_float, "")
Modified: pypy/branch/out-of-line-guards/pypy/rlib/debug.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/rlib/debug.py (original)
+++ pypy/branch/out-of-line-guards/pypy/rlib/debug.py Thu Dec 9 16:33:59 2010
@@ -53,13 +53,11 @@
_log = None # patched from tests to be an object of class DebugLog
# or compatible
-_stderr = sys.stderr # alternatively, this is patched from tests
- # (redirects debug_print(), but not debug_start/stop)
def debug_print(*args):
for arg in args:
- print >> _stderr, arg,
- print >> _stderr
+ print >> sys.stderr, arg,
+ print >> sys.stderr
if _log is not None:
_log.debug_print(*args)
@@ -87,13 +85,15 @@
_stop_colors = ""
def debug_start(category):
- print >> sys.stderr, '%s[%s] {%s%s' % (_start_colors_1, time.clock(),
+ c = int(time.clock() * 100)
+ print >> sys.stderr, '%s[%x] {%s%s' % (_start_colors_1, c,
category, _stop_colors)
if _log is not None:
_log.debug_start(category)
def debug_stop(category):
- print >> sys.stderr, '%s[%s] %s}%s' % (_start_colors_2, time.clock(),
+ c = int(time.clock() * 100)
+ print >> sys.stderr, '%s[%x] %s}%s' % (_start_colors_2, c,
category, _stop_colors)
if _log is not None:
_log.debug_stop(category)
@@ -226,31 +226,6 @@
hop.exception_cannot_occur()
return hop.inputarg(hop.args_r[0], arg=0)
-def make_sure_not_modified(arg):
- """ Function checking whether annotation of SomeList is never resized
- and never modified, useful for debugging. Does nothing when run directly
- """
- return arg
-
-class Entry(ExtRegistryEntry):
- _about_ = make_sure_not_modified
-
- def compute_result_annotation(self, s_arg):
- from pypy.annotation.model import SomeList
- assert isinstance(s_arg, SomeList)
- # the logic behind it is that we try not to propagate
- # make_sure_not_resized, when list comprehension is not on
- if self.bookkeeper.annotator.translator.config.translation.list_comprehension_operations:
- s_arg.listdef.never_mutate()
- else:
- from pypy.annotation.annrpython import log
- log.WARNING('make_sure_not_modified called, but has no effect since list_comprehension is off')
- return s_arg
-
- def specialize_call(self, hop):
- hop.exception_cannot_occur()
- return hop.inputarg(hop.args_r[0], arg=0)
-
class IntegerCanBeNegative(Exception):
pass
Modified: pypy/branch/out-of-line-guards/pypy/rlib/jit.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/rlib/jit.py (original)
+++ pypy/branch/out-of-line-guards/pypy/rlib/jit.py Thu Dec 9 16:33:59 2010
@@ -156,7 +156,7 @@
def jit_debug(string, arg1=-sys.maxint-1, arg2=-sys.maxint-1,
arg3=-sys.maxint-1, arg4=-sys.maxint-1):
- """When JITted, cause an extra operation DEBUG_MERGE_POINT to appear in
+ """When JITted, cause an extra operation JIT_DEBUG to appear in
the graphs. Should not be left after debugging."""
keepalive_until_here(string) # otherwise the whole function call is removed
jit_debug.oopspec = 'jit.debug(string, arg1, arg2, arg3, arg4)'
@@ -260,17 +260,12 @@
OPTIMIZER_NO_PERFECTSPEC = 1
OPTIMIZER_FULL = 2
-DEBUG_OFF = 0
-DEBUG_PROFILE = 1
-DEBUG_STEPS = 2
-DEBUG_DETAILED = 3
-
PARAMETERS = {'threshold': 1000,
'trace_eagerness': 200,
'trace_limit': 10000,
'inlining': False,
'optimizer': OPTIMIZER_FULL,
- 'debug' : DEBUG_STEPS,
+ 'loop_longevity': 1000,
}
unroll_parameters = unrolling_iterable(PARAMETERS.keys())
Modified: pypy/branch/out-of-line-guards/pypy/rlib/libffi.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/rlib/libffi.py (original)
+++ pypy/branch/out-of-line-guards/pypy/rlib/libffi.py Thu Dec 9 16:33:59 2010
@@ -178,6 +178,9 @@
# the optimizer will fail to recognize the pattern and won't turn it
# into a fast CALL. Note that "arg = arg.next" is optimized away,
# assuming that archain is completely virtual.
+ if argchain.numargs != len(self.argtypes):
+ raise TypeError, 'Wrong number of arguments: %d expected, got %d' %\
+ (argchain.numargs, len(self.argtypes))
ll_args = self._prepare()
i = 0
arg = argchain.first
Modified: pypy/branch/out-of-line-guards/pypy/rlib/rarithmetic.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/rlib/rarithmetic.py (original)
+++ pypy/branch/out-of-line-guards/pypy/rlib/rarithmetic.py Thu Dec 9 16:33:59 2010
@@ -92,7 +92,8 @@
return False
r_class = rffi.platform.numbertype_to_rclass[tp]
assert issubclass(r_class, base_int)
- return r_class.BITS < LONG_BIT
+ return r_class.BITS < LONG_BIT or (
+ r_class.BITS == LONG_BIT and r_class.SIGNED)
_should_widen_type._annspecialcase_ = 'specialize:memo'
del _bits, _itest, _Ltest
@@ -389,6 +390,11 @@
r_longlong = build_int('r_longlong', True, 64)
r_ulonglong = build_int('r_ulonglong', False, 64)
+if r_longlong is not r_int:
+ r_int64 = r_longlong
+else:
+ r_int64 = int
+
# float as string -> sign, beforept, afterpt, exponent
Modified: pypy/branch/out-of-line-guards/pypy/rlib/rdynload.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/rlib/rdynload.py (original)
+++ pypy/branch/out-of-line-guards/pypy/rlib/rdynload.py Thu Dec 9 16:33:59 2010
@@ -14,7 +14,7 @@
_MINGW = platform.name == "mingw32"
_WIN32 = _MSVC or _MINGW
_MAC_OS = platform.name == "darwin"
-_FREEBSD_7 = platform.name == "freebsd7"
+_FREEBSD = platform.name == "freebsd"
if _WIN32:
from pypy.rlib import rwin32
@@ -27,7 +27,7 @@
else:
pre_include_bits = []
-if _FREEBSD_7 or _WIN32:
+if _FREEBSD or _WIN32:
libraries = []
else:
libraries = ['dl']
Modified: pypy/branch/out-of-line-guards/pypy/rlib/rerased.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/rlib/rerased.py (original)
+++ pypy/branch/out-of-line-guards/pypy/rlib/rerased.py Thu Dec 9 16:33:59 2010
@@ -91,7 +91,7 @@
return annmodel.SomeInteger()
assert isinstance(s_type, annmodel.SomePBC)
assert len(s_type.descriptions) == 1
- clsdef = s_type.descriptions.keys()[0].getuniqueclassdef()
+ clsdef = s_type.any_description().getuniqueclassdef()
return annmodel.SomeInstance(clsdef)
def specialize_call(self, hop):
@@ -108,7 +108,7 @@
def compute_result_annotation(self, s_obj, s_type):
assert isinstance(s_type, annmodel.SomePBC)
assert len(s_type.descriptions) == 1
- clsdef = s_type.descriptions.keys()[0].getuniqueclassdef()
+ clsdef = s_type.any_description().getuniqueclassdef()
s_item = annmodel.SomeInstance(clsdef)
return self.bookkeeper.newlist(s_item)
Modified: pypy/branch/out-of-line-guards/pypy/rlib/rmmap.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/rlib/rmmap.py (original)
+++ pypy/branch/out-of-line-guards/pypy/rlib/rmmap.py Thu Dec 9 16:33:59 2010
@@ -67,7 +67,7 @@
constant_names = ['PAGE_READONLY', 'PAGE_READWRITE', 'PAGE_WRITECOPY',
'FILE_MAP_READ', 'FILE_MAP_WRITE', 'FILE_MAP_COPY',
'DUPLICATE_SAME_ACCESS', 'MEM_COMMIT', 'MEM_RESERVE',
- 'MEM_RELEASE', 'PAGE_EXECUTE_READWRITE']
+ 'MEM_RELEASE', 'PAGE_EXECUTE_READWRITE', 'PAGE_NOACCESS']
for name in constant_names:
setattr(CConfig, name, rffi_platform.ConstantInteger(name))
Modified: pypy/branch/out-of-line-guards/pypy/rlib/rsre/rsre_core.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/rlib/rsre/rsre_core.py (original)
+++ pypy/branch/out-of-line-guards/pypy/rlib/rsre/rsre_core.py Thu Dec 9 16:33:59 2010
@@ -1,5 +1,5 @@
import sys
-from pypy.rlib.debug import check_nonneg, make_sure_not_modified
+from pypy.rlib.debug import check_nonneg
from pypy.rlib.unroll import unrolling_iterable
from pypy.rlib.rsre import rsre_char
from pypy.tool.sourcetools import func_with_new_name
@@ -471,7 +471,6 @@
while True:
op = ctx.pat(ppos)
ppos += 1
- make_sure_not_modified(ctx.pattern)
#jit.jit_debug("sre_match", op, ppos, ptr)
#
Modified: pypy/branch/out-of-line-guards/pypy/rlib/rsre/test/test_zjit.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/rlib/rsre/test/test_zjit.py (original)
+++ pypy/branch/out-of-line-guards/pypy/rlib/rsre/test/test_zjit.py Thu Dec 9 16:33:59 2010
@@ -1,6 +1,5 @@
from pypy.jit.metainterp.test import test_basic
from pypy.rlib.nonconst import NonConstant
-from pypy.rlib.debug import make_sure_not_modified
from pypy.rlib.rsre.test.test_match import get_code
from pypy.rlib.rsre import rsre_core
from pypy.rpython.lltypesystem import lltype
Modified: pypy/branch/out-of-line-guards/pypy/rlib/test/test_debug.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/rlib/test/test_debug.py (original)
+++ pypy/branch/out-of-line-guards/pypy/rlib/test/test_debug.py Thu Dec 9 16:33:59 2010
@@ -42,14 +42,14 @@
py.test.raises(IntegerCanBeNegative, interpret, g, [9])
def test_make_sure_not_resized():
- from pypy.annotation.listdef import TooLateForChange
+ from pypy.annotation.listdef import ListChangeUnallowed
def f():
result = [1,2,3]
make_sure_not_resized(result)
result.append(4)
return len(result)
- py.test.raises(TooLateForChange, interpret, f, [],
+ py.test.raises(ListChangeUnallowed, interpret, f, [],
list_comprehension_operations=True)
Modified: pypy/branch/out-of-line-guards/pypy/rlib/test/test_libffi.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/rlib/test/test_libffi.py (original)
+++ pypy/branch/out-of-line-guards/pypy/rlib/test/test_libffi.py Thu Dec 9 16:33:59 2010
@@ -262,3 +262,24 @@
#
res = self.call(get_dummy, [], rffi.LONG)
assert res == initval+1
+
+ def test_wrong_number_of_arguments(self):
+ from pypy.rpython.llinterp import LLException
+ libfoo = self.get_libfoo()
+ func = (libfoo, 'sum_xy', [types.sint, types.double], types.sint)
+
+ glob = globals()
+ loc = locals()
+ def my_raises(s):
+ try:
+ exec s in glob, loc
+ except TypeError:
+ pass
+ except LLException, e:
+ if str(e) != "<LLException 'TypeError'>":
+ raise
+ else:
+ assert False, 'Did not raise'
+
+ my_raises("self.call(func, [38], rffi.LONG)") # one less
+ my_raises("self.call(func, [38, 12.3, 42], rffi.LONG)") # one more
Modified: pypy/branch/out-of-line-guards/pypy/rpython/extfunc.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/rpython/extfunc.py (original)
+++ pypy/branch/out-of-line-guards/pypy/rpython/extfunc.py Thu Dec 9 16:33:59 2010
@@ -201,6 +201,11 @@
exec py.code.compile("""
from pypy.rlib.objectmodel import running_on_llinterp
from pypy.rlib.debug import llinterpcall
+ from pypy.rlib.jit import dont_look_inside
+ # note: we say 'dont_look_inside' mostly because the
+ # JIT does not support 'running_on_llinterp', but in
+ # theory it is probably right to stop jitting anyway.
+ @dont_look_inside
def ll_wrapper(%s):
if running_on_llinterp:
return llinterpcall(s_result, fakeimpl, %s)
Modified: pypy/branch/out-of-line-guards/pypy/rpython/lltypesystem/ll2ctypes.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/rpython/lltypesystem/ll2ctypes.py (original)
+++ pypy/branch/out-of-line-guards/pypy/rpython/lltypesystem/ll2ctypes.py Thu Dec 9 16:33:59 2010
@@ -409,6 +409,7 @@
subcls = get_common_subclass(mixin_cls, instance.__class__)
instance.__class__ = subcls
instance._storage = ctypes_storage
+ assert ctypes_storage # null pointer?
class _parentable_mixin(object):
"""Mixin added to _parentable containers when they become ctypes-based.
@@ -442,6 +443,9 @@
"not allocated from RPython at all")
self._storage = None
+ def _getid(self):
+ return self._addressof_storage()
+
def __eq__(self, other):
if isinstance(other, _llgcopaque):
addressof_other = other.intval
@@ -1291,7 +1295,7 @@
def _where_is_errno():
return standard_c_lib.__errno_location()
- elif sys.platform in ('darwin', 'freebsd7'):
+ elif sys.platform in ('darwin', 'freebsd7', 'freebsd8', 'freebsd9'):
standard_c_lib.__error.restype = ctypes.POINTER(ctypes.c_int)
def _where_is_errno():
return standard_c_lib.__error()
Modified: pypy/branch/out-of-line-guards/pypy/rpython/lltypesystem/llarena.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/rpython/lltypesystem/llarena.py (original)
+++ pypy/branch/out-of-line-guards/pypy/rpython/lltypesystem/llarena.py Thu Dec 9 16:33:59 2010
@@ -26,6 +26,7 @@
self.objectptrs = {} # {offset: ptr-to-container}
self.objectsizes = {} # {offset: size}
self.freed = False
+ self.protect_inaccessible = None
self.reset(zero)
def __repr__(self):
@@ -59,6 +60,8 @@
def check(self):
if self.freed:
raise ArenaError("arena was already freed")
+ if self.protect_inaccessible is not None:
+ raise ArenaError("arena is currently arena_protect()ed")
def _getid(self):
address, length = self.usagemap.buffer_info()
@@ -127,6 +130,21 @@
def mark_freed(self):
self.freed = True # this method is a hook for tests
+ def set_protect(self, inaccessible):
+ if inaccessible:
+ assert self.protect_inaccessible is None
+ saved = []
+ for ptr in self.objectptrs.values():
+ obj = ptr._obj
+ saved.append((obj, obj._protect()))
+ self.protect_inaccessible = saved
+ else:
+ assert self.protect_inaccessible is not None
+ saved = self.protect_inaccessible
+ for obj, storage in saved:
+ obj._unprotect(storage)
+ self.protect_inaccessible = None
+
class fakearenaaddress(llmemory.fakeaddress):
def __init__(self, arena, offset):
@@ -365,6 +383,16 @@
"""
return Arena(ptr.arena.nbytes, False).getaddr(0)
+def arena_protect(arena_addr, size, inaccessible):
+ """For debugging, set or reset memory protection on an arena.
+ For now, the starting point and size should reference the whole arena.
+ The value of 'inaccessible' is a boolean.
+ """
+ arena_addr = getfakearenaaddress(arena_addr)
+ assert arena_addr.offset == 0
+ assert size == arena_addr.arena.nbytes
+ arena_addr.arena.set_protect(inaccessible)
+
# ____________________________________________________________
#
# Translation support: the functions above turn into the code below.
@@ -475,6 +503,44 @@
# them immediately.
clear_large_memory_chunk = llmemory.raw_memclear
+if os.name == "posix":
+ from pypy.translator.tool.cbuild import ExternalCompilationInfo
+ _eci = ExternalCompilationInfo(includes=['sys/mman.h'])
+ raw_mprotect = rffi.llexternal('mprotect',
+ [llmemory.Address, rffi.SIZE_T, rffi.INT],
+ rffi.INT,
+ sandboxsafe=True, _nowrapper=True,
+ compilation_info=_eci)
+ def llimpl_protect(addr, size, inaccessible):
+ if inaccessible:
+ prot = 0
+ else:
+ from pypy.rlib.rmmap import PROT_READ, PROT_WRITE
+ prot = PROT_READ | PROT_WRITE
+ raw_mprotect(addr, rffi.cast(rffi.SIZE_T, size),
+ rffi.cast(rffi.INT, prot))
+ # ignore potential errors
+ has_protect = True
+
+elif os.name == 'nt':
+ def llimpl_protect(addr, size, inaccessible):
+ from pypy.rlib.rmmap import VirtualProtect, LPDWORD
+ if inaccessible:
+ from pypy.rlib.rmmap import PAGE_NOACCESS as newprotect
+ else:
+ from pypy.rlib.rmmap import PAGE_READWRITE as newprotect
+ arg = lltype.malloc(LPDWORD.TO, 1, zero=True, flavor='raw')
+ VirtualProtect(rffi.cast(rffi.VOIDP, addr),
+ rffi.cast(rffi.SIZE_T, size),
+ newprotect,
+ arg)
+ # ignore potential errors
+ lltype.free(arg, flavor='raw')
+ has_protect = True
+
+else:
+ has_protect = False
+
llimpl_malloc = rffi.llexternal('malloc', [lltype.Signed], llmemory.Address,
sandboxsafe=True, _nowrapper=True)
@@ -544,6 +610,21 @@
'll_arena.arena_new_view', llimpl=llimpl_arena_new_view,
llfakeimpl=arena_new_view, sandboxsafe=True)
+def llimpl_arena_protect(addr, size, inaccessible):
+ if has_protect:
+ # do some alignment
+ start = rffi.cast(lltype.Signed, addr)
+ end = start + size
+ start = (start + 4095) & ~ 4095
+ end = end & ~ 4095
+ if end > start:
+ llimpl_protect(rffi.cast(llmemory.Address, start), end-start,
+ inaccessible)
+register_external(arena_protect, [llmemory.Address, lltype.Signed,
+ lltype.Bool], lltype.Void,
+ 'll_arena.arena_protect', llimpl=llimpl_arena_protect,
+ llfakeimpl=arena_protect, sandboxsafe=True)
+
def llimpl_getfakearenaaddress(addr):
return addr
register_external(getfakearenaaddress, [llmemory.Address], llmemory.Address,
Modified: pypy/branch/out-of-line-guards/pypy/rpython/lltypesystem/llmemory.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/rpython/lltypesystem/llmemory.py (original)
+++ pypy/branch/out-of-line-guards/pypy/rpython/lltypesystem/llmemory.py Thu Dec 9 16:33:59 2010
@@ -93,8 +93,10 @@
return endmarker._as_ptr()
else:
return parent.getitem(index)._as_ptr()
- elif (isinstance(A, lltype.FixedSizeArray) and
- array_item_type_match(A.OF, self.TYPE)):
+ elif ((isinstance(A, lltype.FixedSizeArray)
+ or (isinstance(A, lltype.Array) and A._hints.get('nolength',
+ False)))
+ and array_item_type_match(A.OF, self.TYPE)):
# for array of primitives or pointers
return lltype.direct_ptradd(firstitemptr, self.repeat)
else:
Modified: pypy/branch/out-of-line-guards/pypy/rpython/lltypesystem/lltype.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/rpython/lltypesystem/lltype.py (original)
+++ pypy/branch/out-of-line-guards/pypy/rpython/lltypesystem/lltype.py Thu Dec 9 16:33:59 2010
@@ -1381,6 +1381,15 @@
self._check() # no double-frees
self._storage = None
+ def _protect(self):
+ result = self._storage
+ self._free() # no double-frees or double-protects
+ return result
+
+ def _unprotect(self, saved_storage):
+ assert self._storage is None
+ self._storage = saved_storage
+
def _was_freed(self):
if self._storage is None:
return True
Modified: pypy/branch/out-of-line-guards/pypy/rpython/lltypesystem/rbuiltin.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/rpython/lltypesystem/rbuiltin.py (original)
+++ pypy/branch/out-of-line-guards/pypy/rpython/lltypesystem/rbuiltin.py Thu Dec 9 16:33:59 2010
@@ -42,7 +42,7 @@
return hop.genop('cast_pointer', [v_inst], # v_type implicit in r_result
resulttype = hop.r_result.lowleveltype)
- classdef = s_class.descriptions.keys()[0].getuniqueclassdef()
+ classdef = s_class.any_description().getuniqueclassdef()
return rclass.rtype_new_instance(hop.rtyper, classdef, hop.llops)
def rtype_builtin_hasattr(hop):
Modified: pypy/branch/out-of-line-guards/pypy/rpython/lltypesystem/rclass.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/rpython/lltypesystem/rclass.py (original)
+++ pypy/branch/out-of-line-guards/pypy/rpython/lltypesystem/rclass.py Thu Dec 9 16:33:59 2010
@@ -410,7 +410,7 @@
source_classdef = source_desc.getclassdef(None)
source_repr = getinstancerepr(self.rtyper, source_classdef)
assert len(s_func.descriptions) == 1
- funcdesc = s_func.descriptions.keys()[0]
+ funcdesc, = s_func.descriptions
graph = funcdesc.getuniquegraph()
FUNCTYPE = FuncType([Ptr(source_repr.object_type)], Void)
destrptr = functionptr(FUNCTYPE, graph.name,
Modified: pypy/branch/out-of-line-guards/pypy/rpython/lltypesystem/rdict.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/rpython/lltypesystem/rdict.py (original)
+++ pypy/branch/out-of-line-guards/pypy/rpython/lltypesystem/rdict.py Thu Dec 9 16:33:59 2010
@@ -581,7 +581,7 @@
def ll_dict_lookup_clean(d, hash):
# a simplified version of ll_dict_lookup() which assumes that the
# key is new, and the dictionary doesn't contain deleted entries.
- # It only find the next free slot for the given hash.
+ # It only finds the next free slot for the given hash.
entries = d.entries
mask = len(entries) - 1
i = hash & mask
Modified: pypy/branch/out-of-line-guards/pypy/rpython/lltypesystem/rpbc.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/rpython/lltypesystem/rpbc.py (original)
+++ pypy/branch/out-of-line-guards/pypy/rpython/lltypesystem/rpbc.py Thu Dec 9 16:33:59 2010
@@ -127,7 +127,7 @@
def __init__(self, rtyper, s_pbc):
self.rtyper = rtyper
self.s_pbc = s_pbc
- self.callfamily = s_pbc.descriptions.iterkeys().next().getcallfamily()
+ self.callfamily = s_pbc.any_description().getcallfamily()
concretetable, uniquerows = get_concrete_calltable(self.rtyper,
self.callfamily)
assert len(uniquerows) == 1
@@ -166,7 +166,7 @@
return self, 0
def get_s_signatures(self, shape):
- funcdesc = self.s_pbc.descriptions.iterkeys().next()
+ funcdesc = self.s_pbc.any_description()
return funcdesc.get_s_signatures(shape)
def convert_desc(self, funcdesc):
@@ -230,7 +230,7 @@
bk = self.rtyper.annotator.bookkeeper
args = bk.build_args(opname, hop.args_s[1:])
s_pbc = hop.args_s[0] # possibly more precise than self.s_pbc
- descs = s_pbc.descriptions.keys()
+ descs = list(s_pbc.descriptions)
shape, index = description.FunctionDesc.variant_for_call_site(bk, self.callfamily, descs, args)
row_of_graphs = self.callfamily.calltables[shape][index]
anygraph = row_of_graphs.itervalues().next() # pick any witness
Modified: pypy/branch/out-of-line-guards/pypy/rpython/lltypesystem/test/test_llarena.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/rpython/lltypesystem/test/test_llarena.py (original)
+++ pypy/branch/out-of-line-guards/pypy/rpython/lltypesystem/test/test_llarena.py Thu Dec 9 16:33:59 2010
@@ -6,6 +6,8 @@
from pypy.rpython.lltypesystem.llarena import round_up_for_allocation
from pypy.rpython.lltypesystem.llarena import ArenaError, arena_new_view
from pypy.rpython.lltypesystem.llarena import arena_shrink_obj
+from pypy.rpython.lltypesystem.llarena import arena_protect, has_protect
+from pypy.translator.c.test import test_genc, test_standalone
def test_arena():
S = lltype.Struct('S', ('x',lltype.Signed))
@@ -265,8 +267,7 @@
assert res == 42
def test_compiled():
- from pypy.translator.c.test.test_genc import compile
- fn = compile(test_look_inside_object, [])
+ fn = test_genc.compile(test_look_inside_object, [])
res = fn()
assert res == 42
@@ -282,3 +283,51 @@
arena_reserve(a, size_gc_header + llmemory.sizeof(S, 10))
arena_shrink_obj(a, size_gc_header + llmemory.sizeof(S, 5))
arena_reset(a, size_gc_header + llmemory.sizeof(S, 5), False)
+
+def test_arena_protect():
+ a = arena_malloc(100, False)
+ S = lltype.Struct('S', ('x', lltype.Signed))
+ arena_reserve(a, llmemory.sizeof(S))
+ p = llmemory.cast_adr_to_ptr(a, lltype.Ptr(S))
+ p.x = 123
+ assert p.x == 123
+ arena_protect(a, 100, True)
+ py.test.raises(ArenaError, arena_reserve, a + 48, llmemory.sizeof(S))
+ py.test.raises(RuntimeError, "p.x")
+ py.test.raises(RuntimeError, "p.x = 124")
+ arena_protect(a, 100, False)
+ assert p.x == 123
+ p.x = 125
+ assert p.x == 125
+
+
+class TestStandalone(test_standalone.StandaloneTests):
+ def test_compiled_arena_protect(self):
+ import os
+ from pypy.translator.c.test.test_genc import compile
+ S = lltype.Struct('S', ('x', lltype.Signed))
+ #
+ def fn(argv):
+ testrun = int(argv[1])
+ a = arena_malloc(65536, False)
+ arena_reserve(a, llmemory.sizeof(S))
+ p = llmemory.cast_adr_to_ptr(a + 23432, lltype.Ptr(S))
+ p.x = 123
+ assert p.x == 123
+ arena_protect(a, 65536, True)
+ result = 0
+ if testrun == 1:
+ print p.x # segfault
+ if testrun == 2:
+ p.x = 124 # segfault
+ arena_protect(a, 65536, False)
+ p.x += 10
+ print p.x
+ return 0
+ #
+ t, cbuilder = self.compile(fn)
+ data = cbuilder.cmdexec('0')
+ assert data == '133\n'
+ if has_protect:
+ cbuilder.cmdexec('1', expect_crash=True)
+ cbuilder.cmdexec('2', expect_crash=True)
Modified: pypy/branch/out-of-line-guards/pypy/rpython/memory/gc/base.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/rpython/memory/gc/base.py (original)
+++ pypy/branch/out-of-line-guards/pypy/rpython/memory/gc/base.py Thu Dec 9 16:33:59 2010
@@ -5,7 +5,6 @@
from pypy.rpython.memory.support import get_address_stack, get_address_deque
from pypy.rpython.memory.support import AddressDict
from pypy.rpython.lltypesystem.llmemory import NULL, raw_malloc_usage
-from pypy.rlib.rarithmetic import r_uint
TYPEID_MAP = lltype.GcStruct('TYPEID_MAP', ('count', lltype.Signed),
('size', lltype.Signed),
@@ -19,6 +18,7 @@
malloc_zero_filled = False
prebuilt_gc_objects_are_static_roots = True
object_minimal_size = 0
+ gcflag_extra = 0 # or a real GC flag that is always 0 when not collecting
def __init__(self, config, chunk_size=DEFAULT_CHUNK_SIZE,
translated_to_c=True):
@@ -36,6 +36,12 @@
self.finalizer_lock_count = 0
self.run_finalizers = self.AddressDeque()
+ def post_setup(self):
+ # More stuff that needs to be initialized when the GC is already
+ # fully working. (Only called by gctransform/framework for now.)
+ from pypy.rpython.memory.gc import env
+ self.DEBUG = env.read_from_env('PYPY_GC_DEBUG')
+
def _teardown(self):
pass
@@ -48,7 +54,8 @@
# The following flag enables costly consistency checks after each
# collection. It is automatically set to True by test_gc.py. The
# checking logic is translatable, so the flag can be set to True
- # here before translation.
+ # here before translation. At run-time, if PYPY_GC_DEBUG is set,
+ # then it is also set to True.
DEBUG = False
def set_query_functions(self, is_varsize, has_gcptr_in_varsize,
@@ -410,42 +417,6 @@
GCClass = getattr(module, classname)
return GCClass, GCClass.TRANSLATION_PARAMS
-def _read_float_and_factor_from_env(varname):
- import os
- value = os.environ.get(varname)
- if value:
- if len(value) > 1 and value[-1] in 'bB':
- value = value[:-1]
- realvalue = value[:-1]
- if value[-1] in 'kK':
- factor = 1024
- elif value[-1] in 'mM':
- factor = 1024*1024
- elif value[-1] in 'gG':
- factor = 1024*1024*1024
- else:
- factor = 1
- realvalue = value
- try:
- return (float(realvalue), factor)
- except ValueError:
- pass
- return (0.0, 0)
-
-def read_from_env(varname):
- value, factor = _read_float_and_factor_from_env(varname)
- return int(value * factor)
-
-def read_uint_from_env(varname):
- value, factor = _read_float_and_factor_from_env(varname)
- return r_uint(value * factor)
-
-def read_float_from_env(varname):
- value, factor = _read_float_and_factor_from_env(varname)
- if factor != 1:
- return 0.0
- return value
-
def _convert_callback_formats(callback):
callback = getattr(callback, 'im_func', callback)
if callback not in _converted_callback_formats:
Modified: pypy/branch/out-of-line-guards/pypy/rpython/memory/gc/generation.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/rpython/memory/gc/generation.py (original)
+++ pypy/branch/out-of-line-guards/pypy/rpython/memory/gc/generation.py Thu Dec 9 16:33:59 2010
@@ -2,7 +2,7 @@
from pypy.rpython.memory.gc.semispace import SemiSpaceGC
from pypy.rpython.memory.gc.semispace import GCFLAG_EXTERNAL, GCFLAG_FORWARDED
from pypy.rpython.memory.gc.semispace import GC_HASH_TAKEN_ADDR
-from pypy.rpython.memory.gc.base import read_from_env
+from pypy.rpython.memory.gc import env
from pypy.rpython.lltypesystem.llmemory import NULL, raw_malloc_usage
from pypy.rpython.lltypesystem import lltype, llmemory, llarena
from pypy.rlib.objectmodel import free_non_gc_object
@@ -93,7 +93,7 @@
if self.auto_nursery_size:
newsize = nursery_size_from_env()
if newsize <= 0:
- newsize = estimate_best_nursery_size()
+ newsize = env.estimate_best_nursery_size()
if newsize > 0:
self.set_nursery_size(newsize)
@@ -633,139 +633,5 @@
# ____________________________________________________________
-import os
-
def nursery_size_from_env():
- return read_from_env('PYPY_GENERATIONGC_NURSERY')
-
-def best_nursery_size_for_L2cache(L2cache):
- # Heuristically, the best nursery size to choose is about half
- # of the L2 cache. XXX benchmark some more.
- return L2cache // 2
-
-
-if sys.platform == 'linux2':
- def estimate_best_nursery_size():
- """Try to estimate the best nursery size at run-time, depending
- on the machine we are running on.
- """
- debug_start("gc-L2cache")
- L2cache = sys.maxint
- try:
- fd = os.open('/proc/cpuinfo', os.O_RDONLY, 0644)
- try:
- data = []
- while True:
- buf = os.read(fd, 4096)
- if not buf:
- break
- data.append(buf)
- finally:
- os.close(fd)
- except OSError:
- pass
- else:
- data = ''.join(data)
- linepos = 0
- while True:
- start = findend(data, '\ncache size', linepos)
- if start < 0:
- break # done
- linepos = findend(data, '\n', start)
- if linepos < 0:
- break # no end-of-line??
- # *** data[start:linepos] == " : 2048 KB\n"
- start = skipspace(data, start)
- if data[start] != ':':
- continue
- # *** data[start:linepos] == ": 2048 KB\n"
- start = skipspace(data, start + 1)
- # *** data[start:linepos] == "2048 KB\n"
- end = start
- while '0' <= data[end] <= '9':
- end += 1
- # *** data[start:end] == "2048"
- if start == end:
- continue
- number = int(data[start:end])
- # *** data[end:linepos] == " KB\n"
- end = skipspace(data, end)
- if data[end] not in ('K', 'k'): # assume kilobytes for now
- continue
- number = number * 1024
- # for now we look for the smallest of the L2 caches of the CPUs
- if number < L2cache:
- L2cache = number
-
- debug_print("L2cache =", L2cache)
- debug_stop("gc-L2cache")
-
- if L2cache < sys.maxint:
- return best_nursery_size_for_L2cache(L2cache)
- else:
- # Print a top-level warning even in non-debug builds
- llop.debug_print(lltype.Void,
- "Warning: cannot find your CPU L2 cache size in /proc/cpuinfo")
- return -1
-
- def findend(data, pattern, pos):
- pos = data.find(pattern, pos)
- if pos < 0:
- return -1
- return pos + len(pattern)
-
- def skipspace(data, pos):
- while data[pos] in (' ', '\t'):
- pos += 1
- return pos
-
-elif sys.platform == 'darwin':
- from pypy.rpython.lltypesystem import rffi
-
- sysctlbyname = rffi.llexternal('sysctlbyname',
- [rffi.CCHARP, rffi.VOIDP, rffi.SIZE_TP,
- rffi.VOIDP, rffi.SIZE_T],
- rffi.INT,
- sandboxsafe=True)
-
- def estimate_best_nursery_size():
- """Try to estimate the best nursery size at run-time, depending
- on the machine we are running on.
- """
- debug_start("gc-L2cache")
- L2cache = 0
- l2cache_p = lltype.malloc(rffi.LONGLONGP.TO, 1, flavor='raw')
- try:
- len_p = lltype.malloc(rffi.SIZE_TP.TO, 1, flavor='raw')
- try:
- size = rffi.sizeof(rffi.LONGLONG)
- l2cache_p[0] = rffi.cast(rffi.LONGLONG, 0)
- len_p[0] = rffi.cast(rffi.SIZE_T, size)
- # XXX a hack for llhelper not being robust-enough
- result = sysctlbyname("hw.l2cachesize",
- rffi.cast(rffi.VOIDP, l2cache_p),
- len_p,
- lltype.nullptr(rffi.VOIDP.TO),
- rffi.cast(rffi.SIZE_T, 0))
- if (rffi.cast(lltype.Signed, result) == 0 and
- rffi.cast(lltype.Signed, len_p[0]) == size):
- L2cache = rffi.cast(lltype.Signed, l2cache_p[0])
- if rffi.cast(rffi.LONGLONG, L2cache) != l2cache_p[0]:
- L2cache = 0 # overflow!
- finally:
- lltype.free(len_p, flavor='raw')
- finally:
- lltype.free(l2cache_p, flavor='raw')
- debug_print("L2cache =", L2cache)
- debug_stop("gc-L2cache")
- if L2cache > 0:
- return best_nursery_size_for_L2cache(L2cache)
- else:
- # Print a top-level warning even in non-debug builds
- llop.debug_print(lltype.Void,
- "Warning: cannot find your CPU L2 cache size with sysctl()")
- return -1
-
-else:
- def estimate_best_nursery_size():
- return -1 # XXX implement me for other platforms
+ return env.read_from_env('PYPY_GENERATIONGC_NURSERY')
Modified: pypy/branch/out-of-line-guards/pypy/rpython/memory/gc/inspector.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/rpython/memory/gc/inspector.py (original)
+++ pypy/branch/out-of-line-guards/pypy/rpython/memory/gc/inspector.py Thu Dec 9 16:33:59 2010
@@ -101,21 +101,24 @@
AddressStack = get_address_stack()
-class HeapDumper:
+class HeapDumper(object):
_alloc_flavor_ = "raw"
BUFSIZE = 8192 # words
def __init__(self, gc, fd):
self.gc = gc
+ self.gcflag = gc.gcflag_extra
self.fd = rffi.cast(rffi.INT, fd)
self.writebuffer = lltype.malloc(rffi.LONGP.TO, self.BUFSIZE,
flavor='raw')
self.buf_count = 0
- self.seen = AddressDict()
+ if self.gcflag == 0:
+ self.seen = AddressDict()
self.pending = AddressStack()
def delete(self):
- self.seen.delete()
+ if self.gcflag == 0:
+ self.seen.delete()
self.pending.delete()
lltype.free(self.writebuffer, flavor='raw')
free_non_gc_object(self)
@@ -140,6 +143,8 @@
self.flush()
write._always_inline_ = True
+ # ----------
+
def write_marker(self):
self.write(0)
self.write(0)
@@ -161,9 +166,15 @@
self.add(obj)
def add(self, obj):
- if not self.seen.contains(obj):
- self.seen.setitem(obj, obj)
- self.pending.append(obj)
+ if self.gcflag == 0:
+ if not self.seen.contains(obj):
+ self.seen.setitem(obj, obj)
+ self.pending.append(obj)
+ else:
+ hdr = self.gc.header(obj)
+ if (hdr.tid & self.gcflag) == 0:
+ hdr.tid |= self.gcflag
+ self.pending.append(obj)
def add_roots(self):
self.gc.enumerate_all_roots(_hd_add_root, self)
@@ -177,14 +188,50 @@
while pending.non_empty():
self.writeobj(pending.pop())
+ # ----------
+ # A simplified copy of the above, to make sure we walk again all the
+ # objects to clear the 'gcflag'.
+
+ def unwriteobj(self, obj):
+ gc = self.gc
+ gc.trace(obj, self._unwriteref, None)
+
+ def _unwriteref(self, pointer, _):
+ obj = pointer.address[0]
+ self.unadd(obj)
+
+ def unadd(self, obj):
+ assert self.gcflag != 0
+ hdr = self.gc.header(obj)
+ if (hdr.tid & self.gcflag) != 0:
+ hdr.tid &= ~self.gcflag
+ self.pending.append(obj)
+
+ def clear_gcflag_again(self):
+ self.gc.enumerate_all_roots(_hd_unadd_root, self)
+ pendingroots = self.pending
+ self.pending = AddressStack()
+ self.unwalk(pendingroots)
+ pendingroots.delete()
+
+ def unwalk(self, pending):
+ while pending.non_empty():
+ self.unwriteobj(pending.pop())
+
def _hd_add_root(obj, heap_dumper):
heap_dumper.add(obj)
+def _hd_unadd_root(obj, heap_dumper):
+ heap_dumper.unadd(obj)
+
def dump_rpy_heap(gc, fd):
heapdumper = HeapDumper(gc, fd)
heapdumper.add_roots()
heapdumper.walk(heapdumper.pending)
heapdumper.flush()
+ if heapdumper.gcflag != 0:
+ heapdumper.clear_gcflag_again()
+ heapdumper.unwalk(heapdumper.pending)
heapdumper.delete()
return True
Modified: pypy/branch/out-of-line-guards/pypy/rpython/memory/gc/markcompact.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/rpython/memory/gc/markcompact.py (original)
+++ pypy/branch/out-of-line-guards/pypy/rpython/memory/gc/markcompact.py Thu Dec 9 16:33:59 2010
@@ -1,5 +1,6 @@
from pypy.rpython.lltypesystem import lltype, llmemory, llarena, llgroup
-from pypy.rpython.memory.gc.base import MovingGCBase, read_from_env
+from pypy.rpython.memory.gc.base import MovingGCBase
+from pypy.rpython.memory.gc import env
from pypy.rlib.debug import ll_assert, have_debug_prints
from pypy.rlib.debug import debug_print, debug_start, debug_stop
from pypy.rpython.memory.support import get_address_stack, get_address_deque
@@ -110,10 +111,10 @@
return next
def setup(self):
- envsize = read_from_env('PYPY_MARKCOMPACTGC_MAX')
+ envsize = env.read_from_env('PYPY_MARKCOMPACTGC_MAX')
if envsize >= 4096:
self.space_size = envsize & ~4095
- mincollect = read_from_env('PYPY_MARKCOMPACTGC_MIN')
+ mincollect = env.read_from_env('PYPY_MARKCOMPACTGC_MIN')
if mincollect >= 4096:
self.min_next_collect_after = mincollect
Modified: pypy/branch/out-of-line-guards/pypy/rpython/memory/gc/minimark.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/rpython/memory/gc/minimark.py (original)
+++ pypy/branch/out-of-line-guards/pypy/rpython/memory/gc/minimark.py Thu Dec 9 16:33:59 2010
@@ -3,7 +3,8 @@
Environment variables can be used to fine-tune the following parameters:
PYPY_GC_NURSERY The nursery size. Defaults to half the size of
- the L2 cache. Try values like '1.2MB'.
+ the L2 cache. Try values like '1.2MB'. Small values
+ (like 1 or 1KB) are useful for debugging.
PYPY_GC_MAJOR_COLLECT Major collection memory factor. Default is '1.82',
which means trigger a major collection when the
@@ -12,7 +13,7 @@
collection.
PYPY_GC_GROWTH Major collection threshold's max growth rate.
- Default is '1.3'. Useful to collect more often
+ Default is '1.4'. Useful to collect more often
than normally on sudden memory growth, e.g. when
there is a temporary peak in memory usage.
@@ -22,10 +23,21 @@
crash the program with a fatal error. Try values
like '1.6GB'.
+ PYPY_GC_MAX_DELTA The major collection threshold will never be set
+ to more than PYPY_GC_MAX_DELTA the amount really
+ used after a collection. Defaults to 1/8th of the
+ total RAM size (which is constrained to be at most
+ 2/3/4GB on 32-bit systems). Try values like '200MB'.
+
PYPY_GC_MIN Don't collect while the memory size is below this
limit. Useful to avoid spending all the time in
the GC in very small programs. Defaults to 8
times the nursery.
+
+ PYPY_GC_DEBUG Enable extra checks around collections that are
+ too slow for normal use. Values are 0 (off),
+ 1 (on major collections) or 2 (also on minor
+ collections).
"""
# XXX Should find a way to bound the major collection threshold by the
# XXX total addressable size. Maybe by keeping some minimarkpage arenas
@@ -36,7 +48,7 @@
from pypy.rpython.lltypesystem.lloperation import llop
from pypy.rpython.lltypesystem.llmemory import raw_malloc_usage
from pypy.rpython.memory.gc.base import GCBase, MovingGCBase
-from pypy.rpython.memory.gc import minimarkpage, base, generation
+from pypy.rpython.memory.gc import minimarkpage, env
from pypy.rlib.rarithmetic import ovfcheck, LONG_BIT, intmask, r_uint
from pypy.rlib.rarithmetic import LONG_BIT_SHIFT
from pypy.rlib.debug import ll_assert, debug_print, debug_start, debug_stop
@@ -96,6 +108,7 @@
needs_write_barrier = True
prebuilt_gc_objects_are_static_roots = False
malloc_zero_filled = True # xxx experiment with False
+ gcflag_extra = GCFLAG_FINALIZATION_ORDERING
# All objects start with a HDR, i.e. with a field 'tid' which contains
# a word. This word is divided in two halves: the lower half contains
@@ -154,7 +167,7 @@
# grow at most by the following factor from one collection to the
# next. Used e.g. when there is a sudden, temporary peak in memory
# usage; this avoids that the upper bound grows too fast.
- "growth_rate_max": 1.3,
+ "growth_rate_max": 1.4,
# The number of array indices that are mapped to a single bit in
# write_barrier_from_array(). Must be a power of two. The default
@@ -198,6 +211,7 @@
self.min_heap_size = 0.0
self.max_heap_size = 0.0
self.max_heap_size_already_raised = False
+ self.max_delta = float(r_uint(-1))
#
self.card_page_indices = card_page_indices
if self.card_page_indices > 0:
@@ -215,7 +229,8 @@
self.nursery = NULL
self.nursery_free = NULL
self.nursery_top = NULL
- self.debug_always_do_minor_collect = False
+ self.debug_tiny_nursery = -1
+ self.debug_rotating_nurseries = None
#
# The ArenaCollection() handles the nonmovable objects allocation.
if ArenaCollectionClass is None:
@@ -282,53 +297,71 @@
#
# From there on, the GC is fully initialized and the code
# below can use it
- newsize = base.read_from_env('PYPY_GC_NURSERY')
- # PYPY_GC_NURSERY=1 forces a minor collect for every malloc.
- # Useful to debug external factors, like trackgcroot or the
- # handling of the write barrier.
- self.debug_always_do_minor_collect = newsize == 1
+ newsize = env.read_from_env('PYPY_GC_NURSERY')
+ # PYPY_GC_NURSERY=smallvalue means that minor collects occur
+ # very frequently; the extreme case is PYPY_GC_NURSERY=1, which
+ # forces a minor collect for every malloc. Useful to debug
+ # external factors, like trackgcroot or the handling of the write
+ # barrier. Implemented by still using 'minsize' for the nursery
+ # size (needed to handle e.g. mallocs of 8249 words) but hacking
+ # at the current nursery position in collect_and_reserve().
if newsize <= 0:
- newsize = generation.estimate_best_nursery_size()
+ newsize = env.estimate_best_nursery_size()
if newsize <= 0:
newsize = defaultsize
- newsize = max(newsize, minsize)
+ if newsize < minsize:
+ self.debug_tiny_nursery = newsize & ~(WORD-1)
+ newsize = minsize
#
- major_coll = base.read_float_from_env('PYPY_GC_MAJOR_COLLECT')
+ major_coll = env.read_float_from_env('PYPY_GC_MAJOR_COLLECT')
if major_coll > 1.0:
self.major_collection_threshold = major_coll
#
- growth = base.read_float_from_env('PYPY_GC_GROWTH')
+ growth = env.read_float_from_env('PYPY_GC_GROWTH')
if growth > 1.0:
self.growth_rate_max = growth
#
- min_heap_size = base.read_uint_from_env('PYPY_GC_MIN')
+ min_heap_size = env.read_uint_from_env('PYPY_GC_MIN')
if min_heap_size > 0:
self.min_heap_size = float(min_heap_size)
else:
# defaults to 8 times the nursery
self.min_heap_size = newsize * 8
#
- max_heap_size = base.read_uint_from_env('PYPY_GC_MAX')
+ max_heap_size = env.read_uint_from_env('PYPY_GC_MAX')
if max_heap_size > 0:
self.max_heap_size = float(max_heap_size)
#
+ max_delta = env.read_uint_from_env('PYPY_GC_MAX_DELTA')
+ if max_delta > 0:
+ self.max_delta = float(max_delta)
+ else:
+ self.max_delta = 0.125 * env.get_total_memory()
+ #
self.minor_collection() # to empty the nursery
llarena.arena_free(self.nursery)
self.nursery_size = newsize
self.allocate_nursery()
- def allocate_nursery(self):
- debug_start("gc-set-nursery-size")
- debug_print("nursery size:", self.nursery_size)
+ def _nursery_memory_size(self):
+ extra = self.nonlarge_gcptrs_max + 1
+ return self.nursery_size + extra
+
+ def _alloc_nursery(self):
# the start of the nursery: we actually allocate a bit more for
# the nursery than really needed, to simplify pointer arithmetic
# in malloc_fixedsize_clear(). The few extra pages are never used
# anyway so it doesn't even count.
- extra = self.nonlarge_gcptrs_max + 1
- self.nursery = llarena.arena_malloc(self.nursery_size + extra, 2)
- if not self.nursery:
+ nursery = llarena.arena_malloc(self._nursery_memory_size(), 2)
+ if not nursery:
raise MemoryError("cannot allocate nursery")
+ return nursery
+
+ def allocate_nursery(self):
+ debug_start("gc-set-nursery-size")
+ debug_print("nursery size:", self.nursery_size)
+ self.nursery = self._alloc_nursery()
# the current position in the nursery:
self.nursery_free = self.nursery
# the end of the nursery:
@@ -362,6 +395,39 @@
return bounded
+ def post_setup(self):
+ # set up extra stuff for PYPY_GC_DEBUG.
+ MovingGCBase.post_setup(self)
+ if self.DEBUG and llarena.has_protect:
+ # gc debug mode: allocate 23 nurseries instead of just 1,
+ # and use them alternatively, while mprotect()ing the unused
+ # ones to detect invalid access.
+ debug_start("gc-debug")
+ self.debug_rotating_nurseries = []
+ for i in range(22):
+ nurs = self._alloc_nursery()
+ llarena.arena_protect(nurs, self._nursery_memory_size(), True)
+ self.debug_rotating_nurseries.append(nurs)
+ debug_print("allocated", len(self.debug_rotating_nurseries),
+ "extra nurseries")
+ debug_stop("gc-debug")
+
+ def debug_rotate_nursery(self):
+ if self.debug_rotating_nurseries is not None:
+ debug_start("gc-debug")
+ oldnurs = self.nursery
+ llarena.arena_protect(oldnurs, self._nursery_memory_size(), True)
+ self.debug_rotating_nurseries.append(oldnurs)
+ #
+ newnurs = self.debug_rotating_nurseries.pop(0)
+ llarena.arena_protect(newnurs, self._nursery_memory_size(), False)
+ self.nursery = newnurs
+ self.nursery_top = self.nursery + self.nursery_size
+ debug_print("switching to nursery", self.nursery,
+ "size", self.nursery_size)
+ debug_stop("gc-debug")
+
+
def malloc_fixedsize_clear(self, typeid, size, can_collect=True,
needs_finalizer=False, contains_weakptr=False):
ll_assert(can_collect, "!can_collect")
@@ -499,8 +565,9 @@
self.nursery_free = result + totalsize
ll_assert(self.nursery_free <= self.nursery_top, "nursery overflow")
#
- if self.debug_always_do_minor_collect:
- self.nursery_free = self.nursery_top
+ if self.debug_tiny_nursery >= 0: # for debugging
+ if self.nursery_top - self.nursery_free > self.debug_tiny_nursery:
+ self.nursery_free = self.nursery_top - self.debug_tiny_nursery
#
return result
collect_and_reserve._dont_inline_ = True
@@ -638,8 +705,13 @@
# means recording that they have a smaller size, so that when
# moved out of the nursery, they will consume less memory.
# In particular, an array with GCFLAG_HAS_CARDS is never resized.
+ # Also, a nursery object with GCFLAG_HAS_SHADOW is not resized
+ # either, as this would potentially loose part of the memory in
+ # the already-allocated shadow.
if not self.is_in_nursery(obj):
return False
+ if self.header(obj).tid & GCFLAG_HAS_SHADOW:
+ return False
#
size_gc_header = self.gcheaderbuilder.size_gc_header
typeid = self.get_type_id(obj)
@@ -822,7 +894,7 @@
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:
+ if DEBUG: # note: PYPY_GC_DEBUG=1 does not enable this
ll_assert(not self.is_in_nursery(addr_struct),
"nursery object with GCFLAG_NO_YOUNG_PTRS")
#
@@ -859,7 +931,7 @@
# '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:
+ if DEBUG: # note: PYPY_GC_DEBUG=1 does not enable this
ll_assert(not self.is_in_nursery(addr_array),
"nursery array with GCFLAG_NO_YOUNG_PTRS")
objhdr = self.header(addr_array)
@@ -981,13 +1053,14 @@
# All live nursery objects are out, and the rest dies. Fill
# the whole nursery with zero and reset the current nursery pointer.
llarena.arena_reset(self.nursery, self.nursery_size, 2)
+ self.debug_rotate_nursery()
self.nursery_free = self.nursery
#
debug_print("minor collect, total memory used:",
self.get_total_memory_used())
+ if self.DEBUG >= 2:
+ self.debug_check_consistency() # expensive!
debug_stop("gc-minor")
- if 0: # not we_are_translated():
- self.debug_check_consistency() # xxx expensive!
def collect_roots_in_nursery(self):
@@ -1245,9 +1318,12 @@
#
# Set the threshold for the next major collection to be when we
# have allocated 'major_collection_threshold' times more than
+ # we currently have -- but no more than 'max_delta' more than
# we currently have.
+ total_memory_used = float(self.get_total_memory_used())
bounded = self.set_major_threshold_from(
- self.get_total_memory_used() * self.major_collection_threshold,
+ min(total_memory_used * self.major_collection_threshold,
+ total_memory_used + self.max_delta),
reserving_size)
#
# Max heap size: gives an upper bound on the threshold. If we
@@ -1406,12 +1482,21 @@
size = self.get_size(obj)
shadowhdr = self._malloc_out_of_nursery(size_gc_header +
size)
- # initialize to an invalid tid *without* GCFLAG_VISITED,
- # so that if the object dies before the next minor
- # collection, the shadow will stay around but be collected
- # by the next major collection.
+ # Initialize the shadow enough to be considered a
+ # valid gc object. If the original object stays
+ # alive at the next minor collection, it will anyway
+ # be copied over the shadow and overwrite the
+ # following fields. But if the object dies, then
+ # the shadow will stay around and only be freed at
+ # the next major collection, at which point we want
+ # it to look valid (but ready to be freed).
shadow = shadowhdr + size_gc_header
- self.header(shadow).tid = 0
+ self.header(shadow).tid = self.header(obj).tid
+ typeid = self.get_type_id(obj)
+ if self.is_varsize(typeid):
+ lenofs = self.varsize_offset_to_length(typeid)
+ (shadow + lenofs).signed[0] = (obj + lenofs).signed[0]
+ #
self.header(obj).tid |= GCFLAG_HAS_SHADOW
self.young_objects_shadows.setitem(obj, shadow)
#
Modified: pypy/branch/out-of-line-guards/pypy/rpython/memory/gc/semispace.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/rpython/memory/gc/semispace.py (original)
+++ pypy/branch/out-of-line-guards/pypy/rpython/memory/gc/semispace.py Thu Dec 9 16:33:59 2010
@@ -42,6 +42,7 @@
inline_simple_malloc_varsize = True
malloc_zero_filled = True
first_unused_gcflag = first_gcflag << 5
+ gcflag_extra = GCFLAG_FINALIZATION_ORDERING
HDR = lltype.Struct('header', ('tid', lltype.Signed)) # XXX or rffi.INT?
typeid_is_in_field = 'tid'
Modified: pypy/branch/out-of-line-guards/pypy/rpython/memory/gc/test/test_direct.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/rpython/memory/gc/test/test_direct.py (original)
+++ pypy/branch/out-of-line-guards/pypy/rpython/memory/gc/test/test_direct.py Thu Dec 9 16:33:59 2010
@@ -60,7 +60,7 @@
pass
-class DirectGCTest(object):
+class BaseDirectGCTest(object):
GC_PARAMS = {}
def setup_method(self, meth):
@@ -106,6 +106,9 @@
addr = self.gc.malloc(self.get_type_id(TYPE), n, zero=True)
return llmemory.cast_adr_to_ptr(addr, lltype.Ptr(TYPE))
+
+class DirectGCTest(BaseDirectGCTest):
+
def test_simple(self):
p = self.malloc(S)
p.x = 5
@@ -339,6 +342,15 @@
self.gc.collect()
assert hash == self.gc.identityhash(self.stackroots[-1])
self.stackroots.pop()
+ # (7) the same, but the objects are dying young
+ for i in range(10):
+ self.gc.collect()
+ p = self.malloc(VAR, i)
+ self.stackroots.append(p)
+ hash1 = self.gc.identityhash(p)
+ hash2 = self.gc.identityhash(p)
+ assert hash1 == hash2
+ self.stackroots.pop()
def test_memory_alignment(self):
A1 = lltype.GcArray(lltype.Char)
Modified: pypy/branch/out-of-line-guards/pypy/rpython/memory/gctransform/asmgcroot.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/rpython/memory/gctransform/asmgcroot.py (original)
+++ pypy/branch/out-of-line-guards/pypy/rpython/memory/gctransform/asmgcroot.py Thu Dec 9 16:33:59 2010
@@ -139,12 +139,13 @@
self._shape_decompressor = ShapeDecompressor()
if hasattr(gctransformer.translator, '_jit2gc'):
jit2gc = gctransformer.translator._jit2gc
- self._extra_gcmapstart = jit2gc['gcmapstart']
- self._extra_gcmapend = jit2gc['gcmapend']
+ self._extra_gcmapstart = jit2gc['gcmapstart']
+ self._extra_gcmapend = jit2gc['gcmapend']
+ self._extra_mark_sorted = jit2gc['gcmarksorted']
else:
- returns_null = lambda: llmemory.NULL
- self._extra_gcmapstart = returns_null
- self._extra_gcmapend = returns_null
+ self._extra_gcmapstart = lambda: llmemory.NULL
+ self._extra_gcmapend = lambda: llmemory.NULL
+ self._extra_mark_sorted = lambda: True
def need_thread_support(self, gctransformer, getfn):
# Threads supported "out of the box" by the rest of the code.
@@ -295,14 +296,16 @@
# we have a non-empty JIT-produced table to look in
item = search_in_gcmap2(gcmapstart2, gcmapend2, retaddr)
if item:
- self._shape_decompressor.setaddr(item.address[1])
+ self._shape_decompressor.setaddr(item)
return
# maybe the JIT-produced table is not sorted?
- sort_gcmap(gcmapstart2, gcmapend2)
- item = search_in_gcmap2(gcmapstart2, gcmapend2, retaddr)
- if item:
- self._shape_decompressor.setaddr(item.address[1])
- return
+ was_already_sorted = self._extra_mark_sorted()
+ if not was_already_sorted:
+ sort_gcmap(gcmapstart2, gcmapend2)
+ item = search_in_gcmap2(gcmapstart2, gcmapend2, retaddr)
+ if item:
+ self._shape_decompressor.setaddr(item)
+ return
# the item may have been not found because the main array was
# not sorted. Sort it and try again.
win32_follow_gcmap_jmp(gcmapstart, gcmapend)
@@ -357,7 +360,8 @@
The interval from the start address (included) to the end address
(excluded) is assumed to be a sorted arrays of pairs (addr1, addr2).
This searches for the item with a given addr1 and returns its
- address.
+ address. If not found exactly, it tries to return the address
+ of the item left of addr1 (i.e. such that result.address[0] < addr1).
"""
count = (end - start) // arrayitemsize
while count > 1:
@@ -386,7 +390,7 @@
# (item.signed[1] is an address in this case, not a signed at all!)
item = binary_search(gcmapstart, gcmapend, retaddr)
if item.address[0] == retaddr:
- return item # found
+ return item.address[1] # found
else:
return llmemory.NULL # failed
Modified: pypy/branch/out-of-line-guards/pypy/rpython/memory/gctransform/boehm.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/rpython/memory/gctransform/boehm.py (original)
+++ pypy/branch/out-of-line-guards/pypy/rpython/memory/gctransform/boehm.py Thu Dec 9 16:33:59 2010
@@ -120,10 +120,11 @@
fptr = self.annotate_finalizer(d['ll_finalizer'], [llmemory.Address], lltype.Void)
elif destrptr:
EXC_INSTANCE_TYPE = self.translator.rtyper.exceptiondata.lltype_of_exception_value
+ typename = TYPE.__name__
def ll_finalizer(addr):
exc_instance = llop.gc_fetch_exception(EXC_INSTANCE_TYPE)
v = llmemory.cast_adr_to_ptr(addr, DESTR_ARG)
- ll_call_destructor(destrptr, v)
+ ll_call_destructor(destrptr, v, typename)
llop.gc_restore_exception(lltype.Void, exc_instance)
fptr = self.annotate_finalizer(ll_finalizer, [llmemory.Address], lltype.Void)
else:
Modified: pypy/branch/out-of-line-guards/pypy/rpython/memory/gctransform/framework.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/rpython/memory/gctransform/framework.py (original)
+++ pypy/branch/out-of-line-guards/pypy/rpython/memory/gctransform/framework.py Thu Dec 9 16:33:59 2010
@@ -189,6 +189,7 @@
# run-time initialization code
root_walker.setup_root_walker()
gcdata.gc.setup()
+ gcdata.gc.post_setup()
def frameworkgc__teardown():
# run-time teardown code for tests!
@@ -1204,9 +1205,10 @@
assert not type_contains_pyobjs(TYPE), "not implemented"
if destrptr:
+ typename = TYPE.__name__
def ll_finalizer(addr):
v = llmemory.cast_adr_to_ptr(addr, DESTR_ARG)
- ll_call_destructor(destrptr, v)
+ ll_call_destructor(destrptr, v, typename)
fptr = self.transformer.annotate_finalizer(ll_finalizer,
[llmemory.Address],
lltype.Void)
Modified: pypy/branch/out-of-line-guards/pypy/rpython/memory/gctransform/refcounting.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/rpython/memory/gctransform/refcounting.py (original)
+++ pypy/branch/out-of-line-guards/pypy/rpython/memory/gctransform/refcounting.py Thu Dec 9 16:33:59 2010
@@ -227,7 +227,7 @@
# refcount is at zero, temporarily bump it to 1:
gcheader.refcount = 1
destr_v = cast_pointer(DESTR_ARG, v)
- ll_call_destructor(destrptr, destr_v)
+ ll_call_destructor(destrptr, destr_v, %r)
refcount = gcheader.refcount - 1
gcheader.refcount = refcount
if refcount == 0:
@@ -239,7 +239,7 @@
pop_alive(exc_instance)
# XXX layering of exceptiontransform versus gcpolicy
-""" % (body, TYPE._gckind)
+""" % (TYPE.__name__, body, TYPE._gckind)
else:
call_del = None
body = '\n'.join(_static_deallocator_body_for_type('v', TYPE))
Modified: pypy/branch/out-of-line-guards/pypy/rpython/memory/gctransform/support.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/rpython/memory/gctransform/support.py (original)
+++ pypy/branch/out-of-line-guards/pypy/rpython/memory/gctransform/support.py Thu Dec 9 16:33:59 2010
@@ -98,11 +98,15 @@
hop.exception_cannot_occur()
return hop.inputconst(hop.r_result.lowleveltype, hop.s_result.const)
-def ll_call_destructor(destrptr, destr_v):
+def ll_call_destructor(destrptr, destr_v, typename):
try:
destrptr(destr_v)
- except:
+ except Exception, e:
try:
- os.write(2, "a destructor raised an exception, ignoring it\n")
+ os.write(2, "a destructor of type ")
+ os.write(2, typename)
+ os.write(2, " raised an exception ")
+ os.write(2, str(e))
+ os.write(2, " ignoring it\n")
except:
pass
Modified: pypy/branch/out-of-line-guards/pypy/rpython/module/ll_os.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/rpython/module/ll_os.py (original)
+++ pypy/branch/out-of-line-guards/pypy/rpython/module/ll_os.py Thu Dec 9 16:33:59 2010
@@ -1386,6 +1386,25 @@
return extdef([], (int, int), "ll_os.ll_os_openpty",
llimpl=openpty_llimpl)
+ @registering_if(os, 'forkpty')
+ def register_os_forkpty(self):
+ os_forkpty = self.llexternal(
+ 'forkpty',
+ [rffi.INTP, rffi.VOIDP, rffi.VOIDP, rffi.VOIDP],
+ rffi.PID_T,
+ compilation_info=ExternalCompilationInfo(libraries=['util']))
+ def forkpty_llimpl():
+ master_p = lltype.malloc(rffi.INTP.TO, 1, flavor='raw')
+ childpid = os_forkpty(master_p, None, None, None)
+ master_fd = master_p[0]
+ lltype.free(master_p, flavor='raw')
+ if childpid == -1:
+ raise OSError(rposix.get_errno(), "os_forkpty failed")
+ return (rffi.cast(lltype.Signed, childpid),
+ rffi.cast(lltype.Signed, master_fd))
+
+ return extdef([], (int, int), "ll_os.ll_os_forkpty",
+ llimpl=forkpty_llimpl)
@registering(os._exit)
def register_os__exit(self):
Modified: pypy/branch/out-of-line-guards/pypy/rpython/module/ll_time.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/rpython/module/ll_time.py (original)
+++ pypy/branch/out-of-line-guards/pypy/rpython/module/ll_time.py Thu Dec 9 16:33:59 2010
@@ -41,7 +41,7 @@
RUSAGE = platform.Struct('struct rusage', [('ru_utime', TIMEVAL),
('ru_stime', TIMEVAL)])
-if sys.platform == 'freebsd7':
+if "freebsd" in sys.platform:
libraries = ['compat']
else:
libraries = []
Modified: pypy/branch/out-of-line-guards/pypy/rpython/ootypesystem/rpbc.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/rpython/ootypesystem/rpbc.py (original)
+++ pypy/branch/out-of-line-guards/pypy/rpython/ootypesystem/rpbc.py Thu Dec 9 16:33:59 2010
@@ -49,7 +49,7 @@
return hop.genop('runtimenew', [v_class], resulttype=resulttype)
def getlowleveltype(self):
- classdescs = self.s_pbc.descriptions.keys()
+ classdescs = list(self.s_pbc.descriptions)
# if any of the classdefs get the lowleveltype ootype.Class,
# we can only pick ootype.Class for us too. Otherwise META.
for classdesc in classdescs:
@@ -70,7 +70,7 @@
class MethodImplementations(object):
def __init__(self, rtyper, methdescs):
- samplemdesc = methdescs.iterkeys().next()
+ samplemdesc = iter(methdescs).next()
concretetable, uniquerows = get_concrete_calltable(rtyper,
samplemdesc.funcdesc.getcallfamily())
self.row_mapping = {}
@@ -117,7 +117,7 @@
concretetable = None # set by _setup_repr_final
def _setup_repr_final(self):
- sampledesc = self.s_pbc.descriptions.iterkeys().next()
+ sampledesc = self.s_pbc.any_description()
self.concretetable, _ = get_concrete_calltable(self.rtyper,
sampledesc.funcdesc.getcallfamily())
Modified: pypy/branch/out-of-line-guards/pypy/rpython/rlist.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/rpython/rlist.py (original)
+++ pypy/branch/out-of-line-guards/pypy/rpython/rlist.py Thu Dec 9 16:33:59 2010
@@ -9,7 +9,7 @@
from pypy.rpython import robject
from pypy.rlib.objectmodel import malloc_zero_filled
from pypy.rlib.debug import ll_assert
-from pypy.rlib.rarithmetic import ovfcheck, widen
+from pypy.rlib.rarithmetic import ovfcheck, widen, r_uint, intmask
from pypy.rpython.annlowlevel import ADTInterface
from pypy.rlib import rgc
@@ -241,17 +241,22 @@
class __extend__(pairtype(AbstractBaseListRepr, IntegerRepr)):
def rtype_getitem((r_lst, r_int), hop, checkidx=False):
+ v_lst, v_index = hop.inputargs(r_lst, Signed)
if checkidx:
- spec = dum_checkidx
+ hop.exception_is_here()
else:
- spec = dum_nocheck
- v_func = hop.inputconst(Void, spec)
- v_lst, v_index = hop.inputargs(r_lst, Signed)
+ hop.exception_cannot_occur()
if hop.args_s[0].listdef.listitem.mutated or checkidx:
if hop.args_s[1].nonneg:
llfn = ll_getitem_nonneg
else:
llfn = ll_getitem
+ if checkidx:
+ spec = dum_checkidx
+ else:
+ spec = dum_nocheck
+ c_func_marker = hop.inputconst(Void, spec)
+ v_res = hop.gendirectcall(llfn, c_func_marker, v_lst, v_index)
else:
# this is the 'foldable' version, which is not used when
# we check for IndexError
@@ -259,11 +264,7 @@
llfn = ll_getitem_foldable_nonneg
else:
llfn = ll_getitem_foldable
- if checkidx:
- hop.exception_is_here()
- else:
- hop.exception_cannot_occur()
- v_res = hop.gendirectcall(llfn, v_func, v_lst, v_index)
+ v_res = hop.gendirectcall(llfn, v_lst, v_index)
return r_lst.recast(hop.llops, v_res)
rtype_getitem_key = rtype_getitem
@@ -538,12 +539,14 @@
dest.ll_setitem_fast(dest_start + i, item)
i += 1
ll_arraycopy._annenforceargs_ = [None, None, int, int, int]
+# no oopspec -- the function is inlined by the JIT
def ll_copy(RESLIST, l):
length = l.ll_length()
new_lst = RESLIST.ll_newlist(length)
ll_arraycopy(l, new_lst, 0, 0, length)
return new_lst
+# no oopspec -- the function is inlined by the JIT
def ll_len(l):
return l.ll_length()
@@ -551,6 +554,7 @@
def ll_list_is_true(l):
# check if a list is True, allowing for None
return bool(l) and l.ll_length() != 0
+# no oopspec -- the function is inlined by the JIT
def ll_len_foldable(l):
return l.ll_length()
@@ -558,6 +562,7 @@
def ll_list_is_true_foldable(l):
return bool(l) and ll_len_foldable(l) != 0
+# no oopspec -- the function is inlined by the JIT
def ll_append(l, newitem):
length = l.ll_length()
@@ -588,6 +593,7 @@
ll_arraycopy(l1, l, 0, 0, len1)
ll_arraycopy(l2, l, 0, len1, len2)
return l
+# no oopspec -- the function is inlined by the JIT
def ll_insert_nonneg(l, index, newitem):
length = l.ll_length()
@@ -674,60 +680,72 @@
l.ll_setitem_fast(length_1_i, tmp)
i += 1
length_1_i -= 1
+ll_reverse.oopspec = 'list.reverse(l)'
def ll_getitem_nonneg(func, l, index):
ll_assert(index >= 0, "unexpectedly negative list getitem index")
if func is dum_checkidx:
if index >= l.ll_length():
raise IndexError
- else:
- ll_assert(index < l.ll_length(), "list getitem index out of bound")
return l.ll_getitem_fast(index)
-ll_getitem_nonneg.oopspec = 'list.getitem(l, index)'
+ll_getitem_nonneg._always_inline_ = True
+# no oopspec -- the function is inlined by the JIT
def ll_getitem(func, l, index):
- length = l.ll_length()
- if index < 0:
- index += length
if func is dum_checkidx:
- if index < 0 or index >= length:
- raise IndexError
+ length = l.ll_length() # common case: 0 <= index < length
+ if r_uint(index) >= r_uint(length):
+ # Failed, so either (-length <= index < 0), or we have to raise
+ # IndexError. First add 'length' to get the final index, then
+ # check that we now have (0 <= index < length).
+ index = r_uint(index) + r_uint(length)
+ if index >= r_uint(length):
+ raise IndexError
+ index = intmask(index)
else:
- ll_assert(index >= 0, "negative list getitem index out of bound")
- ll_assert(index < length, "list getitem index out of bound")
+ # We don't want checking, but still want to support index < 0.
+ # Only call ll_length() if needed.
+ if index < 0:
+ index += l.ll_length()
+ ll_assert(index >= 0, "negative list getitem index out of bound")
return l.ll_getitem_fast(index)
-ll_getitem.oopspec = 'list.getitem(l, index)'
+# no oopspec -- the function is inlined by the JIT
-def ll_getitem_foldable_nonneg(func, l, index):
- return ll_getitem_nonneg(func, l, index)
+def ll_getitem_foldable_nonneg(l, index):
+ ll_assert(index >= 0, "unexpectedly negative list getitem index")
+ return l.ll_getitem_fast(index)
ll_getitem_foldable_nonneg.oopspec = 'list.getitem_foldable(l, index)'
-def ll_getitem_foldable(func, l, index):
- return ll_getitem(func, l, index)
-ll_getitem_foldable.oopspec = 'list.getitem_foldable(l, index)'
+def ll_getitem_foldable(l, index):
+ if index < 0:
+ index += l.ll_length()
+ return ll_getitem_foldable_nonneg(l, index)
+ll_getitem_foldable._always_inline_ = True
+# no oopspec -- the function is inlined by the JIT
def ll_setitem_nonneg(func, l, index, newitem):
ll_assert(index >= 0, "unexpectedly negative list setitem index")
if func is dum_checkidx:
if index >= l.ll_length():
raise IndexError
- else:
- ll_assert(index < l.ll_length(), "list setitem index out of bound")
l.ll_setitem_fast(index, newitem)
-ll_setitem_nonneg.oopspec = 'list.setitem(l, index, newitem)'
+ll_setitem_nonneg._always_inline_ = True
+# no oopspec -- the function is inlined by the JIT
def ll_setitem(func, l, index, newitem):
- length = l.ll_length()
- if index < 0:
- index += length
if func is dum_checkidx:
- if index < 0 or index >= length:
- raise IndexError
+ length = l.ll_length()
+ if r_uint(index) >= r_uint(length): # see comments in ll_getitem().
+ index = r_uint(index) + r_uint(length)
+ if index >= r_uint(length):
+ raise IndexError
+ index = intmask(index)
else:
- ll_assert(index >= 0, "negative list setitem index out of bound")
- ll_assert(index < length, "list setitem index out of bound")
+ if index < 0:
+ index += l.ll_length()
+ ll_assert(index >= 0, "negative list setitem index out of bound")
l.ll_setitem_fast(index, newitem)
-ll_setitem.oopspec = 'list.setitem(l, index, newitem)'
+# no oopspec -- the function is inlined by the JIT
def ll_delitem_nonneg(func, l, index):
ll_assert(index >= 0, "unexpectedly negative list delitem index")
@@ -751,19 +769,20 @@
l._ll_resize_le(newlength)
ll_delitem_nonneg.oopspec = 'list.delitem(l, index)'
-def ll_delitem(func, l, i):
- length = l.ll_length()
- if i < 0:
- i += length
+def ll_delitem(func, l, index):
if func is dum_checkidx:
- if i < 0 or i >= length:
- raise IndexError
+ length = l.ll_length()
+ if r_uint(index) >= r_uint(length): # see comments in ll_getitem().
+ index = r_uint(index) + r_uint(length)
+ if index >= r_uint(length):
+ raise IndexError
+ index = intmask(index)
else:
- ll_assert(i >= 0, "negative list delitem index out of bound")
- ll_assert(i < length, "list delitem index out of bound")
- ll_delitem_nonneg(dum_nocheck, l, i)
-ll_delitem.oopspec = 'list.delitem(l, i)'
-
+ if index < 0:
+ index += l.ll_length()
+ ll_assert(index >= 0, "negative list delitem index out of bound")
+ ll_delitem_nonneg(dum_nocheck, l, index)
+# no oopspec -- the function is inlined by the JIT
def ll_extend(l1, l2):
len1 = l1.ll_length()
@@ -799,6 +818,7 @@
lst.ll_setitem_fast(j, c)
i += 1
j += 1
+# not inlined by the JIT -- contains a loop
def ll_extend_with_str_slice_startstop(lst, s, getstrlen, getstritem,
start, stop):
@@ -824,6 +844,7 @@
lst.ll_setitem_fast(j, c)
i += 1
j += 1
+# not inlined by the JIT -- contains a loop
def ll_extend_with_str_slice_minusone(lst, s, getstrlen, getstritem):
len1 = lst.ll_length()
@@ -843,6 +864,7 @@
lst.ll_setitem_fast(j, c)
i += 1
j += 1
+# not inlined by the JIT -- contains a loop
def ll_extend_with_char_count(lst, char, count):
if count <= 0:
@@ -859,6 +881,7 @@
while j < newlength:
lst.ll_setitem_fast(j, char)
j += 1
+# not inlined by the JIT -- contains a loop
def ll_listslice_startonly(RESLIST, l1, start):
len1 = l1.ll_length()
@@ -869,6 +892,7 @@
ll_arraycopy(l1, l, start, 0, newlength)
return l
ll_listslice_startonly._annenforceargs_ = (None, None, int)
+# no oopspec -- the function is inlined by the JIT
def ll_listslice_startstop(RESLIST, l1, start, stop):
length = l1.ll_length()
@@ -881,6 +905,7 @@
l = RESLIST.ll_newlist(newlength)
ll_arraycopy(l1, l, start, 0, newlength)
return l
+# no oopspec -- the function is inlined by the JIT
def ll_listslice_minusone(RESLIST, l1):
newlength = l1.ll_length() - 1
@@ -888,6 +913,7 @@
l = RESLIST.ll_newlist(newlength)
ll_arraycopy(l1, l, 0, 0, newlength)
return l
+# no oopspec -- the function is inlined by the JIT
def ll_listdelslice_startonly(l, start):
ll_assert(start >= 0, "del l[start:] with unexpectedly negative start")
@@ -958,6 +984,7 @@
return False
j += 1
return True
+# not inlined by the JIT -- contains a loop
def ll_listcontains(lst, obj, eqfn):
lng = lst.ll_length()
@@ -971,6 +998,7 @@
return True
j += 1
return False
+# not inlined by the JIT -- contains a loop
def ll_listindex(lst, obj, eqfn):
lng = lst.ll_length()
@@ -984,6 +1012,7 @@
return j
j += 1
raise ValueError # can't say 'list.index(x): x not in list'
+# not inlined by the JIT -- contains a loop
def ll_listremove(lst, obj, eqfn):
index = ll_listindex(lst, obj, eqfn) # raises ValueError if obj not in lst
@@ -1030,3 +1059,4 @@
i += 1
j += length
return res
+# not inlined by the JIT -- contains a loop
Modified: pypy/branch/out-of-line-guards/pypy/rpython/rpbc.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/rpython/rpbc.py (original)
+++ pypy/branch/out-of-line-guards/pypy/rpython/rpbc.py Thu Dec 9 16:33:59 2010
@@ -15,11 +15,10 @@
from pypy.rpython import callparse
-
def small_cand(rtyper, s_pbc):
if 1 < len(s_pbc.descriptions) < rtyper.getconfig().translation.withsmallfuncsets and \
hasattr(rtyper.type_system.rpbc, 'SmallFunctionSetPBCRepr'):
- callfamily = s_pbc.descriptions.iterkeys().next().getcallfamily()
+ callfamily = s_pbc.any_description().getcallfamily()
concretetable, uniquerows = get_concrete_calltable(rtyper, callfamily)
if len(uniquerows) == 1 and (not s_pbc.subset_of or small_cand(rtyper, s_pbc.subset_of)):
return True
@@ -31,7 +30,7 @@
return none_frozen_pbc_repr
kind = self.getKind()
if issubclass(kind, description.FunctionDesc):
- sample = self.descriptions.keys()[0]
+ sample = self.any_description()
callfamily = sample.querycallfamily()
if callfamily and callfamily.total_calltable_size > 0:
if sample.overridden:
@@ -181,7 +180,7 @@
def __init__(self, rtyper, s_pbc):
self.rtyper = rtyper
self.s_pbc = s_pbc
- self.callfamily = s_pbc.descriptions.iterkeys().next().getcallfamily()
+ self.callfamily = s_pbc.any_description().getcallfamily()
if len(s_pbc.descriptions) == 1 and not s_pbc.can_be_None:
# a single function
self.lowleveltype = Void
@@ -207,7 +206,7 @@
return self, 0
def get_s_signatures(self, shape):
- funcdesc = self.s_pbc.descriptions.iterkeys().next()
+ funcdesc = self.s_pbc.any_description()
return funcdesc.get_s_signatures(shape)
## def function_signatures(self):
@@ -322,7 +321,7 @@
bk = self.rtyper.annotator.bookkeeper
args = bk.build_args(opname, hop.args_s[1:])
s_pbc = hop.args_s[0] # possibly more precise than self.s_pbc
- descs = s_pbc.descriptions.keys()
+ descs = list(s_pbc.descriptions)
shape, index = description.FunctionDesc.variant_for_call_site(bk, self.callfamily, descs, args)
row_of_graphs = self.callfamily.calltables[shape][index]
anygraph = row_of_graphs.itervalues().next() # pick any witness
@@ -368,7 +367,7 @@
return robject.pyobj_repr
def getFrozenPBCRepr(rtyper, s_pbc):
- descs = s_pbc.descriptions.keys()
+ descs = list(s_pbc.descriptions)
assert len(descs) >= 1
if len(descs) == 1 and not s_pbc.can_be_None:
return SingleFrozenPBCRepr(descs[0])
@@ -530,7 +529,7 @@
def __init__(self, rtyper, s_pbc):
self.rtyper = rtyper
- self.funcdesc = s_pbc.descriptions.keys()[0].funcdesc
+ self.funcdesc = s_pbc.any_description().funcdesc
# a hack to force the underlying function to show up in call_families
# (generally not needed, as normalizecalls() should ensure this,
@@ -662,7 +661,7 @@
and the ClassRepr of the class which stores this attribute in
its vtable.
"""
- classdescs = self.s_pbc.descriptions.keys()
+ classdescs = list(self.s_pbc.descriptions)
access = classdescs[0].queryattrfamily(attrname)
for classdesc in classdescs[1:]:
access1 = classdesc.queryattrfamily(attrname)
@@ -819,7 +818,7 @@
if s_pbc.isNone():
raise TyperError("unsupported: variable of type "
"bound-method-object or None")
- mdescs = s_pbc.descriptions.keys()
+ mdescs = list(s_pbc.descriptions)
methodname = mdescs[0].name
classdef = mdescs[0].selfclassdef
flags = mdescs[0].flags
Modified: pypy/branch/out-of-line-guards/pypy/rpython/test/test_rclass.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/rpython/test/test_rclass.py (original)
+++ pypy/branch/out-of-line-guards/pypy/rpython/test/test_rclass.py Thu Dec 9 16:33:59 2010
@@ -910,7 +910,7 @@
assert destrptr is not None
def test_del_inheritance(self):
- import gc
+ from pypy.rlib import rgc
class State:
pass
s = State()
@@ -931,8 +931,7 @@
A()
B()
C()
- gc.collect()
- gc.collect()
+ rgc.collect()
return s.a_dels * 10 + s.b_dels
res = f()
assert res == 42
@@ -1094,6 +1093,7 @@
assert meth.finalizer
def test_del_inheritance(self):
+ from pypy.rlib import rgc
class State:
pass
s = State()
@@ -1114,6 +1114,7 @@
A()
B()
C()
+ rgc.collect()
return s.a_dels * 10 + s.b_dels
res = f()
assert res == 42
Modified: pypy/branch/out-of-line-guards/pypy/rpython/test/test_rint.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/rpython/test/test_rint.py (original)
+++ pypy/branch/out-of-line-guards/pypy/rpython/test/test_rint.py Thu Dec 9 16:33:59 2010
@@ -4,14 +4,9 @@
from pypy.annotation import model as annmodel
from pypy.rpython.test import snippet
from pypy.rlib.rarithmetic import r_int, r_uint, r_longlong, r_ulonglong
-from pypy.rlib.rarithmetic import ovfcheck
+from pypy.rlib.rarithmetic import ovfcheck, r_int64
from pypy.rpython.test.tool import BaseRtypingTest, LLRtypeMixin, OORtypeMixin
-if r_longlong is not r_int:
- int64 = r_longlong
-else:
- int64 = int
-
class TestSnippet(object):
@@ -110,10 +105,10 @@
def f(i):
return str(i)
- res = self.interpret(f, [int64(0)])
+ res = self.interpret(f, [r_int64(0)])
assert self.ll_to_string(res) == '0'
- res = self.interpret(f, [int64(413974738222117)])
+ res = self.interpret(f, [r_int64(413974738222117)])
assert self.ll_to_string(res) == '413974738222117'
def test_unsigned(self):
@@ -135,7 +130,7 @@
f._annspecialcase_ = "specialize:argtype(0)"
def g(n):
if n > 0:
- return f(int64(0))
+ return f(r_int64(0))
else:
return f(0)
res = self.interpret(g, [0])
@@ -147,7 +142,7 @@
def test_downcast_int(self):
def f(i):
return int(i)
- res = self.interpret(f, [int64(0)])
+ res = self.interpret(f, [r_int64(0)])
assert res == 0
def test_isinstance_vs_int_types(self):
@@ -157,7 +152,7 @@
return [None]
if isinstance(x, str):
return x
- if isinstance(x, int64):
+ if isinstance(x, r_int64):
return int(x)
return "XXX"
wrap._annspecialcase_ = 'specialize:argtype(0)'
@@ -165,7 +160,7 @@
space = FakeSpace()
def wrap(x):
return space.wrap(x)
- res = self.interpret(wrap, [int64(0)])
+ res = self.interpret(wrap, [r_int64(0)])
assert res == 0
def test_truediv(self):
@@ -178,25 +173,25 @@
def test_float_conversion(self):
def f(ii):
return float(ii)
- res = self.interpret(f, [int64(100000000)])
+ res = self.interpret(f, [r_int64(100000000)])
assert type(res) is float
assert res == 100000000.
- res = self.interpret(f, [int64(1234567890123456789)])
+ res = self.interpret(f, [r_int64(1234567890123456789)])
assert type(res) is float
assert self.float_eq(res, 1.2345678901234568e+18)
def test_float_conversion_implicit(self):
def f(ii):
return 1.0 + ii
- res = self.interpret(f, [int64(100000000)])
+ res = self.interpret(f, [r_int64(100000000)])
assert type(res) is float
assert res == 100000001.
- res = self.interpret(f, [int64(1234567890123456789)])
+ res = self.interpret(f, [r_int64(1234567890123456789)])
assert type(res) is float
assert self.float_eq(res, 1.2345678901234568e+18)
def test_rarithmetic(self):
- inttypes = [int, r_uint, int64, r_ulonglong]
+ inttypes = [int, r_uint, r_int64, r_ulonglong]
for inttype in inttypes:
c = inttype()
def f():
@@ -231,16 +226,16 @@
res = self.interpret(f, [int(-1<<(r_int.BITS-1))])
assert res == 0
- res = self.interpret(f, [int64(-1)])
+ res = self.interpret(f, [r_int64(-1)])
assert res == 1
- res = self.interpret(f, [int64(-1)<<(r_longlong.BITS-1)])
+ res = self.interpret(f, [r_int64(-1)<<(r_longlong.BITS-1)])
assert res == 0
div_mod_iteration_count = 1000
def test_div_mod(self):
import random
- for inttype in (int, int64):
+ for inttype in (int, r_int64):
def d(x, y):
return x/y
@@ -303,7 +298,7 @@
except ZeroDivisionError:
return 84
- for inttype in (int, int64):
+ for inttype in (int, r_int64):
args = [( 5, 2), (-5, 2), ( 5,-2), (-5,-2),
( 6, 2), (-6, 2), ( 6,-2), (-6,-2),
Modified: pypy/branch/out-of-line-guards/pypy/rpython/test/test_rlist.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/rpython/test/test_rlist.py (original)
+++ pypy/branch/out-of-line-guards/pypy/rpython/test/test_rlist.py Thu Dec 9 16:33:59 2010
@@ -12,6 +12,7 @@
from pypy.rpython.rint import signed_repr
from pypy.objspace.flow.model import Constant, Variable
from pypy.rpython.test.tool import BaseRtypingTest, LLRtypeMixin, OORtypeMixin
+from pypy.rlib.debug import ll_assert
# undo the specialization parameter
for n1 in 'get set del'.split():
@@ -1076,7 +1077,13 @@
res = self.interpret(f, [0])
assert res == 1
- py.test.raises(AssertionError, self.interpret, f, [1])
+ if self.type_system == 'lltype':
+ # on lltype we always get an AssertionError
+ py.test.raises(AssertionError, self.interpret, f, [1])
+ else:
+ # on ootype we happen to get through the ll_asserts and to
+ # hit the IndexError from ootype.py
+ self.interpret_raises(IndexError, f, [1])
def f(x):
l = [1]
@@ -1121,12 +1128,13 @@
res = self.interpret(f, [0])
assert res == 1
- try:
- self.interpret_raises(IndexError, f, [1])
- except (AssertionError,), e:
- pass
+ if self.type_system == 'lltype':
+ # on lltype we always get an AssertionError
+ py.test.raises(AssertionError, self.interpret, f, [1])
else:
- assert False
+ # on ootype we happen to get through the ll_asserts and to
+ # hit the IndexError from ootype.py
+ self.interpret_raises(IndexError, f, [1])
def f(x):
l = [1]
@@ -1163,12 +1171,13 @@
res = self.interpret(f, [0])
assert res == 1
- try:
- self.interpret_raises(IndexError, f, [1])
- except (AssertionError,), e:
- pass
+ if self.type_system == 'lltype':
+ # on lltype we always get an AssertionError
+ py.test.raises(AssertionError, self.interpret, f, [1])
else:
- assert False
+ # on ootype we happen to get through the ll_asserts and to
+ # hit the IndexError from ootype.py
+ self.interpret_raises(IndexError, f, [1])
def test_charlist_extension_1(self):
def f(n):
@@ -1327,8 +1336,32 @@
res = self.interpret(f, [2])
assert res == True
+ def test_immutable_list_out_of_instance(self):
+ from pypy.translator.simplify import get_funcobj
+ for immutable_fields in (["a", "b"], ["a", "b", "y[*]"]):
+ class A(object):
+ _immutable_fields_ = immutable_fields
+ class B(A):
+ pass
+ def f(i):
+ b = B()
+ lst = [i]
+ lst[0] += 1
+ b.y = lst
+ ll_assert(b.y is lst, "copying when reading out the attr?")
+ return b.y[0]
+ res = self.interpret(f, [10])
+ assert res == 11
+ t, rtyper, graph = self.gengraph(f, [int])
+ block = graph.startblock
+ op = block.operations[-1]
+ assert op.opname == 'direct_call'
+ func = get_funcobj(op.args[0].value)._callable
+ assert ('foldable' in func.func_name) == \
+ ("y[*]" in immutable_fields)
class TestLLtype(BaseTestRlist, LLRtypeMixin):
+ type_system = 'lltype'
rlist = ll_rlist
def test_memoryerror(self):
@@ -1420,14 +1453,16 @@
lst2 = [i]
lst2.append(42) # mutated list
return lst1[i] + lst2[i]
- _, _, graph = self.gengraph(f, [int])
+ from pypy.annotation import model as annmodel
+ _, _, graph = self.gengraph(f, [annmodel.SomeInteger(nonneg=True)])
block = graph.startblock
lst1_getitem_op = block.operations[-3] # XXX graph fishing
lst2_getitem_op = block.operations[-2]
func1 = lst1_getitem_op.args[0].value._obj._callable
func2 = lst2_getitem_op.args[0].value._obj._callable
assert func1.oopspec == 'list.getitem_foldable(l, index)'
- assert func2.oopspec == 'list.getitem(l, index)'
+ assert not hasattr(func2, 'oopspec')
class TestOOtype(BaseTestRlist, OORtypeMixin):
rlist = oo_rlist
+ type_system = 'ootype'
Modified: pypy/branch/out-of-line-guards/pypy/tool/ansi_print.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/tool/ansi_print.py (original)
+++ pypy/branch/out-of-line-guards/pypy/tool/ansi_print.py Thu Dec 9 16:33:59 2010
@@ -16,6 +16,7 @@
'WARNING': ((31,), False),
'event': ((1,), True),
'ERROR': ((1, 31), False),
+ 'Error': ((1, 31), False),
'info': ((35,), False),
'stub': ((34,), False),
}
Modified: pypy/branch/out-of-line-guards/pypy/tool/error.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/tool/error.py (original)
+++ pypy/branch/out-of-line-guards/pypy/tool/error.py Thu Dec 9 16:33:59 2010
@@ -120,7 +120,7 @@
msg.append(" (%s getting at the binding!)" % (
e.__class__.__name__,))
return
- for desc in descs.keys():
+ for desc in list(descs):
func = desc.pyobj
if func is None:
r = repr(desc)
Modified: pypy/branch/out-of-line-guards/pypy/tool/logparser.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/tool/logparser.py (original)
+++ pypy/branch/out-of-line-guards/pypy/tool/logparser.py Thu Dec 9 16:33:59 2010
@@ -12,14 +12,6 @@
from pypy.tool import progressbar
def parse_log_file(filename, verbose=True):
- r_start = re.compile(r"\[([0-9a-fA-F]+)\] \{([\w-]+)$")
- r_stop = re.compile(r"\[([0-9a-fA-F]+)\] ([\w-]+)\}$")
- lasttime = 0
- log = DebugLog()
- time_decrase = False
- performance_log = True
- nested = 0
- #
f = open(filename, 'r')
if f.read(2) == 'BZ':
f.close()
@@ -30,19 +22,33 @@
lines = f.readlines()
f.close()
#
- if sys.stdout.isatty():
+ return parse_log(lines, verbose=verbose)
+
+def parse_log(lines, verbose=False):
+ color = "(?:\x1b.*?m)?"
+ r_start = re.compile(color + r"\[([0-9a-fA-F]+)\] \{([\w-]+)" + color + "$")
+ r_stop = re.compile(color + r"\[([0-9a-fA-F]+)\] ([\w-]+)\}" + color + "$")
+ lasttime = 0
+ log = DebugLog()
+ time_decrase = False
+ performance_log = True
+ nested = 0
+ #
+ if verbose and sys.stdout.isatty():
progress = progressbar.ProgressBar(color='green')
+ counter = 0
+ else:
+ progress = None
single_percent = len(lines) / 100
if verbose:
- vnext = single_percent
+ vnext = 0
else:
- vnext = len(lines)
- counter = 0
+ vnext = -1
for i, line in enumerate(lines):
if i == vnext:
- counter += 1
- if sys.stdout.isatty():
+ if progress is not None:
progress.render(counter)
+ counter += 1
vnext += single_percent
else:
sys.stderr.write('%d%%..' % int(100.0*i/len(lines)))
Modified: pypy/branch/out-of-line-guards/pypy/tool/release/force-builds.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/tool/release/force-builds.py (original)
+++ pypy/branch/out-of-line-guards/pypy/tool/release/force-builds.py Thu Dec 9 16:33:59 2010
@@ -20,8 +20,8 @@
'own-linux-x86-32',
'own-linux-x86-64',
# 'own-macosx-x86-32',
- 'pypy-c-app-level-linux-x86-32',
- 'pypy-c-app-level-linux-x86-64',
+# 'pypy-c-app-level-linux-x86-32',
+# 'pypy-c-app-level-linux-x86-64',
'pypy-c-stackless-app-level-linux-x86-32',
'pypy-c-app-level-win-x86-32',
'pypy-c-jit-linux-x86-32',
Modified: pypy/branch/out-of-line-guards/pypy/tool/release/make_release.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/tool/release/make_release.py (original)
+++ pypy/branch/out-of-line-guards/pypy/tool/release/make_release.py Thu Dec 9 16:33:59 2010
@@ -30,7 +30,8 @@
else:
xml = override_xml
dom = minidom.parseString(xml)
- refs = [node.getAttribute('href') for node in dom.getElementsByTagName('a')]
+ refs = [node.getAttribute('href') for node in dom.getElementsByTagName('a')
+ if 'pypy' in node.getAttribute('href')]
# all refs are of form: pypy-{type}-{revision}-{platform}.tar.bz2
r = re.compile('pypy-c-([\w\d]+)-(\d+)-([\w\d]+).tar.bz2$')
d = {}
Modified: pypy/branch/out-of-line-guards/pypy/tool/release/package.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/tool/release/package.py (original)
+++ pypy/branch/out-of-line-guards/pypy/tool/release/package.py Thu Dec 9 16:33:59 2010
@@ -1,8 +1,12 @@
#!/usr/bin/env python
""" A sample script that packages PyPy, provided that it's already built.
-Usage:
+It uses 'pypy/translator/goal/pypy-c' and parts of the rest of the working
+copy. Usage:
-package.py pypydir [name-of-archive] [name-of-pypy-c]
+ package.py root-pypy-dir [name-of-archive] [name-of-pypy-c]
+
+Usually you would do: package.py ../../.. pypy-VER-PLATFORM.
+The output is found in the directory /tmp/usession-YOURNAME/build/.
"""
import autopath
@@ -32,7 +36,7 @@
class PyPyCNotFound(Exception):
pass
-def package(basedir, name='pypy-nightly', rename_pypy_c='pypy-c',
+def package(basedir, name='pypy-nightly', rename_pypy_c='pypy',
copy_to_dir = None, override_pypy_c = None):
basedir = py.path.local(basedir)
if sys.platform == 'win32':
@@ -64,13 +68,17 @@
headers = includedir.listdir('*.h') + includedir.listdir('*.inl')
for n in headers:
shutil.copy(str(n), str(pypydir.join('include')))
+ #
+ spdir = pypydir.ensure('site-packages', dir=True)
+ shutil.copy(str(basedir.join('site-packages', 'README')), str(spdir))
+ #
pypydir.ensure('bin', dir=True)
archive_pypy_c = pypydir.join('bin', rename_pypy_c)
shutil.copy(str(pypy_c), str(archive_pypy_c))
old_dir = os.getcwd()
try:
os.chdir(str(builddir))
- os.system("strip " + str(archive_pypy_c)) # ignore errors
+ os.system("strip -x " + str(archive_pypy_c)) # ignore errors
if USE_TARFILE_MODULE:
import tarfile
tf = tarfile.open(str(builddir.join(name + '.tar.bz2')), 'w:bz2')
Modified: pypy/branch/out-of-line-guards/pypy/tool/release/test/test_package.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/tool/release/test/test_package.py (original)
+++ pypy/branch/out-of-line-guards/pypy/tool/release/test/test_package.py Thu Dec 9 16:33:59 2010
@@ -18,7 +18,7 @@
prefix = builddir.join(test)
cpyver = '%d.%d.%d' % CPYTHON_VERSION[:3]
assert prefix.join('lib-python', cpyver, 'test').check()
- assert prefix.join('bin', 'pypy-c').check()
+ assert prefix.join('bin', 'pypy').check()
assert prefix.join('lib_pypy', 'syslog.py').check()
assert not prefix.join('lib_pypy', 'py').check()
assert not prefix.join('lib_pypy', 'ctypes_configure').check()
Modified: pypy/branch/out-of-line-guards/pypy/translator/c/funcgen.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/translator/c/funcgen.py (original)
+++ pypy/branch/out-of-line-guards/pypy/translator/c/funcgen.py Thu Dec 9 16:33:59 2010
@@ -1,3 +1,4 @@
+import sys
from pypy.translator.c.support import USESLOTS # set to False if necessary while refactoring
from pypy.translator.c.support import cdecl
from pypy.translator.c.support import llvalue_from_constant, gen_assignments
@@ -757,6 +758,16 @@
format.append('%s')
argv.append('(%s) ? "True" : "False"' % self.expr(arg))
continue
+ elif T == SignedLongLong:
+ if sys.platform == 'win32':
+ format.append('%I64d')
+ else:
+ format.append('%lld')
+ elif T == UnsignedLongLong:
+ if sys.platform == 'win32':
+ format.append('%I64u')
+ else:
+ format.append('%llu')
else:
raise Exception("don't know how to debug_print %r" % (T,))
argv.append(self.expr(arg))
@@ -765,17 +776,20 @@
"if (PYPY_HAVE_DEBUG_PRINTS) { fprintf(PYPY_DEBUG_FILE, %s); %s}"
% (', '.join(argv), free_line))
+ def _op_debug(self, opname, arg):
+ if isinstance(arg, Constant):
+ string_literal = c_string_constant(''.join(arg.value.chars))
+ return "%s(%s);" % (opname, string_literal)
+ else:
+ x = "%s(RPyString_AsCharP(%s));\n" % (opname, self.expr(arg))
+ x += "RPyString_FreeCache();"
+ return x
+
def OP_DEBUG_START(self, op):
- arg = op.args[0]
- assert isinstance(arg, Constant)
- return "PYPY_DEBUG_START(%s);" % (
- c_string_constant(''.join(arg.value.chars)),)
+ return self._op_debug('PYPY_DEBUG_START', op.args[0])
def OP_DEBUG_STOP(self, op):
- arg = op.args[0]
- assert isinstance(arg, Constant)
- return "PYPY_DEBUG_STOP(%s);" % (
- c_string_constant(''.join(arg.value.chars)),)
+ return self._op_debug('PYPY_DEBUG_STOP', op.args[0])
def OP_DEBUG_ASSERT(self, op):
return 'RPyAssert(%s, %s);' % (self.expr(op.args[0]),
Modified: pypy/branch/out-of-line-guards/pypy/translator/c/gcc/test/test_trackgcroot.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/translator/c/gcc/test/test_trackgcroot.py (original)
+++ pypy/branch/out-of-line-guards/pypy/translator/c/gcc/test/test_trackgcroot.py Thu Dec 9 16:33:59 2010
@@ -98,14 +98,13 @@
"""
lines = source.splitlines(True)
parts = list(DarwinAssemblerParser().find_functions(iter(lines)))
- assert len(parts) == 7
+ assert len(parts) == 6
assert parts[0] == (False, lines[:3])
assert parts[1] == (True, lines[3:7])
assert parts[2] == (True, lines[7:11])
- assert parts[3] == (True, lines[11:13])
- assert parts[4] == (False, lines[13:18])
- assert parts[5] == (True, lines[18:20])
- assert parts[6] == (False, lines[20:])
+ assert parts[3] == (True, lines[11:18])
+ assert parts[4] == (True, lines[18:20])
+ assert parts[5] == (False, lines[20:])
def test_computegcmaptable():
tests = []
Modified: pypy/branch/out-of-line-guards/pypy/translator/c/gcc/trackgcroot.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/translator/c/gcc/trackgcroot.py (original)
+++ pypy/branch/out-of-line-guards/pypy/translator/c/gcc/trackgcroot.py Thu Dec 9 16:33:59 2010
@@ -1106,7 +1106,7 @@
format = 'darwin64'
function_names_prefix = '_'
- LABEL = ElfFunctionGcRootTracker32.LABEL
+ LABEL = ElfFunctionGcRootTracker64.LABEL
r_jmptable_item = re.compile(r"\t.(?:long|quad)\t"+LABEL+"(-\"?[A-Za-z0-9$]+\"?)?\s*$")
r_functionstart = re.compile(r"_(\w+):\s*$")
@@ -1405,6 +1405,7 @@
'const_data'
]
r_sectionstart = re.compile(r"\t\.("+'|'.join(OTHERSECTIONS)+").*$")
+ sections_doesnt_end_function = {'cstring': True, 'const': True}
def find_functions(self, iterlines):
functionlines = []
@@ -1412,20 +1413,20 @@
in_function = False
for n, line in enumerate(iterlines):
if self.r_textstart.match(line):
- assert not in_text, "unexpected repeated .text start: %d" % n
in_text = True
elif self.r_sectionstart.match(line):
- if in_function:
+ sectionname = self.r_sectionstart.match(line).group(1)
+ if (in_function and
+ sectionname not in self.sections_doesnt_end_function):
yield in_function, functionlines
functionlines = []
+ in_function = False
in_text = False
- in_function = False
elif in_text and self.FunctionGcRootTracker.r_functionstart.match(line):
yield in_function, functionlines
functionlines = []
in_function = True
functionlines.append(line)
-
if functionlines:
yield in_function, functionlines
@@ -1442,23 +1443,6 @@
format = "mingw32"
FunctionGcRootTracker = Mingw32FunctionGcRootTracker
- def find_functions(self, iterlines):
- functionlines = []
- in_text = False
- in_function = False
- for n, line in enumerate(iterlines):
- if self.r_textstart.match(line):
- in_text = True
- elif self.r_sectionstart.match(line):
- in_text = False
- elif in_text and self.FunctionGcRootTracker.r_functionstart.match(line):
- yield in_function, functionlines
- functionlines = []
- in_function = True
- functionlines.append(line)
- if functionlines:
- yield in_function, functionlines
-
class MsvcAssemblerParser(AssemblerParser):
format = "msvc"
FunctionGcRootTracker = MsvcFunctionGcRootTracker
Modified: pypy/branch/out-of-line-guards/pypy/translator/c/src/debug_alloc.h
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/translator/c/src/debug_alloc.h (original)
+++ pypy/branch/out-of-line-guards/pypy/translator/c/src/debug_alloc.h Thu Dec 9 16:33:59 2010
@@ -1,5 +1,5 @@
/**************************************************************/
- /*** tracking raw mallocs and frees for debugging ***/
+/*** tracking raw mallocs and frees for debugging ***/
#ifndef RPY_ASSERT
@@ -62,8 +62,8 @@
count++;
if (count > 0)
{
- fprintf(stderr, "debug_alloc.h: %ld mallocs left", count);
char *env = getenv("PYPY_ALLOC");
+ fprintf(stderr, "debug_alloc.h: %ld mallocs left", count);
if (env && *env)
{
fprintf(stderr, " (most recent first):\n");
Modified: pypy/branch/out-of-line-guards/pypy/translator/c/src/debug_print.h
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/translator/c/src/debug_print.h (original)
+++ pypy/branch/out-of-line-guards/pypy/translator/c/src/debug_print.h Thu Dec 9 16:33:59 2010
@@ -72,7 +72,11 @@
{
char *filename = getenv("PYPYLOG");
if (filename)
+#ifndef MS_WINDOWS
unsetenv("PYPYLOG"); /* don't pass it to subprocesses */
+#else
+ putenv("PYPYLOG="); /* don't pass it to subprocesses */
+#endif
if (filename && filename[0])
{
char *colon = strchr(filename, ':');
Modified: pypy/branch/out-of-line-guards/pypy/translator/c/src/mem.h
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/translator/c/src/mem.h (original)
+++ pypy/branch/out-of-line-guards/pypy/translator/c/src/mem.h Thu Dec 9 16:33:59 2010
@@ -233,4 +233,4 @@
#define OP_GC_GET_RPY_MEMORY_USAGE(x, r) r = -1
#define OP_GC_GET_RPY_TYPE_INDEX(x, r) r = -1
#define OP_GC_IS_RPY_INSTANCE(x, r) r = 0
-#define OP_GC_DUMP_RPY_HEAP(r) r = 0
+#define OP_GC_DUMP_RPY_HEAP(fd, r) r = 0
Modified: pypy/branch/out-of-line-guards/pypy/translator/c/test/test_newgc.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/translator/c/test/test_newgc.py (original)
+++ pypy/branch/out-of-line-guards/pypy/translator/c/test/test_newgc.py Thu Dec 9 16:33:59 2010
@@ -1064,14 +1064,16 @@
def test_get_rpy_type_index(self):
self.run("get_rpy_type_index")
- filename_dump = str(udir.join('test_dump_rpy_heap'))
+ filename1_dump = str(udir.join('test_dump_rpy_heap.1'))
+ filename2_dump = str(udir.join('test_dump_rpy_heap.2'))
def define_dump_rpy_heap(self):
U = lltype.GcForwardReference()
U.become(lltype.GcStruct('U', ('next', lltype.Ptr(U)),
('x', lltype.Signed)))
S = lltype.GcStruct('S', ('u', lltype.Ptr(U)))
A = lltype.GcArray(lltype.Ptr(S))
- filename = self.filename_dump
+ filename1 = self.filename1_dump
+ filename2 = self.filename2_dump
def fn():
s = lltype.malloc(S)
@@ -1081,20 +1083,31 @@
a = lltype.malloc(A, 1000)
s2 = lltype.malloc(S)
#
- fd = os.open(filename, os.O_WRONLY | os.O_CREAT, 0666)
- rgc.dump_rpy_heap(fd)
+ fd1 = os.open(filename1, os.O_WRONLY | os.O_CREAT, 0666)
+ fd2 = os.open(filename2, os.O_WRONLY | os.O_CREAT, 0666)
+ rgc.dump_rpy_heap(fd1)
+ rgc.dump_rpy_heap(fd2) # try twice in a row
keepalive_until_here(s2)
keepalive_until_here(s)
keepalive_until_here(a)
- os.close(fd)
+ os.close(fd1)
+ os.close(fd2)
return 0
return fn
def test_dump_rpy_heap(self):
self.run("dump_rpy_heap")
- assert os.path.exists(self.filename_dump)
- assert os.path.getsize(self.filename_dump) > 64
+ for fn in [self.filename1_dump, self.filename2_dump]:
+ assert os.path.exists(fn)
+ assert os.path.getsize(fn) > 64
+ f = open(self.filename1_dump)
+ data1 = f.read()
+ f.close()
+ f = open(self.filename2_dump)
+ data2 = f.read()
+ f.close()
+ assert data1 == data2
filename_dump_typeids_z = str(udir.join('test_typeids_z'))
def define_write_typeids_z(self):
Modified: pypy/branch/out-of-line-guards/pypy/translator/c/test/test_standalone.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/translator/c/test/test_standalone.py (original)
+++ pypy/branch/out-of-line-guards/pypy/translator/c/test/test_standalone.py Thu Dec 9 16:33:59 2010
@@ -272,7 +272,7 @@
x = "got:"
debug_start ("mycat")
if have_debug_prints(): x += "b"
- debug_print ("foo", 2, "bar", 3)
+ debug_print ("foo", r_longlong(2), "bar", 3)
debug_start ("cat2")
if have_debug_prints(): x += "c"
debug_print ("baz")
@@ -403,6 +403,20 @@
assert not err
assert path.check(file=0)
+ def test_debug_print_start_stop_nonconst(self):
+ def entry_point(argv):
+ debug_start(argv[1])
+ debug_print(argv[2])
+ debug_stop(argv[1])
+ return 0
+ t, cbuilder = self.compile(entry_point)
+ out, err = cbuilder.cmdexec("foo bar", err=True, env={'PYPYLOG': ':-'})
+ lines = err.splitlines()
+ assert '{foo' in lines[0]
+ assert 'bar' == lines[1]
+ assert 'foo}' in lines[2]
+
+
def test_fatal_error(self):
def g(x):
if x == 1:
Modified: pypy/branch/out-of-line-guards/pypy/translator/driver.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/translator/driver.py (original)
+++ pypy/branch/out-of-line-guards/pypy/translator/driver.py Thu Dec 9 16:33:59 2010
@@ -11,7 +11,7 @@
from pypy.annotation import policy as annpolicy
import optparse
from pypy.tool.udir import udir
-from pypy.rlib.jit import DEBUG_OFF, DEBUG_DETAILED, DEBUG_PROFILE, DEBUG_STEPS
+from pypy.tool.debug_print import debug_start, debug_print, debug_stop
from pypy.rlib.entrypoint import secondary_entrypoints
import py
@@ -37,13 +37,6 @@
'c': 'lltype',
}
-JIT_DEBUG = {
- 'off' : DEBUG_OFF,
- 'profile' : DEBUG_PROFILE,
- 'steps' : DEBUG_STEPS,
- 'detailed' : DEBUG_DETAILED,
-}
-
def backend_to_typesystem(backend):
return _BACKEND_TO_TYPESYSTEM.get(backend, 'ootype')
@@ -283,6 +276,8 @@
return
else:
self.log.info("%s..." % title)
+ debug_start('translation-task')
+ debug_print('starting', goal)
self.timer.start_event(goal)
try:
instrument = False
@@ -300,11 +295,13 @@
assert False, 'we should not get here'
finally:
try:
+ debug_stop('translation-task')
self.timer.end_event(goal)
except (KeyboardInterrupt, SystemExit):
raise
except:
pass
+ #import gc; gc.dump_rpy_heap('rpyheap-after-%s.dump' % goal)
return res
def task_annotate(self):
@@ -399,7 +396,6 @@
#
from pypy.jit.metainterp.warmspot import apply_jit
apply_jit(self.translator, policy=self.jitpolicy,
- debug_level=JIT_DEBUG[self.config.translation.jit_debug],
backend_name=self.config.translation.jit_backend, inline=True)
#
self.log.info("the JIT compiler was generated")
@@ -417,7 +413,6 @@
#
from pypy.jit.metainterp.warmspot import apply_jit
apply_jit(self.translator, policy=self.jitpolicy,
- debug_level=JIT_DEBUG[self.config.translation.jit_debug],
backend_name='cli', inline=True) #XXX
#
self.log.info("the JIT compiler was generated")
Modified: pypy/branch/out-of-line-guards/pypy/translator/goal/app_main.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/translator/goal/app_main.py (original)
+++ pypy/branch/out-of-line-guards/pypy/translator/goal/app_main.py Thu Dec 9 16:33:59 2010
@@ -11,6 +11,7 @@
-h, --help show this help message and exit
-m library module to be run as a script (terminates option list)
-W arg warning control (arg is action:message:category:module:lineno)
+ -E ignore environment variables (such as PYTHONPATH)
--version print the PyPy version
--info print translation information about this PyPy executable
"""
@@ -199,7 +200,7 @@
break # found!
return newpath
-def setup_initial_paths(executable, nanos):
+def setup_initial_paths(executable, nanos, readenv=True, **extra):
# a substituted os if we are translated
global os
os = nanos
@@ -220,7 +221,7 @@
sys.executable = os.path.abspath(executable)
newpath = get_library_path(executable)
- path = os.getenv('PYTHONPATH')
+ path = readenv and os.getenv('PYTHONPATH')
if path:
newpath = path.split(os.pathsep) + newpath
# remove duplicates
@@ -230,7 +231,6 @@
if dir not in _seen:
sys.path.append(dir)
_seen[dir] = True
- return executable
def parse_command_line(argv):
@@ -242,6 +242,7 @@
run_stdin = False
warnoptions = []
unbuffered = False
+ readenv = True
while i < len(argv):
arg = argv[i]
if not arg.startswith('-'):
@@ -253,6 +254,8 @@
argv[i] = '-c'
run_command = True
break
+ elif arg == '-E':
+ readenv = False
elif arg == '-u':
unbuffered = True
elif arg == '-O' or arg == '-OO':
@@ -305,11 +308,13 @@
run_stdin,
warnoptions,
unbuffered,
+ readenv,
cmd=None,
**ignored):
# with PyPy in top of CPython we can only have around 100
- # but we need more in the translated PyPy for the compiler package
- sys.setrecursionlimit(5000)
+ # but we need more in the translated PyPy for the compiler package
+ if '__pypy__' not in sys.builtin_module_names:
+ sys.setrecursionlimit(5000)
if unbuffered:
set_unbuffered_io()
@@ -355,7 +360,7 @@
# * PYTHONINSPECT is set and stdin is a tty.
#
return (go_interactive or
- (os.getenv('PYTHONINSPECT') and sys.stdin.isatty()))
+ (readenv and os.getenv('PYTHONINSPECT') and sys.stdin.isatty()))
success = True
@@ -388,7 +393,7 @@
# If stdin is a tty or if "-i" is specified, we print
# a banner and run $PYTHONSTARTUP.
print_banner()
- python_startup = os.getenv('PYTHONSTARTUP')
+ python_startup = readenv and os.getenv('PYTHONSTARTUP')
if python_startup:
try:
f = open(python_startup)
@@ -451,7 +456,6 @@
'"license" for more information.')
def entry_point(executable, argv, nanos):
- executable = setup_initial_paths(executable, nanos)
try:
cmdline = parse_command_line(argv)
except CommandLineError, e:
@@ -459,8 +463,8 @@
return 2
if cmdline is None:
return 0
- else:
- return run_command_line(**cmdline)
+ setup_initial_paths(executable, nanos, **cmdline)
+ return run_command_line(**cmdline)
if __name__ == '__main__':
@@ -495,13 +499,13 @@
sys.pypy_version_info = PYPY_VERSION
sys.pypy_initial_path = pypy_initial_path
os = nanos.os_module_for_testing
- sys.ps1 = '>>>> '
- sys.ps2 = '.... '
try:
sys.exit(int(entry_point(sys.argv[0], sys.argv[1:], os)))
finally:
- sys.ps1 = '>>> ' # restore the normal ones, in case
- sys.ps2 = '... ' # we are dropping to CPython's prompt
+ # restore the normal prompt (which was changed by _pypy_interact), in
+ # case we are dropping to CPython's prompt
+ sys.ps1 = '>>> '
+ sys.ps2 = '... '
import os; os.environ.update(reset)
assert old_argv is sys.argv
assert old_path is sys.path
Modified: pypy/branch/out-of-line-guards/pypy/translator/goal/test2/test_app_main.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/translator/goal/test2/test_app_main.py (original)
+++ pypy/branch/out-of-line-guards/pypy/translator/goal/test2/test_app_main.py Thu Dec 9 16:33:59 2010
@@ -217,6 +217,38 @@
finally:
os.environ['PYTHONSTARTUP'] = old
+ def test_ignore_python_startup(self):
+ old = os.environ.get('PYTHONSTARTUP', '')
+ try:
+ os.environ['PYTHONSTARTUP'] = crashing_demo_script
+ child = self.spawn(['-E'])
+ child.expect(re.escape(banner))
+ index = child.expect(['Traceback', '>>> '])
+ assert index == 1 # no traceback
+ finally:
+ os.environ['PYTHONSTARTUP'] = old
+
+ def test_ignore_python_inspect(self):
+ os.environ['PYTHONINSPECT_'] = '1'
+ try:
+ child = self.spawn(['-E', '-c', 'pass'])
+ from pexpect import EOF
+ index = child.expect(['>>> ', EOF])
+ assert index == 1 # no prompt
+ finally:
+ del os.environ['PYTHONINSPECT_']
+
+ def test_ignore_python_path(self):
+ old = os.environ.get('PYTHONPATH', '')
+ try:
+ os.environ['PYTHONPATH'] = 'foobarbaz'
+ child = self.spawn(['-E', '-c', 'import sys; print sys.path'])
+ from pexpect import EOF
+ index = child.expect(['foobarbaz', EOF])
+ assert index == 1 # no foobarbaz
+ finally:
+ os.environ['PYTHONPATH'] = old
+
def test_unbuffered(self):
line = 'import os,sys;sys.stdout.write(str(789));os.read(0,1)'
child = self.spawn(['-u', '-c', line])
@@ -329,6 +361,10 @@
child = self.spawn(['-mpypy.translator.goal.test2.mymodule'])
child.expect('mymodule running')
+ def test_ps1_only_if_interactive(self):
+ argv = ['-c', 'import sys; print hasattr(sys, "ps1")']
+ child = self.spawn(argv)
+ child.expect('False')
class TestNonInteractive:
@@ -534,7 +570,8 @@
newpath = app_main.get_library_path('/tmp/pypy-c') # stdlib not found
assert newpath == sys.path
newpath = app_main.get_library_path(self.fake_exe)
- assert newpath == self.expected_path
+ # we get at least 'expected_path', and maybe more (e.g.plat-linux2)
+ assert newpath[:len(self.expected_path)] == self.expected_path
finally:
sys.path.pop()
@@ -547,7 +584,9 @@
app_main.os = os
pypy_c = os.path.join(self.trunkdir, 'pypy', 'translator', 'goal', 'pypy-c')
newpath = app_main.get_library_path(pypy_c)
- assert len(newpath) == 3
+ # we get at least lib_pypy, lib-python/modified-X.Y.Z,
+ # lib-python/X.Y.Z, and maybe more (e.g. plat-linux2)
+ assert len(newpath) >= 3
for p in newpath:
assert p.startswith(self.trunkdir)
finally:
Modified: pypy/branch/out-of-line-guards/pypy/translator/platform/__init__.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/translator/platform/__init__.py (original)
+++ pypy/branch/out-of-line-guards/pypy/translator/platform/__init__.py Thu Dec 9 16:33:59 2010
@@ -123,7 +123,9 @@
errorfile.write(stderr, 'wb')
stderrlines = stderr.splitlines()
for line in stderrlines:
- log.ERROR(line)
+ log.Error(line)
+ # ^^^ don't use ERROR, because it might actually be fine.
+ # Also, ERROR confuses lib-python/conftest.py.
raise CompilationError(stdout, stderr)
else:
for line in stderr.splitlines():
@@ -215,13 +217,13 @@
host_factory = Darwin_i386
else:
host_factory = Darwin_x86_64
-elif sys.platform == 'freebsd7':
- from pypy.translator.platform.freebsd7 import Freebsd7, Freebsd7_64
+elif "freebsd" in sys.platform:
+ from pypy.translator.platform.freebsd import Freebsd, Freebsd_64
import platform
if platform.architecture()[0] == '32bit':
- host_factory = Freebsd7
+ host_factory = Freebsd
else:
- host_factory = Freebsd7_64
+ host_factory = Freebsd_64
elif os.name == 'nt':
from pypy.translator.platform.windows import Windows
host_factory = Windows
Modified: pypy/branch/out-of-line-guards/pypy/translator/platform/darwin.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/translator/platform/darwin.py (original)
+++ pypy/branch/out-of-line-guards/pypy/translator/platform/darwin.py Thu Dec 9 16:33:59 2010
@@ -11,13 +11,17 @@
shared_only = ()
so_ext = 'so'
-
+
+ # NOTE: GCC 4.2 will fail at runtime due to subtle issues, possibly
+ # related to GC roots. Using LLVM-GCC or Clang will break the build.
+ default_cc = 'gcc-4.0'
+
def __init__(self, cc=None):
if cc is None:
try:
cc = os.environ['CC']
except KeyError:
- cc = 'gcc'
+ cc = self.default_cc
self.cc = cc
def _args_for_shared(self, args):
Modified: pypy/branch/out-of-line-guards/pypy/translator/platform/linux.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/translator/platform/linux.py (original)
+++ pypy/branch/out-of-line-guards/pypy/translator/platform/linux.py Thu Dec 9 16:33:59 2010
@@ -27,6 +27,8 @@
class Linux(BaseLinux):
+ shared_only = () # it seems that on 32-bit linux, compiling with -fPIC
+ # gives assembler that asmgcc is not happy about.
def library_dirs_for_libffi_a(self):
# places where we need to look for libffi.a
return self.library_dirs_for_libffi() + ['/usr/lib']
Modified: pypy/branch/out-of-line-guards/pypy/translator/platform/posix.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/translator/platform/posix.py (original)
+++ pypy/branch/out-of-line-guards/pypy/translator/platform/posix.py Thu Dec 9 16:33:59 2010
@@ -104,12 +104,10 @@
else:
target_name = exe_name.basename
- cflags = self.cflags
- if sys.maxint > 2147483647: # XXX XXX XXX sort this out
- if shared:
- cflags = self.cflags + self.shared_only
- else:
- cflags = self.cflags + self.standalone_only
+ if shared:
+ cflags = self.cflags + self.shared_only
+ else:
+ cflags = self.cflags + self.standalone_only
m = GnuMakefile(path)
m.exe_name = exe_name
Modified: pypy/branch/out-of-line-guards/pypy/translator/sandbox/test/test_sandbox.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/translator/sandbox/test/test_sandbox.py (original)
+++ pypy/branch/out-of-line-guards/pypy/translator/sandbox/test/test_sandbox.py Thu Dec 9 16:33:59 2010
@@ -148,6 +148,7 @@
if sys.platform == 'linux2': # on Mac, uses another (sandboxsafe) approach
expect(f, g, "ll_os.ll_os_open", ("/proc/cpuinfo", 0, 420),
OSError(5232, "xyz"))
+ expect(f, g, "ll_os.ll_os_getenv", ("PYPY_GC_DEBUG",), None)
g.close()
tail = f.read()
f.close()
Modified: pypy/branch/out-of-line-guards/pypy/translator/tool/cbuild.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/translator/tool/cbuild.py (original)
+++ pypy/branch/out-of-line-guards/pypy/translator/tool/cbuild.py Thu Dec 9 16:33:59 2010
@@ -309,6 +309,7 @@
#define _POSIX_C_SOURCE 200112L
/* Define on FreeBSD to activate all library features */
#define __BSD_VISIBLE 1
+#define __XSI_VISIBLE 700
/* Windows: winsock/winsock2 mess */
#define WIN32_LEAN_AND_MEAN
'''
Modified: pypy/branch/out-of-line-guards/pypy/translator/tool/reftracker.py
==============================================================================
--- pypy/branch/out-of-line-guards/pypy/translator/tool/reftracker.py (original)
+++ pypy/branch/out-of-line-guards/pypy/translator/tool/reftracker.py Thu Dec 9 16:33:59 2010
@@ -3,7 +3,7 @@
Usage: call track(obj).
"""
-import autopath, sys, os
+import autopath, sys, os, types
import gc
from pypy.translator.tool.graphpage import GraphPage, DotGen
from pypy.tool.uid import uid
@@ -39,7 +39,7 @@
if o2 is None:
continue
addedge(objectlist[i], o2)
- id2typename[uid(o2)] = type(o2).__name__
+ id2typename[uid(o2)] = self.shortrepr(o2)
del o2
for o2 in self.get_referrers(objectlist[i]):
if o2 is None:
@@ -47,7 +47,7 @@
if type(o2) is list and o2 and o2[0] is MARKER:
continue
addedge(o2, objectlist[i])
- id2typename[uid(o2)] = type(o2).__name__
+ id2typename[uid(o2)] = self.shortrepr(o2)
del o2
for ids, label in edges.items():
@@ -82,13 +82,23 @@
return self.newpage(objectlist)
def formatobject(self, o):
+ header = self.shortrepr(o, compact=False)
+ secondline = repr(o.__class__)
+ return header, secondline, repr(o)
+
+ def shortrepr(self, o, compact=True):
+ t = type(o)
+ if t is types.FrameType:
+ if compact:
+ return 'frame %r' % (o.f_code.co_name,)
+ else:
+ return 'frame %r' % (o.f_code,)
s = repr(o)
if len(s) > 50:
- linktext = s
s = s[:20] + ' ... ' + s[-20:]
- else:
- linktext = ''
- return type(o).__name__, s, linktext
+ if s.startswith('<') and s.endswith('>'):
+ s = s[1:-1]
+ return s
def edgelabel(self, o1, o2):
return ''
More information about the Pypy-commit
mailing list