[pypy-commit] pypy py3k: hg merge default.

amauryfa noreply at buildbot.pypy.org
Wed May 30 23:11:12 CEST 2012


Author: Amaury Forgeot d'Arc <amauryfa at gmail.com>
Branch: py3k
Changeset: r55210:66685752ce86
Date: 2012-05-30 22:32 +0200
http://bitbucket.org/pypy/pypy/changeset/66685752ce86/

Log:	hg merge default. Note: the step-one-xrange optimization was not
	ported.

diff --git a/lib-python/2.7/test/test_fileio.py b/lib-python/2.7/test/test_fileio.py
--- a/lib-python/2.7/test/test_fileio.py
+++ b/lib-python/2.7/test/test_fileio.py
@@ -318,6 +318,7 @@
         self.assertRaises(ValueError, _FileIO, -10)
         self.assertRaises(OSError, _FileIO, make_bad_fd())
         if sys.platform == 'win32':
+            raise unittest.SkipTest('Set _invalid_parameter_handler for low level io')
             import msvcrt
             self.assertRaises(IOError, msvcrt.get_osfhandle, make_bad_fd())
 
diff --git a/lib-python/2.7/test/test_os.py b/lib-python/2.7/test/test_os.py
--- a/lib-python/2.7/test/test_os.py
+++ b/lib-python/2.7/test/test_os.py
@@ -690,7 +690,8 @@
     class PosixUidGidTests(unittest.TestCase):
         pass
 
- at unittest.skipUnless(sys.platform == "win32", "Win32 specific tests")
+ at unittest.skipUnless(sys.platform == "win32" and hasattr(os,'kill'),
+                         "Win32 specific tests")
 class Win32KillTests(unittest.TestCase):
     def _kill(self, sig):
         # Start sys.executable as a subprocess and communicate from the
diff --git a/pypy/annotation/bookkeeper.py b/pypy/annotation/bookkeeper.py
--- a/pypy/annotation/bookkeeper.py
+++ b/pypy/annotation/bookkeeper.py
@@ -531,8 +531,11 @@
                 try:
                     assert pyobj._freeze_()
                 except AttributeError:
-                    raise Exception("unexpected prebuilt constant: %r" % (
-                        pyobj,))
+                    if hasattr(pyobj, '__call__'):
+                        msg = "object with a __call__ is not RPython"
+                    else:
+                        msg = "unexpected prebuilt constant"
+                    raise Exception("%s: %r" % (msg, pyobj))
                 result = self.getfrozen(pyobj)
             self.descs[pyobj] = result
             return result
diff --git a/pypy/annotation/builtin.py b/pypy/annotation/builtin.py
--- a/pypy/annotation/builtin.py
+++ b/pypy/annotation/builtin.py
@@ -298,6 +298,9 @@
 def rarith_intmask(s_obj):
     return SomeInteger()
 
+def rarith_longlongmask(s_obj):
+    return SomeInteger(knowntype=pypy.rlib.rarithmetic.r_longlong)
+
 def robjmodel_instantiate(s_clspbc):
     assert isinstance(s_clspbc, SomePBC)
     clsdef = None
@@ -376,6 +379,7 @@
         BUILTIN_ANALYZERS[original] = value
 
 BUILTIN_ANALYZERS[pypy.rlib.rarithmetic.intmask] = rarith_intmask
+BUILTIN_ANALYZERS[pypy.rlib.rarithmetic.longlongmask] = rarith_longlongmask
 BUILTIN_ANALYZERS[pypy.rlib.objectmodel.instantiate] = robjmodel_instantiate
 BUILTIN_ANALYZERS[pypy.rlib.objectmodel.r_dict] = robjmodel_r_dict
 BUILTIN_ANALYZERS[pypy.rlib.objectmodel.hlinvoke] = robjmodel_hlinvoke
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
@@ -3756,6 +3756,29 @@
         s = a.build_types(main, [int])
         assert isinstance(s, annmodel.SomeInteger)
 
+    def test_join_none_and_nonnull(self):
+        from pypy.rlib.rstring import assert_str0
+        
+        def f(i):
+            a = str(i)
+            a = assert_str0(a)
+            return a.join([None])
+
+        a = self.RPythonAnnotator()
+        s = a.build_types(f, [int])
+        assert isinstance(s, annmodel.SomeString)
+        assert not s.can_be_None
+
+    def test_no___call__(self):
+        class X(object):
+            def __call__(self):
+                xxx
+        x = X()
+        def f():
+            return x
+        a = self.RPythonAnnotator()
+        e = py.test.raises(Exception, a.build_types, f, [])
+        assert 'object with a __call__ is not RPython' in str(e.value)
 
 def g(n):
     return [0,1,2,n]
diff --git a/pypy/annotation/unaryop.py b/pypy/annotation/unaryop.py
--- a/pypy/annotation/unaryop.py
+++ b/pypy/annotation/unaryop.py
@@ -494,7 +494,7 @@
             return SomeImpossibleValue()
         getbookkeeper().count("str_join", str)
         s_item = s_list.listdef.read_item()
-        if isinstance(s_item, SomeImpossibleValue):
+        if s_None.contains(s_item):
             if isinstance(str, SomeUnicodeString):
                 return immutablevalue(u"")
             return immutablevalue("")
diff --git a/pypy/doc/_ref.txt b/pypy/doc/_ref.txt
--- a/pypy/doc/_ref.txt
+++ b/pypy/doc/_ref.txt
@@ -84,7 +84,6 @@
 .. _`pypy/rlib/rbigint.py`: https://bitbucket.org/pypy/pypy/src/default/pypy/rlib/rbigint.py
 .. _`pypy/rlib/rrandom.py`: https://bitbucket.org/pypy/pypy/src/default/pypy/rlib/rrandom.py
 .. _`pypy/rlib/rsocket.py`: https://bitbucket.org/pypy/pypy/src/default/pypy/rlib/rsocket.py
-.. _`pypy/rlib/rstack.py`: https://bitbucket.org/pypy/pypy/src/default/pypy/rlib/rstack.py
 .. _`pypy/rlib/streamio.py`: https://bitbucket.org/pypy/pypy/src/default/pypy/rlib/streamio.py
 .. _`pypy/rlib/test`: https://bitbucket.org/pypy/pypy/src/default/pypy/rlib/test/
 .. _`pypy/rlib/unroll.py`: https://bitbucket.org/pypy/pypy/src/default/pypy/rlib/unroll.py
@@ -97,7 +96,6 @@
 .. _`pypy/rpython/memory/gc/hybrid.py`: https://bitbucket.org/pypy/pypy/src/default/pypy/rpython/memory/gc/hybrid.py
 .. _`pypy/rpython/memory/gc/markcompact.py`: https://bitbucket.org/pypy/pypy/src/default/pypy/rpython/memory/gc/markcompact.py
 .. _`pypy/rpython/memory/gc/marksweep.py`: https://bitbucket.org/pypy/pypy/src/default/pypy/rpython/memory/gc/marksweep.py
-.. _`pypy/rpython/memory/gc/minimark.py`: https://bitbucket.org/pypy/pypy/src/default/pypy/rpython/memory/gc/minimark.py
 .. _`pypy/rpython/memory/gc/minimarkpage.py`: https://bitbucket.org/pypy/pypy/src/default/pypy/rpython/memory/gc/minimarkpage.py
 .. _`pypy/rpython/memory/gc/semispace.py`: https://bitbucket.org/pypy/pypy/src/default/pypy/rpython/memory/gc/semispace.py
 .. _`pypy/rpython/ootypesystem/`: https://bitbucket.org/pypy/pypy/src/default/pypy/rpython/ootypesystem/
@@ -116,8 +114,8 @@
 .. _`pypy/translator/backendopt/`: https://bitbucket.org/pypy/pypy/src/default/pypy/translator/backendopt/
 .. _`pypy/translator/c/`: https://bitbucket.org/pypy/pypy/src/default/pypy/translator/c/
 .. _`pypy/translator/c/src/stacklet/`: https://bitbucket.org/pypy/pypy/src/default/pypy/translator/c/src/stacklet/
+.. _`pypy/translator/c/src/stacklet/stacklet.h`: https://bitbucket.org/pypy/pypy/src/default/pypy/translator/c/src/stacklet/stacklet.h
 .. _`pypy/translator/cli/`: https://bitbucket.org/pypy/pypy/src/default/pypy/translator/cli/
 .. _`pypy/translator/goal/`: https://bitbucket.org/pypy/pypy/src/default/pypy/translator/goal/
 .. _`pypy/translator/jvm/`: https://bitbucket.org/pypy/pypy/src/default/pypy/translator/jvm/
-.. _`pypy/translator/stackless/`: https://bitbucket.org/pypy/pypy/src/default/pypy/translator/stackless/
 .. _`pypy/translator/tool/`: https://bitbucket.org/pypy/pypy/src/default/pypy/translator/tool/
diff --git a/pypy/doc/getting-started-python.rst b/pypy/doc/getting-started-python.rst
--- a/pypy/doc/getting-started-python.rst
+++ b/pypy/doc/getting-started-python.rst
@@ -50,10 +50,10 @@
      libz-dev libbz2-dev libncurses-dev libexpat1-dev \
      libssl-dev libgc-dev python-sphinx python-greenlet
 
-   On a Fedora box these are::
+   On a Fedora-16 box these are::
 
      [user at fedora-or-rh-box ~]$ sudo yum install \
-     gcc make python-devel libffi-devel pkg-config \
+     gcc make python-devel libffi-devel pkgconfig \
      zlib-devel bzip2-devel ncurses-devel expat-devel \
      openssl-devel gc-devel python-sphinx python-greenlet
 
diff --git a/pypy/doc/test/test_whatsnew.py b/pypy/doc/test/test_whatsnew.py
new file mode 100644
--- /dev/null
+++ b/pypy/doc/test/test_whatsnew.py
@@ -0,0 +1,80 @@
+import py
+import pypy
+from commands import getoutput
+ROOT = py.path.local(pypy.__file__).dirpath().dirpath()
+
+
+def parse_doc(s):
+    startrev = None
+    branches = set()
+    def parseline(line):
+        _, value = line.split(':', 1)
+        return value.strip()
+    #
+    for line in s.splitlines():
+        if line.startswith('.. startrev:'):
+            startrev = parseline(line)
+        elif line.startswith('.. branch:'):
+            branches.add(parseline(line))
+    return startrev, branches
+
+def get_merged_branches(path, startrev, endrev):
+    # X = take all the merges which are descendants of startrev and are on default
+    # revset = all the parents of X which are not on default
+    # ===>
+    # revset contains all the branches which have been merged to default since
+    # startrev
+    revset = 'parents(%s::%s and \
+                      merge() and \
+                      branch(default)) and \
+              not branch(default)' % (startrev, endrev)
+    cmd = r"hg log -R '%s' -r '%s' --template '{branches}\n'" % (path, revset)
+    out = getoutput(cmd)
+    branches = set(map(str.strip, out.splitlines()))
+    return branches
+
+
+def test_parse_doc():
+    s = """
+=====
+Title
+=====
+
+.. startrev: 12345
+
+bla bla bla bla
+
+.. branch: foobar
+
+xxx yyy zzz
+
+.. branch: hello
+
+qqq www ttt
+"""
+    startrev, branches = parse_doc(s)
+    assert startrev == '12345'
+    assert branches == set(['foobar', 'hello'])
+
+def test_get_merged_branches():
+    branches = get_merged_branches(ROOT, 'f34f0c11299f', '79770e0c2f93')
+    assert branches == set(['numpy-indexing-by-arrays-bool',
+                            'better-jit-hooks-2',
+                            'numpypy-ufuncs'])
+
+def test_whatsnew():
+    doc = ROOT.join('pypy', 'doc')
+    whatsnew_list = doc.listdir('whatsnew-*.rst')
+    whatsnew_list.sort()
+    last_whatsnew = whatsnew_list[-1].read()
+    startrev, documented = parse_doc(last_whatsnew)
+    merged = get_merged_branches(ROOT, startrev, '')
+    not_documented = merged.difference(documented)
+    not_merged = documented.difference(merged)
+    print 'Branches merged but not documented:'
+    print '\n'.join(not_documented)
+    print
+    print 'Branches documented but not merged:'
+    print '\n'.join(not_merged)
+    print
+    assert not not_documented and not not_merged
diff --git a/pypy/doc/whatsnew-1.9.rst b/pypy/doc/whatsnew-1.9.rst
new file mode 100644
--- /dev/null
+++ b/pypy/doc/whatsnew-1.9.rst
@@ -0,0 +1,80 @@
+======================
+What's new in PyPy 1.9
+======================
+
+.. this is the revision just after the creation of the release-1.8.x branch
+.. startrev: a4261375b359
+
+.. branch: array_equal
+.. branch: better-jit-hooks-2
+.. branch: faster-heapcache
+.. branch: faster-str-decode-escape
+.. branch: float-bytes
+Added some primitives for dealing with floats as raw bytes.
+.. branch: float-bytes-2
+Added more float byte primitives.
+.. branch: jit-frame-counter
+Put more debug info into resops.
+.. branch: kill-geninterp
+.. branch: kqueue
+Finished select.kqueue.
+.. branch: kwargsdict-strategy
+.. branch: matrixmath-dot
+numpypy can now handle matrix multiplication.
+.. branch: merge-2.7.2
+The stdlib was updated to version 2.7.2
+.. branch: ndmin
+.. branch: newindex
+.. branch: non-null-threadstate
+cpyext: Better support for PyEval_SaveThread and other PyTreadState_*
+functions.
+.. branch: numppy-flatitter
+.. branch: numpy-back-to-applevel
+.. branch: numpy-concatenate
+.. branch: numpy-indexing-by-arrays-bool
+.. branch: numpy-record-dtypes
+.. branch: numpy-single-jitdriver
+.. branch: numpy-ufuncs2
+.. branch: numpy-ufuncs3
+.. branch: numpypy-issue1137
+.. branch: numpypy-out
+The "out" argument was added to most of the numypypy functions.
+.. branch: numpypy-shape-bug
+.. branch: numpypy-ufuncs
+.. branch: pytest
+.. branch: safe-getargs-freelist
+.. branch: set-strategies
+.. branch: speedup-list-comprehension
+.. branch: stdlib-unification
+The directory "lib-python/modified-2.7" has been removed, and its
+content merged into "lib-python/2.7".
+.. branch: step-one-xrange
+The common case of a xrange iterator with no step argument specifed
+was somewhat optimized. The tightest loop involving it,
+sum(xrange(n)), is now 18% faster on average.
+.. branch: string-NUL
+PyPy refuses filenames with chr(0) characters. This is implemented in
+RPython which can enforce no-NUL correctness and propagation, similar
+to const-correctness in C++.
+.. branch: win32-cleanup
+.. branch: win32-cleanup2
+.. branch: win32-cleanup_2
+Many bugs were corrected for windows 32 bit. New functionality was added to
+test validity of file descriptors, leading to the removal of the  global 
+_invalid_parameter_handler
+.. branch: win32-kill
+Add os.kill to windows even if translating python does not have os.kill
+.. branch: win64-stage1
+.. branch: zlib-mem-pressure
+
+.. branch: ffistruct
+The ``ffistruct`` branch adds a very low level way to express C structures
+with _ffi in a very JIT-friendly way
+
+
+
+.. "uninteresting" branches that we should just ignore for the whatsnew:
+.. branch: exception-cannot-occur
+.. branch: sanitize-finally-stack
+.. branch: revive-dlltool
+     (preliminary work for sepcomp)
diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py
--- a/pypy/interpreter/baseobjspace.py
+++ b/pypy/interpreter/baseobjspace.py
@@ -1440,7 +1440,7 @@
                                  self.wrap("expected a 32-bit integer"))
         return value
 
-    def truncatedint(self, w_obj):
+    def truncatedint_w(self, w_obj):
         # Like space.gateway_int_w(), but return the integer truncated
         # instead of raising OverflowError.  For obscure cases only.
         try:
@@ -1451,6 +1451,17 @@
             from pypy.rlib.rarithmetic import intmask
             return intmask(self.bigint_w(w_obj).uintmask())
 
+    def truncatedlonglong_w(self, w_obj):
+        # Like space.gateway_r_longlong_w(), but return the integer truncated
+        # instead of raising OverflowError.
+        try:
+            return self.r_longlong_w(w_obj)
+        except OperationError, e:
+            if not e.match(self, self.w_OverflowError):
+                raise
+            from pypy.rlib.rarithmetic import longlongmask
+            return longlongmask(self.bigint_w(w_obj).ulonglongmask())
+
     def c_filedescriptor_w(self, w_fd):
         # This is only used sometimes in CPython, e.g. for os.fsync() but
         # not os.close().  It's likely designed for 'select'.  It's irregular
diff --git a/pypy/interpreter/gateway.py b/pypy/interpreter/gateway.py
--- a/pypy/interpreter/gateway.py
+++ b/pypy/interpreter/gateway.py
@@ -145,7 +145,7 @@
     def visit_c_nonnegint(self, el, app_sig):
         self.checked_space_method(el, app_sig)
 
-    def visit_truncatedint(self, el, app_sig):
+    def visit_truncatedint_w(self, el, app_sig):
         self.checked_space_method(el, app_sig)
 
     def visit__Wrappable(self, el, app_sig):
@@ -268,8 +268,8 @@
     def visit_c_nonnegint(self, typ):
         self.run_args.append("space.c_nonnegint_w(%s)" % (self.scopenext(),))
 
-    def visit_truncatedint(self, typ):
-        self.run_args.append("space.truncatedint(%s)" % (self.scopenext(),))
+    def visit_truncatedint_w(self, typ):
+        self.run_args.append("space.truncatedint_w(%s)" % (self.scopenext(),))
 
     def _make_unwrap_activation_class(self, unwrap_spec, cache={}):
         try:
@@ -404,8 +404,8 @@
     def visit_c_nonnegint(self, typ):
         self.unwrap.append("space.c_nonnegint_w(%s)" % (self.nextarg(),))
 
-    def visit_truncatedint(self, typ):
-        self.unwrap.append("space.truncatedint(%s)" % (self.nextarg(),))
+    def visit_truncatedint_w(self, typ):
+        self.unwrap.append("space.truncatedint_w(%s)" % (self.nextarg(),))
 
     def make_fastfunc(unwrap_spec, func):
         unwrap_info = UnwrapSpec_FastFunc_Unwrap()
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
@@ -234,6 +234,37 @@
         w_obj = space.wrap(-12)
         space.raises_w(space.w_ValueError, space.r_ulonglong_w, w_obj)
 
+    def test_truncatedint_w(self):
+        space = self.space
+        assert space.truncatedint_w(space.wrap(42)) == 42
+        assert space.truncatedint_w(space.wrap(sys.maxint)) == sys.maxint
+        assert space.truncatedint_w(space.wrap(sys.maxint+1)) == -sys.maxint-1
+        assert space.truncatedint_w(space.wrap(-1)) == -1
+        assert space.truncatedint_w(space.wrap(-sys.maxint-2)) == sys.maxint
+
+    def test_truncatedlonglong_w(self):
+        space = self.space
+        w_value = space.wrap(12)
+        res = space.truncatedlonglong_w(w_value)
+        assert res == 12
+        assert type(res) is r_longlong
+        #
+        w_value = space.wrap(r_ulonglong(9223372036854775808))
+        res = space.truncatedlonglong_w(w_value)
+        assert res == -9223372036854775808
+        assert type(res) is r_longlong
+        #
+        w_value = space.wrap(r_ulonglong(18446744073709551615))
+        res = space.truncatedlonglong_w(w_value)
+        assert res == -1
+        assert type(res) is r_longlong
+        #
+        w_value = space.wrap(r_ulonglong(18446744073709551616))
+        res = space.truncatedlonglong_w(w_value)
+        assert res == 0
+        assert type(res) is r_longlong
+
+
     def test_call_obj_args(self):
         from pypy.interpreter.argument import Arguments
         
diff --git a/pypy/jit/backend/llgraph/llimpl.py b/pypy/jit/backend/llgraph/llimpl.py
--- a/pypy/jit/backend/llgraph/llimpl.py
+++ b/pypy/jit/backend/llgraph/llimpl.py
@@ -823,7 +823,9 @@
     op_getfield_gc_pure = op_getfield_gc
 
     def op_getfield_raw(self, fielddescr, struct):
-        if fielddescr.typeinfo == REF:
+        if fielddescr.arg_types == 'dynamic': # abuse of .arg_types
+            return do_getfield_raw_dynamic(struct, fielddescr)
+        elif fielddescr.typeinfo == REF:
             return do_getfield_raw_ptr(struct, fielddescr.ofs)
         elif fielddescr.typeinfo == INT:
             return do_getfield_raw_int(struct, fielddescr.ofs)
@@ -919,7 +921,9 @@
             raise NotImplementedError
 
     def op_setfield_raw(self, fielddescr, struct, newvalue):
-        if fielddescr.typeinfo == REF:
+        if fielddescr.arg_types == 'dynamic': # abuse of .arg_types
+            do_setfield_raw_dynamic(struct, fielddescr, newvalue)
+        elif fielddescr.typeinfo == REF:
             do_setfield_raw_ptr(struct, fielddescr.ofs, newvalue)
         elif fielddescr.typeinfo == INT:
             do_setfield_raw_int(struct, fielddescr.ofs, newvalue)
@@ -1500,6 +1504,17 @@
 def do_getfield_raw_ptr(struct, fieldnum):
     return cast_to_ptr(_getfield_raw(struct, fieldnum))
 
+def do_getfield_raw_dynamic(struct, fielddescr):
+    from pypy.rlib import libffi
+    addr = cast_from_int(rffi.VOIDP, struct)
+    ofs = fielddescr.ofs
+    if fielddescr.is_pointer_field():
+        assert False, 'fixme'
+    elif fielddescr.is_float_field():
+        assert False, 'fixme'
+    else:
+        return libffi._struct_getfield(lltype.Signed, addr, ofs)
+
 def do_new(size):
     TYPE = symbolic.Size2Type[size]
     x = lltype.malloc(TYPE, zero=True)
@@ -1597,6 +1612,17 @@
     newvalue = cast_from_ptr(FIELDTYPE, newvalue)
     setattr(ptr, fieldname, newvalue)
 
+def do_setfield_raw_dynamic(struct, fielddescr, newvalue):
+    from pypy.rlib import libffi
+    addr = cast_from_int(rffi.VOIDP, struct)
+    ofs = fielddescr.ofs
+    if fielddescr.is_pointer_field():
+        assert False, 'fixme'
+    elif fielddescr.is_float_field():
+        assert False, 'fixme'
+    else:
+        libffi._struct_setfield(lltype.Signed, addr, ofs, newvalue)
+
 def do_newstr(length):
     x = rstr.mallocstr(length)
     return cast_to_ptr(x)
diff --git a/pypy/jit/backend/llgraph/runner.py b/pypy/jit/backend/llgraph/runner.py
--- a/pypy/jit/backend/llgraph/runner.py
+++ b/pypy/jit/backend/llgraph/runner.py
@@ -334,6 +334,16 @@
         token = history.getkind(getattr(S, fieldname))
         return self.getdescr(ofs, token[0], name=fieldname)
 
+    def fielddescrof_dynamic(self, offset, fieldsize, is_pointer, is_float, is_signed):
+        if is_pointer:
+            typeinfo = REF
+        elif is_float:
+            typeinfo = FLOAT
+        else:
+            typeinfo = INT
+        # we abuse the arg_types field to distinguish dynamic and static descrs
+        return self.getdescr(offset, typeinfo, arg_types='dynamic', name='<dynamic field>')
+
     def interiorfielddescrof(self, A, fieldname):
         S = A.OF
         width = symbolic.get_size(A)
diff --git a/pypy/jit/backend/llsupport/descr.py b/pypy/jit/backend/llsupport/descr.py
--- a/pypy/jit/backend/llsupport/descr.py
+++ b/pypy/jit/backend/llsupport/descr.py
@@ -237,18 +237,25 @@
         cache[(ARRAY, name)] = descr
         return descr
 
+def compute_flag(is_pointer, is_float, is_signed):
+    if is_pointer:
+        assert not is_float
+        return FLAG_POINTER
+    elif is_float:
+        return FLAG_FLOAT
+    elif is_signed:
+        return FLAG_SIGNED
+    else:
+        return FLAG_UNSIGNED
+
+def get_dynamic_field_descr(offset, fieldsize, is_pointer, is_float, is_signed):
+    flag = compute_flag(is_pointer, is_float, is_signed)
+    return FieldDescr('dynamic', offset, fieldsize, flag)
+
 def get_dynamic_interiorfield_descr(gc_ll_descr, offset, width, fieldsize,
                                     is_pointer, is_float, is_signed):
     arraydescr = ArrayDescr(0, width, None, FLAG_STRUCT)
-    if is_pointer:
-        assert not is_float
-        flag = FLAG_POINTER
-    elif is_float:
-        flag = FLAG_FLOAT
-    elif is_signed:
-        flag = FLAG_SIGNED
-    else:
-        flag = FLAG_UNSIGNED
+    flag = compute_flag(is_pointer, is_float, is_signed)
     fielddescr = FieldDescr('dynamic', offset, fieldsize, flag)
     return InteriorFieldDescr(arraydescr, fielddescr)
 
diff --git a/pypy/jit/backend/llsupport/llmodel.py b/pypy/jit/backend/llsupport/llmodel.py
--- a/pypy/jit/backend/llsupport/llmodel.py
+++ b/pypy/jit/backend/llsupport/llmodel.py
@@ -11,7 +11,7 @@
 from pypy.jit.backend.llsupport.descr import (
     get_size_descr, get_field_descr, get_array_descr,
     get_call_descr, get_interiorfield_descr, get_dynamic_interiorfield_descr,
-    FieldDescr, ArrayDescr, CallDescr, InteriorFieldDescr)
+    FieldDescr, ArrayDescr, CallDescr, InteriorFieldDescr, get_dynamic_field_descr)
 from pypy.jit.backend.llsupport.asmmemmgr import AsmMemoryManager
 
 
@@ -245,6 +245,9 @@
     def fielddescrof(self, STRUCT, fieldname):
         return get_field_descr(self.gc_ll_descr, STRUCT, fieldname)
 
+    def fielddescrof_dynamic(self, offset, fieldsize, is_pointer, is_float, is_signed):
+        return get_dynamic_field_descr(offset, fieldsize, is_pointer, is_float, is_signed)
+
     def unpack_fielddescr(self, fielddescr):
         assert isinstance(fielddescr, FieldDescr)
         return fielddescr.offset
diff --git a/pypy/jit/backend/test/runner_test.py b/pypy/jit/backend/test/runner_test.py
--- a/pypy/jit/backend/test/runner_test.py
+++ b/pypy/jit/backend/test/runner_test.py
@@ -1660,20 +1660,37 @@
         assert s.x == chr(190)
         assert s.y == chr(150)
 
-    def test_field_raw_pure(self):
-        # This is really testing the same thing as test_field_basic but can't
-        # hurt...
-        S = lltype.Struct('S', ('x', lltype.Signed))
+    def test_fielddescrof_dynamic(self):
+        S = lltype.Struct('S',
+                          ('x', lltype.Signed),
+                          ('y', lltype.Signed),
+                          )
+        longsize = rffi.sizeof(lltype.Signed)
+        y_ofs = longsize
         s = lltype.malloc(S, flavor='raw')
         sa = llmemory.cast_ptr_to_adr(s)
         s_box = BoxInt(heaptracker.adr2int(sa))
+        #
+        field = self.cpu.fielddescrof(S, 'y')
+        field_dyn = self.cpu.fielddescrof_dynamic(offset=y_ofs,
+                                                  fieldsize=longsize,
+                                                  is_pointer=False,
+                                                  is_float=False,
+                                                  is_signed=True)
+        assert field.is_pointer_field() == field_dyn.is_pointer_field()
+        assert field.is_float_field()   == field_dyn.is_float_field()
+        if 'llgraph' not in str(self.cpu):
+            assert field.is_field_signed()  == field_dyn.is_field_signed()
+
+        #
         for get_op, set_op in ((rop.GETFIELD_RAW, rop.SETFIELD_RAW),
                                (rop.GETFIELD_RAW_PURE, rop.SETFIELD_RAW)):
-            fd = self.cpu.fielddescrof(S, 'x')
-            self.execute_operation(set_op, [s_box, BoxInt(32)], 'void',
-                                   descr=fd)
-            res = self.execute_operation(get_op, [s_box], 'int', descr=fd)
-            assert res.getint()  == 32
+            for descr in (field, field_dyn):
+                self.execute_operation(set_op, [s_box, BoxInt(32)], 'void',
+                                       descr=descr)
+                res = self.execute_operation(get_op, [s_box], 'int', descr=descr)
+                assert res.getint()  == 32
+
         lltype.free(s, flavor='raw')
 
     def test_new_with_vtable(self):
diff --git a/pypy/jit/codewriter/effectinfo.py b/pypy/jit/codewriter/effectinfo.py
--- a/pypy/jit/codewriter/effectinfo.py
+++ b/pypy/jit/codewriter/effectinfo.py
@@ -48,8 +48,10 @@
     OS_LIBFFI_PREPARE           = 60
     OS_LIBFFI_PUSH_ARG          = 61
     OS_LIBFFI_CALL              = 62
-    OS_LIBFFI_GETARRAYITEM      = 63
-    OS_LIBFFI_SETARRAYITEM      = 64
+    OS_LIBFFI_STRUCT_GETFIELD   = 63
+    OS_LIBFFI_STRUCT_SETFIELD   = 64
+    OS_LIBFFI_GETARRAYITEM      = 65
+    OS_LIBFFI_SETARRAYITEM      = 66
     #
     OS_LLONG_INVERT             = 69
     OS_LLONG_ADD                = 70
diff --git a/pypy/jit/codewriter/jtransform.py b/pypy/jit/codewriter/jtransform.py
--- a/pypy/jit/codewriter/jtransform.py
+++ b/pypy/jit/codewriter/jtransform.py
@@ -1675,6 +1675,12 @@
         elif oopspec_name.startswith('libffi_call_'):
             oopspecindex = EffectInfo.OS_LIBFFI_CALL
             extraeffect = EffectInfo.EF_RANDOM_EFFECTS
+        elif oopspec_name == 'libffi_struct_getfield':
+            oopspecindex = EffectInfo.OS_LIBFFI_STRUCT_GETFIELD
+            extraeffect = EffectInfo.EF_CANNOT_RAISE
+        elif oopspec_name == 'libffi_struct_setfield':
+            oopspecindex = EffectInfo.OS_LIBFFI_STRUCT_SETFIELD
+            extraeffect = EffectInfo.EF_CANNOT_RAISE
         elif oopspec_name == 'libffi_array_getitem':
             oopspecindex = EffectInfo.OS_LIBFFI_GETARRAYITEM
             extraeffect = EffectInfo.EF_CANNOT_RAISE
diff --git a/pypy/jit/codewriter/support.py b/pypy/jit/codewriter/support.py
--- a/pypy/jit/codewriter/support.py
+++ b/pypy/jit/codewriter/support.py
@@ -456,7 +456,6 @@
 def _ll_3_libffi_call_void(llfunc, funcsym, ll_args):
     return func(llfunc)._do_call(funcsym, ll_args, lltype.Void)
 
-
 # in the following calls to builtins, the JIT is allowed to look inside:
 inline_calls_to = [
     ('int_floordiv_ovf_zer', [lltype.Signed, lltype.Signed], lltype.Signed),
diff --git a/pypy/jit/metainterp/optimizeopt/fficall.py b/pypy/jit/metainterp/optimizeopt/fficall.py
--- a/pypy/jit/metainterp/optimizeopt/fficall.py
+++ b/pypy/jit/metainterp/optimizeopt/fficall.py
@@ -7,7 +7,9 @@
 from pypy.rlib.libffi import Func
 from pypy.rlib.objectmodel import we_are_translated
 from pypy.rpython.annlowlevel import cast_base_ptr_to_instance
-from pypy.rpython.lltypesystem import llmemory, rffi
+from pypy.rpython.lltypesystem import lltype, llmemory, rffi
+from pypy.rlib.objectmodel import we_are_translated
+from pypy.rlib.rarithmetic import intmask
 
 
 class FuncInfo(object):
@@ -118,6 +120,9 @@
             ops = self.do_push_arg(op)
         elif oopspec == EffectInfo.OS_LIBFFI_CALL:
             ops = self.do_call(op)
+        elif (oopspec == EffectInfo.OS_LIBFFI_STRUCT_GETFIELD or
+              oopspec == EffectInfo.OS_LIBFFI_STRUCT_SETFIELD):
+            ops = self.do_struct_getsetfield(op, oopspec)
         elif (oopspec == EffectInfo.OS_LIBFFI_GETARRAYITEM or
             oopspec == EffectInfo.OS_LIBFFI_SETARRAYITEM):
             ops = self.do_getsetarrayitem(op, oopspec)
@@ -195,6 +200,46 @@
         ops.append(newop)
         return ops
 
+    def do_struct_getsetfield(self, op, oopspec):
+        ffitypeval = self.getvalue(op.getarg(1))
+        addrval = self.getvalue(op.getarg(2))
+        offsetval = self.getvalue(op.getarg(3))
+        if not ffitypeval.is_constant() or not offsetval.is_constant():
+            return [op]
+        #
+        ffitypeaddr = ffitypeval.box.getaddr()
+        ffitype = llmemory.cast_adr_to_ptr(ffitypeaddr, clibffi.FFI_TYPE_P)
+        offset = offsetval.box.getint()
+        descr = self._get_field_descr(ffitype, offset)
+        #
+        arglist = [addrval.force_box(self.optimizer)]
+        if oopspec == EffectInfo.OS_LIBFFI_STRUCT_GETFIELD:
+            opnum = rop.GETFIELD_RAW
+        else:
+            opnum = rop.SETFIELD_RAW
+            newval = self.getvalue(op.getarg(4))
+            arglist.append(newval.force_box(self.optimizer))
+        #
+        newop = ResOperation(opnum, arglist, op.result, descr=descr)
+        return [newop]
+
+    def _get_field_descr(self, ffitype, offset):
+        kind = libffi.types.getkind(ffitype)
+        is_pointer = is_float = is_signed = False
+        if ffitype is libffi.types.pointer:
+            is_pointer = True
+        elif kind == 'i':
+            is_signed = True
+        elif kind == 'f' or kind == 'I' or kind == 'U':
+            # longlongs are treated as floats, see e.g. llsupport/descr.py:getDescrClass
+            is_float = True
+        else:
+            assert False, "unsupported ffitype or kind"
+        #
+        fieldsize = intmask(ffitype.c_size)
+        return self.optimizer.cpu.fielddescrof_dynamic(offset, fieldsize,
+                                                       is_pointer, is_float, is_signed)
+    
     def do_getsetarrayitem(self, op, oopspec):
         ffitypeval = self.getvalue(op.getarg(1))
         widthval = self.getvalue(op.getarg(2))
@@ -245,6 +290,7 @@
             offset, width, fieldsize, is_pointer, is_float, is_signed
         )
 
