[pypy-commit] pypy remove-globals-in-jit: hg merge default

arigo noreply at buildbot.pypy.org
Tue Dec 18 12:51:40 CET 2012


Author: Armin Rigo <arigo at tunes.org>
Branch: remove-globals-in-jit
Changeset: r59482:d8bdb7ec0050
Date: 2012-12-18 12:51 +0100
http://bitbucket.org/pypy/pypy/changeset/d8bdb7ec0050/

Log:	hg merge default

diff too long, truncating to 2000 out of 7859 lines

diff --git a/README b/README
deleted file mode 100644
--- a/README
+++ /dev/null
@@ -1,24 +0,0 @@
-=====================================
-PyPy: Python in Python Implementation 
-=====================================
-
-Welcome to PyPy!
-
-PyPy is both an implementation of the Python programming language, and
-an extensive compiler framework for dynamic language implementations.
-You can build self-contained Python implementations which execute
-independently from CPython.
-
-The home page is:
-
-    http://pypy.org/
-
-The getting-started document will help guide you:
-
-    http://doc.pypy.org/en/latest/getting-started.html
-
-It will also point you to the rest of the documentation which is generated
-from files in the pypy/doc directory within the source repositories. Enjoy
-and send us feedback!
-
-    the pypy-dev team <pypy-dev at python.org>
diff --git a/README.rst b/README.rst
new file mode 100644
--- /dev/null
+++ b/README.rst
@@ -0,0 +1,24 @@
+=====================================
+PyPy: Python in Python Implementation 
+=====================================
+
+Welcome to PyPy!
+
+PyPy is both an implementation of the Python programming language, and
+an extensive compiler framework for dynamic language implementations.
+You can build self-contained Python implementations which execute
+independently from CPython.
+
+The home page is:
+
+    http://pypy.org/
+
+The getting-started document will help guide you:
+
+    http://doc.pypy.org/en/latest/getting-started.html
+
+It will also point you to the rest of the documentation which is generated
+from files in the pypy/doc directory within the source repositories. Enjoy
+and send us feedback!
+
+    the pypy-dev team <pypy-dev at python.org>
diff --git a/lib_pypy/stackless.py b/lib_pypy/stackless.py
--- a/lib_pypy/stackless.py
+++ b/lib_pypy/stackless.py
@@ -434,8 +434,8 @@
     def insert(self):
         if self.blocked:
             raise RuntimeError, "You cannot run a blocked tasklet"
-            if not self.alive:
-                raise RuntimeError, "You cannot run an unbound(dead) tasklet"
+        if not self.alive:
+            raise RuntimeError, "You cannot run an unbound(dead) tasklet"
         _scheduler_append(self)
 
     def remove(self):
diff --git a/pypy/annotation/annrpython.py b/pypy/annotation/annrpython.py
--- a/pypy/annotation/annrpython.py
+++ b/pypy/annotation/annrpython.py
@@ -1,3 +1,5 @@
+from __future__ import absolute_import
+
 import types
 from pypy.tool.ansi_print import ansi_log
 from pypy.tool.pairtype import pair
@@ -373,7 +375,12 @@
         # Merge the new 'cells' with each of the block's existing input
         # variables.
         oldcells = [self.binding(a) for a in block.inputargs]
-        unions = [annmodel.unionof(c1,c2) for c1, c2 in zip(oldcells,inputcells)]
+        try:
+            unions = [annmodel.unionof(c1,c2) for c1, c2 in zip(oldcells,inputcells)]
+        except annmodel.UnionError, e:
+            e.args = e.args + (
+                ErrorWrapper(gather_error(self, graph, block, None)),)
+            raise
         # if the merged cells changed, we must redo the analysis
         if unions != oldcells:
             self.bindinputargs(graph, block, unions)
diff --git a/pypy/annotation/bookkeeper.py b/pypy/annotation/bookkeeper.py
--- a/pypy/annotation/bookkeeper.py
+++ b/pypy/annotation/bookkeeper.py
@@ -1,6 +1,9 @@
 """
 The Bookkeeper class.
 """
+
+from __future__ import absolute_import
+
 import sys, types, inspect, weakref
 
 from pypy.objspace.flow.model import Constant
diff --git a/pypy/annotation/description.py b/pypy/annotation/description.py
--- a/pypy/annotation/description.py
+++ b/pypy/annotation/description.py
@@ -1,4 +1,6 @@
+from __future__ import absolute_import
 import types, py
+from pypy.annotation.signature import enforce_signature_args, enforce_signature_return
 from pypy.objspace.flow.model import Constant, FunctionGraph
 from pypy.objspace.flow.bytecode import cpython_code_signature
 from pypy.objspace.flow.argument import rawshape, ArgErr
@@ -275,12 +277,17 @@
             policy = self.bookkeeper.annotator.policy
             self.specializer = policy.get_specializer(tag)
         enforceargs = getattr(self.pyobj, '_annenforceargs_', None)
+        signature = getattr(self.pyobj, '_signature_', None)
+        if enforceargs and signature:
+            raise Exception("%r: signature and enforceargs cannot both be used" % (self,))
         if enforceargs:
             if not callable(enforceargs):
                 from pypy.annotation.policy import Sig
                 enforceargs = Sig(*enforceargs)
                 self.pyobj._annenforceargs_ = enforceargs
             enforceargs(self, inputcells) # can modify inputcells in-place
+        if signature:
+            enforce_signature_args(self, signature[0], inputcells) # mutates inputcells
         if getattr(self.pyobj, '_annspecialcase_', '').endswith("call_location"):
             return self.specializer(self, inputcells, op)
         else:
@@ -297,6 +304,10 @@
             new_args = args.unmatch_signature(self.signature, inputcells)
             inputcells = self.parse_arguments(new_args, graph)
             result = schedule(graph, inputcells)
+            signature = getattr(self.pyobj, '_signature_', None)
+            if signature:
+                result = enforce_signature_return(self, signature[1], result)
+                self.bookkeeper.annotator.addpendingblock(graph, graph.returnblock, [result])
         # Some specializations may break the invariant of returning
         # annotations that are always more general than the previous time.
         # We restore it here:
diff --git a/pypy/annotation/model.py b/pypy/annotation/model.py
--- a/pypy/annotation/model.py
+++ b/pypy/annotation/model.py
@@ -27,6 +27,7 @@
 #    \_____________________________________________________/
 #
 
+from __future__ import absolute_import
 
 from types import BuiltinFunctionType, MethodType, FunctionType
 import pypy
diff --git a/pypy/annotation/signature.py b/pypy/annotation/signature.py
--- a/pypy/annotation/signature.py
+++ b/pypy/annotation/signature.py
@@ -1,3 +1,5 @@
+
+from __future__ import absolute_import
 
 import types
 from pypy.annotation.model import SomeBool, SomeInteger, SomeString,\
@@ -128,3 +130,25 @@
                                              s_arg,
                                              s_input))
         inputcells[:] = args_s
+
+def finish_type(paramtype, bookkeeper, func):
+    from pypy.rlib.types import SelfTypeMarker
+    if isinstance(paramtype, SomeObject):
+        return paramtype
+    elif isinstance(paramtype, SelfTypeMarker):
+        raise Exception("%r argument declared as annotation.types.self(); class needs decorator rlib.signature.finishsigs()" % (func,))
+    else:
+        return paramtype(bookkeeper)
+
+def enforce_signature_args(funcdesc, paramtypes, actualtypes):
+    assert len(paramtypes) == len(actualtypes)
+    params_s = [finish_type(paramtype, funcdesc.bookkeeper, funcdesc.pyobj) for paramtype in paramtypes]
+    for i, (s_param, s_actual) in enumerate(zip(params_s, actualtypes)):
+        if not s_param.contains(s_actual):
+            raise Exception("%r argument %d:\n"
+                            "expected %s,\n"
+                            "     got %s" % (funcdesc, i+1, s_param, s_actual))
+    actualtypes[:] = params_s
+
+def enforce_signature_return(funcdesc, sigtype, inferredtype):
+    return finish_type(sigtype, funcdesc.bookkeeper, funcdesc.pyobj)
diff --git a/pypy/annotation/test/test_annrpython.py b/pypy/annotation/test/test_annrpython.py
--- a/pypy/annotation/test/test_annrpython.py
+++ b/pypy/annotation/test/test_annrpython.py
@@ -255,13 +255,6 @@
         assert getcdef(snippet.H).about_attribute('attr') == (
                           a.bookkeeper.immutablevalue(1))
 
-    def DISABLED_test_knownkeysdict(self):
-        # disabled, SomeDict() is now a general {s_key: s_value} dict
-        a = self.RPythonAnnotator()
-        s = a.build_types(snippet.knownkeysdict, [int])
-        # result should be an integer
-        assert s.knowntype == int
-
     def test_generaldict(self):
         a = self.RPythonAnnotator()
         s = a.build_types(snippet.generaldict, [str, int, str, int])
@@ -483,6 +476,13 @@
         s = a.build_types(f, [str])
         assert isinstance(s, annmodel.SomeString)
 
+    def test_str_isalpha(self):
+        def f(s):
+            return s.isalpha()
+        a = self.RPythonAnnotator()
+        s = a.build_types(f, [str])
+        assert isinstance(s, annmodel.SomeBool)
+
     def test_simple_slicing(self):
         a = self.RPythonAnnotator()
         s = a.build_types(snippet.simple_slice, [somelist(annmodel.s_Int)])
