David Schneider avatar David Schneider committed 6885a43 Merge

merge heads

Comments (0)

Files changed (14)

rpython/annotator/model.py

 s_Int = SomeInteger()
 s_ImpossibleValue = SomeImpossibleValue()
 s_Str0 = SomeString(no_nul=True)
+s_Unicode0 = SomeUnicodeString(no_nul=True)
 
 
 # ____________________________________________________________

rpython/jit/backend/arm/assembler.py

         if we_are_translated():
             self.debug = False
         self.current_clt = looptoken.compiled_loop_token
-        self.mc = InstrBuilder(self.cpu.arch_version)
+        self.mc = InstrBuilder(self.cpu.cpuinfo.arch_version)
         self.pending_guards = []
         assert self.datablockwrapper is None
         allblocks = self.get_asmmemmgr_blocks(looptoken)
         if not self.cpu.propagate_exception_descr:
             return      # not supported (for tests, or non-translated)
         #
-        mc = InstrBuilder(self.cpu.arch_version)
+        mc = InstrBuilder(self.cpu.cpuinfo.arch_version)
         self._store_and_reset_exception(mc, r.r0)
         ofs = self.cpu.get_ofs_of_frame_field('jf_guard_exc')
         # make sure ofs fits into a register
         #    |  my own retaddr       |    <-- sp
         #    +-----------------------+
         #
-        mc = InstrBuilder(self.cpu.arch_version)
+        mc = InstrBuilder(self.cpu.cpuinfo.arch_version)
         # save argument registers and return address
         mc.PUSH([reg.value for reg in r.argument_regs] + [r.ip.value, r.lr.value])
         # stack is aligned here
         # write barriers.  It must save all registers, and optionally
         # all vfp registers.  It takes a single argument which is in r0.
         # It must keep stack alignment accordingly.