+
     def propagate_forward(self, op):
         if self.logops is not None:
             debug_print(self.logops.repr_of_resop(op))
diff --git a/pypy/jit/metainterp/optimizeopt/test/test_optimizebasic.py b/pypy/jit/metainterp/optimizeopt/test/test_optimizebasic.py
--- a/pypy/jit/metainterp/optimizeopt/test/test_optimizebasic.py
+++ b/pypy/jit/metainterp/optimizeopt/test/test_optimizebasic.py
@@ -5068,6 +5068,7 @@
         self.optimize_strunicode_loop(ops, expected)
 
     def test_call_pure_vstring_const(self):
+        py.test.skip("implement me")
         ops = """
         []
         p0 = newstr(3)
diff --git a/pypy/jit/metainterp/optimizeopt/test/test_optimizefficall.py b/pypy/jit/metainterp/optimizeopt/test/test_optimizefficall.py
--- a/pypy/jit/metainterp/optimizeopt/test/test_optimizefficall.py
+++ b/pypy/jit/metainterp/optimizeopt/test/test_optimizefficall.py
@@ -56,6 +56,13 @@
                              restype=types.sint,
                              flags=43)
         #
+        ffi_slong = types.slong
+        dyn_123_field = cpu.fielddescrof_dynamic(offset=123,
+                                                 fieldsize=types.slong.c_size,
+                                                 is_pointer=False,
+                                                 is_float=False,
+                                                 is_signed=True)
+        #
         def calldescr(cpu, FUNC, oopspecindex, extraeffect=None):
             if extraeffect == EffectInfo.EF_RANDOM_EFFECTS:
                 f = None   # means "can force all" really
@@ -69,6 +76,8 @@
         libffi_push_arg = calldescr(cpu, FUNC, EffectInfo.OS_LIBFFI_PUSH_ARG)
         libffi_call =     calldescr(cpu, FUNC, EffectInfo.OS_LIBFFI_CALL,
                                     EffectInfo.EF_RANDOM_EFFECTS)
+        libffi_struct_getfield = calldescr(cpu, FUNC, EffectInfo.OS_LIBFFI_STRUCT_GETFIELD)
+        libffi_struct_setfield = calldescr(cpu, FUNC, EffectInfo.OS_LIBFFI_STRUCT_SETFIELD)
     
     namespace = namespace.__dict__
 
@@ -277,3 +286,30 @@
         jump(i3, f1, p2)
         """
         loop = self.optimize_loop(ops, expected)
+
+    def test_ffi_struct_fields(self):
+        ops = """
+        [i0]
+        i1 = call(0, ConstClass(ffi_slong), i0, 123, descr=libffi_struct_getfield)
+        i2 = int_add(i1, 1)
+        call(0, ConstClass(ffi_slong), i0, 123, i2, descr=libffi_struct_setfield)
+        jump(i1)
+        """
+        expected = """
+        [i0]
+        i1 = getfield_raw(i0, descr=dyn_123_field)
+        i2 = int_add(i1, 1)
+        setfield_raw(i0, i2, descr=dyn_123_field)
+        jump(i1)
+        """
+        loop = self.optimize_loop(ops, expected)
+
+    def test_ffi_struct_fields_nonconst(self):
+        ops = """
+        [i0, i1]
+        i2 = call(0, ConstClass(ffi_slong), i0, i1,  descr=libffi_struct_getfield)
+        i3 = call(0, i1                   , i0, 123, descr=libffi_struct_getfield)
+        jump(i1)
+        """
+        expected = ops
+        loop = self.optimize_loop(ops, expected)
diff --git a/pypy/jit/metainterp/test/test_fficall.py b/pypy/jit/metainterp/test/test_fficall.py
--- a/pypy/jit/metainterp/test/test_fficall.py
+++ b/pypy/jit/metainterp/test/test_fficall.py
@@ -4,7 +4,7 @@
 from pypy.jit.metainterp.test.support import LLJitMixin
 from pypy.rlib.jit import JitDriver, promote, dont_look_inside
 from pypy.rlib.libffi import (ArgChain, IS_32_BIT, array_getitem, array_setitem,
-    types)
+    types, struct_setfield_int, struct_getfield_int)
 from pypy.rlib.objectmodel import specialize
 from pypy.rlib.rarithmetic import r_singlefloat, r_longlong, r_ulonglong
 from pypy.rlib.test.test_libffi import TestLibffiCall as _TestLibffiCall
@@ -187,5 +187,24 @@
 class TestFfiCallSupportAll(FfiCallTests, LLJitMixin):
     supports_all = True     # supports_{floats,longlong,singlefloats}
 
+    def test_struct_getfield(self):
+        myjitdriver = JitDriver(greens = [], reds = ['n', 'i', 'addr'])
+
+        def f(n):
+            i = 0
+            addr = lltype.malloc(rffi.VOIDP.TO, 10, flavor='raw')
+            while i < n:
+                myjitdriver.jit_merge_point(n=n, i=i, addr=addr)
+                struct_setfield_int(types.slong, addr, 0, 1)
+                i += struct_getfield_int(types.slong, addr, 0)
+            lltype.free(addr, flavor='raw')
+            return i
+        assert self.meta_interp(f, [20]) == f(20)
+        self.check_resops(
+            setfield_raw=2,
+            getfield_raw=2,
+            call=0)
+
+
 class TestFfiLookup(FfiLookupTests, LLJitMixin):
     pass
diff --git a/pypy/module/__builtin__/test/test_functional.py b/pypy/module/__builtin__/test/test_functional.py
--- a/pypy/module/__builtin__/test/test_functional.py
+++ b/pypy/module/__builtin__/test/test_functional.py
@@ -146,6 +146,25 @@
       y = callable(*args)
       assert list(y) == list(x)
 
+   def test_xrange_iter_reduce(self):
+      x = iter(xrange(2, 9, 3))
+      x.next()
+      callable, args = x.__reduce__()
+      y = callable(*args)
+      assert list(y) == list(x)
+
+   def test_xrange_iter_reduce_one(self):
+      x = iter(xrange(2, 9))
+      x.next()
+      callable, args = x.__reduce__()
+      y = callable(*args)
+      assert list(y) == list(x)
+
+   def test_lib_python_xrange_optimization(self):
+      x = xrange(1)
+      assert type(reversed(x)) == type(iter(x))
+
+
 class AppTestReversed:
    def test_reversed(self):
       r = reversed("hello")
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
@@ -3,7 +3,6 @@
 from pypy.interpreter.mixedmodule import MixedModule
 from pypy.module.imp.importing import get_pyc_magic
 
-
 class BuildersModule(MixedModule):
     appleveldefs = {}
 
@@ -43,6 +42,7 @@
         'lookup_special'            : 'interp_magic.lookup_special',
         'do_what_I_mean'            : 'interp_magic.do_what_I_mean',
         'list_strategy'             : 'interp_magic.list_strategy',