diff --git a/pypy/annotation/unaryop.py b/pypy/annotation/unaryop.py
--- a/pypy/annotation/unaryop.py
+++ b/pypy/annotation/unaryop.py
@@ -2,6 +2,8 @@
 Unary operations on SomeValues.
 """
 
+from __future__ import absolute_import
+
 from types import MethodType
 from pypy.annotation.model import \
      SomeObject, SomeInteger, SomeBool, SomeString, SomeChar, SomeList, \
@@ -524,7 +526,14 @@
         return SomeString()
     method_encode.can_only_throw = [UnicodeEncodeError]
 
+
 class __extend__(SomeString):
+    def method_isdigit(chr):
+        return s_Bool
+
+    def method_isalpha(chr):
+        return s_Bool
+
     def method_upper(str):
         return SomeString()
 
@@ -560,12 +569,6 @@
     def method_isspace(chr):
         return s_Bool
 
-    def method_isdigit(chr):
-        return s_Bool
-
-    def method_isalpha(chr):
-        return s_Bool
-
     def method_isalnum(chr):
         return s_Bool
 
diff --git a/pypy/doc/faq.rst b/pypy/doc/faq.rst
--- a/pypy/doc/faq.rst
+++ b/pypy/doc/faq.rst
@@ -320,6 +320,30 @@
 .. _JVM: translation.html#genjvm
 .. _`translation document`: translation.html
 
+------------------
+Could we use LLVM?
+------------------
+
+In theory yes.  But we tried to use it 5 or 6 times already, as a
+translation backend or as a JIT backend --- and failed each time.
+
+In more details: using LLVM as a (static) translation backend is
+pointless nowadays because you can generate C code and compile it with
+clang.  (Note that compiling PyPy with clang gives a result that is not
+faster than compiling it with gcc.)  We might in theory get extra
+benefits from LLVM's GC integration, but this requires more work on the
+LLVM side before it would be remotely useful.  Anyway, it could be
+interfaced via a custom primitive in the C code.
+
+On the other hand, using LLVM as our JIT backend looks interesting as
+well --- but again we made an attempt, and it failed: LLVM has no way to
+patch the generated machine code.
+
+So the position of the core PyPy developers is that if anyone wants to
+make an N+1'th attempt with LLVM, he is welcome, and he will receive a
+bit of help on the IRC channel, but he is left with the burden of proof
+that it works.
+
 ----------------------
 How do I compile PyPy?
 ----------------------
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,10 +7,13 @@
 
 .. branch: length-hint
 Implement __lenght_hint__ according to PEP 424
-   
+
 .. branches we don't care about
 .. branch: autoreds
 
 .. branch: release-2.0-beta1
 
 .. branch: remove-PYPY_NOT_MAIN_FILE
+
+.. branch: fix-lookinside-iff-oopspec
+Fixed the interaction between two internal tools for controlling the JIT.
diff --git a/pypy/doc/windows.rst b/pypy/doc/windows.rst
--- a/pypy/doc/windows.rst
+++ b/pypy/doc/windows.rst
@@ -13,8 +13,8 @@
 Translating PyPy with Visual Studio
 -----------------------------------
 
-We routinely test the `RPython translation toolchain`_ using Visual Studio .NET
-2005, Professional Edition, and Visual Studio .NET 2008, Express
+We routinely test the `RPython translation toolchain`_ using 
+Visual Studio 2008, Express
 Edition.  Other configurations may work as well.
 
 The translation scripts will set up the appropriate environment variables
diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py
--- a/pypy/interpreter/baseobjspace.py
+++ b/pypy/interpreter/baseobjspace.py
@@ -1,17 +1,19 @@
-from pypy.interpreter.executioncontext import ExecutionContext, ActionFlag
-from pypy.interpreter.executioncontext import UserDelAction, FrameTraceAction
-from pypy.interpreter.error import OperationError, operationerrfmt
-from pypy.interpreter.error import new_exception_class, typed_unwrap_error_msg
+import sys
+
+from pypy.interpreter.executioncontext import (ExecutionContext, ActionFlag,
+    UserDelAction, FrameTraceAction)
+from pypy.interpreter.error import (OperationError, operationerrfmt,
+    new_exception_class, typed_unwrap_error_msg)
 from pypy.interpreter.argument import Arguments
 from pypy.interpreter.miscutils import ThreadLocals
 from pypy.tool.cache import Cache
 from pypy.tool.uid import HUGEVAL_BYTES
+from pypy.rlib import jit
+from pypy.rlib.debug import make_sure_not_resized
 from pypy.rlib.objectmodel import we_are_translated, newlist_hint,\
      compute_unique_id
-from pypy.rlib.debug import make_sure_not_resized
 from pypy.rlib.rarithmetic import r_uint
-from pypy.rlib import jit
-import os, sys
+
 
 __all__ = ['ObjSpace', 'OperationError', 'Wrappable', 'W_Root']
 
@@ -507,15 +509,10 @@
         for name, w_type in types_w:
             self.setitem(self.builtin.w_dict, self.wrap(name), w_type)
 
-        # install mixed and faked modules
+        # install mixed modules
         for mixedname in self.get_builtinmodule_to_install():
-            if (mixedname not in bootstrap_modules
-                and not mixedname.startswith('faked+')):
+            if mixedname not in bootstrap_modules:
                 self.install_mixedmodule(mixedname, installed_builtin_modules)
-        for mixedname in self.get_builtinmodule_to_install():
-            if mixedname.startswith('faked+'):
-                modname = mixedname[6:]
-                self.install_faked_module(modname, installed_builtin_modules)
 
         installed_builtin_modules.sort()
         w_builtin_module_names = self.newtuple(
@@ -553,24 +550,6 @@
                 "app-level module %r" % (modname,))
             installed_builtin_modules.append(modname)
 
-    def load_cpython_module(self, modname):
-        "NOT_RPYTHON. Steal a module from CPython."
-        cpy_module = __import__(modname, {}, {}, ['*'])
-        return cpy_module
-
-    def install_faked_module(self, modname, installed_builtin_modules):
-        """NOT_RPYTHON"""
-        if modname in installed_builtin_modules:
-            return
-        try:
-            module = self.load_cpython_module(modname)
-        except ImportError:
-            return
-        else:
-            w_modules = self.sys.get('modules')
-            self.setitem(w_modules, self.wrap(modname), self.wrap(module))
-            installed_builtin_modules.append(modname)
-
     def setup_builtin_modules(self):
         "NOT_RPYTHON: only for initializing the space."
         if self.config.objspace.usemodules.cpyext:
diff --git a/pypy/interpreter/pycode.py b/pypy/interpreter/pycode.py
--- a/pypy/interpreter/pycode.py
+++ b/pypy/interpreter/pycode.py
@@ -153,10 +153,8 @@
 
     @classmethod
     def _from_code(cls, space, code, hidden_applevel=False, code_hook=None):
-        """ Initialize the code object from a real (CPython) one.
-            This is just a hack, until we have our own compile.
-            At the moment, we just fake this.
-            This method is called by our compile builtin function.
+        """
+        Hack to initialize the code object from a real (CPython) one.
         """
         assert isinstance(code, types.CodeType)
         newconsts_w = [None] * len(code.co_consts)
@@ -186,7 +184,6 @@
                       list(code.co_cellvars),
                       hidden_applevel, cpython_magic)
 
-
     def _compute_flatcall(self):
         # Speed hack!
         self.fast_natural_arity = eval.Code.HOPELESS
diff --git a/pypy/interpreter/test/test_main.py b/pypy/interpreter/test/test_main.py
--- a/pypy/interpreter/test/test_main.py
+++ b/pypy/interpreter/test/test_main.py
@@ -24,17 +24,18 @@
 
 testresultoutput = '11\n'
 
-def checkoutput(space, expected_output,f,*args):
+
+def checkoutput(space, expected_output, f, *args):
     w_oldout = space.sys.get('stdout')
     capturefn = udir.join('capturefile')
-    capturefile = capturefn.open('w')
+    w_capturefile = space.call_method(space.builtin, "open", space.wrap(str(capturefn)), space.wrap("w"))
     w_sys = space.sys.getmodule('sys')
-    space.setattr(w_sys, space.wrap("stdout"), space.wrap(capturefile))
+    space.setattr(w_sys, space.wrap("stdout"), w_capturefile)
     try:
         f(*(args + (space,)))
     finally:
         space.setattr(w_sys, space.wrap("stdout"), w_oldout)
-    capturefile.close()
+    space.call_method(w_capturefile, "close")
     assert capturefn.read(mode='rU') == expected_output
 
 testfn = udir.join('tmp_hello_world.py')
diff --git a/pypy/interpreter/test/test_objspace.py b/pypy/interpreter/test/test_objspace.py
--- a/pypy/interpreter/test/test_objspace.py
+++ b/pypy/interpreter/test/test_objspace.py
@@ -320,40 +320,20 @@
 
 class TestModuleMinimal: 
     def test_sys_exists(self):
-        assert self.space.sys 
+        assert self.space.sys
 
     def test_import_exists(self):
         space = self.space
-        assert space.builtin 
+        assert space.builtin
         w_name = space.wrap('__import__')
         w_builtin = space.sys.getmodule('__builtin__')
-        w_import = self.space.getattr(w_builtin, w_name) 
+        w_import = self.space.getattr(w_builtin, w_name)
         assert space.is_true(w_import)
 
     def test_sys_import(self):
         from pypy.interpreter.main import run_string
         run_string('import sys', space=self.space)
 
-    def test_get_builtinmodule_to_install(self):
-        space = self.space
-        try:
-            # force rebuilding with this fake builtin
-            space.ALL_BUILTIN_MODULES.append('this_doesnt_exist')
-            del space._builtinmodule_list
-            mods = space.get_builtinmodule_to_install()
-            
-            assert '__pypy__' in mods                # real builtin
-            assert '_functools' not in mods               # in lib_pypy
-            assert 'faked+_functools' not in mods         # in lib_pypy
-            assert 'this_doesnt_exist' not in mods   # not in lib_pypy
-            assert 'faked+this_doesnt_exist' in mods # not in lib_pypy, but in
-                                                     # ALL_BUILTIN_MODULES
-        finally:
-            # rebuild the original list
-            space.ALL_BUILTIN_MODULES.pop()
-            del space._builtinmodule_list
-            mods = space.get_builtinmodule_to_install()
-
     def test_dont_reload_builtin_mods_on_startup(self):
         from pypy.tool.option import make_config, make_objspace
         config = make_config(None)
diff --git a/pypy/interpreter/test/test_zzpickle_and_slow.py b/pypy/interpreter/test/test_zzpickle_and_slow.py
--- a/pypy/interpreter/test/test_zzpickle_and_slow.py
+++ b/pypy/interpreter/test/test_zzpickle_and_slow.py
@@ -71,9 +71,12 @@
     space.delitem(space.builtin.w_dict,
                   space.wrap('restore_top_frame'))
 
+
 class AppTestInterpObjectPickling:
     pytestmark = py.test.mark.skipif("config.option.runappdirect")
-    spaceconfig = dict(usemodules=['struct'])
+    spaceconfig = {
+        "usemodules": ["struct", "binascii"]
+    }
 
     def setup_class(cls):
         _attach_helpers(cls.space)
diff --git a/pypy/interpreter/typedef.py b/pypy/interpreter/typedef.py
--- a/pypy/interpreter/typedef.py
+++ b/pypy/interpreter/typedef.py
@@ -32,8 +32,6 @@
         self.rawdict = {}
         self.acceptable_as_base_class = '__new__' in rawdict
         self.applevel_subclasses_base = None
-        # xxx used by faking
-        self.fakedcpytype = None
         self.add_entries(**rawdict)
         assert __total_ordering__ in (None, 'auto'), "Unknown value for __total_ordering"
         if __total_ordering__ == 'auto':
diff --git a/pypy/jit/codewriter/test/test_codewriter.py b/pypy/jit/codewriter/test/test_codewriter.py
--- a/pypy/jit/codewriter/test/test_codewriter.py
+++ b/pypy/jit/codewriter/test/test_codewriter.py
@@ -1,8 +1,11 @@
 import py
+
+from pypy.jit.codewriter import support
 from pypy.jit.codewriter.codewriter import CodeWriter
-from pypy.jit.codewriter import support
 from pypy.jit.metainterp.history import AbstractDescr
 from pypy.rpython.lltypesystem import lltype, llmemory, rffi
+from pypy.translator.backendopt.all import backend_optimizations
+
 
 class FakeCallDescr(AbstractDescr):
     def __init__(self, FUNC, ARGS, RESULT, effectinfo):
@@ -230,7 +233,8 @@
     rtyper = support.annotate(f, [-1])
     jitdriver_sd = FakeJitDriverSD(rtyper.annotator.translator.graphs[0])
     cw = CodeWriter(FakeCPU(rtyper), [jitdriver_sd])
-    cw.find_all_graphs(FakePolicy())
+    graphs = cw.find_all_graphs(FakePolicy())
+    backend_optimizations(rtyper.annotator.translator, graphs=graphs)
     cw.make_jitcodes(verbose=True)
     s = jitdriver_sd.mainjitcode.dump()
     assert 'int_force_ge_zero' in s
diff --git a/pypy/module/__pypy__/__init__.py b/pypy/module/__pypy__/__init__.py
--- a/pypy/module/__pypy__/__init__.py
+++ b/pypy/module/__pypy__/__init__.py
@@ -59,7 +59,6 @@
     def setup_after_space_initialization(self):
         """NOT_RPYTHON"""
         if not self.space.config.translating:
-            self.extra_interpdef('isfake', 'interp_magic.isfake')
             self.extra_interpdef('interp_pdb', 'interp_magic.interp_pdb')
         if self.space.config.objspace.std.withmethodcachecounter:
             self.extra_interpdef('method_cache_counter',
diff --git a/pypy/module/__pypy__/interp_magic.py b/pypy/module/__pypy__/interp_magic.py
--- a/pypy/module/__pypy__/interp_magic.py
+++ b/pypy/module/__pypy__/interp_magic.py
@@ -7,16 +7,10 @@
 from pypy.objspace.std.mapdict import IndexCache
 from pypy.rlib import rposix
 
+
 def internal_repr(space, w_object):
     return space.wrap('%r' % (w_object,))
 
-def isfake(space, w_obj):
-    """Return whether the argument is faked (stolen from CPython). This is
-    always False after translation."""
-    if we_are_translated():
-        return space.w_False
-    return space.wrap(bool(w_obj.typedef.fakedcpytype))
-    #return space.wrap(bool(getattr(w_obj.typedef, 'fakedcpytype', None)))
 
 def interp_pdb(space):
     """Run an interp-level pdb.
@@ -25,6 +19,7 @@
     import pdb
     pdb.set_trace()
 
+
 @unwrap_spec(name=str)
 def method_cache_counter(space, name):
     """Return a tuple (method_cache_hits, method_cache_misses) for calls to
diff --git a/pypy/module/__pypy__/test/test_debug.py b/pypy/module/__pypy__/test/test_debug.py
--- a/pypy/module/__pypy__/test/test_debug.py
+++ b/pypy/module/__pypy__/test/test_debug.py
@@ -1,13 +1,16 @@
 import py
+
+from pypy.interpreter.gateway import interp2app
 from pypy.rlib import debug
 
+
 class AppTestDebug:
     spaceconfig = dict(usemodules=['__pypy__'])
 
     def setup_class(cls):
         if cls.runappdirect:
             py.test.skip("not meant to be run with -A")
-        cls.w_check_log = cls.space.wrap(cls.check_log)
+        cls.w_check_log = cls.space.wrap(interp2app(cls.check_log))
 
     def setup_method(self, meth):
         debug._log = debug.DebugLog()
@@ -15,9 +18,9 @@
     def teardown_method(self, meth):
         debug._log = None
 
-    @classmethod
-    def check_log(cls, expected):
-        assert list(debug._log) == expected
+    @staticmethod
+    def check_log(space, w_expected):
+        assert list(debug._log) == space.unwrap(w_expected)
 
     def test_debug_print(self):
         from __pypy__ import debug_start, debug_stop, debug_print
diff --git a/pypy/module/__pypy__/test/test_special.py b/pypy/module/__pypy__/test/test_special.py
--- a/pypy/module/__pypy__/test/test_special.py
+++ b/pypy/module/__pypy__/test/test_special.py
@@ -8,17 +8,6 @@
         if cls.runappdirect:
             py.test.skip("does not make sense on pypy-c")
 
-    def test__isfake(self):
-        from __pypy__ import isfake
-        assert not isfake(map)
-        assert not isfake(object)
-        assert not isfake(isfake)
-
-    def test__isfake_currently_true(self):
-        from __pypy__ import isfake
-        import select
-        assert isfake(select)
-
     def test_cpumodel(self):
         import __pypy__
         assert hasattr(__pypy__, 'cpumodel')
diff --git a/pypy/module/_ast/test/test_ast.py b/pypy/module/_ast/test/test_ast.py
--- a/pypy/module/_ast/test/test_ast.py
+++ b/pypy/module/_ast/test/test_ast.py
@@ -1,7 +1,10 @@
 import py
 
+
 class AppTestAST:
-    spaceconfig = dict(usemodules=['struct'])
+    spaceconfig = {
+        "usemodules": ['struct', 'binascii'],
+    }
 
     def setup_class(cls):
         cls.w_ast = cls.space.getbuiltinmodule('_ast')
diff --git a/pypy/module/_cffi_backend/ctypeenum.py b/pypy/module/_cffi_backend/ctypeenum.py
--- a/pypy/module/_cffi_backend/ctypeenum.py
+++ b/pypy/module/_cffi_backend/ctypeenum.py
@@ -37,6 +37,13 @@
                 space.setitem(w_dct, space.wrap(enumvalue),
                                      space.wrap(enumerator))
             return w_dct
+        if attrchar == 'R':     # relements
+            space = self.space
+            w_dct = space.newdict()
+            for enumerator, enumvalue in self.enumerators2values.iteritems():
+                space.setitem(w_dct, space.wrap(enumerator),
+                                     space.wrap(enumvalue))
+            return w_dct
         return W_CTypePrimitiveSigned._fget(self, attrchar)
 
     def string(self, cdataobj, maxlen):
diff --git a/pypy/module/_cffi_backend/ctypeobj.py b/pypy/module/_cffi_backend/ctypeobj.py
--- a/pypy/module/_cffi_backend/ctypeobj.py
+++ b/pypy/module/_cffi_backend/ctypeobj.py
@@ -188,7 +188,7 @@
         if attrchar == 'c':     # cname
             return space.wrap(self.name)
         raise operationerrfmt(space.w_AttributeError,
-                              "cdata '%s' has no such attribute",
+                              "ctype '%s' has no such attribute",
                               self.name)
 
     def fget_kind(self, space):     return self._fget('k')
@@ -201,6 +201,7 @@
     def fget_ellipsis(self, space): return self._fget('E')
     def fget_abi(self, space):      return self._fget('A')
     def fget_elements(self, space): return self._fget('e')
+    def fget_relements(self, space):return self._fget('R')
 
 
 W_CType.typedef = TypeDef(
@@ -218,6 +219,8 @@
     ellipsis = GetSetProperty(W_CType.fget_ellipsis, doc="function has '...'"),
     abi = GetSetProperty(W_CType.fget_abi, doc="function ABI"),
     elements = GetSetProperty(W_CType.fget_elements, doc="enum elements"),
+    relements = GetSetProperty(W_CType.fget_relements,
+                               doc="enum elements, reversed"),
     __dir__ = interp2app(W_CType.dir),
     )
 W_CType.typedef.acceptable_as_base_class = False
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
@@ -1272,6 +1272,10 @@
     # 'elements' is not the real dict, but merely a copy
     BEnum.elements[2] = '??'
     assert BEnum.elements == {-20: 'ab', 0: 'def', 1: 'c'}
+    #
+    BEnum = new_enum_type("bar", ('ab', 'cd'), (5, 5))
+    assert BEnum.elements == {5: 'ab'}
+    assert BEnum.relements == {'ab': 5, 'cd': 5}
 
 def test_cast_to_enum():
     BEnum = new_enum_type("foo", ('def', 'c', 'ab'), (0, 1, -20))
diff --git a/pypy/module/_codecs/test/test_codecs.py b/pypy/module/_codecs/test/test_codecs.py
--- a/pypy/module/_codecs/test/test_codecs.py
+++ b/pypy/module/_codecs/test/test_codecs.py
@@ -2,7 +2,9 @@
 
 
 class AppTestCodecs:
-    spaceconfig = dict(usemodules=('binascii', 'struct', 'unicodedata'))
+    spaceconfig = {
+        "usemodules": ['unicodedata', 'struct', 'binascii'],
+    }
 
     def test_register_noncallable(self):
         import _codecs
@@ -19,7 +21,7 @@
     def test_ucs4(self):
         x = u'\U00100000'
         y = x.encode("raw-unicode-escape").decode("raw-unicode-escape")
-        assert x == y 
+        assert x == y
 
     def test_named_unicode(self):
         assert unicode('\\N{SPACE}','unicode-escape') == u" "
diff --git a/pypy/module/_continuation/test/test_zpickle.py b/pypy/module/_continuation/test/test_zpickle.py
--- a/pypy/module/_continuation/test/test_zpickle.py
+++ b/pypy/module/_continuation/test/test_zpickle.py
@@ -101,9 +101,11 @@
 
 class AppTestPickle:
     version = 0
-    spaceconfig = dict(usemodules=['_continuation', 'struct'],
-                       continuation=True,
-                       CALL_METHOD=True)
+    spaceconfig = {
+        "usemodules": ['_continuation', 'struct', 'binascii'],
+        "continuation": True,
+        "CALL_METHOD": True,
+    }
 
     def setup_class(cls):
         cls.space.appexec([], """():
diff --git a/pypy/module/_ffi/test/test_struct.py b/pypy/module/_ffi/test/test_struct.py
--- a/pypy/module/_ffi/test/test_struct.py
+++ b/pypy/module/_ffi/test/test_struct.py
@@ -1,7 +1,7 @@
-import sys
+from pypy.interpreter.gateway import interp2app, unwrap_spec
+from pypy.module._ffi.interp_ffitype import app_types, W_FFIType
+from pypy.module._ffi.interp_struct import compute_size_and_alignement, W_Field
 from pypy.module._ffi.test.test_funcptr import BaseAppTestFFI
-from pypy.module._ffi.interp_struct import compute_size_and_alignement, W_Field
-from pypy.module._ffi.interp_ffitype import app_types, W_FFIType
 
 
 class TestStruct(object):
@@ -37,12 +37,14 @@
         assert self.sizeof([T.slonglong, T.sbyte, T.sbyte, T.sbyte]) == llong_size + llong_align
         assert self.sizeof([T.slonglong, T.sbyte, T.sbyte, T.sbyte, T.sbyte]) == llong_size + llong_align
 
+
 class AppTestStruct(BaseAppTestFFI):
 
     def setup_class(cls):
         BaseAppTestFFI.setup_class.im_func(cls)
-        #
-        def read_raw_mem(self, addr, typename, length):
+
+        @unwrap_spec(addr=int, typename=str, length=int)
+        def read_raw_mem(space, addr, typename, length):
             import ctypes
             addr = ctypes.cast(addr, ctypes.c_void_p)
             c_type = getattr(ctypes, typename)
@@ -50,8 +52,11 @@
             ptr_array = ctypes.cast(addr, array_type)
             array = ptr_array[0]
             lst = [array[i] for i in range(length)]
-            return lst
-        cls.w_read_raw_mem = cls.space.wrap(read_raw_mem)
+            return space.wrap(lst)
+        if cls.runappdirect:
+            cls.w_read_raw_mem = lambda self, *args: read_raw_mem(cls.space, *args)
+        else:
+            cls.w_read_raw_mem = cls.space.wrap(interp2app(read_raw_mem))
         #
         from pypy.rlib import clibffi
         from pypy.rlib.rarithmetic import r_uint
diff --git a/pypy/module/_file/test/test_file_extra.py b/pypy/module/_file/test/test_file_extra.py
--- a/pypy/module/_file/test/test_file_extra.py
+++ b/pypy/module/_file/test/test_file_extra.py
@@ -207,15 +207,19 @@
         assert repr(self.file).startswith(
             "<closed file '%s', mode '%s' at 0x" % (
                 self.expected_filename, self.expected_mode))
-        
+
 # ____________________________________________________________
 #
 #  Basic 'rb' mode
 
+
 class AppTestFile(BaseROTests):
-    expected_filename  = str(udir.join('sample'))
-    expected_mode      = 'rb'
+    expected_filename = str(udir.join('sample'))
+    expected_mode = 'rb'
     extra_args = ()
+    spaceconfig = {
+        "usemodules": ["binascii", "rctime"],
+    }
 
     def setup_method(self, method):
         space = self.space
@@ -270,10 +274,14 @@
 #
 #  Files built with fdopen()
 
+
 class AppTestFdOpen(BaseROTests):
-    expected_filename  = '<fdopen>'
-    expected_mode      = 'rb'
+    expected_filename = '<fdopen>'
+    expected_mode = 'rb'
     extra_args = ()
+    spaceconfig = {
+        "usemodules": ["binascii", "rctime"],
+    }
 
     def setup_method(self, method):
         space = self.space
@@ -351,7 +359,9 @@
 #  A few extra tests
 
 class AppTestAFewExtra:
-    spaceconfig = dict(usemodules=('array', '_socket'))
+    spaceconfig = {
+        "usemodules": ['array', '_socket', 'binascii', 'rctime'],
+    }
 
     def setup_method(self, method):
         fn = str(udir.join('temptestfile'))
diff --git a/pypy/module/_hashlib/test/test_hashlib.py b/pypy/module/_hashlib/test/test_hashlib.py
--- a/pypy/module/_hashlib/test/test_hashlib.py
+++ b/pypy/module/_hashlib/test/test_hashlib.py
@@ -1,7 +1,7 @@
-import py
-
 class AppTestHashlib:
-    spaceconfig = dict(usemodules=['_hashlib', 'array', 'struct'])
+    spaceconfig = {
+        "usemodules": ['_hashlib', 'array', 'struct', 'binascii'],
+    }
 
     def test_simple(self):
         import _hashlib
diff --git a/pypy/module/_lsprof/test/test_cprofile.py b/pypy/module/_lsprof/test/test_cprofile.py
--- a/pypy/module/_lsprof/test/test_cprofile.py
+++ b/pypy/module/_lsprof/test/test_cprofile.py
@@ -1,5 +1,7 @@
 class AppTestCProfile(object):
-    spaceconfig = dict(usemodules=('_lsprof',))
+    spaceconfig = {
+        "usemodules": ['_lsprof', 'rctime'],
+    }
 
     def setup_class(cls):
         cls.w_expected_output = cls.space.wrap(expected_output)
diff --git a/pypy/module/_md5/test/test_md5.py b/pypy/module/_md5/test/test_md5.py
--- a/pypy/module/_md5/test/test_md5.py
+++ b/pypy/module/_md5/test/test_md5.py
@@ -4,7 +4,9 @@
 
 
 class AppTestMD5(object):
-    spaceconfig = dict(usemodules=['_md5'])
+    spaceconfig = {
+        "usemodules": ['_md5', 'rctime', 'binascii'],
+    }
 
     def setup_class(cls):
         cls.w_md5 = cls.space.appexec([], """():
@@ -24,7 +26,6 @@
             assert self.md5.blocksize == 1
             assert self.md5.md5().digestsize == 16
 
-
     def test_MD5Type(self):
         """
         Test the two ways to construct an md5 object.
@@ -37,7 +38,6 @@
         d = md5.new()
         assert isinstance(d, md5.MD5Type)
 
-
     def test_md5object(self):
         """
         Feed example strings into a md5 object and check the digest and
@@ -57,7 +57,7 @@
            "c3fcd3d76192e4007dfb496cca67e13b"),
           ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
            "d174ab98d277d9f5a5611c2c9f419d9f"),