-        mc = InstrBuilder(self.cpu.arch_version)
+        mc = InstrBuilder(self.cpu.cpuinfo.arch_version)
         #
         exc0 = exc1 = None
         mc.PUSH([r.ip.value, r.lr.value]) # push two words to keep alignment
         This function must preserve all registers apart from r0 and r1.
         """
         assert kind in ['fixed', 'str', 'unicode', 'var']
-        mc = InstrBuilder(self.cpu.arch_version)
+        mc = InstrBuilder(self.cpu.cpuinfo.arch_version)
         #
         self._push_all_regs_to_jitframe(mc, [r.r0, r.r1], self.cpu.supports_floats)
         #
                 self.load_reg(mc, vfpr, r.fp, ofs)
 
     def _build_failure_recovery(self, exc, withfloats=False):
-        mc = InstrBuilder(self.cpu.arch_version)
+        mc = InstrBuilder(self.cpu.cpuinfo.arch_version)
         self._push_all_regs_to_jitframe(mc, [], withfloats)
 
         if exc:
                                 expected_size=expected_size)
 
     def _patch_frame_depth(self, adr, allocated_depth):
-        mc = InstrBuilder(self.cpu.arch_version)
+        mc = InstrBuilder(self.cpu.cpuinfo.arch_version)
         mc.gen_load_int(r.lr.value, allocated_depth)
         mc.copy_to_raw_memory(adr)
 
         # f) store the address of the new jitframe in the shadowstack
         # c) set the gcmap field to 0 in the new jitframe
         # g) restore registers and return
-        mc = InstrBuilder(self.cpu.arch_version)
+        mc = InstrBuilder(self.cpu.cpuinfo.arch_version)
         self._push_all_regs_to_jitframe(mc, [], self.cpu.supports_floats)
         # this is the gcmap stored by push_gcmap(mov=True) in _check_stack_frame
         # and the expected_size pushed in _check_stack_frame
         self.target_tokens_currently_compiling = None
 
     def _patch_stackadjust(self, adr, allocated_depth):
-        mc = InstrBuilder(self.cpu.arch_version)
+        mc = InstrBuilder(self.cpu.cpuinfo.arch_version)
         mc.gen_load_int(r.lr.value, allocated_depth)
         mc.copy_to_raw_memory(adr)
 
                 # patch the guard jumpt to the stub
                 # overwrite the generate NOP with a B_offs to the pos of the
                 # stub
-                mc = InstrBuilder(self.cpu.arch_version)
+                mc = InstrBuilder(self.cpu.cpuinfo.arch_version)
                 mc.B_offs(relative_offset, c.get_opposite_of(tok.fcond))
                 mc.copy_to_raw_memory(guard_pos)
             else:
                 self.mc.ASR_ri(resloc.value, resloc.value, 16)
 
     def patch_trace(self, faildescr, looptoken, bridge_addr, regalloc):
-        b = InstrBuilder(self.cpu.arch_version)
+        b = InstrBuilder(self.cpu.cpuinfo.arch_version)
         patch_addr = faildescr._arm_failure_recovery_block
         assert patch_addr != 0
         b.B(bridge_addr)
             self.mc.LSL_ri(targetreg.value, sourcereg.value,
                     get_scale(itemsize))
         else:
-            mc.gen_load_int(targetreg.value, itemsize.value)
+            mc.gen_load_int(targetreg.value, itemsize)
             mc.MUL(targetreg.value, sourcereg.value, targetreg.value)
         #
         return shiftsize

rpython/jit/backend/arm/detect.py

 import os
 
 from rpython.translator.tool.cbuild import ExternalCompilationInfo
+from rpython.rtyper.tool import rffi_platform
 from rpython.rlib.clibffi import FFI_DEFAULT_ABI, FFI_SYSV, FFI_VFP
-from rpython.rtyper.tool import rffi_platform
 from rpython.translator.platform import CompilationError
 from rpython.rlib.debug import debug_print, debug_start, debug_stop
 
     # "Processor       : ARMv%d-compatible processor rev 7 (v6l)"
     i = buf.find('ARMv')
     if i == -1:
-        raise ValueError("Unknown Processor entry")
-
-    n = int(buf[i + 4])
+        n = 6
+        debug_print("Could not detect architecture version, "
+                    "falling back to", "ARMv%d" % n)
+    else:
+        n = int(buf[i + 4])
 
     if n < 6:
         raise ValueError("Unsupported ARM architecture version")

rpython/jit/backend/arm/opassembler.py

                     # whether to worry about a CALL that can collect; this
                     # is always true except in call_release_gil
                     can_collect=True):
-        if self.cpu.hf_abi:
+        if self.cpu.cpuinfo.hf_abi:
             stack_args, adr = self._setup_call_hf(adr, arglocs, fcond,
                                             resloc, result_info)
         else:
 
         # ensure the result is wellformed and stored in the correct location
         if resloc is not None:
-            if resloc.is_vfp_reg() and not self.cpu.hf_abi:
+            if resloc.is_vfp_reg() and not self.cpu.cpuinfo.hf_abi:
                 # move result to the allocated register
                 self.mov_to_vfp_loc(r.r0, r.r1, resloc)
             elif resloc.is_reg() and result_info != (-1, -1):
         baseofs = self.cpu.get_baseofs_of_frame_field()
         newlooptoken.compiled_loop_token.update_frame_info(
             oldlooptoken.compiled_loop_token, baseofs)
-        mc = InstrBuilder(self.cpu.arch_version)
+        mc = InstrBuilder(self.cpu.cpuinfo.arch_version)
         mc.B(target)
         mc.copy_to_raw_memory(oldadr)
 

rpython/jit/backend/arm/runner.py

 
 jitframe.STATICSIZE = JITFRAME_FIXED_SIZE
 
+class CPUInfo(object):
+    hf_abi = False
+    arch_version = 6
+
 class AbstractARMCPU(AbstractLLCPU):
 
     IS_64_BIT = False
     float_regs = VFPRegisterManager.all_regs
     frame_reg = fp
 
-    hf_abi = False        # use hard float abi flag
-    arch_version = 6      # assume ARMv6 as base case
-
     def __init__(self, rtyper, stats, opts=None, translate_support_code=False,
                  gcdescr=None):
         AbstractLLCPU.__init__(self, rtyper, stats, opts,
                                translate_support_code, gcdescr)
+        self.cpuinfo = CPUInfo()
 
     def set_debug(self, flag):
         return self.assembler.set_debug(flag)
         self.assembler = AssemblerARM(self, self.translate_support_code)
 
     def setup_once(self):
-        self.arch_version = detect_arch_version()
-        self.hf_abi = detect_hardfloat()
+        self.cpuinfo.arch_version = detect_arch_version()
+        self.cpuinfo.hf_abi = detect_hardfloat()
         self.assembler.setup_once()
 
     def finish_once(self):
         from rpython.jit.backend.arm.codebuilder import InstrBuilder
 
         for jmp, tgt in looptoken.compiled_loop_token.invalidate_positions:
-            mc = InstrBuilder(self.arch_version)
+            mc = InstrBuilder(self.cpuinfo.arch_version)
             mc.B_offs(tgt)
             mc.copy_to_raw_memory(jmp)
         # positions invalidated

rpython/jit/backend/arm/test/test_detect.py

 from rpython.jit.backend.arm.detect import detect_arch_version
 
 cpuinfo = "Processor : ARMv%d-compatible processor rev 7 (v6l)"""
