Author: Philip Jenvey <pjen...@underboss.org>
Branch: py3.3
Changeset: r73636:ac2759ae7eb6
Date: 2014-09-18 21:14 -0700
http://bitbucket.org/pypy/pypy/changeset/ac2759ae7eb6/

Log:    merge py3k

diff --git a/pypy/doc/windows.rst b/pypy/doc/windows.rst
--- a/pypy/doc/windows.rst
+++ b/pypy/doc/windows.rst
@@ -85,10 +85,13 @@
 
 Abridged method (for -Ojit builds using Visual Studio 2008)
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-Download the versions of all the external packages
-from 
+Download the versions of all the external packages from 
+https://bitbucket.org/pypy/pypy/downloads/local_2.4.zip
+(for 2.4 release and later) or
 https://bitbucket.org/pypy/pypy/downloads/local.zip
-Then expand it into the base directory (base_dir) and modify your environment 
to reflect this::
+(for pre-2.4 versions)
+Then expand it into the base directory (base_dir) and modify your environment
+to reflect this::
 
     set PATH=<base_dir>\bin;<base_dir>\tcltk\bin;%PATH%
     set INCLUDE=<base_dir>\include;<base_dir>\tcltk\include;%INCLUDE%
diff --git a/pypy/interpreter/pycode.py b/pypy/interpreter/pycode.py
--- a/pypy/interpreter/pycode.py
+++ b/pypy/interpreter/pycode.py
@@ -46,6 +46,7 @@
 def cpython_code_signature(code):
     "([list-of-arg-names], vararg-name-or-None, kwarg-name-or-None)."
     argcount = code.co_argcount
+    varnames = code.co_varnames
     if we_are_translated():
         kwonlyargcount = code.co_kwonlyargcount
     else:
@@ -53,16 +54,18 @@
         kwonlyargcount = getattr(code, 'co_kwonlyargcount', 0)
     assert argcount >= 0     # annotator hint
     assert kwonlyargcount >= 0
-    argnames = list(code.co_varnames[:argcount])
-    kwonlyargs = list(code.co_varnames[argcount:argcount + kwonlyargcount])
+    argnames = list(varnames[:argcount])
+    if argcount < len(varnames):
+        kwonlyargs = list(varnames[argcount:argcount + kwonlyargcount])
+    else:
+        kwonlyargs = None
     if code.co_flags & CO_VARARGS:
-        varargname = code.co_varnames[argcount]
+        varargname = varnames[argcount]
         argcount += 1
     else:
         varargname = None
     if code.co_flags & CO_VARKEYWORDS:
         kwargname = code.co_varnames[argcount + kwonlyargcount]
-        argcount += 1
     else:
         kwargname = None
     return Signature(argnames, varargname, kwargname, kwonlyargs)
diff --git a/pypy/interpreter/pyparser/parsestring.py 
b/pypy/interpreter/pyparser/parsestring.py
--- a/pypy/interpreter/pyparser/parsestring.py
+++ b/pypy/interpreter/pyparser/parsestring.py
@@ -82,12 +82,6 @@
     v = PyString_DecodeEscape(space, substr, 'strict', encoding)
     return space.wrapbytes(v)
 
-def hexbyte(val):
-    result = "%x" % val
-    if len(result) == 1:
-        result = "0" + result
-    return result
-
 def decode_unicode_utf8(space, s, ps, q):
     # ****The Python 2.7 version, producing UTF-32 escapes****
     # String is utf8-encoded, but 'unicode_escape' expects
@@ -107,15 +101,14 @@
                 # instead.
                 lis.append("u005c")
         if ord(s[ps]) & 0x80: # XXX inefficient
-            w, ps = decode_utf8(space, s, ps, end, "utf-32-be")
-            rn = len(w)
-            assert rn % 4 == 0
-            for i in range(0, rn, 4):
-                lis.append('\\U')
-                lis.append(hexbyte(ord(w[i])))
-                lis.append(hexbyte(ord(w[i+1])))
-                lis.append(hexbyte(ord(w[i+2])))
-                lis.append(hexbyte(ord(w[i+3])))
+            w, ps = decode_utf8(space, s, ps, end)
+            for c in w:
+                # The equivalent of %08x, which is not supported by RPython.
+                # 7 zeroes are enough for the unicode range, and the
+                # result still fits in 32-bit.
+                hexa = hex(ord(c) + 0x10000000)
+                lis.append('\\U0')
+                lis.append(hexa[3:])  # Skip 0x and the leading 1
         else:
             lis.append(s[ps])
             ps += 1
@@ -135,7 +128,7 @@
             # note that the C code has a label here.
             # the logic is the same.
             if recode_encoding and ord(s[ps]) & 0x80:
-                w, ps = decode_utf8(space, s, ps, end, recode_encoding)
+                w, ps = decode_utf8_recode(space, s, ps, end, recode_encoding)
                 # Append bytes to output buffer.
                 builder.append(w)
             else:
@@ -222,14 +215,18 @@
             ch >= 'A' and ch <= 'F')
 
 
-def decode_utf8(space, s, ps, end, encoding):
+def decode_utf8(space, s, ps, end):
     assert ps >= 0
     pt = ps
     # while (s < end && *s != '\\') s++; */ /* inefficient for u".."
     while ps < end and ord(s[ps]) & 0x80:
         ps += 1
-    w_u = space.wrap(unicodehelper.decode_utf8(space, s[pt:ps]))
-    w_v = unicodehelper.encode(space, w_u, encoding)
+    u = unicodehelper.decode_utf8(space, s[pt:ps])
+    return u, ps
+
+def decode_utf8_recode(space, s, ps, end, recode_encoding):
+    u, ps = decode_utf8(space, s, ps, end)
+    w_v = unicodehelper.encode(space, space.wrap(u), recode_encoding)
     v = space.bytes_w(w_v)
     return v, ps
 
diff --git a/pypy/interpreter/pyparser/test/test_parsestring.py 
b/pypy/interpreter/pyparser/test/test_parsestring.py
--- a/pypy/interpreter/pyparser/test/test_parsestring.py
+++ b/pypy/interpreter/pyparser/test/test_parsestring.py
@@ -100,11 +100,11 @@
 
     def test_simple_enc_roundtrip(self):
         space = self.space
-        s = "'\x81'"
+        s = "'\x81\\t'"
         s = s.decode("koi8-u").encode("utf8")
         w_ret = parsestring.parsestr(self.space, 'koi8-u', s)
         ret = space.unwrap(w_ret)
-        assert ret == eval("# -*- coding: koi8-u -*-\nu'\x81'") 
+        assert ret == eval("# -*- coding: koi8-u -*-\nu'\x81\\t'") 
 
     def test_multiline_unicode_strings_with_backslash(self):
         space = self.space
diff --git a/pypy/interpreter/test/test_app_main.py 
b/pypy/interpreter/test/test_app_main.py
--- a/pypy/interpreter/test/test_app_main.py
+++ b/pypy/interpreter/test/test_app_main.py
@@ -1064,7 +1064,7 @@
         prefix = udir.join('pathtest').ensure(dir=1)
         fake_exe = 'bin/pypy-c'
         if sys.platform == 'win32':