+        'validate_fd'               : 'interp_magic.validate_fd',
     }
 
     submodules = {
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
@@ -1,9 +1,10 @@
 from pypy.interpreter.baseobjspace import ObjSpace, W_Root
-from pypy.interpreter.error import OperationError
+from pypy.interpreter.error import OperationError, wrap_oserror
 from pypy.interpreter.gateway import unwrap_spec
 from pypy.rlib.objectmodel import we_are_translated
 from pypy.objspace.std.typeobject import MethodCache
 from pypy.objspace.std.mapdict import IndexCache
+from pypy.rlib import rposix
 
 def internal_repr(space, w_object):
     return space.wrap('%r' % (w_object,))
@@ -77,3 +78,10 @@
     else:
         w_msg = space.wrap("Can only get the list strategy of a list")
         raise OperationError(space.w_TypeError, w_msg)
+
+ at unwrap_spec(fd='c_int')
+def validate_fd(space, fd):
+    try:
+        rposix.validate_fd(fd)
+    except OSError, e:
+        raise wrap_oserror(space, e)
diff --git a/pypy/module/_ffi/__init__.py b/pypy/module/_ffi/__init__.py
--- a/pypy/module/_ffi/__init__.py
+++ b/pypy/module/_ffi/__init__.py
@@ -1,13 +1,16 @@
 from pypy.interpreter.mixedmodule import MixedModule
-from pypy.module._ffi import interp_ffi
 
 class Module(MixedModule):
 
     interpleveldefs = {
-        'CDLL':    'interp_ffi.W_CDLL',
-        'types':   'interp_ffi.W_types',
-        'FuncPtr': 'interp_ffi.W_FuncPtr',
-        'get_libc':'interp_ffi.get_libc',
+        'types':   'interp_ffitype.W_types',
+        'CDLL':    'interp_funcptr.W_CDLL',
+        'FuncPtr': 'interp_funcptr.W_FuncPtr',
+        'get_libc':'interp_funcptr.get_libc',
+        '_StructDescr': 'interp_struct.W__StructDescr',
+        'Field':     'interp_struct.W_Field',
     }
 
-    appleveldefs = {}
+    appleveldefs = {
+        'Structure': 'app_struct.Structure',
+        }
diff --git a/pypy/module/_ffi/app_struct.py b/pypy/module/_ffi/app_struct.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/_ffi/app_struct.py
@@ -0,0 +1,21 @@
+import _ffi
+
+class MetaStructure(type):
+
+    def __new__(cls, name, bases, dic):
+        cls._compute_shape(name, dic)
+        return type.__new__(cls, name, bases, dic)
+
+    @classmethod
+    def _compute_shape(cls, name, dic):
+        fields = dic.get('_fields_')
+        if fields is None:
+            return
+        struct_descr = _ffi._StructDescr(name, fields)
+        for field in fields:
+            dic[field.name] = field
+        dic['_struct_'] = struct_descr
+
+
+class Structure(object):
+    __metaclass__ = MetaStructure
diff --git a/pypy/module/_ffi/interp_ffi.py b/pypy/module/_ffi/interp_ffi.py
deleted file mode 100644
--- a/pypy/module/_ffi/interp_ffi.py
+++ /dev/null
@@ -1,514 +0,0 @@
-from pypy.interpreter.baseobjspace import Wrappable
-from pypy.interpreter.error import OperationError, wrap_oserror, \
-    operationerrfmt
-from pypy.interpreter.gateway import interp2app, unwrap_spec
-from pypy.interpreter.typedef import TypeDef
-from pypy.module._rawffi.structure import W_StructureInstance, W_Structure
-#
-from pypy.rpython.lltypesystem import lltype, rffi
-#
-from pypy.rlib import jit
-from pypy.rlib import libffi
-from pypy.rlib.rdynload import DLOpenError
-from pypy.rlib.rarithmetic import intmask, r_uint
-from pypy.rlib.objectmodel import we_are_translated
-
-class W_FFIType(Wrappable):
-
-    _immutable_fields_ = ['name', 'ffitype', 'w_datashape', 'w_pointer_to']
-
-    def __init__(self, name, ffitype, w_datashape=None, w_pointer_to=None):
-        self.name = name
-        self.ffitype = ffitype
-        self.w_datashape = w_datashape
-        self.w_pointer_to = w_pointer_to
-        if self.is_struct():
-            assert w_datashape is not None
-
-    def descr_deref_pointer(self, space):
-        if self.w_pointer_to is None:
-            return space.w_None
-        return self.w_pointer_to
-
-    def repr(self, space):
-        return space.wrap(self.__repr__())
-
-    def __repr__(self):
-        return "<ffi type %s>" % self.name
-
-    def is_signed(self):
-        return (self is app_types.slong or
-                self is app_types.sint or
-                self is app_types.sshort or
-                self is app_types.sbyte or
-                self is app_types.slonglong)
-
-    def is_unsigned(self):
-        return (self is app_types.ulong or
-                self is app_types.uint or
-                self is app_types.ushort or
-                self is app_types.ubyte or
-                self is app_types.ulonglong)
-
-    def is_pointer(self):
-        return self.ffitype is libffi.types.pointer
-
-    def is_char(self):
-        return self is app_types.char
-
-    def is_unichar(self):
-        return self is app_types.unichar
-
-    def is_longlong(self):
-        return libffi.IS_32_BIT and (self is app_types.slonglong or
-                                     self is app_types.ulonglong)
-
-    def is_double(self):
-        return self is app_types.double
-
-    def is_singlefloat(self):
-        return self is app_types.float
-
-    def is_void(self):
-        return self is app_types.void
-
-    def is_struct(self):
-        return libffi.types.is_struct(self.ffitype)
-
-    def is_char_p(self):
-        return self is app_types.char_p
-
-    def is_unichar_p(self):
-        return self is app_types.unichar_p
-
-
-W_FFIType.typedef = TypeDef(
-    'FFIType',
-    __repr__ = interp2app(W_FFIType.repr),
-    deref_pointer = interp2app(W_FFIType.descr_deref_pointer),
-    )
-
-
-def build_ffi_types():
-    types = [
-        # note: most of the type name directly come from the C equivalent,
-        # with the exception of bytes: in C, ubyte and char are equivalent,
-        # but for _ffi the first expects a number while the second a 1-length
-        # string
-        W_FFIType('slong',     libffi.types.slong),
-        W_FFIType('sint',      libffi.types.sint),
-        W_FFIType('sshort',    libffi.types.sshort),
-        W_FFIType('sbyte',     libffi.types.schar),
-        W_FFIType('slonglong', libffi.types.slonglong),
-        #
-        W_FFIType('ulong',     libffi.types.ulong),
-        W_FFIType('uint',      libffi.types.uint),
-        W_FFIType('ushort',    libffi.types.ushort),
-        W_FFIType('ubyte',     libffi.types.uchar),
-        W_FFIType('ulonglong', libffi.types.ulonglong),
-        #
-        W_FFIType('char',      libffi.types.uchar),
-        W_FFIType('unichar',   libffi.types.wchar_t),
-        #
-        W_FFIType('double',    libffi.types.double),
-        W_FFIType('float',     libffi.types.float),
-        W_FFIType('void',      libffi.types.void),
-        W_FFIType('void_p',    libffi.types.pointer),
-        #
-        # missing types:
-
-        ## 's' : ffi_type_pointer,
-        ## 'z' : ffi_type_pointer,
-        ## 'O' : ffi_type_pointer,
-        ## 'Z' : ffi_type_pointer,
-
-        ]
-    d = dict([(t.name, t) for t in types])
-    w_char = d['char']
-    w_unichar = d['unichar']
-    d['char_p'] = W_FFIType('char_p', libffi.types.pointer, w_pointer_to = w_char)
-    d['unichar_p'] = W_FFIType('unichar_p', libffi.types.pointer, w_pointer_to = w_unichar)
-    return d
-
-class app_types:
-    pass
-app_types.__dict__ = build_ffi_types()
-
-def descr_new_pointer(space, w_cls, w_pointer_to):
-    try:
-        return descr_new_pointer.cache[w_pointer_to]
-    except KeyError:
-        if w_pointer_to is app_types.char:
-            w_result = app_types.char_p
-        elif w_pointer_to is app_types.unichar:
-            w_result = app_types.unichar_p
-        else:
-            w_pointer_to = space.interp_w(W_FFIType, w_pointer_to)
-            name = '(pointer to %s)' % w_pointer_to.name
-            w_result = W_FFIType(name, libffi.types.pointer, w_pointer_to = w_pointer_to)
-        descr_new_pointer.cache[w_pointer_to] = w_result
-        return w_result
-descr_new_pointer.cache = {}
-
-class W_types(Wrappable):
-    pass
-W_types.typedef = TypeDef(
-    'types',
-    Pointer = interp2app(descr_new_pointer, as_classmethod=True),
-    **app_types.__dict__)
-
-
-def unwrap_ffitype(space, w_argtype, allow_void=False):
-    res = w_argtype.ffitype
-    if res is libffi.types.void and not allow_void:
-        msg = 'void is not a valid argument type'
-        raise OperationError(space.w_TypeError, space.wrap(msg))
-    return res
-
-def unwrap_truncate_int(TP, space, w_arg):
-    if space.is_true(space.isinstance(w_arg, space.w_int)):
-        return rffi.cast(TP, space.int_w(w_arg))
-    else:
-        return rffi.cast(TP, space.bigint_w(w_arg).ulonglongmask())
-unwrap_truncate_int._annspecialcase_ = 'specialize:arg(0)'
-
-# ========================================================================
-
-class W_FuncPtr(Wrappable):
-
-    _immutable_fields_ = ['func', 'argtypes_w[*]', 'w_restype']
-
-    def __init__(self, func, argtypes_w, w_restype):
-        self.func = func
-        self.argtypes_w = argtypes_w
-        self.w_restype = w_restype
-        self.to_free = []
-
-    @jit.unroll_safe
-    def build_argchain(self, space, args_w):
-        expected = len(self.argtypes_w)
-        given = len(args_w)
-        if given != expected:
-            arg = 'arguments'
-            if len(self.argtypes_w) == 1:
-                arg = 'argument'
-            raise operationerrfmt(space.w_TypeError,
-                                  '%s() takes exactly %d %s (%d given)',
-                                  self.func.name, expected, arg, given)
-        #
-        argchain = libffi.ArgChain()
-        for i in range(expected):
-            w_argtype = self.argtypes_w[i]
-            w_arg = args_w[i]
-            if w_argtype.is_longlong():
-                # note that we must check for longlong first, because either
-                # is_signed or is_unsigned returns true anyway
-                assert libffi.IS_32_BIT
-                self.arg_longlong(space, argchain, w_arg)
-            elif w_argtype.is_signed():
-                argchain.arg(unwrap_truncate_int(rffi.LONG, space, w_arg))
-            elif self.add_char_p_maybe(space, argchain, w_arg, w_argtype):
-                # the argument is added to the argchain direcly by the method above
-                pass
-            elif w_argtype.is_pointer():
-                w_arg = self.convert_pointer_arg_maybe(space, w_arg, w_argtype)
-                argchain.arg(intmask(space.uint_w(w_arg)))
-            elif w_argtype.is_unsigned():
-                argchain.arg(unwrap_truncate_int(rffi.ULONG, space, w_arg))
-            elif w_argtype.is_char():
-                w_arg = space.ord(w_arg)
-                argchain.arg(space.int_w(w_arg))
-            elif w_argtype.is_unichar():
-                w_arg = space.ord(w_arg)
-                argchain.arg(space.int_w(w_arg))
-            elif w_argtype.is_double():
-                self.arg_float(space, argchain, w_arg)
-            elif w_argtype.is_singlefloat():
-                self.arg_singlefloat(space, argchain, w_arg)
-            elif w_argtype.is_struct():
-                # arg_raw directly takes value to put inside ll_args
-                w_arg = space.interp_w(W_StructureInstance, w_arg)
-                ptrval = w_arg.ll_buffer
-                argchain.arg_raw(ptrval)
-            else:
-                assert False, "Argument shape '%s' not supported" % w_argtype
-        return argchain
-
-    def add_char_p_maybe(self, space, argchain, w_arg, w_argtype):
-        """
-        Automatic conversion from string to char_p. The allocated buffer will
-        be automatically freed after the call.
-        """
-        w_type = jit.promote(space.type(w_arg))
-        if w_argtype.is_char_p() and w_type is space.w_str:
-            strval = space.str_w(w_arg)
-            buf = rffi.str2charp(strval)
-            self.to_free.append(rffi.cast(rffi.VOIDP, buf))
-            addr = rffi.cast(rffi.ULONG, buf)
-            argchain.arg(addr)
-            return True
-        elif w_argtype.is_unichar_p() and (w_type is space.w_str or
-                                           w_type is space.w_unicode):
-            unicodeval = space.unicode_w(w_arg)
-            buf = rffi.unicode2wcharp(unicodeval)
-            self.to_free.append(rffi.cast(rffi.VOIDP, buf))
-            addr = rffi.cast(rffi.ULONG, buf)
-            argchain.arg(addr)
-            return True
-        return False
-
-    def convert_pointer_arg_maybe(self, space, w_arg, w_argtype):
-        """
-        Try to convert the argument by calling _as_ffi_pointer_()
-        """
-        meth = space.lookup(w_arg, '_as_ffi_pointer_') # this also promotes the type
-        if meth:
-            return space.call_function(meth, w_arg, w_argtype)
-        else:
-            return w_arg
-
-    def arg_float(self, space, argchain, w_arg):
-        # a separate function, which can be seen by the jit or not,
-        # depending on whether floats are supported
-        argchain.arg(space.float_w(w_arg))
-
-    def arg_longlong(self, space, argchain, w_arg):
-        # a separate function, which can be seen by the jit or not,
-        # depending on whether longlongs are supported
-        bigarg = space.bigint_w(w_arg)
-        ullval = bigarg.ulonglongmask()
-        llval = rffi.cast(rffi.LONGLONG, ullval)
-        argchain.arg(llval)
-
-    def arg_singlefloat(self, space, argchain, w_arg):
-        # a separate function, which can be seen by the jit or not,
-        # depending on whether singlefloats are supported
-        from pypy.rlib.rarithmetic import r_singlefloat
-        fval = space.float_w(w_arg)
-        sfval = r_singlefloat(fval)
-        argchain.arg(sfval)
-
-    def call(self, space, args_w):
-        self = jit.promote(self)
-        argchain = self.build_argchain(space, args_w)
-        return self._do_call(space, argchain)
-
-    def free_temp_buffers(self, space):
-        for buf in self.to_free:
-            if not we_are_translated():
-                buf[0] = '\00' # invalidate the buffer, so that
-                               # test_keepalive_temp_buffer can fail
-            lltype.free(buf, flavor='raw')
-        self.to_free = []
-
-    def _do_call(self, space, argchain):
-        w_restype = self.w_restype
-        if w_restype.is_longlong():
-            # note that we must check for longlong first, because either
-            # is_signed or is_unsigned returns true anyway
-            assert libffi.IS_32_BIT
-            return self._call_longlong(space, argchain)
-        elif w_restype.is_signed():
-            return self._call_int(space, argchain)
-        elif w_restype.is_unsigned() or w_restype.is_pointer():
-            return self._call_uint(space, argchain)
-        elif w_restype.is_char():
-            intres = self.func.call(argchain, rffi.UCHAR)
-            return space.wrap(chr(intres))
-        elif w_restype.is_unichar():
-            intres = self.func.call(argchain, rffi.WCHAR_T)
-            return space.wrap(unichr(intres))
-        elif w_restype.is_double():
-            return self._call_float(space, argchain)
-        elif w_restype.is_singlefloat():
-            return self._call_singlefloat(space, argchain)
-        elif w_restype.is_struct():
-            w_datashape = w_restype.w_datashape
-            assert isinstance(w_datashape, W_Structure)
-            ptrval = self.func.call(argchain, rffi.ULONG, is_struct=True)
-            return w_datashape.fromaddress(space, ptrval)
-        elif w_restype.is_void():
-            voidres = self.func.call(argchain, lltype.Void)
-            assert voidres is None
-            return space.w_None
-        else:
-            assert False, "Return value shape '%s' not supported" % w_restype
-
-    def _call_int(self, space, argchain):
-        # if the declared return type of the function is smaller than LONG,
-        # the result buffer may contains garbage in its higher bits.  To get
-        # the correct value, and to be sure to handle the signed/unsigned case
-        # correctly, we need to cast the result to the correct type.  After
-        # that, we cast it back to LONG, because this is what we want to pass
-        # to space.wrap in order to get a nice applevel <int>.
-        #
-        restype = self.func.restype
-        call = self.func.call
-        if restype is libffi.types.slong:
-            intres = call(argchain, rffi.LONG)
-        elif restype is libffi.types.sint:
-            intres = rffi.cast(rffi.LONG, call(argchain, rffi.INT))
-        elif restype is libffi.types.sshort:
-            intres = rffi.cast(rffi.LONG, call(argchain, rffi.SHORT))
-        elif restype is libffi.types.schar:
-            intres = rffi.cast(rffi.LONG, call(argchain, rffi.SIGNEDCHAR))
-        else:
-            raise OperationError(space.w_ValueError,
-                                 space.wrap('Unsupported restype'))
-        return space.wrap(intres)
-
-    def _call_uint(self, space, argchain):
-        # the same comment as above apply. Moreover, we need to be careful
-        # when the return type is ULONG, because the value might not fit into
-        # a signed LONG: this is the only case in which we cast the result to
-        # something different than LONG; as a result, the applevel value will
-        # be a <long>.
-        #
-        # Note that we check for ULONG before UINT: this is needed on 32bit
-        # machines, where they are they same: if we checked for UINT before
-        # ULONG, we would cast to the wrong type.  Note that this also means
-        # that on 32bit the UINT case will never be entered (because it is
-        # handled by the ULONG case).
-        restype = self.func.restype
-        call = self.func.call
-        if restype is libffi.types.ulong:
-            # special case
-            uintres = call(argchain, rffi.ULONG)
-            return space.wrap(uintres)
-        elif restype is libffi.types.pointer:
-            ptrres = call(argchain, rffi.VOIDP)
-            uintres = rffi.cast(rffi.ULONG, ptrres)
-            return space.wrap(uintres)
-        elif restype is libffi.types.uint:
-            intres = rffi.cast(rffi.LONG, call(argchain, rffi.UINT))
-        elif restype is libffi.types.ushort:
-            intres = rffi.cast(rffi.LONG, call(argchain, rffi.USHORT))
-        elif restype is libffi.types.uchar:
-            intres = rffi.cast(rffi.LONG, call(argchain, rffi.UCHAR))
-        else:
-            raise OperationError(space.w_ValueError,
-                                 space.wrap('Unsupported restype'))
-        return space.wrap(intres)
-
-    def _call_float(self, space, argchain):
-        # a separate function, which can be seen by the jit or not,
-        # depending on whether floats are supported
-        floatres = self.func.call(argchain, rffi.DOUBLE)
-        return space.wrap(floatres)
-
-    def _call_longlong(self, space, argchain):
-        # a separate function, which can be seen by the jit or not,
-        # depending on whether longlongs are supported
-        restype = self.func.restype
-        call = self.func.call
-        if restype is libffi.types.slonglong:
-            llres = call(argchain, rffi.LONGLONG)
-            return space.wrap(llres)
-        elif restype is libffi.types.ulonglong:
-            ullres = call(argchain, rffi.ULONGLONG)
-            return space.wrap(ullres)
-        else:
-            raise OperationError(space.w_ValueError,
-                                 space.wrap('Unsupported longlong restype'))
-
-    def _call_singlefloat(self, space, argchain):
-        # a separate function, which can be seen by the jit or not,
-        # depending on whether singlefloats are supported
-        sfres = self.func.call(argchain, rffi.FLOAT)
-        return space.wrap(float(sfres))
-
-    def getaddr(self, space):
-        """
-        Return the physical address in memory of the function
-        """
-        return space.wrap(rffi.cast(rffi.LONG, self.func.funcsym))
-
-
-
-def unpack_argtypes(space, w_argtypes, w_restype):
-    argtypes_w = [space.interp_w(W_FFIType, w_argtype)
-                  for w_argtype in space.listview(w_argtypes)]
-    argtypes = [unwrap_ffitype(space, w_argtype) for w_argtype in
-                argtypes_w]
-    w_restype = space.interp_w(W_FFIType, w_restype)
-    restype = unwrap_ffitype(space, w_restype, allow_void=True)
-    return argtypes_w, argtypes, w_restype, restype
-
- at unwrap_spec(addr=r_uint, name=str)
-def descr_fromaddr(space, w_cls, addr, name, w_argtypes, w_restype):
-    argtypes_w, argtypes, w_restype, restype = unpack_argtypes(space,
-                                                               w_argtypes,
-                                                               w_restype)
-    addr = rffi.cast(rffi.VOIDP, addr)
-    func = libffi.Func(name, argtypes, restype, addr)
-    return W_FuncPtr(func, argtypes_w, w_restype)
-
-
-W_FuncPtr.typedef = TypeDef(
-    '_ffi.FuncPtr',
-    __call__ = interp2app(W_FuncPtr.call),
-    getaddr = interp2app(W_FuncPtr.getaddr),
-    free_temp_buffers = interp2app(W_FuncPtr.free_temp_buffers),
-    fromaddr = interp2app(descr_fromaddr, as_classmethod=True)
-    )
-
-
-
-# ========================================================================
-
-class W_CDLL(Wrappable):
-    def __init__(self, space, name, mode):
-        self.space = space
-        if name is None:
-            self.name = "<None>"
-        else:
-            self.name = name
-        try:
-            self.cdll = libffi.CDLL(name, mode)
-        except DLOpenError, e:
-            raise operationerrfmt(space.w_OSError, '%s: %s', self.name,
-                                  e.msg or 'unspecified error')
-
-    @unwrap_spec(name=str)
-    def getfunc(self, space, name, w_argtypes, w_restype):
-        argtypes_w, argtypes, w_restype, restype = unpack_argtypes(space,
-                                                                   w_argtypes,
-                                                                   w_restype)
-        try:
-            func = self.cdll.getpointer(name, argtypes, restype)
-        except KeyError:
-            raise operationerrfmt(space.w_AttributeError,
-                                  "No symbol %s found in library %s", name, self.name)
-
-        return W_FuncPtr(func, argtypes_w, w_restype)
-
-    @unwrap_spec(name=str)
-    def getaddressindll(self, space, name):
-        try:
-            address_as_uint = rffi.cast(lltype.Unsigned,
-                                        self.cdll.getaddressindll(name))
-        except KeyError:
-            raise operationerrfmt(space.w_ValueError,
-                                  "No symbol %s found in library %s", name, self.name)
-        return space.wrap(address_as_uint)
-
- at unwrap_spec(name='str_or_None', mode=int)
-def descr_new_cdll(space, w_type, name, mode=-1):
-    return space.wrap(W_CDLL(space, name, mode))
-
-
-W_CDLL.typedef = TypeDef(
-    '_ffi.CDLL',
-    __new__     = interp2app(descr_new_cdll),
-    getfunc     = interp2app(W_CDLL.getfunc),
-    getaddressindll = interp2app(W_CDLL.getaddressindll),
-    )
-
-# ========================================================================
-
-def get_libc(space):
-    from pypy.rlib.clibffi import get_libc_name
-    try:
-        return space.wrap(W_CDLL(space, get_libc_name(), -1))
-    except OSError, e:
-        raise wrap_oserror(space, e)
diff --git a/pypy/module/_ffi/interp_ffitype.py b/pypy/module/_ffi/interp_ffitype.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/_ffi/interp_ffitype.py
@@ -0,0 +1,181 @@
+from pypy.rlib import libffi, clibffi
+from pypy.rlib.rarithmetic import intmask
+from pypy.rlib import jit
+from pypy.interpreter.baseobjspace import Wrappable
+from pypy.interpreter.typedef import TypeDef, interp_attrproperty
+from pypy.interpreter.gateway import interp2app
+from pypy.interpreter.error import OperationError
+
+class W_FFIType(Wrappable):
+
+    _immutable_fields_ = ['name', 'w_structdescr', 'w_pointer_to']
+
+    def __init__(self, name, ffitype, w_structdescr=None, w_pointer_to=None):
+        self.name = name
+        self._ffitype = clibffi.FFI_TYPE_NULL
+        self.w_structdescr = w_structdescr
+        self.w_pointer_to = w_pointer_to
+        self.set_ffitype(ffitype)
+
+    @jit.elidable
+    def get_ffitype(self):
+        if not self._ffitype:
+            raise ValueError("Operation not permitted on an incomplete type")
+        return self._ffitype
+
+    def set_ffitype(self, ffitype):
+        if self._ffitype:
+            raise ValueError("The _ffitype is already set")
+        self._ffitype = ffitype
+        if ffitype and self.is_struct():
+            assert self.w_structdescr is not None
+
+    def descr_deref_pointer(self, space):
+        if self.w_pointer_to is None:
+            return space.w_None
+        return self.w_pointer_to
+
+    def descr_sizeof(self, space):
+        try:
+            return space.wrap(self.sizeof())
+        except ValueError:
+            msg = "Operation not permitted on an incomplete type"
+            raise OperationError(space.w_ValueError, space.wrap(msg))
+
+    def sizeof(self):
+        return intmask(self.get_ffitype().c_size)
+
+    def get_alignment(self):
+        return intmask(self.get_ffitype().c_alignment)
+
+    def repr(self, space):
+        return space.wrap(self.__repr__())
+
+    def __repr__(self):
+        name = self.name
+        if not self._ffitype:
+            name += ' (incomplete)'
+        return "<ffi type %s>" % name
+
+    def is_signed(self):
+        return (self is app_types.slong or
+                self is app_types.sint or
+                self is app_types.sshort or
+                self is app_types.sbyte or
+                self is app_types.slonglong)
+
+    def is_unsigned(self):
+        return (self is app_types.ulong or
+                self is app_types.uint or
+                self is app_types.ushort or
+                self is app_types.ubyte or
+                self is app_types.ulonglong)
+
+    def is_pointer(self):
+        return self.get_ffitype() is libffi.types.pointer
+
+    def is_char(self):
+        return self is app_types.char
+
+    def is_unichar(self):
+        return self is app_types.unichar
+
+    def is_longlong(self):
+        return libffi.IS_32_BIT and (self is app_types.slonglong or
+                                     self is app_types.ulonglong)
+
+    def is_double(self):
+        return self is app_types.double
+
+    def is_singlefloat(self):
+        return self is app_types.float
+
+    def is_void(self):
+        return self is app_types.void
+
+    def is_struct(self):
+        return libffi.types.is_struct(self.get_ffitype())
+
+    def is_char_p(self):
+        return self is app_types.char_p
+
+    def is_unichar_p(self):
+        return self is app_types.unichar_p
+
+
+W_FFIType.typedef = TypeDef(
+    'FFIType',
+    name = interp_attrproperty('name', W_FFIType),
+    __repr__ = interp2app(W_FFIType.repr),
+    deref_pointer = interp2app(W_FFIType.descr_deref_pointer),
+    sizeof = interp2app(W_FFIType.descr_sizeof),
+    )
+
+
+def build_ffi_types():
+    types = [
+        # note: most of the type name directly come from the C equivalent,
+        # with the exception of bytes: in C, ubyte and char are equivalent,
+        # but for _ffi the first expects a number while the second a 1-length
+        # string
+        W_FFIType('slong',     libffi.types.slong),
+        W_FFIType('sint',      libffi.types.sint),
+        W_FFIType('sshort',    libffi.types.sshort),
+        W_FFIType('sbyte',     libffi.types.schar),
+        W_FFIType('slonglong', libffi.types.slonglong),
+        #
+        W_FFIType('ulong',     libffi.types.ulong),
+        W_FFIType('uint',      libffi.types.uint),
+        W_FFIType('ushort',    libffi.types.ushort),
+        W_FFIType('ubyte',     libffi.types.uchar),
+        W_FFIType('ulonglong', libffi.types.ulonglong),
+        #
+        W_FFIType('char',      libffi.types.uchar),
+        W_FFIType('unichar',   libffi.types.wchar_t),
+        #
+        W_FFIType('double',    libffi.types.double),
+        W_FFIType('float',     libffi.types.float),
+        W_FFIType('void',      libffi.types.void),
+        W_FFIType('void_p',    libffi.types.pointer),
+        #
+        # missing types:
+
+        ## 's' : ffi_type_pointer,
+        ## 'z' : ffi_type_pointer,
+        ## 'O' : ffi_type_pointer,
+        ## 'Z' : ffi_type_pointer,
+
+        ]
+    d = dict([(t.name, t) for t in types])
+    w_char = d['char']
+    w_unichar = d['unichar']
+    d['char_p'] = W_FFIType('char_p', libffi.types.pointer, w_pointer_to = w_char)
+    d['unichar_p'] = W_FFIType('unichar_p', libffi.types.pointer, w_pointer_to = w_unichar)
+    return d
+
+class app_types:
+    pass
+app_types.__dict__ = build_ffi_types()
+
+def descr_new_pointer(space, w_cls, w_pointer_to):
+    try:
+        return descr_new_pointer.cache[w_pointer_to]
+    except KeyError:
+        if w_pointer_to is app_types.char:
+            w_result = app_types.char_p
+        elif w_pointer_to is app_types.unichar:
+            w_result = app_types.unichar_p
+        else:
+            w_pointer_to = space.interp_w(W_FFIType, w_pointer_to)
+            name = '(pointer to %s)' % w_pointer_to.name
+            w_result = W_FFIType(name, libffi.types.pointer, w_pointer_to = w_pointer_to)
+        descr_new_pointer.cache[w_pointer_to] = w_result
+        return w_result
+descr_new_pointer.cache = {}
+
+class W_types(Wrappable):
+    pass
+W_types.typedef = TypeDef(
+    'types',
+    Pointer = interp2app(descr_new_pointer, as_classmethod=True),
+    **app_types.__dict__)
diff --git a/pypy/module/_ffi/interp_funcptr.py b/pypy/module/_ffi/interp_funcptr.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/_ffi/interp_funcptr.py
@@ -0,0 +1,311 @@
+from pypy.interpreter.baseobjspace import Wrappable
+from pypy.interpreter.error import OperationError, wrap_oserror, \
+    operationerrfmt
+from pypy.interpreter.gateway import interp2app, unwrap_spec
+from pypy.interpreter.typedef import TypeDef
+from pypy.module._ffi.interp_ffitype import W_FFIType
+#
+from pypy.rpython.lltypesystem import lltype, rffi
+#
+from pypy.rlib import jit
+from pypy.rlib import libffi
+from pypy.rlib.rdynload import DLOpenError
+from pypy.rlib.rarithmetic import intmask, r_uint
+from pypy.rlib.objectmodel import we_are_translated
+from pypy.module._ffi.type_converter import FromAppLevelConverter, ToAppLevelConverter
+
+
+def unwrap_ffitype(space, w_argtype, allow_void=False):
+    res = w_argtype.get_ffitype()
+    if res is libffi.types.void and not allow_void:
+        msg = 'void is not a valid argument type'
+        raise OperationError(space.w_TypeError, space.wrap(msg))
+    return res
+
+
+# ========================================================================
+
+class W_FuncPtr(Wrappable):
+
+    _immutable_fields_ = ['func', 'argtypes_w[*]', 'w_restype']
+
+    def __init__(self, func, argtypes_w, w_restype):
+        self.func = func
+        self.argtypes_w = argtypes_w
+        self.w_restype = w_restype
+        self.to_free = []
+
+    @jit.unroll_safe
+    def build_argchain(self, space, args_w):
+        expected = len(self.argtypes_w)
+        given = len(args_w)
+        if given != expected:
+            arg = 'arguments'
+            if len(self.argtypes_w) == 1:
+                arg = 'argument'
+            raise operationerrfmt(space.w_TypeError,
+                                  '%s() takes exactly %d %s (%d given)',
+                                  self.func.name, expected, arg, given)
+        #
+        argchain = libffi.ArgChain()
+        argpusher = PushArgumentConverter(space, argchain, self)
+        for i in range(expected):
+            w_argtype = self.argtypes_w[i]
+            w_arg = args_w[i]
+            argpusher.unwrap_and_do(w_argtype, w_arg)
+        return argchain
+
+    def call(self, space, args_w):
+        self = jit.promote(self)
+        argchain = self.build_argchain(space, args_w)
+        func_caller = CallFunctionConverter(space, self.func, argchain)
+        return func_caller.do_and_wrap(self.w_restype)
+        #return self._do_call(space, argchain)
+
+    def free_temp_buffers(self, space):
+        for buf in self.to_free:
+            if not we_are_translated():
+                buf[0] = '\00' # invalidate the buffer, so that
+                               # test_keepalive_temp_buffer can fail
+            lltype.free(buf, flavor='raw')
+        self.to_free = []
+
+    def getaddr(self, space):
+        """
+        Return the physical address in memory of the function
+        """
+        return space.wrap(rffi.cast(rffi.LONG, self.func.funcsym))
+
+
+class PushArgumentConverter(FromAppLevelConverter):
+    """
+    A converter used by W_FuncPtr to unwrap the app-level objects into
+    low-level types and push them to the argchain.
+    """
+
+    def __init__(self, space, argchain, w_func):
+        FromAppLevelConverter.__init__(self, space)
+        self.argchain = argchain
+        self.w_func = w_func
+
+    def handle_signed(self, w_ffitype, w_obj, intval):
+        self.argchain.arg(intval)
+
+    def handle_unsigned(self, w_ffitype, w_obj, uintval):
+        self.argchain.arg(uintval)
+
+    def handle_pointer(self, w_ffitype, w_obj, intval):
+        self.argchain.arg(intval)
+
+    def handle_char(self, w_ffitype, w_obj, intval):
+        self.argchain.arg(intval)
+
+    def handle_unichar(self, w_ffitype, w_obj, intval):
+        self.argchain.arg(intval)
+
+    def handle_longlong(self, w_ffitype, w_obj, longlongval):
+        self.argchain.arg(longlongval)
+
+    def handle_char_p(self, w_ffitype, w_obj, strval):
+        buf = rffi.str2charp(strval)
+        self.w_func.to_free.append(rffi.cast(rffi.VOIDP, buf))
+        addr = rffi.cast(rffi.ULONG, buf)
+        self.argchain.arg(addr)
+
+    def handle_unichar_p(self, w_ffitype, w_obj, unicodeval):
+        buf = rffi.unicode2wcharp(unicodeval)
+        self.w_func.to_free.append(rffi.cast(rffi.VOIDP, buf))
+        addr = rffi.cast(rffi.ULONG, buf)
+        self.argchain.arg(addr)
+
+    def handle_float(self, w_ffitype, w_obj, floatval):
+        self.argchain.arg(floatval)
+
+    def handle_singlefloat(self, w_ffitype, w_obj, singlefloatval):
+        self.argchain.arg(singlefloatval)
+
+    def handle_struct(self, w_ffitype, w_structinstance):
+        # arg_raw directly takes value to put inside ll_args
+        ptrval = w_structinstance.rawmem
+        self.argchain.arg_raw(ptrval)
+
+    def handle_struct_rawffi(self, w_ffitype, w_structinstance):
+        # arg_raw directly takes value to put inside ll_args
+        ptrval = w_structinstance.ll_buffer
+        self.argchain.arg_raw(ptrval)
+
+
+class CallFunctionConverter(ToAppLevelConverter):
+    """
+    A converter used by W_FuncPtr to call the function, expect the result of
+    a correct low-level type and wrap it to the corresponding app-level type
+    """
+
+    def __init__(self, space, func, argchain):
+        ToAppLevelConverter.__init__(self, space)
+        self.func = func
+        self.argchain = argchain
+
+    def get_longlong(self, w_ffitype):
+        return self.func.call(self.argchain, rffi.LONGLONG)
+
+    def get_ulonglong(self, w_ffitype):
+        return self.func.call(self.argchain, rffi.ULONGLONG)
+
+    def get_signed(self, w_ffitype):
+        # if the declared return type of the function is smaller than LONG,
+        # the result buffer may contains garbage in its higher bits.  To get
+        # the correct value, and to be sure to handle the signed/unsigned case
+        # correctly, we need to cast the result to the correct type.  After
+        # that, we cast it back to LONG, because this is what we want to pass
+        # to space.wrap in order to get a nice applevel <int>.
+        #
+        restype = w_ffitype.get_ffitype()
+        call = self.func.call
+        if restype is libffi.types.slong:
+            return call(self.argchain, rffi.LONG)
+        elif restype is libffi.types.sint:
+            return rffi.cast(rffi.LONG, call(self.argchain, rffi.INT))
+        elif restype is libffi.types.sshort:
+            return rffi.cast(rffi.LONG, call(self.argchain, rffi.SHORT))
+        elif restype is libffi.types.schar:
+            return rffi.cast(rffi.LONG, call(self.argchain, rffi.SIGNEDCHAR))
+        else:
+            self.error(w_ffitype)
+            
+    def get_unsigned(self, w_ffitype):
+        return self.func.call(self.argchain, rffi.ULONG)
+
+    def get_unsigned_which_fits_into_a_signed(self, w_ffitype):
+        # the same comment as get_signed apply
+        restype = w_ffitype.get_ffitype()
+        call = self.func.call
+        if restype is libffi.types.uint:
+            assert not libffi.IS_32_BIT
+            # on 32bit machines, we should never get here, because it's a case
+            # which has already been handled by get_unsigned above.
+            return rffi.cast(rffi.LONG, call(self.argchain, rffi.UINT))
+        elif restype is libffi.types.ushort:
+            return rffi.cast(rffi.LONG, call(self.argchain, rffi.USHORT))
+        elif restype is libffi.types.uchar:
+            return rffi.cast(rffi.LONG, call(self.argchain, rffi.UCHAR))
+        else:
+            self.error(w_ffitype)
+
+
+    def get_pointer(self, w_ffitype):
+        ptrres = self.func.call(self.argchain, rffi.VOIDP)
+        return rffi.cast(rffi.ULONG, ptrres)
+
+    def get_char(self, w_ffitype):
+        return self.func.call(self.argchain, rffi.UCHAR)
+
+    def get_unichar(self, w_ffitype):
+        return self.func.call(self.argchain, rffi.WCHAR_T)
+
+    def get_float(self, w_ffitype):
+        return self.func.call(self.argchain, rffi.DOUBLE)
+
+    def get_singlefloat(self, w_ffitype):
+        return self.func.call(self.argchain, rffi.FLOAT)
+
+    def get_struct(self, w_ffitype, w_structdescr):
+        addr = self.func.call(self.argchain, rffi.LONG, is_struct=True)
+        return w_structdescr.fromaddress(self.space, addr)
+
+    def get_struct_rawffi(self, w_ffitype, w_structdescr):
+        uintval = self.func.call(self.argchain, rffi.ULONG, is_struct=True)
+        return w_structdescr.fromaddress(self.space, uintval)
+
+    def get_void(self, w_ffitype):
+        return self.func.call(self.argchain, lltype.Void)
+    
+
+def unpack_argtypes(space, w_argtypes, w_restype):
+    argtypes_w = [space.interp_w(W_FFIType, w_argtype)
+                  for w_argtype in space.listview(w_argtypes)]
+    argtypes = [unwrap_ffitype(space, w_argtype) for w_argtype in
+                argtypes_w]
+    w_restype = space.interp_w(W_FFIType, w_restype)
+    restype = unwrap_ffitype(space, w_restype, allow_void=True)
+    return argtypes_w, argtypes, w_restype, restype
+
+ at unwrap_spec(addr=r_uint, name=str)
+def descr_fromaddr(space, w_cls, addr, name, w_argtypes, w_restype):
+    argtypes_w, argtypes, w_restype, restype = unpack_argtypes(space,
+                                                               w_argtypes,
+                                                               w_restype)
+    addr = rffi.cast(rffi.VOIDP, addr)
+    func = libffi.Func(name, argtypes, restype, addr)
+    return W_FuncPtr(func, argtypes_w, w_restype)
+
+
+W_FuncPtr.typedef = TypeDef(
+    '_ffi.FuncPtr',
+    __call__ = interp2app(W_FuncPtr.call),
+    getaddr = interp2app(W_FuncPtr.getaddr),
+    free_temp_buffers = interp2app(W_FuncPtr.free_temp_buffers),
+    fromaddr = interp2app(descr_fromaddr, as_classmethod=True)
+    )
+
+
+
+# ========================================================================
+
+class W_CDLL(Wrappable):
+    def __init__(self, space, name, mode):
+        self.space = space
+        if name is None:
+            self.name = "<None>"
+        else:
+            self.name = name
+        try:
+            self.cdll = libffi.CDLL(name, mode)
+        except DLOpenError, e:
+            raise operationerrfmt(space.w_OSError, '%s: %s', self.name,
+                                  e.msg or 'unspecified error')
+
+    @unwrap_spec(name=str)
+    def getfunc(self, space, name, w_argtypes, w_restype):
+        argtypes_w, argtypes, w_restype, restype = unpack_argtypes(space,
+                                                                   w_argtypes,
+                                                                   w_restype)
+        try:
+            func = self.cdll.getpointer(name, argtypes, restype)
+        except KeyError:
+            raise operationerrfmt(space.w_AttributeError,
+                                  "No symbol %s found in library %s", name, self.name)
+
+        return W_FuncPtr(func, argtypes_w, w_restype)
+
+    @unwrap_spec(name=str)
+    def getaddressindll(self, space, name):
+        try:
+            address_as_uint = rffi.cast(lltype.Unsigned,
+                                        self.cdll.getaddressindll(name))
+        except KeyError:
+            raise operationerrfmt(space.w_ValueError,
+                                  "No symbol %s found in library %s", name, self.name)
+        return space.wrap(address_as_uint)
+
+ at unwrap_spec(name='str_or_None', mode=int)
+def descr_new_cdll(space, w_type, name, mode=-1):
+    return space.wrap(W_CDLL(space, name, mode))
+
+
+W_CDLL.typedef = TypeDef(
+    '_ffi.CDLL',
+    __new__     = interp2app(descr_new_cdll),
+    getfunc     = interp2app(W_CDLL.getfunc),
+    getaddressindll = interp2app(W_CDLL.getaddressindll),
+    )
+
+# ========================================================================
+
+def get_libc(space):
+    from pypy.rlib.clibffi import get_libc_name
+    try:
+        return space.wrap(W_CDLL(space, get_libc_name(), -1))
+    except OSError, e:
+        raise wrap_oserror(space, e)
+
diff --git a/pypy/module/_ffi/interp_struct.py b/pypy/module/_ffi/interp_struct.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/_ffi/interp_struct.py
@@ -0,0 +1,319 @@
+from pypy.rpython.lltypesystem import lltype, rffi
+from pypy.rlib import clibffi
+from pypy.rlib import libffi
+from pypy.rlib import jit
+from pypy.rlib.rgc import must_be_light_finalizer
+from pypy.rlib.rarithmetic import r_uint, r_ulonglong, r_singlefloat, intmask
+from pypy.interpreter.baseobjspace import Wrappable
+from pypy.interpreter.typedef import TypeDef, interp_attrproperty
+from pypy.interpreter.gateway import interp2app, unwrap_spec
+from pypy.interpreter.error import operationerrfmt
+from pypy.objspace.std.typetype import type_typedef
+from pypy.module._ffi.interp_ffitype import W_FFIType, app_types
+from pypy.module._ffi.type_converter import FromAppLevelConverter, ToAppLevelConverter
+
+
+class W_Field(Wrappable):
+
+    def __init__(self, name, w_ffitype):
+        self.name = name
+        self.w_ffitype = w_ffitype
+        self.offset = -1
+
+    def __repr__(self):
+        return '<Field %s %s>' % (self.name, self.w_ffitype.name)
+
+ at unwrap_spec(name=str)
+def descr_new_field(space, w_type, name, w_ffitype):
+    w_ffitype = space.interp_w(W_FFIType, w_ffitype)
+    return W_Field(name, w_ffitype)
+
+W_Field.typedef = TypeDef(
+    'Field',
+    __new__ = interp2app(descr_new_field),
+    name = interp_attrproperty('name', W_Field),
+    ffitype = interp_attrproperty('w_ffitype', W_Field),
+    offset = interp_attrproperty('offset', W_Field),
+    )
+
+
+# ==============================================================================
+
+class FFIStructOwner(object):
+    """
+    The only job of this class is to stay outside of the reference cycle
+    W__StructDescr -> W_FFIType -> W__StructDescr and free the ffistruct
+    """
+
+    def __init__(self, ffistruct):
+        self.ffistruct = ffistruct
+
+    @must_be_light_finalizer
+    def __del__(self):
+        if self.ffistruct:
+            lltype.free(self.ffistruct, flavor='raw', track_allocation=True)
+        
+
+class W__StructDescr(Wrappable):
+
+    def __init__(self, space, name):
+        self.space = space
+        self.w_ffitype = W_FFIType('struct %s' % name, clibffi.FFI_TYPE_NULL,
+                                   w_structdescr=self)
+        self.fields_w = None
+        self.name2w_field = {}
+        self._ffistruct_owner = None
+
+    def define_fields(self, space, w_fields):
+        if self.fields_w is not None:
+            raise operationerrfmt(space.w_ValueError,
+                                  "%s's fields has already been defined",
+                                  self.w_ffitype.name)
+        space = self.space
+        fields_w = space.fixedview(w_fields)
+        # note that the fields_w returned by compute_size_and_alignement has a
+        # different annotation than the original: list(W_Root) vs list(W_Field)
+        size, alignment, fields_w = compute_size_and_alignement(space, fields_w)
+        self.fields_w = fields_w
+        field_types = [] # clibffi's types
+        for w_field in fields_w:
+            field_types.append(w_field.w_ffitype.get_ffitype())
+            self.name2w_field[w_field.name] = w_field
+        #
+        # on CPython, the FFIStructOwner might go into gc.garbage and thus the
+        # __del__ never be called. Thus, we don't track the allocation of the
+        # malloc done inside this function, else the leakfinder might complain
+        ffistruct = clibffi.make_struct_ffitype_e(size, alignment, field_types,
+                                                  track_allocation=False)
+        self.w_ffitype.set_ffitype(ffistruct.ffistruct)
+        self._ffistruct_owner = FFIStructOwner(ffistruct)
+
+    def check_complete(self, space):
+        if self.fields_w is None:
+            raise operationerrfmt(space.w_ValueError, "%s has an incomplete type",
+                                  self.w_ffitype.name)
+
+    def allocate(self, space):
+        self.check_complete(space)
+        return W__StructInstance(self)
+
+    @unwrap_spec(addr=int)
+    def fromaddress(self, space, addr):
+        self.check_complete(space)
+        rawmem = rffi.cast(rffi.VOIDP, addr)
+        return W__StructInstance(self, allocate=False, autofree=True, rawmem=rawmem)
+
+    @jit.elidable_promote('0')
+    def get_type_and_offset_for_field(self, name):
+        try:
+            w_field = self.name2w_field[name]
+        except KeyError:
+            raise operationerrfmt(self.space.w_AttributeError, '%s', name)
+
+        return w_field.w_ffitype, w_field.offset
+
+
+
+ at unwrap_spec(name=str)
+def descr_new_structdescr(space, w_type, name, w_fields=None):
+    descr = W__StructDescr(space, name)
+    if w_fields is not space.w_None:
+        descr.define_fields(space, w_fields)
+    return descr
+
+def round_up(size, alignment):
+    return (size + alignment - 1) & -alignment
+
+def compute_size_and_alignement(space, fields_w):
+    size = 0
+    alignment = 1
+    fields_w2 = []
+    for w_field in fields_w:
+        w_field = space.interp_w(W_Field, w_field)
+        fieldsize = w_field.w_ffitype.sizeof()
+        fieldalignment = w_field.w_ffitype.get_alignment()
+        alignment = max(alignment, fieldalignment)
+        size = round_up(size, fieldalignment)
+        w_field.offset = size
+        size += fieldsize
+        fields_w2.append(w_field)
+    #
+    size = round_up(size, alignment)
+    return size, alignment, fields_w2
+
+
+
+W__StructDescr.typedef = TypeDef(
+    '_StructDescr',
+    __new__ = interp2app(descr_new_structdescr),
+    ffitype = interp_attrproperty('w_ffitype', W__StructDescr),
+    define_fields = interp2app(W__StructDescr.define_fields),
+    allocate = interp2app(W__StructDescr.allocate),
+    fromaddress = interp2app(W__StructDescr.fromaddress),
+    )
+
+
+# ==============================================================================
+
+NULL = lltype.nullptr(rffi.VOIDP.TO)
+
+class W__StructInstance(Wrappable):
+
+    _immutable_fields_ = ['structdescr', 'rawmem']
+
+    def __init__(self, structdescr, allocate=True, autofree=True, rawmem=NULL):
+        self.structdescr = structdescr
+        self.autofree = autofree
+        if allocate:
+            assert not rawmem
+            assert autofree
+            size = structdescr.w_ffitype.sizeof()
+            self.rawmem = lltype.malloc(rffi.VOIDP.TO, size, flavor='raw',
+                                        zero=True, add_memory_pressure=True)
+        else:
+            self.rawmem = rawmem
+
+    @must_be_light_finalizer
+    def __del__(self):
+        if self.autofree and self.rawmem:
+            lltype.free(self.rawmem, flavor='raw')
+            self.rawmem = lltype.nullptr(rffi.VOIDP.TO)
+
+    def getaddr(self, space):
+        addr = rffi.cast(rffi.ULONG, self.rawmem)
+        return space.wrap(addr)
+
+    @unwrap_spec(name=str)
+    def getfield(self, space, name):
+        w_ffitype, offset = self.structdescr.get_type_and_offset_for_field(name)
+        field_getter = GetFieldConverter(space, self.rawmem, offset)
+        return field_getter.do_and_wrap(w_ffitype)
+
+    @unwrap_spec(name=str)
+    def setfield(self, space, name, w_value):
+        w_ffitype, offset = self.structdescr.get_type_and_offset_for_field(name)
+        field_setter = SetFieldConverter(space, self.rawmem, offset)
+        field_setter.unwrap_and_do(w_ffitype, w_value)
+
+
+class GetFieldConverter(ToAppLevelConverter):
+    """
+    A converter used by W__StructInstance to get a field from the struct and
+    wrap it to the correct app-level type.
+    """
+
+    def __init__(self, space, rawmem, offset):
+        self.space = space
+        self.rawmem = rawmem
+        self.offset = offset
+
+    def get_longlong(self, w_ffitype): 
+        return libffi.struct_getfield_longlong(libffi.types.slonglong,
+                                               self.rawmem, self.offset)
+
+    def get_ulonglong(self, w_ffitype):
+        longlongval = libffi.struct_getfield_longlong(libffi.types.ulonglong,
+                                                      self.rawmem, self.offset)
+        return r_ulonglong(longlongval)
+
+
+    def get_signed(self, w_ffitype):
+        return libffi.struct_getfield_int(w_ffitype.get_ffitype(),
+                                          self.rawmem, self.offset)
+
+    def get_unsigned(self, w_ffitype):
+        value = libffi.struct_getfield_int(w_ffitype.get_ffitype(),
+                                           self.rawmem, self.offset)
+        return r_uint(value)
+
+    get_unsigned_which_fits_into_a_signed = get_signed
+    get_pointer = get_unsigned
+
+    def get_char(self, w_ffitype):
+        intval = libffi.struct_getfield_int(w_ffitype.get_ffitype(),
+                                            self.rawmem, self.offset)
+        return rffi.cast(rffi.UCHAR, intval)
+
+    def get_unichar(self, w_ffitype):
+        intval = libffi.struct_getfield_int(w_ffitype.get_ffitype(),
+                                            self.rawmem, self.offset)
+        return rffi.cast(rffi.WCHAR_T, intval)
+
+    def get_float(self, w_ffitype):
+        return libffi.struct_getfield_float(w_ffitype.get_ffitype(),
+                                            self.rawmem, self.offset)
+
+    def get_singlefloat(self, w_ffitype):
+        return libffi.struct_getfield_singlefloat(w_ffitype.get_ffitype(),
+                                                  self.rawmem, self.offset)
+
+    def get_struct(self, w_ffitype, w_structdescr):
+        assert isinstance(w_structdescr, W__StructDescr)
+        rawmem = rffi.cast(rffi.CCHARP, self.rawmem)
+        innermem = rffi.cast(rffi.VOIDP, rffi.ptradd(rawmem, self.offset))
+        # we return a reference to the inner struct, not a copy
+        # autofree=False because it's still owned by the parent struct
+        return W__StructInstance(w_structdescr, allocate=False, autofree=False,
+                                 rawmem=innermem)
+
+    ## def get_void(self, w_ffitype):
+    ##     ...
+
+
+class SetFieldConverter(FromAppLevelConverter):
+    """
+    A converter used by W__StructInstance to convert an app-level object to
+    the corresponding low-level value and set the field of a structure.
+    """
+
+    def __init__(self, space, rawmem, offset):
+        self.space = space
+        self.rawmem = rawmem
+        self.offset = offset
+
+    def handle_signed(self, w_ffitype, w_obj, intval):
+        libffi.struct_setfield_int(w_ffitype.get_ffitype(), self.rawmem, self.offset,
+                                   intval)
+
+    def handle_unsigned(self, w_ffitype, w_obj, uintval):
+        libffi.struct_setfield_int(w_ffitype.get_ffitype(), self.rawmem, self.offset,
+                                   intmask(uintval))
+
+    handle_pointer = handle_signed
+    handle_char = handle_signed
+    handle_unichar = handle_signed
+
+    def handle_longlong(self, w_ffitype, w_obj, longlongval):
+        libffi.struct_setfield_longlong(w_ffitype.get_ffitype(),
+                                        self.rawmem, self.offset, longlongval)
+
+    def handle_float(self, w_ffitype, w_obj, floatval):
+        libffi.struct_setfield_float(w_ffitype.get_ffitype(),
+                                     self.rawmem, self.offset, floatval)
+
+    def handle_singlefloat(self, w_ffitype, w_obj, singlefloatval):
+        libffi.struct_setfield_singlefloat(w_ffitype.get_ffitype(),
+                                           self.rawmem, self.offset, singlefloatval)
+
+    def handle_struct(self, w_ffitype, w_structinstance):
+        rawmem = rffi.cast(rffi.CCHARP, self.rawmem)
+        dst = rffi.cast(rffi.VOIDP, rffi.ptradd(rawmem, self.offset))
+        src = w_structinstance.rawmem
+        length = w_ffitype.sizeof()
+        rffi.c_memcpy(dst, src, length)
+
+    ## def handle_char_p(self, w_ffitype, w_obj, strval):
+    ##     ...
+
+    ## def handle_unichar_p(self, w_ffitype, w_obj, unicodeval):
+    ##     ...
+
+
+
+
+W__StructInstance.typedef = TypeDef(
+    '_StructInstance',
+    getaddr  = interp2app(W__StructInstance.getaddr),
+    getfield = interp2app(W__StructInstance.getfield),
+    setfield = interp2app(W__StructInstance.setfield),
+    )
diff --git a/pypy/module/_ffi/test/test__ffi.py b/pypy/module/_ffi/test/test__ffi.py
deleted file mode 100644
--- a/pypy/module/_ffi/test/test__ffi.py
+++ /dev/null
@@ -1,542 +0,0 @@
-from pypy.conftest import gettestobjspace
-from pypy.translator.platform import platform
-from pypy.translator.tool.cbuild import ExternalCompilationInfo
-from pypy.module._rawffi.interp_rawffi import TYPEMAP
-from pypy.module._rawffi.tracker import Tracker
-from pypy.translator.platform import platform
-
-import os, sys, py
-
-class AppTestFfi:
-
-    @classmethod
-    def prepare_c_example(cls):
-        from pypy.tool.udir import udir
-        from pypy.translator.tool.cbuild import ExternalCompilationInfo
-        from pypy.translator.platform import platform
-
-        c_file = udir.ensure("test__ffi", dir=1).join("foolib.c")
-        # automatically collect the C source from the docstrings of the tests
-        snippets = ["""
-        #ifdef _WIN32
-        #define DLLEXPORT __declspec(dllexport)
-        #else
-        #define DLLEXPORT
-        #endif
-        """]
-        for name in dir(cls):
-            if name.startswith('test_'):
-                meth = getattr(cls, name)
-                # the heuristic to determine it it's really C code could be
-                # improved: so far we just check that there is a '{' :-)
-                if meth.__doc__ is not None and '{' in meth.__doc__:
-                    snippets.append(meth.__doc__)
-        #
-        c_file.write(py.code.Source('\n'.join(snippets)))
-        eci = ExternalCompilationInfo(export_symbols=[])
-        return str(platform.compile([c_file], eci, 'x', standalone=False))
-
-    
-    def setup_class(cls):
-        from pypy.rpython.lltypesystem import rffi
-        from pypy.rlib.libffi import get_libc_name, CDLL, types
-        from pypy.rlib.test.test_libffi import get_libm_name
-        space = gettestobjspace(usemodules=('_ffi', '_rawffi'))
-        cls.space = space
-        cls.w_iswin32 = space.wrap(sys.platform == 'win32')
-        cls.w_libfoo_name = space.wrap(cls.prepare_c_example())
-        cls.w_libc_name = space.wrap(get_libc_name())
-        libm_name = get_libm_name(sys.platform)
-        cls.w_libm_name = space.wrap(libm_name)
-        libm = CDLL(libm_name)
-        pow = libm.getpointer('pow', [], types.void)
-        pow_addr = rffi.cast(rffi.LONG, pow.funcsym)
-        cls.w_pow_addr = space.wrap(pow_addr)
-        #
-        # these are needed for test_single_float_args
-        from ctypes import c_float
-        f_12_34 = c_float(12.34).value
-        f_56_78 = c_float(56.78).value
-        f_result = c_float(f_12_34 + f_56_78).value
-        cls.w_f_12_34_plus_56_78 = space.wrap(f_result)
-
-    def test_libload(self):
-        import _ffi
-        _ffi.CDLL(self.libc_name)
-
-    def test_libload_fail(self):
-        import _ffi
-        raises(OSError, _ffi.CDLL, "xxxxx_this_name_does_not_exist_xxxxx")
-
-    def test_libload_None(self):
-        if self.iswin32:
-            skip("unix specific")
-        from _ffi import CDLL, types
-        # this should return *all* loaded libs, dlopen(NULL)
-        dll = CDLL(None)
-        # Assume CPython, or PyPy compiled with cpyext
-        res = dll.getfunc('Py_IsInitialized', [], types.slong)()
-        assert res == 1
-
-    def test_simple_types(self):
-        from _ffi import types
-        assert str(types.sint) == "<ffi type sint>"
-        assert str(types.uint) == "<ffi type uint>"
-        
-    def test_callfunc(self):
-        from _ffi import CDLL, types
-        libm = CDLL(self.libm_name)
-        pow = libm.getfunc('pow', [types.double, types.double], types.double)
-        assert pow(2, 3) == 8
-
-    def test_getaddr(self):
-        from _ffi import CDLL, types
-        libm = CDLL(self.libm_name)
-        pow = libm.getfunc('pow', [types.double, types.double], types.double)
-        assert pow.getaddr() == self.pow_addr
-
-    def test_getaddressindll(self):
-        import sys
-        from _ffi import CDLL, types
-        libm = CDLL(self.libm_name)
-        pow_addr = libm.getaddressindll('pow')
-        fff = sys.maxint*2-1
-        if sys.platform == 'win32':
-            fff = sys.maxint*2+1
-        assert pow_addr == self.pow_addr & fff
-
-    def test_func_fromaddr(self):
-        import sys
-        from _ffi import CDLL, types, FuncPtr
-        libm = CDLL(self.libm_name)
-        pow_addr = libm.getaddressindll('pow')
-        pow = FuncPtr.fromaddr(pow_addr, 'pow', [types.double, types.double],
-                               types.double)
-        assert pow(2, 3) == 8
-
-    def test_int_args(self):
-        """
-            DLLEXPORT int sum_xy(int x, int y)
-            {
-                return x+y;
-            }
-        """
-        py3k_skip('missing support for longs')
-        import sys
-        from _ffi import CDLL, types
-        libfoo = CDLL(self.libfoo_name)
-        sum_xy = libfoo.getfunc('sum_xy', [types.sint, types.sint], types.sint)
-        assert sum_xy(30, 12) == 42
-        assert sum_xy(sys.maxint*2, 0) == -2
-
-    def test_void_result(self):
-        """
-            int dummy = 0;
-            DLLEXPORT void set_dummy(int val) { dummy = val; }
-            DLLEXPORT int get_dummy() { return dummy; }
-        """
-        from _ffi import CDLL, types
-        libfoo = CDLL(self.libfoo_name)
-        set_dummy = libfoo.getfunc('set_dummy', [types.sint], types.void)
-        get_dummy = libfoo.getfunc('get_dummy', [], types.sint)
-        assert get_dummy() == 0
-        assert set_dummy(42) is None
-        assert get_dummy() == 42
-        set_dummy(0)
-
-    def test_pointer_args(self):
-        """
-            extern int dummy; // defined in test_void_result 
-            DLLEXPORT int* get_dummy_ptr() { return &dummy; }
-            DLLEXPORT void set_val_to_ptr(int* ptr, int val) { *ptr = val; }
-        """
-        from _ffi import CDLL, types
-        libfoo = CDLL(self.libfoo_name)
-        get_dummy = libfoo.getfunc('get_dummy', [], types.sint)
-        get_dummy_ptr = libfoo.getfunc('get_dummy_ptr', [], types.void_p)
-        set_val_to_ptr = libfoo.getfunc('set_val_to_ptr',
-                                        [types.void_p, types.sint],
-                                        types.void)
-        assert get_dummy() == 0
-        ptr = get_dummy_ptr()
-        set_val_to_ptr(ptr, 123)
-        assert get_dummy() == 123
-        set_val_to_ptr(ptr, 0)
-
-    def test_convert_pointer_args(self):
-        """
-            extern int dummy; // defined in test_void_result 
-            DLLEXPORT int* get_dummy_ptr(); // defined in test_pointer_args
-            DLLEXPORT void set_val_to_ptr(int* ptr, int val); // ditto
-        """
-        from _ffi import CDLL, types
-
-        class MyPointerWrapper(object):
-            def __init__(self, value):
-                self.value = value
-            def _as_ffi_pointer_(self, ffitype):
-                assert ffitype is types.void_p
-                return self.value
-        
-        libfoo = CDLL(self.libfoo_name)
-        get_dummy = libfoo.getfunc('get_dummy', [], types.sint)
-        get_dummy_ptr = libfoo.getfunc('get_dummy_ptr', [], types.void_p)
-        set_val_to_ptr = libfoo.getfunc('set_val_to_ptr',
-                                        [types.void_p, types.sint],
-                                        types.void)
-        assert get_dummy() == 0
-        ptr = get_dummy_ptr()
-        assert type(ptr) is int
-        ptr2 = MyPointerWrapper(ptr)
-        set_val_to_ptr(ptr2, 123)
-        assert get_dummy() == 123
-        set_val_to_ptr(ptr2, 0)
-
-    def test_convert_strings_to_char_p(self):
-        """
-            DLLEXPORT
-            long mystrlen(char* s)
-            {
-                long len = 0;
-                while(*s++)
-                    len++;
-                return len;
-            }
-        """
-        py3k_skip('missing support for unicode')
-        from _ffi import CDLL, types
-        import _rawffi
-        libfoo = CDLL(self.libfoo_name)
-        mystrlen = libfoo.getfunc('mystrlen', [types.char_p], types.slong)
-        #
-        # first, try automatic conversion from a string
-        assert mystrlen('foobar') == 6
-        # then, try to pass an explicit pointer
-        CharArray = _rawffi.Array('c')
-        mystr = CharArray(7, 'foobar')
-        assert mystrlen(mystr.buffer) == 6
-        mystr.free()
-        mystrlen.free_temp_buffers()
-
-    def test_convert_unicode_to_unichar_p(self):
-        """
-            #include <wchar.h>
-            DLLEXPORT
-            long mystrlen_u(wchar_t* s)
-            {
-                long len = 0;
-                while(*s++)
-                    len++;
-                return len;
-            }
-        """
-        from _ffi import CDLL, types
-        import _rawffi
-        libfoo = CDLL(self.libfoo_name)
-        mystrlen = libfoo.getfunc('mystrlen_u', [types.unichar_p], types.slong)
-        #
-        # first, try automatic conversion from strings and unicode
-        assert mystrlen('foobar') == 6
-        assert mystrlen('foobar') == 6
-        assert mystrlen('ab\u2070') == 3
-        # then, try to pass an explicit pointer
-        UniCharArray = _rawffi.Array('u')
-        mystr = UniCharArray(7, 'foobar')
-        assert mystrlen(mystr.buffer) == 6
-        mystr.free()
-        mystrlen.free_temp_buffers()
-
-    def test_keepalive_temp_buffer(self):
-        """
-            DLLEXPORT
-            char* do_nothing(char* s)
-            {
-                return s;
-            }
-        """
-        py3k_skip('missing support for unicode')
-        from _ffi import CDLL, types
-        import _rawffi
-        libfoo = CDLL(self.libfoo_name)
-        do_nothing = libfoo.getfunc('do_nothing', [types.char_p], types.char_p)
-        CharArray = _rawffi.Array('c')
-        #
-        ptr = do_nothing('foobar')
-        array = CharArray.fromaddress(ptr, 7)
-        assert list(array) == list('foobar\00')
-        do_nothing.free_temp_buffers()
-
-    def test_typed_pointer(self):
-        from _ffi import types
-        intptr = types.Pointer(types.sint) # create a typed pointer to sint
-        assert intptr.deref_pointer() is types.sint
-        assert str(intptr) == '<ffi type (pointer to sint)>'
-        assert types.sint.deref_pointer() is None
-        raises(TypeError, "types.Pointer(42)")
-
-    def test_pointer_identity(self):
-        from _ffi import types
-        x = types.Pointer(types.slong)
-        y = types.Pointer(types.slong)
-        z = types.Pointer(types.char)
-        assert x is y
-        assert x is not z
-
-    def test_char_p_cached(self):
-        from _ffi import types
-        x = types.Pointer(types.char)
-        assert x is types.char_p
-        x = types.Pointer(types.unichar)
-        assert x is types.unichar_p
-
-    def test_typed_pointer_args(self):
-        """
-            extern int dummy; // defined in test_void_result 
-            DLLEXPORT int* get_dummy_ptr(); // defined in test_pointer_args
-            DLLEXPORT void set_val_to_ptr(int* ptr, int val); // ditto
-        """
-        from _ffi import CDLL, types
-
-        libfoo = CDLL(self.libfoo_name)
-        intptr = types.Pointer(types.sint)
-        get_dummy = libfoo.getfunc('get_dummy', [], types.sint)
-        get_dummy_ptr = libfoo.getfunc('get_dummy_ptr', [], intptr)
-        set_val_to_ptr = libfoo.getfunc('set_val_to_ptr', [intptr, types.sint], types.void)
-        assert get_dummy() == 0
-        ptr = get_dummy_ptr()
-        set_val_to_ptr(ptr, 123)
-        assert get_dummy() == 123
-        set_val_to_ptr(ptr, 0)
-
-    def test_huge_pointer_args(self):
-        """
-            #include <stdlib.h>
-            DLLEXPORT long is_null_ptr(void* ptr) { return ptr == NULL; }
-        """
-        import sys
-        from _ffi import CDLL, types
-        libfoo = CDLL(self.libfoo_name)
-        is_null_ptr = libfoo.getfunc('is_null_ptr', [types.void_p], types.ulong)
-        assert not is_null_ptr(sys.maxint+1)
-
-    def test_unsigned_long_args(self):
-        """
-            DLLEXPORT unsigned long sum_xy_ul(unsigned long x, unsigned long y)
-            {
-                return x+y;
-            }
-        """
-        py3k_skip('missing support for longs')
-        import sys
-        from _ffi import CDLL, types
-        libfoo = CDLL(self.libfoo_name)
-        sum_xy = libfoo.getfunc('sum_xy_ul', [types.ulong, types.ulong],
-                                types.ulong)
-        assert sum_xy(sys.maxint, 12) == sys.maxint+12
-        assert sum_xy(sys.maxint+1, 12) == sys.maxint+13
-        #
-        res = sum_xy(sys.maxint*2+3, 0)
-        assert res == 1
-
-    def test_unsigned_short_args(self):
-        """
-            DLLEXPORT unsigned short sum_xy_us(unsigned short x, unsigned short y)
-            {
-                return x+y;
-            }
-        """
-        from _ffi import CDLL, types
-        libfoo = CDLL(self.libfoo_name)
-        sum_xy = libfoo.getfunc('sum_xy_us', [types.ushort, types.ushort],
-                                types.ushort)
-        assert sum_xy(32000, 8000) == 40000
-        assert sum_xy(60000, 30000) == 90000 % 65536
-
-    def test_unsigned_byte_args(self):
-        """
-            DLLEXPORT unsigned char sum_xy_ub(unsigned char x, unsigned char y)
-            {
-                return x+y;
-            }
-        """
-        from _ffi import CDLL, types
-        libfoo = CDLL(self.libfoo_name)
-        sum_xy = libfoo.getfunc('sum_xy_us', [types.ubyte, types.ubyte],
-                                types.ubyte)
-        assert sum_xy(100, 40) == 140
-        assert sum_xy(200, 60) == 260 % 256
-
-    def test_signed_byte_args(self):
-        """
-            DLLEXPORT signed char sum_xy_sb(signed char x, signed char y)
-            {
-                return x+y;
-            }
-        """
-        from _ffi import CDLL, types
-        libfoo = CDLL(self.libfoo_name)
-        sum_xy = libfoo.getfunc('sum_xy_sb', [types.sbyte, types.sbyte],
-                                types.sbyte)
-        assert sum_xy(10, 20) == 30
-        assert sum_xy(100, 28) == -128
-
-    def test_char_args(self):
-        """
-            DLLEXPORT char my_toupper(char x)
-            {
-                return x - ('a'-'A');
-            }
-        """
-        from _ffi import CDLL, types
-        libfoo = CDLL(self.libfoo_name)
-        my_toupper = libfoo.getfunc('my_toupper', [types.char],
-                                    types.char)
-        assert my_toupper('c') == 'C'
-
-    def test_unichar_args(self):
-        """
-            #include <stddef.h>
-            DLLEXPORT wchar_t sum_xy_wc(wchar_t x, wchar_t y)
-            {
-                return x + y;
-            }
-        """
-        from _ffi import CDLL, types
-        libfoo = CDLL(self.libfoo_name)
-        sum_xy = libfoo.getfunc('sum_xy_wc', [types.unichar, types.unichar],
-                                types.unichar)
-        res = sum_xy(chr(1000), chr(2000))
-        assert type(res) is str
-        assert ord(res) == 3000
-
-    def test_single_float_args(self):
-        """
-            DLLEXPORT float sum_xy_float(float x, float y)
-            {
-                return x+y;
-            }
-        """
-        from _ffi import CDLL, types
-        libfoo = CDLL(self.libfoo_name)
-        sum_xy = libfoo.getfunc('sum_xy_float', [types.float, types.float],
-                                types.float)
-        res = sum_xy(12.34, 56.78)
-        assert res == self.f_12_34_plus_56_78
-
-
-    def test_slonglong_args(self):
-        """
-            DLLEXPORT long long sum_xy_longlong(long long x, long long y)
-            {
-                return x+y;
-            }
-        """
-        from _ffi import CDLL, types
-        maxint32 = 2147483647 # we cannot really go above maxint on 64 bits
-                              # (and we would not test anything, as there long
-                              # is the same as long long)
-
-        libfoo = CDLL(self.libfoo_name)
-        sum_xy = libfoo.getfunc('sum_xy_longlong', [types.slonglong, types.slonglong],
-                                types.slonglong)
-        x = maxint32+1
-        y = maxint32+2
-        res = sum_xy(x, y)
-        expected = maxint32*2 + 3
-        assert res == expected
-
-    def test_ulonglong_args(self):
-        """
-            DLLEXPORT unsigned long long sum_xy_ulonglong(unsigned long long x,
-                                                unsigned long long y)
-            {
-                return x+y;
-            }
-        """
-        py3k_skip('missing support for ulonglong')
-        from _ffi import CDLL, types
-        maxint64 = 9223372036854775807 # maxint64+1 does not fit into a
-                                       # longlong, but it does into a
-                                       # ulonglong
-        libfoo = CDLL(self.libfoo_name)
-        sum_xy = libfoo.getfunc('sum_xy_ulonglong', [types.ulonglong, types.ulonglong],
-                                types.ulonglong)
-        x = maxint64+1
-        y = 2
-        res = sum_xy(x, y)
-        expected = maxint64 + 3
-        assert res == expected
-        #
-        res = sum_xy(maxint64*2+3, 0)
-        assert res == 1
-
-    def test_byval_argument(self):
-        """
-            struct Point {
-                long x;
-                long y;
-            };
-
-            DLLEXPORT long sum_point(struct Point p) {
-                return p.x + p.y;
-            }
-        """
-        import _rawffi
-        from _ffi import CDLL, types
-        POINT = _rawffi.Structure([('x', 'l'), ('y', 'l')])
-        ffi_point = POINT.get_ffi_type()
-        libfoo = CDLL(self.libfoo_name)
-        sum_point = libfoo.getfunc('sum_point', [ffi_point], types.slong)
-        #
-        p = POINT()
-        p.x = 30
-        p.y = 12
-        res = sum_point(p)
-        assert res == 42
-        p.free()
-
-    def test_byval_result(self):
-        """
-            DLLEXPORT struct Point make_point(long x, long y) {
-                struct Point p;
-                p.x = x;
-                p.y = y;
-                return p;
-            }
-        """
-        import _rawffi
-        from _ffi import CDLL, types
-        POINT = _rawffi.Structure([('x', 'l'), ('y', 'l')])
-        ffi_point = POINT.get_ffi_type()
-        libfoo = CDLL(self.libfoo_name)
-        make_point = libfoo.getfunc('make_point', [types.slong, types.slong], ffi_point)
-        #
-        p = make_point(12, 34)
-        assert p.x == 12
-        assert p.y == 34
-        p.free()
-
-    def test_TypeError_numargs(self):
-        from _ffi import CDLL, types
-        libfoo = CDLL(self.libfoo_name)
-        sum_xy = libfoo.getfunc('sum_xy', [types.sint, types.sint], types.sint)
-        raises(TypeError, "sum_xy(1, 2, 3)")
-        raises(TypeError, "sum_xy(1)")
-
-    def test_TypeError_voidarg(self):
-        from _ffi import CDLL, types
-        libfoo = CDLL(self.libfoo_name)
-        raises(TypeError, "libfoo.getfunc('sum_xy', [types.void], types.sint)")
-        
-    def test_OSError_loading(self):
-        from _ffi import CDLL, types
-        raises(OSError, "CDLL('I do not exist')")
-
-    def test_AttributeError_missing_function(self):
-        from _ffi import CDLL, types
-        libfoo = CDLL(self.libfoo_name)
-        raises(AttributeError, "libfoo.getfunc('I_do_not_exist', [], types.void)")
-        if self.iswin32:
-            skip("unix specific")
-        libnone = CDLL(None)
-        raises(AttributeError, "libnone.getfunc('I_do_not_exist', [], types.void)")
diff --git a/pypy/module/_ffi/test/test_ffitype.py b/pypy/module/_ffi/test/test_ffitype.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/_ffi/test/test_ffitype.py
@@ -0,0 +1,39 @@
+from pypy.module._ffi.test.test_funcptr import BaseAppTestFFI
+
+class AppTestFFIType(BaseAppTestFFI):
+
+    def test_simple_types(self):
+        from _ffi import types
+        assert str(types.sint) == "<ffi type sint>"
+        assert str(types.uint) == "<ffi type uint>"
+        assert types.sint.name == 'sint'
+        assert types.uint.name == 'uint'
+        
+    def test_sizeof(self):
+        from _ffi import types
+        assert types.sbyte.sizeof() == 1
+        assert types.sint.sizeof() == 4
+
+    def test_typed_pointer(self):
+        from _ffi import types
+        intptr = types.Pointer(types.sint) # create a typed pointer to sint
+        assert intptr.deref_pointer() is types.sint
+        assert str(intptr) == '<ffi type (pointer to sint)>'
+        assert types.sint.deref_pointer() is None
+        raises(TypeError, "types.Pointer(42)")
+
+    def test_pointer_identity(self):
+        from _ffi import types
+        x = types.Pointer(types.slong)
+        y = types.Pointer(types.slong)
+        z = types.Pointer(types.char)
+        assert x is y
+        assert x is not z
+
+    def test_char_p_cached(self):
+        from _ffi import types
+        x = types.Pointer(types.char)
+        assert x is types.char_p
+        x = types.Pointer(types.unichar)
+        assert x is types.unichar_p
+
diff --git a/pypy/module/_ffi/test/test_funcptr.py b/pypy/module/_ffi/test/test_funcptr.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/_ffi/test/test_funcptr.py
@@ -0,0 +1,576 @@
+from pypy.conftest import gettestobjspace
+from pypy.translator.platform import platform
+from pypy.translator.tool.cbuild import ExternalCompilationInfo
+from pypy.module._rawffi.interp_rawffi import TYPEMAP
+from pypy.module._rawffi.tracker import Tracker
+from pypy.translator.platform import platform
+
+import os, sys, py
+
+class BaseAppTestFFI(object):
+
+    @classmethod
+    def prepare_c_example(cls):
+        from pypy.tool.udir import udir
+        from pypy.translator.tool.cbuild import ExternalCompilationInfo
+        from pypy.translator.platform import platform
+
+        c_file = udir.ensure("test__ffi", dir=1).join("foolib.c")
+        # automatically collect the C source from the docstrings of the tests
+        snippets = ["""
+        #ifdef _WIN32
+        #define DLLEXPORT __declspec(dllexport)
+        #else
+        #define DLLEXPORT
+        #endif
+        """]
+        for name in dir(cls):
+            if name.startswith('test_'):
+                meth = getattr(cls, name)
+                # the heuristic to determine it it's really C code could be
+                # improved: so far we just check that there is a '{' :-)
+                if meth.__doc__ is not None and '{' in meth.__doc__:
+                    snippets.append(meth.__doc__)
+        #
+        c_file.write(py.code.Source('\n'.join(snippets)))
+        eci = ExternalCompilationInfo(export_symbols=[])
+        return str(platform.compile([c_file], eci, 'x', standalone=False))
+
+    def setup_class(cls):
+        from pypy.rpython.lltypesystem import rffi
+        from pypy.rlib.libffi import get_libc_name, CDLL, types
+        from pypy.rlib.test.test_libffi import get_libm_name
+        space = gettestobjspace(usemodules=('_ffi', '_rawffi'))
+        cls.space = space
+        cls.w_iswin32 = space.wrap(sys.platform == 'win32')
+        cls.w_libfoo_name = space.wrap(cls.prepare_c_example())
+        cls.w_libc_name = space.wrap(get_libc_name())
+        libm_name = get_libm_name(sys.platform)
+        cls.w_libm_name = space.wrap(libm_name)
+        libm = CDLL(libm_name)
+        pow = libm.getpointer('pow', [], types.void)
+        pow_addr = rffi.cast(rffi.LONG, pow.funcsym)
+        cls.w_pow_addr = space.wrap(pow_addr)
+
+class AppTestFFI(BaseAppTestFFI):
+
+    def setup_class(cls):
+        BaseAppTestFFI.setup_class.im_func(cls)
+        space = cls.space
+        # these are needed for test_single_float_args
+        from ctypes import c_float
+        f_12_34 = c_float(12.34).value
+        f_56_78 = c_float(56.78).value
+        f_result = c_float(f_12_34 + f_56_78).value
+        cls.w_f_12_34_plus_56_78 = space.wrap(f_result)
+
+    def test_libload(self):
+        import _ffi
+        _ffi.CDLL(self.libc_name)
+
+    def test_libload_fail(self):
+        import _ffi
+        raises(OSError, _ffi.CDLL, "xxxxx_this_name_does_not_exist_xxxxx")
+
+    def test_libload_None(self):
+        if self.iswin32:
+            skip("unix specific")
+        from _ffi import CDLL, types
+        # this should return *all* loaded libs, dlopen(NULL)
+        dll = CDLL(None)
+        # Assume CPython, or PyPy compiled with cpyext
+        res = dll.getfunc('Py_IsInitialized', [], types.slong)()
+        assert res == 1
+
+    def test_callfunc(self):
+        from _ffi import CDLL, types
+        libm = CDLL(self.libm_name)
+        pow = libm.getfunc('pow', [types.double, types.double], types.double)
+        assert pow(2, 3) == 8
+
+    def test_getaddr(self):
+        from _ffi import CDLL, types
+        libm = CDLL(self.libm_name)
+        pow = libm.getfunc('pow', [types.double, types.double], types.double)
+        assert pow.getaddr() == self.pow_addr
+
+    def test_getaddressindll(self):
+        import sys
+        from _ffi import CDLL, types
+        libm = CDLL(self.libm_name)
+        pow_addr = libm.getaddressindll('pow')
+        fff = sys.maxint*2-1
+        if sys.platform == 'win32':
+            fff = sys.maxint*2+1
+        assert pow_addr == self.pow_addr & fff
+
+    def test_func_fromaddr(self):
+        import sys
+        from _ffi import CDLL, types, FuncPtr
+        libm = CDLL(self.libm_name)
+        pow_addr = libm.getaddressindll('pow')
+        pow = FuncPtr.fromaddr(pow_addr, 'pow', [types.double, types.double],
+                               types.double)
+        assert pow(2, 3) == 8
+
+    def test_int_args(self):
+        """
+            DLLEXPORT int sum_xy(int x, int y)
+            {
+                return x+y;
+            }
+        """
+        py3k_skip('missing support for longs')
+        import sys
+        from _ffi import CDLL, types
+        libfoo = CDLL(self.libfoo_name)
+        sum_xy = libfoo.getfunc('sum_xy', [types.sint, types.sint], types.sint)
+        assert sum_xy(30, 12) == 42
+        assert sum_xy(sys.maxint*2, 0) == -2
+
+    def test_void_result(self):
+        """
+            int dummy = 0;
+            DLLEXPORT void set_dummy(int val) { dummy = val; }
+            DLLEXPORT int get_dummy() { return dummy; }
+        """
+        from _ffi import CDLL, types
+        libfoo = CDLL(self.libfoo_name)
+        set_dummy = libfoo.getfunc('set_dummy', [types.sint], types.void)
+        get_dummy = libfoo.getfunc('get_dummy', [], types.sint)
+        assert get_dummy() == 0
+        assert set_dummy(42) is None
+        assert get_dummy() == 42
+        set_dummy(0)
+
+    def test_pointer_args(self):
+        """
+            extern int dummy; // defined in test_void_result 
+            DLLEXPORT int* get_dummy_ptr() { return &dummy; }
+            DLLEXPORT void set_val_to_ptr(int* ptr, int val) { *ptr = val; }
+        """
+        from _ffi import CDLL, types
+        libfoo = CDLL(self.libfoo_name)
+        get_dummy = libfoo.getfunc('get_dummy', [], types.sint)
+        get_dummy_ptr = libfoo.getfunc('get_dummy_ptr', [], types.void_p)
+        set_val_to_ptr = libfoo.getfunc('set_val_to_ptr',
+                                        [types.void_p, types.sint],
+                                        types.void)
+        assert get_dummy() == 0
+        ptr = get_dummy_ptr()
+        set_val_to_ptr(ptr, 123)
+        assert get_dummy() == 123
+        set_val_to_ptr(ptr, 0)
+
+    def test_convert_pointer_args(self):
+        """
+            extern int dummy; // defined in test_void_result 
+            DLLEXPORT int* get_dummy_ptr(); // defined in test_pointer_args
+            DLLEXPORT void set_val_to_ptr(int* ptr, int val); // ditto
+        """
+        from _ffi import CDLL, types
+
+        class MyPointerWrapper(object):
+            def __init__(self, value):
+                self.value = value
+            def _as_ffi_pointer_(self, ffitype):
+                assert ffitype is types.void_p
+                return self.value
+        
+        libfoo = CDLL(self.libfoo_name)
+        get_dummy = libfoo.getfunc('get_dummy', [], types.sint)
+        get_dummy_ptr = libfoo.getfunc('get_dummy_ptr', [], types.void_p)
+        set_val_to_ptr = libfoo.getfunc('set_val_to_ptr',
+                                        [types.void_p, types.sint],
+                                        types.void)
+        assert get_dummy() == 0
+        ptr = get_dummy_ptr()
+        assert type(ptr) is int
+        ptr2 = MyPointerWrapper(ptr)
+        set_val_to_ptr(ptr2, 123)
+        assert get_dummy() == 123
+        set_val_to_ptr(ptr2, 0)
+
+    def test_convert_strings_to_char_p(self):
+        """
+            DLLEXPORT
+            long mystrlen(char* s)
+            {
+                long len = 0;
+                while(*s++)
+                    len++;
+                return len;
+            }
+        """
+        py3k_skip('missing support for unicode')
+        from _ffi import CDLL, types
+        import _rawffi
+        libfoo = CDLL(self.libfoo_name)
+        mystrlen = libfoo.getfunc('mystrlen', [types.char_p], types.slong)
+        #
+        # first, try automatic conversion from a string
+        assert mystrlen('foobar') == 6
+        # then, try to pass an explicit pointer
+        CharArray = _rawffi.Array('c')
+        mystr = CharArray(7, 'foobar')
+        assert mystrlen(mystr.buffer) == 6
+        mystr.free()
+        mystrlen.free_temp_buffers()
+
+    def test_convert_unicode_to_unichar_p(self):
+        """
+            #include <wchar.h>
+            DLLEXPORT
+            long mystrlen_u(wchar_t* s)
+            {
+                long len = 0;
+                while(*s++)
+                    len++;
+                return len;
+            }
+        """
+        from _ffi import CDLL, types
+        import _rawffi
+        libfoo = CDLL(self.libfoo_name)
+        mystrlen = libfoo.getfunc('mystrlen_u', [types.unichar_p], types.slong)
+        #
+        # first, try automatic conversion from strings and unicode
+        assert mystrlen('foobar') == 6
+        assert mystrlen('foobar') == 6
+        assert mystrlen('ab\u2070') == 3
+        # then, try to pass an explicit pointer
+        UniCharArray = _rawffi.Array('u')
+        mystr = UniCharArray(7, 'foobar')
+        assert mystrlen(mystr.buffer) == 6
+        mystr.free()
+        mystrlen.free_temp_buffers()
+
+    def test_keepalive_temp_buffer(self):
+        """
+            DLLEXPORT
+            char* do_nothing(char* s)
+            {
+                return s;
+            }
+        """
+        py3k_skip('missing support for unicode')
+        from _ffi import CDLL, types
+        import _rawffi
+        libfoo = CDLL(self.libfoo_name)
+        do_nothing = libfoo.getfunc('do_nothing', [types.char_p], types.char_p)
+        CharArray = _rawffi.Array('c')
+        #
+        ptr = do_nothing('foobar')
+        array = CharArray.fromaddress(ptr, 7)
+        assert list(array) == list('foobar\00')
+        do_nothing.free_temp_buffers()
+
+    def test_typed_pointer_args(self):
+        """
+            extern int dummy; // defined in test_void_result 
+            DLLEXPORT int* get_dummy_ptr(); // defined in test_pointer_args
+            DLLEXPORT void set_val_to_ptr(int* ptr, int val); // ditto
+        """
+        from _ffi import CDLL, types
+
+        libfoo = CDLL(self.libfoo_name)
+        intptr = types.Pointer(types.sint)
+        get_dummy = libfoo.getfunc('get_dummy', [], types.sint)
+        get_dummy_ptr = libfoo.getfunc('get_dummy_ptr', [], intptr)
+        set_val_to_ptr = libfoo.getfunc('set_val_to_ptr', [intptr, types.sint], types.void)
+        assert get_dummy() == 0
+        ptr = get_dummy_ptr()
+        set_val_to_ptr(ptr, 123)
+        assert get_dummy() == 123
+        set_val_to_ptr(ptr, 0)
+
+    def test_huge_pointer_args(self):
+        """
+            #include <stdlib.h>
+            DLLEXPORT long is_null_ptr(void* ptr) { return ptr == NULL; }
+        """
+        import sys
+        from _ffi import CDLL, types
+        libfoo = CDLL(self.libfoo_name)
+        is_null_ptr = libfoo.getfunc('is_null_ptr', [types.void_p], types.ulong)
+        assert not is_null_ptr(sys.maxint+1)
+
+    def test_unsigned_long_args(self):
+        """
+            DLLEXPORT unsigned long sum_xy_ul(unsigned long x, unsigned long y)
+            {
+                return x+y;
+            }
+        """
+        py3k_skip('missing support for longs')
+        import sys
+        from _ffi import CDLL, types
+        libfoo = CDLL(self.libfoo_name)
+        sum_xy = libfoo.getfunc('sum_xy_ul', [types.ulong, types.ulong],
+                                types.ulong)
+        assert sum_xy(sys.maxint, 12) == sys.maxint+12
+        assert sum_xy(sys.maxint+1, 12) == sys.maxint+13
+        #
+        res = sum_xy(sys.maxint*2+3, 0)
+        assert res == 1
+
+    def test_unsigned_short_args(self):
+        """
+            DLLEXPORT unsigned short sum_xy_us(unsigned short x, unsigned short y)
+            {
+                return x+y;
+            }
+        """
+        from _ffi import CDLL, types
+        libfoo = CDLL(self.libfoo_name)
+        sum_xy = libfoo.getfunc('sum_xy_us', [types.ushort, types.ushort],
+                                types.ushort)
+        assert sum_xy(32000, 8000) == 40000
+        assert sum_xy(60000, 30000) == 90000 % 65536
+
+    def test_unsigned_byte_args(self):
+        """
+            DLLEXPORT unsigned char sum_xy_ub(unsigned char x, unsigned char y)
+            {
+                return x+y;
+            }
+        """
+        from _ffi import CDLL, types
+        libfoo = CDLL(self.libfoo_name)
+        sum_xy = libfoo.getfunc('sum_xy_us', [types.ubyte, types.ubyte],
+                                types.ubyte)
+        assert sum_xy(100, 40) == 140
+        assert sum_xy(200, 60) == 260 % 256
+
+    def test_unsigned_int_args(self):
+        r"""
+            DLLEXPORT unsigned int sum_xy_ui(unsigned int x, unsigned int y)
+            {
+                return x+y;
+            }
+        """
+        import sys
+        from _ffi import CDLL, types
+        maxint32 = 2147483647
+        libfoo = CDLL(self.libfoo_name)
+        sum_xy = libfoo.getfunc('sum_xy_ui', [types.uint, types.uint],
+                                types.uint)
+        assert sum_xy(maxint32, 1) == maxint32+1
+        assert sum_xy(maxint32, maxint32+2) == 0
+
+    def test_signed_byte_args(self):
+        """
+            DLLEXPORT signed char sum_xy_sb(signed char x, signed char y)
+            {
+                return x+y;
+            }
+        """
+        from _ffi import CDLL, types
+        libfoo = CDLL(self.libfoo_name)
+        sum_xy = libfoo.getfunc('sum_xy_sb', [types.sbyte, types.sbyte],
+                                types.sbyte)
+        assert sum_xy(10, 20) == 30
+        assert sum_xy(100, 28) == -128
+
+    def test_char_args(self):
+        """
+            DLLEXPORT char my_toupper(char x)
+            {
+                return x - ('a'-'A');
+            }
+        """
+        from _ffi import CDLL, types
+        libfoo = CDLL(self.libfoo_name)
+        my_toupper = libfoo.getfunc('my_toupper', [types.char],
+                                    types.char)
+        assert my_toupper('c') == 'C'
+
+    def test_unichar_args(self):
+        """
+            #include <stddef.h>
+            DLLEXPORT wchar_t sum_xy_wc(wchar_t x, wchar_t y)
+            {
+                return x + y;
+            }
+        """
+        from _ffi import CDLL, types
+        libfoo = CDLL(self.libfoo_name)
+        sum_xy = libfoo.getfunc('sum_xy_wc', [types.unichar, types.unichar],
+                                types.unichar)
+        res = sum_xy(chr(1000), chr(2000))
+        assert type(res) is str
+        assert ord(res) == 3000
+
+    def test_single_float_args(self):
+        """
+            DLLEXPORT float sum_xy_float(float x, float y)
+            {
+                return x+y;
+            }
+        """
+        from _ffi import CDLL, types
+        libfoo = CDLL(self.libfoo_name)
+        sum_xy = libfoo.getfunc('sum_xy_float', [types.float, types.float],
+                                types.float)
+        res = sum_xy(12.34, 56.78)
+        assert res == self.f_12_34_plus_56_78
+
+
+    def test_slonglong_args(self):
+        """
+            DLLEXPORT long long sum_xy_longlong(long long x, long long y)
+            {
+                return x+y;
+            }
+        """
+        from _ffi import CDLL, types
+        maxint32 = 2147483647 # we cannot really go above maxint on 64 bits
+                              # (and we would not test anything, as there long
+                              # is the same as long long)
+
+        libfoo = CDLL(self.libfoo_name)
+        sum_xy = libfoo.getfunc('sum_xy_longlong', [types.slonglong, types.slonglong],
+                                types.slonglong)
+        x = maxint32+1
+        y = maxint32+2
+        res = sum_xy(x, y)
+        expected = maxint32*2 + 3
+        assert res == expected
+
+    def test_ulonglong_args(self):
+        """
+            DLLEXPORT unsigned long long sum_xy_ulonglong(unsigned long long x,
+                                                unsigned long long y)
+            {
+                return x+y;
+            }
+        """
+        py3k_skip('missing support for ulonglong')
+        from _ffi import CDLL, types
+        maxint64 = 9223372036854775807 # maxint64+1 does not fit into a
+                                       # longlong, but it does into a
+                                       # ulonglong
+        libfoo = CDLL(self.libfoo_name)
+        sum_xy = libfoo.getfunc('sum_xy_ulonglong', [types.ulonglong, types.ulonglong],
+                                types.ulonglong)
+        x = maxint64+1
+        y = 2
+        res = sum_xy(x, y)
+        expected = maxint64 + 3
+        assert res == expected
+        #
+        res = sum_xy(maxint64*2+3, 0)
+        assert res == 1
+
+    def test_byval_argument(self):
+        """
+            struct Point {
+                long x;
+                long y;
+            };
+
+            DLLEXPORT long sum_point(struct Point p) {
+                return p.x + p.y;
+            }
+        """
+        from _ffi import CDLL, types, _StructDescr, Field
+        Point = _StructDescr('Point', [
+                Field('x', types.slong),
+                Field('y', types.slong),
+                ])
+        libfoo = CDLL(self.libfoo_name)
+        sum_point = libfoo.getfunc('sum_point', [Point.ffitype], types.slong)
+        #
+        p = Point.allocate()
+        p.setfield('x', 30)
+        p.setfield('y', 12)
+        res = sum_point(p)
+        assert res == 42
+
+    def test_byval_result(self):
+        """
+            DLLEXPORT struct Point make_point(long x, long y) {
+                struct Point p;
+                p.x = x;
+                p.y = y;
+                return p;
+            }
+        """
+        from _ffi import CDLL, types, _StructDescr, Field
+        Point = _StructDescr('Point', [
+                Field('x', types.slong),
+                Field('y', types.slong),
+                ])
+        libfoo = CDLL(self.libfoo_name)
+        make_point = libfoo.getfunc('make_point', [types.slong, types.slong],
+                                    Point.ffitype)
+        #
+        p = make_point(12, 34)
+        assert p.getfield('x') == 12
+        assert p.getfield('y') == 34
+
+    # XXX: support for _rawffi structures should be killed as soon as we
+    # implement ctypes.Structure on top of _ffi. In the meantime, we support
+    # both
+    def test_byval_argument__rawffi(self):
+        """
+            // defined above
+            struct Point;
+            DLLEXPORT long sum_point(struct Point p);
+        """
+        import _rawffi
+        from _ffi import CDLL, types
+        POINT = _rawffi.Structure([('x', 'l'), ('y', 'l')])
+        ffi_point = POINT.get_ffi_type()
+        libfoo = CDLL(self.libfoo_name)
+        sum_point = libfoo.getfunc('sum_point', [ffi_point], types.slong)
+        #
+        p = POINT()
+        p.x = 30
+        p.y = 12
+        res = sum_point(p)
+        assert res == 42
+        p.free()
+
+    def test_byval_result__rawffi(self):
+        """
+            // defined above
+            DLLEXPORT struct Point make_point(long x, long y);
+        """
+        import _rawffi
+        from _ffi import CDLL, types
+        POINT = _rawffi.Structure([('x', 'l'), ('y', 'l')])
+        ffi_point = POINT.get_ffi_type()
+        libfoo = CDLL(self.libfoo_name)
+        make_point = libfoo.getfunc('make_point', [types.slong, types.slong], ffi_point)
+        #
+        p = make_point(12, 34)
+        assert p.x == 12
+        assert p.y == 34
+        p.free()
+
+
+    def test_TypeError_numargs(self):
+        from _ffi import CDLL, types
+        libfoo = CDLL(self.libfoo_name)
+        sum_xy = libfoo.getfunc('sum_xy', [types.sint, types.sint], types.sint)
+        raises(TypeError, "sum_xy(1, 2, 3)")
+        raises(TypeError, "sum_xy(1)")
+
+    def test_TypeError_voidarg(self):
+        from _ffi import CDLL, types
+        libfoo = CDLL(self.libfoo_name)
+        raises(TypeError, "libfoo.getfunc('sum_xy', [types.void], types.sint)")
+        
+    def test_OSError_loading(self):
+        from _ffi import CDLL, types
+        raises(OSError, "CDLL('I do not exist')")
+
+    def test_AttributeError_missing_function(self):
+        from _ffi import CDLL, types
+        libfoo = CDLL(self.libfoo_name)
+        raises(AttributeError, "libfoo.getfunc('I_do_not_exist', [], types.void)")
+        if self.iswin32:
+            skip("unix specific")
+        libnone = CDLL(None)
+        raises(AttributeError, "libnone.getfunc('I_do_not_exist', [], types.void)")
diff --git a/pypy/module/_ffi/test/test_struct.py b/pypy/module/_ffi/test/test_struct.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/_ffi/test/test_struct.py
@@ -0,0 +1,323 @@
+import sys
+from pypy.conftest import gettestobjspace, option
+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):
+
+    class FakeSpace(object):
+        def interp_w(self, cls, obj):
+            return obj
+
+    def compute(self, ffitypes_w):
+        fields_w = [W_Field('<dummy>', w_ffitype) for
+                    w_ffitype in ffitypes_w]
+        return compute_size_and_alignement(self.FakeSpace(), fields_w)
+
+    def sizeof(self, ffitypes_w):
+        size, aligned, fields_w = self.compute(ffitypes_w)
+        return size
+
+    def test_compute_size(self):
+        T = app_types
+        byte_size = app_types.sbyte.sizeof()
+        long_size = app_types.slong.sizeof()
+        llong_size = app_types.slonglong.sizeof()
+        llong_align = app_types.slonglong.get_alignment()
+        #
+        assert llong_align >= 4
+        assert self.sizeof([T.sbyte, T.slong]) == 2*long_size
+        assert self.sizeof([T.sbyte, T.slonglong]) == llong_align + llong_size
+        assert self.sizeof([T.sbyte, T.sbyte, T.slonglong]) == llong_align + llong_size
+        assert self.sizeof([T.sbyte, T.sbyte, T.sbyte, T.slonglong]) == llong_align + llong_size
+        assert self.sizeof([T.sbyte, T.sbyte, T.sbyte, T.sbyte, T.slonglong]) == llong_align + llong_size
+        assert self.sizeof([T.slonglong, T.sbyte]) == llong_size + llong_align
+        assert self.sizeof([T.slonglong, T.sbyte, T.sbyte]) == llong_size + llong_align
+        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):
+            import ctypes
+            addr = ctypes.cast(addr, ctypes.c_void_p)
+            c_type = getattr(ctypes, typename)
+            array_type = ctypes.POINTER(c_type * length)
+            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)
+        #
+        from pypy.rlib import clibffi
+        from pypy.rlib.rarithmetic import r_uint
+        from pypy.rpython.lltypesystem import lltype, rffi
+        dummy_type = lltype.malloc(clibffi.FFI_TYPE_P.TO, flavor='raw')
+        dummy_type.c_size = r_uint(123)
+        dummy_type.c_alignment = rffi.cast(rffi.USHORT, 0)
+        dummy_type.c_type = rffi.cast(rffi.USHORT, 0)
+        cls.w_dummy_type = W_FFIType('dummy', dummy_type)
+        cls.w_runappdirect = cls.space.wrap(option.runappdirect)
+        
+    def test__StructDescr(self):
+        from _ffi import _StructDescr, Field, types
+        longsize = types.slong.sizeof()
+        fields = [
+            Field('x', types.slong),
+            Field('y', types.slong),
+            ]
+        descr = _StructDescr('foo', fields)
+        assert descr.ffitype.sizeof() == longsize*2
+        assert descr.ffitype.name == 'struct foo'
+
+    def test_alignment(self):
+        from _ffi import _StructDescr, Field, types
+        longsize = types.slong.sizeof()
+        fields = [
+            Field('x', types.sbyte),
+            Field('y', types.slong),
+            ]
+        descr = _StructDescr('foo', fields)
+        assert descr.ffitype.sizeof() == longsize*2
+        assert fields[0].offset == 0
+        assert fields[1].offset == longsize # aligned to WORD
+
+    def test_missing_field(self):
+        from _ffi import _StructDescr, Field, types
+        longsize = types.slong.sizeof()
+        fields = [
+            Field('x', types.slong),
+            Field('y', types.slong),
+            ]
+        descr = _StructDescr('foo', fields)
+        struct = descr.allocate()
+        raises(AttributeError, "struct.getfield('missing')")
+        raises(AttributeError, "struct.setfield('missing', 42)")
+
+    def test_unknown_type(self):
+        if self.runappdirect:
+            skip('cannot use self.dummy_type with -A')
+        from _ffi import _StructDescr, Field
+        fields = [
+            Field('x', self.dummy_type),
+            ]
+        descr = _StructDescr('foo', fields)
+        struct = descr.allocate()
+        raises(TypeError, "struct.getfield('x')")
+        raises(TypeError, "struct.setfield('x', 42)")
+
+    def test_getfield_setfield(self):
+        from _ffi import _StructDescr, Field, types
+        longsize = types.slong.sizeof()
+        fields = [
+            Field('x', types.slong),
+            Field('y', types.slong),
+            ]
+        descr = _StructDescr('foo', fields)
+        struct = descr.allocate()
+        struct.setfield('x', 42)
+        struct.setfield('y', 43)
+        assert struct.getfield('x') == 42
+        assert struct.getfield('y') == 43
+        mem = self.read_raw_mem(struct.getaddr(), 'c_long', 2)
+        assert mem == [42, 43]
+
+    def test_getfield_setfield_signed_types(self):
+        import sys
+        from _ffi import _StructDescr, Field, types
+        longsize = types.slong.sizeof()
+        fields = [
+            Field('sbyte', types.sbyte),
+            Field('sshort', types.sshort),
+            Field('sint', types.sint),
+            Field('slong', types.slong),
+            ]
+        descr = _StructDescr('foo', fields)
+        struct = descr.allocate()
+        struct.setfield('sbyte', 128)
+        assert struct.getfield('sbyte') == -128
+        struct.setfield('sshort', 32768)
+        assert struct.getfield('sshort') == -32768
+        struct.setfield('sint', 43)
+        assert struct.getfield('sint') == 43
+        struct.setfield('slong', sys.maxint+1)
+        assert struct.getfield('slong') == -sys.maxint-1
+        struct.setfield('slong', sys.maxint*3)
+        assert struct.getfield('slong') == sys.maxint-2
+
+    def test_getfield_setfield_unsigned_types(self):
+        import sys
+        from _ffi import _StructDescr, Field, types
+        longsize = types.slong.sizeof()
+        fields = [
+            Field('ubyte', types.ubyte),
+            Field('ushort', types.ushort),
+            Field('uint', types.uint),
+            Field('ulong', types.ulong),
+            Field('char', types.char),
+            Field('unichar', types.unichar),
+            Field('ptr', types.void_p),
+            ]
+        descr = _StructDescr('foo', fields)
+        struct = descr.allocate()
+        struct.setfield('ubyte', -1)
+        assert struct.getfield('ubyte') == 255
+        struct.setfield('ushort', -1)
+        assert struct.getfield('ushort') == 65535
+        struct.setfield('uint', 43)
+        assert struct.getfield('uint') == 43
+        struct.setfield('ulong', -1)
+        assert struct.getfield('ulong') == sys.maxint*2 + 1
+        struct.setfield('ulong', sys.maxint*2 + 2)
+        assert struct.getfield('ulong') == 0
+        struct.setfield('char', 'a')
+        assert struct.getfield('char') == 'a'
+        struct.setfield('unichar', u'\u1234')
+        assert struct.getfield('unichar') == u'\u1234'
+        struct.setfield('ptr', -1)
+        assert struct.getfield('ptr') == sys.maxint*2 + 1
+    
+    def test_getfield_setfield_longlong(self):
+        import sys
+        from _ffi import _StructDescr, Field, types
+        longsize = types.slong.sizeof()
+        fields = [
+            Field('slonglong', types.slonglong),
+            Field('ulonglong', types.ulonglong),
+            ]
+        descr = _StructDescr('foo', fields)
+        struct = descr.allocate()
+        struct.setfield('slonglong', 9223372036854775808)
+        assert struct.getfield('slonglong') == -9223372036854775808
+        struct.setfield('ulonglong', -1)
+        assert struct.getfield('ulonglong') == 18446744073709551615        
+        mem = self.read_raw_mem(struct.getaddr(), 'c_longlong', 2)
+        assert mem == [-9223372036854775808, -1]
+
+    def test_getfield_setfield_float(self):
+        import sys
+        from _ffi import _StructDescr, Field, types
+        longsize = types.slong.sizeof()
+        fields = [
+            Field('x', types.double),
+            ]
+        descr = _StructDescr('foo', fields)
+        struct = descr.allocate()
+        struct.setfield('x', 123.4)
+        assert struct.getfield('x') == 123.4
+        mem = self.read_raw_mem(struct.getaddr(), 'c_double', 1)
+        assert mem == [123.4]
+
+    def test_getfield_setfield_singlefloat(self):
+        import sys
+        from _ffi import _StructDescr, Field, types
+        longsize = types.slong.sizeof()
+        fields = [
+            Field('x', types.float),
+            ]
+        descr = _StructDescr('foo', fields)
+        struct = descr.allocate()
+        struct.setfield('x', 123.4) # this is a value which DOES loose
+                                    # precision in a single float
+        assert 0 < abs(struct.getfield('x') - 123.4) < 0.0001
+        #
+        struct.setfield('x', 123.5) # this is a value which does not loose
+                                    # precision in a single float
+        assert struct.getfield('x') == 123.5
+        mem = self.read_raw_mem(struct.getaddr(), 'c_float', 1)
+        assert mem == [123.5]
+
+    def test_define_fields(self):
+        from _ffi import _StructDescr, Field, types
+        longsize = types.slong.sizeof()
+        fields = [
+            Field('x', types.slong),
+            Field('y', types.slong),
+            ]
+        descr = _StructDescr('foo')
+        assert descr.ffitype.name == 'struct foo'
+        assert repr(descr.ffitype) == '<ffi type struct foo (incomplete)>'
+        raises(ValueError, "descr.ffitype.sizeof()")
+        raises(ValueError, "descr.allocate()")
+        #
+        descr.define_fields(fields)
+        assert repr(descr.ffitype) == '<ffi type struct foo>'
+        assert descr.ffitype.sizeof() == longsize*2
+        raises(ValueError, "descr.define_fields(fields)")
+
+    def test_pointer_to_incomplete_struct(self):
+        from _ffi import _StructDescr, Field, types
+        longsize = types.slong.sizeof()
+        fields = [
+            Field('x', types.slong),
+            Field('y', types.slong),
+            ]
+        descr = _StructDescr('foo')
+        foo_ffitype = descr.ffitype
+        foo_p = types.Pointer(descr.ffitype)
+        assert foo_p.deref_pointer() is foo_ffitype
+        descr.define_fields(fields)
+        assert descr.ffitype is foo_ffitype
+        assert foo_p.deref_pointer() is foo_ffitype
+        assert types.Pointer(descr.ffitype) is foo_p
+
+    def test_nested_structure(self):
+        from _ffi import _StructDescr, Field, types
+        longsize = types.slong.sizeof()
+        foo_fields = [
+            Field('x', types.slong),
+            Field('y', types.slong),
+            ]
+        foo_descr = _StructDescr('foo', foo_fields)
+        #
+        bar_fields = [
+            Field('x', types.slong),
+            Field('foo', foo_descr.ffitype),
+            ]
+        bar_descr = _StructDescr('bar', bar_fields)
+        assert bar_descr.ffitype.sizeof() == longsize*3
+        #
+        struct = bar_descr.allocate()
+        struct.setfield('x', 40)
+        # reading a nested structure yields a reference to it
+        struct_foo = struct.getfield('foo')
+        struct_foo.setfield('x', 41)
+        struct_foo.setfield('y', 42)
+        mem = self.read_raw_mem(struct.getaddr(), 'c_long', 3)
+        assert mem == [40, 41, 42]
+        #
+        struct_foo2 = foo_descr.allocate()
+        struct_foo2.setfield('x', 141)
+        struct_foo2.setfield('y', 142)
+        # writing a nested structure copies its memory into the target
+        struct.setfield('foo', struct_foo2)
+        struct_foo2.setfield('x', 241)
+        struct_foo2.setfield('y', 242)
+        mem = self.read_raw_mem(struct.getaddr(), 'c_long', 3)
+        assert mem == [40, 141, 142]
+        mem = self.read_raw_mem(struct_foo2.getaddr(), 'c_long', 2)
+        assert mem == [241, 242]
+
+
+
+    def test_compute_shape(self):
+        from _ffi import Structure, Field, types
+        class Point(Structure):
+            _fields_ = [
+                Field('x', types.slong),
+                Field('y', types.slong),
+                ]
+
+        longsize = types.slong.sizeof()
+        assert isinstance(Point.x, Field)
+        assert isinstance(Point.y, Field)
+        assert Point.x.offset == 0
+        assert Point.y.offset == longsize
+        assert Point._struct_.ffitype.sizeof() == longsize*2
+        assert Point._struct_.ffitype.name == 'struct Point'
+
diff --git a/pypy/module/_ffi/test/test_type_converter.py b/pypy/module/_ffi/test/test_type_converter.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/_ffi/test/test_type_converter.py
@@ -0,0 +1,170 @@
+import sys
+from pypy.conftest import gettestobjspace
+from pypy.rlib.rarithmetic import r_uint, r_singlefloat, r_longlong, r_ulonglong
+from pypy.rlib.libffi import IS_32_BIT
+from pypy.module._ffi.interp_ffitype import app_types, descr_new_pointer
+from pypy.module._ffi.type_converter import FromAppLevelConverter, ToAppLevelConverter
+
+class DummyFromAppLevelConverter(FromAppLevelConverter):
+
+    def handle_all(self, w_ffitype, w_obj, val):
+        self.lastval = val
+
+    handle_signed = handle_all
+    handle_unsigned = handle_all
+    handle_pointer = handle_all
+    handle_char = handle_all        
+    handle_unichar = handle_all
+    handle_longlong = handle_all
+    handle_char_p = handle_all
+    handle_unichar_p = handle_all
+    handle_float = handle_all
+    handle_singlefloat = handle_all
+    
+    def handle_struct(self, w_ffitype, w_structinstance):
+        self.lastval = w_structinstance
+
+    def convert(self, w_ffitype, w_obj):
+        self.unwrap_and_do(w_ffitype, w_obj)
+        return self.lastval
+
+
+class TestFromAppLevel(object):
+
+    def setup_class(cls):
+        cls.space = gettestobjspace(usemodules=('_ffi',))
+        converter = DummyFromAppLevelConverter(cls.space)
+        cls.from_app_level = staticmethod(converter.convert)
+
+    def check(self, w_ffitype, w_obj, expected):
+        v = self.from_app_level(w_ffitype, w_obj)
+        assert v == expected
+        assert type(v) is type(expected)
+
+    def test_int(self):
+        self.check(app_types.sint, self.space.wrap(42), 42)
+        self.check(app_types.sint, self.space.wrap(sys.maxint+1), -sys.maxint-1)
+        self.check(app_types.sint, self.space.wrap(sys.maxint*2), -2)
+
+    def test_unsigned(self):
+        space = self.space
+        self.check(app_types.uint, space.wrap(42), r_uint(42))
+        self.check(app_types.uint, space.wrap(-1), r_uint(sys.maxint*2 +1))
+        self.check(app_types.uint, space.wrap(sys.maxint*3),
+                   r_uint(sys.maxint - 2))
+        self.check(app_types.ulong, space.wrap(sys.maxint+12),
+                   r_uint(sys.maxint+12))
+        self.check(app_types.ulong, space.wrap(sys.maxint*2+3), r_uint(1))
+
+    def test_char(self):
+        space = self.space
+        self.check(app_types.char, space.wrap('a'), ord('a'))
+        self.check(app_types.unichar, space.wrap(u'\u1234'), 0x1234)
+
+    def test_signed_longlong(self):
+        space = self.space
+        maxint32 = 2147483647 # we cannot really go above maxint on 64 bits
+                              # (and we would not test anything, as there long
+                              # is the same as long long)
+        expected = maxint32+1
+        if IS_32_BIT:
+            expected = r_longlong(expected)
+        self.check(app_types.slonglong, space.wrap(maxint32+1), expected)
+
+    def test_unsigned_longlong(self):
+        space = self.space
+        maxint64 = 9223372036854775807 # maxint64+1 does not fit into a
+                                       # longlong, but it does into a
+                                       # ulonglong
+        if IS_32_BIT:
+            # internally, the type converter always casts to signed longlongs
+            expected = r_longlong(-maxint64-1)
+        else:
+            # on 64 bit, ulonglong == uint (i.e., unsigned long in C terms)
+            expected = r_uint(maxint64+1)
+        self.check(app_types.ulonglong, space.wrap(maxint64+1), expected)
+
+    def test_float_and_double(self):
+        space = self.space
+        self.check(app_types.float, space.wrap(12.34), r_singlefloat(12.34))
+        self.check(app_types.double, space.wrap(12.34), 12.34)
+
+    def test_pointer(self):
+        # pointers are "unsigned" at applevel, but signed at interp-level (for
+        # no good reason, at interp-level Signed or Unsigned makes no
+        # difference for passing bits around)
+        space = self.space
+        self.check(app_types.void_p, space.wrap(42), 42)
+        self.check(app_types.void_p, space.wrap(sys.maxint+1), -sys.maxint-1)
+        #
+        # typed pointers
+        w_ptr_sint = descr_new_pointer(space, None, app_types.sint)
+        self.check(w_ptr_sint, space.wrap(sys.maxint+1), -sys.maxint-1)
+
+
+    def test__as_ffi_pointer_(self):
+        space = self.space
+        w_MyPointerWrapper = space.appexec([], """():
+            import _ffi
+            class MyPointerWrapper(object):
+                def __init__(self, value):
+                    self.value = value
+                def _as_ffi_pointer_(self, ffitype):
+                    assert ffitype is _ffi.types.void_p
+                    return self.value
+
+            return MyPointerWrapper
+        """)
+        w_obj = space.call_function(w_MyPointerWrapper, space.wrap(42))
+        self.check(app_types.void_p, w_obj, 42)
+
+    def test_strings(self):
+        # first, try automatic conversion from applevel
+        self.check(app_types.char_p, self.space.wrap('foo'), 'foo')
+        self.check(app_types.unichar_p, self.space.wrap(u'foo\u1234'), u'foo\u1234')    
+        self.check(app_types.unichar_p, self.space.wrap('foo'), u'foo')    
+        # then, try to pass explicit pointers
+        self.check(app_types.char_p, self.space.wrap(42), 42)
+        self.check(app_types.unichar_p, self.space.wrap(42), 42)        
+
+
+
+class DummyToAppLevelConverter(ToAppLevelConverter):
+
+    def get_all(self, w_ffitype):
+        return self.val
+
+    get_signed = get_all
+    get_unsigned = get_all
+    get_pointer = get_all
+    get_char = get_all        
+    get_unichar = get_all
+    get_longlong = get_all
+    get_char_p = get_all
+    get_unichar_p = get_all
+    get_float = get_all
+    get_singlefloat = get_all
+    
+    def convert(self, w_ffitype, val):
+        self.val = val
+        return self.do_and_wrap(w_ffitype)
+
+
+class TestFromAppLevel(object):
+
+    def setup_class(cls):
+        cls.space = gettestobjspace(usemodules=('_ffi',))
+        converter = DummyToAppLevelConverter(cls.space)
+        cls.from_app_level = staticmethod(converter.convert)
+
+    def check(self, w_ffitype, val, w_expected):
+        w_v = self.from_app_level(w_ffitype, val)
+        assert self.space.eq_w(w_v, w_expected)
+
+    def test_int(self):
+        self.check(app_types.sint, 42, self.space.wrap(42))
+        self.check(app_types.sint, -sys.maxint-1, self.space.wrap(-sys.maxint-1))
+
+    def test_uint(self):
+        self.check(app_types.uint, 42, self.space.wrap(42))
+        self.check(app_types.uint, r_uint(sys.maxint+1), self.space.wrap(sys.maxint+1))
diff --git a/pypy/module/_ffi/type_converter.py b/pypy/module/_ffi/type_converter.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/_ffi/type_converter.py
@@ -0,0 +1,366 @@
+from pypy.rlib import libffi
+from pypy.rlib import jit
+from pypy.rlib.rarithmetic import intmask, r_uint
+from pypy.rpython.lltypesystem import rffi
+from pypy.interpreter.error import operationerrfmt, OperationError
+from pypy.module._rawffi.structure import W_StructureInstance, W_Structure
+from pypy.module._ffi.interp_ffitype import app_types
+
+class FromAppLevelConverter(object):
+    """
+    Unwrap an app-level object to the corresponding low-level type, following
+    the conversion rules which apply to the specified w_ffitype.  Once
+    unwrapped, the value is passed to the corresponding handle_* method.
+    Subclasses should override the desired ones.
+    """
+
+    def __init__(self, space):
+        self.space = space
+
+    def unwrap_and_do(self, w_ffitype, w_obj):
+        from pypy.module._ffi.interp_struct import W__StructInstance
+        space = self.space
+        if w_ffitype.is_longlong():
+            # note that we must check for longlong first, because either
+            # is_signed or is_unsigned returns true anyway
+            assert libffi.IS_32_BIT
+            self._longlong(w_ffitype, w_obj)
+        elif w_ffitype.is_signed():
+            intval = space.truncatedint_w(w_obj)
+            self.handle_signed(w_ffitype, w_obj, intval)
+        elif self.maybe_handle_char_or_unichar_p(w_ffitype, w_obj):
+            # the object was already handled from within
+            # maybe_handle_char_or_unichar_p
+            pass
+        elif w_ffitype.is_pointer():
+            w_obj = self.convert_pointer_arg_maybe(w_obj, w_ffitype)
+            intval = space.truncatedint_w(w_obj)
+            self.handle_pointer(w_ffitype, w_obj, intval)
+        elif w_ffitype.is_unsigned():
+            uintval = r_uint(space.truncatedint_w(w_obj))
+            self.handle_unsigned(w_ffitype, w_obj, uintval)
+        elif w_ffitype.is_char():
+            intval = space.int_w(space.ord(w_obj))
+            self.handle_char(w_ffitype, w_obj, intval)
+        elif w_ffitype.is_unichar():
+            intval = space.int_w(space.ord(w_obj))
+            self.handle_unichar(w_ffitype, w_obj, intval)
+        elif w_ffitype.is_double():
+            self._float(w_ffitype, w_obj)
+        elif w_ffitype.is_singlefloat():
+            self._singlefloat(w_ffitype, w_obj)
+        elif w_ffitype.is_struct():
+            if isinstance(w_obj, W_StructureInstance):
+                self.handle_struct_rawffi(w_ffitype, w_obj)
+            else:
+                w_obj = space.interp_w(W__StructInstance, w_obj)
+                self.handle_struct(w_ffitype, w_obj)
+        else:
+            self.error(w_ffitype, w_obj)
+
+    def _longlong(self, w_ffitype, w_obj):
+        # a separate function, which can be seen by the jit or not,
+        # depending on whether longlongs are supported
+        longlongval = self.space.truncatedlonglong_w(w_obj)
+        self.handle_longlong(w_ffitype, w_obj, longlongval)
+
+    def _float(self, w_ffitype, w_obj):
+        # a separate function, which can be seen by the jit or not,
+        # depending on whether floats are supported
+        floatval = self.space.float_w(w_obj)
+        self.handle_float(w_ffitype, w_obj, floatval)
+
+    def _singlefloat(self, w_ffitype, w_obj):
+        # a separate function, which can be seen by the jit or not,
+        # depending on whether singlefloats are supported
+        from pypy.rlib.rarithmetic import r_singlefloat
+        floatval = self.space.float_w(w_obj)
+        singlefloatval = r_singlefloat(floatval)
+        self.handle_singlefloat(w_ffitype, w_obj, singlefloatval)
+
+    def maybe_handle_char_or_unichar_p(self, w_ffitype, w_obj):
+        w_type = jit.promote(self.space.type(w_obj))
+        if w_ffitype.is_char_p() and w_type is self.space.w_str:
+            strval = self.space.str_w(w_obj)
+            self.handle_char_p(w_ffitype, w_obj, strval)
+            return True
+        elif w_ffitype.is_unichar_p() and (w_type is self.space.w_str or
+                                           w_type is self.space.w_unicode):
+            unicodeval = self.space.unicode_w(w_obj)
+            self.handle_unichar_p(w_ffitype, w_obj, unicodeval)
+            return True
+        return False
+
+    def convert_pointer_arg_maybe(self, w_arg, w_argtype):
+        """
+        Try to convert the argument by calling _as_ffi_pointer_()
+        """
+        space = self.space
+        meth = space.lookup(w_arg, '_as_ffi_pointer_') # this also promotes the type
+        if meth:
+            return space.call_function(meth, w_arg, w_argtype)
+        else:
+            return w_arg
+
+    def error(self, w_ffitype, w_obj):
+        raise operationerrfmt(self.space.w_TypeError,
+                              'Unsupported ffi type to convert: %s',
+                              w_ffitype.name)
+
+    def handle_signed(self, w_ffitype, w_obj, intval):
+        """
+        intval: lltype.Signed
+        """
+        self.error(w_ffitype, w_obj)
+
+    def handle_unsigned(self, w_ffitype, w_obj, uintval):
+        """
+        uintval: lltype.Unsigned
+        """
+        self.error(w_ffitype, w_obj)
+
+    def handle_pointer(self, w_ffitype, w_obj, intval):
+        """
+        intval: lltype.Signed
+        """
+        self.error(w_ffitype, w_obj)
+
+    def handle_char(self, w_ffitype, w_obj, intval):
+        """
+        intval: lltype.Signed
+        """
+        self.error(w_ffitype, w_obj)
+        
+    def handle_unichar(self, w_ffitype, w_obj, intval):
+        """
+        intval: lltype.Signed
+        """
+        self.error(w_ffitype, w_obj)
+
+    def handle_longlong(self, w_ffitype, w_obj, longlongval):
+        """
+        longlongval: lltype.SignedLongLong
+        """
+        self.error(w_ffitype, w_obj)
+
+    def handle_char_p(self, w_ffitype, w_obj, strval):
+        """
+        strval: interp-level str
+        """
+        self.error(w_ffitype, w_obj)
+
+    def handle_unichar_p(self, w_ffitype, w_obj, unicodeval):
+        """
+        unicodeval: interp-level unicode
+        """
+        self.error(w_ffitype, w_obj)
+
+    def handle_float(self, w_ffitype, w_obj, floatval):
+        """
+        floatval: lltype.Float
+        """
+        self.error(w_ffitype, w_obj)
+
+    def handle_singlefloat(self, w_ffitype, w_obj, singlefloatval):
+        """
+        singlefloatval: lltype.SingleFloat
+        """
+        self.error(w_ffitype, w_obj)
+
+    def handle_struct(self, w_ffitype, w_structinstance):
+        """
+        w_structinstance: W_StructureInstance
+        """
+        self.error(w_ffitype, w_structinstance)
+
+    def handle_struct_rawffi(self, w_ffitype, w_structinstance):
+        """
+        This method should be killed as soon as we remove support for _rawffi structures
+        
+        w_structinstance: W_StructureInstance
+        """
+        self.error(w_ffitype, w_structinstance)
+
+
+
+class ToAppLevelConverter(object):
+    """
+    Wrap a low-level value to an app-level object, following the conversion
+    rules which apply to the specified w_ffitype.  The value is got by calling
+    the get_* method corresponding to the w_ffitype. Subclasses should
+    override the desired ones.
+    """
+
+    def __init__(self, space):
+        self.space = space
+
+    def do_and_wrap(self, w_ffitype):
+        from pypy.module._ffi.interp_struct import W__StructDescr
+        space = self.space
+        if w_ffitype.is_longlong():
+            # note that we must check for longlong first, because either
+            # is_signed or is_unsigned returns true anyway
+            assert libffi.IS_32_BIT
+            return self._longlong(w_ffitype)
+        elif w_ffitype.is_signed():
+            intval = self.get_signed(w_ffitype)
+            return space.wrap(intval)
+        elif (w_ffitype is app_types.ulonglong or
+              w_ffitype is app_types.ulong or (libffi.IS_32_BIT and
+                                               w_ffitype is app_types.uint)):
+            # Note that we the second check (for ulonglong) is meaningful only
+            # on 64 bit, because on 32 bit the ulonglong case would have been
+            # handled by the is_longlong() branch above. On 64 bit, ulonglong
+            # is essentially the same as ulong.
+            #
+            # We need to be careful when the return type is ULONG, because the
+            # value might not fit into a signed LONG, and thus might require
+            # and app-evel <long>.  This is why we need to treat it separately
+            # than the other unsigned types.
+            uintval = self.get_unsigned(w_ffitype)
+            return space.wrap(uintval)
+        elif w_ffitype.is_unsigned(): # note that ulong is handled just before
+            intval = self.get_unsigned_which_fits_into_a_signed(w_ffitype)
+            return space.wrap(intval)
+        elif w_ffitype.is_pointer():
+            uintval = self.get_pointer(w_ffitype)
+            return space.wrap(uintval)
+        elif w_ffitype.is_char():
+            ucharval = self.get_char(w_ffitype)
+            return space.wrap(chr(ucharval))
+        elif w_ffitype.is_unichar():
+            wcharval = self.get_unichar(w_ffitype)
+            return space.wrap(unichr(wcharval))
+        elif w_ffitype.is_double():
+            return self._float(w_ffitype)
+        elif w_ffitype.is_singlefloat():
+            return self._singlefloat(w_ffitype)
+        elif w_ffitype.is_struct():
+            w_structdescr = w_ffitype.w_structdescr
+            if isinstance(w_structdescr, W__StructDescr):
+                return self.get_struct(w_ffitype, w_structdescr)
+            elif isinstance(w_structdescr, W_Structure):
+                return self.get_struct_rawffi(w_ffitype, w_structdescr)
+            else:
+                raise OperationError(self.space.w_TypeError,
+                                     self.space.wrap("Unsupported struct shape"))
+        elif w_ffitype.is_void():
+            voidval = self.get_void(w_ffitype)
+            assert voidval is None
+            return space.w_None
+        else:
+            self.error(w_ffitype)
+
+    def _longlong(self, w_ffitype):
+        # a separate function, which can be seen by the jit or not,
+        # depending on whether longlongs are supported
+        if w_ffitype is app_types.slonglong:
+            longlongval = self.get_longlong(w_ffitype)
+            return self.space.wrap(longlongval)
+        elif w_ffitype is app_types.ulonglong:
+            ulonglongval = self.get_ulonglong(w_ffitype)
+            return self.space.wrap(ulonglongval)
+        else:
+            self.error(w_ffitype)
+
+    def _float(self, w_ffitype):
+        # a separate function, which can be seen by the jit or not,
+        # depending on whether floats are supported
+        floatval = self.get_float(w_ffitype)
+        return self.space.wrap(floatval)
+
+    def _singlefloat(self, w_ffitype):
+        # a separate function, which can be seen by the jit or not,
+        # depending on whether singlefloats are supported
+        singlefloatval = self.get_singlefloat(w_ffitype)
+        return self.space.wrap(float(singlefloatval))
+
+    def error(self, w_ffitype):
+        raise operationerrfmt(self.space.w_TypeError,
+                              'Unsupported ffi type to convert: %s',
+                              w_ffitype.name)
+
+    def get_longlong(self, w_ffitype):
+        """
+        Return type: lltype.SignedLongLong
+        """
+        self.error(w_ffitype)
+
+    def get_ulonglong(self, w_ffitype):
+        """
+        Return type: lltype.UnsignedLongLong
+        """
+        self.error(w_ffitype)
+
+    def get_signed(self, w_ffitype):
+        """
+        Return type: lltype.Signed
+        """
+        self.error(w_ffitype)
+
+    def get_unsigned(self, w_ffitype):
+        """
+        Return type: lltype.Unsigned
+        """
+        self.error(w_ffitype)
+
+    def get_unsigned_which_fits_into_a_signed(self, w_ffitype):
+        """
+        Return type: lltype.Signed.
+        
+        We return Signed even if the input type is unsigned, because this way
+        we get an app-level <int> instead of a <long>.
+        """
+        self.error(w_ffitype)
+
+    def get_pointer(self, w_ffitype):
+        """
+        Return type: lltype.Unsigned
+        """
+        self.error(w_ffitype)
+
+    def get_char(self, w_ffitype):
+        """
+        Return type: rffi.UCHAR
+        """
+        self.error(w_ffitype)
+
+    def get_unichar(self, w_ffitype):
+        """
+        Return type: rffi.WCHAR_T
+        """
+        self.error(w_ffitype)
+
+    def get_float(self, w_ffitype):
+        """
+        Return type: lltype.Float
+        """
+        self.error(w_ffitype)
+
+    def get_singlefloat(self, w_ffitype):
+        """
+        Return type: lltype.SingleFloat
+        """
+        self.error(w_ffitype)
+
+    def get_struct(self, w_ffitype, w_structdescr):
+        """
+        Return type: lltype.Signed
+        (the address of the structure)
+        """
+        self.error(w_ffitype)
+
+    def get_struct_rawffi(self, w_ffitype, w_structdescr):
+        """
+        This should be killed as soon as we kill support for _rawffi structures
+        
+        Return type: lltype.Unsigned
+        (the address of the structure)
+        """
+        self.error(w_ffitype)
+
+    def get_void(self, w_ffitype):
+        """
+        Return type: None
+        """
+        self.error(w_ffitype)
diff --git a/pypy/module/_rawffi/interp_rawffi.py b/pypy/module/_rawffi/interp_rawffi.py
--- a/pypy/module/_rawffi/interp_rawffi.py
+++ b/pypy/module/_rawffi/interp_rawffi.py
@@ -253,7 +253,7 @@
         # XXX: this assumes that you have the _ffi module enabled. In the long
         # term, probably we will move the code for build structures and arrays
         # from _rawffi to _ffi