-
+cpuinfo2 = """processor       : 0
+vendor_id       : GenuineIntel
+cpu family      : 6
+model           : 23
+model name      : Intel(R) Core(TM)2 Duo CPU     E8400  @ 3.00GHz
+stepping        : 10
+microcode       : 0xa07
+cpu MHz         : 2997.000
+cache size      : 6144 KB
+physical id     : 0
+siblings        : 2
+core id         : 0
+cpu cores       : 2
+apicid          : 0
+initial apicid  : 0
+fpu             : yes
+fpu_exception   : yes
+cpuid level     : 13
+wp              : yes
+flags           : fpu vme ...
+bogomips        : 5993.08
+clflush size    : 64
+cache_alignment : 64
+address sizes   : 36 bits physical, 48 bits virtual
+power management:
+"""
 
 def write_cpuinfo(info):
     filepath = udir.join('get_arch_version')
     assert detect_arch_version(write_cpuinfo(cpuinfo % 8)) == 7
     py.test.raises(ValueError,
             'detect_arch_version(write_cpuinfo(cpuinfo % 5))')
-    py.test.raises(ValueError,
-            'detect_arch_version(write_cpuinfo("Lorem ipsum dolor sit amet, consectetur"))')
+    assert detect_arch_version(write_cpuinfo(cpuinfo2)) == 6

rpython/jit/backend/arm/test/test_runner.py

 from rpython.rtyper.annlowlevel import llhelper
 from rpython.jit.codewriter.effectinfo import EffectInfo
 from rpython.jit.metainterp.history import JitCellToken, TargetToken
+from rpython.jit.backend.arm.detect import detect_arch_version
 
 
 CPU = getcpuclass()
     bridge_loop_instructions = ['ldr', 'mov', 'nop', 'cmp', 'bge',
                                 'push', 'mov', 'mov', 'push', 'mov', 'mov',
                                 'blx', 'mov', 'mov', 'bx']
-    if CPU.arch_version == 7:
+    arch_version = detect_arch_version()
+    if arch_version == 7:
         bridge_loop_instructions = ['ldr', 'mov', 'nop', 'cmp', 'bge',
                                     'push', 'mov', 'mov', 'push', 'mov', 'mov',
                                     'blx', 'mov', 'mov', 'bx']

rpython/memory/gc/env.py

 def best_nursery_size_for_L2cache(L2cache):
     # Heuristically, the best nursery size to choose is about half
     # of the L2 cache.
-    if L2cache > 1024 * 1024: # we don't want to have nursery estimated
+    if L2cache > 2 * 1024 * 1024: # we don't want to have nursery estimated
         # on L2 when L3 is present
         return L2cache // 2
     else:

rpython/memory/gc/minimark.py

             # hacking at the current nursery position in collect_and_reserve().
             if newsize <= 0:
                 newsize = env.estimate_best_nursery_size()
-                #         4*1024*1024   # fixed to 4MB by default
-                #        (it was env.estimate_best_nursery_size())
                 if newsize <= 0:
                     newsize = defaultsize
             if newsize < minsize:

rpython/rlib/rwin32.py

 import os
 import errno
 
+from rpython.rtyper.module.ll_os_environ import make_env_impls
 from rpython.rtyper.tool import rffi_platform
 from rpython.tool.udir import udir
 from rpython.translator.tool.cbuild import ExternalCompilationInfo
                 raise lastWindowsError('os_kill failed to terminate process')
         finally:
             CloseHandle(handle)
+
+    _wenviron_items, _wgetenv, _wputenv = make_env_impls(win32=True)

rpython/rlib/test/test_rwin32.py

+# encoding: utf-8
 import os, py
 if os.name != 'nt':
     py.test.skip('tests for win32 only')
     rwin32.CloseHandle(handle)
     assert proc.wait() == signal.SIGTERM
  
+@py.test.mark.dont_track_allocations('putenv intentionally keeps strings alive')
+def test_wenviron():
+    name, value = u'PYPY_TEST_日本', u'foobar日本'
+    rwin32._wputenv(name, value)
+    assert rwin32._wgetenv(name) == value
+    env = dict(rwin32._wenviron_items())
+    assert env[name] == value
+    for key, value in env.iteritems():
+        assert type(key) is unicode
+        assert type(value) is unicode

rpython/rtyper/module/ll_os.py

 
 import os, sys, errno
 import py
-from rpython.rtyper.module.support import OOSupport
+from rpython.rtyper.module.support import (
+    _WIN32, OOSupport, StringTraits, UnicodeTraits, underscore_on_windows)
 from rpython.tool.sourcetools import func_renamer
 from rpython.rlib.rarithmetic import r_longlong
 from rpython.rtyper.extfunc import (
     BaseLazyRegistering, register_external)
 from rpython.rtyper.extfunc import registering, registering_if, extdef
 from rpython.annotator.model import (
-    SomeInteger, SomeString, SomeTuple, SomeFloat, SomeUnicodeString)
+    SomeInteger, SomeString, SomeTuple, SomeFloat, s_Str0, s_Unicode0)
 from rpython.annotator.model import s_ImpossibleValue, s_None, s_Bool
 from rpython.rtyper.lltypesystem import rffi
 from rpython.rtyper.lltypesystem import lltype
 from rpython.rtyper.lltypesystem.rstr import STR
 from rpython.rlib.objectmodel import specialize
 
-str0 = SomeString(no_nul=True)
-unicode0 = SomeUnicodeString(no_nul=True)
+str0 = s_Str0
+unicode0 = s_Unicode0
 
 def monkeypatch_rposix(posixfunc, unicodefunc, signature):
     func_name = posixfunc.__name__
     # Monkeypatch the function in rpython.rlib.rposix
     setattr(rposix, func_name, new_func)
 
-class StringTraits:
-    str = str
-    str0 = str0
-    CHAR = rffi.CHAR
-    CCHARP = rffi.CCHARP
-    charp2str = staticmethod(rffi.charp2str)
-    str2charp = staticmethod(rffi.str2charp)
-    free_charp = staticmethod(rffi.free_charp)
-    scoped_alloc_buffer = staticmethod(rffi.scoped_alloc_buffer)
-
-    @staticmethod
-    def posix_function_name(name):
-        return underscore_on_windows + name
-
-    @staticmethod
-    def ll_os_name(name):
-        return 'll_os.ll_os_' + name
-
-class UnicodeTraits:
-    str = unicode
-    str0 = unicode0
-    CHAR = rffi.WCHAR_T
-    CCHARP = rffi.CWCHARP
-    charp2str = staticmethod(rffi.wcharp2unicode)
-    str2charp = staticmethod(rffi.unicode2wcharp)
-    free_charp = staticmethod(rffi.free_wcharp)
-    scoped_alloc_buffer = staticmethod(rffi.scoped_alloc_unicodebuffer)
-
-    @staticmethod
-    def posix_function_name(name):
-        return underscore_on_windows + 'w' + name
-
-    @staticmethod
-    def ll_os_name(name):
-        return 'll_os.ll_os_w' + name
-
 def registering_str_unicode(posixfunc, condition=True):
     if not condition or posixfunc is None:
         return registering(None, condition=False)
 
 posix = __import__(os.name)
 