-          ("1234567890"*8,
+          ("1234567890" * 8,
            "57edf4a22be3c955ac49da2e2107b67a"),
         )
         for input, expected in cases:
@@ -65,7 +65,6 @@
             assert d.hexdigest() == expected
             assert d.digest() == expected.decode('hex')
 
-
     def test_copy(self):
         """
         Test the copy() method.
@@ -79,7 +78,6 @@
         assert d1.hexdigest() == 'e570e7110ecef72fcb772a9c05d03373'
         assert d2.hexdigest() == 'e8dc4081b13434b45189a720b77b6818'
 
-
     def test_buffer(self):
         """
         Test passing a buffer object.
@@ -89,7 +87,6 @@
         d1.update(buffer("jkl"))
         assert d1.hexdigest() == 'e570e7110ecef72fcb772a9c05d03373'
 
-
     def test_unicode(self):
         """
         Test passing unicode strings.
diff --git a/pypy/module/_multibytecodec/c_codecs.py b/pypy/module/_multibytecodec/c_codecs.py
--- a/pypy/module/_multibytecodec/c_codecs.py
+++ b/pypy/module/_multibytecodec/c_codecs.py
@@ -285,6 +285,7 @@
             # py3k only
             replace = rets
         else:
+            assert retu is not None
             codec = pypy_cjk_enc_getcodec(encodebuf)
             replace = encode(codec, retu, "strict", errorcb, namecb)
     inbuf = rffi.get_nonmovingbuffer(replace)
diff --git a/pypy/module/_multiprocessing/test/test_connection.py b/pypy/module/_multiprocessing/test/test_connection.py
--- a/pypy/module/_multiprocessing/test/test_connection.py
+++ b/pypy/module/_multiprocessing/test/test_connection.py
@@ -89,40 +89,43 @@
 
         return multiprocessing.Pipe(duplex=False)
 
+
 class AppTestSocketConnection(BaseConnectionTest):
-    spaceconfig = dict(usemodules=('_multiprocessing', 'thread', 'signal',
-                                   'struct', 'array', 'itertools'))
+    spaceconfig = {
+        "usemodules": [
+            '_multiprocessing', 'thread', 'signal', 'struct', 'array',
+            'itertools', '_socket', 'binascii',
+        ]
+    }
+
     def setup_class(cls):
         cls.w_connections = cls.space.newlist([])
 
-        def socketpair(space):
-            "A socket.socketpair() that works on Windows"
-            import socket, errno
-            serverSocket = socket.socket()
-            serverSocket.bind(('127.0.0.1', 0))
-            serverSocket.listen(1)
+    def w_socketpair(self):
+        "A socket.socketpair() that works on Windows"
+        import errno
+        import socket
 
-            client = socket.socket()
-            client.setblocking(False)
-            try:
-                client.connect(('127.0.0.1', serverSocket.getsockname()[1]))
-            except socket.error, e:
-                assert e.args[0] in (errno.EINPROGRESS, errno.EWOULDBLOCK)
-            server, addr = serverSocket.accept()
+        serverSocket = socket.socket()
+        serverSocket.bind(('127.0.0.1', 0))
+        serverSocket.listen(1)
 
-            # keep sockets alive during the test
-            space.call_method(cls.w_connections, "append", space.wrap(server))
-            space.call_method(cls.w_connections, "append", space.wrap(client))
+        client = socket.socket()
+        client.setblocking(False)
+        try:
+            client.connect(('127.0.0.1', serverSocket.getsockname()[1]))
+        except socket.error, e:
+            assert e.args[0] in (errno.EINPROGRESS, errno.EWOULDBLOCK)
+        server, addr = serverSocket.accept()
 
-            return space.wrap((server.fileno(), client.fileno()))
-        if cls.runappdirect:
-            cls.w_socketpair = lambda self: socketpair(cls.space)
-        else:
-            cls.w_socketpair = cls.space.wrap(interp2app(socketpair))
+        # keep sockets alive during the test
+        self.connections.append(server)
+        self.connections.append(client)
+
+        return server.fileno(), client.fileno()
 
     def w_make_pair(self):
         import _multiprocessing
-        import os
 
         fd1, fd2 = self.socketpair()
         rhandle = _multiprocessing.Connection(fd1, writable=False)
@@ -170,4 +173,3 @@
         assert data1 == '\x00\x00\x00\x03abc'
         data2 = sock.recv(8)
         assert data2 == '\x00\x00\x00\x04defg'
-
diff --git a/pypy/module/_random/test/test_random.py b/pypy/module/_random/test/test_random.py
--- a/pypy/module/_random/test/test_random.py
+++ b/pypy/module/_random/test/test_random.py
@@ -1,5 +1,7 @@
 class AppTestRandom:
-    spaceconfig = dict(usemodules=['_random'])
+    spaceconfig = {
+        "usemodules": ['_random', 'rctime'],
+    }
 
     def test_dict(self):
         import _random
diff --git a/pypy/module/_sha/test/test_sha.py b/pypy/module/_sha/test/test_sha.py
--- a/pypy/module/_sha/test/test_sha.py
+++ b/pypy/module/_sha/test/test_sha.py
@@ -2,11 +2,11 @@
 Tests for the sha module implemented at interp-level in pypy/module/sha.
 """
 
-import py
-
 
 class AppTestSHA(object):
-    spaceconfig = dict(usemodules=['_sha'])
+    spaceconfig = {
+        "usemodules": ['_sha', 'rctime', 'binascii'],
+    }
 
     def setup_class(cls):
         cls.w_sha = cls.space.appexec([], """():
@@ -14,7 +14,6 @@
             return sha
         """)
 
-
     def test_digest_size(self):
         """
         Check some numeric values from the sha module.
@@ -26,7 +25,6 @@
         assert d.digest_size == 20
         assert d.digestsize == 20
 
-
     def test_SHAType(self):
         """
         Test the two ways to construct an sha object.
@@ -39,7 +37,6 @@
         d = sha.new()
         assert isinstance(d, sha.SHAType)
 
-
     def test_shaobject(self):
         """
         Feed example strings into a sha object and check the digest and
@@ -57,7 +54,7 @@
            "c12252ceda8be8994d5fa0290a47231c1d16aae3"),
           ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
            "761c457bf73b14d27e9e9265c46f4b4dda11f940"),
-          ("1234567890"*8,
+          ("1234567890" * 8,
            "50abf5706a150990a08b2c5ea40fa0e585554732"),
           ("1234567890"*999,
            "eaaca5490568fde98d8dc553d9566bdc602fde4a"),
@@ -67,7 +64,6 @@
             assert d.hexdigest() == expected
             assert d.digest() == expected.decode('hex')
 
-
     def test_copy(self):
         """
         Test the copy() method.
@@ -81,7 +77,6 @@
         assert d1.hexdigest() == 'f5d13cf6341db9b0e299d7b9d562de9572b58e5d'
         assert d2.hexdigest() == '425af12a0743502b322e93a015bcf868e324d56a'
 
-
     def test_buffer(self):
         """
         Test passing a buffer object.
@@ -91,7 +86,6 @@
         d1.update(buffer("jkl"))
         assert d1.hexdigest() == 'f5d13cf6341db9b0e299d7b9d562de9572b58e5d'
 
-
     def test_unicode(self):
         """
         Test passing unicode strings.
diff --git a/pypy/module/_ssl/test/test_ssl.py b/pypy/module/_ssl/test/test_ssl.py
--- a/pypy/module/_ssl/test/test_ssl.py
+++ b/pypy/module/_ssl/test/test_ssl.py
@@ -82,7 +82,9 @@
 
 
 class AppTestConnectedSSL:
-    spaceconfig = dict(usemodules=('_ssl', '_socket', 'struct'))
+    spaceconfig = {
+        "usemodules": ['_ssl', '_socket', 'struct', 'binascii'],
+    }
 
     def setup_method(self, method):
         # https://www.verisign.net/
@@ -165,10 +167,13 @@
         raises(ssl.SSLError, ss.write, "hello\n")
         del ss; gc.collect()
 