-        from pypy.module._ffi.interp_ffi import W_FFIType
+        from pypy.module._ffi.interp_ffitype import W_FFIType
         return W_FFIType('<unknown>', self.get_basic_ffi_type(), self)
 
     @unwrap_spec(n=int)
diff --git a/pypy/module/binascii/interp_crc32.py b/pypy/module/binascii/interp_crc32.py
--- a/pypy/module/binascii/interp_crc32.py
+++ b/pypy/module/binascii/interp_crc32.py
@@ -61,7 +61,7 @@
 crc_32_tab = map(r_uint, crc_32_tab)
 
 
- at unwrap_spec(data='bufferstr', oldcrc='truncatedint')
+ at unwrap_spec(data='bufferstr', oldcrc='truncatedint_w')
 def crc32(space, data, oldcrc=0):
     "Compute the CRC-32 incrementally."
 
diff --git a/pypy/module/micronumpy/signature.py b/pypy/module/micronumpy/signature.py
--- a/pypy/module/micronumpy/signature.py
+++ b/pypy/module/micronumpy/signature.py
@@ -441,7 +441,11 @@
         ofs = frame.iterators[0].offset
         arr.left.setitem(ofs, self.right.eval(frame, arr.right).convert_to(
             self.calc_dtype))
-    
+
+    def _invent_numbering(self, cache, allnumbers):
+        self.left._invent_numbering(new_cache(), allnumbers)
+        self.right._invent_numbering(cache, allnumbers)
+
     def debug_repr(self):
         return 'SliceLoop(%s, %s, %s)' % (self.name, self.left.debug_repr(),
                                           self.right.debug_repr())