-if sys.platform.startswith('win'):
-    _WIN32 = True
-else:
-    _WIN32 = False
-
-if _WIN32:
-    underscore_on_windows = '_'
-else:
-    underscore_on_windows = ''
-
 includes = []
 if not _WIN32:
     # XXX many of these includes are not portable at all

rpython/rtyper/module/ll_os_environ.py

 from rpython.rtyper.controllerentry import Controller
 from rpython.rtyper.extfunc import register_external
 from rpython.rtyper.lltypesystem import rffi, lltype
-from rpython.rtyper.module import ll_os
-from rpython.rlib import rposix
+from rpython.rtyper.module.support import _WIN32, StringTraits, UnicodeTraits
+from rpython.translator.tool.cbuild import ExternalCompilationInfo
 
-str0 = ll_os.str0
+str0 = annmodel.s_Str0
 
 # ____________________________________________________________
 #
         return r_getenv
 
 # ____________________________________________________________
-#
-# Lower-level interface: dummy placeholders and external registations
-
-def r_getenv(name):
-    just_a_placeholder     # should return None if name not found
-
-os_getenv = rffi.llexternal('getenv', [rffi.CCHARP], rffi.CCHARP,
-                            threadsafe=False)
-
-def getenv_llimpl(name):
-    with rffi.scoped_str2charp(name) as l_name:
-        l_result = os_getenv(l_name)
-        return rffi.charp2str(l_result) if l_result else None
-
-register_external(r_getenv, [str0],
-                  annmodel.SomeString(can_be_None=True, no_nul=True),
-                  export_name='ll_os.ll_os_getenv',
-                  llimpl=getenv_llimpl)
-
-# ____________________________________________________________
-
-def r_putenv(name, value):
-    just_a_placeholder
-
-class EnvKeepalive:
-    pass
-envkeepalive = EnvKeepalive()
-envkeepalive.byname = {}
-
-os_putenv = rffi.llexternal('putenv', [rffi.CCHARP], rffi.INT)
-
-def putenv_llimpl(name, value):
-    l_string = rffi.str2charp('%s=%s' % (name, value))
-    error = rffi.cast(lltype.Signed, os_putenv(l_string))
-    if error:
-        rffi.free_charp(l_string)
-        raise OSError(rposix.get_errno(), "os_putenv failed")
-    # keep 'l_string' alive - we know that the C library needs it
-    # until the next call to putenv() with the same 'name'.
-    l_oldstring = envkeepalive.byname.get(name, lltype.nullptr(rffi.CCHARP.TO))
-    envkeepalive.byname[name] = l_string
-    if l_oldstring:
-        rffi.free_charp(l_oldstring)
-
-register_external(r_putenv, [str0, str0], annmodel.s_None,
-                  export_name='ll_os.ll_os_putenv',
-                  llimpl=putenv_llimpl)
-
-# ____________________________________________________________
-
-def r_unsetenv(name):
-    # default implementation for platforms without a real unsetenv()
-    r_putenv(name, '')
-
-if hasattr(__import__(os.name), 'unsetenv'):
-    os_unsetenv = rffi.llexternal('unsetenv', [rffi.CCHARP], rffi.INT)
-
-    def unsetenv_llimpl(name):
-        with rffi.scoped_str2charp(name) as l_name:
-            error = rffi.cast(lltype.Signed, os_unsetenv(l_name))
-        if error:
-            raise OSError(rposix.get_errno(), "os_unsetenv failed")
-        try:
-            l_oldstring = envkeepalive.byname[name]
-        except KeyError:
-            pass
-        else:
-            del envkeepalive.byname[name]
-            rffi.free_charp(l_oldstring)
-
-    register_external(r_unsetenv, [str0], annmodel.s_None,
-                      export_name='ll_os.ll_os_unsetenv',
-                      llimpl=unsetenv_llimpl)
-
-# ____________________________________________________________
 # Access to the 'environ' external variable
 