+
 class AppTestConnectedSSL_Timeout(AppTestConnectedSSL):
     # Same tests, with a socket timeout
     # to exercise the poll() calls
-    spaceconfig = dict(usemodules=('_ssl', '_socket', 'struct'))
+    spaceconfig = {
+        "usemodules": ['_ssl', '_socket', 'struct', 'binascii'],
+    }
 
     def setup_class(cls):
         cls.space.appexec([], """():
diff --git a/pypy/module/_ssl/thread_lock.py b/pypy/module/_ssl/thread_lock.py
--- a/pypy/module/_ssl/thread_lock.py
+++ b/pypy/module/_ssl/thread_lock.py
@@ -62,13 +62,14 @@
 }
 """
 
+from pypy.module.thread import ll_thread
 
-eci = ExternalCompilationInfo(
+eci = ll_thread.eci.merge(ExternalCompilationInfo(
     separate_module_sources=[separate_module_source],
     post_include_bits=[
         "int _PyPy_SSL_SetupThreads(void);"],
     export_symbols=['_PyPy_SSL_SetupThreads'],
-)
+))
 
 _PyPy_SSL_SetupThreads = rffi.llexternal('_PyPy_SSL_SetupThreads',
                                          [], rffi.INT,
diff --git a/pypy/module/array/test/test_array.py b/pypy/module/array/test/test_array.py
--- a/pypy/module/array/test/test_array.py
+++ b/pypy/module/array/test/test_array.py
@@ -877,8 +877,9 @@
         cls.tempfile = str(py.test.ensuretemp('array').join('tmpfile'))
         cls.maxint = sys.maxint
 
+
 class AppTestArray(BaseArrayTests):
-    spaceconfig = dict(usemodules=('array', 'struct', '_rawffi'))
+    spaceconfig = {'usemodules': ['array', 'struct', '_rawffi', 'binascii']}
 
     def setup_class(cls):
         cls.w_array = cls.space.appexec([], """():
@@ -888,7 +889,7 @@
         cls.w_tempfile = cls.space.wrap(
             str(py.test.ensuretemp('array').join('tmpfile')))
         cls.w_maxint = cls.space.wrap(sys.maxint)
-    
+
     def test_buffer_info(self):
         a = self.array('c', 'Hi!')
         bi = a.buffer_info()
diff --git a/pypy/module/array/test/test_array_old.py b/pypy/module/array/test/test_array_old.py
--- a/pypy/module/array/test/test_array_old.py
+++ b/pypy/module/array/test/test_array_old.py
@@ -89,7 +89,7 @@
 
 
 class AppTestArray(BaseArrayTests):
-    spaceconfig = dict(usemodules=['struct', 'array'])
+    spaceconfig = {'usemodules': ['struct', 'array', 'binascii']}
 
     def setup_class(cls):
         """Import the array module and make it available as self.array."""
diff --git a/pypy/module/bz2/test/test_bz2_compdecomp.py b/pypy/module/bz2/test/test_bz2_compdecomp.py
--- a/pypy/module/bz2/test/test_bz2_compdecomp.py
+++ b/pypy/module/bz2/test/test_bz2_compdecomp.py
@@ -1,6 +1,11 @@
+import os
+
+import py
+
+from pypy.interpreter.gateway import interp2app
 from pypy.module.bz2.test.support import CheckAllocation
 from pypy.module.bz2 import interp_bz2
-import os, py
+
 
 HUGE_OK = False
 
@@ -11,9 +16,10 @@
 def setup_module(mod):
     DATA = 'BZh91AY&SY.\xc8N\x18\x00\x01>_\x80\x00\x10@\x02\xff\xf0\x01\x07n\x00?\xe7\xff\xe00\x01\x99\xaa\x00\xc0\x03F\x86\x8c#&\x83F\x9a\x03\x06\xa6\xd0\xa6\x93M\x0fQ\xa7\xa8\x06\x804hh\x12$\x11\xa4i4\xf14S\xd2<Q\xb5\x0fH\xd3\xd4\xdd\xd5\x87\xbb\xf8\x94\r\x8f\xafI\x12\xe1\xc9\xf8/E\x00pu\x89\x12]\xc9\xbbDL\nQ\x0e\t1\x12\xdf\xa0\xc0\x97\xac2O9\x89\x13\x94\x0e\x1c7\x0ed\x95I\x0c\xaaJ\xa4\x18L\x10\x05#\x9c\xaf\xba\xbc/\x97\x8a#C\xc8\xe1\x8cW\xf9\xe2\xd0\xd6M\xa7\x8bXa<e\x84t\xcbL\xb3\xa7\xd9\xcd\xd1\xcb\x84.\xaf\xb3\xab\xab\xad`n}\xa0lh\tE,\x8eZ\x15\x17VH>\x88\xe5\xcd9gd6\x0b\n\xe9\x9b\xd5\x8a\x99\xf7\x08.K\x8ev\xfb\xf7xw\xbb\xdf\xa1\x92\xf1\xdd|/";\xa2\xba\x9f\xd5\xb1#A\xb6\xf6\xb3o\xc9\xc5y\\\xebO\xe7\x85\x9a\xbc\xb6f8\x952\xd5\xd7"%\x89>V,\xf7\xa6z\xe2\x9f\xa3\xdf\x11\x11"\xd6E)I\xa9\x13^\xca\xf3r\xd0\x03U\x922\xf26\xec\xb6\xed\x8b\xc3U\x13\x9d\xc5\x170\xa4\xfa^\x92\xacDF\x8a\x97\xd6\x19\xfe\xdd\xb8\xbd\x1a\x9a\x19\xa3\x80ankR\x8b\xe5\xd83]\xa9\xc6\x08\x82f\xf6\xb9"6l$\xb8j@\xc0\x8a\xb0l1..\xbak\x83ls\x15\xbc\xf4\xc1\x13\xbe\xf8E\xb8\x9d\r\xa8\x9dk\x84\xd3n\xfa\xacQ\x07\xb1%y\xaav\xb4\x08\xe0z\x1b\x16\xf5\x04\xe9\xcc\xb9\x08z\x1en7.G\xfc]\xc9\x14\xe1B@\xbb!8`'
 
-    def decompress(self, data):
+    def decompress(space, w_data):
         import popen2
         import bz2
+        data = space.str_w(w_data)
         pop = popen2.Popen3("bunzip2", capturestderr=1)
         pop.tochild.write(data)
         pop.tochild.close()
@@ -21,7 +27,7 @@
         pop.fromchild.close()
         if pop.wait() != 0:
             res = bz2.decompress(data)
-        return res
+        return space.wrap(res)
 
     mod.TEXT = 'root:x:0:0:root:/root:/bin/bash\nbin:x:1:1:bin:/bin:\ndaemon:x:2:2:daemon:/sbin:\nadm:x:3:4:adm:/var/adm:\nlp:x:4:7:lp:/var/spool/lpd:\nsync:x:5:0:sync:/sbin:/bin/sync\nshutdown:x:6:0:shutdown:/sbin:/sbin/shutdown\nhalt:x:7:0:halt:/sbin:/sbin/halt\nmail:x:8:12:mail:/var/spool/mail:\nnews:x:9:13:news:/var/spool/news:\nuucp:x:10:14:uucp:/var/spool/uucp:\noperator:x:11:0:operator:/root:\ngames:x:12:100:games:/usr/games:\ngopher:x:13:30:gopher:/usr/lib/gopher-data:\nftp:x:14:50:FTP User:/var/ftp:/bin/bash\nnobody:x:65534:65534:Nobody:/home:\npostfix:x:100:101:postfix:/var/spool/postfix:\nniemeyer:x:500:500::/home/niemeyer:/bin/bash\npostgres:x:101:102:PostgreSQL Server:/var/lib/pgsql:/bin/bash\nmysql:x:102:103:MySQL server:/var/lib/mysql:/bin/bash\nwww:x:103:104::/var/www:/bin/false\n'
     mod.DATA = DATA
@@ -40,9 +46,12 @@
 
     def setup_class(cls):
         cls.w_TEXT = cls.space.wrap(TEXT)
-        cls.w_decompress = cls.space.wrap(decompress)
+        if cls.runappdirect:
+            cls.w_decompress = lambda self, *args: decompress(cls.space, *args)
+        else:
+            cls.w_decompress = cls.space.wrap(interp2app(decompress))
         cls.w_HUGE_OK = cls.space.wrap(HUGE_OK)
-        
+
     def test_creation(self):
         from bz2 import BZ2Compressor
         
@@ -95,6 +104,7 @@
         data = "%s%s" % (data, bz2c.flush())
         assert self.decompress(data) == self.TEXT
 
+
 class AppTestBZ2Decompressor(CheckAllocation):
     spaceconfig = dict(usemodules=('bz2',))
 
@@ -170,13 +180,17 @@
         assert decompressed_data == ''
         raises(IOError, bz2d.decompress, self.BUGGY_DATA)
 
+
 class AppTestBZ2ModuleFunctions(CheckAllocation):
     spaceconfig = dict(usemodules=('bz2',))
 
     def setup_class(cls):
         cls.w_TEXT = cls.space.wrap(TEXT)
         cls.w_DATA = cls.space.wrap(DATA)
-        cls.w_decompress = cls.space.wrap(decompress)
+        if cls.runappdirect:
+            cls.w_decompress = lambda self, *args: decompress(cls.space, *args)
+        else:
+            cls.w_decompress = cls.space.wrap(interp2app(decompress))
         cls.w_HUGE_OK = cls.space.wrap(HUGE_OK)
 
     def test_compress_function(self):
diff --git a/pypy/module/bz2/test/test_bz2_file.py b/pypy/module/bz2/test/test_bz2_file.py
--- a/pypy/module/bz2/test/test_bz2_file.py
+++ b/pypy/module/bz2/test/test_bz2_file.py
@@ -1,29 +1,34 @@
 from __future__ import with_statement
 
-import py
-from pypy.module.bz2.test.support import CheckAllocation
 import os
 import random
 
+import py
+
+from pypy.interpreter.gateway import unwrap_spec, interp2app
+
+
 if os.name == "nt":
     from py.test import skip
     skip("bz2 module is not available on Windows")
-        
+
 def setup_module(mod):
     DATA = 'BZh91AY&SY.\xc8N\x18\x00\x01>_\x80\x00\x10@\x02\xff\xf0\x01\x07n\x00?\xe7\xff\xe00\x01\x99\xaa\x00\xc0\x03F\x86\x8c#&\x83F\x9a\x03\x06\xa6\xd0\xa6\x93M\x0fQ\xa7\xa8\x06\x804hh\x12$\x11\xa4i4\xf14S\xd2<Q\xb5\x0fH\xd3\xd4\xdd\xd5\x87\xbb\xf8\x94\r\x8f\xafI\x12\xe1\xc9\xf8/E\x00pu\x89\x12]\xc9\xbbDL\nQ\x0e\t1\x12\xdf\xa0\xc0\x97\xac2O9\x89\x13\x94\x0e\x1c7\x0ed\x95I\x0c\xaaJ\xa4\x18L\x10\x05#\x9c\xaf\xba\xbc/\x97\x8a#C\xc8\xe1\x8cW\xf9\xe2\xd0\xd6M\xa7\x8bXa<e\x84t\xcbL\xb3\xa7\xd9\xcd\xd1\xcb\x84.\xaf\xb3\xab\xab\xad`n}\xa0lh\tE,\x8eZ\x15\x17VH>\x88\xe5\xcd9gd6\x0b\n\xe9\x9b\xd5\x8a\x99\xf7\x08.K\x8ev\xfb\xf7xw\xbb\xdf\xa1\x92\xf1\xdd|/";\xa2\xba\x9f\xd5\xb1#A\xb6\xf6\xb3o\xc9\xc5y\\\xebO\xe7\x85\x9a\xbc\xb6f8\x952\xd5\xd7"%\x89>V,\xf7\xa6z\xe2\x9f\xa3\xdf\x11\x11"\xd6E)I\xa9\x13^\xca\xf3r\xd0\x03U\x922\xf26\xec\xb6\xed\x8b\xc3U\x13\x9d\xc5\x170\xa4\xfa^\x92\xacDF\x8a\x97\xd6\x19\xfe\xdd\xb8\xbd\x1a\x9a\x19\xa3\x80ankR\x8b\xe5\xd83]\xa9\xc6\x08\x82f\xf6\xb9"6l$\xb8j@\xc0\x8a\xb0l1..\xbak\x83ls\x15\xbc\xf4\xc1\x13\xbe\xf8E\xb8\x9d\r\xa8\x9dk\x84\xd3n\xfa\xacQ\x07\xb1%y\xaav\xb4\x08\xe0z\x1b\x16\xf5\x04\xe9\xcc\xb9\x08z\x1en7.G\xfc]\xc9\x14\xe1B@\xbb!8`'
     DATA_CRLF = 'BZh91AY&SY\xaez\xbbN\x00\x01H\xdf\x80\x00\x12@\x02\xff\xf0\x01\x07n\x00?\xe7\xff\xe0@\x01\xbc\xc6`\x86*\x8d=M\xa9\x9a\x86\xd0L@\x0fI\xa6!\xa1\x13\xc8\x88jdi\x8d@\x03@\x1a\x1a\x0c\x0c\x83 \x00\xc4h2\x19\x01\x82D\x84e\t\xe8\x99\x89\x19\x1ah\x00\r\x1a\x11\xaf\x9b\x0fG\xf5(\x1b\x1f?\t\x12\xcf\xb5\xfc\x95E\x00ps\x89\x12^\xa4\xdd\xa2&\x05(\x87\x04\x98\x89u\xe40%\xb6\x19\'\x8c\xc4\x89\xca\x07\x0e\x1b!\x91UIFU%C\x994!DI\xd2\xfa\xf0\xf1N8W\xde\x13A\xf5\x9cr%?\x9f3;I45A\xd1\x8bT\xb1<l\xba\xcb_\xc00xY\x17r\x17\x88\x08\x08@\xa0\ry@\x10\x04$)`\xf2\xce\x89z\xb0s\xec\x9b.iW\x9d\x81\xb5-+t\x9f\x1a\'\x97dB\xf5x\xb5\xbe.[.\xd7\x0e\x81\xe7\x08\x1cN`\x88\x10\xca\x87\xc3!"\x80\x92R\xa1/\xd1\xc0\xe6mf\xac\xbd\x99\xcca\xb3\x8780>\xa4\xc7\x8d\x1a\\"\xad\xa1\xabyBg\x15\xb9l\x88\x88\x91k"\x94\xa4\xd4\x89\xae*\xa6\x0b\x10\x0c\xd6\xd4m\xe86\xec\xb5j\x8a\x86j\';\xca.\x01I\xf2\xaaJ\xe8\x88\x8cU+t3\xfb\x0c\n\xa33\x13r2\r\x16\xe0\xb3(\xbf\x1d\x83r\xe7M\xf0D\x1365\xd8\x88\xd3\xa4\x92\xcb2\x06\x04\\\xc1\xb0\xea//\xbek&\xd8\xe6+t\xe5\xa1\x13\xada\x16\xder5"w]\xa2i\xb7[\x97R \xe2IT\xcd;Z\x04dk4\xad\x8a\t\xd3\x81z\x10\xf1:^`\xab\x1f\xc5\xdc\x91N\x14$+\x9e\xae\xd3\x80'
 
-    def create_temp_file(self, crlf=False):
+    @unwrap_spec(crlf=bool)
+    def create_temp_file(space, crlf=False):
         f = py.test.ensuretemp("bz2").join("foo")
         data = (DATA, DATA_CRLF)[crlf]
         f.write(data, 'wb')
 
-    def create_broken_temp_file(self):
+    def create_broken_temp_file():
         f = py.test.ensuretemp("bz2").join("foo")
         data = DATA[:100]
         f.write(data, 'wb')
-    
-    def decompress(self, data):
+
+    @unwrap_spec(data=str)
+    def decompress(space, data):
         import popen2
         import bz2
         pop = popen2.Popen3("bunzip2", capturestderr=1)
@@ -33,7 +38,7 @@
         pop.fromchild.close()
         if pop.wait() != 0:
             res = bz2.decompress(data)
-        return res
+        return space.wrap(res)
 
     mod.TEXT = 'root:x:0:0:root:/root:/bin/bash\nbin:x:1:1:bin:/bin:\ndaemon:x:2:2:daemon:/sbin:\nadm:x:3:4:adm:/var/adm:\nlp:x:4:7:lp:/var/spool/lpd:\nsync:x:5:0:sync:/sbin:/bin/sync\nshutdown:x:6:0:shutdown:/sbin:/sbin/shutdown\nhalt:x:7:0:halt:/sbin:/sbin/halt\nmail:x:8:12:mail:/var/spool/mail:\nnews:x:9:13:news:/var/spool/news:\nuucp:x:10:14:uucp:/var/spool/uucp:\noperator:x:11:0:operator:/root:\ngames:x:12:100:games:/usr/games:\ngopher:x:13:30:gopher:/usr/lib/gopher-data:\nftp:x:14:50:FTP User:/var/ftp:/bin/bash\nnobody:x:65534:65534:Nobody:/home:\npostfix:x:100:101:postfix:/var/spool/postfix:\nniemeyer:x:500:500::/home/niemeyer:/bin/bash\npostgres:x:101:102:PostgreSQL Server:/var/lib/pgsql:/bin/bash\nmysql:x:102:103:MySQL server:/var/lib/mysql:/bin/bash\nwww:x:103:104::/var/www:/bin/false\n'
     mod.DATA = DATA
@@ -44,11 +49,14 @@
     s = 'abcdefghijklmnop'
     mod.RANDOM_DATA = ''.join([s[int(random.random() * len(s))] for i in range(30000)])
 
+
 class AppTestBZ2File: #(CheckAllocation):
     # XXX for unknown reasons, we cannot do allocation checks, as sth is
     # keeping those objects alive (BZ2File objects)
 
-    spaceconfig = dict(usemodules=('bz2',))
+    spaceconfig = {
+        "usemodules": ["bz2", "binascii", "rctime"]
+    }
 
     def setup_class(cls):
         cls.w_TEXT = cls.space.wrap(TEXT)
@@ -56,14 +64,19 @@
         cls.w_DATA_CRLF = cls.space.wrap(DATA_CRLF)
         cls.w_temppath = cls.space.wrap(
             str(py.test.ensuretemp("bz2").join("foo")))
-        cls.w_create_temp_file = cls.space.wrap(create_temp_file)
-        cls.w_decompress = cls.space.wrap(decompress)
-        cls.w_create_broken_temp_file = cls.space.wrap(create_broken_temp_file)
+        if cls.runappdirect:
+            cls.w_create_temp_file = create_temp_file
+            cls.w_create_broken_temp_file = lambda self: create_broken_temp_file()
+            cls.w_decompress = lambda self, *args: decompress(cls.space, *args)
+        else:
+            cls.w_create_temp_file = cls.space.wrap(interp2app(create_temp_file))
+            cls.w_create_broken_temp_file = cls.space.wrap(interp2app(create_broken_temp_file))
+            cls.w_decompress = cls.space.wrap(interp2app(decompress))
         cls.w_random_data = cls.space.wrap(RANDOM_DATA)
-        
+
     def test_attributes(self):
         from bz2 import BZ2File
-        
+
         bz2f = BZ2File(self.temppath, mode="w")
         assert bz2f.name == self.temppath
         assert bz2f.newlines == None
diff --git a/pypy/module/cppyy/capi/__init__.py b/pypy/module/cppyy/capi/__init__.py
--- a/pypy/module/cppyy/capi/__init__.py
+++ b/pypy/module/cppyy/capi/__init__.py
@@ -27,6 +27,7 @@
 
 C_METHOD = _C_OPAQUE_PTR
 C_INDEX = rffi.LONG
+C_INDEX_ARRAY = rffi.LONGP
 WLAVC_INDEX = rffi.LONG
 
 C_METHPTRGETTER = lltype.FuncType([C_OBJECT], rffi.VOIDP)
@@ -39,6 +40,9 @@
     address = rffi.cast(rffi.CCHARP, ptr)
     return rffi.cast(C_OBJECT, lltype.direct_ptradd(address, offset))
 
+def exchange_address(ptr, cif_descr, index):
+    return rffi.ptradd(ptr, cif_descr.exchange_args[index])
+
 c_load_dictionary = backend.c_load_dictionary
 
 # name to opaque C++ scope representation ------------------------------------
@@ -293,13 +297,24 @@
     compilation_info=backend.eci)
 def c_method_index_at(cppscope, imethod):
     return _c_method_index_at(cppscope.handle, imethod)
-_c_method_index_from_name = rffi.llexternal(
-    "cppyy_method_index_from_name",
-    [C_SCOPE, rffi.CCHARP], C_INDEX,
+_c_method_indices_from_name = rffi.llexternal(
+    "cppyy_method_indices_from_name",
+    [C_SCOPE, rffi.CCHARP], C_INDEX_ARRAY,
     threadsafe=ts_reflect,
     compilation_info=backend.eci)
-def c_method_index_from_name(cppscope, name):
-    return _c_method_index_from_name(cppscope.handle, name)
+def c_method_indices_from_name(cppscope, name):
+    indices = _c_method_indices_from_name(cppscope.handle, name)
+    if not indices:
+        return []
+    py_indices = []
+    i = 0
+    index = indices[i]
+    while index != -1:
+        i += 1
+        py_indices.append(index)
+        index = indices[i]
+    c_free(rffi.cast(rffi.VOIDP, indices))   # c_free defined below
+    return py_indices
 
 _c_method_name = rffi.llexternal(
     "cppyy_method_name",
diff --git a/pypy/module/cppyy/capi/cint_capi.py b/pypy/module/cppyy/capi/cint_capi.py
--- a/pypy/module/cppyy/capi/cint_capi.py
+++ b/pypy/module/cppyy/capi/cint_capi.py
@@ -53,7 +53,7 @@
     include_dirs=[incpath] + rootincpath,
     includes=["cintcwrapper.h"],
     library_dirs=rootlibpath,
-    link_extra=["-lCore", "-lCint"],
+    libraries=["Core", "Cint"],
     use_cpp_linker=True,
 )
 
@@ -65,14 +65,21 @@
 
 def c_load_dictionary(name):
     result = _c_load_dictionary(name)
-    if not result:
-        err = rdynload.dlerror()
-        raise rdynload.DLOpenError(err)
-    return libffi.CDLL(name)       # should return handle to already open file
+    # ignore result: libffi.CDLL(name) either returns a handle to the already
+    # open file, or will fail as well and produce a correctly formatted error
+    return libffi.CDLL(name)
 
 
 # CINT-specific pythonizations ===============================================
 
+def _get_string_data(space, w_obj, m1, m2 = None):
+    from pypy.module.cppyy import interp_cppyy
+    obj = space.interp_w(interp_cppyy.W_CPPInstance, w_obj)
+    w_1 = obj.space.call_method(w_obj, m1)
+    if m2 is None:
+        return w_1
+    return obj.space.call_method(w_1, m2)
+
 ### TTree --------------------------------------------------------------------
 _ttree_Branch = rffi.llexternal(
     "cppyy_ttree_Branch",
@@ -212,25 +219,41 @@
 def register_pythonizations(space):
     "NOT_RPYTHON"
 
-    ### TTree
-    _pythonizations['ttree_Branch']  = space.wrap(interp2app(ttree_Branch))
-    _pythonizations['ttree_iter']    = space.wrap(interp2app(ttree_iter))
-    _pythonizations['ttree_getattr'] = space.wrap(interp2app(ttree_getattr))
+    allfuncs = [
+
+        ### TTree
+        ttree_Branch, ttree_iter, ttree_getattr,
+    ]
+
+    for f in allfuncs:
+        _pythonizations[f.__name__] = space.wrap(interp2app(f))
+
+def _method_alias(space, w_pycppclass, m1, m2):
+    space.setattr(w_pycppclass, space.wrap(m1),
+                  space.getattr(w_pycppclass, space.wrap(m2)))
 
 # callback coming in when app-level bound classes have been created
 def pythonize(space, name, w_pycppclass):
 
-    if name == 'TFile':
-        space.setattr(w_pycppclass, space.wrap("__getattr__"),
-                      space.getattr(w_pycppclass, space.wrap("Get")))
+    if name == "TFile":
+        _method_alias(space, w_pycppclass, "__getattr__", "Get")
 
-    elif name == 'TTree':
-        space.setattr(w_pycppclass, space.wrap("_unpythonized_Branch"),
-                      space.getattr(w_pycppclass, space.wrap("Branch")))
-        space.setattr(w_pycppclass, space.wrap("Branch"), _pythonizations["ttree_Branch"])
-        space.setattr(w_pycppclass, space.wrap("__iter__"), _pythonizations["ttree_iter"])
+    elif name == "TObjString":
+        _method_alias(space, w_pycppclass, "__str__", "GetName")
+        _method_alias(space, w_pycppclass, "_cppyy_as_builtin", "GetString")
+
+    elif name == "TString":
+        _method_alias(space, w_pycppclass, "__str__", "Data")
+        _method_alias(space, w_pycppclass, "__len__", "Length")
+        _method_alias(space, w_pycppclass, "__cmp__", "CompareTo")
+        _method_alias(space, w_pycppclass, "_cppyy_as_builtin", "Data")
+
+    elif name == "TTree":
+        _method_alias(space, w_pycppclass, "_unpythonized_Branch", "Branch")
+
+        space.setattr(w_pycppclass, space.wrap("Branch"),      _pythonizations["ttree_Branch"])
+        space.setattr(w_pycppclass, space.wrap("__iter__"),    _pythonizations["ttree_iter"])
         space.setattr(w_pycppclass, space.wrap("__getattr__"), _pythonizations["ttree_getattr"])
 
     elif name[0:8] == "TVectorT":    # TVectorT<> template
-        space.setattr(w_pycppclass, space.wrap("__len__"),
-                      space.getattr(w_pycppclass, space.wrap("GetNoElements")))
+        _method_alias(space, w_pycppclass, "__len__", "GetNoElements")
diff --git a/pypy/module/cppyy/capi/reflex_capi.py b/pypy/module/cppyy/capi/reflex_capi.py
--- a/pypy/module/cppyy/capi/reflex_capi.py
+++ b/pypy/module/cppyy/capi/reflex_capi.py
@@ -35,7 +35,7 @@
     include_dirs=[incpath] + rootincpath,
     includes=["reflexcwrapper.h"],
     library_dirs=rootlibpath,
-    link_extra=["-lReflex"],
+    libraries=["Reflex"],
     use_cpp_linker=True,
 )
 
diff --git a/pypy/module/cppyy/converter.py b/pypy/module/cppyy/converter.py
--- a/pypy/module/cppyy/converter.py
+++ b/pypy/module/cppyy/converter.py
@@ -4,7 +4,7 @@
 
 from pypy.rpython.lltypesystem import rffi, lltype
 from pypy.rlib.rarithmetic import r_singlefloat
-from pypy.rlib import libffi, clibffi, rfloat
+from pypy.rlib import jit_libffi, rfloat
 
 from pypy.module._rawffi.interp_rawffi import unpack_simple_shape
 from pypy.module._rawffi.array import W_Array
@@ -67,10 +67,10 @@
 
 
 class TypeConverter(object):
-    _immutable_ = True
-    libffitype = lltype.nullptr(clibffi.FFI_TYPE_P.TO)
+    _immutable_fields_ = ['libffitype', 'uses_local', 'name']
+
+    libffitype = lltype.nullptr(jit_libffi.FFI_TYPE_P.TO)
     uses_local = False
-
     name = ""
 
     def __init__(self, space, extra):
@@ -91,11 +91,11 @@
     def convert_argument(self, space, w_obj, address, call_local):
         self._is_abstract(space)
 
-    def convert_argument_libffi(self, space, w_obj, argchain, call_local):
+    def convert_argument_libffi(self, space, w_obj, address, call_local):
         from pypy.module.cppyy.interp_cppyy import FastCallNotPossible
         raise FastCallNotPossible
 
-    def default_argument_libffi(self, space, argchain):
+    def default_argument_libffi(self, space, address):
         from pypy.module.cppyy.interp_cppyy import FastCallNotPossible
         raise FastCallNotPossible
 
@@ -128,7 +128,9 @@
 
 class ArrayTypeConverterMixin(object):
     _mixin_ = True
-    _immutable_ = True
+    _immutable_fields_ = ['libffitype', 'size']
+
+    libffitype = jit_libffi.types.pointer
 
     def __init__(self, space, array_size):
         if array_size <= 0:
@@ -157,7 +159,9 @@
 
 class PtrTypeConverterMixin(object):
     _mixin_ = True
-    _immutable_ = True
+    _immutable_fields_ = ['libffitype', 'size']
+
+    libffitype = jit_libffi.types.pointer
 
     def __init__(self, space, array_size):
         self.size = sys.maxint
@@ -167,9 +171,9 @@
         if w_tc is not None and space.str_w(w_tc) != self.typecode:
             msg = "expected %s pointer type, but received %s" % (self.typecode, space.str_w(w_tc))
             raise OperationError(space.w_TypeError, space.wrap(msg))
-        x = rffi.cast(rffi.LONGP, address)
+        x = rffi.cast(rffi.VOIDPP, address)
         try:
-            x[0] = rffi.cast(rffi.LONG, get_rawbuffer(space, w_obj))
+            x[0] = rffi.cast(rffi.VOIDP, get_rawbuffer(space, w_obj))
         except TypeError:
             raise OperationError(space.w_TypeError,
                                  space.wrap("raw buffer interface not supported"))
@@ -198,13 +202,14 @@
 
 class NumericTypeConverterMixin(object):
     _mixin_ = True
-    _immutable_ = True
 
-    def convert_argument_libffi(self, space, w_obj, argchain, call_local):
-        argchain.arg(self._unwrap_object(space, w_obj))
+    def convert_argument_libffi(self, space, w_obj, address, call_local):
+        x = rffi.cast(self.c_ptrtype, address)
+        x[0] = self._unwrap_object(space, w_obj)
 
-    def default_argument_libffi(self, space, argchain):
-        argchain.arg(self.default)
+    def default_argument_libffi(self, space, address):
+        x = rffi.cast(self.c_ptrtype, address)
+        x[0] = self.default
 
     def from_memory(self, space, w_obj, w_pycppclass, offset):
         address = self._get_raw_address(space, w_obj, offset)
@@ -218,19 +223,20 @@
 
 class ConstRefNumericTypeConverterMixin(NumericTypeConverterMixin):
     _mixin_ = True
-    _immutable_ = True
+    _immutable_fields_ = ['uses_local']
+
     uses_local = True
 
-    def convert_argument_libffi(self, space, w_obj, argchain, call_local):
+    def convert_argument_libffi(self, space, w_obj, address, call_local):
         assert rffi.sizeof(self.c_type) <= 2*rffi.sizeof(rffi.VOIDP)  # see interp_cppyy.py
         obj = self._unwrap_object(space, w_obj)
         typed_buf = rffi.cast(self.c_ptrtype, call_local)
         typed_buf[0] = obj
-        argchain.arg(call_local)
+        x = rffi.cast(rffi.VOIDPP, address)
+        x[0] = call_local
 
 class IntTypeConverterMixin(NumericTypeConverterMixin):
     _mixin_ = True
-    _immutable_ = True
 
     def convert_argument(self, space, w_obj, address, call_local):
         x = rffi.cast(self.c_ptrtype, address)
@@ -238,7 +244,6 @@
 
 class FloatTypeConverterMixin(NumericTypeConverterMixin):
     _mixin_ = True
-    _immutable_ = True
 
     def convert_argument(self, space, w_obj, address, call_local):
         x = rffi.cast(self.c_ptrtype, address)
@@ -248,8 +253,9 @@
 
 
 class VoidConverter(TypeConverter):
-    _immutable_ = True
-    libffitype = libffi.types.void
+    _immutable_fields_ = ['libffitype', 'name']
+
+    libffitype = jit_libffi.types.void
 
     def __init__(self, space, name):
         self.name = name
@@ -260,14 +266,13 @@
 
 
 class BoolConverter(ffitypes.typeid(bool), TypeConverter):
-    _immutable_ = True
-
     def convert_argument(self, space, w_obj, address, call_local):
         x = rffi.cast(rffi.LONGP, address)
         x[0] = self._unwrap_object(space, w_obj)
 
-    def convert_argument_libffi(self, space, w_obj, argchain, call_local):
-        argchain.arg(self._unwrap_object(space, w_obj))
+    def convert_argument_libffi(self, space, w_obj, address, call_local):
+        x = rffi.cast(rffi.LONGP, address)
+        x[0] = self._unwrap_object(space, w_obj)
 
     def from_memory(self, space, w_obj, w_pycppclass, offset):
         address = rffi.cast(rffi.CCHARP, self._get_raw_address(space, w_obj, offset))
@@ -284,14 +289,13 @@
             address[0] = '\x00'
 
 class CharConverter(ffitypes.typeid(rffi.CHAR), TypeConverter):
-    _immutable_ = True
-
     def convert_argument(self, space, w_obj, address, call_local):
         x = rffi.cast(rffi.CCHARP, address)
         x[0] = self._unwrap_object(space, w_obj)
 
-    def convert_argument_libffi(self, space, w_obj, argchain, call_local):
-        argchain.arg(self._unwrap_object(space, w_obj))
+    def convert_argument_libffi(self, space, w_obj, address, call_local):
+        x = rffi.cast(self.c_ptrtype, address)
+        x[0] = self._unwrap_object(space, w_obj)
 
     def from_memory(self, space, w_obj, w_pycppclass, offset):
         address = rffi.cast(rffi.CCHARP, self._get_raw_address(space, w_obj, offset))
@@ -302,7 +306,7 @@
         address[0] = self._unwrap_object(space, w_value)
 
 class FloatConverter(ffitypes.typeid(rffi.FLOAT), FloatTypeConverterMixin, TypeConverter):
-    _immutable_ = True
+    _immutable_fields_ = ['default']
 
     def __init__(self, space, default):
         if default:
@@ -317,16 +321,17 @@
         return space.wrap(float(rffiptr[0]))
 
 class ConstFloatRefConverter(FloatConverter):
-    _immutable_ = True
-    libffitype = libffi.types.pointer
+    _immutable_fields_ = ['libffitype', 'typecode']
+
+    libffitype = jit_libffi.types.pointer
     typecode = 'F'
 
-    def convert_argument_libffi(self, space, w_obj, argchain, call_local):
+    def convert_argument_libffi(self, space, w_obj, address, call_local):
         from pypy.module.cppyy.interp_cppyy import FastCallNotPossible
         raise FastCallNotPossible
 
 class DoubleConverter(ffitypes.typeid(rffi.DOUBLE), FloatTypeConverterMixin, TypeConverter):
-    _immutable_ = True
+    _immutable_fields_ = ['default']
 
     def __init__(self, space, default):
         if default:
@@ -335,14 +340,13 @@
             self.default = rffi.cast(self.c_type, 0.)
 
 class ConstDoubleRefConverter(ConstRefNumericTypeConverterMixin, DoubleConverter):
-    _immutable_ = True
-    libffitype = libffi.types.pointer
+    _immutable_fields_ = ['libffitype', 'typecode']
+
+    libffitype = jit_libffi.types.pointer
     typecode = 'D'
 
 
 class CStringConverter(TypeConverter):
-    _immutable_ = True
-
     def convert_argument(self, space, w_obj, address, call_local):
         x = rffi.cast(rffi.LONGP, address)
         arg = space.str_w(w_obj)
@@ -360,22 +364,30 @@
 
 
 class VoidPtrConverter(TypeConverter):
-    _immutable_ = True
+    _immutable_fields_ = ['libffitype']
+
+    libffitype = jit_libffi.types.pointer
+
+    def _unwrap_object(self, space, w_obj):
+        try:
+            obj = get_rawbuffer(space, w_obj)
+        except TypeError:
+            obj = rffi.cast(rffi.VOIDP, get_rawobject(space, w_obj))
+        return obj
 
     def convert_argument(self, space, w_obj, address, call_local):
         x = rffi.cast(rffi.VOIDPP, address)
+        x[0] = self._unwrap_object(space, w_obj)
         ba = rffi.cast(rffi.CCHARP, address)
-        try:
-            x[0] = get_rawbuffer(space, w_obj)
-        except TypeError:
-            x[0] = rffi.cast(rffi.VOIDP, get_rawobject(space, w_obj))
         ba[capi.c_function_arg_typeoffset()] = 'o'
 
-    def convert_argument_libffi(self, space, w_obj, argchain, call_local):
-        argchain.arg(get_rawobject(space, w_obj))
+    def convert_argument_libffi(self, space, w_obj, address, call_local):
+        x = rffi.cast(rffi.VOIDPP, address)
+        x[0] = self._unwrap_object(space, w_obj)
 
 class VoidPtrPtrConverter(TypeConverter):
-    _immutable_ = True
+    _immutable_fields_ = ['uses_local']
+
     uses_local = True
 
     def convert_argument(self, space, w_obj, address, call_local):
@@ -397,11 +409,13 @@
             pass             # no set on buffer/array/None
 
 class VoidPtrRefConverter(VoidPtrPtrConverter):
-    _immutable_ = True
+    _immutable_fields_ = ['uses_local']
     uses_local = True
 
 class InstancePtrConverter(TypeConverter):
-    _immutable_ = True
+    _immutable_fields_ = ['libffitype', 'cppclass']
+
+    libffitype  = jit_libffi.types.pointer
 
     def __init__(self, space, cppclass):
         from pypy.module.cppyy.interp_cppyy import W_CPPClass
@@ -428,8 +442,9 @@
         ba = rffi.cast(rffi.CCHARP, address)
         ba[capi.c_function_arg_typeoffset()] = 'o'
 
-    def convert_argument_libffi(self, space, w_obj, argchain, call_local):
-        argchain.arg(self._unwrap_object(space, w_obj))
+    def convert_argument_libffi(self, space, w_obj, address, call_local):
+        x = rffi.cast(rffi.VOIDPP, address)
+        x[0] = rffi.cast(rffi.VOIDP, self._unwrap_object(space, w_obj))
 
     def from_memory(self, space, w_obj, w_pycppclass, offset):
         address = rffi.cast(capi.C_OBJECT, self._get_raw_address(space, w_obj, offset))
@@ -442,7 +457,10 @@
         address[0] = rffi.cast(rffi.VOIDP, self._unwrap_object(space, w_value))
 
 class InstanceConverter(InstancePtrConverter):
-    _immutable_ = True
+
+    def convert_argument_libffi(self, space, w_obj, address, call_local):
+        from pypy.module.cppyy.interp_cppyy import FastCallNotPossible
+        raise FastCallNotPossible       # TODO: by-value is a jit_libffi special case
 
     def from_memory(self, space, w_obj, w_pycppclass, offset):
         address = rffi.cast(capi.C_OBJECT, self._get_raw_address(space, w_obj, offset))
@@ -454,7 +472,8 @@
         self._is_abstract(space)
 
 class InstancePtrPtrConverter(InstancePtrConverter):
-    _immutable_ = True
+    _immutable_fields_ = ['uses_local']
+
     uses_local = True
 
     def convert_argument(self, space, w_obj, address, call_local):
@@ -466,6 +485,11 @@
         ba = rffi.cast(rffi.CCHARP, address)
         ba[capi.c_function_arg_typeoffset()] = 'o'
 
+    def convert_argument_libffi(self, space, w_obj, address, call_local):
+        # TODO: finalize_call not yet called for fast call (see interp_cppyy.py)
+        from pypy.module.cppyy.interp_cppyy import FastCallNotPossible
+        raise FastCallNotPossible
+
     def from_memory(self, space, w_obj, w_pycppclass, offset):
         self._is_abstract(space)
 
@@ -481,7 +505,7 @@
 
 
 class StdStringConverter(InstanceConverter):
-    _immutable_ = True
+    _immutable_fields_ = ['cppclass']
 
     def __init__(self, space, extra):
         from pypy.module.cppyy import interp_cppyy
@@ -513,7 +537,7 @@
         capi.c_free_stdstring(rffi.cast(capi.C_OBJECT, rffi.cast(rffi.VOIDPP, arg)[0]))
 
 class StdStringRefConverter(InstancePtrConverter):
-    _immutable_ = True
+    _immutable_fields_ = ['cppclass']
 
     def __init__(self, space, extra):
         from pypy.module.cppyy import interp_cppyy
@@ -522,7 +546,9 @@
 
 
 class PyObjectConverter(TypeConverter):
-    _immutable_ = True
+    _immutable_fields_ = ['libffitype']
+
+    libffitype = jit_libffi.types.pointer
 
     def convert_argument(self, space, w_obj, address, call_local):
         if hasattr(space, "fake"):
@@ -535,13 +561,19 @@
         ba = rffi.cast(rffi.CCHARP, address)
         ba[capi.c_function_arg_typeoffset()] = 'a'
 
-    def convert_argument_libffi(self, space, w_obj, argchain, call_local):
-        if hasattr(space, "fake"):
+    def convert_argument_libffi(self, space, w_obj, address, call_local):
+        # TODO: free_argument not yet called for fast call (see interp_cppyy.py)
+        from pypy.module.cppyy.interp_cppyy import FastCallNotPossible
+        raise FastCallNotPossible
+
+        # proposed implementation:
+        """if hasattr(space, "fake"):
             raise NotImplementedError
         space.getbuiltinmodule("cpyext")
         from pypy.module.cpyext.pyobject import make_ref
         ref = make_ref(space, w_obj)
-        argchain.arg(rffi.cast(rffi.VOIDP, ref))
+        x = rffi.cast(rffi.VOIDPP, address)
+        x[0] = rffi.cast(rffi.VOIDP, ref)"""
 
     def free_argument(self, space, arg, call_local):
         if hasattr(space, "fake"):
@@ -649,7 +681,7 @@
                 self.default = rffi.cast(self.c_type, capi.c_strtoll(default))
         class ConstRefConverter(ConstRefNumericTypeConverterMixin, BasicConverter):
             _immutable_ = True
-            libffitype = libffi.types.pointer
+            libffitype = jit_libffi.types.pointer
         for name in names:
             _converters[name] = BasicConverter
             _converters["const "+name+"&"] = ConstRefConverter
@@ -666,7 +698,7 @@
                 self.default = rffi.cast(self.c_type, capi.c_strtoll(default))
         class ConstRefConverter(ConstRefNumericTypeConverterMixin, BasicConverter):
             _immutable_ = True
-            libffitype = libffi.types.pointer
+            libffitype = jit_libffi.types.pointer
             typecode = 'r'
             def convert_argument(self, space, w_obj, address, call_local):
                 x = rffi.cast(self.c_ptrtype, address)
@@ -692,7 +724,7 @@
                 self.default = rffi.cast(self.c_type, capi.c_strtoull(default))
         class ConstRefConverter(ConstRefNumericTypeConverterMixin, BasicConverter):
             _immutable_ = True
-            libffitype = libffi.types.pointer
+            libffitype = jit_libffi.types.pointer
         for name in names:
             _converters[name] = BasicConverter
             _converters["const "+name+"&"] = ConstRefConverter
@@ -715,11 +747,9 @@
 
     for tcode, tsize, names in array_info:
         class ArrayConverter(ArrayTypeConverterMixin, TypeConverter):
-            _immutable_ = True
             typecode = tcode
             typesize = tsize
         class PtrConverter(PtrTypeConverterMixin, TypeConverter):
-            _immutable_ = True
             typecode = tcode
             typesize = tsize
         for name in names:
@@ -744,4 +774,3 @@
     for c_type, alias in aliases:
         _converters[alias] = _converters[c_type]
 _add_aliased_converters()
-
diff --git a/pypy/module/cppyy/executor.py b/pypy/module/cppyy/executor.py
--- a/pypy/module/cppyy/executor.py
+++ b/pypy/module/cppyy/executor.py
@@ -3,7 +3,7 @@
 from pypy.interpreter.error import OperationError
 
 from pypy.rpython.lltypesystem import rffi, lltype
-from pypy.rlib import libffi, clibffi
+from pypy.rlib import jit_libffi
 
 from pypy.module._rawffi.interp_rawffi import unpack_simple_shape
 from pypy.module._rawffi.array import W_Array, W_ArrayInstance
@@ -24,10 +24,11 @@
 # exact match for the qualified type.
 
 
-NULL = lltype.nullptr(clibffi.FFI_TYPE_P.TO)
+NULL = lltype.nullptr(jit_libffi.FFI_TYPE_P.TO)
 
 class FunctionExecutor(object):
-    _immutable_ = True
+    _immutable_fields_ = ['libffitype']
+
     libffitype = NULL
 
     def __init__(self, space, extra):
@@ -37,13 +38,15 @@
         raise OperationError(space.w_TypeError,
                              space.wrap('return type not available or supported'))
 
-    def execute_libffi(self, space, libffifunc, argchain):
+    def execute_libffi(self, space, cif_descr, funcaddr, buffer):
         from pypy.module.cppyy.interp_cppyy import FastCallNotPossible
         raise FastCallNotPossible
 
 


More information about the pypy-commit mailing list