[pypy-commit] pypy py3k: hg merge default

mjacob pypy.commits at gmail.com
Fri Feb 19 13:05:11 EST 2016


Author: Manuel Jacob <me at manueljacob.de>
Branch: py3k
Changeset: r82329:4634d8e8bf6e
Date: 2016-02-19 19:04 +0100
http://bitbucket.org/pypy/pypy/changeset/4634d8e8bf6e/

Log:	hg merge default

diff --git a/lib-python/2.7/distutils/command/build_ext.py b/lib-python/2.7/distutils/command/build_ext.py
--- a/lib-python/2.7/distutils/command/build_ext.py
+++ b/lib-python/2.7/distutils/command/build_ext.py
@@ -188,7 +188,7 @@
             # the 'libs' directory is for binary installs - we assume that
             # must be the *native* platform.  But we don't really support
             # cross-compiling via a binary install anyway, so we let it go.
-            self.library_dirs.append(os.path.join(sys.exec_prefix, 'include'))
+            self.library_dirs.append(os.path.join(sys.exec_prefix, 'libs'))
             if self.debug:
                 self.build_temp = os.path.join(self.build_temp, "Debug")
             else:
diff --git a/lib_pypy/_pypy_testcapi.py b/lib_pypy/_pypy_testcapi.py
--- a/lib_pypy/_pypy_testcapi.py
+++ b/lib_pypy/_pypy_testcapi.py
@@ -62,7 +62,7 @@
     if sys.platform == 'win32':
         # XXX pyconfig.h uses a pragma to link to the import library,
         #     which is currently python3.lib
-        library = os.path.join(thisdir, '..', 'include', 'python32')
+        library = os.path.join(thisdir, '..', 'libs', 'python32')
         if not os.path.exists(library + '.lib'):
             # For a local translation or nightly build
             library = os.path.join(thisdir, '..', 'pypy', 'goal', 'python32')
diff --git a/lib_pypy/cffi.egg-info/PKG-INFO b/lib_pypy/cffi.egg-info/PKG-INFO
--- a/lib_pypy/cffi.egg-info/PKG-INFO
+++ b/lib_pypy/cffi.egg-info/PKG-INFO
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: cffi
-Version: 1.5.1
+Version: 1.5.2
 Summary: Foreign Function Interface for Python calling C code.
 Home-page: http://cffi.readthedocs.org
 Author: Armin Rigo, Maciej Fijalkowski
diff --git a/lib_pypy/cffi/__init__.py b/lib_pypy/cffi/__init__.py
--- a/lib_pypy/cffi/__init__.py
+++ b/lib_pypy/cffi/__init__.py
@@ -4,8 +4,8 @@
 from .api import FFI, CDefError, FFIError
 from .ffiplatform import VerificationError, VerificationMissing
 
-__version__ = "1.5.1"
-__version_info__ = (1, 5, 1)
+__version__ = "1.5.2"
+__version_info__ = (1, 5, 2)
 
 # The verifier module file names are based on the CRC32 of a string that
 # contains the following version number.  It may be older than __version__
diff --git a/lib_pypy/cffi/_embedding.h b/lib_pypy/cffi/_embedding.h
--- a/lib_pypy/cffi/_embedding.h
+++ b/lib_pypy/cffi/_embedding.h
@@ -233,7 +233,7 @@
         f = PySys_GetObject((char *)"stderr");
         if (f != NULL && f != Py_None) {
             PyFile_WriteString("\nFrom: " _CFFI_MODULE_NAME
-                               "\ncompiled with cffi version: 1.5.1"
+                               "\ncompiled with cffi version: 1.5.2"
                                "\n_cffi_backend module: ", f);
             modules = PyImport_GetModuleDict();
             mod = PyDict_GetItemString(modules, "_cffi_backend");
diff --git a/lib_pypy/cffi/api.py b/lib_pypy/cffi/api.py
--- a/lib_pypy/cffi/api.py
+++ b/lib_pypy/cffi/api.py
@@ -1,4 +1,4 @@
-import sys, sysconfig, types
+import sys, types
 from .lock import allocate_lock
 
 try:
@@ -550,16 +550,34 @@
                 lst.append(value)
         #
         if '__pypy__' in sys.builtin_module_names:
+            import os
+            if sys.platform == "win32":
+                # we need 'libpypy-c.lib'.  Current distributions of
+                # pypy (>= 4.1) contain it as 'libs/python27.lib'.
+                pythonlib = "python27"
+                if hasattr(sys, 'prefix'):
+                    ensure('library_dirs', os.path.join(sys.prefix, 'libs'))
+            else:
+                # we need 'libpypy-c.{so,dylib}', which should be by
+                # default located in 'sys.prefix/bin' for installed
+                # systems.
+                pythonlib = "pypy-c"
+                if hasattr(sys, 'prefix'):
+                    ensure('library_dirs', os.path.join(sys.prefix, 'bin'))
+            # On uninstalled pypy's, the libpypy-c is typically found in
+            # .../pypy/goal/.
             if hasattr(sys, 'prefix'):
-                import os
-                ensure('library_dirs', os.path.join(sys.prefix, 'bin'))
-            pythonlib = "pypy-c"
+                ensure('library_dirs', os.path.join(sys.prefix, 'pypy', 'goal'))
         else:
             if sys.platform == "win32":
                 template = "python%d%d"
                 if hasattr(sys, 'gettotalrefcount'):
                     template += '_d'
             else:
+                try:
+                    import sysconfig
+                except ImportError:    # 2.6
+                    from distutils import sysconfig
                 template = "python%d.%d"
                 if sysconfig.get_config_var('DEBUG_EXT'):
                     template += sysconfig.get_config_var('DEBUG_EXT')
diff --git a/lib_pypy/cffi/vengine_cpy.py b/lib_pypy/cffi/vengine_cpy.py
--- a/lib_pypy/cffi/vengine_cpy.py
+++ b/lib_pypy/cffi/vengine_cpy.py
@@ -1,3 +1,6 @@
+#
+# DEPRECATED: implementation for ffi.verify()
+#
 import sys, imp
 from . import model, ffiplatform
 
diff --git a/lib_pypy/cffi/vengine_gen.py b/lib_pypy/cffi/vengine_gen.py
--- a/lib_pypy/cffi/vengine_gen.py
+++ b/lib_pypy/cffi/vengine_gen.py
@@ -1,3 +1,6 @@
+#
+# DEPRECATED: implementation for ffi.verify()
+#
 import sys, os
 import types
 
diff --git a/lib_pypy/cffi/verifier.py b/lib_pypy/cffi/verifier.py
--- a/lib_pypy/cffi/verifier.py
+++ b/lib_pypy/cffi/verifier.py
@@ -1,3 +1,6 @@
+#
+# DEPRECATED: implementation for ffi.verify()
+#
 import sys, os, binascii, shutil, io
 from . import __version_verifier_modules__
 from . import ffiplatform
diff --git a/pypy/config/pypyoption.py b/pypy/config/pypyoption.py
--- a/pypy/config/pypyoption.py
+++ b/pypy/config/pypyoption.py
@@ -37,13 +37,16 @@
     "thread", "itertools", "pyexpat", "_ssl", "cpyext", "array",
     "binascii", "_multiprocessing", '_warnings', "_collections",
     "_multibytecodec", "_continuation", "_cffi_backend",
-    "_csv", "_pypyjson", "_vmprof", "_posixsubprocess", # "cppyy", "micronumpy"
+    "_csv", "_pypyjson", "_posixsubprocess", # "cppyy", "micronumpy"
 ])
 