-from rpython.translator.tool.cbuild import ExternalCompilationInfo
-
 if sys.platform.startswith('darwin'):
     CCHARPPP = rffi.CArrayPtr(rffi.CCHARPP)
     _os_NSGetEnviron = rffi.llexternal(
         )
     def os_get_environ():
         return _os_NSGetEnviron()[0]
-elif sys.platform.startswith('win'):
+elif _WIN32:
+    eci = ExternalCompilationInfo(includes=['stdlib.h'])
+    CWCHARPP = lltype.Ptr(lltype.Array(rffi.CWCHARP, hints={'nolength': True}))
+
     os_get_environ, _os_set_environ = rffi.CExternVariable(
-        rffi.CCHARPP,
-        '_environ',
-        ExternalCompilationInfo(includes=['stdlib.h']))
+        rffi.CCHARPP, '_environ', eci)
+    get__wenviron, _set__wenviron = rffi.CExternVariable(
+        CWCHARPP, '_wenviron', eci, c_type='wchar_t **')
 else:
     os_get_environ, _os_set_environ = rffi.CExternVariable(
         rffi.CCHARPP, 'environ', ExternalCompilationInfo())
 
 # ____________________________________________________________
+#
+# Lower-level interface: dummy placeholders and external registations
 
 def r_envkeys():
     just_a_placeholder
 def r_envitems():
     just_a_placeholder
 
-def envitems_llimpl():
-    environ = os_get_environ()
-    result = []
-    i = 0
-    while environ[i]:
-        name_value = rffi.charp2str(environ[i])
-        p = name_value.find('=')
-        if p >= 0:
-            result.append((name_value[:p], name_value[p+1:]))
-        i += 1
-    return result
+def r_getenv(name):
+    just_a_placeholder     # should return None if name not found
+
+def r_putenv(name, value):
+    just_a_placeholder
+
+os_getenv = rffi.llexternal('getenv', [rffi.CCHARP], rffi.CCHARP,
+                            threadsafe=False)
+os_putenv = rffi.llexternal('putenv', [rffi.CCHARP], rffi.INT)
+if _WIN32:
+    _wgetenv = rffi.llexternal('_wgetenv', [rffi.CWCHARP], rffi.CWCHARP,
+                               compilation_info=eci, threadsafe=False)
+    _wputenv = rffi.llexternal('_wputenv', [rffi.CWCHARP], rffi.INT,
+                               compilation_info=eci)
+
+class EnvKeepalive:
+    pass
+envkeepalive = EnvKeepalive()
+envkeepalive.byname = {}
+envkeepalive.bywname = {}
+
+def make_env_impls(win32=False):
+    if not win32:
+        traits = StringTraits()
+        get_environ, getenv, putenv = os_get_environ, os_getenv, os_putenv
+        byname, eq = envkeepalive.byname, '='
+        def last_error(msg):
+            from rpython.rlib import rposix
+            raise OSError(rposix.get_errno(), msg)
+    else:
+        traits = UnicodeTraits()
+        get_environ, getenv, putenv = get__wenviron, _wgetenv, _wputenv
+        byname, eq = envkeepalive.bywname, u'='
+        from rpython.rlib.rwin32 import lastWindowsError as last_error
+
+    def envitems_llimpl():
+        environ = get_environ()
+        result = []
+        i = 0
+        while environ[i]:
+            name_value = traits.charp2str(environ[i])
+            p = name_value.find(eq)
+            if p >= 0:
+                result.append((name_value[:p], name_value[p+1:]))
+            i += 1
+        return result
+
+    def getenv_llimpl(name):
+        with traits.scoped_str2charp(name) as l_name:
+            l_result = getenv(l_name)
+            return traits.charp2str(l_result) if l_result else None
+
+    def putenv_llimpl(name, value):
+        l_string = traits.str2charp(name + eq + value)
+        error = rffi.cast(lltype.Signed, putenv(l_string))
+        if error:
+            traits.free_charp(l_string)
+            last_error("putenv failed")
+        # keep 'l_string' alive - we know that the C library needs it
+        # until the next call to putenv() with the same 'name'.
+        l_oldstring = byname.get(name, lltype.nullptr(traits.CCHARP.TO))
+        byname[name] = l_string
+        if l_oldstring:
+            traits.free_charp(l_oldstring)
+
+    return envitems_llimpl, getenv_llimpl, putenv_llimpl
+
+envitems_llimpl, getenv_llimpl, putenv_llimpl = make_env_impls()
 
 register_external(r_envitems, [], [(str0, str0)],
                   export_name='ll_os.ll_os_envitems',
                   llimpl=envitems_llimpl)