-            fake_exe += '.exe'
+            fake_exe = 'pypy-c.exe'
         fake_exe = prefix.join(fake_exe).ensure(file=1)
         expected_path = [str(prefix.join(subdir).ensure(dir=1))
                          for subdir in ('lib_pypy',
@@ -1104,8 +1104,10 @@
             assert sys.path == old_sys_path + [self.goal_dir]
 
             app_main.setup_bootstrap_path(self.fake_exe)
-            assert sys.executable == ''      # not executable!
-            assert sys.path == old_sys_path + [self.goal_dir]
+            if not sys.platform == 'win32':
+                # an existing file is always 'executable' on windows
+                assert sys.executable == ''      # not executable!
+                assert sys.path == old_sys_path + [self.goal_dir]
 
             os.chmod(self.fake_exe, 0o755)
             app_main.setup_bootstrap_path(self.fake_exe)
diff --git a/pypy/interpreter/test/test_code.py 
b/pypy/interpreter/test/test_code.py
--- a/pypy/interpreter/test/test_code.py
+++ b/pypy/interpreter/test/test_code.py
@@ -194,3 +194,9 @@
         # CO_NESTED
         assert d['f'](4).__code__.co_flags & 0x10
         assert d['f'].__code__.co_flags & 0x10 == 0
+
+    def test_issue1844(self):
+        import types
+        args = (1, 0, 1, 0, 0, b'', (), (), (), '', 'operator', 0, b'')
+        # previously raised a MemoryError when translated
+        types.CodeType(*args)
diff --git a/pypy/interpreter/unicodehelper.py 
b/pypy/interpreter/unicodehelper.py
--- a/pypy/interpreter/unicodehelper.py
+++ b/pypy/interpreter/unicodehelper.py
@@ -13,6 +13,7 @@
 
 @specialize.memo()
 def decode_error_handler(space):
+    # Fast version of the "strict" errors handler.
     def raise_unicode_exception_decode(errors, encoding, msg, s,
                                        startingpos, endingpos):
         raise OperationError(space.w_UnicodeDecodeError,
@@ -25,6 +26,7 @@
 
 @specialize.memo()
 def encode_error_handler(space):
+    # Fast version of the "strict" errors handler.
     def raise_unicode_exception_encode(errors, encoding, msg, u,
                                        startingpos, endingpos):
         raise OperationError(space.w_UnicodeEncodeError,
diff --git a/pypy/module/_cffi_backend/ctypefunc.py 
b/pypy/module/_cffi_backend/ctypefunc.py
--- a/pypy/module/_cffi_backend/ctypefunc.py
+++ b/pypy/module/_cffi_backend/ctypefunc.py
@@ -8,6 +8,7 @@
 from rpython.rlib.jit_libffi import (CIF_DESCRIPTION, CIF_DESCRIPTION_P,
     FFI_TYPE, FFI_TYPE_P, FFI_TYPE_PP, SIZE_OF_FFI_ARG)
 from rpython.rlib.objectmodel import we_are_translated, instantiate
+from rpython.rlib.objectmodel import keepalive_until_here
 from rpython.rtyper.lltypesystem import lltype, llmemory, rffi
 
 from pypy.interpreter.error import OperationError, oefmt
@@ -160,6 +161,7 @@
                         raw_cdata = rffi.cast(rffi.CCHARPP, data)[0]
                         lltype.free(raw_cdata, flavor='raw')
             lltype.free(buffer, flavor='raw')
+            keepalive_until_here(args_w)
         return w_res
 
 def get_mustfree_flag(data):
diff --git a/pypy/module/operator/app_operator.py 
b/pypy/module/operator/app_operator.py
--- a/pypy/module/operator/app_operator.py
+++ b/pypy/module/operator/app_operator.py
@@ -4,7 +4,8 @@
 This module exports a set of operators as functions. E.g. operator.add(x,y) is
 equivalent to x+y.
 '''
-from __pypy__ import builtinify
+
+import types
 
 
 def countOf(a,b):
@@ -15,51 +16,78 @@
             count += 1
     return count
 
+def _resolve_attr_chain(chain, obj, idx=0):
+    obj = getattr(obj, chain[idx])
+    if idx + 1 == len(chain):
+        return obj
+    else:
+        return _resolve_attr_chain(chain, obj, idx + 1)
+
+
+class _simple_attrgetter(object):
+    def __init__(self, attr):
+        self._attr = attr
+
+    def __call__(self, obj):
+        return getattr(obj, self._attr)
+
+
+class _single_attrgetter(object):
+    def __init__(self, attrs):
+        self._attrs = attrs
+
+    def __call__(self, obj):
+        return _resolve_attr_chain(self._attrs, obj)
+
+
+class _multi_attrgetter(object):
+    def __init__(self, attrs):
+        self._attrs = attrs
+
+    def __call__(self, obj):
+        return tuple([
+            _resolve_attr_chain(attrs, obj)
+            for attrs in self._attrs
+        ])
+
+
 def attrgetter(attr, *attrs):
+    if (
+        not isinstance(attr, str) or
+        not all(isinstance(a, str) for a in attrs)
+    ):
+        raise TypeError("attribute name must be a string, not %r" %
+                        type(attr).__name__)
     if attrs:
-        getters = [single_attr_getter(a) for a in (attr,) + attrs]
-        def getter(obj):
-            return tuple([getter(obj) for getter in getters])
+        return _multi_attrgetter([
+            a.split(".") for a in [attr] + list(attrs)
+        ])
+    elif "." not in attr:
+        return _simple_attrgetter(attr)
     else:
-        getter = single_attr_getter(attr)
-    return builtinify(getter)
+        return _single_attrgetter(attr.split("."))
 
-def single_attr_getter(attr):
-    if not isinstance(attr, str):
-        raise TypeError("attribute name must be a string, not {!r}".format(
-                type(attr).__name__))
-    #
-    def make_getter(name, prevfn=None):
-        if prevfn is None:
-            def getter(obj):
-                return getattr(obj, name)
+
+class itemgetter(object):
+    def __init__(self, item, *items):
+        self._single = not bool(items)
+        if self._single:
+            self._idx = item
         else:
-            def getter(obj):
-                return getattr(prevfn(obj), name)
-        return getter
-    #
-    last = 0
-    getter = None
-    while True:
-        dot = attr.find(".", last)
-        if dot < 0: break
-        getter = make_getter(attr[last:dot], getter)
-        last = dot + 1
-    return make_getter(attr[last:], getter)
+            self._idx = [item] + list(items)
 
+    def __call__(self, obj):
+        if self._single:
+            return obj[self._idx]
+        else:
+            return tuple([obj[i] for i in self._idx])
 
-def itemgetter(item, *items):
-    if items:
-        list_of_indices = [item] + list(items)
-        def getter(obj):
-            return tuple([obj[i] for i in list_of_indices])
-    else:
-        def getter(obj):
-            return obj[item]
-    return builtinify(getter)
 
+class methodcaller(object):
+    def __init__(self, method_name, *args, **kwargs):
+        self._method_name = method_name
+        self._args = args
+        self._kwargs = kwargs
 
-def methodcaller(method_name, *args, **kwargs):
-    def call(obj):
-        return getattr(obj, method_name)(*args, **kwargs)
-    return builtinify(call)
+    def __call__(self, obj):
+        return getattr(obj, self._method_name)(*self._args, **self._kwargs)
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
@@ -168,6 +168,11 @@
     # not visible via os, inconsistency in nt:
     if hasattr(posix, '_getfullpathname'):
         interpleveldefs['_getfullpathname'] = 'interp_posix._getfullpathname'
+    if os.name == 'nt':
+        interpleveldefs.update({
+                '_getfileinformation': 'interp_posix._getfileinformation',
+                '_getfinalpathname': 'interp_posix._getfinalpathname',
+        })
     if hasattr(os, 'chroot'):
         interpleveldefs['chroot'] = 'interp_posix.chroot'
 
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
@@ -5,8 +5,7 @@
 from rpython.rlib.objectmodel import specialize
 from rpython.rlib.rarithmetic import r_longlong
 from rpython.rlib.unroll import unrolling_iterable
-from rpython.rtyper.module import ll_os_stat
-from rpython.rtyper.module.ll_os import RegisterOs
+from rpython.rtyper.module import ll_os, ll_os_stat
 
 from pypy.interpreter.gateway import unwrap_spec, WrappedDefault
 from pypy.interpreter.error import OperationError, wrap_oserror, wrap_oserror2
@@ -1234,7 +1233,7 @@
         raise wrap_oserror(space, e)
 
 def declare_new_w_star(name):
-    if name in RegisterOs.w_star_returning_int:
+    if name in ll_os.RegisterOs.w_star_returning_int:
         @unwrap_spec(status=c_int)
         def WSTAR(space, status):
             return space.wrap(getattr(os, name)(status))
@@ -1246,7 +1245,7 @@
     WSTAR.func_name = name
     return WSTAR
 
-for name in RegisterOs.w_star:
+for name in ll_os.RegisterOs.w_star:
     if hasattr(os, name):
         func = declare_new_w_star(name)
         globals()[name] = func
@@ -1412,3 +1411,25 @@
         if codeset:
             return space.wrap(codeset)
     return space.w_None
+
+if _WIN32:
+    @unwrap_spec(fd=c_int)
+    def _getfileinformation(space, fd):
+        try:
+            info = ll_os._getfileinformation(fd)
+        except OSError as e:
+            raise wrap_oserror(space, e)
+        return space.newtuple([space.wrap(info[0]),
+                               space.wrap(info[1]),
+                               space.wrap(info[2])])
+
+    def _getfinalpathname(space, w_path):
+        path = space.unicode_w(w_path)
+        try:
+            result = ll_os._getfinalpathname(path)
+        except ll_os.LLNotImplemented as e:
+            raise OperationError(space.w_NotImplementedError,
+                                 space.wrap(e.msg))
+        except OSError as e:
+            raise wrap_oserror2(space, e, w_path)
+        return space.wrap(result)
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
@@ -1069,6 +1069,24 @@
         # just ensure it returns something reasonable
         assert encoding is None or type(encoding) is str
 
+    if os.name == 'nt':
+        def test__getfileinformation(self):
+            import os
+            path = os.path.join(self.pdir, 'file1')
+            with open(path) as fp:
+                info = self.posix._getfileinformation(fp.fileno())
+            assert len(info) == 3
+            assert all(isinstance(obj, int) for obj in info)
+
+        def test__getfinalpathname(self):
+            import os
+            path = os.path.join(self.pdir, 'file1')
+            try:
+                result = self.posix._getfinalpathname(path)
+            except NotImplementedError:
+                skip("_getfinalpathname not supported on this platform")
+            assert os.path.exists(result)
+
     def test_rtld_constants(self):
         # check presence of major RTLD_* constants
         self.posix.RTLD_LAZY
@@ -1076,6 +1094,7 @@
         self.posix.RTLD_GLOBAL
         self.posix.RTLD_LOCAL
 
+
 class AppTestEnvironment(object):
     def setup_class(cls):
         cls.space = space
diff --git a/pypy/module/sys/test/test_sysmodule.py 
b/pypy/module/sys/test/test_sysmodule.py
--- a/pypy/module/sys/test/test_sysmodule.py
+++ b/pypy/module/sys/test/test_sysmodule.py
@@ -127,9 +127,9 @@
         assert isinstance(sys.__stdin__, io.IOBase)
         assert sys.__stderr__.errors == 'backslashreplace'
 
-        assert sys.__stdin__.name == "<stdin>"
-        assert sys.__stdout__.name == "<stdout>"
-        assert sys.__stderr__.name == "<stderr>"
+        #assert sys.__stdin__.name == "<stdin>"
+        #assert sys.__stdout__.name == "<stdout>"
+        #assert sys.__stderr__.name == "<stderr>"
 
         if self.appdirect and not isinstance(sys.stdin, io.IOBase):
             return
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
@@ -306,10 +306,10 @@
         import imp
         argparse = imp.load_source('argparse', 'lib-python/2.7/argparse.py')
     if sys.platform == 'win32':
-        pypy_exe = 'pypy.exe'
+        pypy_exe = 'pypy3.exe'
         license_base = os.path.join(basedir, r'..\..\..\local') # as on 
buildbot YMMV
     else:
-        pypy_exe = 'pypy'
+        pypy_exe = 'pypy3'
         license_base = '/usr/share/doc'
     parser = argparse.ArgumentParser()
     args = list(args)
diff --git a/rpython/jit/backend/arm/callbuilder.py 
b/rpython/jit/backend/arm/callbuilder.py
--- a/rpython/jit/backend/arm/callbuilder.py
+++ b/rpython/jit/backend/arm/callbuilder.py
@@ -92,7 +92,8 @@
             self.mc.LDR_ri(r.r7.value, r.r5.value)
 
         # change 'rpy_fastgil' to 0 (it should be non-zero right now)
-        self.mc.DMB()
+        if self.asm.cpu.cpuinfo.arch_version >= 7:
+            self.mc.DMB()
         self.mc.gen_load_int(r.r6.value, fastgil)
         self.mc.MOV_ri(r.ip.value, 0)
         self.mc.STR_ri(r.ip.value, r.r6.value)
@@ -112,7 +113,8 @@
         self.mc.STREX(r.r3.value, r.ip.value, r.r6.value, c=c.EQ)
                                                  # try to claim the lock
         self.mc.CMP_ri(r.r3.value, 0, cond=c.EQ) # did this succeed?
-        self.mc.DMB()
+        if self.asm.cpu.cpuinfo.arch_version >= 7:
+            self.mc.DMB()
         # the success of the lock acquisition is defined by
         # 'EQ is true', or equivalently by 'r3 == 0'.
         #
diff --git a/rpython/jit/backend/arm/codebuilder.py 
b/rpython/jit/backend/arm/codebuilder.py
--- a/rpython/jit/backend/arm/codebuilder.py
+++ b/rpython/jit/backend/arm/codebuilder.py
@@ -333,6 +333,8 @@
                     | (rn & 0xF) << 16)
 
     def DMB(self):
+        # ARMv7 only.  I guess ARMv6 CPUs cannot be used in symmetric
+        # multi-processing at all? That would make this instruction unneeded.
         # note: 'cond' is only permitted on Thumb here, but don't
         # write literally 0xf57ff05f, because it's larger than 31 bits
         c = cond.AL
diff --git a/rpython/jit/backend/arm/instructions.py 
b/rpython/jit/backend/arm/instructions.py
--- a/rpython/jit/backend/arm/instructions.py
+++ b/rpython/jit/backend/arm/instructions.py
@@ -142,6 +142,7 @@
     #'VCVT' : {'opc1':0xB, 'opc2':0xE, 'opc3':0x1, 'base': False},
 }
 
+# ARMv7 only
 simd_instructions_3regs = {
     'VADD_i64': {'A': 0x8, 'B': 0, 'U': 0},
     'VSUB_i64': {'A': 0x8, 'B': 0, 'U': 1},
diff --git a/rpython/jit/backend/llsupport/rewrite.py 
b/rpython/jit/backend/llsupport/rewrite.py
--- a/rpython/jit/backend/llsupport/rewrite.py
+++ b/rpython/jit/backend/llsupport/rewrite.py
@@ -1,3 +1,4 @@
+from rpython.rlib import rgc
 from rpython.rlib.rarithmetic import ovfcheck
 from rpython.rtyper.lltypesystem import llmemory
 from rpython.jit.metainterp import history
@@ -390,8 +391,8 @@
         val = op.getarg(0)
         if val not in self.write_barrier_applied:
             v = op.getarg(1)
-            if isinstance(v, BoxPtr) or (isinstance(v, ConstPtr) and
-                                         bool(v.value)): # store a non-NULL
+            if (isinstance(v, BoxPtr) or (isinstance(v, ConstPtr) and
+                               rgc.needs_write_barrier(v.value))):
                 self.gen_write_barrier(val)
                 #op = op.copy_and_change(rop.SETFIELD_RAW)
         self.newops.append(op)
@@ -400,8 +401,8 @@
         val = op.getarg(0)
         if val not in self.write_barrier_applied:
             v = op.getarg(2)
-            if isinstance(v, BoxPtr) or (isinstance(v, ConstPtr) and
-                                         bool(v.value)): # store a non-NULL
+            if (isinstance(v, BoxPtr) or (isinstance(v, ConstPtr) and
+                                         rgc.needs_write_barrier(v.value))):
                 self.gen_write_barrier_array(val, op.getarg(1))
                 #op = op.copy_and_change(rop.SET{ARRAYITEM,INTERIORFIELD}_RAW)
         self.newops.append(op)
diff --git a/rpython/rlib/rdynload.py b/rpython/rlib/rdynload.py
--- a/rpython/rlib/rdynload.py
+++ b/rpython/rlib/rdynload.py
@@ -158,3 +158,4 @@
         return res
 
     LoadLibrary = rwin32.LoadLibrary
+    GetModuleHandle = rwin32.GetModuleHandle
diff --git a/rpython/rlib/rgc.py b/rpython/rlib/rgc.py
--- a/rpython/rlib/rgc.py
+++ b/rpython/rlib/rgc.py
@@ -86,6 +86,14 @@
         collect(i)
         i += 1
 
+def needs_write_barrier(obj):
+    """ We need to emit write barrier if the right hand of assignment
+    is in nursery, used by the JIT for handling set*_gc(Const)
+    """
+    if not obj:
+        return False
+    return can_move(obj)
+
 def _heap_stats():
     raise NotImplementedError # can't be run directly
 
diff --git a/rpython/rlib/rwin32.py b/rpython/rlib/rwin32.py
--- a/rpython/rlib/rwin32.py
+++ b/rpython/rlib/rwin32.py
@@ -130,6 +130,7 @@
     # is hidden by operations in ll2ctypes.  Call it now.
     GetLastError()
 
+    GetModuleHandle = winexternal('GetModuleHandleA', [rffi.CCHARP], HMODULE)
     LoadLibrary = winexternal('LoadLibraryA', [rffi.CCHARP], HMODULE)
     GetProcAddress = winexternal('GetProcAddress',
                                  [HMODULE, rffi.CCHARP],
diff --git a/rpython/rtyper/lltypesystem/ll2ctypes.py 
b/rpython/rtyper/lltypesystem/ll2ctypes.py
--- a/rpython/rtyper/lltypesystem/ll2ctypes.py
+++ b/rpython/rtyper/lltypesystem/ll2ctypes.py
@@ -361,7 +361,9 @@
             functype = ctypes.CFUNCTYPE
             if sys.platform == 'win32':
                 from rpython.rlib.clibffi import FFI_STDCALL, FFI_DEFAULT_ABI
-                if getattr(T.TO, 'ABI', FFI_DEFAULT_ABI) == FFI_STDCALL:
+                # XXX:
+                #if getattr(T.TO, 'ABI', FFI_DEFAULT_ABI) == FFI_STDCALL:
+                if getattr(T.TO, 'ABI', FFI_DEFAULT_ABI) == 'FFI_STDCALL':
                     # for win32 system call
                     functype = ctypes.WINFUNCTYPE
             argtypes = [get_ctypes_type(ARG) for ARG in T.TO.ARGS
diff --git a/rpython/rtyper/lltypesystem/lltype.py 
b/rpython/rtyper/lltypesystem/lltype.py
--- a/rpython/rtyper/lltypesystem/lltype.py
+++ b/rpython/rtyper/lltypesystem/lltype.py
@@ -1,16 +1,17 @@
-from types import NoneType, MethodType
 import weakref
+from types import MethodType, NoneType
+
+from rpython.annotator.bookkeeper import analyzer_for, immutablevalue
 from rpython.annotator.model import (
-        SomeInteger, SomeBool, SomeObject, AnnotatorError)
+        AnnotatorError, SomeBool, SomeInteger, SomeObject)
+from rpython.rlib.objectmodel import Symbolic
 from rpython.rlib.rarithmetic import (
-    r_int, r_uint, intmask, r_singlefloat, r_ulonglong, r_longlong,
-    r_longfloat, r_longlonglong, base_int, normalizedinttype, longlongmask,
-    longlonglongmask, maxint, is_valid_int, is_emulated_long)
-from rpython.rlib.objectmodel import Symbolic
+    base_int, intmask, is_emulated_long, is_valid_int, longlonglongmask,
+    longlongmask, maxint, normalizedinttype, r_int, r_longfloat, r_longlong,
+    r_longlonglong, r_singlefloat, r_uint, r_ulonglong)
+from rpython.rtyper.extregistry import ExtRegistryEntry
+from rpython.tool import leakfinder
 from rpython.tool.identity_dict import identity_dict
-from rpython.tool import leakfinder
-from rpython.annotator.bookkeeper import analyzer_for, immutablevalue
-from rpython.rtyper.extregistry import ExtRegistryEntry
 
 class State(object):
     pass
@@ -313,14 +314,12 @@
         except KeyError:
             return ContainerType.__getattr__(self, name)
 
-
     def _nofield(self, name):
         raise AttributeError('struct %s has no field %r' % (self._name,
                                                              name))
 
     def _names_without_voids(self):
-        names_without_voids = [name for name in self._names if 
self._flds[name] is not Void]
-        return names_without_voids
+        return [name for name in self._names if self._flds[name] is not Void]
 
     def _str_fields_without_voids(self):
         return ', '.join(['%s: %s' % (name, self._flds[name])
@@ -576,8 +575,10 @@
     _gckind = 'raw'
 
     def __init__(self, tag, hints={}):
-        """ if hints['render_structure'] is set, the type is internal and not 
considered
-            to come from somewhere else (it should be rendered as a structure) 
"""
+        """If hints['render_structure'] is set, the type is internal and
+        not considered to come from somewhere else (it should be
+        rendered as a structure)
+        """
         self.tag = tag
         self.__name__ = tag
         self.hints = frozendict(hints)
@@ -675,7 +676,8 @@
 
 _numbertypes = {int: Number("Signed", int, intmask)}
 _numbertypes[r_int] = _numbertypes[int]
-_numbertypes[r_longlonglong] = Number("SignedLongLongLong", r_longlonglong, 
longlonglongmask)
+_numbertypes[r_longlonglong] = Number("SignedLongLongLong", r_longlonglong,
+                                      longlonglongmask)
 if r_longlong is not r_int:
     _numbertypes[r_longlong] = Number("SignedLongLong", r_longlong,
                                       longlongmask)
@@ -702,8 +704,8 @@
 UnsignedLongLong = build_number("UnsignedLongLong", r_ulonglong)
 
 Float       = Primitive("Float",       0.0)                  # C type 'double'
-SingleFloat = Primitive("SingleFloat", r_singlefloat(0.0))   # C type 'float'
-LongFloat   = Primitive("LongFloat",   r_longfloat(0.0))     # C type 'long 
double'
+SingleFloat = Primitive("SingleFloat", r_singlefloat(0.0))   # 'float'
+LongFloat   = Primitive("LongFloat",   r_longfloat(0.0))     # 'long double'
 r_singlefloat._TYPE = SingleFloat
 
 Char     = Primitive("Char", '\x00')
@@ -876,9 +878,11 @@
 
 @analyzer_for(cast_primitive)
 def ann_cast_primitive(T, s_v):
-    from rpython.rtyper.llannotation import annotation_to_lltype, 
ll_to_annotation
+    from rpython.rtyper.llannotation import (
+        annotation_to_lltype, ll_to_annotation)
     assert T.is_constant()
-    return ll_to_annotation(cast_primitive(T.const, 
annotation_to_lltype(s_v)._defl()))
+    return ll_to_annotation(cast_primitive(T.const,
+                                           annotation_to_lltype(s_v)._defl()))
 
 
 def _cast_whatever(TGT, value):
@@ -905,7 +909,8 @@
     elif TGT == llmemory.Address and isinstance(ORIG, Ptr):
         return llmemory.cast_ptr_to_adr(value)
     elif TGT == Signed and isinstance(ORIG, Ptr) and ORIG.TO._gckind == 'raw':
-        return llmemory.cast_adr_to_int(llmemory.cast_ptr_to_adr(value), 
'symbolic')
+        return llmemory.cast_adr_to_int(llmemory.cast_ptr_to_adr(value),
+                                        'symbolic')
     raise TypeError("don't know how to cast from %r to %r" % (ORIG, TGT))
 
 
@@ -1176,8 +1181,8 @@
         except DelayedPointer:
             return True    # assume it's not a delayed null
 
-    # _setobj, _getobj and _obj0 are really _internal_ implementations details 
of _ptr,
-    # use _obj if necessary instead !
+    # _setobj, _getobj and _obj0 are really _internal_ implementations
+    # details of _ptr, use _obj if necessary instead !
     def _setobj(self, pointing_to, solid=False):
         if pointing_to is None:
             obj0 = None
@@ -1244,12 +1249,12 @@
                 if T1 == T2:
                     setattr(self._obj, field_name, val)
                 else:
-                    raise TypeError("%r instance field %r:\n"
-                                    "expects %r\n"
-                                    "    got %r" % (self._T, field_name, T1, 
T2))
+                    raise TypeError(
+                        "%r instance field %r:\nexpects %r\n    got %r" %
+                        (self._T, field_name, T1, T2))
                 return
-        raise AttributeError("%r instance has no field %r" % (self._T,
-                                                              field_name))
+        raise AttributeError("%r instance has no field %r" %
+                             (self._T, field_name))
 
     def __getitem__(self, i): # ! can only return basic or ptr !
         if isinstance(self._T, (Array, FixedSizeArray)):
@@ -1266,7 +1271,8 @@
         if isinstance(self._T, (Array, FixedSizeArray)):
             T1 = self._T.OF
             if isinstance(T1, ContainerType):
-                raise TypeError("cannot directly assign to container array 
items")
+                raise TypeError("cannot directly assign to container array "
+                                "items")
             T2 = typeOf(val)
             if T2 != T1:
                 from rpython.rtyper.lltypesystem import rffi
@@ -1316,7 +1322,8 @@
         from rpython.rtyper.lltypesystem import rffi
         if isinstance(self._T, FuncType):
             if len(args) != len(self._T.ARGS):
-                raise TypeError("calling %r with wrong argument number: %r" % 
(self._T, args))
+                raise TypeError("calling %r with wrong argument number: %r" %
+                                (self._T, args))
             for i, a, ARG in zip(range(len(self._T.ARGS)), args, self._T.ARGS):
                 if typeOf(a) != ARG:
                     # ARG could be Void
@@ -1415,11 +1422,13 @@
                 raise RuntimeError("widening to trash: %r" % self)
             PARENTTYPE = struc._parent_type
             if getattr(parent, PARENTTYPE._names[0]) != struc:
-                raise InvalidCast(CURTYPE, PTRTYPE) # xxx different exception 
perhaps?
+                 # xxx different exception perhaps?
+                raise InvalidCast(CURTYPE, PTRTYPE)
             struc = parent
             u -= 1
         if PARENTTYPE != PTRTYPE.TO:
-            raise RuntimeError("widening %r inside %r instead of %r" % 
(CURTYPE, PARENTTYPE, PTRTYPE.TO))
+            raise RuntimeError("widening %r inside %r instead of %r" %
+                               (CURTYPE, PARENTTYPE, PTRTYPE.TO))
         return _ptr(PTRTYPE, struc, solid=self._solid)
 
     def _cast_to_int(self, check=True):
@@ -1430,7 +1439,9 @@
             return obj     # special case for cast_int_to_ptr() results
         obj = normalizeptr(self, check)._getobj(check)
         if isinstance(obj, int):
-            return obj     # special case for cast_int_to_ptr() results put 
into opaques
+            # special case for cast_int_to_ptr() results put into
+            # opaques
+            return obj
         if getattr(obj, '_read_directly_intval', False):
             return obj.intval   # special case for _llgcopaque
         result = intmask(obj._getid())
@@ -1468,7 +1479,8 @@
         """XXX A nice docstring here"""
         T = typeOf(val)
         if isinstance(T, ContainerType):
-            if self._T._gckind == 'gc' and T._gckind == 'raw' and not 
isinstance(T, OpaqueType):
+            if (self._T._gckind == 'gc' and T._gckind == 'raw' and
+                not isinstance(T, OpaqueType)):
                 val = _interior_ptr(T, self._obj, [offset])
             else:
                 val = _ptr(Ptr(T), val, solid=self._solid)
@@ -1531,12 +1543,14 @@
             setattr(example, s_attr.const, v_lltype._defl())
 
     def call(self, args):
-        from rpython.rtyper.llannotation import annotation_to_lltype, 
ll_to_annotation
+        from rpython.rtyper.llannotation import (
+            annotation_to_lltype, ll_to_annotation)
         args_s, kwds_s = args.unpack()
         if kwds_s:
             raise Exception("keyword arguments to call to a low-level fn ptr")
         info = 'argument to ll function pointer call'
-        llargs = [annotation_to_lltype(s_arg, info)._defl() for s_arg in 
args_s]
+        llargs = [annotation_to_lltype(s_arg, info)._defl()
+                  for s_arg in args_s]
         v = self.ll_ptrtype._example()(*llargs)
         return ll_to_annotation(v)
 
@@ -1593,7 +1607,6 @@
         return val
 
 
-
 assert not '__dict__' in dir(_interior_ptr)
 
 class _container(object):
@@ -1721,11 +1734,13 @@
 
     __slots__ = ('_hash_cache_', '_compilation_info')
 
-    def __new__(self, TYPE, n=None, initialization=None, parent=None, 
parentindex=None):
+    def __new__(self, TYPE, n=None, initialization=None, parent=None,
+                parentindex=None):
         my_variety = _struct_variety(TYPE._names)
         return object.__new__(my_variety)
 
-    def __init__(self, TYPE, n=None, initialization=None, parent=None, 
parentindex=None):
+    def __init__(self, TYPE, n=None, initialization=None, parent=None,
+                 parentindex=None):
         _parentable.__init__(self, TYPE)
         if n is not None and TYPE._arrayfld is None:
             raise TypeError("%r is not variable-sized" % (TYPE,))
@@ -1734,9 +1749,11 @@
         first, FIRSTTYPE = TYPE._first_struct()
         for fld, typ in TYPE._flds.items():
             if fld == TYPE._arrayfld:
-                value = _array(typ, n, initialization=initialization, 
parent=self, parentindex=fld)
+                value = _array(typ, n, initialization=initialization,
+                               parent=self, parentindex=fld)
             else:
-                value = typ._allocate(initialization=initialization, 
parent=self, parentindex=fld)
+                value = typ._allocate(initialization=initialization,
+                                      parent=self, parentindex=fld)
             setattr(self, fld, value)
         if parent is not None:
             self._setparentstructure(parent, parentindex)
@@ -1795,7 +1812,8 @@
 
     __slots__ = ('items',)
 
-    def __init__(self, TYPE, n, initialization=None, parent=None, 
parentindex=None):
+    def __init__(self, TYPE, n, initialization=None, parent=None,
+                 parentindex=None):
         if not is_valid_int(n):
             raise TypeError("array length must be an int")
         if n < 0:
@@ -1964,7 +1982,8 @@
                     if not key._was_freed():
                         newcache[key] = value
                 except RuntimeError:
-                    pass    # ignore "accessing subxxx, but already gc-ed 
parent"
+                    # ignore "accessing subxxx, but already gc-ed parent"
+                    pass
             if newcache:
                 _subarray._cache[T] = newcache
             else:
@@ -2020,8 +2039,10 @@
         attrs.setdefault('_name', '?')
         attrs.setdefault('_callable', None)
         self.__dict__.update(attrs)
-        if '_callable' in attrs and hasattr(attrs['_callable'], 
'_compilation_info'):
-            self.__dict__['compilation_info'] = 
attrs['_callable']._compilation_info
+        if '_callable' in attrs and hasattr(attrs['_callable'],
+                                            '_compilation_info'):
+            self.__dict__['compilation_info'] = \
+                attrs['_callable']._compilation_info
 
     def __repr__(self):
         return '<%s>' % (self,)
@@ -2126,8 +2147,8 @@
     return _ptr(Ptr(T), o, solid)
 
 @analyzer_for(malloc)
-def ann_malloc(s_T, s_n=None, s_flavor=None, s_zero=None, 
s_track_allocation=None,
-           s_add_memory_pressure=None):
+def ann_malloc(s_T, s_n=None, s_flavor=None, s_zero=None,
+               s_track_allocation=None, s_add_memory_pressure=None):
     assert (s_n is None or s_n.knowntype == int
             or issubclass(s_n.knowntype, base_int))
     assert s_T.is_constant()
@@ -2303,7 +2324,8 @@
 
 @analyzer_for(runtime_type_info)
 def ann_runtime_type_info(s_p):
-    assert isinstance(s_p, SomePtr), "runtime_type_info of non-pointer: %r" % 
s_p
+    assert isinstance(s_p, SomePtr), \
+        "runtime_type_info of non-pointer: %r" % s_p
     return SomePtr(typeOf(runtime_type_info(s_p.ll_ptrtype._example())))
 
 
diff --git a/rpython/rtyper/module/ll_os.py b/rpython/rtyper/module/ll_os.py
--- a/rpython/rtyper/module/ll_os.py
+++ b/rpython/rtyper/module/ll_os.py
@@ -105,6 +105,12 @@
 
 _CYGWIN = sys.platform == 'cygwin'
 
+# plain NotImplementedError is invalid RPython
+class LLNotImplemented(NotImplementedError):
+
+    def __init__(self, msg):
+        self.msg = msg
+
 class CConfig:
     """
     Definitions for platform integration.
@@ -1179,7 +1185,7 @@
                              condition=sys.platform=='win32')
     def register_posix__getfullpathname(self, traits):
         # this nt function is not exposed via os, but needed
-        # to get a correct implementation of os.abspath
+        # to get a correct implementation of os.path.abspath
         from rpython.rtyper.module.ll_win32file import 
make_getfullpathname_impl
         getfullpathname_llimpl = make_getfullpathname_impl(traits)
 
@@ -1963,10 +1969,12 @@
         return OsEnvironController()
 
 # ____________________________________________________________
-# Support for the WindowsError exception
+# Support for the WindowsError exception and misc functions
 
 if sys.platform == 'win32':
     from rpython.rlib import rwin32
+    from rpython.rtyper.module.ll_win32file import (
+        make__getfileinformation_impl, make__getfinalpathname_impl)
 
     class RegisterFormatError(BaseLazyRegistering):
         def __init__(self):
@@ -1977,3 +1985,6 @@
             return extdef([lltype.Signed], str,
                           "rwin32_FormatError",
                           llimpl=rwin32.llimpl_FormatError)
+
+    _getfileinformation = make__getfileinformation_impl(UnicodeTraits())
+    _getfinalpathname = make__getfinalpathname_impl(UnicodeTraits())
diff --git a/rpython/rtyper/module/ll_os_stat.py 
b/rpython/rtyper/module/ll_os_stat.py
--- a/rpython/rtyper/module/ll_os_stat.py
+++ b/rpython/rtyper/module/ll_os_stat.py
@@ -186,7 +186,10 @@
     _name_struct_stat = '_stati64'
     INCLUDES = ['sys/types.h', 'sys/stat.h', 'sys/statvfs.h']
 else:
-    _name_struct_stat = 'stat'
+    if sys.platform.startswith('linux'):
+        _name_struct_stat = 'stat64'
+    else:
+        _name_struct_stat = 'stat'
     INCLUDES = ['sys/types.h', 'sys/stat.h', 'sys/statvfs.h', 'unistd.h']
 
 compilation_info = ExternalCompilationInfo(
diff --git a/rpython/rtyper/module/ll_win32file.py 
b/rpython/rtyper/module/ll_win32file.py
--- a/rpython/rtyper/module/ll_win32file.py
+++ b/rpython/rtyper/module/ll_win32file.py
@@ -55,6 +55,15 @@
         FILE_TYPE_CHAR = platform.ConstantInteger('FILE_TYPE_CHAR')
         FILE_TYPE_PIPE = platform.ConstantInteger('FILE_TYPE_PIPE')
 
+        FILE_WRITE_ATTRIBUTES = platform.ConstantInteger(
+            'FILE_WRITE_ATTRIBUTES')
+        OPEN_EXISTING = platform.ConstantInteger(
+            'OPEN_EXISTING')
+        FILE_FLAG_BACKUP_SEMANTICS = platform.ConstantInteger(
+            'FILE_FLAG_BACKUP_SEMANTICS')
+        VOLUME_NAME_DOS = platform.ConstantInteger('VOLUME_NAME_DOS')
+        VOLUME_NAME_NT = platform.ConstantInteger('VOLUME_NAME_NT')
+
         WIN32_FILE_ATTRIBUTE_DATA = platform.Struct(
             'WIN32_FILE_ATTRIBUTE_DATA',
             [('dwFileAttributes', rwin32.DWORD),
@@ -67,14 +76,15 @@
         BY_HANDLE_FILE_INFORMATION = platform.Struct(
             'BY_HANDLE_FILE_INFORMATION',
             [('dwFileAttributes', rwin32.DWORD),
+             ('ftCreationTime', rwin32.FILETIME),
+             ('ftLastAccessTime', rwin32.FILETIME),
+             ('ftLastWriteTime', rwin32.FILETIME),
+             ('dwVolumeSerialNumber', rwin32.DWORD),
              ('nFileSizeHigh', rwin32.DWORD),
              ('nFileSizeLow', rwin32.DWORD),
              ('nNumberOfLinks', rwin32.DWORD),
              ('nFileIndexHigh', rwin32.DWORD),
-             ('nFileIndexLow', rwin32.DWORD),
-             ('ftCreationTime', rwin32.FILETIME),
-             ('ftLastAccessTime', rwin32.FILETIME),
-             ('ftLastWriteTime', rwin32.FILETIME)])
+             ('nFileIndexLow', rwin32.DWORD)])
 
     config = platform.configure(CConfig)
 
@@ -92,6 +102,8 @@
                        INVALID_FILE_ATTRIBUTES
                        _S_IFDIR _S_IFREG _S_IFCHR _S_IFIFO
                        FILE_TYPE_UNKNOWN FILE_TYPE_CHAR FILE_TYPE_PIPE
+                       FILE_WRITE_ATTRIBUTES OPEN_EXISTING 
FILE_FLAG_BACKUP_SEMANTICS
+                       VOLUME_NAME_DOS VOLUME_NAME_NT
                        ERROR_FILE_NOT_FOUND ERROR_NO_MORE_FILES
                        ERROR_SHARING_VIOLATION
                     '''.split():
@@ -163,6 +175,13 @@
             [traits.CCHARP, traits.CCHARP],
             rwin32.BOOL)
 
+        CreateFile = external(
+            'CreateFile' + apisuffix,
+            [traits.CCHARP, rwin32.DWORD, rwin32.DWORD,
+             rwin32.LPSECURITY_ATTRIBUTES, rwin32.DWORD, rwin32.DWORD,
+             rwin32.HANDLE],
+            rwin32.HANDLE)
+
         DeleteFile = external(
             'DeleteFile' + suffix,
             [traits.CCHARP],
@@ -173,7 +192,29 @@
             [traits.CCHARP, traits.CCHARP],
             rwin32.BOOL)
 
-    return Win32Traits
+        GETFINALPATHNAMEBYHANDLE_TP = lltype.Ptr(lltype.FuncType(
+                [rwin32.HANDLE, traits.CCHARP, rwin32.DWORD, rwin32.DWORD],
+                rwin32.DWORD, abi='FFI_STDCALL'))
+        # dynamically loaded
+        GetFinalPathNameByHandle = lltype.nullptr(
+            GETFINALPATHNAMEBYHANDLE_TP.TO)
+
+        def check_GetFinalPathNameByHandle(self):
+            if self.GetFinalPathNameByHandle:
+                return True
+
+            from rpython.rlib.rdynload import GetModuleHandle, dlsym
+            hKernel32 = GetModuleHandle("KERNEL32")
+            try:
+                func = dlsym(hKernel32, 'GetFinalPathNameByHandle' + suffix)
+            except KeyError:
+                return False
+
+            self.GetFinalPathNameByHandle = rffi.cast(
+                Win32Traits.GETFINALPATHNAMEBYHANDLE_TP, func)
+            return True
+
+    return Win32Traits()
 
 #_______________________________________________________________
 # listdir
@@ -336,27 +377,6 @@
     win32traits = make_win32_traits(traits)
     from rpython.rtyper.module.ll_os_stat import time_t_to_FILE_TIME
 
-    class CConfig:
-        _compilation_info_ = ExternalCompilationInfo(
-            includes = ['windows.h'],
-            )
-
-        FILE_WRITE_ATTRIBUTES = platform.ConstantInteger(
-            'FILE_WRITE_ATTRIBUTES')
-        OPEN_EXISTING = platform.ConstantInteger(
-            'OPEN_EXISTING')
-        FILE_FLAG_BACKUP_SEMANTICS = platform.ConstantInteger(
-            'FILE_FLAG_BACKUP_SEMANTICS')
-    globals().update(platform.configure(CConfig))
-
-    CreateFile = rffi.llexternal(
-        'CreateFile' + win32traits.apisuffix,
-        [traits.CCHARP, rwin32.DWORD, rwin32.DWORD,
-         rwin32.LPSECURITY_ATTRIBUTES, rwin32.DWORD, rwin32.DWORD,
-         rwin32.HANDLE],
-        rwin32.HANDLE,
-        calling_conv='win')
-
     GetSystemTime = rffi.llexternal(
         'GetSystemTime',
         [lltype.Ptr(rwin32.SYSTEMTIME)],
@@ -381,10 +401,10 @@
 
     @specialize.argtype(1)
     def os_utime_llimpl(path, tp):
-        hFile = CreateFile(path,
-                           FILE_WRITE_ATTRIBUTES, 0,
-                           None, OPEN_EXISTING,
-                           FILE_FLAG_BACKUP_SEMANTICS,
+        hFile = win32traits.CreateFile(path,
+                           win32traits.FILE_WRITE_ATTRIBUTES, 0,
+                           None, win32traits.OPEN_EXISTING,
+                           win32traits.FILE_FLAG_BACKUP_SEMANTICS,
                            rwin32.NULL_HANDLE)
         if hFile == rwin32.INVALID_HANDLE_VALUE:
             raise rwin32.lastWindowsError()
@@ -413,3 +433,68 @@
             lltype.free(mtime, flavor='raw')
 
     return os_utime_llimpl
+
+#_______________________________________________________________
+# _getfileinformation (py3)
+
+def make__getfileinformation_impl(traits):
+    from rpython.rlib import rwin32
+    win32traits = make_win32_traits(traits)
+
+    def _getfileinformation_llimpl(fd):
+        hFile = rwin32.get_osfhandle(fd)
+        with lltype.scoped_alloc(
+            win32traits.BY_HANDLE_FILE_INFORMATION) as info:
+            if win32traits.GetFileInformationByHandle(hFile, info) == 0:
+                raise rwin32.lastWindowsError("_getfileinformation")
+            return (rffi.cast(lltype.Signed, info.c_dwVolumeSerialNumber),
+                    rffi.cast(lltype.Signed, info.c_nFileIndexHigh),
+                    rffi.cast(lltype.Signed, info.c_nFileIndexLow))
+
+    return _getfileinformation_llimpl
+
+#_______________________________________________________________
+# _getfinalpathname (py3)
+
+def make__getfinalpathname_impl(traits):
+    from rpython.rlib import rwin32
+    from rpython.rtyper.module.ll_os import LLNotImplemented
+    assert traits.str is unicode, 'Currently only handles unicode paths'
+    win32traits = make_win32_traits(traits)
+
+    def _getfinalpathname_llimpl(path):
+        if not win32traits.check_GetFinalPathNameByHandle():
+            raise LLNotImplemented("GetFinalPathNameByHandle not available on "
+                                   "this platform")
+
+        hFile = win32traits.CreateFile(path, 0, 0, None,
+                                       win32traits.OPEN_EXISTING,
+                                       win32traits.FILE_FLAG_BACKUP_SEMANTICS,
+                                       rwin32.NULL_HANDLE)
+        if hFile == rwin32.INVALID_HANDLE_VALUE:
+            raise rwin32.lastWindowsError("CreateFile")
+
+        VOLUME_NAME_DOS = rffi.cast(rwin32.DWORD, win32traits.VOLUME_NAME_DOS)
+        try:
+            size = win32traits.GetFinalPathNameByHandle(
+                hFile,
+                lltype.nullptr(traits.CCHARP.TO),
+                rffi.cast(rwin32.DWORD, 0),
+                VOLUME_NAME_DOS)
+            if size == 0:
+                raise rwin32.lastWindowsError("GetFinalPathNameByHandle")
+
+            with lltype.scoped_alloc(traits.CCHARP.TO, size + 1) as 
target_path:
+                result = win32traits.GetFinalPathNameByHandle(
+                    hFile,
+                    target_path,
+                    size,
+                    VOLUME_NAME_DOS)
+                if result == 0:
+                    raise rwin32.lastWindowsError("GetFinalPathNameByHandle")
+                return traits.charpsize2str(target_path,
+                                            rffi.cast(lltype.Signed, result))
+        finally:
+            rwin32.CloseHandle(hFile)
+
+    return _getfinalpathname_llimpl
diff --git a/rpython/rtyper/module/support.py b/rpython/rtyper/module/support.py
--- a/rpython/rtyper/module/support.py
+++ b/rpython/rtyper/module/support.py
@@ -49,6 +49,7 @@
     CHAR = rffi.CHAR
     CCHARP = rffi.CCHARP
     charp2str = staticmethod(rffi.charp2str)
+    charpsize2str = staticmethod(rffi.charpsize2str)
     scoped_str2charp = staticmethod(rffi.scoped_str2charp)
     str2charp = staticmethod(rffi.str2charp)
     free_charp = staticmethod(rffi.free_charp)
@@ -68,6 +69,7 @@
     CHAR = rffi.WCHAR_T
     CCHARP = rffi.CWCHARP
     charp2str = staticmethod(rffi.wcharp2unicode)
+    charpsize2str = staticmethod(rffi.wcharpsize2unicode)
     str2charp = staticmethod(rffi.unicode2wcharp)
     scoped_str2charp = staticmethod(rffi.scoped_unicode2wcharp)
     free_charp = staticmethod(rffi.free_wcharp)
diff --git a/rpython/rtyper/module/test/test_ll_win32file.py 
b/rpython/rtyper/module/test/test_ll_win32file.py
new file mode 100644
--- /dev/null
+++ b/rpython/rtyper/module/test/test_ll_win32file.py
@@ -0,0 +1,26 @@
+import os
+
+import py
+
+from rpython.rtyper.module import ll_os
+
+if not ll_os._WIN32:
+    py.test.skip("requires Windows")
+
+
+def test__getfileinformation():
+    with open(__file__) as fp:
+        stat = os.fstat(fp.fileno())
+        info = ll_os._getfileinformation(fp.fileno())
+    serial, high, low = info
+    assert type(serial) in (int, long)
+    assert (high << 32) + low == stat.st_ino
+
+
+def test__getfinalpathname():
+    path = __file__.decode('mbcs')
+    try:
+        result = ll_os._getfinalpathname(path)
+    except ll_os.LLNotImplemented:
+        py.test.skip("_getfinalpathname not supported on this platform")
+    assert os.path.exists(result)
diff --git a/rpython/translator/platform/test/test_makefile.py 
b/rpython/translator/platform/test/test_makefile.py
--- a/rpython/translator/platform/test/test_makefile.py
+++ b/rpython/translator/platform/test/test_makefile.py
@@ -44,6 +44,7 @@
         assert res.returncode == 0        
     
     def test_900_files(self):
+        tmpdir = udir.join('test_900_files').ensure(dir=1)
         txt = '#include <stdio.h>\n'
         for i in range(900):
             txt += 'int func%03d();\n' % i
@@ -52,11 +53,11 @@
             txt += '    j += func%03d();\n' % i
         txt += '    printf("%d\\n", j);\n'
         txt += '    return 0;};\n'
-        cfile = udir.join('test_900_files.c')
+        cfile = tmpdir.join('test_900_files.c')
         cfile.write(txt)
         cfiles = [cfile]
         for i in range(900):
-            cfile2 = udir.join('implement%03d.c' %i)
+            cfile2 = tmpdir.join('implement%03d.c' %i)
             cfile2.write('''
                 int func%03d()
             {
@@ -64,10 +65,10 @@
             }
             ''' % (i, i))
             cfiles.append(cfile2)
-        mk = self.platform.gen_makefile(cfiles, ExternalCompilationInfo(), 
path=udir)
+        mk = self.platform.gen_makefile(cfiles, ExternalCompilationInfo(), 
path=tmpdir)
         mk.write()
         self.platform.execute_makefile(mk)
-        res = self.platform.execute(udir.join('test_900_files'))
+        res = self.platform.execute(tmpdir.join('test_900_files'))
         self.check_res(res, '%d\n' %sum(range(900)))
 
     def test_precompiled_headers(self):
diff --git a/rpython/translator/platform/windows.py 
b/rpython/translator/platform/windows.py
--- a/rpython/translator/platform/windows.py
+++ b/rpython/translator/platform/windows.py
@@ -203,6 +203,9 @@
         # the assembler still has the old behavior that all options
         # must come first, and after the file name all options are ignored.
         # So please be careful with the order of parameters! ;-)
+        pdb_dir = oname.dirname
+        if pdb_dir:
+                compile_args += ['/Fd%s\\' % (pdb_dir,)]
         args = ['/nologo', '/c'] + compile_args + ['/Fo%s' % (oname,), 
str(cfile)]
         self._execute_c_compiler(cc, args, oname)
         return oname
diff --git a/rpython/translator/sandbox/rsandbox.py 
b/rpython/translator/sandbox/rsandbox.py
--- a/rpython/translator/sandbox/rsandbox.py
+++ b/rpython/translator/sandbox/rsandbox.py
@@ -60,8 +60,7 @@
 
     def need_more_data(self):
         buflen = self.buflen
-        buf = lltype.malloc(rffi.CCHARP.TO, buflen, flavor='raw')
-        try:
+        with lltype.scoped_alloc(rffi.CCHARP.TO, buflen) as buf:
             buflen = rffi.cast(rffi.SIZE_T, buflen)
             count = ll_read_not_sandboxed(self.fd, buf, buflen)
             count = rffi.cast(lltype.Signed, count)
@@ -69,20 +68,15 @@
                 raise IOError
             self.buf += ''.join([buf[i] for i in range(count)])
             self.buflen *= 2
-        finally:
-            lltype.free(buf, flavor='raw')
 
 def sandboxed_io(buf):
     STDIN = 0
     STDOUT = 1
     # send the buffer with the marshalled fnname and input arguments to STDOUT
-    p = lltype.malloc(rffi.CCHARP.TO, len(buf), flavor='raw')
-    try:
+    with lltype.scoped_alloc(rffi.CCHARP.TO, len(buf)) as p:
         for i in range(len(buf)):
             p[i] = buf[i]
         writeall_not_sandboxed(STDOUT, p, len(buf))
-    finally:
-        lltype.free(p, flavor='raw')
     # build a Loader that will get the answer from STDIN
     loader = FdLoader(STDIN)
     # check for errors
@@ -108,9 +102,8 @@
 @signature(types.str(), returns=types.impossible())
 def not_implemented_stub(msg):
     STDERR = 2
-    buf = rffi.str2charp(msg + '\n')
-    writeall_not_sandboxed(STDERR, buf, len(msg) + 1)
-    rffi.free_charp(buf)
+    with rffi.scoped_str2charp(msg + '\n') as buf:
+        writeall_not_sandboxed(STDERR, buf, len(msg) + 1)
     raise RuntimeError(msg)  # XXX in RPython, the msg is ignored at the moment
 
 dump_string = rmarshal.get_marshaller(str)
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to