diff --git a/pypy/module/micronumpy/test/test_dtypes.py b/pypy/module/micronumpy/test/test_dtypes.py
--- a/pypy/module/micronumpy/test/test_dtypes.py
+++ b/pypy/module/micronumpy/test/test_dtypes.py
@@ -212,6 +212,30 @@
         b = array([0] * 10, dtype=int64)
         for idx in b: a[idx] += 1
 
+    def test_hash_int8(self):
+        from _numpypy import int8
+
+        hash(int8(0))
+        d = {int8(5):99}
+
+    def test_hash_int16(self):
+        from _numpypy import int16
+
+        hash(int16(0))
+        d = {int16(99):42}
+
+    def test_hash_int32(self):
+        from _numpypy import int32
+
+        hash(int32(0))
+        d = {int32(5):99}
+
+    def test_hash_int64(self):
+        from _numpypy import int64
+
+        hash(int64(0))
+        d = {int64(99):42}
+
 class AppTestTypes(BaseNumpyAppTest):    
     def test_abstract_types(self):
         import _numpypy as numpy
diff --git a/pypy/module/micronumpy/test/test_numarray.py b/pypy/module/micronumpy/test/test_numarray.py
--- a/pypy/module/micronumpy/test/test_numarray.py
+++ b/pypy/module/micronumpy/test/test_numarray.py
@@ -1530,6 +1530,12 @@
         # test virtual
         assert ((x + x).swapaxes(0,1) == array([[[ 2,  4,  6], [14, 16, 18]], 
                                          [[ 8, 10, 12], [20, 22, 24]]])).all()