+register_external(r_getenv, [str0],
+                  annmodel.SomeString(can_be_None=True, no_nul=True),
+                  export_name='ll_os.ll_os_getenv',
+                  llimpl=getenv_llimpl)
+register_external(r_putenv, [str0, str0], annmodel.s_None,
+                  export_name='ll_os.ll_os_putenv',
+                  llimpl=putenv_llimpl)
+
+# ____________________________________________________________
+
+def r_unsetenv(name):
+    # default implementation for platforms without a real unsetenv()
+    r_putenv(name, '')
+
+if hasattr(__import__(os.name), 'unsetenv'):
+    os_unsetenv = rffi.llexternal('unsetenv', [rffi.CCHARP], rffi.INT)
+
+    def unsetenv_llimpl(name):
+        with rffi.scoped_str2charp(name) as l_name:
+            error = rffi.cast(lltype.Signed, os_unsetenv(l_name))
+        if error:
+            from rpython.rlib import rposix
+            raise OSError(rposix.get_errno(), "os_unsetenv failed")
+        try:
+            l_oldstring = envkeepalive.byname[name]
+        except KeyError:
+            pass
+        else:
+            del envkeepalive.byname[name]
+            rffi.free_charp(l_oldstring)
+
+    register_external(r_unsetenv, [str0], annmodel.s_None,
+                      export_name='ll_os.ll_os_unsetenv',
+                      llimpl=unsetenv_llimpl)

rpython/rtyper/module/support.py

-from rpython.rtyper.lltypesystem import lltype
+import os
+import sys
+
+from rpython.annotator import model as annmodel
+from rpython.rtyper.lltypesystem import lltype, rffi
 from rpython.rtyper.ootypesystem import ootype
-import os
+
+_WIN32 = sys.platform.startswith('win')
+underscore_on_windows = '_' if _WIN32 else ''
 
 # utility conversion functions
 class LLSupport:
     from_rstr_nonnull = staticmethod(from_rstr_nonnull)
 
 
+class StringTraits:
+    str = str
+    str0 = annmodel.s_Str0
+    CHAR = rffi.CHAR
+    CCHARP = rffi.CCHARP
+    charp2str = staticmethod(rffi.charp2str)
+    scoped_str2charp = staticmethod(rffi.scoped_str2charp)
+    str2charp = staticmethod(rffi.str2charp)
+    free_charp = staticmethod(rffi.free_charp)
+    scoped_alloc_buffer = staticmethod(rffi.scoped_alloc_buffer)
+
+    @staticmethod
+    def posix_function_name(name):
+        return underscore_on_windows + name
+
+    @staticmethod
+    def ll_os_name(name):
+        return 'll_os.ll_os_' + name
+
+class UnicodeTraits:
+    str = unicode
+    str0 = annmodel.s_Unicode0
+    CHAR = rffi.WCHAR_T
+    CCHARP = rffi.CWCHARP
+    charp2str = staticmethod(rffi.wcharp2unicode)
+    str2charp = staticmethod(rffi.unicode2wcharp)
+    scoped_str2charp = staticmethod(rffi.scoped_unicode2wcharp)
+    free_charp = staticmethod(rffi.free_wcharp)
+    scoped_alloc_buffer = staticmethod(rffi.scoped_alloc_unicodebuffer)
+
+    @staticmethod
+    def posix_function_name(name):
+        return underscore_on_windows + 'w' + name
+
+    @staticmethod
+    def ll_os_name(name):
+        return 'll_os.ll_os_w' + name
+
+
 def ll_strcpy(dst_s, src_s, n):
     dstchars = dst_s.chars
     srcchars = src_s.chars
     while i < n:
         dstchars[i] = srcchars[i]
         i += 1
-
-
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.