-#if ((sys.platform.startswith('linux') or sys.platform == 'darwin')
-#    and os.uname()[4] == 'x86_64' and sys.maxint > 2**32):
-    # it's not enough that we get x86_64
-#    working_modules.add('_vmprof')
+from rpython.jit.backend import detect_cpu
+try:
+    if detect_cpu.autodetect().startswith('x86'):
+        working_modules.add('_vmprof')
+except detect_cpu.ProcessorAutodetectError:
+    pass
+
 
 translation_modules = default_modules.copy()
 translation_modules.update([
diff --git a/pypy/doc/whatsnew-head.rst b/pypy/doc/whatsnew-head.rst
--- a/pypy/doc/whatsnew-head.rst
+++ b/pypy/doc/whatsnew-head.rst
@@ -7,6 +7,9 @@
 
 Fixed ``_PyLong_FromByteArray()``, which was buggy.
 
+Fixed a crash with stacklets (or greenlets) on non-Linux machines
+which showed up if you forget stacklets without resuming them.
+
 .. branch: numpy-1.10
 
 Fix tests to run cleanly with -A and start to fix micronumpy for upstream numpy
@@ -38,7 +41,8 @@
 
 .. branch: compress-numbering
 
-Improve the memory signature of numbering instances in the JIT.
+Improve the memory signature of numbering instances in the JIT. This should massively
+decrease the amount of memory consumed by the JIT, which is significant for most programs.
 
 .. branch: fix-trace-too-long-heuristic
 
@@ -148,3 +152,14 @@
 
 Seperate structmember.h from Python.h Also enhance creating api functions
 to specify which header file they appear in (previously only pypy_decl.h) 
+
+.. branch: llimpl
+
+Refactor register_external(), remove running_on_llinterp mechanism and
+apply sandbox transform on externals at the end of annotation.
+
+.. branch: cffi-embedding-win32
+
+.. branch: windows-vmprof-support
+
+vmprof should work on Windows.
diff --git a/pypy/goal/targetpypystandalone.py b/pypy/goal/targetpypystandalone.py
--- a/pypy/goal/targetpypystandalone.py
+++ b/pypy/goal/targetpypystandalone.py
@@ -246,6 +246,9 @@
                 raise Exception("Cannot use the --output option with PyPy "
                                 "when --shared is on (it is by default). "
                                 "See issue #1971.")
+        if sys.platform == 'win32':
+            config.translation.libname = '..\\..\\libs\\python27.lib'
+            thisdir.join('..', '..', 'libs').ensure(dir=1)
 
         if config.translation.thread:
             config.objspace.usemodules.thread = True
diff --git a/pypy/module/_cffi_backend/__init__.py b/pypy/module/_cffi_backend/__init__.py
--- a/pypy/module/_cffi_backend/__init__.py
+++ b/pypy/module/_cffi_backend/__init__.py
@@ -3,7 +3,7 @@
 from rpython.rlib import rdynload, clibffi, entrypoint
 from rpython.rtyper.lltypesystem import rffi
 
-VERSION = "1.5.1"
+VERSION = "1.5.2"
 
 FFI_DEFAULT_ABI = clibffi.FFI_DEFAULT_ABI
 try:
diff --git a/pypy/module/_cffi_backend/embedding.py b/pypy/module/_cffi_backend/embedding.py
--- a/pypy/module/_cffi_backend/embedding.py
+++ b/pypy/module/_cffi_backend/embedding.py
@@ -57,7 +57,7 @@
     # pypy_init_embedded_cffi_module().
     if not glob.patched_sys:
         space.appexec([], """():
-            import os
+            import os, sys
             sys.stdin  = sys.__stdin__  = os.fdopen(0, 'rb', 0)
             sys.stdout = sys.__stdout__ = os.fdopen(1, 'wb', 0)
             sys.stderr = sys.__stderr__ = os.fdopen(2, 'wb', 0)
diff --git a/pypy/module/_cffi_backend/test/_backend_test_c.py b/pypy/module/_cffi_backend/test/_backend_test_c.py
--- a/pypy/module/_cffi_backend/test/_backend_test_c.py
+++ b/pypy/module/_cffi_backend/test/_backend_test_c.py
@@ -1,7 +1,7 @@
 # ____________________________________________________________
 
 import sys
-assert __version__ == "1.5.1", ("This test_c.py file is for testing a version"
+assert __version__ == "1.5.2", ("This test_c.py file is for testing a version"
                                 " of cffi that differs from the one that we"
                                 " get from 'import _cffi_backend'")
 if sys.version_info < (3,):
diff --git a/pypy/module/sys/interp_encoding.py b/pypy/module/sys/interp_encoding.py
--- a/pypy/module/sys/interp_encoding.py
+++ b/pypy/module/sys/interp_encoding.py
@@ -33,7 +33,7 @@
 
 def _getfilesystemencoding(space):
     encoding = base_encoding
-    if rlocale.HAVE_LANGINFO and rlocale.CODESET:
+    if rlocale.HAVE_LANGINFO:
         try:
             oldlocale = rlocale.setlocale(rlocale.LC_CTYPE, None)
             rlocale.setlocale(rlocale.LC_CTYPE, "")
diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi0/test_zintegration.py b/pypy/module/test_lib_pypy/cffi_tests/cffi0/test_zintegration.py
--- a/pypy/module/test_lib_pypy/cffi_tests/cffi0/test_zintegration.py
+++ b/pypy/module/test_lib_pypy/cffi_tests/cffi0/test_zintegration.py
@@ -5,6 +5,9 @@
 
 if sys.platform == 'win32':
     py.test.skip('snippets do not run on win32')
+if sys.version_info < (2, 7):
+    py.test.skip('fails e.g. on a Debian/Ubuntu which patches virtualenv'
+                 ' in a non-2.6-friendly way')
 
 def create_venv(name):
     tmpdir = udir.join(name)
diff --git a/pypy/module/test_lib_pypy/cffi_tests/embedding/test_basic.py b/pypy/module/test_lib_pypy/cffi_tests/embedding/test_basic.py
--- a/pypy/module/test_lib_pypy/cffi_tests/embedding/test_basic.py
+++ b/pypy/module/test_lib_pypy/cffi_tests/embedding/test_basic.py
@@ -28,11 +28,14 @@
 
 def prefix_pythonpath():
     cffi_base = os.path.dirname(os.path.dirname(local_dir))
-    pythonpath = os.environ.get('PYTHONPATH', '').split(os.pathsep)
+    pythonpath = org_env.get('PYTHONPATH', '').split(os.pathsep)
     if cffi_base not in pythonpath:
         pythonpath.insert(0, cffi_base)
     return os.pathsep.join(pythonpath)
 
+def setup_module(mod):
+    mod.org_env = os.environ.copy()
+
 
 class EmbeddingTests:
     _compiled_modules = {}
@@ -46,14 +49,12 @@
     def get_path(self):
         return str(self._path.ensure(dir=1))
 
-    def _run_base(self, args, env_extra={}, **kwds):
-        print('RUNNING:', args, env_extra, kwds)
-        env = os.environ.copy()
-        env.update(env_extra)
-        return subprocess.Popen(args, env=env, **kwds)
+    def _run_base(self, args, **kwds):
+        print('RUNNING:', args, kwds)
+        return subprocess.Popen(args, **kwds)
 
-    def _run(self, args, env_extra={}):
-        popen = self._run_base(args, env_extra, cwd=self.get_path(),
+    def _run(self, args):
+        popen = self._run_base(args, cwd=self.get_path(),
                                  stdout=subprocess.PIPE,
                                  universal_newlines=True)
         output = popen.stdout.read()
@@ -65,6 +66,7 @@
         return output
 
     def prepare_module(self, name):
+        self.patch_environment()
         if name not in self._compiled_modules:
             path = self.get_path()
             filename = '%s.py' % name
@@ -74,9 +76,8 @@
             # find a solution to that: we could hack sys.path inside the
             # script run here, but we can't hack it in the same way in
             # execute().
-            env_extra = {'PYTHONPATH': prefix_pythonpath()}
-            output = self._run([sys.executable, os.path.join(local_dir, filename)],
-                               env_extra=env_extra)
+            output = self._run([sys.executable,
+                                os.path.join(local_dir, filename)])
             match = re.compile(r"\bFILENAME: (.+)").search(output)
             assert match
             dynamic_lib_name = match.group(1)
@@ -101,6 +102,7 @@
             c = distutils.ccompiler.new_compiler()
             print('compiling %s with %r' % (name, modules))
             extra_preargs = []
+            debug = True
             if sys.platform == 'win32':
                 libfiles = []
                 for m in modules:
@@ -109,29 +111,45 @@
                     libfiles.append('Release\\%s.lib' % m[:-4])
                 modules = libfiles
                 extra_preargs.append('/MANIFEST')
+                debug = False    # you need to install extra stuff
+                                 # for this to work
             elif threads:
                 extra_preargs.append('-pthread')
-            objects = c.compile([filename], macros=sorted(defines.items()), debug=True)
+            objects = c.compile([filename], macros=sorted(defines.items()),
+                                debug=debug)
             c.link_executable(objects + modules, name, extra_preargs=extra_preargs)
         finally:
             os.chdir(curdir)
 
+    def patch_environment(self):
+        path = self.get_path()
+        # for libpypy-c.dll or Python27.dll
+        path = os.path.split(sys.executable)[0] + os.path.pathsep + path
+        env_extra = {'PYTHONPATH': prefix_pythonpath()}
+        if sys.platform == 'win32':
+            envname = 'PATH'
+        else:
+            envname = 'LD_LIBRARY_PATH'
+        libpath = org_env.get(envname)
+        if libpath:
+            libpath = path + os.path.pathsep + libpath
+        else:
+            libpath = path
+        env_extra[envname] = libpath
+        for key, value in sorted(env_extra.items()):
+            if os.environ.get(key) != value:
+                print '* setting env var %r to %r' % (key, value)
+                os.environ[key] = value
+
     def execute(self, name):
         path = self.get_path()
-        env_extra = {'PYTHONPATH': prefix_pythonpath()}
-        libpath = os.environ.get('LD_LIBRARY_PATH')
-        if libpath:
-            libpath = path + ':' + libpath
-        else:
-            libpath = path
-        env_extra['LD_LIBRARY_PATH'] = libpath
         print('running %r in %r' % (name, path))
         executable_name = name
         if sys.platform == 'win32':
             executable_name = os.path.join(path, executable_name + '.exe')
         else:
             executable_name = os.path.join('.', executable_name)
-        popen = self._run_base([executable_name], env_extra, cwd=path,
+        popen = self._run_base([executable_name], cwd=path,
                                stdout=subprocess.PIPE,
                                universal_newlines=True)
         result = popen.stdout.read()
diff --git a/pypy/tool/release/package.py b/pypy/tool/release/package.py
--- a/pypy/tool/release/package.py
+++ b/pypy/tool/release/package.py
@@ -111,13 +111,8 @@
     #
     builddir = py.path.local(options.builddir)
     pypydir = builddir.ensure(name, dir=True)
+
     includedir = basedir.join('include')
-    # Recursively copy all headers, shutil has only ignore
-    # so we do a double-negative to include what we want
-    def copyonly(dirpath, contents):
-        return set(contents) - set(    # XXX function not used?
-            shutil.ignore_patterns('*.h', '*.incl')(dirpath, contents),
-        )
     shutil.copytree(str(includedir), str(pypydir.join('include')))
     pypydir.ensure('include', dir=True)
 
@@ -132,9 +127,6 @@
         win_extras = ['libpypy-c.dll', 'sqlite3.dll']
         if not options.no_tk:
             win_extras += ['tcl85.dll', 'tk85.dll']
-        # add the .lib too, which is convenient to compile other programs
-        # that use the .dll (and for cffi's embedding mode)
-        win_extras.append('libpypy-c.lib')
 
         for extra in win_extras:
             p = pypy_c.dirpath().join(extra)
@@ -145,32 +137,27 @@
                     continue
             print "Picking %s" % p
             binaries.append((p, p.basename))
-        importlib_name = 'libpypy-c.lib'    
-        if pypy_c.dirpath().join(importlib_name).check():
-            try:
-                ver = subprocess.check_output([r'pypy\goal\pypy-c','-c',
-                                            "import sys;print(sys.version)"])
-                importlib_target = 'python%s%s.lib' % (ver[0], ver[2])
-                shutil.copyfile(str(pypy_c.dirpath().join(importlib_name)),
-                            str(pypydir.join(importlib_target)))
-                # XXX fix this, either an additional build step or rename
-                # both DLL and LIB to versioned names, like cpython
-                shutil.copyfile(str(pypy_c.dirpath().join(importlib_name)),
-                            str(pypy_c.dirpath().join(importlib_target)))
-                print "Picking %s as %s" % (pypy_c.dirpath().join(importlib_name),
-                            pypydir.join('include', importlib_target))
-            except:
-                pass
+        libsdir = basedir.join('libs')
+        if libsdir.exists():
+            print 'Picking %s (and contents)' % libsdir
+            shutil.copytree(str(libsdir), str(pypydir.join('libs')))
         else:
-            pass
-            # XXX users will complain that they cannot compile cpyext
-            # modules for windows, has the lib moved or are there no
-            # exported functions in the dll so no import library is created?
+            print '"libs" dir with import library not found.'
+            print 'You have to create %r' % (str(libsdir),)
+            print 'and copy libpypy-c.lib in there, renamed to python32.lib'
+            # XXX users will complain that they cannot compile capi (cpyext)
+            # modules for windows, also embedding pypy (i.e. in cffi)
+            # will fail.
+            # Has the lib moved, was translation not 'shared', or are 
+            # there no exported functions in the dll so no import
+            # library was created?
         if not options.no_tk:
             try:
                 p = pypy_c.dirpath().join('tcl85.dll')
                 if not p.check():
                     p = py.path.local.sysfind('tcl85.dll')
+                    if p is None:
+                        raise WindowsError("tcl85.dll not found")
                 tktcldir = p.dirpath().join('..').join('lib')
                 shutil.copytree(str(tktcldir), str(pypydir.join('tcl')))
             except WindowsError:
diff --git a/rpython/annotator/bookkeeper.py b/rpython/annotator/bookkeeper.py
--- a/rpython/annotator/bookkeeper.py
+++ b/rpython/annotator/bookkeeper.py
@@ -551,20 +551,6 @@
                 emulated = callback
             return self.pbc_call(pbc, args, emulated=emulated)
 
-    def _find_current_op(self, opname=None, arity=None, pos=None, s_type=None):
-        """ Find operation that is currently being annotated. Do some
-        sanity checks to see whether the correct op was found."""
-        # XXX XXX HACK HACK HACK
-        fn, block, i = self.position_key
-        op = block.operations[i]
-        if opname is not None:
-            assert op.opname == opname
-        if arity is not None:
-            assert len(op.args) == arity
-        if pos is not None:
-            assert self.annotator.binding(op.args[pos]) == s_type
-        return op
-
     def whereami(self):
         return self.annotator.whereami(self.position_key)
 
diff --git a/rpython/annotator/policy.py b/rpython/annotator/policy.py
--- a/rpython/annotator/policy.py
+++ b/rpython/annotator/policy.py
@@ -3,6 +3,9 @@
 from rpython.annotator.specialize import (
     specialize_argvalue, specialize_argtype, specialize_arglistitemtype,
     specialize_arg_or_var, memo, specialize_call_location)
+from rpython.flowspace.operation import op
+from rpython.flowspace.model import Constant
+from rpython.annotator.model import SomeTuple
 
 
 class AnnotatorPolicy(object):
@@ -64,7 +67,34 @@
         return LowLevelAnnotatorPolicy.specialize__ll_and_arg(*args)
 
     def no_more_blocks_to_annotate(pol, annotator):
+        bk = annotator.bookkeeper
         # hint to all pending specializers that we are done
-        for callback in annotator.bookkeeper.pending_specializations:
+        for callback in bk.pending_specializations:
             callback()
-        del annotator.bookkeeper.pending_specializations[:]
+        del bk.pending_specializations[:]
+        if annotator.added_blocks is not None:
+            all_blocks = annotator.added_blocks
+        else:
+            all_blocks = annotator.annotated
+        for block in list(all_blocks):
+            for i, instr in enumerate(block.operations):
+                if not isinstance(instr, (op.simple_call, op.call_args)):
+                    continue
+                v_func = instr.args[0]
+                s_func = annotator.annotation(v_func)
+                if not hasattr(s_func, 'needs_sandboxing'):
+                    continue
+                key = ('sandboxing', s_func.const)
+                if key not in bk.emulated_pbc_calls:
+                    params_s = s_func.args_s
+                    s_result = s_func.s_result
+                    from rpython.translator.sandbox.rsandbox import make_sandbox_trampoline
+                    sandbox_trampoline = make_sandbox_trampoline(
+                        s_func.name, params_s, s_result)
+                    sandbox_trampoline._signature_ = [SomeTuple(items=params_s)], s_result
+                    bk.emulate_pbc_call(key, bk.immutablevalue(sandbox_trampoline), params_s)
+                else:
+                    s_trampoline = bk.emulated_pbc_calls[key][0]
+                    sandbox_trampoline = s_trampoline.const
+                new = instr.replace({instr.args[0]: Constant(sandbox_trampoline)})
+                block.operations[i] = new
diff --git a/rpython/annotator/specialize.py b/rpython/annotator/specialize.py
--- a/rpython/annotator/specialize.py
+++ b/rpython/annotator/specialize.py
@@ -317,18 +317,6 @@
             yield (value,) + tuple_tail
 
 
-def make_constgraphbuilder(n, v=None, factory=None, srcmodule=None):
-    def constgraphbuilder(translator, ignore):
-        args = ','.join(["arg%d" % i for i in range(n)])
-        if factory is not None:
-            computed_v = factory()
-        else:
-            computed_v = v
-        miniglobals = {'v': computed_v, '__name__': srcmodule}
-        exec py.code.Source("constf = lambda %s: v" % args).compile() in miniglobals
-        return translator.buildflowgraph(miniglobals['constf'])
-    return constgraphbuilder
-
 def maybe_star_args(funcdesc, key, args_s):
     args_s, key1, builder = flatten_star_args(funcdesc, args_s)
     if key1 is not None:
diff --git a/rpython/annotator/unaryop.py b/rpython/annotator/unaryop.py
--- a/rpython/annotator/unaryop.py
+++ b/rpython/annotator/unaryop.py
@@ -113,8 +113,9 @@
 
 @op.simple_call.register(SomeObject)
 def simple_call_SomeObject(annotator, func, *args):
-    return annotator.annotation(func).call(
-        simple_args([annotator.annotation(arg) for arg in args]))
+    s_func = annotator.annotation(func)
+    argspec = simple_args([annotator.annotation(arg) for arg in args])
+    return s_func.call(argspec)
 
 @op.call_args.register_transform(SomeObject)
 def transform_varargs(annotator, v_func, v_shape, *data_v):
diff --git a/rpython/config/translationoption.py b/rpython/config/translationoption.py
--- a/rpython/config/translationoption.py
+++ b/rpython/config/translationoption.py
@@ -192,6 +192,8 @@
                "If true, makes an lldebug0 build", default=False,
                cmdline="--lldebug0"),
     StrOption("icon", "Path to the (Windows) icon to use for the executable"),
+    StrOption("libname",
+              "Windows: name and possibly location of the lib file to create"),
 
     OptionDescription("backendopt", "Backend Optimization Options", [
         # control inlining
diff --git a/rpython/jit/metainterp/optimizeopt/rewrite.py b/rpython/jit/metainterp/optimizeopt/rewrite.py
--- a/rpython/jit/metainterp/optimizeopt/rewrite.py
+++ b/rpython/jit/metainterp/optimizeopt/rewrite.py
@@ -380,7 +380,7 @@
                     raise InvalidLoop("promote of a virtual")
                 old_guard_op = info.get_last_guard(self.optimizer)
                 if old_guard_op is not None:
-                    op = self.replace_guard_class_with_guard_value(op, info,
+                    op = self.replace_old_guard_with_guard_value(op, info,
                                                               old_guard_op)
         elif arg0.type == 'f':
             arg0 = self.get_box_replacement(arg0)
@@ -390,11 +390,26 @@
         assert isinstance(constbox, Const)
         self.optimize_guard(op, constbox)
 
-    def replace_guard_class_with_guard_value(self, op, info, old_guard_op):
-        if old_guard_op.opnum != rop.GUARD_NONNULL:
-            previous_classbox = info.get_known_class(self.optimizer.cpu)
-            expected_classbox = self.optimizer.cpu.ts.cls_of_box(op.getarg(1))
-            assert previous_classbox is not None
+    def replace_old_guard_with_guard_value(self, op, info, old_guard_op):
+        # there already has been a guard_nonnull or guard_class or
+        # guard_nonnull_class on this value, which is rather silly.
+        # This function replaces the original guard with a
+        # guard_value.  Must be careful: doing so is unsafe if the
+        # original guard checks for something inconsistent,
+        # i.e. different than what it would give if the guard_value
+        # passed (this is a rare case, but possible).  If we get
+        # inconsistent results in this way, then we must not do the
+        # replacement, otherwise we'd put guard_value up there but all
+        # intermediate ops might be executed by assuming something
+        # different, from the old guard that is now removed...
+
+        c_value = op.getarg(1)
+        if not c_value.nonnull():
+            raise InvalidLoop('A GUARD_VALUE(..., NULL) follows some other '
+                              'guard that it is not NULL')
+        previous_classbox = info.get_known_class(self.optimizer.cpu)
+        if previous_classbox is not None:
+            expected_classbox = self.optimizer.cpu.ts.cls_of_box(c_value)
             assert expected_classbox is not None
             if not previous_classbox.same_constant(
                     expected_classbox):
diff --git a/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py b/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py
--- a/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py
+++ b/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py
@@ -3063,6 +3063,16 @@
         self.optimize_loop(ops, expected, preamble)
         #self.check_expanded_fail_descr("i0", rop.GUARD_VALUE)
 
+    def test_invalid_guard_value_after_guard_class(self):
+        ops = """
+        [p1, i0, i1, i2, p2]
+        guard_class(p1, ConstClass(node_vtable)) [i0]
+        i3 = int_add(i1, i2)
+        guard_value(p1, NULL) [i1]
+        jump(p2, i0, i1, i3, p2)
+        """
+        self.raises(InvalidLoop, self.optimize_loop, ops, ops)
+
     def test_guard_class_oois(self):
         ops = """
         [p1]
diff --git a/rpython/memory/gctransform/test/test_transform.py b/rpython/memory/gctransform/test/test_transform.py
--- a/rpython/memory/gctransform/test/test_transform.py
+++ b/rpython/memory/gctransform/test/test_transform.py
@@ -5,6 +5,7 @@
 from rpython.translator.exceptiontransform import ExceptionTransformer
 from rpython.rtyper.lltypesystem import lltype
 from rpython.conftest import option
+from rpython.rtyper.rtyper import llinterp_backend
 
 
 class LLInterpedTranformerTests:
@@ -131,8 +132,10 @@
 def rtype(func, inputtypes, specialize=True):
     t = TranslationContext()
     t.buildannotator().build_types(func, inputtypes)
+    rtyper = t.buildrtyper()
+    rtyper.backend = llinterp_backend
     if specialize:
-        t.buildrtyper().specialize()
+        rtyper.specialize()
     if option.view:
         t.view()
     return t
diff --git a/rpython/memory/test/test_transformed_gc.py b/rpython/memory/test/test_transformed_gc.py
--- a/rpython/memory/test/test_transformed_gc.py
+++ b/rpython/memory/test/test_transformed_gc.py
@@ -14,6 +14,7 @@
 from rpython.conftest import option
 from rpython.rlib.rstring import StringBuilder
 from rpython.rlib.rarithmetic import LONG_BIT
+from rpython.rtyper.rtyper import llinterp_backend
 
 
 WORD = LONG_BIT // 8
@@ -29,9 +30,11 @@
     t.config.set(**extraconfigopts)
     ann = t.buildannotator()
     ann.build_types(func, inputtypes)
+    rtyper = t.buildrtyper()
+    rtyper.backend = llinterp_backend
 
     if specialize:
-        t.buildrtyper().specialize()
+        rtyper.specialize()
     if backendopt:
         from rpython.translator.backendopt.all import backend_optimizations
         backend_optimizations(t)
diff --git a/rpython/rlib/objectmodel.py b/rpython/rlib/objectmodel.py
--- a/rpython/rlib/objectmodel.py
+++ b/rpython/rlib/objectmodel.py
@@ -275,8 +275,6 @@
         return lltype.Signed
 
 malloc_zero_filled = CDefinedIntSymbolic('MALLOC_ZERO_FILLED', default=0)
-running_on_llinterp = CDefinedIntSymbolic('RUNNING_ON_LLINTERP', default=1)
-# running_on_llinterp is meant to have the value 0 in all backends
 
 # ____________________________________________________________
 
diff --git a/rpython/rlib/rvmprof/cintf.py b/rpython/rlib/rvmprof/cintf.py
--- a/rpython/rlib/rvmprof/cintf.py
+++ b/rpython/rlib/rvmprof/cintf.py
@@ -7,8 +7,6 @@
 from rpython.rtyper.tool import rffi_platform as platform
 from rpython.rlib import rthread
 
-from rpython.jit.backend import detect_cpu
-
 class VMProfPlatformUnsupported(Exception):
     pass
 
diff --git a/rpython/rlib/rvmprof/test/test_rvmprof.py b/rpython/rlib/rvmprof/test/test_rvmprof.py
--- a/rpython/rlib/rvmprof/test/test_rvmprof.py
+++ b/rpython/rlib/rvmprof/test/test_rvmprof.py
@@ -101,7 +101,7 @@
         s = 0
         for i in range(num):
             s += (i << 1)
-            if s % 32423423423 == 0:
+            if s % 2123423423 == 0:
                 print s
         return s
 
diff --git a/rpython/rtyper/extfunc.py b/rpython/rtyper/extfunc.py
--- a/rpython/rtyper/extfunc.py
+++ b/rpython/rtyper/extfunc.py
@@ -1,99 +1,105 @@
-from rpython.rtyper.extregistry import ExtRegistryEntry
-from rpython.rtyper.lltypesystem.lltype import typeOf, FuncType, functionptr
-from rpython.annotator.model import unionof
+from rpython.annotator.model import unionof, SomeObject
 from rpython.annotator.signature import annotation, SignatureError
+from rpython.rtyper.extregistry import ExtRegistryEntry, lookup
+from rpython.rtyper.lltypesystem.lltype import (
+    typeOf, FuncType, functionptr, _ptr, Void)
+from rpython.rtyper.error import TyperError
+from rpython.rtyper.rmodel import Repr
 
-import py
+class SomeExternalFunction(SomeObject):
+    def __init__(self, name, args_s, s_result):
+        self.name = name
+        self.args_s = args_s
+        self.s_result = s_result
+
+    def check_args(self, callspec):
+        params_s = self.args_s
+        args_s, kwargs = callspec.unpack()
+        if kwargs:
+            raise SignatureError(
+                "External functions cannot be called with keyword arguments")
+        if len(args_s) != len(params_s):
+            raise SignatureError("Argument number mismatch")
+        for i, s_param in enumerate(params_s):
+            arg = unionof(args_s[i], s_param)
+            if not s_param.contains(arg):
+                raise SignatureError(
+                    "In call to external function %r:\n"
+                    "arg %d must be %s,\n"
+                    "          got %s" % (
+                        self.name, i + 1, s_param, args_s[i]))
+
+    def call(self, callspec):
+        self.check_args(callspec)
+        return self.s_result
+
+    def rtyper_makerepr(self, rtyper):
+        if not self.is_constant():
+            raise TyperError("Non-constant external function!")
+        entry = lookup(self.const)
+        impl = getattr(entry, 'lltypeimpl', None)
+        fakeimpl = getattr(entry, 'lltypefakeimpl', None)
+        return ExternalFunctionRepr(self, impl, fakeimpl)
+
+    def rtyper_makekey(self):
+        return self.__class__, self
+
+class ExternalFunctionRepr(Repr):
+    lowleveltype = Void
+
+    def __init__(self, s_func, impl, fakeimpl):
+        self.s_func = s_func
+        self.impl = impl
+        self.fakeimpl = fakeimpl
+
+    def rtype_simple_call(self, hop):
+        rtyper = hop.rtyper
+        args_r = [rtyper.getrepr(s_arg) for s_arg in self.s_func.args_s]
+        r_result = rtyper.getrepr(self.s_func.s_result)
+        obj = self.get_funcptr(rtyper, args_r, r_result)
+        hop2 = hop.copy()
+        hop2.r_s_popfirstarg()
+        vlist = [hop2.inputconst(typeOf(obj), obj)] + hop2.inputargs(*args_r)
+        hop2.exception_is_here()
+        return hop2.genop('direct_call', vlist, r_result)
+
+    def get_funcptr(self, rtyper, args_r, r_result):
+        from rpython.rtyper.rtyper import llinterp_backend
+        args_ll = [r_arg.lowleveltype for r_arg in args_r]
+        ll_result = r_result.lowleveltype
+        name = self.s_func.name
+        if self.fakeimpl and rtyper.backend is llinterp_backend:
+            FT = FuncType(args_ll, ll_result)
+            return functionptr(
+                FT, name, _external_name=name, _callable=self.fakeimpl)
+        elif self.impl:
+            if isinstance(self.impl, _ptr):
+                return self.impl
+            else:
+                # store some attributes to the 'impl' function, where
+                # the eventual call to rtyper.getcallable() will find them
+                # and transfer them to the final lltype.functionptr().
+                self.impl._llfnobjattrs_ = {'_name': name}
+                return rtyper.getannmixlevel().delayedfunction(
+                    self.impl, self.s_func.args_s, self.s_func.s_result)
+        else:
+            fakeimpl = self.fakeimpl or self.s_func.const
+            FT = FuncType(args_ll, ll_result)
+            return functionptr(
+                FT, name, _external_name=name, _callable=fakeimpl)
+
 
 class ExtFuncEntry(ExtRegistryEntry):
     safe_not_sandboxed = False
 
-    # common case: args is a list of annotation or types
-    def normalize_args(self, *args_s):
-        args = self.signature_args
-        signature_args = [annotation(arg, None) for arg in args]
-        assert len(args_s) == len(signature_args),\
-               "Argument number mismatch"
+    def compute_annotation(self):
+        s_result = SomeExternalFunction(
+            self.name, self.signature_args, self.signature_result)
+        if (self.bookkeeper.annotator.translator.config.translation.sandbox
+                and not self.safe_not_sandboxed):
+            s_result.needs_sandboxing = True
+        return s_result
 
-        for i, expected in enumerate(signature_args):
-            arg = unionof(args_s[i], expected)
-            if not expected.contains(arg):
-                name = getattr(self, 'name', None)
-                if not name:
-                    try:
-                        name = self.instance.__name__
-                    except AttributeError:
-                        name = '?'
-                raise SignatureError("In call to external function %r:\n"
-                                "arg %d must be %s,\n"
-                                "          got %s" % (
-                    name, i+1, expected, args_s[i]))
-        return signature_args
-
-    def compute_result_annotation(self, *args_s):
-        self.normalize_args(*args_s)   # check arguments
-        return self.signature_result
-
-    def specialize_call(self, hop):
-        rtyper = hop.rtyper
-        signature_args = self.normalize_args(*hop.args_s)
-        args_r = [rtyper.getrepr(s_arg) for s_arg in signature_args]
-        args_ll = [r_arg.lowleveltype for r_arg in args_r]
-        s_result = hop.s_result
-        r_result = rtyper.getrepr(s_result)
-        ll_result = r_result.lowleveltype
-        name = getattr(self, 'name', None) or self.instance.__name__
-        impl = getattr(self, 'lltypeimpl', None)
-        fakeimpl = getattr(self, 'lltypefakeimpl', self.instance)
-        if impl:
-            if (rtyper.annotator.translator.config.translation.sandbox
-                    and not self.safe_not_sandboxed):
-                from rpython.translator.sandbox.rsandbox import (
-                    make_sandbox_trampoline)
-                impl = make_sandbox_trampoline(
-                    self.name, signature_args, s_result)
-            if hasattr(self, 'lltypefakeimpl'):
-                # If we have both an llimpl and an llfakeimpl,
-                # we need a wrapper that selects the proper one and calls it
-                from rpython.tool.sourcetools import func_with_new_name
-                # Using '*args' is delicate because this wrapper is also
-                # created for init-time functions like llarena.arena_malloc
-                # which are called before the GC is fully initialized
-                args = ', '.join(['arg%d' % i for i in range(len(args_ll))])
-                d = {'original_impl': impl,
-                     's_result': s_result,
-                     'fakeimpl': fakeimpl,
-                     '__name__': __name__,
-                     }
-                exec py.code.compile("""
-                    from rpython.rlib.objectmodel import running_on_llinterp
-                    from rpython.rlib.debug import llinterpcall
-                    from rpython.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)
-                        else:
-                            return original_impl(%s)
-                """ % (args, args, args)) in d
-                impl = func_with_new_name(d['ll_wrapper'], name + '_wrapper')
-            # store some attributes to the 'impl' function, where
-            # the eventual call to rtyper.getcallable() will find them
-            # and transfer them to the final lltype.functionptr().
-            impl._llfnobjattrs_ = {'_name': self.name}
-            obj = rtyper.getannmixlevel().delayedfunction(
-                impl, signature_args, hop.s_result)
-        else:
-            FT = FuncType(args_ll, ll_result)
-            obj = functionptr(FT, name, _external_name=self.name,
-                              _callable=fakeimpl,
-                              _safe_not_sandboxed=self.safe_not_sandboxed)
-        vlist = [hop.inputconst(typeOf(obj), obj)] + hop.inputargs(*args_r)
-        hop.exception_is_here()
-        return hop.genop('direct_call', vlist, r_result)
 
 def register_external(function, args, result=None, export_name=None,
                        llimpl=None, llfakeimpl=None, sandboxsafe=False):
@@ -109,32 +115,20 @@
 
     if export_name is None:
         export_name = function.__name__
+    params_s = [annotation(arg) for arg in args]
+    s_result = annotation(result)
 
     class FunEntry(ExtFuncEntry):
         _about_ = function
         safe_not_sandboxed = sandboxsafe
-
-        if args is None:
-            def normalize_args(self, *args_s):
-                return args_s    # accept any argument unmodified
-        elif callable(args):
-            # custom annotation normalizer (see e.g. os.utime())
-            normalize_args = staticmethod(args)
-        else: # use common case behavior
-            signature_args = args
-
-        signature_result = annotation(result, None)
+        signature_args = params_s
+        signature_result = s_result
         name = export_name
         if llimpl:
             lltypeimpl = staticmethod(llimpl)
         if llfakeimpl:
             lltypefakeimpl = staticmethod(llfakeimpl)
 
-    if export_name:
-        FunEntry.__name__ = export_name
-    else:
-        FunEntry.__name__ = function.func_name
-
 def is_external(func):
     if hasattr(func, 'value'):
         func = func.value
diff --git a/rpython/rtyper/rtyper.py b/rpython/rtyper/rtyper.py
--- a/rpython/rtyper/rtyper.py
+++ b/rpython/rtyper/rtyper.py
@@ -32,11 +32,24 @@
 from rpython.translator.sandbox.rsandbox import make_sandbox_trampoline
 
 
+class RTyperBackend(object):
+    pass
+
+class GenCBackend(RTyperBackend):
+    pass
+genc_backend = GenCBackend()
+
+class LLInterpBackend(RTyperBackend):
+    pass
+llinterp_backend = LLInterpBackend()
+
+
 class RPythonTyper(object):
     from rpython.rtyper.rmodel import log
 
-    def __init__(self, annotator):
+    def __init__(self, annotator, backend=genc_backend):
         self.annotator = annotator
+        self.backend = backend
         self.lowlevel_ann_policy = LowLevelAnnotatorPolicy(self)
         self.reprs = {}
         self._reprs_must_call_setup = []
diff --git a/rpython/rtyper/test/test_extfunc.py b/rpython/rtyper/test/test_extfunc.py
--- a/rpython/rtyper/test/test_extfunc.py
+++ b/rpython/rtyper/test/test_extfunc.py
@@ -1,7 +1,6 @@
 import py
 
-from rpython.rtyper.extfunc import ExtFuncEntry, register_external,\
-     is_external
+from rpython.rtyper.extfunc import register_external
 from rpython.annotator.model import SomeInteger, SomeString, AnnotatorError
 from rpython.annotator.annrpython import RPythonAnnotator
 from rpython.annotator.policy import AnnotatorPolicy
@@ -19,11 +18,7 @@
             "NOT_RPYTHON"
             return eval("x+40")
 
-        class BTestFuncEntry(ExtFuncEntry):
-            _about_ = b
-            name = 'b'
-            signature_args = [SomeInteger()]
-            signature_result = SomeInteger()
+        register_external(b, [int], result=int)
 
         def f():
             return b(2)
@@ -43,15 +38,11 @@
         def c(y, x):
             yyy
 
-        class CTestFuncEntry(ExtFuncEntry):
-            _about_ = c
-            name = 'ccc'
-            signature_args = [SomeInteger()] * 2
-            signature_result = SomeInteger()
+        def llimpl(y, x):
+            return y + x
 
-            def lltypeimpl(y, x):
-                return y + x
-            lltypeimpl = staticmethod(lltypeimpl)
+        register_external(c, [int, int], result=int, llimpl=llimpl,
+                          export_name='ccc')
 
         def f():
             return c(3, 4)
@@ -59,22 +50,6 @@
         res = interpret(f, [])
         assert res == 7
 
-    def test_register_external_signature(self):
-        """
-        Test the standard interface for external functions.
-        """
-        def dd():
-            pass
-        register_external(dd, [int], int)
-
-        def f():
-            return dd(3)
-
-        policy = AnnotatorPolicy()
-        a = RPythonAnnotator(policy=policy)
-        s = a.build_types(f, [])
-        assert isinstance(s, SomeInteger)
-
     def test_register_external_tuple_args(self):
         """
         Verify the annotation of a registered external function which takes a
@@ -121,23 +96,6 @@
         s = a.build_types(f, [])
         assert isinstance(s, SomeInteger)
 
-    def test_register_external_specialcase(self):
-        """
-        When args=None, the external function accepts any arguments unmodified.
-        """
-        def function_withspecialcase(arg):
-            return repr(arg)
-        register_external(function_withspecialcase, args=None, result=str)
-
-        def f():
-            x = function_withspecialcase
-            return x(33) + x("aaa") + x([]) + "\n"
-
-        policy = AnnotatorPolicy()
-        a = RPythonAnnotator(policy=policy)
-        s = a.build_types(f, [])
-        assert isinstance(s, SomeString)
-
     def test_str0(self):
         str0 = SomeString(no_nul=True)
         def os_open(s):
@@ -182,3 +140,22 @@
             # fails with TooLateForChange
             a.build_types(g, [[str]])
         a.build_types(g, [[str0]])  # Does not raise
+
+    def test_register_external_llfakeimpl(self):
+        def a(i):
+            return i
+        def a_llimpl(i):
+            return i * 2
+        def a_llfakeimpl(i):
+            return i * 3
+        register_external(a, [int], int, llimpl=a_llimpl,
+                          llfakeimpl=a_llfakeimpl)
+        def f(i):
+            return a(i)
+
+        res = interpret(f, [7])
+        assert res == 21
+
+        from rpython.translator.c.test.test_genc import compile
+        fc = compile(f, [int])
+        assert fc(7) == 14
diff --git a/rpython/rtyper/test/test_llinterp.py b/rpython/rtyper/test/test_llinterp.py
--- a/rpython/rtyper/test/test_llinterp.py
+++ b/rpython/rtyper/test/test_llinterp.py
@@ -13,7 +13,7 @@
 from rpython.rlib.rarithmetic import r_uint, ovfcheck
 from rpython.tool import leakfinder
 from rpython.conftest import option
-
+from rpython.rtyper.rtyper import llinterp_backend
 
 # switch on logging of interp to show more info on failing tests
 
@@ -39,6 +39,7 @@
         t.view()
     global typer # we need it for find_exception
     typer = t.buildrtyper()
+    typer.backend = llinterp_backend
     typer.specialize()
     #t.view()
     t.checkgraphs()
diff --git a/rpython/rtyper/test/test_rbuiltin.py b/rpython/rtyper/test/test_rbuiltin.py
--- a/rpython/rtyper/test/test_rbuiltin.py
+++ b/rpython/rtyper/test/test_rbuiltin.py
@@ -3,8 +3,7 @@
 
 import py
 
-from rpython.rlib.debug import llinterpcall
-from rpython.rlib.objectmodel import instantiate, running_on_llinterp, compute_unique_id, current_object_addr_as_int
+from rpython.rlib.objectmodel import instantiate, compute_unique_id, current_object_addr_as_int
 from rpython.rlib.rarithmetic import (intmask, longlongmask, r_int64, is_valid_int,
     r_int, r_uint, r_longlong, r_ulonglong)
 from rpython.rlib.rstring import StringBuilder, UnicodeBuilder
@@ -456,26 +455,6 @@
         res = self.interpret(fn, [3.25])
         assert res == 7.25
 
-    def test_debug_llinterpcall(self):
-        S = lltype.Struct('S', ('m', lltype.Signed))
-        SPTR = lltype.Ptr(S)
-        def foo(n):
-            "NOT_RPYTHON"
-            s = lltype.malloc(S, immortal=True)
-            s.m = eval("n*6", locals())
-            return s
-        def fn(n):
-            if running_on_llinterp:
-                return llinterpcall(SPTR, foo, n).m
-            else:
-                return 321
-        res = self.interpret(fn, [7])
-        assert res == 42
-        from rpython.translator.c.test.test_genc import compile
-        f = compile(fn, [int])
-        res = f(7)
-        assert res == 321
-
     def test_id(self):
         class A:
             pass
diff --git a/rpython/rtyper/test/test_rpbc.py b/rpython/rtyper/test/test_rpbc.py
--- a/rpython/rtyper/test/test_rpbc.py
+++ b/rpython/rtyper/test/test_rpbc.py
@@ -1,7 +1,7 @@
 import py
 
 from rpython.annotator import model as annmodel
-from rpython.annotator import policy, specialize
+from rpython.annotator import specialize
 from rpython.rtyper.lltypesystem.lltype import typeOf
 from rpython.rtyper.test.tool import BaseRtypingTest
 from rpython.rtyper.llannotation import SomePtr, lltype_to_annotation
@@ -1690,59 +1690,6 @@
 
 # ____________________________________________________________
 
-class TestRPBCExtra(BaseRtypingTest):
-
-    def test_folding_specialize_support(self):
-
-        class S(object):
-
-            def w(s, x):
-                if isinstance(x, int):
-                    return x
-                if isinstance(x, str):
-                    return len(x)
-                return -1
-            w._annspecialcase_ = "specialize:w"
-
-            def _freeze_(self):
-                return True
-
-        s = S()
-
-        def f(i, n):
-            w = s.w
-            if i == 0:
-                return w(0)
-            elif i == 1:
-                return w("abc")
-            elif i == 2:
-                return w(3*n)
-            elif i == 3:
-                return w(str(n))
-            return -1
-
-        class P(policy.AnnotatorPolicy):
-            def specialize__w(pol, funcdesc, args_s):
-                typ = args_s[1].knowntype
-                if args_s[0].is_constant() and args_s[1].is_constant():
-                    x = args_s[1].const
-                    v = s.w(x)
-                    builder = specialize.make_constgraphbuilder(2, v)
-                    return funcdesc.cachedgraph(x, builder=builder)
-                return funcdesc.cachedgraph(typ)
-
-        p = P()
-
-        res = self.interpret(f, [0, 66], policy=p)
-        assert res == 0
-        res = self.interpret(f, [1, 66], policy=p)
-        assert res == 3
-        res = self.interpret(f, [2, 4], policy=p)
-        assert res == 12
-        res = self.interpret(f, [3, 5555], policy=p)
-        assert res == 4
-
-
 def test_hlinvoke_simple():
     def f(a,b):
         return a + b
diff --git a/rpython/translator/c/node.py b/rpython/translator/c/node.py
--- a/rpython/translator/c/node.py
+++ b/rpython/translator/c/node.py
@@ -913,6 +913,7 @@
         return []
 
 def new_funcnode(db, T, obj, forcename=None):
+    from rpython.rtyper.rtyper import llinterp_backend
     if db.sandbox:
         if (getattr(obj, 'external', None) is not None and
                 not obj._safe_not_sandboxed):
@@ -934,6 +935,9 @@
         return ExternalFuncNode(db, T, obj, name)
     elif hasattr(obj._callable, "c_name"):
         return ExternalFuncNode(db, T, obj, name)  # this case should only be used for entrypoints
+    elif db.translator.rtyper.backend is llinterp_backend:
+        # on llinterp, anything goes
+        return ExternalFuncNode(db, T, obj, name)
     else:
         raise ValueError("don't know how to generate code for %r" % (obj,))
 
diff --git a/rpython/translator/driver.py b/rpython/translator/driver.py
--- a/rpython/translator/driver.py
+++ b/rpython/translator/driver.py
@@ -487,7 +487,15 @@
                     exe = py.path.local(exename)
                     exename = exe.new(purebasename=exe.purebasename + 'w')
                     shutil_copy(str(exename), str(newexename))
-                    ext_to_copy = ['lib', 'pdb']
+                    # for pypy, the import library is renamed and moved to
+                    # libs/python32.lib, according to the pragma in pyconfig.h
+                    libname = self.config.translation.libname
+                    libname = libname or soname.new(ext='lib').basename
+                    libname = str(newsoname.dirpath().join(libname))
+                    shutil.copyfile(str(soname.new(ext='lib')), libname)
+                    self.log.info("copied: %s" % (libname,))
+                    # the pdb file goes in the same place as pypy(w).exe
+                    ext_to_copy = ['pdb',]
                     for ext in ext_to_copy:
                         name = soname.new(ext=ext)
                         newname = newexename.new(basename=soname.basename)
diff --git a/rpython/translator/sandbox/test/test_sandbox.py b/rpython/translator/sandbox/test/test_sandbox.py
--- a/rpython/translator/sandbox/test/test_sandbox.py
+++ b/rpython/translator/sandbox/test/test_sandbox.py
@@ -292,6 +292,21 @@
     rescode = pipe.wait()
     assert rescode == 0
 
+def test_environ_items():
+    def entry_point(argv):
+        print os.environ.items()
+        return 0
+
+    exe = compile(entry_point)
+    g, f = run_in_subprocess(exe)
+    expect(f, g, "ll_os.ll_os_envitems", (), [])
+    expect(f, g, "ll_os.ll_os_write", (1, "[]\n"), 3)
+    g.close()
+    tail = f.read()
+    f.close()
+    assert tail == ""
+
+
 class TestPrintedResults:
 
     def run(self, entry_point, args, expected):


More information about the pypy-commit mailing list