+
+    def test_filter_bug(self):
+        from numpypy import array
+        a = array([1.0,-1.0])
+        a[a<0] = -a[a<0]
+        assert (a == [1, 1]).all()
                         
 class AppTestMultiDim(BaseNumpyAppTest):
     def test_init(self):
diff --git a/pypy/module/posix/__init__.py b/pypy/module/posix/__init__.py
--- a/pypy/module/posix/__init__.py
+++ b/pypy/module/posix/__init__.py
@@ -86,6 +86,8 @@
     '_exit'     : 'interp_posix._exit',
     'utime'     : 'interp_posix.utime',
     '_statfields': 'interp_posix.getstatfields(space)',
+    'kill'      : 'interp_posix.kill',
+    'abort'     : 'interp_posix.abort',
     }
 
     if os.name == 'nt':
@@ -107,9 +109,6 @@
         interpleveldefs['putenv'] = 'interp_posix.putenv'
     if hasattr(posix, 'unsetenv'): # note: emulated in os
         interpleveldefs['unsetenv'] = 'interp_posix.unsetenv'
-    if hasattr(os, 'kill') and sys.platform != 'win32':
-        interpleveldefs['kill'] = 'interp_posix.kill'
-        interpleveldefs['abort'] = 'interp_posix.abort'
     if hasattr(os, 'killpg'):
         interpleveldefs['killpg'] = 'interp_posix.killpg'
     if hasattr(os, 'getpid'):
diff --git a/pypy/module/posix/app_posix.py b/pypy/module/posix/app_posix.py
--- a/pypy/module/posix/app_posix.py
+++ b/pypy/module/posix/app_posix.py
@@ -1,5 +1,6 @@
 # NOT_RPYTHON
 from _structseq import structseqtype, structseqfield
+from __pypy__ import validate_fd
 
 # XXX we need a way to access the current module's globals more directly...
 import sys
@@ -73,9 +74,7 @@
         except IOError as e:
             raise OSError(e.errno, e.strerror, e.filename)
 else:
-    def _validate_fd(fd):
-        # XXX for the moment
-        return
+    _validate_fd = validate_fd
 
 if osname == 'posix':
     def wait():
diff --git a/pypy/module/posix/interp_posix.py b/pypy/module/posix/interp_posix.py
--- a/pypy/module/posix/interp_posix.py
+++ b/pypy/module/posix/interp_posix.py
@@ -621,7 +621,7 @@
 def kill(space, pid, sig):
     "Kill a process with a signal."
     try:
-        os.kill(pid, sig)
+        rposix.os_kill(pid, sig)
     except OSError, e:
         raise wrap_oserror(space, e)
 
@@ -637,7 +637,7 @@
     """Abort the interpreter immediately.  This 'dumps core' or otherwise fails
 in the hardest way possible on the hosting operating system."""
     import signal
-    os.kill(os.getpid(), signal.SIGABRT)
+    rposix.os_kill(os.getpid(), signal.SIGABRT)
 
 @unwrap_spec(src='str0', dst='str0')
 def link(space, src, dst):
@@ -747,22 +747,7 @@
         path: path of executable file
         args: iterable of strings
     """
-    command = fsencode_w(space, w_command)
-    try:
-        args_w = space.unpackiterable(w_args)
-        if len(args_w) < 1:
-            w_msg = space.wrap("execv() must have at least one argument")
-            raise OperationError(space.w_ValueError, w_msg)
-        args = [fsencode_w(space, w_arg) for w_arg in args_w]
-    except OperationError, e:
-        if not e.match(space, space.w_TypeError):
-            raise
-        msg = "execv() arg 2 must be an iterable of strings"
-        raise OperationError(space.w_TypeError, space.wrap(str(msg)))
-    try:
-        os.execv(command, args)
-    except OSError, e:
-        raise wrap_oserror(space, e)
+    execve(space, w_command, w_args, None)
 
 def _env2interp(space, w_env):
     env = {}
@@ -782,12 +767,29 @@
         env: dictionary of strings mapping to strings
     """
     command = fsencode_w(space, w_command)
-    args = [fsencode_w(space, w_arg) for w_arg in space.unpackiterable(w_args)]
-    env = _env2interp(space, w_env)
     try:
-        os.execve(command, args, env)
-    except OSError, e:
-        raise wrap_oserror(space, e)
+        args_w = space.unpackiterable(w_args)
+        if len(args_w) < 1:
+            w_msg = space.wrap("execv() must have at least one argument")
+            raise OperationError(space.w_ValueError, w_msg)
+        args = [fsencode_w(space, w_arg) for w_arg in args_w]
+    except OperationError, e:
+        if not e.match(space, space.w_TypeError):
+            raise
+        msg = "execv() arg 2 must be an iterable of strings"
+        raise OperationError(space.w_TypeError, space.wrap(str(msg)))
+    #
+    if w_env is None:    # when called via execv() above
+        try:
+            os.execv(command, args)
+        except OSError, e:
+            raise wrap_oserror(space, e)
+    else:
+        env = _env2interp(space, w_env)
+        try:
+            os.execve(command, args, env)
+        except OSError, e:
+            raise wrap_oserror(space, e)
 
 @unwrap_spec(mode=int, path='str0')
 def spawnv(space, mode, path, w_args):
diff --git a/pypy/module/posix/test/test_posix2.py b/pypy/module/posix/test/test_posix2.py
--- a/pypy/module/posix/test/test_posix2.py
+++ b/pypy/module/posix/test/test_posix2.py
@@ -384,6 +384,7 @@
         def test_execv_no_args(self):
             os = self.posix
             raises(ValueError, os.execv, "notepad", [])
+            raises(ValueError, os.execve, "notepad", [], {})
 
         def test_execv_raising2(self):
             os = self.posix
@@ -454,12 +455,11 @@
     if hasattr(__import__(os.name), "spawnve"):
         def test_spawnve(self):
             os = self.posix
-            import sys
-            print(self.python)
+            env = {'PATH':os.environ['PATH'], 'FOOBAR': '42'}
             ret = os.spawnve(os.P_WAIT, self.python,
                              ['python', '-c',
                               "raise(SystemExit(int(__import__('os').environ['FOOBAR'])))"],
-                             {'FOOBAR': '42'})
+                             env)
             assert ret == 42
 
     if hasattr(__import__(os.name), '_getfullpathname'):
@@ -839,6 +839,71 @@
             # How else could we test that getlogin is properly
             # working?
 
+    def test_tmpfile(self):
+        os = self.posix
+        f = os.tmpfile()
+        f.write("xxx")
+        f.flush()
+        f.seek(0, 0)
+        assert isinstance(f, file)
+        assert f.read() == 'xxx'
+
+    def test_tmpnam(self):
+        import stat, os
+        s1 = os.tmpnam()
+        s2 = os.tmpnam()
+        assert s1 != s2
+        def isdir(s):
+            try:
+                return stat.S_ISDIR(os.stat(s).st_mode)
+            except OSError:
+                return -1
+        assert isdir(s1) == -1
+        assert isdir(s2) == -1
+        assert isdir(os.path.dirname(s1)) == 1
+        assert isdir(os.path.dirname(s2)) == 1
+
+    def test_tempnam(self):
+        import stat, os
+        for dir in [None, self.udir]:
+            for prefix in [None, 'foobar']:
+                s1 = os.tempnam(dir, prefix)
+                s2 = os.tempnam(dir, prefix)
+                assert s1 != s2
+                def isdir(s):
+                    try:
+                        return stat.S_ISDIR(os.stat(s).st_mode)
+                    except OSError:
+                        return -1
+                assert isdir(s1) == -1
+                assert isdir(s2) == -1
+                assert isdir(os.path.dirname(s1)) == 1
+                assert isdir(os.path.dirname(s2)) == 1
+                if dir:
+                    assert os.path.dirname(s1) == dir
+                    assert os.path.dirname(s2) == dir
+                assert os.path.basename(s1).startswith(prefix or 'tmp')
+                assert os.path.basename(s2).startswith(prefix or 'tmp')
+
+    def test_tmpnam_warning(self):
+        import warnings, os
+        #
+        def f_tmpnam_warning(): os.tmpnam()    # a single line
+        #
+        with warnings.catch_warnings(record=True) as w:
+            warnings.simplefilter("always")
+            f_tmpnam_warning()
+            assert len(w) == 1
+            assert issubclass(w[-1].category, RuntimeWarning)
+            assert "potential security risk" in str(w[-1].message)
+            # check that the warning points to the call to os.tmpnam(),
+            # not to some code inside app_posix.py
+            assert w[-1].lineno == f_tmpnam_warning.func_code.co_firstlineno
+
+    def test_has_kill(self):
+        import os
+        assert hasattr(os, 'kill')
+
 class AppTestEnvironment(object):
     def setup_class(cls):
         cls.space = space
diff --git a/pypy/module/pypyjit/test_pypy_c/test__ffi.py b/pypy/module/pypyjit/test_pypy_c/test__ffi.py
--- a/pypy/module/pypyjit/test_pypy_c/test__ffi.py
+++ b/pypy/module/pypyjit/test_pypy_c/test__ffi.py
@@ -134,3 +134,31 @@
         call = ops[idx]
         assert (call.args[0] == 'ConstClass(fabs)' or    # e.g. OS/X
                 int(call.args[0]) == fabs_addr)
+
+
+    def test__ffi_struct(self):
+        def main():
+            from _ffi import _StructDescr, Field, types
+            fields = [
+                Field('x', types.slong),
+                ]
+            descr = _StructDescr('foo', fields)
+            struct = descr.allocate()
+            i = 0
+            while i < 300:
+                x = struct.getfield('x')   # ID: getfield
+                x = x+1
+                struct.setfield('x', x)    # ID: setfield
+                i += 1
+            return struct.getfield('x')
+        #
+        log = self.run(main, [])
+        loop, = log.loops_by_filename(self.filepath)
+        assert loop.match_by_id('getfield', """
+            guard_not_invalidated(descr=...)
+            i57 = getfield_raw(i46, descr=<FieldS dynamic 0>)
+        """)
+        assert loop.match_by_id('setfield', """
+            setfield_raw(i44, i57, descr=<FieldS dynamic 0>)
+        """)
+
diff --git a/pypy/module/pypyjit/test_pypy_c/test_misc.py b/pypy/module/pypyjit/test_pypy_c/test_misc.py
--- a/pypy/module/pypyjit/test_pypy_c/test_misc.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_misc.py
@@ -131,6 +131,36 @@
             jump(..., descr=...)
             """)
 
+    def test_xrange_iter(self):
+        def main(n):
+            def g(n):
+                return xrange(n)
+            s = 0
+            for i in xrange(n):  # ID: for
+                tmp = g(n)
+                s += tmp[i]     # ID: getitem
+                a = 0
+            return s
+        #
+        log = self.run(main, [1000])
+        assert log.result == 1000 * 999 / 2
+        loop, = log.loops_by_filename(self.filepath)
+        assert loop.match("""
+        i15 = int_lt(i10, i11)
+        guard_true(i15, descr=...)
+        i17 = int_add(i10, 1)
+        i18 = force_token()
+        setfield_gc(p9, i17, descr=<.* .*W_XRangeIterator.inst_current .*>)
+        guard_not_invalidated(descr=...)
+        i21 = int_lt(i10, 0)
+        guard_false(i21, descr=...)
+        i22 = int_lt(i10, i14)
+        guard_true(i22, descr=...)
+        i23 = int_add_ovf(i6, i10)
+        guard_no_overflow(descr=...)
+        --TICK--
+        jump(..., descr=...)
+        """)
 
     def test_range_iter(self):
         def main(n):
diff --git a/pypy/module/select/interp_kqueue.py b/pypy/module/select/interp_kqueue.py
--- a/pypy/module/select/interp_kqueue.py
+++ b/pypy/module/select/interp_kqueue.py
@@ -3,6 +3,7 @@
 from pypy.interpreter.gateway import interp2app, unwrap_spec
 from pypy.interpreter.typedef import TypeDef, generic_new_descr, GetSetProperty
 from pypy.rlib._rsocket_rffi import socketclose
+from pypy.rlib.rarithmetic import r_uint
 from pypy.rpython.lltypesystem import rffi, lltype
 from pypy.rpython.tool import rffi_platform
 from pypy.translator.tool.cbuild import ExternalCompilationInfo
@@ -226,9 +227,12 @@
         if self.event:
             lltype.free(self.event, flavor="raw")
 
-    @unwrap_spec(filter=int, flags='c_uint', fflags='c_uint', data=int, udata='c_uint')
-    def descr__init__(self, space, w_ident, filter=KQ_FILTER_READ, flags=KQ_EV_ADD, fflags=0, data=0, udata=0):
-        ident = space.c_filedescriptor_w(w_ident)
+    @unwrap_spec(filter=int, flags='c_uint', fflags='c_uint', data=int, udata=r_uint)
+    def descr__init__(self, space, w_ident, filter=KQ_FILTER_READ, flags=KQ_EV_ADD, fflags=0, data=0, udata=r_uint(0)):
+        if space.isinstance_w(w_ident, space.w_long):
+            ident = space.uint_w(w_ident)
+        else:
+            ident = r_uint(space.c_filedescriptor_w(w_ident))
 
         self.event = lltype.malloc(kevent, flavor="raw")
         rffi.setintfield(self.event, "c_ident", ident)
@@ -320,7 +324,7 @@
         return space.wrap(self.event.c_data)
 
     def descr_get_udata(self, space):
-        return space.wrap(rffi.cast(rffi.SIZE_T, self.event.c_udata))
+        return space.wrap(rffi.cast(rffi.UINTPTR_T, self.event.c_udata))
 
 
 W_Kevent.typedef = TypeDef("select.kevent",
diff --git a/pypy/module/select/interp_select.py b/pypy/module/select/interp_select.py
--- a/pypy/module/select/interp_select.py
+++ b/pypy/module/select/interp_select.py
@@ -74,6 +74,32 @@
     pollmethods[methodname] = interp2app(getattr(Poll, methodname))
 Poll.typedef = TypeDef('select.poll', **pollmethods)
 
+# ____________________________________________________________
+
+
+from pypy.rlib import _rsocket_rffi as _c
+from pypy.rpython.lltypesystem import lltype, rffi
+
+
+def _build_fd_set(space, list_w, ll_list, nfds):
+    _c.FD_ZERO(ll_list)
+    fdlist = []
+    for w_f in list_w:
+        fd = space.c_filedescriptor_w(w_f)
+        if fd > nfds:
+            nfds = fd
+        _c.FD_SET(fd, ll_list)
+        fdlist.append(fd)
+    return fdlist, nfds
+_build_fd_set._always_inline_ = True    # get rid of the tuple result
+
+def _unbuild_fd_set(space, list_w, fdlist, ll_list, reslist_w):
+    for i in range(len(fdlist)):
+        fd = fdlist[i]
+        if _c.FD_ISSET(fd, ll_list):
+            reslist_w.append(list_w[i])
+
+
 def select(space, w_iwtd, w_owtd, w_ewtd, w_timeout=None):
     """Wait until one or more file descriptors are ready for some kind of I/O.
 The first three arguments are sequences of file descriptors to be waited for:
@@ -99,29 +125,62 @@
     iwtd_w = space.listview(w_iwtd)
     owtd_w = space.listview(w_owtd)
     ewtd_w = space.listview(w_ewtd)
-    iwtd = [space.c_filedescriptor_w(w_f) for w_f in iwtd_w]
-    owtd = [space.c_filedescriptor_w(w_f) for w_f in owtd_w]
-    ewtd = [space.c_filedescriptor_w(w_f) for w_f in ewtd_w]
-    iwtd_d = {}
-    owtd_d = {}
-    ewtd_d = {}
-    for i in range(len(iwtd)):
-        iwtd_d[iwtd[i]] = iwtd_w[i]
-    for i in range(len(owtd)):
-        owtd_d[owtd[i]] = owtd_w[i]
-    for i in range(len(ewtd)):
-        ewtd_d[ewtd[i]] = ewtd_w[i]
+
+    ll_inl  = lltype.nullptr(_c.fd_set.TO)
+    ll_outl = lltype.nullptr(_c.fd_set.TO)
+    ll_errl = lltype.nullptr(_c.fd_set.TO)
+    ll_timeval = lltype.nullptr(_c.timeval)
+    
     try:
+        fdlistin  = None
+        fdlistout = None
+        fdlisterr = None
+        nfds = -1
+        if len(iwtd_w) > 0:
+            ll_inl = lltype.malloc(_c.fd_set.TO, flavor='raw')
+            fdlistin, nfds = _build_fd_set(space, iwtd_w, ll_inl, nfds)
+        if len(owtd_w) > 0:
+            ll_outl = lltype.malloc(_c.fd_set.TO, flavor='raw')
+            fdlistout, nfds = _build_fd_set(space, owtd_w, ll_outl, nfds)
+        if len(ewtd_w) > 0:
+            ll_errl = lltype.malloc(_c.fd_set.TO, flavor='raw')
+            fdlisterr, nfds = _build_fd_set(space, ewtd_w, ll_errl, nfds)
+
         if space.is_w(w_timeout, space.w_None):
-            iwtd, owtd, ewtd = rpoll.select(iwtd, owtd, ewtd)
+            timeout = -1.0
         else:
-            iwtd, owtd, ewtd = rpoll.select(iwtd, owtd, ewtd, space.float_w(w_timeout))
-    except rpoll.SelectError, s:
-        w_errortype = space.fromcache(Cache).w_error
-        raise OperationError(w_errortype, space.newtuple([
-            space.wrap(s.errno), space.wrap(s.get_msg())]))
+            timeout = space.float_w(w_timeout)
+        if timeout >= 0.0:
+            ll_timeval = rffi.make(_c.timeval)
+            i = int(timeout)
+            rffi.setintfield(ll_timeval, 'c_tv_sec', i)
+            rffi.setintfield(ll_timeval, 'c_tv_usec', int((timeout-i)*1000000))
 
-    return space.newtuple([
-        space.newlist([iwtd_d[i] for i in iwtd]),
-        space.newlist([owtd_d[i] for i in owtd]),
-        space.newlist([ewtd_d[i] for i in ewtd])])
+        res = _c.select(nfds + 1, ll_inl, ll_outl, ll_errl, ll_timeval)
+
+        if res < 0:
+            errno = _c.geterrno()
+            msg = _c.socket_strerror_str(errno)
+            w_errortype = space.fromcache(Cache).w_error
+            raise OperationError(w_errortype, space.newtuple([
+                space.wrap(errno), space.wrap(msg)]))
+
+        resin_w = []
+        resout_w = []
+        reserr_w = []
+        if res > 0:
+            if fdlistin is not None:
+                _unbuild_fd_set(space, iwtd_w, fdlistin,  ll_inl,  resin_w)
+            if fdlistout is not None:
+                _unbuild_fd_set(space, owtd_w, fdlistout, ll_outl, resout_w)
+            if fdlisterr is not None:
+                _unbuild_fd_set(space, ewtd_w, fdlisterr, ll_errl, reserr_w)
+    finally:
+        if ll_timeval: lltype.free(ll_timeval, flavor='raw')
+        if ll_errl:    lltype.free(ll_errl, flavor='raw')
+        if ll_outl:    lltype.free(ll_outl, flavor='raw')
+        if ll_inl:     lltype.free(ll_inl, flavor='raw')
+
+    return space.newtuple([space.newlist(resin_w),
+                           space.newlist(resout_w),
+                           space.newlist(reserr_w)])
diff --git a/pypy/module/select/test/test_kqueue.py b/pypy/module/select/test/test_kqueue.py
--- a/pypy/module/select/test/test_kqueue.py
+++ b/pypy/module/select/test/test_kqueue.py
@@ -100,7 +100,7 @@
         client.setblocking(False)
         try:
             client.connect(("127.0.0.1", server_socket.getsockname()[1]))
-        except socket.error as e:
+        except socket.error, e:
             if 'bsd' in sys.platform:
                 assert e.args[0] == errno.ENOENT
             else:
diff --git a/pypy/module/signal/interp_signal.py b/pypy/module/signal/interp_signal.py
--- a/pypy/module/signal/interp_signal.py
+++ b/pypy/module/signal/interp_signal.py
@@ -16,7 +16,8 @@
 def setup():
     for key, value in cpy_signal.__dict__.items():
         if (key.startswith('SIG') or key.startswith('CTRL_')) and \
-                is_valid_int(value):
+                is_valid_int(value) and \
+                key != 'SIG_DFL' and key != 'SIG_IGN':
             globals()[key] = value
             yield key
 
@@ -24,11 +25,18 @@
 SIG_DFL = cpy_signal.SIG_DFL
 SIG_IGN = cpy_signal.SIG_IGN
 signal_names = list(setup())
-signal_values = [globals()[key] for key in signal_names]
 signal_values = {}
 for key in signal_names:
     signal_values[globals()[key]] = None
-
+if sys.platform == 'win32' and not hasattr(cpy_signal,'CTRL_C_EVENT'):
+    # XXX Hack to revive values that went missing,
+    #     Remove this once we are sure the host cpy module has them.
+    signal_values[0] = None
+    signal_values[1] = None
+    signal_names.append('CTRL_C_EVENT')
+    signal_names.append('CTRL_BREAK_EVENT')
+    CTRL_C_EVENT = 0
+    CTRL_BREAK_EVENT = 1
 includes = ['stdlib.h', 'src/signals.h']
 if sys.platform != 'win32':
     includes.append('sys/time.h')
diff --git a/pypy/module/signal/test/test_signal.py b/pypy/module/signal/test/test_signal.py
--- a/pypy/module/signal/test/test_signal.py
+++ b/pypy/module/signal/test/test_signal.py
@@ -43,7 +43,11 @@
         cls.w_signal = space.appexec([], "(): import signal; return signal")
 
     def test_exported_names(self):
+        import os
         self.signal.__dict__   # crashes if the interpleveldefs are invalid
+        if os.name == 'nt':
+            assert self.signal.CTRL_BREAK_EVENT == 1
+            assert self.signal.CTRL_C_EVENT == 0
 
     def test_basics(self):
         import types, os
@@ -61,8 +65,6 @@
             received.append(signum)
         signal.signal(signum, myhandler)
 
-        print dir(os)
-
         os.kill(os.getpid(), signum)
         # the signal should be delivered to the handler immediately
         assert received == [signum]
diff --git a/pypy/module/sys/version.py b/pypy/module/sys/version.py
--- a/pypy/module/sys/version.py
+++ b/pypy/module/sys/version.py
@@ -7,7 +7,8 @@
 from pypy.interpreter import gateway
 
 #XXX # the release serial 42 is not in range(16)
-CPYTHON_VERSION            = (3, 2, 2, "final", 0)   #XXX # sync patchlevel.h
+CPYTHON_VERSION            = (3, 2, 2, "final", 0)
+#XXX # sync CPYTHON_VERSION with patchlevel.h, package.py
 CPYTHON_API_VERSION        = 1013   #XXX # sync with include/modsupport.h
 
 PYPY_VERSION               = (1, 9, 1, "dev", 0)    #XXX # sync patchlevel.h
diff --git a/pypy/module/test_lib_pypy/ctypes_tests/_ctypes_test.c b/pypy/module/test_lib_pypy/ctypes_tests/_ctypes_test.c
--- a/pypy/module/test_lib_pypy/ctypes_tests/_ctypes_test.c
+++ b/pypy/module/test_lib_pypy/ctypes_tests/_ctypes_test.c
@@ -14,6 +14,7 @@
 #include <string.h>
 #include <wchar.h>
 #include <stdio.h>
+#include <errno.h>
 
 #define HAVE_LONG_LONG
 #define LONG_LONG long long
@@ -559,3 +560,10 @@
 {
     return 42;
 }
+
+EXPORT(int) test_errno(void)
+{
+    int result = errno;
+    errno = result + 1;
+    return result;
+}
diff --git a/pypy/module/test_lib_pypy/ctypes_tests/test_errno.py b/pypy/module/test_lib_pypy/ctypes_tests/test_errno.py
--- a/pypy/module/test_lib_pypy/ctypes_tests/test_errno.py
+++ b/pypy/module/test_lib_pypy/ctypes_tests/test_errno.py
@@ -19,3 +19,5 @@
         f._call_funcptr(check)
         assert _rawffi.get_errno() == old
         ctypes.set_errno(0)
+
+    # see also test_functions.test_errno
diff --git a/pypy/module/test_lib_pypy/ctypes_tests/test_functions.py b/pypy/module/test_lib_pypy/ctypes_tests/test_functions.py
--- a/pypy/module/test_lib_pypy/ctypes_tests/test_functions.py
+++ b/pypy/module/test_lib_pypy/ctypes_tests/test_functions.py
@@ -5,6 +5,7 @@
 Later...
 """
 
+from __future__ import with_statement
 from ctypes import *
 import sys
 import py
@@ -20,7 +21,7 @@
 def setup_module(mod):
     import conftest
     _ctypes_test = str(conftest.sofile)
-    mod.dll = CDLL(_ctypes_test)
+    mod.dll = CDLL(_ctypes_test, use_errno=True)
     if sys.platform == "win32":
         mod.windll = WinDLL(_ctypes_test)
 
@@ -521,3 +522,12 @@
             assert len(w) == 0
             
         warnings.resetwarnings()
+
+
+    def test_errno(self):
+        test_errno = dll.test_errno
+        test_errno.restype = c_int
+        set_errno(42)
+        res = test_errno()
+        n = get_errno()
+        assert (res, n) == (42, 43)
diff --git a/pypy/module/unicodedata/generate_unicodedb.py b/pypy/module/unicodedata/generate_unicodedb.py
--- a/pypy/module/unicodedata/generate_unicodedb.py
+++ b/pypy/module/unicodedata/generate_unicodedb.py
@@ -430,9 +430,19 @@
     print >> outfile, 'version = %r' % version
     print >> outfile
 
-    cjk_end = 0x9FA5
-    if version >= "4.1":
-        cjk_end = 0x9FBB
+    if version < "4.1":
+        cjk_interval = ("(0x3400 <= code <= 0x4DB5 or"
+                        " 0x4E00 <= code <= 0x9FA5 or"
+                        " 0x20000 <= code <= 0x2A6D6)")
+    elif version < "5":    # don't know the exact limit
+        cjk_interval = ("(0x3400 <= code <= 0x4DB5 or"
+                        " 0x4E00 <= code <= 0x9FBB or"
+                        " 0x20000 <= code <= 0x2A6D6)")
+    else:
+        cjk_interval = ("(0x3400 <= code <= 0x4DB5 or"
+                        " 0x4E00 <= code <= 0x9FCB or"
+                        " 0x20000 <= code <= 0x2A6D6 or"
+                        " 0x2A700 <= code <= 0x2B734)")
 
     write_character_names(outfile, table, base_mod)
 
@@ -488,9 +498,7 @@
         if not ('0' <= c <= '9' or 'A' <= c <= 'F'):
             raise KeyError
     code = int(cjk_code, 16)
-    if (0x3400 <= code <= 0x4DB5 or
-        0x4E00 <= code <= 0x%X or
-        0x20000 <= code <= 0x2A6D6):
+    if %s:
         return code
     raise KeyError
 
@@ -512,9 +520,7 @@
                 raise
 
 def name(code):
-    if (0x3400 <= code <= 0x4DB5 or
-        0x4E00 <= code <= 0x%X or
-        0x20000 <= code <= 0x2A6D6):
+    if %s:
         return "CJK UNIFIED IDEOGRAPH-" + hex(code)[2:].upper()
     if 0xAC00 <= code <= 0xD7A3:
         # vl_code, t_code = divmod(code - 0xAC00, len(_hangul_T))
@@ -536,7 +542,7 @@
                 return base_mod.lookup_charcode(code)
             else:
                 raise
-''' % (cjk_end, cjk_end)
+''' % (cjk_interval, cjk_interval)
 
     # Categories
     writeDbRecord(outfile, table)
diff --git a/pypy/module/unicodedata/test/test_unicodedata.py b/pypy/module/unicodedata/test/test_unicodedata.py
--- a/pypy/module/unicodedata/test/test_unicodedata.py
+++ b/pypy/module/unicodedata/test/test_unicodedata.py
@@ -53,7 +53,12 @@
         import unicodedata
         cases = ((0x3400, 0x4DB5),
                  (0x4E00, 0x9FA5))
-        if unicodedata.unidata_version >= "4.1":
+        if unicodedata.unidata_version >= "5":    # don't know the exact limit
+            cases = ((0x3400, 0x4DB5),
+                     (0x4E00, 0x9FCB),
+                     (0x20000, 0x2A6D6),
+                     (0x2A700, 0x2B734))
+        elif unicodedata.unidata_version >= "4.1":
             cases = ((0x3400, 0x4DB5),
                      (0x4E00, 0x9FBB),
                      (0x20000, 0x2A6D6))
diff --git a/pypy/module/unicodedata/unicodedb_5_2_0.py b/pypy/module/unicodedata/unicodedb_5_2_0.py
--- a/pypy/module/unicodedata/unicodedb_5_2_0.py
+++ b/pypy/module/unicodedata/unicodedb_5_2_0.py
@@ -134464,9 +134464,7 @@
         if not ('0' <= c <= '9' or 'A' <= c <= 'F'):
             raise KeyError
     code = int(cjk_code, 16)
-    if (0x3400 <= code <= 0x4DB5 or
-        0x4E00 <= code <= 0x9FBB or
-        0x20000 <= code <= 0x2A6D6):
+    if (0x3400 <= code <= 0x4DB5 or 0x4E00 <= code <= 0x9FCB or 0x20000 <= code <= 0x2A6D6 or 0x2A700 <= code <= 0x2B734):
         return code
     raise KeyError
 
@@ -134488,9 +134486,7 @@
                 raise
 
 def name(code):
-    if (0x3400 <= code <= 0x4DB5 or
-        0x4E00 <= code <= 0x9FBB or
-        0x20000 <= code <= 0x2A6D6):
+    if (0x3400 <= code <= 0x4DB5 or 0x4E00 <= code <= 0x9FCB or 0x20000 <= code <= 0x2A6D6 or 0x2A700 <= code <= 0x2B734):
         return "CJK UNIFIED IDEOGRAPH-" + hex(code)[2:].upper()
     if 0xAC00 <= code <= 0xD7A3:
         # vl_code, t_code = divmod(code - 0xAC00, len(_hangul_T))
diff --git a/pypy/module/zlib/interp_zlib.py b/pypy/module/zlib/interp_zlib.py
--- a/pypy/module/zlib/interp_zlib.py
+++ b/pypy/module/zlib/interp_zlib.py
@@ -20,7 +20,7 @@
         return intmask((x ^ SIGN_EXTEND2) - SIGN_EXTEND2)
 
 
- at unwrap_spec(string='bufferstr', start='truncatedint')
+ at unwrap_spec(string='bufferstr', start='truncatedint_w')
 def crc32(space, string, start = rzlib.CRC32_DEFAULT_START):
     """
     crc32(string[, start]) -- Compute a CRC-32 checksum of string.
@@ -41,7 +41,7 @@
     return space.wrap(checksum)
 
 
- at unwrap_spec(string='bufferstr', start='truncatedint')
+ at unwrap_spec(string='bufferstr', start='truncatedint_w')
 def adler32(space, string, start=rzlib.ADLER32_DEFAULT_START):
     """
     adler32(string[, start]) -- Compute an Adler-32 checksum of string.
diff --git a/pypy/objspace/fake/objspace.py b/pypy/objspace/fake/objspace.py
--- a/pypy/objspace/fake/objspace.py
+++ b/pypy/objspace/fake/objspace.py
@@ -55,6 +55,9 @@
         from pypy.rlib.rbigint import rbigint
         return rbigint.fromint(NonConstant(42))
 
+class W_MyType(W_MyObject):
+    def __init__(self):
+        self.mro_w = [w_some_obj(), w_some_obj()]
 
 def w_some_obj():
     if NonConstant(False):
@@ -66,6 +69,9 @@
         return None
     return w_some_obj()
 
+def w_some_type():
+    return W_MyType()
+
 def is_root(w_obj):
     assert isinstance(w_obj, W_Root)
 is_root.expecting = W_Root
@@ -224,6 +230,9 @@
         assert typedef is not None
         return self.fromcache(TypeCache).getorbuild(typedef)
 
+    def type(self, w_obj):
+        return w_some_type()
+
     def unpackiterable(self, w_iterable, expected_length=-1):
         is_root(w_iterable)
         if expected_length < 0:
@@ -291,10 +300,13 @@
                  ObjSpace.ExceptionTable +
                  ['int', 'str', 'float', 'long', 'tuple', 'list',
                   'dict', 'bytes', 'complex', 'slice', 'bool',
-                  'type', 'text', 'object', 'unicode']):
+                  'text', 'object', 'unicode']):
         setattr(FakeObjSpace, 'w_' + name, w_some_obj())
+    FakeObjSpace.w_type = w_some_type()
     #
     for (name, _, arity, _) in ObjSpace.MethodTable:
+        if name == 'type':
+            continue
         args = ['w_%d' % i for i in range(arity)]
         params = args[:]
         d = {'is_root': is_root,
diff --git a/pypy/objspace/fake/test/test_checkmodule.py b/pypy/objspace/fake/test/test_checkmodule.py
--- a/pypy/objspace/fake/test/test_checkmodule.py
+++ b/pypy/objspace/fake/test/test_checkmodule.py
@@ -1,9 +1,9 @@
-import py
+
 from pypy.objspace.fake.objspace import FakeObjSpace, is_root
 from pypy.interpreter.baseobjspace import Wrappable
 from pypy.interpreter.typedef import TypeDef, GetSetProperty
 from pypy.interpreter.gateway import interp2app, W_Root, ObjSpace
-
+from pypy.rpython.test.test_llinterp import interpret
 
 def make_checker():
     check = []
@@ -61,3 +61,18 @@
     assert not check
     space.translates()
     assert check
+
+def test_gettype_mro_untranslated():
+    space = FakeObjSpace()
+    w_type = space.type(space.wrap(1))
+    assert len(w_type.mro_w) == 2
+
+def test_gettype_mro():
+    space = FakeObjSpace()
+
+    def f(i):
+        w_x = space.wrap(i)
+        w_type = space.type(w_x)
+        return len(w_type.mro_w)
+
+    assert interpret(f, [1]) == 2
diff --git a/pypy/objspace/std/test/test_stdobjspace.py b/pypy/objspace/std/test/test_stdobjspace.py
--- a/pypy/objspace/std/test/test_stdobjspace.py
+++ b/pypy/objspace/std/test/test_stdobjspace.py
@@ -74,3 +74,20 @@
         space = gettestobjspace(withstrbuf=True)
         cls = space._get_interplevel_cls(space.w_str)
         assert cls is W_AbstractStringObject
+
+    def test_wrap_various_unsigned_types(self):
+        import sys
+        from pypy.rpython.lltypesystem import lltype, rffi
+        space = self.space
+        value = sys.maxint * 2
+        x = rffi.cast(lltype.Unsigned, value)
+        assert space.eq_w(space.wrap(value), space.wrap(x))
+        x = rffi.cast(rffi.UINTPTR_T, value)
+        assert x > 0
+        assert space.eq_w(space.wrap(value), space.wrap(x))
+        value = 60000
+        x = rffi.cast(rffi.USHORT, value)
+        assert space.eq_w(space.wrap(value), space.wrap(x))
+        value = 200
+        x = rffi.cast(rffi.UCHAR, value)
+        assert space.eq_w(space.wrap(value), space.wrap(x))
diff --git a/pypy/rlib/_rsocket_rffi.py b/pypy/rlib/_rsocket_rffi.py
--- a/pypy/rlib/_rsocket_rffi.py
+++ b/pypy/rlib/_rsocket_rffi.py
@@ -58,12 +58,12 @@
     header_lines = [
         '#include <WinSock2.h>',
         '#include <WS2tcpip.h>',
-        '#include <Mstcpip.h>',
         # winsock2 defines AF_UNIX, but not sockaddr_un
         '#undef AF_UNIX',
         ]
     if _MSVC:
         header_lines.extend([
+            '#include <Mstcpip.h>',
             # these types do not exist on microsoft compilers
             'typedef int ssize_t;',
             'typedef unsigned __int16 uint16_t;',
@@ -71,7 +71,6 @@
             ])
     else: # MINGW
         includes = ('stdint.h',)
-        """
         header_lines.extend([
             '''\
             #ifndef _WIN32_WINNT
@@ -89,7 +88,6 @@
                 u_long  keepaliveinterval;
             };'''
             ])
-        """
     HEADER = '\n'.join(header_lines)
     COND_HEADER = ''
 constants = {}
diff --git a/pypy/rlib/clibffi.py b/pypy/rlib/clibffi.py
--- a/pypy/rlib/clibffi.py
+++ b/pypy/rlib/clibffi.py
@@ -11,6 +11,7 @@
 from pypy.rlib.rdynload import dlopen, dlclose, dlsym, dlsym_byordinal
 from pypy.rlib.rdynload import DLOpenError, DLLHANDLE
 from pypy.rlib import jit
+from pypy.rlib.objectmodel import specialize
 from pypy.tool.autopath import pypydir
 from pypy.translator.tool.cbuild import ExternalCompilationInfo
 from pypy.translator.platform import platform
@@ -141,6 +142,7 @@
 
 FFI_TYPE_P = lltype.Ptr(lltype.ForwardReference())
 FFI_TYPE_PP = rffi.CArrayPtr(FFI_TYPE_P)
+FFI_TYPE_NULL = lltype.nullptr(FFI_TYPE_P.TO)
 
 class CConfig:
     _compilation_info_ = eci
@@ -346,11 +348,13 @@
                                         ('ffistruct', FFI_TYPE_P.TO),
                                         ('members', lltype.Array(FFI_TYPE_P))))
 
-def make_struct_ffitype_e(size, aligment, field_types):
+ at specialize.arg(3)
+def make_struct_ffitype_e(size, aligment, field_types, track_allocation=True):
     """Compute the type of a structure.  Returns a FFI_STRUCT_P out of
        which the 'ffistruct' member is a regular FFI_TYPE.
     """
-    tpe = lltype.malloc(FFI_STRUCT_P.TO, len(field_types)+1, flavor='raw')
+    tpe = lltype.malloc(FFI_STRUCT_P.TO, len(field_types)+1, flavor='raw',
+                        track_allocation=track_allocation)
     tpe.ffistruct.c_type = rffi.cast(rffi.USHORT, FFI_TYPE_STRUCT)
     tpe.ffistruct.c_size = rffi.cast(rffi.SIZE_T, size)
     tpe.ffistruct.c_alignment = rffi.cast(rffi.USHORT, aligment)
diff --git a/pypy/rlib/libffi.py b/pypy/rlib/libffi.py
--- a/pypy/rlib/libffi.py
+++ b/pypy/rlib/libffi.py
@@ -210,7 +210,7 @@
 
     _immutable_fields_ = ['funcsym']
     argtypes = []
-    restype = lltype.nullptr(clibffi.FFI_TYPE_P.TO)
+    restype = clibffi.FFI_TYPE_NULL
     flags = 0
     funcsym = lltype.nullptr(rffi.VOIDP.TO)
 
@@ -416,6 +416,96 @@
     def getaddressindll(self, name):
         return dlsym(self.lib, name)
 
+# ======================================================================
+
+ at jit.oopspec('libffi_struct_getfield(ffitype, addr, offset)')
+def struct_getfield_int(ffitype, addr, offset):
+    """
+    Return the field of type ``ffitype`` at ``addr+offset``, widened to
+    lltype.Signed.
+    """
+    for TYPE, ffitype2 in clibffi.ffitype_map_int_or_ptr:
+        if ffitype is ffitype2:
+            value = _struct_getfield(TYPE, addr, offset)
+            return rffi.cast(lltype.Signed, value)
+    assert False, "cannot find the given ffitype"
+
+
+ at jit.oopspec('libffi_struct_setfield(ffitype, addr, offset, value)')
+def struct_setfield_int(ffitype, addr, offset, value):
+    """
+    Set the field of type ``ffitype`` at ``addr+offset``.  ``value`` is of
+    type lltype.Signed, and it's automatically converted to the right type.
+    """
+    for TYPE, ffitype2 in clibffi.ffitype_map_int_or_ptr:
+        if ffitype is ffitype2:
+            value = rffi.cast(TYPE, value)
+            _struct_setfield(TYPE, addr, offset, value)
+            return
+    assert False, "cannot find the given ffitype"
+
+
+ at jit.oopspec('libffi_struct_getfield(ffitype, addr, offset)')
+def struct_getfield_longlong(ffitype, addr, offset):
+    """
+    Return the field of type ``ffitype`` at ``addr+offset``, casted to
+    lltype.LongLong.
+    """
+    value = _struct_getfield(lltype.SignedLongLong, addr, offset)
+    return value
+
+ at jit.oopspec('libffi_struct_setfield(ffitype, addr, offset, value)')
+def struct_setfield_longlong(ffitype, addr, offset, value):
+    """
+    Set the field of type ``ffitype`` at ``addr+offset``.  ``value`` is of
+    type lltype.LongLong
+    """
+    _struct_setfield(lltype.SignedLongLong, addr, offset, value)
+
+
+ at jit.oopspec('libffi_struct_getfield(ffitype, addr, offset)')
+def struct_getfield_float(ffitype, addr, offset):
+    value = _struct_getfield(lltype.Float, addr, offset)
+    return value
+
+ at jit.oopspec('libffi_struct_setfield(ffitype, addr, offset, value)')
+def struct_setfield_float(ffitype, addr, offset, value):
+    _struct_setfield(lltype.Float, addr, offset, value)
+
+
+ at jit.oopspec('libffi_struct_getfield(ffitype, addr, offset)')
+def struct_getfield_singlefloat(ffitype, addr, offset):
+    value = _struct_getfield(lltype.SingleFloat, addr, offset)
+    return value
+
+ at jit.oopspec('libffi_struct_setfield(ffitype, addr, offset, value)')
+def struct_setfield_singlefloat(ffitype, addr, offset, value):
+    _struct_setfield(lltype.SingleFloat, addr, offset, value)
+
+
+ at specialize.arg(0)
+def _struct_getfield(TYPE, addr, offset):
+    """
+    Read the field of type TYPE at addr+offset.
+    addr is of type rffi.VOIDP, offset is an int.
+    """
+    addr = rffi.ptradd(addr, offset)
+    PTR_FIELD = lltype.Ptr(rffi.CArray(TYPE))
+    return rffi.cast(PTR_FIELD, addr)[0]
+
+
+ at specialize.arg(0)
+def _struct_setfield(TYPE, addr, offset, value):
+    """
+    Write the field of type TYPE at addr+offset.
+    addr is of type rffi.VOIDP, offset is an int.
+    """
+    addr = rffi.ptradd(addr, offset)
+    PTR_FIELD = lltype.Ptr(rffi.CArray(TYPE))
+    rffi.cast(PTR_FIELD, addr)[0] = value
+
+# ======================================================================
+
 # These specialize.call_location's should really be specialize.arg(0), however
 # you can't hash a pointer obj, which the specialize machinery wants to do.
 # Given the present usage of these functions, it's good enough.
diff --git a/pypy/rlib/rarithmetic.py b/pypy/rlib/rarithmetic.py
--- a/pypy/rlib/rarithmetic.py
+++ b/pypy/rlib/rarithmetic.py
@@ -97,6 +97,9 @@
 # XXX TODO: replace all int(n) by long(n) and fix everything that breaks.
 # XXX       Then relax it and replace int(n) by n.
 def intmask(n):
+    """
+    NOT_RPYTHON
+    """
     if isinstance(n, objectmodel.Symbolic):
         return n        # assume Symbolics don't overflow
     assert not isinstance(n, float)
@@ -109,6 +112,9 @@
     return int(n)
 
 def longlongmask(n):
+    """
+    NOT_RPYTHON
+    """
     assert isinstance(n, (int, long))
     n = long(n)
     n &= LONGLONG_MASK
diff --git a/pypy/rlib/rposix.py b/pypy/rlib/rposix.py
--- a/pypy/rlib/rposix.py
+++ b/pypy/rlib/rposix.py
@@ -1,11 +1,11 @@
 import os
-from pypy.rpython.lltypesystem.rffi import (CConstant, CExternVariable,
-        INT, CCHARPP)
-from pypy.rpython.lltypesystem import lltype, ll2ctypes, rffi
+from pypy.rpython.lltypesystem.rffi import CConstant, CExternVariable, INT
+from pypy.rpython.lltypesystem import ll2ctypes, rffi
 from pypy.translator.tool.cbuild import ExternalCompilationInfo
 from pypy.rlib.rarithmetic import intmask
 from pypy.rlib.objectmodel import specialize
 from pypy.rlib import jit
+from pypy.translator.platform import platform
 
 class CConstantErrno(CConstant):
     # these accessors are used when calling get_errno() or set_errno()
@@ -21,6 +21,10 @@
         assert index == 0
         ll2ctypes.TLS.errno = value
 if os.name == 'nt':
+    if platform.name == 'msvc':
+        includes=['errno.h','stdio.h']
+    else:
+        includes=['errno.h','stdio.h', 'stdint.h']
     separate_module_sources =['''
         /* Lifted completely from CPython 3.3 Modules/posix_module.c */
         #include <malloc.h> /* for _msize */
@@ -79,10 +83,11 @@
 else:
     separate_module_sources = []
     export_symbols = []
+    includes=['errno.h','stdio.h']
 errno_eci = ExternalCompilationInfo(
-    includes=['errno.h','stdio.h'],
-    separate_module_sources = separate_module_sources,
-    export_symbols = export_symbols,
+    includes=includes,
+    separate_module_sources=separate_module_sources,
+    export_symbols=export_symbols,
 )
 
 _get_errno, _set_errno = CExternVariable(INT, 'errno', errno_eci,
@@ -242,6 +247,7 @@
         else:
             return nt._getfullpathname(path.as_bytes())
 
+<<<<<<< local
 @specialize.argtype(0, 1)
 def putenv(name, value):
     if isinstance(name, str):
@@ -256,3 +262,11 @@
     else:
         del os.environ[name.as_bytes()]
 
+=======
+if os.name == 'nt':
+    from pypy.rlib import rwin32
+    os_kill = rwin32.os_kill
+else:
+    os_kill = os.kill
+    
+>>>>>>> other
diff --git a/pypy/rlib/rwin32.py b/pypy/rlib/rwin32.py
--- a/pypy/rlib/rwin32.py
+++ b/pypy/rlib/rwin32.py
@@ -8,7 +8,6 @@
 from pypy.translator.platform import CompilationError
 from pypy.rpython.lltypesystem import lltype, rffi
 from pypy.rlib.rarithmetic import intmask
-from pypy.rlib.rposix import validate_fd
 from pypy.rlib import jit
 import os, sys, errno
 
@@ -76,11 +75,25 @@
         DEFAULT_LANGUAGE = rffi_platform.ConstantInteger(
             "MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT)")
 
-        for name in """FORMAT_MESSAGE_ALLOCATE_BUFFER FORMAT_MESSAGE_FROM_SYSTEM
+        defines = """FORMAT_MESSAGE_ALLOCATE_BUFFER FORMAT_MESSAGE_FROM_SYSTEM
                        MAX_PATH
                        WAIT_OBJECT_0 WAIT_TIMEOUT INFINITE
                        ERROR_INVALID_HANDLE
-                    """.split():
+                       DELETE READ_CONTROL SYNCHRONIZE WRITE_DAC
+                       WRITE_OWNER PROCESS_ALL_ACCESS
+                       PROCESS_CREATE_PROCESS PROCESS_CREATE_THREAD
+                       PROCESS_DUP_HANDLE PROCESS_QUERY_INFORMATION
+                       PROCESS_SET_QUOTA
+                       PROCESS_SUSPEND_RESUME PROCESS_TERMINATE
+                       PROCESS_VM_OPERATION PROCESS_VM_READ
+                       PROCESS_VM_WRITE
+                       CTRL_C_EVENT CTRL_BREAK_EVENT
+                    """
+        from pypy.translator.platform import host_factory
+        static_platform = host_factory()
+        if static_platform.name == 'msvc':
+            defines += ' PROCESS_QUERY_LIMITED_INFORMATION' 
+        for name in defines.split():
             locals()[name] = rffi_platform.ConstantInteger(name)
 
 for k, v in rffi_platform.configure(CConfig).items():
@@ -129,6 +142,7 @@
     _get_osfhandle = rffi.llexternal('_get_osfhandle', [rffi.INT], HANDLE)
 
     def get_osfhandle(fd):
+        from pypy.rlib.rposix import validate_fd
         validate_fd(fd)
         handle = _get_osfhandle(fd)
         if handle == INVALID_HANDLE_VALUE:
@@ -316,4 +330,53 @@
         'SetEvent', [HANDLE], BOOL)
     ResetEvent = winexternal(
         'ResetEvent', [HANDLE], BOOL)
+    _OpenProcess = winexternal(
+        'OpenProcess', [DWORD, BOOL, DWORD], HANDLE)
+    def OpenProcess(*args):
+        ''' OpenProcess( dwDesiredAccess, bInheritHandle, dwProcessId)
+        where dwDesiredAccess is a combination of the flags:
+        DELETE (0x00010000L)
+        READ_CONTROL (0x00020000L)
+        SYNCHRONIZE (0x00100000L)
+        WRITE_DAC (0x00040000L)
+        WRITE_OWNER (0x00080000L)
 
+        PROCESS_ALL_ACCESS
+        PROCESS_CREATE_PROCESS (0x0080)
+        PROCESS_CREATE_THREAD (0x0002)
+        PROCESS_DUP_HANDLE (0x0040)
+        PROCESS_QUERY_INFORMATION (0x0400)
+        PROCESS_QUERY_LIMITED_INFORMATION (0x1000)
+        PROCESS_SET_QUOTA (0x0100)
+        PROCESS_SUSPEND_RESUME (0x0800)
+        PROCESS_TERMINATE (0x0001)
+        PROCESS_VM_OPERATION (0x0008)
+        PROCESS_VM_READ (0x0010)
+        PROCESS_VM_WRITE (0x0020)
+        SYNCHRONIZE (0x00100000L)
+        '''
+        handle = _OpenProcess(*args)
+        if handle == NULL_HANDLE:
+            raise lastWindowsError("OpenProcess")
+        return handle
+    TerminateProcess = winexternal(
+        'TerminateProcess', [HANDLE, rffi.UINT], BOOL)
+    GenerateConsoleCtrlEvent = winexternal(
+        'GenerateConsoleCtrlEvent', [DWORD, DWORD], BOOL)
+    _GetCurrentProcessId = winexternal(
+        'GetCurrentProcessId', [], DWORD)
+    def GetCurrentProcessId():
+        return rffi.cast(lltype.Signed, _GetCurrentProcessId())
+    def os_kill(pid, sig):
+        if sig == CTRL_C_EVENT or sig == CTRL_BREAK_EVENT:
+            if GenerateConsoleCtrlEvent(sig, pid) == 0:
+                raise lastWindowsError('os_kill failed generating event')
+            return
+        handle = OpenProcess(PROCESS_ALL_ACCESS, False, pid)
+        if handle == NULL_HANDLE:
+            raise lastWindowsError('os_kill failed opening process')
+        try:
+            if TerminateProcess(handle, sig) == 0:
+                raise lastWindowsError('os_kill failed to terminate process')
+        finally:
+            CloseHandle(handle)
diff --git a/pypy/rlib/test/test_libffi.py b/pypy/rlib/test/test_libffi.py
--- a/pypy/rlib/test/test_libffi.py
+++ b/pypy/rlib/test/test_libffi.py
@@ -2,12 +2,16 @@
 
 import py
 
-from pypy.rlib.libffi import (CDLL, Func, get_libc_name, ArgChain, types,
-    IS_32_BIT, array_getitem, array_setitem)
 from pypy.rlib.rarithmetic import r_singlefloat, r_longlong, r_ulonglong
 from pypy.rlib.test.test_clibffi import BaseFfiTest, get_libm_name, make_struct_ffitype_e
 from pypy.rpython.lltypesystem import rffi, lltype
 from pypy.rpython.lltypesystem.ll2ctypes import ALLOCATED
+from pypy.rlib.libffi import (CDLL, Func, get_libc_name, ArgChain, types,
+                              IS_32_BIT, array_getitem, array_setitem)
+from pypy.rlib.libffi import (struct_getfield_int, struct_setfield_int,
+                              struct_getfield_longlong, struct_setfield_longlong,
+                              struct_getfield_float, struct_setfield_float,
+                              struct_getfield_singlefloat, struct_setfield_singlefloat)
 
 class TestLibffiMisc(BaseFfiTest):
 
@@ -54,6 +58,33 @@
         del lib
         assert not ALLOCATED
 
+    def test_struct_fields(self):
+        longsize = 4 if IS_32_BIT else 8
+        POINT = lltype.Struct('POINT',
+                              ('x', rffi.LONG),
+                              ('y', rffi.SHORT),
+                              ('z', rffi.VOIDP),
+                              )
+        y_ofs = longsize
+        z_ofs = longsize*2
+        p = lltype.malloc(POINT, flavor='raw')
+        p.x = 42
+        p.y = rffi.cast(rffi.SHORT, -1)
+        p.z = rffi.cast(rffi.VOIDP, 0x1234)
+        addr = rffi.cast(rffi.VOIDP, p)
+        assert struct_getfield_int(types.slong, addr, 0) == 42
+        assert struct_getfield_int(types.sshort, addr, y_ofs) == -1
+        assert struct_getfield_int(types.pointer, addr, z_ofs) == 0x1234
+        #
+        struct_setfield_int(types.slong, addr, 0, 43)
+        struct_setfield_int(types.sshort, addr, y_ofs, 0x1234FFFE) # 0x1234 is masked out
+        struct_setfield_int(types.pointer, addr, z_ofs, 0x4321)
+        assert p.x == 43
+        assert p.y == -2
+        assert rffi.cast(rffi.LONG, p.z) == 0x4321
+        #
+        lltype.free(p, flavor='raw')
+
     def test_array_fields(self):
         POINT = lltype.Struct("POINT",
             ("x", lltype.Float),
@@ -69,18 +100,81 @@
         assert array_getitem(types.double, 16, points, 0, 8) == 2.0
         assert array_getitem(types.double, 16, points, 1, 0) == 3.0
         assert array_getitem(types.double, 16, points, 1, 8) == 4.0
-
+        #
         array_setitem(types.double, 16, points, 0, 0, 10.0)
         array_setitem(types.double, 16, points, 0, 8, 20.0)
         array_setitem(types.double, 16, points, 1, 0, 30.0)
         array_setitem(types.double, 16, points, 1, 8, 40.0)
-
+        #
         assert array_getitem(types.double, 16, points, 0, 0) == 10.0
         assert array_getitem(types.double, 16, points, 0, 8) == 20.0
         assert array_getitem(types.double, 16, points, 1, 0) == 30.0
         assert array_getitem(types.double, 16, points, 1, 8) == 40.0
+        #
+        lltype.free(points, flavor="raw")
 
-        lltype.free(points, flavor="raw")
+
+    def test_struct_fields_longlong(self):
+        POINT = lltype.Struct('POINT',
+                              ('x', rffi.LONGLONG),
+                              ('y', rffi.ULONGLONG)
+                              )
+        y_ofs = 8
+        p = lltype.malloc(POINT, flavor='raw')
+        p.x = r_longlong(123)
+        p.y = r_ulonglong(456)
+        addr = rffi.cast(rffi.VOIDP, p)
+        assert struct_getfield_longlong(types.slonglong, addr, 0) == 123
+        assert struct_getfield_longlong(types.ulonglong, addr, y_ofs) == 456
+        #
+        v = rffi.cast(lltype.SignedLongLong, r_ulonglong(9223372036854775808))
+        struct_setfield_longlong(types.slonglong, addr, 0, v)
+        struct_setfield_longlong(types.ulonglong, addr, y_ofs, r_longlong(-1))
+        assert p.x == -9223372036854775808
+        assert rffi.cast(lltype.UnsignedLongLong, p.y) == 18446744073709551615
+        #
+        lltype.free(p, flavor='raw')
+
+    def test_struct_fields_float(self):
+        POINT = lltype.Struct('POINT',
+                              ('x', rffi.DOUBLE),
+                              ('y', rffi.DOUBLE)
+                              )
+        y_ofs = 8
+        p = lltype.malloc(POINT, flavor='raw')
+        p.x = 123.4
+        p.y = 567.8
+        addr = rffi.cast(rffi.VOIDP, p)
+        assert struct_getfield_float(types.double, addr, 0) == 123.4
+        assert struct_getfield_float(types.double, addr, y_ofs) == 567.8
+        #
+        struct_setfield_float(types.double, addr, 0, 321.0)
+        struct_setfield_float(types.double, addr, y_ofs, 876.5)
+        assert p.x == 321.0
+        assert p.y == 876.5
+        #
+        lltype.free(p, flavor='raw')
+
+    def test_struct_fields_singlefloat(self):
+        POINT = lltype.Struct('POINT',
+                              ('x', rffi.FLOAT),
+                              ('y', rffi.FLOAT)
+                              )
+        y_ofs = 4
+        p = lltype.malloc(POINT, flavor='raw')
+        p.x = r_singlefloat(123.4)
+        p.y = r_singlefloat(567.8)
+        addr = rffi.cast(rffi.VOIDP, p)
+        assert struct_getfield_singlefloat(types.double, addr, 0) == r_singlefloat(123.4)
+        assert struct_getfield_singlefloat(types.double, addr, y_ofs) == r_singlefloat(567.8)
+        #
+        struct_setfield_singlefloat(types.double, addr, 0, r_singlefloat(321.0))
+        struct_setfield_singlefloat(types.double, addr, y_ofs, r_singlefloat(876.5))
+        assert p.x == r_singlefloat(321.0)
+        assert p.y == r_singlefloat(876.5)
+        #
+        lltype.free(p, flavor='raw')
+
 
 class TestLibffiCall(BaseFfiTest):
     """
diff --git a/pypy/rlib/test/test_rwin32.py b/pypy/rlib/test/test_rwin32.py
--- a/pypy/rlib/test/test_rwin32.py
+++ b/pypy/rlib/test/test_rwin32.py
@@ -26,3 +26,24 @@
     rwin32.validate_fd = validate_fd
     raises(WindowsError, rwin32.get_osfhandle, fd)
     rwin32.validate_fd = _validate_fd
+
+def test_open_process():
+    pid = rwin32.GetCurrentProcessId()
+    assert pid != 0
+    handle = rwin32.OpenProcess(rwin32.PROCESS_QUERY_INFORMATION, False, pid)
+    rwin32.CloseHandle(handle)
+    raises(WindowsError, rwin32.OpenProcess, rwin32.PROCESS_TERMINATE, False, 0)
+
+def test_terminate_process():
+    import subprocess, signal, sys
+    proc = subprocess.Popen([sys.executable, "-c",
+                         "import time;"
+                         "time.sleep(10)",
+                         ],
+                        ) 
+    print proc.pid
+    handle = rwin32.OpenProcess(rwin32.PROCESS_ALL_ACCESS, False, proc.pid)
+    assert rwin32.TerminateProcess(handle, signal.SIGTERM) == 0
+    rwin32.CloseHandle(handle)
+    assert proc.wait() == signal.SIGTERM
+ 
diff --git a/pypy/rpython/lltypesystem/rdict.py b/pypy/rpython/lltypesystem/rdict.py
--- a/pypy/rpython/lltypesystem/rdict.py
+++ b/pypy/rpython/lltypesystem/rdict.py
@@ -518,8 +518,6 @@
     else:
         return default
 
-# XXX: Move the size checking and resize into a single call which is opauqe to
-# the JIT when the dict isn't virtual, to avoid extra branches.
 @jit.look_inside_iff(lambda d, i: jit.isvirtual(d) and jit.isconstant(i))
 def _ll_dict_del(d, i):
     d.entries.mark_deleted(i)
@@ -532,18 +530,32 @@
         entry.key = lltype.nullptr(ENTRY.key.TO)
     if ENTRIES.must_clear_value:
         entry.value = lltype.nullptr(ENTRY.value.TO)
-    num_entries = len(d.entries)
-    if num_entries > DICT_INITSIZE and d.num_items < num_entries / 4:
-        ll_dict_resize(d)
+    #
+    # The rest is commented out: like CPython we no longer shrink the
+    # dictionary here.  It may shrink later if we try to append a number
+    # of new items to it.  Unsure if this behavior was designed in
+    # CPython or is accidental.  A design reason would be that if you
+    # delete all items in a dictionary (e.g. with a series of
+    # popitem()), then CPython avoids shrinking the table several times.
+    #num_entries = len(d.entries)
+    #if num_entries > DICT_INITSIZE and d.num_items <= num_entries / 4:
+    #    ll_dict_resize(d)
+    # A previous xxx: move the size checking and resize into a single
+    # call which is opaque to the JIT when the dict isn't virtual, to
+    # avoid extra branches.
 
 def ll_dict_resize(d):
     old_entries = d.entries
     old_size = len(old_entries)
     # make a 'new_size' estimate and shrink it if there are many
-    # deleted entry markers
-    new_size = old_size * 2
-    while new_size > DICT_INITSIZE and d.num_items < new_size / 4:
-        new_size /= 2
+    # deleted entry markers.  See CPython for why it is a good idea to
+    # quadruple the dictionary size as long as it's not too big.
+    if d.num_items > 50000: new_estimate = d.num_items * 2
+    else:                   new_estimate = d.num_items * 4
+    new_size = DICT_INITSIZE
+    while new_size <= new_estimate:
+        new_size *= 2
+    #
     d.entries = lltype.typeOf(old_entries).TO.allocate(new_size)
     d.num_items = 0
     d.resize_counter = new_size * 2
diff --git a/pypy/rpython/lltypesystem/rffi.py b/pypy/rpython/lltypesystem/rffi.py
--- a/pypy/rpython/lltypesystem/rffi.py
+++ b/pypy/rpython/lltypesystem/rffi.py
@@ -436,6 +436,7 @@
           'long long', 'unsigned long long',
           'size_t', 'time_t', 'wchar_t',
           'uintptr_t', 'intptr_t']
+_TYPES_ARE_UNSIGNED = set(['size_t', 'uintptr_t'])   # plus "unsigned *"
 if os.name != 'nt':
     TYPES.append('mode_t')
     TYPES.append('pid_t')
@@ -454,7 +455,7 @@
             name = 'u' + name[9:]
             signed = False
         else:
-            signed = (name != 'size_t')
+            signed = (name not in _TYPES_ARE_UNSIGNED)
         name = name.replace(' ', '')
         names.append(name)
         populatelist.append((name.upper(), c_name, signed))
diff --git a/pypy/rpython/module/ll_os.py b/pypy/rpython/module/ll_os.py
--- a/pypy/rpython/module/ll_os.py
+++ b/pypy/rpython/module/ll_os.py
@@ -7,11 +7,11 @@
 
 import os, sys, errno
 import py
-from pypy.rpython.module.support import ll_strcpy, OOSupport
-from pypy.tool.sourcetools import func_with_new_name, func_renamer
+from pypy.rpython.module.support import OOSupport
+from pypy.tool.sourcetools import func_renamer
 from pypy.rlib.rarithmetic import r_longlong
 from pypy.rpython.extfunc import (
-    BaseLazyRegistering, lazy_register, register_external)
+    BaseLazyRegistering, register_external)
 from pypy.rpython.extfunc import registering, registering_if, extdef
 from pypy.annotation.model import (
     SomeInteger, SomeString, SomeTuple, SomeFloat, SomeUnicodeString)
@@ -20,21 +20,14 @@
 from pypy.rpython.lltypesystem import lltype
 from pypy.rpython.tool import rffi_platform as platform
 from pypy.rlib import rposix
-from pypy.tool.udir import udir
 from pypy.translator.tool.cbuild import ExternalCompilationInfo
-from pypy.rpython.lltypesystem.rstr import mallocstr
-from pypy.rpython.annlowlevel import llstr
-from pypy.rpython.lltypesystem.llmemory import sizeof,\
-     itemoffsetof, cast_ptr_to_adr, cast_adr_to_ptr, offsetof
+from pypy.rpython.lltypesystem.llmemory import itemoffsetof, offsetof
 from pypy.rpython.lltypesystem.rstr import STR
-from pypy.rpython.annlowlevel import llstr
-from pypy.rlib import rgc
 from pypy.rlib.objectmodel import specialize
 
 str0 = SomeString(no_nul=True)
 unicode0 = SomeUnicodeString(no_nul=True)
 
-
 def monkeypatch_rposix(posixfunc, unicodefunc, signature):
     func_name = posixfunc.__name__
 
@@ -514,27 +507,23 @@
             from pypy.rpython.module.ll_win32file import make_utime_impl
             os_utime_llimpl = make_utime_impl(traits)
 
-        if traits.str is str:
-            s_string = SomeString()
-        else:
-            s_string = SomeUnicodeString()
         s_tuple_of_2_floats = SomeTuple([SomeFloat(), SomeFloat()])
 
         def os_utime_normalize_args(s_path, s_times):
             # special handling of the arguments: they can be either
             # [str, (float, float)] or [str, s_None], and get normalized
             # to exactly one of these two.
-            if not s_string.contains(s_path):
+            if not traits.str0.contains(s_path):
                 raise Exception("os.utime() arg 1 must be a string, got %s" % (
                     s_path,))
             case1 = s_None.contains(s_times)
             case2 = s_tuple_of_2_floats.contains(s_times)
             if case1 and case2:
-                return [s_string, s_ImpossibleValue] #don't know which case yet
+                return [traits.str0, s_ImpossibleValue] #don't know which case yet
             elif case1:
-                return [s_string, s_None]
+                return [traits.str0, s_None]
             elif case2:
-                return [s_string, s_tuple_of_2_floats]
+                return [traits.str0, s_tuple_of_2_floats]
             else:
                 raise Exception("os.utime() arg 2 must be None or a tuple of "
                                 "2 floats, got %s" % (s_times,))
@@ -977,7 +966,7 @@
 
         os_lseek = self.llexternal(funcname,
                                    [rffi.INT, rffi.LONGLONG, rffi.INT],
-                                   rffi.LONGLONG)
+                                   rffi.LONGLONG, macro=True)
 
         def lseek_llimpl(fd, pos, how):
             rposix.validate_fd(fd)
@@ -1544,9 +1533,8 @@
     def register_os_umask(self):
         os_umask = self.llexternal(underscore_on_windows+'umask', [rffi.MODE_T], rffi.MODE_T)
 
-        def umask_llimpl(fd):
-            rposix.validate_fd(fd)
-            res = os_umask(rffi.cast(rffi.MODE_T, fd))
+        def umask_llimpl(newmask):
+            res = os_umask(rffi.cast(rffi.MODE_T, newmask))
             return rffi.cast(lltype.Signed, res)
 
         return extdef([int], int, llimpl=umask_llimpl,
@@ -1556,13 +1544,11 @@
     def register_os_kill(self):
         os_kill = self.llexternal('kill', [rffi.PID_T, rffi.INT],
                                   rffi.INT)
-
         def kill_llimpl(pid, sig):
             res = rffi.cast(lltype.Signed, os_kill(rffi.cast(rffi.PID_T, pid),
                                                    rffi.cast(rffi.INT, sig)))
             if res < 0:
                 raise OSError(rposix.get_errno(), "os_kill failed")
-
         return extdef([int, int], s_None, llimpl=kill_llimpl,
                       export_name="ll_os.ll_os_kill")
 
diff --git a/pypy/rpython/module/test/test_ll_os.py b/pypy/rpython/module/test/test_ll_os.py
--- a/pypy/rpython/module/test/test_ll_os.py
+++ b/pypy/rpython/module/test/test_ll_os.py
@@ -252,6 +252,22 @@
     os.close(fd)
     raises(OSError, f, fd)
 
+
+def test_os_kill():
+    if not hasattr(os,'kill') or sys.platform == 'win32':
+        skip('No kill in os')
+    f = getllimpl(os.kill)
+    import subprocess
+    import signal
+    proc = subprocess.Popen([sys.executable, "-c",
+                         "import time;"
+                         "time.sleep(10)",
+                         ],
+                        )
+    f(proc.pid, signal.SIGTERM)
+    expected = -signal.SIGTERM
+    assert proc.wait() == expected
+
 class ExpectTestOs:
     def setup_class(cls):
         if not hasattr(os, 'ttyname'):
@@ -273,3 +289,4 @@
 
         assert ll_to_string(interpret(f, [0])) == f(0)
         assert ll_to_string(interpret(f, [338])) == ''
+
diff --git a/pypy/rpython/rbuiltin.py b/pypy/rpython/rbuiltin.py
--- a/pypy/rpython/rbuiltin.py
+++ b/pypy/rpython/rbuiltin.py
@@ -247,6 +247,11 @@
     vlist = hop.inputargs(lltype.Signed)
     return vlist[0]
 
+def rtype_longlongmask(hop):
+    hop.exception_cannot_occur()
+    vlist = hop.inputargs(lltype.SignedLongLong)
+    return vlist[0]
+
 def rtype_builtin_min(hop):
     v1, v2 = hop.inputargs(hop.r_result, hop.r_result)
     hop.exception_cannot_occur()
@@ -564,6 +569,7 @@
 BUILTIN_TYPER[lltype.Ptr] = rtype_const_result
 BUILTIN_TYPER[lltype.runtime_type_info] = rtype_runtime_type_info
 BUILTIN_TYPER[rarithmetic.intmask] = rtype_intmask
+BUILTIN_TYPER[rarithmetic.longlongmask] = rtype_longlongmask
 
 BUILTIN_TYPER[objectmodel.hlinvoke] = rtype_hlinvoke
 
diff --git a/pypy/rpython/test/test_llinterp.py b/pypy/rpython/test/test_llinterp.py
--- a/pypy/rpython/test/test_llinterp.py
+++ b/pypy/rpython/test/test_llinterp.py
@@ -137,7 +137,7 @@
     info = py.test.raises(LLException, "interp.eval_graph(graph, values)")
     try:
         got = interp.find_exception(info.value)
-    except ValueError as message:
+    except ValueError, message:
         got = 'None %r' % message
     assert got is exc, "wrong exception type, expected %r got %r" % (exc, got)
 
diff --git a/pypy/rpython/test/test_rbuiltin.py b/pypy/rpython/test/test_rbuiltin.py
--- a/pypy/rpython/test/test_rbuiltin.py
+++ b/pypy/rpython/test/test_rbuiltin.py
@@ -5,7 +5,7 @@
 from pypy.rlib.debug import llinterpcall
 from pypy.rpython.lltypesystem import lltype
 from pypy.tool import udir
-from pypy.rlib.rarithmetic import intmask, is_valid_int
+from pypy.rlib.rarithmetic import intmask, longlongmask, r_int64, is_valid_int
 from pypy.rlib.rarithmetic import r_int, r_uint, r_longlong, r_ulonglong
 from pypy.annotation.builtin import *
 from pypy.rpython.test.tool import BaseRtypingTest, LLRtypeMixin, OORtypeMixin
@@ -79,6 +79,16 @@
         res = self.interpret(f, [r_uint(5)])
         assert type(res) is int and res == 5
 
+    def test_longlongmask(self):
+        def f(x=r_ulonglong):
+            try:
+                return longlongmask(x)
+            except ValueError:
+                return 0
+
+        res = self.interpret(f, [r_ulonglong(5)])
+        assert type(res) is r_int64 and res == 5
+
     def test_rbuiltin_list(self):
         def f(): 
             l=list((1,2,3))
diff --git a/pypy/rpython/test/test_rdict.py b/pypy/rpython/test/test_rdict.py
--- a/pypy/rpython/test/test_rdict.py
+++ b/pypy/rpython/test/test_rdict.py
@@ -759,13 +759,20 @@
         assert count_frees >= 3
 
     def test_dict_resize(self):
+        # XXX we no longer automatically resize on 'del'.  We need to
+        # hack a bit in this test to trigger a resize by continuing to
+        # fill the dict's table while keeping the actual size very low
+        # in order to force a resize to shrink the table back
         def func(want_empty):
             d = {}
-            for i in range(rdict.DICT_INITSIZE):
+            for i in range(rdict.DICT_INITSIZE << 1):
                 d[chr(ord('a') + i)] = i
             if want_empty:
-                for i in range(rdict.DICT_INITSIZE):
+                for i in range(rdict.DICT_INITSIZE << 1):
                     del d[chr(ord('a') + i)]
+                for i in range(rdict.DICT_INITSIZE << 3):
+                    d[chr(ord('A') - i)] = i
+                    del d[chr(ord('A') - i)]
             return d
         res = self.interpret(func, [0])
         assert len(res.entries) > rdict.DICT_INITSIZE
diff --git a/pypy/rpython/tool/rfficache.py b/pypy/rpython/tool/rfficache.py
--- a/pypy/rpython/tool/rfficache.py
+++ b/pypy/rpython/tool/rfficache.py
@@ -4,17 +4,16 @@
 
 import py
 import os
-import distutils
 from pypy.translator.tool.cbuild import ExternalCompilationInfo
 from pypy.tool.udir import udir
-from pypy.tool.autopath import pypydir
 from pypy.rlib import rarithmetic
 from pypy.rpython.lltypesystem import lltype
 from pypy.tool.gcc_cache import build_executable_cache
 
 def ask_gcc(question, add_source=""):
+    from pypy.translator.platform import platform
     includes = ['stdlib.h', 'stdio.h', 'sys/types.h']
-    if os.name != 'nt':
+    if platform.name != 'msvc':
         includes += ['inttypes.h']
     include_string = "\n".join(["#include <%s>" % i for i in includes])
     c_source = py.code.Source('''
diff --git a/pypy/testrunner_cfg.py b/pypy/testrunner_cfg.py
--- a/pypy/testrunner_cfg.py
+++ b/pypy/testrunner_cfg.py
@@ -1,15 +1,16 @@
 # nightly test configuration for the paraller runner
 import os
 
+DIRS_SPLIT = [
+    'translator/c', 'translator/jvm', 'rlib', 'rpython/memory',
+    'jit/backend/x86', 'jit/metainterp', 'rpython/test',
+]
+
 def collect_one_testdir(testdirs, reldir, tests):
-    if (reldir.startswith('translator/c/') or 
-        reldir.startswith('translator/jvm/') or
-        reldir.startswith('rlib/test') or
-        reldir.startswith('rpython/memory/') or
-        reldir.startswith('jit/backend/x86/') or
-        #reldir.startswith('jit/backend/cli') or
-        0):
-        testdirs.extend(tests)
+    for dir in DIRS_SPLIT:
+        if reldir.startswith(dir):
+            testdirs.extend(tests)
+            break
     else:
         testdirs.append(reldir)
 
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
@@ -21,6 +21,8 @@
 
 USE_ZIPFILE_MODULE = sys.platform == 'win32'
 
+STDLIB_VER = "2.7"
+
 def ignore_patterns(*patterns):
     """Function that can be used as copytree() ignore parameter.
 
@@ -52,7 +54,15 @@
         pypy_c = py.path.local(override_pypy_c)
     if not pypy_c.check():
         print pypy_c
-        raise PyPyCNotFound('Please compile pypy first, using translate.py')
+        if os.path.isdir(os.path.dirname(str(pypy_c))):
+            raise PyPyCNotFound(
+                'Please compile pypy first, using translate.py,'
+                ' or check that you gave the correct path'
+                ' (see docstring for more info)')
+        else:
+            raise PyPyCNotFound(
+                'Bogus path: %r does not exist (see docstring for more info)'
+                % (os.path.dirname(str(pypy_c)),))
     if sys.platform == 'win32' and not rename_pypy_c.lower().endswith('.exe'):
         rename_pypy_c += '.exe'
     binaries = [(pypy_c, rename_pypy_c)]
@@ -77,8 +87,8 @@
     pypydir = builddir.ensure(name, dir=True)
     # Careful: to copy lib_pypy, copying just the svn-tracked files
     # would not be enough: there are also ctypes_config_cache/_*_cache.py.
-    shutil.copytree(str(basedir.join('lib-python')),
-                    str(pypydir.join('lib-python')),
+    shutil.copytree(str(basedir.join('lib-python').join(STDLIB_VER)),
+                    str(pypydir.join('lib-python').join(STDLIB_VER)),
                     ignore=ignore_patterns('.svn', 'py', '*.pyc', '*~'))
     shutil.copytree(str(basedir.join('lib_pypy')),
                     str(pypydir.join('lib_pypy')),
diff --git a/pypy/tool/release/win32build.py b/pypy/tool/release/win32build.py
deleted file mode 100644
--- a/pypy/tool/release/win32build.py
+++ /dev/null
@@ -1,29 +0,0 @@
-import autopath
-import package
-import subprocess
-import py, sys
-import shutil
-
-pypydir = py.path.local(autopath.pypydir)
-builddir = pypydir.join('translator', 'goal')
-
-VERSION = "1.5.0a0"
-
-def make_pypy(tag, options):
-    pypy = 'pypy%s' % (tag,)
-    args = [sys.executable,
-         str(builddir.join('translate.py')),
-         '--output=' + pypy,
-         ] + options
-    print "Execute", args
-    p = subprocess.Popen(args, cwd=str(builddir))
-    p.wait()
-    zipfile = 'pypy-%s-win32%s' % (VERSION, tag)
-    package.package(pypydir.dirpath(), zipfile, pypy, pypydir)
-
-shutil.copy(str(pypydir.join('..', '..', 'expat-2.0.1', 'win32', 'bin', 'release', 'libexpat.dll')), str(builddir))
-
-make_pypy('',            ['-Ojit'])
-make_pypy('-nojit',      ['-O2'])
-#make_pypy('-stackless', [--stackless])
-#make_pypy('-sandbox',   [--sandbox])
diff --git a/pypy/tool/test/test_package.py b/pypy/tool/test/test_package.py
new file mode 100644
--- /dev/null
+++ b/pypy/tool/test/test_package.py
@@ -0,0 +1,6 @@
+from pypy.tool.release import package
+from pypy.module.sys import version
+
+def test_version():
+    assert package.STDLIB_VER == '%d.%d' % (version.CPYTHON_VERSION[0],
+                                            version.CPYTHON_VERSION[1])
diff --git a/pypy/translator/backendopt/test/test_finalizer.py b/pypy/translator/backendopt/test/test_finalizer.py
--- a/pypy/translator/backendopt/test/test_finalizer.py
+++ b/pypy/translator/backendopt/test/test_finalizer.py
@@ -84,8 +84,8 @@
 
             def __del__(self):
                 if self.x:
+                    lltype.free(self.x, flavor='raw')
                     self.x = lltype.nullptr(S)
-                    lltype.free(self.x, flavor='raw')
 
         def f():
             return A()
diff --git a/pypy/translator/c/database.py b/pypy/translator/c/database.py
--- a/pypy/translator/c/database.py
+++ b/pypy/translator/c/database.py
@@ -62,7 +62,7 @@
         else:
             self.exctransformer = translator.getexceptiontransformer()
         if translator is not None:
-            self.gctransformer = self.gcpolicy.transformerclass(translator)
+            self.gctransformer = self.gcpolicy.gettransformer()
         self.completed = False
 
         self.instrument_ncounter = 0
diff --git a/pypy/translator/c/gc.py b/pypy/translator/c/gc.py
--- a/pypy/translator/c/gc.py
+++ b/pypy/translator/c/gc.py
@@ -5,8 +5,6 @@
 from pypy.rpython.lltypesystem.lltype import \
      typeOf, Ptr, ContainerType, RttiStruct, \
      RuntimeTypeInfo, getRuntimeTypeInfo, top_container
-from pypy.rpython.memory.gctransform import \
-     refcounting, boehm, framework, asmgcroot
 from pypy.rpython.lltypesystem import lltype, llmemory
 from pypy.translator.tool.cbuild import ExternalCompilationInfo
 
@@ -111,7 +109,10 @@
 from pypy.rlib.objectmodel import CDefinedIntSymbolic
 
 class RefcountingGcPolicy(BasicGcPolicy):
-    transformerclass = refcounting.RefcountingGCTransformer
+
+    def gettransformer(self):
+        from pypy.rpython.memory.gctransform import refcounting
+        return refcounting.RefcountingGCTransformer(self.db.translator)
 
     def common_gcheader_initdata(self, defnode):
         if defnode.db.gctransformer is not None:
@@ -196,7 +197,10 @@
 
 
 class BoehmGcPolicy(BasicGcPolicy):
-    transformerclass = boehm.BoehmGCTransformer
+
+    def gettransformer(self):
+        from pypy.rpython.memory.gctransform import boehm
+        return boehm.BoehmGCTransformer(self.db.translator)
 
     def common_gcheader_initdata(self, defnode):
         if defnode.db.gctransformer is not None:
@@ -246,9 +250,11 @@
         yield 'boehm_gc_startup_code();'
 
     def get_real_weakref_type(self):
+        from pypy.rpython.memory.gctransform import boehm
         return boehm.WEAKLINK
 
     def convert_weakref_to(self, ptarget):
+        from pypy.rpython.memory.gctransform import boehm
         return boehm.convert_weakref_to(ptarget)
 
     def OP_GC__COLLECT(self, funcgen, op):
@@ -305,7 +311,12 @@
 
 
 class FrameworkGcPolicy(BasicGcPolicy):
-    transformerclass = framework.FrameworkGCTransformer
+
+    def gettransformer(self):
+        if hasattr(self, 'transformerclass'):    # for rpython/memory tests
+            return self.transformerclass(self.db.translator)
+        from pypy.rpython.memory.gctransform import framework
+        return framework.FrameworkGCTransformer(self.db.translator)
 
     def struct_setup(self, structdefnode, rtti):
         if rtti is not None and hasattr(rtti._obj, 'destructor_funcptr'):
@@ -337,9 +348,11 @@
         yield '%s();' % (self.db.get(fnptr),)
 
     def get_real_weakref_type(self):
+        from pypy.rpython.memory.gctransform import framework
         return framework.WEAKREF
 
     def convert_weakref_to(self, ptarget):
+        from pypy.rpython.memory.gctransform import framework
         return framework.convert_weakref_to(ptarget)
 
     def OP_GC_RELOAD_POSSIBLY_MOVED(self, funcgen, op):
@@ -395,7 +408,10 @@
         raise Exception("the FramewokGCTransformer should handle this")
 
 class AsmGcRootFrameworkGcPolicy(FrameworkGcPolicy):
-    transformerclass = asmgcroot.AsmGcRootFrameworkGCTransformer
+
+    def gettransformer(self):
+        from pypy.rpython.memory.gctransform import asmgcroot
+        return asmgcroot.AsmGcRootFrameworkGCTransformer(self.db.translator)
 
     def GC_KEEPALIVE(self, funcgen, v):
         return 'pypy_asm_keepalive(%s);' % funcgen.expr(v)
diff --git a/pypy/translator/c/test/test_extfunc.py b/pypy/translator/c/test/test_extfunc.py
--- a/pypy/translator/c/test/test_extfunc.py
+++ b/pypy/translator/c/test/test_extfunc.py
@@ -134,6 +134,13 @@
         res = os.lseek(fd, -r5200000000, 2)
         assert res == r4800000000
         os.close(fd)
+        try:
+            os.lseek(fd, 0, 0)
+        except OSError:
+            pass
+        else:
+            print "DID NOT RAISE"
+            raise AssertionError
         st = os.stat(filename)
         assert st.st_size == r10000000000
     does_stuff()
diff --git a/pypy/translator/c/test/test_typed.py b/pypy/translator/c/test/test_typed.py
--- a/pypy/translator/c/test/test_typed.py
+++ b/pypy/translator/c/test/test_typed.py
@@ -885,3 +885,13 @@
         assert res == 'acquire, hello, raised, release'
         res = f(2)
         assert res == 'acquire, hello, raised, release'
+
+    def test_longlongmask(self):
+        from pypy.rlib.rarithmetic import longlongmask, r_ulonglong
+        def func(n):
+            m = r_ulonglong(n)
+            m *= 100000
+            return longlongmask(m)
+        f = self.getcompiled(func, [int])
+        res = f(-2000000000)
+        assert res == -200000000000000
diff --git a/pypy/translator/cli/test/test_builtin.py b/pypy/translator/cli/test/test_builtin.py
--- a/pypy/translator/cli/test/test_builtin.py
+++ b/pypy/translator/cli/test/test_builtin.py
@@ -16,7 +16,10 @@
     test_os_isdir = skip_os
     test_os_dup_oo = skip_os
     test_os_access = skip_os
-        
+
+    def test_longlongmask(self):
+        py.test.skip("fix me")
+    
     def test_builtin_math_frexp(self):
         self._skip_powerpc("Mono math floating point problem")
         BaseTestBuiltin.test_builtin_math_frexp(self)
diff --git a/pypy/translator/goal/win32/gc_patch_windows.py b/pypy/translator/goal/win32/gc_patch_windows.py
deleted file mode 100644
--- a/pypy/translator/goal/win32/gc_patch_windows.py
+++ /dev/null
@@ -1,129 +0,0 @@
-# patches for the Boehm GC for PyPy under Windows
-
-"""
-This file is obsolete now since gc-7.0 / gc-7.1 .
-Please use the instructions in pypy\doc\windows.rst .
-
-How to build a pypy compatible version of the Boehm collector
-for Windows and Visual Studio .net 2003.
-
-First of all, download the official Boehm collector suite
-from http://www.hpl.hp.com/personal/Hans_Boehm/gc/gc_source/gc.tar.gz
-At the time of writing (2005-10-06) this contains version gc6.5 .
-
-Unpack this folder somewhere, for instance to "d:\tmp".
-Change to this folder using
-
-d:
-cd \tmp\gc6.5
-
-Then copy the file NT_THREADS_MAKEFILE to Makefile:
-
-copy NT_THREADS_MAKEFILE Makefile
-
-This file is the general-purpose gc dll makefile. For some internal
-reasons, this file's defaults are bad for PyPy. The early initialisation
-in DllMain() inhibits the changes necessary for PyPy. Use this script to
-do a patch: (assuming that you have d:\pypy\dist\pypy\translator\goal)
-
-python d:\pypy\dist\pypy\translator\goal\win32\gc_patch_windows.py
-
-Now, your makefile is patched a little bit. In particular,
-
-ALL_INTERIOR_POINTERS   is now undefined, which PyPy wants to have
-NO_GETENV               is specified, since we don't want dependencies
-
-and the name of the .lib and .dll files is changed to gc_pypy.???
-
-Now you need to build your gc, either as a debug or as a release
-build. First of all, make sure that you have your environment prepared.
-Please note that you will need to use Microsoft's cmd, as cygwin bash
-doesn't correctly handle the batch file in the next step.
-
-With my setup, I have to do
-
-"e:\Programme\Microsoft Visual Studio .NET 2003\Vc7\bin\vcvars32.bat"
-
-After that, you can either build a release or a debug gc. 
-
-After a successful build, you need to enable gc_pypy.dll for your compiler.
-There are many ways to install this. The following recommendation just
-works without changing your environment variables. I think this is the
-easiest way possible, but this is a matter of taste. What I did is:
-
-nmake CFG="gc - Win32 Release"
-
-After the build, you will find a gc_pypy.dll file in the Release folder.
-Copy this file to c:\windows\system32 or any other folder that is always
-in your PATH variable.
-
-Also, copy Release\gc_pypy.lib to (in my case)
-"e:\Programme\Microsoft Visual Studio .NET 2003\Vc7\lib";
-
-finally, copy d:\tmp\gc6.5\include to
-"e:\Programme\Microsoft Visual Studio .NET 2003\Vc7\include"
-and rename this folder to "gc", so that "gc/gc.h" is valid.
-
-That's all, folks!
-
-In case of a debug build, replace "Release" by "Debug", and also copy
-gc_pypy.pdb to your lib folder. This allows you to use source-level
-debugging. Please note: If you want to both build the default gc.dll
-and gc_pypy.dll, please delete the Debug resp. Release folders in
-between. The generated .sbr files are in the way.
-
-Please use the above recipe and report any bugs to me.
-In case of trouble, I also can provide you with pre-built dlls.
-Note: We also could have solved this by including the gc source
-into the PyPy build. This may or may not become necessary if something
-changes dramatically, again. As long as this is not needed, I prefer
-this simple solution.
-
-Summary transcript of the steps involved: (please adjust paths)
-
-d:
-cd \tmp\gc6.5
-copy NT_THREADS_MAKEFILE Makefile
-python d:\pypy\dist\pypy\translator\goal\win32\gc_patch_windows.py
-"e:\Programme\Microsoft Visual Studio .NET 2003\Vc7\bin\vcvars32.bat"
-nmake CFG="gc - Win32 Release"
-copy Release\gc_pypy.dll c:\windows\system32
-copy Release\gc_pypy.lib "e:\Programme\Microsoft Visual Studio .NET 2003\Vc7\lib"
-mkdir "e:\Programme\Microsoft Visual Studio .NET 2003\Vc7\include\gc"
-copy include "e:\Programme\Microsoft Visual Studio .NET 2003\Vc7\include\gc"
-
-cheers - chris
-"""
-
-REPLACE = {
-    '"ALL_INTERIOR_POINTERS"': '"NO_GETENV"',
-    }
-
-for ending in "lib exp map pdb bsc dll pch".split():
-    REPLACE["gc.%s" % ending] = "gc_pypy.%s" % ending
-
-def change_settings(src):
-    for old, new in REPLACE.items():
-        newsrc = src.replace(old, new)
-        if newsrc == src:
-            raise ValueError, "this makefile does not contain %s" % old
-        src = newsrc
-    return src
-
-def find_file():
-    import os
-    for name in os.listdir("."):
-        if name.lower() == 'makefile':
-            return name
-    else:
-        raise ValueError, 'Makefile not found'
-
-try:
-    name = find_file()
-    source = change_settings(file(name).read())
-    file(name, "w").write(source)
-    print "Updated your Makefile to fit PyPy's needs. Your lib will be named gc_pypy.dll"
-    print "and gc_pypy.lib. Please put them into appropriate places, see __doc__."
-except:
-    print __doc__
-    raise
diff --git a/pypy/translator/jvm/test/test_builtin.py b/pypy/translator/jvm/test/test_builtin.py
--- a/pypy/translator/jvm/test/test_builtin.py
+++ b/pypy/translator/jvm/test/test_builtin.py
@@ -47,6 +47,9 @@
         res = self.interpret(fn, [])
         assert stat.S_ISREG(res)
 
+    def test_longlongmask(self):
+        py.test.skip("fix me")
+
 class TestJvmTime(JvmTest, BaseTestTime):
 
     pass
diff --git a/pypy/translator/platform/posix.py b/pypy/translator/platform/posix.py
--- a/pypy/translator/platform/posix.py
+++ b/pypy/translator/platform/posix.py
@@ -55,6 +55,9 @@
 
         if relto:
             response_file = relto.bestrelpath(response_file)
+        if self.cc == 'mingw32' or (self.cc== 'gcc' and os.name=='nt'):    
+            return ["-Wl,--export-all-symbols,--version-script=%s" % \
+                    (response_file,)]
         return ["-Wl,--export-dynamic,--version-script=%s" % (response_file,)]
 
     def _link(self, cc, ofiles, link_args, standalone, exe_name):
diff --git a/pypy/translator/platform/windows.py b/pypy/translator/platform/windows.py
--- a/pypy/translator/platform/windows.py
+++ b/pypy/translator/platform/windows.py
@@ -13,7 +13,7 @@
         cc = os.environ.get('CC','')
     if not cc:
         return MsvcPlatform(cc=cc, x64=x64_flag)
-    elif cc.startswith('mingw'):
+    elif cc.startswith('mingw') or cc == 'gcc':
         return MingwPlatform(cc)
     try:
         subprocess.check_output([cc, '--version'])
diff --git a/testrunner/filetimes.py b/testrunner/filetimes.py
new file mode 100644
--- /dev/null
+++ b/testrunner/filetimes.py
@@ -0,0 +1,59 @@
+from lxml.etree import parse
+from collections import defaultdict
+from os.path import join, exists
+import argparse
+parser = argparse.ArgumentParser()
+parser.add_argument('junitxml')
+parser.add_argument('fileroot')
+
+opts = parser.parse_args()
+
+xml = parse(opts.junitxml)
+root = xml.getroot()
+
+
+bugstarts = 'interpreter', 'tool', 'module'
+def findfile(root, classname):
+    if not classname:
+        return
+    parts = classname.split('.')
+    
+    #pytest bug workaround
+    first = parts[0]
+    for start in bugstarts:
+        if first.startswith(start) and \
+           first != start and \
+           first[len(start)] != '.':
+            parts[0] = start
+            parts.insert(1, 'py'+first[len(start):])
+
+    while parts:
+        path = join(root, *parts) + '.py'
+        if exists(path):
+            return join(*parts) + '.py'
+        parts.pop()
+
+accum = defaultdict(list)
+garbageitems = []
+
+for item in root:
+    filename = findfile(opts.fileroot, item.attrib['classname'])
+    accum[filename].append(float(item.attrib['time']))
+    if filename is None:
+        garbageitems.append(item)
+
+
+
+
+garbage = accum.pop(None, [])
+if garbage:
+    print 'garbage', sum(garbage), len(garbage)
+
+for key in sorted(accum):
+    value = accum[key]
+    print key, sum(value), len(value)
+
+print '-'*30
+
+for item in garbageitems:
+    print item.attrib
diff --git a/testrunner/junitmerge.py b/testrunner/junitmerge.py
new file mode 100644
--- /dev/null
+++ b/testrunner/junitmerge.py
@@ -0,0 +1,49 @@
+"""
+simple scrpt for junitxml file merging
+"""
+
+from lxml.etree import parse, Element, tostring
+from collections import defaultdict
+import argparse
+
+parser = argparse.ArgumentParser()
+parser.add_argument('--out')
+parser.add_argument('path', nargs='...')
+
+opts = parser.parse_args()
+
+files = []
+
+for path in opts.path:
+    files.append(parse(path))
+
+
+accum = defaultdict(int)
+children = []
+
+for item in files:
+    root = item.getroot()
+    for key, value in root.attrib.items():
+        if not value:
+            continue
+        value = float(value) if '.' in value else int(value)
+        accum[key] += value
+    children.extend(root)
+
+
+
+
+assert len(children) == sum(accum[x] for x in 'tests errors skips'.split())
+
+children.sort(key=lambda x:(x.attrib['classname'], x.attrib['name']))
+
+
+
+new = Element('testsuite', dict((k, str(v)) for k, v in accum.items()))
+new.extend(children)
+
+data = tostring(new)
+
+with open(opts.out, 'w') as fp:
+    fp.write(data)
+


More information about the pypy-commit mailing list