[pypy-commit] pypy numpypy-out: merge with default

mattip noreply at buildbot.pypy.org
Mon Feb 13 00:57:51 CET 2012


Author: mattip
Branch: numpypy-out
Changeset: r52402:5325f0bba750
Date: 2012-02-09 20:06 +0200
http://bitbucket.org/pypy/pypy/changeset/5325f0bba750/

Log:	merge with default

diff --git a/lib_pypy/numpy.py b/lib_pypy/numpy.py
new file mode 100644
--- /dev/null
+++ b/lib_pypy/numpy.py
@@ -0,0 +1,5 @@
+raise ImportError(
+    "The 'numpy' module of PyPy is in-development and not complete. "
+    "To try it out anyway, you can either import from 'numpypy', "
+    "or just write 'import numpypy' first in your program and then "
+    "import from 'numpy' as usual.")
diff --git a/lib_pypy/numpypy/__init__.py b/lib_pypy/numpypy/__init__.py
--- a/lib_pypy/numpypy/__init__.py
+++ b/lib_pypy/numpypy/__init__.py
@@ -1,2 +1,5 @@
 from _numpypy import *
 from .core import *
+
+import sys
+sys.modules.setdefault('numpy', sys.modules['numpypy'])
diff --git a/lib_pypy/numpypy/core/numeric.py b/lib_pypy/numpypy/core/numeric.py
--- a/lib_pypy/numpypy/core/numeric.py
+++ b/lib_pypy/numpypy/core/numeric.py
@@ -1,6 +1,7 @@
 
-from _numpypy import array, ndarray, int_, float_ #, complex_# , longlong
+from _numpypy import array, ndarray, int_, float_, bool_ #, complex_# , longlong
 from _numpypy import concatenate
+import math
 import sys
 import _numpypy as multiarray # ARGH
 from numpypy.core.arrayprint import array2string
@@ -309,3 +310,13 @@
 set_string_function(array_repr, 1)
 
 little_endian = (sys.byteorder == 'little')
+
+Inf = inf = infty = Infinity = PINF = float('inf')
+NINF = float('-inf')
+PZERO = 0.0
+NZERO = -0.0
+nan = NaN = NAN = float('nan')
+False_ = bool_(False)
+True_ = bool_(True)
+e = math.e
+pi = math.pi
\ No newline at end of file
diff --git a/py/_io/terminalwriter.py b/py/_io/terminalwriter.py
--- a/py/_io/terminalwriter.py
+++ b/py/_io/terminalwriter.py
@@ -271,16 +271,24 @@
                     ('srWindow', SMALL_RECT),
                     ('dwMaximumWindowSize', COORD)]
 
+    _GetStdHandle = ctypes.windll.kernel32.GetStdHandle
+    _GetStdHandle.argtypes = [wintypes.DWORD]
+    _GetStdHandle.restype = wintypes.HANDLE
     def GetStdHandle(kind):
-        return ctypes.windll.kernel32.GetStdHandle(kind)
+        return _GetStdHandle(kind)
 
-    SetConsoleTextAttribute = \
-        ctypes.windll.kernel32.SetConsoleTextAttribute
-
+    SetConsoleTextAttribute = ctypes.windll.kernel32.SetConsoleTextAttribute
+    SetConsoleTextAttribute.argtypes = [wintypes.HANDLE, wintypes.WORD]
+    SetConsoleTextAttribute.restype = wintypes.BOOL
+        
+    _GetConsoleScreenBufferInfo = \
+        ctypes.windll.kernel32.GetConsoleScreenBufferInfo
+    _GetConsoleScreenBufferInfo.argtypes = [wintypes.HANDLE, 
+                                ctypes.POINTER(CONSOLE_SCREEN_BUFFER_INFO)]
+    _GetConsoleScreenBufferInfo.restype = wintypes.BOOL
     def GetConsoleInfo(handle):
         info = CONSOLE_SCREEN_BUFFER_INFO()
-        ctypes.windll.kernel32.GetConsoleScreenBufferInfo(\
-            handle, ctypes.byref(info))
+        _GetConsoleScreenBufferInfo(handle, ctypes.byref(info))
         return info
 
     def _getdimensions():
diff --git a/pypy/annotation/annrpython.py b/pypy/annotation/annrpython.py
--- a/pypy/annotation/annrpython.py
+++ b/pypy/annotation/annrpython.py
@@ -93,6 +93,10 @@
         # make input arguments and set their type
         args_s = [self.typeannotation(t) for t in input_arg_types]
 
+        # XXX hack
+        annmodel.TLS.check_str_without_nul = (
+            self.translator.config.translation.check_str_without_nul)
+
         flowgraph, inputcells = self.get_call_parameters(function, args_s, policy)
         if not isinstance(flowgraph, FunctionGraph):
             assert isinstance(flowgraph, annmodel.SomeObject)
diff --git a/pypy/annotation/binaryop.py b/pypy/annotation/binaryop.py
--- a/pypy/annotation/binaryop.py
+++ b/pypy/annotation/binaryop.py
@@ -434,11 +434,13 @@
 class __extend__(pairtype(SomeString, SomeString)):
 
     def union((str1, str2)):
-        return SomeString(can_be_None=str1.can_be_None or str2.can_be_None)
+        can_be_None = str1.can_be_None or str2.can_be_None
+        no_nul = str1.no_nul and str2.no_nul
+        return SomeString(can_be_None=can_be_None, no_nul=no_nul)
 
     def add((str1, str2)):
         # propagate const-ness to help getattr(obj, 'prefix' + const_name)
-        result = SomeString()
+        result = SomeString(no_nul=str1.no_nul and str2.no_nul)
         if str1.is_immutable_constant() and str2.is_immutable_constant():
             result.const = str1.const + str2.const
         return result
@@ -475,7 +477,16 @@
                 raise NotImplementedError(
                     "string formatting mixing strings and unicode not supported")
         getbookkeeper().count('strformat', str, s_tuple)
-        return SomeString()
+        no_nul = str.no_nul
+        for s_item in s_tuple.items:
+            if isinstance(s_item, SomeFloat):
+                pass   # or s_item is a subclass, like SomeInteger
+            elif isinstance(s_item, SomeString) and s_item.no_nul:
+                pass
+            else:
+                no_nul = False
+                break
+        return SomeString(no_nul=no_nul)
 
 
 class __extend__(pairtype(SomeString, SomeObject)):
@@ -828,7 +839,7 @@
     exec source.compile() in glob
 
 _make_none_union('SomeInstance',   'classdef=obj.classdef, can_be_None=True')
-_make_none_union('SomeString',      'can_be_None=True')
+_make_none_union('SomeString',      'no_nul=obj.no_nul, can_be_None=True')
 _make_none_union('SomeUnicodeString', 'can_be_None=True')
 _make_none_union('SomeList',         'obj.listdef')
 _make_none_union('SomeDict',          'obj.dictdef')
diff --git a/pypy/annotation/bookkeeper.py b/pypy/annotation/bookkeeper.py
--- a/pypy/annotation/bookkeeper.py
+++ b/pypy/annotation/bookkeeper.py
@@ -342,10 +342,11 @@
             else:
                 raise Exception("seeing a prebuilt long (value %s)" % hex(x))
         elif issubclass(tp, str): # py.lib uses annotated str subclasses
+            no_nul = not '\x00' in x
             if len(x) == 1:
-                result = SomeChar()
+                result = SomeChar(no_nul=no_nul)
             else:
-                result = SomeString()
+                result = SomeString(no_nul=no_nul)
         elif tp is unicode:
             if len(x) == 1:
                 result = SomeUnicodeCodePoint()
diff --git a/pypy/annotation/listdef.py b/pypy/annotation/listdef.py
--- a/pypy/annotation/listdef.py
+++ b/pypy/annotation/listdef.py
@@ -86,18 +86,19 @@
             read_locations = self.read_locations.copy()
             other_read_locations = other.read_locations.copy()
             self.read_locations.update(other.read_locations)
-            self.patch()    # which should patch all refs to 'other'
             s_value = self.s_value
             s_other_value = other.s_value
             s_new_value = unionof(s_value, s_other_value)
+            if s_new_value != s_value:
+                if self.dont_change_any_more:
+                    raise TooLateForChange
             if isdegenerated(s_new_value):
                 if self.bookkeeper:
                     self.bookkeeper.ondegenerated(self, s_new_value)
                 elif other.bookkeeper:
                     other.bookkeeper.ondegenerated(other, s_new_value)
+            self.patch()    # which should patch all refs to 'other'
             if s_new_value != s_value:
-                if self.dont_change_any_more:
-                    raise TooLateForChange
                 self.s_value = s_new_value
                 # reflow from reading points
                 for position_key in read_locations:
@@ -222,4 +223,5 @@
 
 MOST_GENERAL_LISTDEF = ListDef(None, SomeObject())
 
-s_list_of_strings = SomeList(ListDef(None, SomeString(), resized = True))
+s_list_of_strings = SomeList(ListDef(None, SomeString(no_nul=True),
+                                     resized = True))
diff --git a/pypy/annotation/model.py b/pypy/annotation/model.py
--- a/pypy/annotation/model.py
+++ b/pypy/annotation/model.py
@@ -39,7 +39,9 @@
 DEBUG = False    # set to False to disable recording of debugging information
 
 class State(object):
-    pass
+    # A global attribute :-(  Patch it with 'True' to enable checking of
+    # the no_nul attribute...
+    check_str_without_nul = False
 TLS = State()
 
 class SomeObject(object):
@@ -225,43 +227,57 @@
     def __init__(self):
         pass
 
-class SomeString(SomeObject):
-    "Stands for an object which is known to be a string."
-    knowntype = str
+class SomeStringOrUnicode(SomeObject):
     immutable = True
-    def __init__(self, can_be_None=False):
-        self.can_be_None = can_be_None
+    can_be_None=False
+    no_nul = False  # No NUL character in the string.
+
+    def __init__(self, can_be_None=False, no_nul=False):
+        if can_be_None:
+            self.can_be_None = True
+        if no_nul:
+            self.no_nul = True
 
     def can_be_none(self):
         return self.can_be_None
 
+    def __eq__(self, other):
+        if self.__class__ is not other.__class__:
+            return False
+        d1 = self.__dict__
+        d2 = other.__dict__
+        if not TLS.check_str_without_nul:
+            d1 = d1.copy(); d1['no_nul'] = 0   # ignored
+            d2 = d2.copy(); d2['no_nul'] = 0   # ignored
+        return d1 == d2
+
+class SomeString(SomeStringOrUnicode):
+    "Stands for an object which is known to be a string."
+    knowntype = str
+
     def nonnoneify(self):
-        return SomeString(can_be_None=False)
+        return SomeString(can_be_None=False, no_nul=self.no_nul)
 
-class SomeUnicodeString(SomeObject):
+class SomeUnicodeString(SomeStringOrUnicode):
     "Stands for an object which is known to be an unicode string"
     knowntype = unicode
-    immutable = True
-    def __init__(self, can_be_None=False):
-        self.can_be_None = can_be_None
-
-    def can_be_none(self):
-        return self.can_be_None
 
     def nonnoneify(self):
-        return SomeUnicodeString(can_be_None=False)
+        return SomeUnicodeString(can_be_None=False, no_nul=self.no_nul)
 
 class SomeChar(SomeString):
     "Stands for an object known to be a string of length 1."
     can_be_None = False
-    def __init__(self):    # no 'can_be_None' argument here
-        pass
+    def __init__(self, no_nul=False):    # no 'can_be_None' argument here
+        if no_nul:
+            self.no_nul = True
 
 class SomeUnicodeCodePoint(SomeUnicodeString):
     "Stands for an object known to be a unicode codepoint."
     can_be_None = False
-    def __init__(self):    # no 'can_be_None' argument here
-        pass
+    def __init__(self, no_nul=False):    # no 'can_be_None' argument here
+        if no_nul:
+            self.no_nul = True
 
 SomeString.basestringclass = SomeString
 SomeString.basecharclass = SomeChar
@@ -502,6 +518,7 @@
 s_None = SomePBC([], can_be_None=True)
 s_Bool = SomeBool()
 s_ImpossibleValue = SomeImpossibleValue()
+s_Str0 = SomeString(no_nul=True)
 
 # ____________________________________________________________
 # weakrefs
@@ -716,8 +733,7 @@
 
 def not_const(s_obj):
     if s_obj.is_constant():
-        new_s_obj = SomeObject()
-        new_s_obj.__class__ = s_obj.__class__
+        new_s_obj = SomeObject.__new__(s_obj.__class__)
         dic = new_s_obj.__dict__ = s_obj.__dict__.copy()
         if 'const' in dic:
             del new_s_obj.const
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
@@ -456,6 +456,20 @@
             return ''.join(g(n))
         s = a.build_types(f, [int])
         assert s.knowntype == str
+        assert s.no_nul
+
+    def test_str_split(self):
+        a = self.RPythonAnnotator()
+        def g(n):
+            if n:
+                return "test string"
+        def f(n):
+            if n:
+                return g(n).split(' ')
+        s = a.build_types(f, [int])
+        assert isinstance(s, annmodel.SomeList)
+        s_item = s.listdef.listitem.s_value
+        assert s_item.no_nul
 
     def test_str_splitlines(self):
         a = self.RPythonAnnotator()
@@ -465,6 +479,18 @@
         assert isinstance(s, annmodel.SomeList)
         assert s.listdef.listitem.resized
 
+    def test_str_strip(self):
+        a = self.RPythonAnnotator()
+        def f(n, a_str):
+            if n == 0:
+                return a_str.strip(' ')
+            elif n == 1:
+                return a_str.rstrip(' ')
+            else: 
+                return a_str.lstrip(' ')
+        s = a.build_types(f, [int, annmodel.SomeString(no_nul=True)])
+        assert s.no_nul
+
     def test_str_mul(self):
         a = self.RPythonAnnotator()
         def f(a_str):
@@ -1841,7 +1867,7 @@
             return obj.indirect()
         a = self.RPythonAnnotator()
         s = a.build_types(f, [bool])
-        assert s == annmodel.SomeString(can_be_None=True)
+        assert annmodel.SomeString(can_be_None=True).contains(s)
 
     def test_dont_see_AttributeError_clause(self):
         class Stuff:
@@ -2018,6 +2044,37 @@
         s = a.build_types(g, [int])
         assert not s.can_be_None
 
+    def test_string_noNUL_canbeNone(self):
+        def f(a):
+            if a:
+                return "abc"
+            else:
+                return None
+        a = self.RPythonAnnotator()
+        s = a.build_types(f, [int])
+        assert s.can_be_None
+        assert s.no_nul
+
+    def test_str_or_None(self):
+        def f(a):
+            if a:
+                return "abc"
+            else:
+                return None
+        def g(a):
+            x = f(a)
+            #assert x is not None
+            if x is None:
+                return "abcd"
+            return x
+            if isinstance(x, str):
+                return x
+            return "impossible"
+        a = self.RPythonAnnotator()
+        s = a.build_types(f, [int])
+        assert s.can_be_None
+        assert s.no_nul
+
     def test_emulated_pbc_call_simple(self):
         def f(a,b):
             return a + b
@@ -2071,6 +2128,19 @@
         assert isinstance(s, annmodel.SomeIterator)
         assert s.variant == ('items',)
 
+    def test_iteritems_str0(self):
+        def it(d):
+            return d.iteritems()
+        def f():
+            d0 = {'1a': '2a', '3': '4'}
+            for item in it(d0):
+                return "%s=%s" % item
+            raise ValueError
+        a = self.RPythonAnnotator()
+        s = a.build_types(f, [])
+        assert isinstance(s, annmodel.SomeString)
+        assert s.no_nul
+
     def test_non_none_and_none_with_isinstance(self):
         class A(object):
             pass
diff --git a/pypy/annotation/unaryop.py b/pypy/annotation/unaryop.py
--- a/pypy/annotation/unaryop.py
+++ b/pypy/annotation/unaryop.py
@@ -480,13 +480,13 @@
         return SomeInteger(nonneg=True)
 
     def method_strip(str, chr):
-        return str.basestringclass()
+        return str.basestringclass(no_nul=str.no_nul)
 
     def method_lstrip(str, chr):
-        return str.basestringclass()
+        return str.basestringclass(no_nul=str.no_nul)
 
     def method_rstrip(str, chr):
-        return str.basestringclass()
+        return str.basestringclass(no_nul=str.no_nul)
 
     def method_join(str, s_list):
         if s_None.contains(s_list):
@@ -497,7 +497,8 @@
             if isinstance(str, SomeUnicodeString):
                 return immutablevalue(u"")
             return immutablevalue("")
-        return str.basestringclass()
+        no_nul = str.no_nul and s_item.no_nul
+        return str.basestringclass(no_nul=no_nul)
 
     def iter(str):
         return SomeIterator(str)
@@ -508,18 +509,21 @@
 
     def method_split(str, patt, max=-1):
         getbookkeeper().count("str_split", str, patt)
-        return getbookkeeper().newlist(str.basestringclass())
+        s_item = str.basestringclass(no_nul=str.no_nul)
+        return getbookkeeper().newlist(s_item)
 
     def method_rsplit(str, patt, max=-1):
         getbookkeeper().count("str_rsplit", str, patt)
-        return getbookkeeper().newlist(str.basestringclass())
+        s_item = str.basestringclass(no_nul=str.no_nul)
+        return getbookkeeper().newlist(s_item)
 
     def method_replace(str, s1, s2):
         return str.basestringclass()
 
     def getslice(str, s_start, s_stop):
         check_negative_slice(s_start, s_stop)
-        return str.basestringclass()
+        result = str.basestringclass(no_nul=str.no_nul)
+        return result
 
 class __extend__(SomeUnicodeString):
     def method_encode(uni, s_enc):
diff --git a/pypy/config/translationoption.py b/pypy/config/translationoption.py
--- a/pypy/config/translationoption.py
+++ b/pypy/config/translationoption.py
@@ -123,6 +123,9 @@
                  default="off"),
     # jit_ffi is automatically turned on by withmod-_ffi (which is enabled by default)
     BoolOption("jit_ffi", "optimize libffi calls", default=False, cmdline=None),
+    BoolOption("check_str_without_nul",
+               "Forbid NUL chars in strings in some external function calls",
+               default=False, cmdline=None),
 
     # misc
     BoolOption("verbose", "Print extra information", default=False),
diff --git a/pypy/doc/Makefile b/pypy/doc/Makefile
--- a/pypy/doc/Makefile
+++ b/pypy/doc/Makefile
@@ -81,6 +81,7 @@
 	      "run these through (pdf)latex."
 
 man:
+	python config/generate.py
 	$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
 	@echo
 	@echo "Build finished. The manual pages are in $(BUILDDIR)/man"
diff --git a/pypy/doc/commandline_ref.rst b/pypy/doc/commandline_ref.rst
new file mode 100644
--- /dev/null
+++ b/pypy/doc/commandline_ref.rst
@@ -0,0 +1,10 @@
+Command line reference
+======================
+
+Manual pages
+------------
+
+.. toctree::
+   :maxdepth: 1
+
+   man/pypy.1.rst
diff --git a/pypy/doc/conf.py b/pypy/doc/conf.py
--- a/pypy/doc/conf.py
+++ b/pypy/doc/conf.py
@@ -45,9 +45,9 @@
 # built documents.
 #
 # The short X.Y version.
-version = '1.7'
+version = '1.8'
 # The full version, including alpha/beta/rc tags.
-release = '1.7'
+release = '1.8'
 
 # The language for content autogenerated by Sphinx. Refer to documentation
 # for a list of supported languages.
diff --git a/pypy/doc/config/translation.check_str_without_nul.txt b/pypy/doc/config/translation.check_str_without_nul.txt
new file mode 100644
--- /dev/null
+++ b/pypy/doc/config/translation.check_str_without_nul.txt
@@ -0,0 +1,5 @@
+If turned on, the annotator will keep track of which strings can
+potentially contain NUL characters, and complain if one such string
+is passed to some external functions --- e.g. if it is used as a
+filename in os.open().  Defaults to False because it is usually more
+pain than benefit, but turned on by targetpypystandalone.
diff --git a/pypy/doc/config/translation.log.txt b/pypy/doc/config/translation.log.txt
--- a/pypy/doc/config/translation.log.txt
+++ b/pypy/doc/config/translation.log.txt
@@ -2,4 +2,4 @@
 
 These must be enabled by setting the PYPYLOG environment variable.
 The exact set of features supported by PYPYLOG is described in
-pypy/translation/c/src/debug.h.
+pypy/translation/c/src/debug_print.h.
diff --git a/pypy/doc/garbage_collection.rst b/pypy/doc/garbage_collection.rst
--- a/pypy/doc/garbage_collection.rst
+++ b/pypy/doc/garbage_collection.rst
@@ -142,10 +142,9 @@
 So as a first approximation, when compared to the Hybrid GC, the
 Minimark GC saves one word of memory per old object.
 
-There are a number of environment variables that can be tweaked to
-influence the GC.  (Their default value should be ok for most usages.)
-You can read more about them at the start of
-`pypy/rpython/memory/gc/minimark.py`_.
+There are :ref:`a number of environment variables
+<minimark-environment-variables>` that can be tweaked to influence the
+GC.  (Their default value should be ok for most usages.)
 
 In more detail:
 
@@ -211,5 +210,4 @@
   are preserved.  If the object dies then the pre-reserved location
   becomes free garbage, to be collected at the next major collection.
 
-
 .. include:: _ref.txt
diff --git a/pypy/doc/gc_info.rst b/pypy/doc/gc_info.rst
new file mode 100644
--- /dev/null
+++ b/pypy/doc/gc_info.rst
@@ -0,0 +1,53 @@
+Garbage collector configuration
+===============================
+
+.. _minimark-environment-variables:
+
+Minimark
+--------
+
+PyPy's default ``minimark`` garbage collector is configurable through
+several environment variables:
+
+``PYPY_GC_NURSERY``
+    The nursery size.
+    Defaults to ``4MB``.
+    Small values (like 1 or 1KB) are useful for debugging.
+
+``PYPY_GC_MAJOR_COLLECT``
+    Major collection memory factor.
+    Default is ``1.82``, which means trigger a major collection when the
+    memory consumed equals 1.82 times the memory really used at the end
+    of the previous major collection.
+
+``PYPY_GC_GROWTH``
+    Major collection threshold's max growth rate.
+    Default is ``1.4``.
+    Useful to collect more often than normally on sudden memory growth,
+    e.g. when there is a temporary peak in memory usage.
+
+``PYPY_GC_MAX``
+    The max heap size.
+    If coming near this limit, it will first collect more often, then
+    raise an RPython MemoryError, and if that is not enough, crash the
+    program with a fatal error.
+    Try values like ``1.6GB``.
+
+``PYPY_GC_MAX_DELTA``
+    The major collection threshold will never be set to more than
+    ``PYPY_GC_MAX_DELTA`` the amount really used after a collection.
+    Defaults to 1/8th of the total RAM size (which is constrained to be
+    at most 2/3/4GB on 32-bit systems).
+    Try values like ``200MB``.
+
+``PYPY_GC_MIN``
+    Don't collect while the memory size is below this limit.
+    Useful to avoid spending all the time in the GC in very small
+    programs.
+    Defaults to 8 times the nursery.
+
+``PYPY_GC_DEBUG``
+    Enable extra checks around collections that are too slow for normal
+    use.
+    Values are ``0`` (off), ``1`` (on major collections) or ``2`` (also
+    on minor collections).
diff --git a/pypy/doc/getting-started.rst b/pypy/doc/getting-started.rst
--- a/pypy/doc/getting-started.rst
+++ b/pypy/doc/getting-started.rst
@@ -53,11 +53,10 @@
 PyPy is ready to be executed as soon as you unpack the tarball or the zip
 file, with no need to install it in any specific location::
 
-    $ tar xf pypy-1.7-linux.tar.bz2
-
-    $ ./pypy-1.7/bin/pypy
-    Python 2.7.1 (?, Apr 27 2011, 12:44:21)
-    [PyPy 1.7.0 with GCC 4.4.3] on linux2
+    $ tar xf pypy-1.8-linux.tar.bz2
+    $ ./pypy-1.8/bin/pypy
+    Python 2.7.1 (48ebdce33e1b, Feb 09 2012, 00:55:31)
+    [PyPy 1.8.0 with GCC 4.4.3] on linux2
     Type "help", "copyright", "credits" or "license" for more information.
     And now for something completely different: ``implementing LOGO in LOGO:
     "turtles all the way down"''
@@ -75,14 +74,14 @@
 
     $ curl -O https://raw.github.com/pypa/pip/master/contrib/get-pip.py
 
-    $ ./pypy-1.7/bin/pypy distribute_setup.py
+    $ ./pypy-1.8/bin/pypy distribute_setup.py
 
-    $ ./pypy-1.7/bin/pypy get-pip.py
+    $ ./pypy-1.8/bin/pypy get-pip.py
 
-    $ ./pypy-1.7/bin/pip install pygments  # for example
+    $ ./pypy-1.8/bin/pip install pygments  # for example
 
-3rd party libraries will be installed in ``pypy-1.7/site-packages``, and
-the scripts in ``pypy-1.7/bin``.
+3rd party libraries will be installed in ``pypy-1.8/site-packages``, and
+the scripts in ``pypy-1.8/bin``.
 
 Installing using virtualenv
 ---------------------------
diff --git a/pypy/doc/index.rst b/pypy/doc/index.rst
--- a/pypy/doc/index.rst
+++ b/pypy/doc/index.rst
@@ -15,7 +15,7 @@
 
 * `FAQ`_: some frequently asked questions.
 
-* `Release 1.7`_: the latest official release
+* `Release 1.8`_: the latest official release
 
 * `PyPy Blog`_: news and status info about PyPy 
 
@@ -75,7 +75,7 @@
 .. _`Getting Started`: getting-started.html
 .. _`Papers`: extradoc.html
 .. _`Videos`: video-index.html
-.. _`Release 1.7`: http://pypy.org/download.html
+.. _`Release 1.8`: http://pypy.org/download.html
 .. _`speed.pypy.org`: http://speed.pypy.org
 .. _`RPython toolchain`: translation.html
 .. _`potential project ideas`: project-ideas.html
@@ -120,9 +120,9 @@
 Windows, on top of .NET, and on top of Java.
 To dig into PyPy it is recommended to try out the current
 Mercurial default branch, which is always working or mostly working,
-instead of the latest release, which is `1.7`__.
+instead of the latest release, which is `1.8`__.
 
-.. __: release-1.7.0.html
+.. __: release-1.8.0.html
 
 PyPy is mainly developed on Linux and Mac OS X.  Windows is supported,
 but platform-specific bugs tend to take longer before we notice and fix
@@ -353,10 +353,12 @@
    getting-started-dev.rst
    windows.rst
    faq.rst
+   commandline_ref.rst
    architecture.rst
    coding-guide.rst
    cpython_differences.rst
    garbage_collection.rst
+   gc_info.rst
    interpreter.rst
    objspace.rst
    __pypy__-module.rst
diff --git a/pypy/doc/jit-hooks.rst b/pypy/doc/jit-hooks.rst
new file mode 100644
--- /dev/null
+++ b/pypy/doc/jit-hooks.rst
@@ -0,0 +1,66 @@
+JIT hooks in PyPy
+=================
+
+There are several hooks in the `pypyjit` module that may help you with
+understanding what's pypy's JIT doing while running your program. There
+are three functions related to that coming from the `pypyjit` module:
+
+* `set_optimize_hook`::
+
+    Set a compiling hook that will be called each time a loop is optimized,
+    but before assembler compilation. This allows to add additional
+    optimizations on Python level.
+    
+    The hook will be called with the following signature:
+    hook(jitdriver_name, loop_type, greenkey or guard_number, operations)
+
+    jitdriver_name is the name of this particular jitdriver, 'pypyjit' is
+    the main interpreter loop
+
+    loop_type can be either `loop` `entry_bridge` or `bridge`
+    in case loop is not `bridge`, greenkey will be a tuple of constants
+    or a string describing it.
+
+    for the interpreter loop` it'll be a tuple
+    (code, offset, is_being_profiled)
+
+    Note that jit hook is not reentrant. It means that if the code
+    inside the jit hook is itself jitted, it will get compiled, but the
+    jit hook won't be called for that.
+
+    Result value will be the resulting list of operations, or None
+
+* `set_compile_hook`::
+
+    Set a compiling hook that will be called each time a loop is compiled.
+    The hook will be called with the following signature:
+    hook(jitdriver_name, loop_type, greenkey or guard_number, operations,
+         assembler_addr, assembler_length)
+
+    jitdriver_name is the name of this particular jitdriver, 'pypyjit' is
+    the main interpreter loop
+
+    loop_type can be either `loop` `entry_bridge` or `bridge`
+    in case loop is not `bridge`, greenkey will be a tuple of constants
+    or a string describing it.
+
+    for the interpreter loop` it'll be a tuple
+    (code, offset, is_being_profiled)
+
+    assembler_addr is an integer describing where assembler starts,
+    can be accessed via ctypes, assembler_lenght is the lenght of compiled
+    asm
+
+    Note that jit hook is not reentrant. It means that if the code
+    inside the jit hook is itself jitted, it will get compiled, but the
+    jit hook won't be called for that.
+
+* `set_abort_hook`::
+
+    Set a hook (callable) that will be called each time there is tracing
+    aborted due to some reason.
+
+    The hook will be called as in: hook(jitdriver_name, greenkey, reason)
+
+    Where reason is the reason for abort, see documentation for set_compile_hook
+    for descriptions of other arguments.
diff --git a/pypy/doc/jit/index.rst b/pypy/doc/jit/index.rst
--- a/pypy/doc/jit/index.rst
+++ b/pypy/doc/jit/index.rst
@@ -21,6 +21,9 @@
 
 - Notes_ about the current work in PyPy
 
+- Hooks_ debugging facilities available to a python programmer
+
 
 .. _Overview: overview.html
 .. _Notes: pyjitpl5.html
+.. _Hooks: ../jit-hooks.html
diff --git a/pypy/doc/man/pypy.1.rst b/pypy/doc/man/pypy.1.rst
--- a/pypy/doc/man/pypy.1.rst
+++ b/pypy/doc/man/pypy.1.rst
@@ -24,6 +24,9 @@
 -S
     Do not ``import site`` on initialization.
 
+-s
+    Don't add the user site directory to `sys.path`.
+
 -u
     Unbuffered binary ``stdout`` and ``stderr``.
 
@@ -39,6 +42,9 @@
 -E
     Ignore environment variables (such as ``PYTHONPATH``).
 
+-B
+    Disable writing bytecode (``.pyc``) files.
+
 --version
     Print the PyPy version.
 
@@ -84,6 +90,64 @@
         Optimizations to enabled or ``all``.
         Warning, this option is dangerous, and should be avoided.
 
+ENVIRONMENT
+===========
+
+``PYTHONPATH``
+    Add directories to pypy's module search path.
+    The format is the same as shell's ``PATH``.
+
+``PYTHONSTARTUP``
+    A script referenced by this variable will be executed before the
+    first prompt is displayed, in interactive mode.
+
+``PYTHONDONTWRITEBYTECODE``
+    If set to a non-empty value, equivalent to the ``-B`` option.
+    Disable writing ``.pyc`` files.
+
+``PYTHONINSPECT``
+    If set to a non-empty value, equivalent to the ``-i`` option.
+    Inspect interactively after running the specified script.
+
+``PYTHONIOENCODING``
+    If this is set, it overrides the encoding used for
+    *stdin*/*stdout*/*stderr*.
+    The syntax is *encodingname*:*errorhandler*
+    The *errorhandler* part is optional and has the same meaning as in
+    `str.encode`.
+
+``PYTHONNOUSERSITE``
+    If set to a non-empty value, equivalent to the ``-s`` option.
+    Don't add the user site directory to `sys.path`.
+
+``PYTHONWARNINGS``
+    If set, equivalent to the ``-W`` option (warning control).
+    The value should be a comma-separated list of ``-W`` parameters.
+
+``PYPYLOG``
+    If set to a non-empty value, enable logging, the format is:
+
+    *fname*
+        logging for profiling: includes all
+        ``debug_start``/``debug_stop`` but not any nested
+        ``debug_print``.
+        *fname* can be ``-`` to log to *stderr*.
+
+    ``:``\ *fname*
+        Full logging, including ``debug_print``.
+
+    *prefix*\ ``:``\ *fname*
+        Conditional logging.
+        Multiple prefixes can be specified, comma-separated.
+        Only sections whose name match the prefix will be logged.
+
+    ``PYPYLOG``\ =\ ``jit-log-opt,jit-backend:``\ *logfile* will
+    generate a log suitable for *jitviewer*, a tool for debugging
+    performance issues under PyPy.
+
+.. include:: ../gc_info.rst
+   :start-line: 7
+
 SEE ALSO
 ========
 
diff --git a/pypy/doc/release-1.8.0.rst b/pypy/doc/release-1.8.0.rst
new file mode 100644
--- /dev/null
+++ b/pypy/doc/release-1.8.0.rst
@@ -0,0 +1,93 @@
+============================
+PyPy 1.8 - business as usual
+============================
+
+We're pleased to announce the 1.8 release of PyPy. As habitual this
+release brings a lot of bugfixes, together with performance and memory improvements over
+the 1.7 release. The main highlight of the release is the introduction of
+`list strategies`_ which makes homogenous lists more efficient both in terms
+of performance and memory. This release also upgrades us from Python 2.7.1 compatibility to 2.7.2. Otherwise it's "business as usual" in the sense
+that performance improved roughly 10% on average since the previous release.
+
+You can download the PyPy 1.8 release here:
+
+    http://pypy.org/download.html
+
+.. _`list strategies`: http://morepypy.blogspot.com/2011/10/more-compact-lists-with-list-strategies.html
+
+What is PyPy?
+=============
+
+PyPy is a very compliant Python interpreter, almost a drop-in replacement for
+CPython 2.7. It's fast (`pypy 1.8 and cpython 2.7.1`_ performance comparison)
+due to its integrated tracing JIT compiler.
+
+This release supports x86 machines running Linux 32/64, Mac OS X 32/64 or
+Windows 32. Windows 64 work has been stalled, we would welcome a volunteer
+to handle that.
+
+.. _`pypy 1.8 and cpython 2.7.1`: http://speed.pypy.org
+
+
+Highlights
+==========
+
+* List strategies. Now lists that contain only ints or only floats should
+  be as efficient as storing them in a binary-packed array. It also improves
+  the JIT performance in places that use such lists. There are also special
+  strategies for unicode and string lists.
+
+* As usual, numerous performance improvements. There are many examples
+  of python constructs that now should be faster; too many to list them.
+
+* Bugfixes and compatibility fixes with CPython.
+
+* Windows fixes.
+
+* NumPy effort progress; for the exact list of things that have been done,
+  consult the `numpy status page`_. A tentative list of things that has
+  been done:
+
+  * multi dimensional arrays
+
+  * various sizes of dtypes
+
+  * a lot of ufuncs
+
+  * a lot of other minor changes
+
+  Right now the `numpy` module is available under both `numpy` and `numpypy`
+  names. However, because it's incomplete, you have to `import numpypy` first
+  before doing any imports from `numpy`.
+
+* New JIT hooks that allow you to hook into the JIT process from your python
+  program. There is a `brief overview`_ of what they offer.
+
+* Standard library upgrade from 2.7.1 to 2.7.2.
+
+Ongoing work
+============
+
+As usual, there is quite a bit of ongoing work that either didn't make it to
+the release or is not ready yet. Highlights include:
+
+* Non-x86 backends for the JIT: ARMv7 (almost ready) and PPC64 (in progress)
+
+* Specialized type instances - allocate instances as efficient as C structs,
+  including type specialization
+
+* More numpy work
+
+* Since the last release there was a significant breakthrough in PyPy's
+  fundraising. We now have enough funds to work on first stages of `numpypy`_
+  and `py3k`_. We would like to thank again to everyone who donated.
+
+* It's also probably worth noting, we're considering donations for the
+  Software Transactional Memory project. You can read more about `our plans`_
+
+.. _`brief overview`: http://doc.pypy.org/en/latest/jit-hooks.html
+.. _`numpy status page`: http://buildbot.pypy.org/numpy-status/latest.html
+.. _`numpy status update blog report`: http://morepypy.blogspot.com/2012/01/numpypy-status-update.html
+.. _`numpypy`: http://pypy.org/numpydonate.html
+.. _`py3k`: http://pypy.org/py3donate.html
+.. _`our plans`: http://morepypy.blogspot.com/2012/01/transactional-memory-ii.html
diff --git a/pypy/interpreter/astcompiler/optimize.py b/pypy/interpreter/astcompiler/optimize.py
--- a/pypy/interpreter/astcompiler/optimize.py
+++ b/pypy/interpreter/astcompiler/optimize.py
@@ -302,8 +302,7 @@
                     # narrow builds will return a surrogate.  In both
                     # the cases skip the optimization in order to
                     # produce compatible pycs.
-                    if (self.space.isinstance_w(w_obj, self.space.w_unicode)
-                        and 
+                    if (self.space.isinstance_w(w_obj, self.space.w_unicode) and
                         self.space.isinstance_w(w_const, self.space.w_unicode)):
                         unistr = self.space.unicode_w(w_const)
                         if len(unistr) == 1:
@@ -311,7 +310,7 @@
                         else:
                             ch = 0
                         if (ch > 0xFFFF or
-                            (MAXUNICODE == 0xFFFF and 0xD800 <= ch <= 0xDFFFF)):
+                            (MAXUNICODE == 0xFFFF and 0xD800 <= ch <= 0xDFFF)):
                             return subs
 
                     return ast.Const(w_const, subs.lineno, subs.col_offset)
diff --git a/pypy/interpreter/astcompiler/test/test_compiler.py b/pypy/interpreter/astcompiler/test/test_compiler.py
--- a/pypy/interpreter/astcompiler/test/test_compiler.py
+++ b/pypy/interpreter/astcompiler/test/test_compiler.py
@@ -838,7 +838,7 @@
         # Just checking this doesn't crash out
         self.count_instructions(source)
 
-    def test_const_fold_unicode_subscr(self):
+    def test_const_fold_unicode_subscr(self, monkeypatch):
         source = """def f():
         return u"abc"[0]
         """
@@ -853,6 +853,14 @@
         assert counts == {ops.LOAD_CONST: 2, ops.BINARY_SUBSCR: 1,
                           ops.RETURN_VALUE: 1}
 
+        monkeypatch.setattr(optimize, "MAXUNICODE", 0xFFFF)
+        source = """def f():
+        return u"\uE01F"[0]
+        """
+        counts = self.count_instructions(source)
+        assert counts == {ops.LOAD_CONST: 1, ops.RETURN_VALUE: 1}
+        monkeypatch.undo()
+
         # getslice is not yet optimized.
         # Still, check a case which yields the empty string.
         source = """def f():
diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py
--- a/pypy/interpreter/baseobjspace.py
+++ b/pypy/interpreter/baseobjspace.py
@@ -1312,6 +1312,15 @@
     def str_w(self, w_obj):
         return w_obj.str_w(self)
 
+    def str0_w(self, w_obj):
+        "Like str_w, but rejects strings with NUL bytes."
+        from pypy.rlib import rstring
+        result = w_obj.str_w(self)
+        if '\x00' in result:
+            raise OperationError(self.w_TypeError, self.wrap(
+                    'argument must be a string without NUL characters'))
+        return rstring.assert_str0(result)
+
     def int_w(self, w_obj):
         return w_obj.int_w(self)
 
@@ -1331,6 +1340,15 @@
     def unicode_w(self, w_obj):
         return w_obj.unicode_w(self)
 
+    def unicode0_w(self, w_obj):
+        "Like unicode_w, but rejects strings with NUL bytes."
+        from pypy.rlib import rstring
+        result = w_obj.unicode_w(self)
+        if u'\x00' in result:
+            raise OperationError(self.w_TypeError, self.wrap(
+                    'argument must be a unicode string without NUL characters'))
+        return rstring.assert_str0(result)
+
     def realunicode_w(self, w_obj):
         # Like unicode_w, but only works if w_obj is really of type
         # 'unicode'.
@@ -1629,6 +1647,9 @@
     'UnicodeEncodeError',
     'UnicodeDecodeError',
     ]
+    
+if sys.platform.startswith("win"):
+    ObjSpace.ExceptionTable += ['WindowsError']
 
 ## Irregular part of the interface:
 #
diff --git a/pypy/interpreter/gateway.py b/pypy/interpreter/gateway.py
--- a/pypy/interpreter/gateway.py
+++ b/pypy/interpreter/gateway.py
@@ -130,6 +130,9 @@
     def visit_str_or_None(self, el, app_sig):
         self.checked_space_method(el, app_sig)
 
+    def visit_str0(self, el, app_sig):
+        self.checked_space_method(el, app_sig)
+
     def visit_nonnegint(self, el, app_sig):
         self.checked_space_method(el, app_sig)
 
@@ -249,6 +252,9 @@
     def visit_str_or_None(self, typ):
         self.run_args.append("space.str_or_None_w(%s)" % (self.scopenext(),))
 
+    def visit_str0(self, typ):
+        self.run_args.append("space.str0_w(%s)" % (self.scopenext(),))
+
     def visit_nonnegint(self, typ):
         self.run_args.append("space.gateway_nonnegint_w(%s)" % (
             self.scopenext(),))
@@ -383,6 +389,9 @@
     def visit_str_or_None(self, typ):
         self.unwrap.append("space.str_or_None_w(%s)" % (self.nextarg(),))
 
+    def visit_str0(self, typ):
+        self.unwrap.append("space.str0_w(%s)" % (self.nextarg(),))
+
     def visit_nonnegint(self, typ):
         self.unwrap.append("space.gateway_nonnegint_w(%s)" % (self.nextarg(),))
 
diff --git a/pypy/interpreter/mixedmodule.py b/pypy/interpreter/mixedmodule.py
--- a/pypy/interpreter/mixedmodule.py
+++ b/pypy/interpreter/mixedmodule.py
@@ -50,7 +50,7 @@
             space.call_method(self.w_dict, 'update', self.w_initialdict)
 
         for w_submodule in self.submodules_w:
-            name = space.str_w(w_submodule.w_name)
+            name = space.str0_w(w_submodule.w_name)
             space.setitem(self.w_dict, space.wrap(name.split(".")[-1]), w_submodule)
             space.getbuiltinmodule(name)
 
diff --git a/pypy/interpreter/module.py b/pypy/interpreter/module.py
--- a/pypy/interpreter/module.py
+++ b/pypy/interpreter/module.py
@@ -31,7 +31,8 @@
     def install(self):
         """NOT_RPYTHON: installs this module into space.builtin_modules"""
         w_mod = self.space.wrap(self)
-        self.space.builtin_modules[self.space.unwrap(self.w_name)] = w_mod
+        modulename = self.space.str0_w(self.w_name)
+        self.space.builtin_modules[modulename] = w_mod
 
     def setup_after_space_initialization(self):
         """NOT_RPYTHON: to allow built-in modules to do some more setup
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
@@ -178,6 +178,14 @@
         res = self.space.interp_w(Function, w(None), can_be_None=True)
         assert res is None
 
+    def test_str0_w(self):
+        space = self.space
+        w = space.wrap
+        assert space.str0_w(w("123")) == "123"
+        exc = space.raises_w(space.w_TypeError, space.str0_w, w("123\x004"))
+        assert space.unicode0_w(w(u"123")) == u"123"
+        exc = space.raises_w(space.w_TypeError, space.unicode0_w, w(u"123\x004"))
+
     def test_getindex_w(self):
         w_instance1 = self.space.appexec([], """():
             class X(object):
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
@@ -780,6 +780,9 @@
         self.overflow_flag = ovf
         return z
 
+    def op_keepalive(self, _, x):
+        pass
+
     # ----------
     # delegating to the builtins do_xxx() (done automatically for simple cases)
 
diff --git a/pypy/jit/backend/x86/regalloc.py b/pypy/jit/backend/x86/regalloc.py
--- a/pypy/jit/backend/x86/regalloc.py
+++ b/pypy/jit/backend/x86/regalloc.py
@@ -1463,6 +1463,9 @@
         if jump_op is not None and jump_op.getdescr() is descr:
             self._compute_hint_frame_locations_from_descr(descr)
 
+    def consider_keepalive(self, op):
+        pass
+
     def not_implemented_op(self, op):
         not_implemented("not implemented operation: %s" % op.getopname())
 
diff --git a/pypy/jit/codewriter/flatten.py b/pypy/jit/codewriter/flatten.py
--- a/pypy/jit/codewriter/flatten.py
+++ b/pypy/jit/codewriter/flatten.py
@@ -162,7 +162,9 @@
         if len(block.exits) == 1:
             # A single link, fall-through
             link = block.exits[0]
-            assert link.exitcase is None
+            assert link.exitcase in (None, False, True)
+            # the cases False or True should not really occur, but can show
+            # up in the manually hacked graphs for generators...
             self.make_link(link)
         #
         elif block.exitswitch is c_last_exception:
diff --git a/pypy/jit/codewriter/policy.py b/pypy/jit/codewriter/policy.py
--- a/pypy/jit/codewriter/policy.py
+++ b/pypy/jit/codewriter/policy.py
@@ -48,7 +48,7 @@
         mod = func.__module__ or '?'
         if mod.startswith('pypy.rpython.module.'):
             return True
-        if mod.startswith('pypy.translator.'): # XXX wtf?
+        if mod == 'pypy.translator.goal.nanos':    # more helpers
             return True
         return False
 
diff --git a/pypy/jit/metainterp/executor.py b/pypy/jit/metainterp/executor.py
--- a/pypy/jit/metainterp/executor.py
+++ b/pypy/jit/metainterp/executor.py
@@ -254,6 +254,9 @@
         assert isinstance(x, r_longlong)  # 32-bit
         return BoxFloat(x)
 
+def do_keepalive(cpu, _, x):
+    pass
+
 # ____________________________________________________________
 
 ##def do_force_token(cpu):
diff --git a/pypy/jit/metainterp/pyjitpl.py b/pypy/jit/metainterp/pyjitpl.py
--- a/pypy/jit/metainterp/pyjitpl.py
+++ b/pypy/jit/metainterp/pyjitpl.py
@@ -1346,12 +1346,16 @@
             resbox = self.metainterp.execute_and_record_varargs(
                 rop.CALL_MAY_FORCE, allboxes, descr=descr)
             self.metainterp.vrefs_after_residual_call()
+            vablebox = None
             if assembler_call:
-                self.metainterp.direct_assembler_call(assembler_call_jd)
+                vablebox = self.metainterp.direct_assembler_call(
+                    assembler_call_jd)
             if resbox is not None:
                 self.make_result_of_lastop(resbox)
             self.metainterp.vable_after_residual_call()
             self.generate_guard(rop.GUARD_NOT_FORCED, None)
+            if vablebox is not None:
+                self.metainterp.history.record(rop.KEEPALIVE, [vablebox], None)
             self.metainterp.handle_possible_exception()
             return resbox
         else:
@@ -2478,6 +2482,15 @@
         token = warmrunnerstate.get_assembler_token(greenargs)
         op = op.copy_and_change(rop.CALL_ASSEMBLER, args=args, descr=token)
         self.history.operations.append(op)
+        #
+        # To fix an obscure issue, make sure the vable stays alive
+        # longer than the CALL_ASSEMBLER operation.  We do it by
+        # inserting explicitly an extra KEEPALIVE operation.
+        jd = token.outermost_jitdriver_sd
+        if jd.index_of_virtualizable >= 0:
+            return args[jd.index_of_virtualizable]
+        else:
+            return None
 
 # ____________________________________________________________
 
diff --git a/pypy/jit/metainterp/resoperation.py b/pypy/jit/metainterp/resoperation.py
--- a/pypy/jit/metainterp/resoperation.py
+++ b/pypy/jit/metainterp/resoperation.py
@@ -503,6 +503,7 @@
     'COPYUNICODECONTENT/5',
     'QUASIIMMUT_FIELD/1d',    # [objptr], descr=SlowMutateDescr
     'RECORD_KNOWN_CLASS/2',   # [objptr, clsptr]
+    'KEEPALIVE/1',
 
     '_CANRAISE_FIRST', # ----- start of can_raise operations -----
     '_CALL_FIRST',
diff --git a/pypy/jit/metainterp/test/test_ajit.py b/pypy/jit/metainterp/test/test_ajit.py
--- a/pypy/jit/metainterp/test/test_ajit.py
+++ b/pypy/jit/metainterp/test/test_ajit.py
@@ -322,6 +322,17 @@
         res = self.interp_operations(f, [42])
         assert res == ord(u"?")
 
+    def test_char_in_constant_string(self):
+        def g(string):
+            return '\x00' in string
+        def f():
+            if g('abcdef'): return -60
+            if not g('abc\x00ef'): return -61
+            return 42
+        res = self.interp_operations(f, [])
+        assert res == 42
+        self.check_operations_history({'finish': 1})   # nothing else
+
     def test_residual_call(self):
         @dont_look_inside
         def externfn(x, y):
@@ -3695,6 +3706,18 @@
         # here it works again
         self.check_operations_history(guard_class=0, record_known_class=1)
 
+    def test_generator(self):
+        def g(n):
+            yield n+1
+            yield n+2
+            yield n+3
+        def f(n):
+            gen = g(n)
+            return gen.next() * gen.next() * gen.next()
+        res = self.interp_operations(f, [10])
+        assert res == 11 * 12 * 13
+        self.check_operations_history(int_add=3, int_mul=2)
+
 
 class TestLLtype(BaseLLtypeTests, LLJitMixin):
     def test_tagged(self):
diff --git a/pypy/module/_ffi/test/test__ffi.py b/pypy/module/_ffi/test/test__ffi.py
--- a/pypy/module/_ffi/test/test__ffi.py
+++ b/pypy/module/_ffi/test/test__ffi.py
@@ -190,6 +190,7 @@
 
     def test_convert_strings_to_char_p(self):
         """
+            DLLEXPORT
             long mystrlen(char* s)
             {
                 long len = 0;
@@ -215,6 +216,7 @@
     def test_convert_unicode_to_unichar_p(self):
         """
             #include <wchar.h>
+            DLLEXPORT
             long mystrlen_u(wchar_t* s)
             {
                 long len = 0;
@@ -241,6 +243,7 @@
 
     def test_keepalive_temp_buffer(self):
         """
+            DLLEXPORT
             char* do_nothing(char* s)
             {
                 return s;
@@ -525,5 +528,7 @@
         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/_file/test/test_file.py b/pypy/module/_file/test/test_file.py
--- a/pypy/module/_file/test/test_file.py
+++ b/pypy/module/_file/test/test_file.py
@@ -265,6 +265,13 @@
 
         if option.runappdirect:
             py.test.skip("works with internals of _file impl on py.py")
+        import platform
+        if platform.system() == 'Windows':
+            # XXX This test crashes until someone implements something like
+            # XXX verify_fd from
+            # XXX http://hg.python.org/cpython/file/80ddbd822227/Modules/posixmodule.c#l434
+            # XXX and adds it to fopen
+            assert False
 
         state = [0]
         def read(fd, n=None):
diff --git a/pypy/module/bz2/interp_bz2.py b/pypy/module/bz2/interp_bz2.py
--- a/pypy/module/bz2/interp_bz2.py
+++ b/pypy/module/bz2/interp_bz2.py
@@ -328,7 +328,7 @@
     if basemode == "a":
         raise OperationError(space.w_ValueError,
                              space.wrap("cannot append to bz2 file"))
-    stream = open_path_helper(space.str_w(w_path), os_flags, False)
+    stream = open_path_helper(space.str0_w(w_path), os_flags, False)
     if reading:
         bz2stream = ReadBZ2Filter(space, stream, buffering)
         buffering = 0     # by construction, the ReadBZ2Filter acts like
diff --git a/pypy/module/cpyext/include/pythonrun.h b/pypy/module/cpyext/include/pythonrun.h
--- a/pypy/module/cpyext/include/pythonrun.h
+++ b/pypy/module/cpyext/include/pythonrun.h
@@ -13,6 +13,7 @@
 
 #define Py_FrozenFlag 0
 #define Py_VerboseFlag 0
+#define Py_DebugFlag 1
 
 typedef struct {
     int cf_flags;  /* bitmask of CO_xxx flags relevant to future */
diff --git a/pypy/module/gc/interp_gc.py b/pypy/module/gc/interp_gc.py
--- a/pypy/module/gc/interp_gc.py
+++ b/pypy/module/gc/interp_gc.py
@@ -49,7 +49,7 @@
 
 # ____________________________________________________________
 
- at unwrap_spec(filename=str)
+ at unwrap_spec(filename='str0')
 def dump_heap_stats(space, filename):
     tb = rgc._heap_stats()
     if not tb:
diff --git a/pypy/module/imp/importing.py b/pypy/module/imp/importing.py
--- a/pypy/module/imp/importing.py
+++ b/pypy/module/imp/importing.py
@@ -138,7 +138,7 @@
     ctxt_package = None
     if ctxt_w_package is not None and ctxt_w_package is not space.w_None:
         try:
-            ctxt_package = space.str_w(ctxt_w_package)
+            ctxt_package = space.str0_w(ctxt_w_package)
         except OperationError, e:
             if not e.match(space, space.w_TypeError):
                 raise
@@ -187,7 +187,7 @@
         ctxt_name = None
         if ctxt_w_name is not None:
             try:
-                ctxt_name = space.str_w(ctxt_w_name)
+                ctxt_name = space.str0_w(ctxt_w_name)
             except OperationError, e:
                 if not e.match(space, space.w_TypeError):
                     raise
@@ -230,7 +230,7 @@
     return rel_modulename, rel_level
 
 
- at unwrap_spec(name=str, level=int)
+ at unwrap_spec(name='str0', level=int)
 def importhook(space, name, w_globals=None,
                w_locals=None, w_fromlist=None, level=-1):
     modulename = name
@@ -377,8 +377,8 @@
                     fromlist_w = space.fixedview(w_all)
             for w_name in fromlist_w:
                 if try_getattr(space, w_mod, w_name) is None:
-                    load_part(space, w_path, prefix, space.str_w(w_name), w_mod,
-                              tentative=1)
+                    load_part(space, w_path, prefix, space.str0_w(w_name),
+                              w_mod, tentative=1)
         return w_mod
     else:
         return first
@@ -432,7 +432,7 @@
     def __init__(self, space):
         pass
 
-    @unwrap_spec(path=str)
+    @unwrap_spec(path='str0')
     def descr_init(self, space, path):
         if not path:
             raise OperationError(space.w_ImportError, space.wrap(
@@ -513,7 +513,7 @@
                 if w_loader:
                     return FindInfo.fromLoader(w_loader)
 
-            path = space.str_w(w_pathitem)
+            path = space.str0_w(w_pathitem)
             filepart = os.path.join(path, partname)
             if os.path.isdir(filepart) and case_ok(filepart):
                 initfile = os.path.join(filepart, '__init__')
@@ -671,7 +671,7 @@
             space.wrap("reload() argument must be module"))
 
     w_modulename = space.getattr(w_module, space.wrap("__name__"))
-    modulename = space.str_w(w_modulename)
+    modulename = space.str0_w(w_modulename)
     if not space.is_w(check_sys_modules(space, w_modulename), w_module):
         raise operationerrfmt(
             space.w_ImportError,
diff --git a/pypy/module/imp/interp_imp.py b/pypy/module/imp/interp_imp.py
--- a/pypy/module/imp/interp_imp.py
+++ b/pypy/module/imp/interp_imp.py
@@ -44,7 +44,7 @@
         return space.interp_w(W_File, w_file).stream
 
 def find_module(space, w_name, w_path=None):
-    name = space.str_w(w_name)
+    name = space.str0_w(w_name)
     if space.is_w(w_path, space.w_None):
         w_path = None
 
@@ -75,7 +75,7 @@
 def load_module(space, w_name, w_file, w_filename, w_info):
     w_suffix, w_filemode, w_modtype = space.unpackiterable(w_info)
 
-    filename = space.str_w(w_filename)
+    filename = space.str0_w(w_filename)
     filemode = space.str_w(w_filemode)
     if space.is_w(w_file, space.w_None):
         stream = None
@@ -92,7 +92,7 @@
         space, w_name, find_info, reuse=True)
 
 def load_source(space, w_modulename, w_filename, w_file=None):
-    filename = space.str_w(w_filename)
+    filename = space.str0_w(w_filename)
 
     stream = get_file(space, w_file, filename, 'U')
 
@@ -105,7 +105,7 @@
         stream.close()
     return w_mod
 
- at unwrap_spec(filename=str)
+ at unwrap_spec(filename='str0')
 def _run_compiled_module(space, w_modulename, filename, w_file, w_module):
     # the function 'imp._run_compiled_module' is a pypy-only extension
     stream = get_file(space, w_file, filename, 'rb')
@@ -119,7 +119,7 @@
     if space.is_w(w_file, space.w_None):
         stream.close()
 
- at unwrap_spec(filename=str)
+ at unwrap_spec(filename='str0')
 def load_compiled(space, w_modulename, filename, w_file=None):
     w_mod = space.wrap(Module(space, w_modulename))
     importing._prepare_module(space, w_mod, filename, None)
@@ -138,7 +138,7 @@
     return space.wrap(Module(space, w_name, add_package=False))
 
 def init_builtin(space, w_name):
-    name = space.str_w(w_name)
+    name = space.str0_w(w_name)
     if name not in space.builtin_modules:
         return
     if space.finditem(space.sys.get('modules'), w_name) is not None:
@@ -151,7 +151,7 @@
     return None
 
 def is_builtin(space, w_name):
-    name = space.str_w(w_name)
+    name = space.str0_w(w_name)
     if name not in space.builtin_modules:
         return space.wrap(0)
     if space.finditem(space.sys.get('modules'), w_name) is not None:
diff --git a/pypy/module/micronumpy/__init__.py b/pypy/module/micronumpy/__init__.py
--- a/pypy/module/micronumpy/__init__.py
+++ b/pypy/module/micronumpy/__init__.py
@@ -31,7 +31,7 @@
         'concatenate': 'interp_numarray.concatenate',
 
         'set_string_function': 'appbridge.set_string_function',
-        
+
         'count_reduce_items': 'interp_numarray.count_reduce_items',
 
         'True_': 'types.Bool.True',
@@ -111,8 +111,5 @@
         'min': 'app_numpy.min',
         'identity': 'app_numpy.identity',
         'max': 'app_numpy.max',
-        'inf': 'app_numpy.inf',
-        'e': 'app_numpy.e',
-        'pi': 'app_numpy.pi',
         'arange': 'app_numpy.arange',
     }
diff --git a/pypy/module/micronumpy/app_numpy.py b/pypy/module/micronumpy/app_numpy.py
--- a/pypy/module/micronumpy/app_numpy.py
+++ b/pypy/module/micronumpy/app_numpy.py
@@ -3,11 +3,6 @@
 import _numpypy
 
 
-inf = float("inf")
-e = math.e
-pi = math.pi
-
-
 def average(a):
     # This implements a weighted average, for now we don't implement the
     # weighting, just the average part!
@@ -59,7 +54,7 @@
     if not hasattr(a, "max"):
         a = _numpypy.array(a)
     return a.max(axis)
-    
+
 def arange(start, stop=None, step=1, dtype=None):
     '''arange([start], stop[, step], dtype=None)
     Generate values in the half-interval [start, stop).
diff --git a/pypy/module/micronumpy/interp_boxes.py b/pypy/module/micronumpy/interp_boxes.py
--- a/pypy/module/micronumpy/interp_boxes.py
+++ b/pypy/module/micronumpy/interp_boxes.py
@@ -80,7 +80,15 @@
     descr_sub = _binop_impl("subtract")
     descr_mul = _binop_impl("multiply")
     descr_div = _binop_impl("divide")
+    descr_truediv = _binop_impl("true_divide")
+    descr_mod = _binop_impl("mod")
     descr_pow = _binop_impl("power")
+    descr_lshift = _binop_impl("left_shift")
+    descr_rshift = _binop_impl("right_shift")
+    descr_and = _binop_impl("bitwise_and")
+    descr_or = _binop_impl("bitwise_or")
+    descr_xor = _binop_impl("bitwise_xor")
+
     descr_eq = _binop_impl("equal")
     descr_ne = _binop_impl("not_equal")
     descr_lt = _binop_impl("less")
@@ -91,9 +99,29 @@
     descr_radd = _binop_right_impl("add")
     descr_rsub = _binop_right_impl("subtract")
     descr_rmul = _binop_right_impl("multiply")
+    descr_rdiv = _binop_right_impl("divide")
+    descr_rmod = _binop_right_impl("mod")
+    descr_rpow = _binop_right_impl("power")
+    descr_rlshift = _binop_right_impl("left_shift")
+    descr_rrshift = _binop_right_impl("right_shift")
+    descr_rand = _binop_right_impl("bitwise_and")
+    descr_ror = _binop_right_impl("bitwise_or")
+    descr_rxor = _binop_right_impl("bitwise_xor")
 
+    descr_pos = _unaryop_impl("positive")
     descr_neg = _unaryop_impl("negative")
     descr_abs = _unaryop_impl("absolute")
+    descr_invert = _unaryop_impl("invert")
+
+    def descr_divmod(self, space, w_other):
+        w_quotient = self.descr_div(space, w_other)
+        w_remainder = self.descr_mod(space, w_other)
+        return space.newtuple([w_quotient, w_remainder])
+
+    def descr_rdivmod(self, space, w_other):
+        w_quotient = self.descr_rdiv(space, w_other)
+        w_remainder = self.descr_rmod(space, w_other)
+        return space.newtuple([w_quotient, w_remainder])
 
     def item(self, space):
         return self.get_dtype(space).itemtype.to_builtin_type(space, self)
@@ -174,11 +202,28 @@
     __sub__ = interp2app(W_GenericBox.descr_sub),
     __mul__ = interp2app(W_GenericBox.descr_mul),
     __div__ = interp2app(W_GenericBox.descr_div),
+    __truediv__ = interp2app(W_GenericBox.descr_truediv),
+    __mod__ = interp2app(W_GenericBox.descr_mod),
+    __divmod__ = interp2app(W_GenericBox.descr_divmod),
     __pow__ = interp2app(W_GenericBox.descr_pow),
+    __lshift__ = interp2app(W_GenericBox.descr_lshift),
+    __rshift__ = interp2app(W_GenericBox.descr_rshift),
+    __and__ = interp2app(W_GenericBox.descr_and),
+    __or__ = interp2app(W_GenericBox.descr_or),
+    __xor__ = interp2app(W_GenericBox.descr_xor),
 
     __radd__ = interp2app(W_GenericBox.descr_radd),
     __rsub__ = interp2app(W_GenericBox.descr_rsub),
     __rmul__ = interp2app(W_GenericBox.descr_rmul),
+    __rdiv__ = interp2app(W_GenericBox.descr_rdiv),
+    __rmod__ = interp2app(W_GenericBox.descr_rmod),
+    __rdivmod__ = interp2app(W_GenericBox.descr_rdivmod),
+    __rpow__ = interp2app(W_GenericBox.descr_rpow),
+    __rlshift__ = interp2app(W_GenericBox.descr_rlshift),
+    __rrshift__ = interp2app(W_GenericBox.descr_rrshift),
+    __rand__ = interp2app(W_GenericBox.descr_rand),
+    __ror__ = interp2app(W_GenericBox.descr_ror),
+    __rxor__ = interp2app(W_GenericBox.descr_rxor),
 
     __eq__ = interp2app(W_GenericBox.descr_eq),
     __ne__ = interp2app(W_GenericBox.descr_ne),
@@ -187,8 +232,10 @@
     __gt__ = interp2app(W_GenericBox.descr_gt),
     __ge__ = interp2app(W_GenericBox.descr_ge),
 
+    __pos__ = interp2app(W_GenericBox.descr_pos),
     __neg__ = interp2app(W_GenericBox.descr_neg),
     __abs__ = interp2app(W_GenericBox.descr_abs),
+    __invert__ = interp2app(W_GenericBox.descr_invert),
 
     tolist = interp2app(W_GenericBox.item),
 )
diff --git a/pypy/module/micronumpy/interp_numarray.py b/pypy/module/micronumpy/interp_numarray.py
--- a/pypy/module/micronumpy/interp_numarray.py
+++ b/pypy/module/micronumpy/interp_numarray.py
@@ -101,8 +101,13 @@
     descr_sub = _binop_impl("subtract")
     descr_mul = _binop_impl("multiply")
     descr_div = _binop_impl("divide")
+    descr_mod = _binop_impl("mod")
     descr_pow = _binop_impl("power")
-    descr_mod = _binop_impl("mod")
+    descr_lshift = _binop_impl("left_shift")
+    descr_rshift = _binop_impl("right_shift")
+    descr_and = _binop_impl("bitwise_and")
+    descr_or = _binop_impl("bitwise_or")
+    descr_xor = _binop_impl("bitwise_xor")
 
     descr_eq = _binop_impl("equal")
     descr_ne = _binop_impl("not_equal")
@@ -111,8 +116,10 @@
     descr_gt = _binop_impl("greater")
     descr_ge = _binop_impl("greater_equal")
 
-    descr_and = _binop_impl("bitwise_and")
-    descr_or = _binop_impl("bitwise_or")
+    def descr_divmod(self, space, w_other):
+        w_quotient = self.descr_div(space, w_other)
+        w_remainder = self.descr_mod(space, w_other)
+        return space.newtuple([w_quotient, w_remainder])
 
     def _binop_right_impl(ufunc_name):
         def impl(self, space, w_other):
@@ -127,8 +134,18 @@
     descr_rsub = _binop_right_impl("subtract")
     descr_rmul = _binop_right_impl("multiply")
     descr_rdiv = _binop_right_impl("divide")
+    descr_rmod = _binop_right_impl("mod")
     descr_rpow = _binop_right_impl("power")
-    descr_rmod = _binop_right_impl("mod")
+    descr_rlshift = _binop_right_impl("left_shift")
+    descr_rrshift = _binop_right_impl("right_shift")
+    descr_rand = _binop_right_impl("bitwise_and")
+    descr_ror = _binop_right_impl("bitwise_or")
+    descr_rxor = _binop_right_impl("bitwise_xor")
+
+    def descr_rdivmod(self, space, w_other):
+        w_quotient = self.descr_rdiv(space, w_other)
+        w_remainder = self.descr_rmod(space, w_other)
+        return space.newtuple([w_quotient, w_remainder])
 
     def _reduce_ufunc_impl(ufunc_name, promote_to_largest=False):
         def impl(self, space, w_axis=None, w_out=None):
@@ -803,7 +820,7 @@
                                self.left.create_sig(), self.right.create_sig())
 
 class ResultArray(Call2):
-    def __init__(self, child, size, shape, dtype, res=None, order='C'): 
+    def __init__(self, child, size, shape, dtype, res=None, order='C'):
         if res is None:
             res = W_NDimArray(size, shape, dtype, order)
         Call2.__init__(self, None, 'assign', shape, dtype, dtype, res, child)
@@ -831,7 +848,7 @@
             frame.next(len(self.right.shape))
         else:
             frame.cur_value = self.identity.convert_to(self.calc_dtype)
-    
+
     def create_sig(self):
         if self.name == 'logical_and':
             done_func = done_if_false
@@ -1234,21 +1251,34 @@
     __pos__ = interp2app(BaseArray.descr_pos),
     __neg__ = interp2app(BaseArray.descr_neg),
     __abs__ = interp2app(BaseArray.descr_abs),
+    __invert__ = interp2app(BaseArray.descr_invert),
     __nonzero__ = interp2app(BaseArray.descr_nonzero),
 
     __add__ = interp2app(BaseArray.descr_add),
     __sub__ = interp2app(BaseArray.descr_sub),
     __mul__ = interp2app(BaseArray.descr_mul),
     __div__ = interp2app(BaseArray.descr_div),
+    __mod__ = interp2app(BaseArray.descr_mod),
+    __divmod__ = interp2app(BaseArray.descr_divmod),
     __pow__ = interp2app(BaseArray.descr_pow),
-    __mod__ = interp2app(BaseArray.descr_mod),
+    __lshift__ = interp2app(BaseArray.descr_lshift),
+    __rshift__ = interp2app(BaseArray.descr_rshift),
+    __and__ = interp2app(BaseArray.descr_and),
+    __or__ = interp2app(BaseArray.descr_or),
+    __xor__ = interp2app(BaseArray.descr_xor),
 
     __radd__ = interp2app(BaseArray.descr_radd),
     __rsub__ = interp2app(BaseArray.descr_rsub),
     __rmul__ = interp2app(BaseArray.descr_rmul),
     __rdiv__ = interp2app(BaseArray.descr_rdiv),
+    __rmod__ = interp2app(BaseArray.descr_rmod),
+    __rdivmod__ = interp2app(BaseArray.descr_rdivmod),
     __rpow__ = interp2app(BaseArray.descr_rpow),
-    __rmod__ = interp2app(BaseArray.descr_rmod),
+    __rlshift__ = interp2app(BaseArray.descr_rlshift),
+    __rrshift__ = interp2app(BaseArray.descr_rrshift),
+    __rand__ = interp2app(BaseArray.descr_rand),
+    __ror__ = interp2app(BaseArray.descr_ror),
+    __rxor__ = interp2app(BaseArray.descr_rxor),
 
     __eq__ = interp2app(BaseArray.descr_eq),
     __ne__ = interp2app(BaseArray.descr_ne),
@@ -1257,10 +1287,6 @@
     __gt__ = interp2app(BaseArray.descr_gt),
     __ge__ = interp2app(BaseArray.descr_ge),
 
-    __and__ = interp2app(BaseArray.descr_and),
-    __or__ = interp2app(BaseArray.descr_or),
-    __invert__ = interp2app(BaseArray.descr_invert),
-
     __repr__ = interp2app(BaseArray.descr_repr),
     __str__ = interp2app(BaseArray.descr_str),
     __array_interface__ = GetSetProperty(BaseArray.descr_array_iface),
@@ -1328,6 +1354,9 @@
     def descr_iter(self):
         return self
 
+    def descr_len(self, space):
+        return space.wrap(self.size)
+
     def descr_index(self, space):
         return space.wrap(self.index)
 
@@ -1403,7 +1432,7 @@
         return signature.FlatSignature(self.base.dtype)
 
     def create_iter(self, transforms=None):
-        return ViewIterator(self.base.start, self.base.strides, 
+        return ViewIterator(self.base.start, self.base.strides,
                     self.base.backstrides,
                     self.base.shape).apply_transformations(self.base,
                                                            transforms)
@@ -1414,14 +1443,17 @@
 W_FlatIterator.typedef = TypeDef(
     'flatiter',
     __iter__ = interp2app(W_FlatIterator.descr_iter),
+    __len__ = interp2app(W_FlatIterator.descr_len),
     __getitem__ = interp2app(W_FlatIterator.descr_getitem),
     __setitem__ = interp2app(W_FlatIterator.descr_setitem),
+
     __eq__ = interp2app(BaseArray.descr_eq),
     __ne__ = interp2app(BaseArray.descr_ne),
     __lt__ = interp2app(BaseArray.descr_lt),
     __le__ = interp2app(BaseArray.descr_le),
     __gt__ = interp2app(BaseArray.descr_gt),
     __ge__ = interp2app(BaseArray.descr_ge),
+
     base = GetSetProperty(W_FlatIterator.descr_base),
     index = GetSetProperty(W_FlatIterator.descr_index),
     coords = GetSetProperty(W_FlatIterator.descr_coords),
diff --git a/pypy/module/micronumpy/interp_ufuncs.py b/pypy/module/micronumpy/interp_ufuncs.py
--- a/pypy/module/micronumpy/interp_ufuncs.py
+++ b/pypy/module/micronumpy/interp_ufuncs.py
@@ -414,14 +414,17 @@
             ("subtract", "sub", 2),
             ("multiply", "mul", 2, {"identity": 1}),
             ("bitwise_and", "bitwise_and", 2, {"identity": 1,
-                                               'int_only': True}),
+                                               "int_only": True}),
             ("bitwise_or", "bitwise_or", 2, {"identity": 0,
-                                             'int_only': True}),
+                                             "int_only": True}),
+            ("bitwise_xor", "bitwise_xor", 2, {"int_only": True}),
             ("invert", "invert", 1, {"int_only": True}),
             ("divide", "div", 2, {"promote_bools": True}),
             ("true_divide", "div", 2, {"promote_to_float": True}),
             ("mod", "mod", 2, {"promote_bools": True}),
             ("power", "pow", 2, {"promote_bools": True}),
+            ("left_shift", "lshift", 2, {"int_only": True}),
+            ("right_shift", "rshift", 2, {"int_only": True}),
 
             ("equal", "eq", 2, {"comparison_func": True}),
             ("not_equal", "ne", 2, {"comparison_func": True}),
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
@@ -401,3 +401,32 @@
         else:
             assert issubclass(int64, int)
             assert int_ is int64
+
+    def test_operators(self):
+        from operator import truediv
+        from _numpypy import float64, int_, True_, False_
+
+        assert 5 / int_(2) == int_(2)
+        assert truediv(int_(3), int_(2)) == float64(1.5)
+        assert int_(8) % int_(3) == int_(2)
+        assert 8 % int_(3) == int_(2)
+        assert divmod(int_(8), int_(3)) == (int_(2), int_(2))
+        assert divmod(8, int_(3)) == (int_(2), int_(2))
+        assert 2 ** int_(3) == int_(8)
+        assert int_(3) << int_(2) == int_(12)
+        assert 3 << int_(2) == int_(12)
+        assert int_(8) >> int_(2) == int_(2)
+        assert 8 >> int_(2) == int_(2)
+        assert int_(3) & int_(1) == int_(1)
+        assert 2 & int_(3) == int_(2)
+        assert int_(2) | int_(1) == int_(3)
+        assert 2 | int_(1) == int_(3)
+        assert int_(3) ^ int_(5) == int_(6)
+        assert True_ ^ False_ is True_
+        assert 5 ^ int_(3) == int_(6)
+
+        assert +int_(3) == int_(3)
+        assert ~int_(3) == int_(-4)
+
+        raises(TypeError, lambda: float64(3) & 1)
+
diff --git a/pypy/module/micronumpy/test/test_module.py b/pypy/module/micronumpy/test/test_module.py
--- a/pypy/module/micronumpy/test/test_module.py
+++ b/pypy/module/micronumpy/test/test_module.py
@@ -21,13 +21,3 @@
         from _numpypy import array, max
         assert max(range(10)) == 9
         assert max(array(range(10))) == 9
-
-    def test_constants(self):
-        import math
-        from _numpypy import inf, e, pi
-        assert type(inf) is float
-        assert inf == float("inf")
-        assert e == math.e
-        assert type(e) is float
-        assert pi == math.pi
-        assert type(pi) is float
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
@@ -579,7 +579,7 @@
 
     def test_div(self):
         from math import isnan
-        from _numpypy import array, dtype, inf
+        from _numpypy import array, dtype
 
         a = array(range(1, 6))
         b = a / a
@@ -600,15 +600,15 @@
         a = array([-1.0, 0.0, 1.0])
         b = array([0.0, 0.0, 0.0])
         c = a / b
-        assert c[0] == -inf
+        assert c[0] == float('-inf')
         assert isnan(c[1])
-        assert c[2] == inf
+        assert c[2] == float('inf')
 
         b = array([-0.0, -0.0, -0.0])
         c = a / b
-        assert c[0] == inf
+        assert c[0] == float('inf')
         assert isnan(c[1])
-        assert c[2] == -inf
+        assert c[2] == float('-inf')
 
     def test_div_other(self):
         from _numpypy import array
@@ -625,6 +625,52 @@
         for i in range(5):
             assert b[i] == i / 5.0
 
+    def test_divmod(self):
+        from _numpypy import arange
+
+        a, b = divmod(arange(10), 3)
+        assert (a == [0, 0, 0, 1, 1, 1, 2, 2, 2, 3]).all()
+        assert (b == [0, 1, 2, 0, 1, 2, 0, 1, 2, 0]).all()
+
+    def test_rdivmod(self):
+        from _numpypy import arange
+
+        a, b = divmod(3, arange(1, 5))
+        assert (a == [3, 1, 1, 0]).all()
+        assert (b == [0, 1, 0, 3]).all()
+
+    def test_lshift(self):
+        from _numpypy import array
+
+        a = array([0, 1, 2, 3])
+        assert (a << 2 == [0, 4, 8, 12]).all()
+        a = array([True, False])
+        assert (a << 2 == [4, 0]).all()
+        a = array([1.0])
+        raises(TypeError, lambda: a << 2)
+
+    def test_rlshift(self):
+        from _numpypy import arange
+
+        a = arange(3)
+        assert (2 << a == [2, 4, 8]).all()
+
+    def test_rshift(self):
+        from _numpypy import arange, array
+
+        a = arange(10)
+        assert (a >> 2 == [0, 0, 0, 0, 1, 1, 1, 1, 2, 2]).all()
+        a = array([True, False])
+        assert (a >> 1 == [0, 0]).all()
+        a = arange(3, dtype=float)
+        raises(TypeError, lambda: a >> 1)
+
+    def test_rrshift(self):
+        from _numpypy import arange
+
+        a = arange(5)
+        assert (2 >> a == [2, 1, 0, 0, 0]).all()
+
     def test_pow(self):
         from _numpypy import array
         a = array(range(5), float)
@@ -678,6 +724,30 @@
         for i in range(5):
             assert b[i] == i % 2
 
+    def test_rand(self):
+        from _numpypy import arange
+
+        a = arange(5)
+        assert (3 & a == [0, 1, 2, 3, 0]).all()
+
+    def test_ror(self):
+        from _numpypy import arange
+
+        a = arange(5)
+        assert (3 | a == [3, 3, 3, 3, 7]).all()
+
+    def test_xor(self):
+        from _numpypy import arange
+
+        a = arange(5)
+        assert (a ^ 3 == [3, 2, 1, 0, 7]).all()
+
+    def test_rxor(self):
+        from _numpypy import arange
+
+        a = arange(5)
+        assert (3 ^ a == [3, 2, 1, 0, 7]).all()
+
     def test_pos(self):
         from _numpypy import array
         a = array([1., -2., 3., -4., -5.])
@@ -1512,24 +1582,26 @@
     def test_flatiter_view(self):
         from _numpypy import arange
         a = arange(10).reshape(5, 2)
-        #no == yet.
-        # a[::2].flat == [0, 1, 4, 5, 8, 9]
-        isequal = True
-        for y,z in zip(a[::2].flat, [0, 1, 4, 5, 8, 9]):
-            if y != z:
-                isequal = False
-        assert isequal == True
+        assert (a[::2].flat == [0, 1, 4, 5, 8, 9]).all()
 
     def test_flatiter_transpose(self):
         from _numpypy import arange
-        a = arange(10).reshape(2,5).T
+        a = arange(10).reshape(2, 5).T
         b = a.flat
         assert (b[:5] == [0, 5, 1, 6, 2]).all()
         b.next()
         b.next()
         b.next()
         assert b.index == 3
-        assert b.coords == (1,1)
+        assert b.coords == (1, 1)
+
+    def test_flatiter_len(self):
+        from _numpypy import arange
+
+        assert len(arange(10).flat) == 10
+        assert len(arange(10).reshape(2, 5).flat) == 10
+        assert len(arange(10)[:2].flat) == 2
+        assert len((arange(2) + arange(2)).flat) == 2
 
     def test_slice_copy(self):
         from _numpypy import zeros
diff --git a/pypy/module/micronumpy/test/test_ufuncs.py b/pypy/module/micronumpy/test/test_ufuncs.py
--- a/pypy/module/micronumpy/test/test_ufuncs.py
+++ b/pypy/module/micronumpy/test/test_ufuncs.py
@@ -312,9 +312,9 @@
 
     def test_arcsinh(self):
         import math
-        from _numpypy import arcsinh, inf
+        from _numpypy import arcsinh
 
-        for v in [inf, -inf, 1.0, math.e]:
+        for v in [float('inf'), float('-inf'), 1.0, math.e]:
             assert math.asinh(v) == arcsinh(v)
         assert math.isnan(arcsinh(float("nan")))
 
@@ -367,7 +367,7 @@
         b = add.reduce(a, 0, keepdims=True)
         assert b.shape == (1, 4)
         assert (add.reduce(a, 0, keepdims=True) == [12, 15, 18, 21]).all()
-        
+
 
     def test_bitwise(self):
         from _numpypy import bitwise_and, bitwise_or, arange, array
@@ -416,7 +416,7 @@
         assert count_reduce_items(a) == 24
         assert count_reduce_items(a, 1) == 3
         assert count_reduce_items(a, (1, 2)) == 3 * 4
-        
+
     def test_true_divide(self):
         from _numpypy import arange, array, true_divide
         assert (true_divide(arange(3), array([2, 2, 2])) == array([0, 0.5, 1])).all()
diff --git a/pypy/module/micronumpy/test/test_zjit.py b/pypy/module/micronumpy/test/test_zjit.py
--- a/pypy/module/micronumpy/test/test_zjit.py
+++ b/pypy/module/micronumpy/test/test_zjit.py
@@ -199,7 +199,7 @@
         assert result == 1
         self.check_simple_loop({"getinteriorfield_raw": 2, "float_add": 1,
                                 "int_and": 1, "int_add": 1,
-                                'convert_float_to_int': 1,
+                                'cast_float_to_int': 1,
                                 "int_ge": 1, "jump": 1,
                                 "guard_false": 2, 'arraylen_gc': 1})
 
diff --git a/pypy/module/micronumpy/types.py b/pypy/module/micronumpy/types.py
--- a/pypy/module/micronumpy/types.py
+++ b/pypy/module/micronumpy/types.py
@@ -59,10 +59,6 @@
 class BaseType(object):
     def _unimplemented_ufunc(self, *args):
         raise NotImplementedError
-    # add = sub = mul = div = mod = pow = eq = ne = lt = le = gt = ge = max = \
-    #     min = copysign = pos = neg = abs = sign = reciprocal = fabs = floor = \
-    #     exp = sin = cos = tan = arcsin = arccos = arctan = arcsinh = \
-    #     arctanh = _unimplemented_ufunc
 
 class Primitive(object):
     _mixin_ = True
@@ -253,6 +249,10 @@
     def bitwise_or(self, v1, v2):
         return v1 | v2
 
+    @simple_binary_op
+    def bitwise_xor(self, v1, v2):
+        return v1 ^ v2
+
     @simple_unary_op
     def invert(self, v):
         return ~v
@@ -295,6 +295,14 @@
             v1 *= v1
         return res
 
+    @simple_binary_op
+    def lshift(self, v1, v2):
+        return v1 << v2
+
+    @simple_binary_op
+    def rshift(self, v1, v2):
+        return v1 >> v2
+
     @simple_unary_op
     def sign(self, v):
         if v > 0:
@@ -313,6 +321,10 @@
     def bitwise_or(self, v1, v2):
         return v1 | v2
 
+    @simple_binary_op
+    def bitwise_xor(self, v1, v2):
+        return v1 ^ v2
+
     @simple_unary_op
     def invert(self, v):
         return ~v
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
@@ -37,7 +37,7 @@
     if space.isinstance_w(w_obj, space.w_unicode):
         w_obj = space.call_method(w_obj, 'encode',
                                   getfilesystemencoding(space))
-    return space.str_w(w_obj)
+    return space.str0_w(w_obj)
 
 class FileEncoder(object):
     def __init__(self, space, w_obj):
@@ -48,7 +48,7 @@
         return fsencode_w(self.space, self.w_obj)
 
     def as_unicode(self):
-        return self.space.unicode_w(self.w_obj)
+        return self.space.unicode0_w(self.w_obj)
 
 class FileDecoder(object):
     def __init__(self, space, w_obj):
@@ -56,13 +56,13 @@
         self.w_obj = w_obj
 
     def as_bytes(self):
-        return self.space.str_w(self.w_obj)
+        return self.space.str0_w(self.w_obj)
 
     def as_unicode(self):
         space = self.space
         w_unicode = space.call_method(self.w_obj, 'decode',
                                       getfilesystemencoding(space))
-        return space.unicode_w(w_unicode)
+        return space.unicode0_w(w_unicode)
 
 @specialize.memo()
 def dispatch_filename(func, tag=0):
@@ -71,7 +71,7 @@
             fname = FileEncoder(space, w_fname)
             return func(fname, *args)
         else:
-            fname = space.str_w(w_fname)
+            fname = space.str0_w(w_fname)
             return func(fname, *args)
     return dispatch
 
@@ -369,7 +369,7 @@
                                space.wrap(times[3]),
                                space.wrap(times[4])])
 
- at unwrap_spec(cmd=str)
+ at unwrap_spec(cmd='str0')
 def system(space, cmd):
     """Execute the command (a string) in a subshell."""
     try:
@@ -401,7 +401,7 @@
             fullpath = rposix._getfullpathname(path)
             w_fullpath = space.wrap(fullpath)
         else:
-            path = space.str_w(w_path)
+            path = space.str0_w(w_path)
             fullpath = rposix._getfullpathname(path)
             w_fullpath = space.wrap(fullpath)
     except OSError, e:
@@ -512,7 +512,7 @@
     for key, value in os.environ.items():
         space.setitem(w_env, space.wrap(key), space.wrap(value))
 
- at unwrap_spec(name=str, value=str)
+ at unwrap_spec(name='str0', value='str0')
 def putenv(space, name, value):
     """Change or add an environment variable."""
     try:
@@ -520,7 +520,7 @@
     except OSError, e:
         raise wrap_oserror(space, e)
 
- at unwrap_spec(name=str)
+ at unwrap_spec(name='str0')
 def unsetenv(space, name):
     """Delete an environment variable."""
     try:
@@ -543,12 +543,18 @@
             dirname = FileEncoder(space, w_dirname)
             result = rposix.listdir(dirname)
             w_fs_encoding = getfilesystemencoding(space)
-            result_w = [
-                space.call_method(space.wrap(s), "decode", w_fs_encoding)
-                for s in result
-            ]
+            len_result = len(result)
+            result_w = [None] * len_result
+            for i in range(len_result):
+                w_bytes = space.wrap(result[i])
+                try:
+                    result_w[i] = space.call_method(w_bytes,
+                                                    "decode", w_fs_encoding)
+                except OperationError, e:
+                    # fall back to the original byte string
+                    result_w[i] = w_bytes
         else:
-            dirname = space.str_w(w_dirname)
+            dirname = space.str0_w(w_dirname)
             result = rposix.listdir(dirname)
             result_w = [space.wrap(s) for s in result]
     except OSError, e:
@@ -635,7 +641,7 @@
     import signal
     os.kill(os.getpid(), signal.SIGABRT)
 
- at unwrap_spec(src=str, dst=str)
+ at unwrap_spec(src='str0', dst='str0')
 def link(space, src, dst):
     "Create a hard link to a file."
     try:
@@ -650,7 +656,7 @@
     except OSError, e:
         raise wrap_oserror(space, e)
 
- at unwrap_spec(path=str)
+ at unwrap_spec(path='str0')
 def readlink(space, path):
     "Return a string representing the path to which the symbolic link points."
     try:
@@ -765,7 +771,7 @@
     w_keys = space.call_method(w_env, 'keys')
     for w_key in space.unpackiterable(w_keys):
         w_value = space.getitem(w_env, w_key)
-        env[space.str_w(w_key)] = space.str_w(w_value)
+        env[space.str0_w(w_key)] = space.str0_w(w_value)
     return env
 
 def execve(space, w_command, w_args, w_env):
@@ -785,18 +791,18 @@
     except OSError, e:
         raise wrap_oserror(space, e)
 
- at unwrap_spec(mode=int, path=str)
+ at unwrap_spec(mode=int, path='str0')
 def spawnv(space, mode, path, w_args):
-    args = [space.str_w(w_arg) for w_arg in space.unpackiterable(w_args)]
+    args = [space.str0_w(w_arg) for w_arg in space.unpackiterable(w_args)]
     try:
         ret = os.spawnv(mode, path, args)
     except OSError, e:
         raise wrap_oserror(space, e)
     return space.wrap(ret)
 
- at unwrap_spec(mode=int, path=str)
+ at unwrap_spec(mode=int, path='str0')
 def spawnve(space, mode, path, w_args, w_env):
-    args = [space.str_w(w_arg) for w_arg in space.unpackiterable(w_args)]
+    args = [space.str0_w(w_arg) for w_arg in space.unpackiterable(w_args)]
     env = _env2interp(space, w_env)
     try:
         ret = os.spawnve(mode, path, args, env)
@@ -914,7 +920,7 @@
         raise wrap_oserror(space, e)
     return space.w_None
 
- at unwrap_spec(path=str)
+ at unwrap_spec(path='str0')
 def chroot(space, path):
     """ chroot(path)
 
@@ -1103,7 +1109,7 @@
     except OSError, e:
         raise wrap_oserror(space, e)
 
- at unwrap_spec(path=str, uid=c_uid_t, gid=c_gid_t)
+ at unwrap_spec(path='str0', uid=c_uid_t, gid=c_gid_t)
 def chown(space, path, uid, gid):
     check_uid_range(space, uid)
     check_uid_range(space, gid)
@@ -1113,7 +1119,7 @@
         raise wrap_oserror(space, e, path)
     return space.w_None
 
- at unwrap_spec(path=str, uid=c_uid_t, gid=c_gid_t)
+ at unwrap_spec(path='str0', uid=c_uid_t, gid=c_gid_t)
 def lchown(space, path, uid, gid):
     check_uid_range(space, uid)
     check_uid_range(space, gid)
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
@@ -29,6 +29,7 @@
     mod.pdir = pdir
     unicode_dir = udir.ensure('fi\xc5\x9fier.txt', dir=True)
     unicode_dir.join('somefile').write('who cares?')
+    unicode_dir.join('caf\xe9').write('who knows?')
     mod.unicode_dir = unicode_dir
 
     # in applevel tests, os.stat uses the CPython os.stat.
@@ -308,14 +309,22 @@
                           'file2']
 
     def test_listdir_unicode(self):
+        import sys
         unicode_dir = self.unicode_dir
         if unicode_dir is None:
             skip("encoding not good enough")
         posix = self.posix
         result = posix.listdir(unicode_dir)
-        result.sort()
-        assert result == [u'somefile']
-        assert type(result[0]) is unicode
+        typed_result = [(type(x), x) for x in result]
+        assert (unicode, u'somefile') in typed_result
+        try:
+            u = "caf\xe9".decode(sys.getfilesystemencoding())
+        except UnicodeDecodeError:
+            # Could not decode, listdir returned the byte string
+            assert (str, "caf\xe9") in typed_result
+        else:
+            assert (unicode, u) in typed_result
+
 
     def test_access(self):
         pdir = self.pdir + '/file1'
diff --git a/pypy/module/posix/test/test_ztranslation.py b/pypy/module/posix/test/test_ztranslation.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/posix/test/test_ztranslation.py
@@ -0,0 +1,4 @@
+from pypy.objspace.fake.checkmodule import checkmodule
+
+def test_posix_translates():
+    checkmodule('posix')
\ No newline at end of file
diff --git a/pypy/module/pypyjit/test_pypy_c/test_call.py b/pypy/module/pypyjit/test_pypy_c/test_call.py
--- a/pypy/module/pypyjit/test_pypy_c/test_call.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_call.py
@@ -27,6 +27,7 @@
             ...
             p53 = call_assembler(..., descr=...)
             guard_not_forced(descr=...)
+            keepalive(...)
             guard_no_exception(descr=...)
             ...
         """)
diff --git a/pypy/module/sys/state.py b/pypy/module/sys/state.py
--- a/pypy/module/sys/state.py
+++ b/pypy/module/sys/state.py
@@ -74,7 +74,7 @@
     #
     return importlist
 
- at unwrap_spec(srcdir=str)
+ at unwrap_spec(srcdir='str0')
 def pypy_initial_path(space, srcdir):
     try:
         path = getinitialpath(get(space), srcdir)
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,7 @@
 from pypy.interpreter import gateway
 
 #XXX # the release serial 42 is not in range(16)
-CPYTHON_VERSION            = (2, 7, 1, "final", 42)   #XXX # sync patchlevel.h
+CPYTHON_VERSION            = (2, 7, 2, "final", 42)   #XXX # sync patchlevel.h
 CPYTHON_API_VERSION        = 1013   #XXX # sync with include/modsupport.h
 
 PYPY_VERSION               = (1, 8, 1, "dev", 0)    #XXX # sync patchlevel.h
diff --git a/pypy/module/test_lib_pypy/numpypy/test_numpy.py b/pypy/module/test_lib_pypy/numpypy/test_numpy.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/test_lib_pypy/numpypy/test_numpy.py
@@ -0,0 +1,13 @@
+from pypy.conftest import gettestobjspace
+
+class AppTestNumpy:
+    def setup_class(cls):
+        cls.space = gettestobjspace(usemodules=['micronumpy'])
+
+    def test_imports(self):
+        try:
+            import numpy   # fails if 'numpypy' was not imported so far
+        except ImportError:
+            pass
+        import numpypy
+        import numpy     # works after 'numpypy' has been imported
diff --git a/pypy/module/zipimport/interp_zipimport.py b/pypy/module/zipimport/interp_zipimport.py
--- a/pypy/module/zipimport/interp_zipimport.py
+++ b/pypy/module/zipimport/interp_zipimport.py
@@ -123,7 +123,9 @@
         self.prefix = prefix
 
     def getprefix(self, space):
-        return space.wrap(self.prefix)
+        if ZIPSEP == os.path.sep:
+            return space.wrap(self.prefix)
+        return space.wrap(self.prefix.replace(ZIPSEP, os.path.sep))    
 
     def _find_relative_path(self, filename):
         if filename.startswith(self.filename):
@@ -342,7 +344,7 @@
         space = self.space
         return space.wrap(self.filename)
 
- at unwrap_spec(name=str)
+ at unwrap_spec(name='str0')
 def descr_new_zipimporter(space, w_type, name):
     w = space.wrap
     ok = False
@@ -381,7 +383,7 @@
     prefix = name[len(filename):]
     if prefix.startswith(os.path.sep) or prefix.startswith(ZIPSEP):
         prefix = prefix[1:]
-    if prefix and not prefix.endswith(ZIPSEP):
+    if prefix and not prefix.endswith(ZIPSEP) and not prefix.endswith(os.path.sep):
         prefix += ZIPSEP
     w_result = space.wrap(W_ZipImporter(space, name, filename, zip_file, prefix))
     zip_cache.set(filename, w_result)
diff --git a/pypy/module/zipimport/test/test_undocumented.py b/pypy/module/zipimport/test/test_undocumented.py
--- a/pypy/module/zipimport/test/test_undocumented.py
+++ b/pypy/module/zipimport/test/test_undocumented.py
@@ -119,7 +119,7 @@
             zip_importer = zipimport.zipimporter(path)
             assert isinstance(zip_importer, zipimport.zipimporter)
             assert zip_importer.archive == zip_path
-            assert zip_importer.prefix == prefix
+            assert zip_importer.prefix == prefix.replace('/', os.path.sep)
             assert zip_path in zipimport._zip_directory_cache
         finally:
             self.cleanup_zipfile(self.created_paths)
diff --git a/pypy/module/zipimport/test/test_zipimport.py b/pypy/module/zipimport/test/test_zipimport.py
--- a/pypy/module/zipimport/test/test_zipimport.py
+++ b/pypy/module/zipimport/test/test_zipimport.py
@@ -15,7 +15,7 @@
     cpy's regression tests
     """
     compression = ZIP_STORED
-    pathsep = '/'
+    pathsep = os.path.sep
     
     def make_pyc(cls, space, co, mtime):
         data = marshal.dumps(co)
@@ -129,7 +129,7 @@
         self.writefile('sub/__init__.py', '')
         self.writefile('sub/yy.py', '')
         from zipimport import _zip_directory_cache, zipimporter
-        sub_importer = zipimporter(self.zipfile + '/sub')
+        sub_importer = zipimporter(self.zipfile + os.path.sep + 'sub')
         main_importer = zipimporter(self.zipfile)
 
         assert main_importer is not sub_importer
diff --git a/pypy/rlib/ropenssl.py b/pypy/rlib/ropenssl.py
--- a/pypy/rlib/ropenssl.py
+++ b/pypy/rlib/ropenssl.py
@@ -54,6 +54,7 @@
 
 ASN1_STRING = lltype.Ptr(lltype.ForwardReference())
 ASN1_ITEM = rffi.COpaquePtr('ASN1_ITEM')
+ASN1_ITEM_EXP = lltype.Ptr(lltype.FuncType([], ASN1_ITEM))
 X509_NAME = rffi.COpaquePtr('X509_NAME')
 
 class CConfig:
@@ -101,12 +102,11 @@
     X509_extension_st = rffi_platform.Struct(
         'struct X509_extension_st',
         [('value', ASN1_STRING)])
-    ASN1_ITEM_EXP = lltype.FuncType([], ASN1_ITEM)
     X509V3_EXT_D2I = lltype.FuncType([rffi.VOIDP, rffi.CCHARPP, rffi.LONG], 
                                      rffi.VOIDP)
     v3_ext_method = rffi_platform.Struct(
         'struct v3_ext_method',
-        [('it', lltype.Ptr(ASN1_ITEM_EXP)),
+        [('it', ASN1_ITEM_EXP),
          ('d2i', lltype.Ptr(X509V3_EXT_D2I))])
     GENERAL_NAME_st = rffi_platform.Struct(
         'struct GENERAL_NAME_st',
@@ -118,6 +118,8 @@
          ('block_size', rffi.INT)])
     EVP_MD_SIZE = rffi_platform.SizeOf('EVP_MD')
     EVP_MD_CTX_SIZE = rffi_platform.SizeOf('EVP_MD_CTX')
+    OPENSSL_EXPORT_VAR_AS_FUNCTION = rffi_platform.Defined(
+                                             "OPENSSL_EXPORT_VAR_AS_FUNCTION")
 
 
 for k, v in rffi_platform.configure(CConfig).items():
@@ -224,7 +226,10 @@
 ssl_external('i2a_ASN1_INTEGER', [BIO, ASN1_INTEGER], rffi.INT)
 ssl_external('ASN1_item_d2i', 
              [rffi.VOIDP, rffi.CCHARPP, rffi.LONG, ASN1_ITEM], rffi.VOIDP)
-ssl_external('ASN1_ITEM_ptr', [rffi.VOIDP], ASN1_ITEM, macro=True)
+if OPENSSL_EXPORT_VAR_AS_FUNCTION:             
+    ssl_external('ASN1_ITEM_ptr', [ASN1_ITEM_EXP], ASN1_ITEM, macro=True)
+else:    
+    ssl_external('ASN1_ITEM_ptr', [rffi.VOIDP], ASN1_ITEM, macro=True)
 
 ssl_external('sk_GENERAL_NAME_num', [GENERAL_NAMES], rffi.INT,
              macro=True)
diff --git a/pypy/rlib/rstring.py b/pypy/rlib/rstring.py
--- a/pypy/rlib/rstring.py
+++ b/pypy/rlib/rstring.py
@@ -205,3 +205,45 @@
         assert p.const is None
         return SomeUnicodeBuilder(can_be_None=True)
 
+#___________________________________________________________________
+# Support functions for SomeString.no_nul
+
+def assert_str0(fname):
+    assert '\x00' not in fname, "NUL byte in string"
+    return fname
+
+class Entry(ExtRegistryEntry):
+    _about_ = assert_str0
+
+    def compute_result_annotation(self, s_obj):
+        if s_None.contains(s_obj):
+            return s_obj
+        assert isinstance(s_obj, (SomeString, SomeUnicodeString))
+        if s_obj.no_nul:
+            return s_obj
+        new_s_obj = SomeObject.__new__(s_obj.__class__)
+        new_s_obj.__dict__ = s_obj.__dict__.copy()
+        new_s_obj.no_nul = True
+        return new_s_obj
+
+    def specialize_call(self, hop):
+        hop.exception_cannot_occur()
+        return hop.inputarg(hop.args_r[0], arg=0)
+
+def check_str0(fname):
+    """A 'probe' to trigger a failure at translation time, if the
+    string was not proved to not contain NUL characters."""
+    assert '\x00' not in fname, "NUL byte in string"
+
+class Entry(ExtRegistryEntry):
+    _about_ = check_str0
+
+    def compute_result_annotation(self, s_obj):
+        if not isinstance(s_obj, (SomeString, SomeUnicodeString)):
+            return s_obj
+        if not s_obj.no_nul:
+            raise ValueError("Value is not no_nul")
+
+    def specialize_call(self, hop):
+        pass
+
diff --git a/pypy/rlib/test/test_rmarshal.py b/pypy/rlib/test/test_rmarshal.py
--- a/pypy/rlib/test/test_rmarshal.py
+++ b/pypy/rlib/test/test_rmarshal.py
@@ -169,7 +169,7 @@
         assert st2.st_mode == st.st_mode
         assert st2[9] == st[9]
         return buf
-    fn = compile(f, [str])
+    fn = compile(f, [annmodel.s_Str0])
     res = fn('.')
     st = os.stat('.')
     sttuple = marshal.loads(res)
diff --git a/pypy/rpython/extfunc.py b/pypy/rpython/extfunc.py
--- a/pypy/rpython/extfunc.py
+++ b/pypy/rpython/extfunc.py
@@ -2,7 +2,7 @@
 from pypy.rpython.extregistry import ExtRegistryEntry
 from pypy.rpython.lltypesystem.lltype import typeOf
 from pypy.objspace.flow.model import Constant
-from pypy.annotation.model import unionof
+from pypy.annotation import model as annmodel
 from pypy.annotation.signature import annotation
 
 import py, sys
@@ -138,7 +138,6 @@
     # we defer a bit annotation here
 
     def compute_result_annotation(self):
-        from pypy.annotation import model as annmodel
         return annmodel.SomeGenericCallable([annotation(i, self.bookkeeper)
                                              for i in self.instance.args],
                            annotation(self.instance.result, self.bookkeeper))
@@ -152,8 +151,9 @@
         signature_args = [annotation(arg, None) for arg in args]
         assert len(args_s) == len(signature_args),\
                "Argument number mismatch"
+
         for i, expected in enumerate(signature_args):
-            arg = unionof(args_s[i], expected)
+            arg = annmodel.unionof(args_s[i], expected)
             if not expected.contains(arg):
                 name = getattr(self, 'name', None)
                 if not name:
diff --git a/pypy/rpython/extfuncregistry.py b/pypy/rpython/extfuncregistry.py
--- a/pypy/rpython/extfuncregistry.py
+++ b/pypy/rpython/extfuncregistry.py
@@ -85,7 +85,8 @@
 # llinterpreter
 
 path_functions = [
-    ('join',     [str, str], str),
+    ('join',     [ll_os.str0, ll_os.str0], ll_os.str0),
+    ('dirname',  [ll_os.str0], ll_os.str0),
     ]
 
 for name, args, res in path_functions:
diff --git a/pypy/rpython/lltypesystem/ll2ctypes.py b/pypy/rpython/lltypesystem/ll2ctypes.py
--- a/pypy/rpython/lltypesystem/ll2ctypes.py
+++ b/pypy/rpython/lltypesystem/ll2ctypes.py
@@ -1036,13 +1036,8 @@
     libraries = eci.testonly_libraries + eci.libraries + eci.frameworks
 
     FUNCTYPE = lltype.typeOf(funcptr).TO
-    if not libraries:
-        cfunc = get_on_lib(standard_c_lib, funcname)
-        # XXX magic: on Windows try to load the function from 'kernel32' too
-        if cfunc is None and hasattr(ctypes, 'windll'):
-            cfunc = get_on_lib(ctypes.windll.kernel32, funcname)
-    else:
-        cfunc = None
+    cfunc = None
+    if libraries:
         not_found = []
         for libname in libraries:
             libpath = None
@@ -1075,6 +1070,12 @@
                 not_found.append(libname)
 
     if cfunc is None:
+        cfunc = get_on_lib(standard_c_lib, funcname)
+        # XXX magic: on Windows try to load the function from 'kernel32' too
+        if cfunc is None and hasattr(ctypes, 'windll'):
+            cfunc = get_on_lib(ctypes.windll.kernel32, funcname)
+
+    if cfunc is None:
         # function name not found in any of the libraries
         if not libraries:
             place = 'the standard C library (missing libraries=...?)'
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
@@ -15,7 +15,7 @@
 from pypy.translator.tool.cbuild import ExternalCompilationInfo
 from pypy.rpython.annlowlevel import llhelper
 from pypy.rlib.objectmodel import we_are_translated
-from pypy.rlib.rstring import StringBuilder, UnicodeBuilder
+from pypy.rlib.rstring import StringBuilder, UnicodeBuilder, assert_str0
 from pypy.rlib import jit
 from pypy.rpython.lltypesystem import llmemory
 import os, sys
@@ -698,7 +698,7 @@
         while cp[i] != lastchar:
             b.append(cp[i])
             i += 1
-        return b.build()
+        return assert_str0(b.build())
 
     # str -> char*
     # Can't inline this because of the raw address manipulation.
@@ -804,7 +804,7 @@
         while i < maxlen and cp[i] != lastchar:
             b.append(cp[i])
             i += 1
-        return b.build()
+        return assert_str0(b.build())
 
     # char* and size -> str (which can contain null bytes)
     def charpsize2str(cp, size):
@@ -842,6 +842,7 @@
         array[i] = str2charp(l[i])
     array[len(l)] = lltype.nullptr(CCHARP.TO)
     return array
+liststr2charpp._annenforceargs_ = [[annmodel.s_Str0]]  # List of strings
 
 def free_charpp(ref):
     """ frees list of char**, NULL terminated
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
@@ -31,6 +31,10 @@
 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__
 
@@ -39,12 +43,15 @@
     arglist = ['arg%d' % (i,) for i in range(len(signature))]
     transformed_arglist = arglist[:]
     for i, arg in enumerate(signature):
-        if arg is unicode:
+        if arg in (unicode, unicode0):
             transformed_arglist[i] = transformed_arglist[i] + '.as_unicode()'
 
     args = ', '.join(arglist)
     transformed_args = ', '.join(transformed_arglist)
-    main_arg = 'arg%d' % (signature.index(unicode),)
+    try:
+        main_arg = 'arg%d' % (signature.index(unicode0),)
+    except ValueError:
+        main_arg = 'arg%d' % (signature.index(unicode),)
 
     source = py.code.Source("""
     def %(func_name)s(%(args)s):
@@ -60,7 +67,7 @@
     exec source.compile() in miniglobals
     new_func = miniglobals[func_name]
     specialized_args = [i for i in range(len(signature))
-                        if signature[i] in (unicode, None)]
+                        if signature[i] in (unicode, unicode0, None)]
     new_func = specialize.argtype(*specialized_args)(new_func)
 
     # Monkeypatch the function in pypy.rlib.rposix
@@ -68,6 +75,7 @@
 
 class StringTraits:
     str = str
+    str0 = str0
     CHAR = rffi.CHAR
     CCHARP = rffi.CCHARP
     charp2str = staticmethod(rffi.charp2str)
@@ -85,6 +93,7 @@
 
 class UnicodeTraits:
     str = unicode
+    str0 = unicode0
     CHAR = rffi.WCHAR_T
     CCHARP = rffi.CWCHARP
     charp2str = staticmethod(rffi.wcharp2unicode)
@@ -301,7 +310,7 @@
             rffi.free_charpp(l_args)
             raise OSError(rposix.get_errno(), "execv failed")
 
-        return extdef([str, [str]], s_ImpossibleValue, llimpl=execv_llimpl,
+        return extdef([str0, [str0]], s_ImpossibleValue, llimpl=execv_llimpl,
                       export_name="ll_os.ll_os_execv")
 
 
@@ -319,7 +328,8 @@
             # appropriate
             envstrs = []
             for item in env.iteritems():
-                envstrs.append("%s=%s" % item)
+                envstr = "%s=%s" % item
+                envstrs.append(envstr)
 
             l_args = rffi.liststr2charpp(args)
             l_env = rffi.liststr2charpp(envstrs)
@@ -332,7 +342,7 @@
             raise OSError(rposix.get_errno(), "execve failed")
 
         return extdef(
-            [str, [str], {str: str}],
+            [str0, [str0], {str0: str0}],
             s_ImpossibleValue,
             llimpl=execve_llimpl,
             export_name="ll_os.ll_os_execve")
@@ -353,7 +363,7 @@
                 raise OSError(rposix.get_errno(), "os_spawnv failed")
             return rffi.cast(lltype.Signed, childpid)
 
-        return extdef([int, str, [str]], int, llimpl=spawnv_llimpl,
+        return extdef([int, str0, [str0]], int, llimpl=spawnv_llimpl,
                       export_name="ll_os.ll_os_spawnv")
 
     @registering_if(os, 'spawnve')
@@ -378,7 +388,7 @@
                 raise OSError(rposix.get_errno(), "os_spawnve failed")
             return rffi.cast(lltype.Signed, childpid)
 
-        return extdef([int, str, [str], {str: str}], int,
+        return extdef([int, str0, [str0], {str0: str0}], int,
                       llimpl=spawnve_llimpl,
                       export_name="ll_os.ll_os_spawnve")
 
@@ -517,7 +527,7 @@
             else:
                 raise Exception("os.utime() arg 2 must be None or a tuple of "
                                 "2 floats, got %s" % (s_times,))
-        os_utime_normalize_args._default_signature_ = [traits.str, None]
+        os_utime_normalize_args._default_signature_ = [traits.str0, None]
 
         return extdef(os_utime_normalize_args, s_None,
                       "ll_os.ll_os_utime",
@@ -612,7 +622,7 @@
             if result == -1:
                 raise OSError(rposix.get_errno(), "os_chroot failed")
 
-        return extdef([str], None, export_name="ll_os.ll_os_chroot",
+        return extdef([str0], None, export_name="ll_os.ll_os_chroot",
                       llimpl=chroot_llimpl)
 
     @registering_if(os, 'uname')
@@ -816,7 +826,7 @@
         def os_open_oofakeimpl(path, flags, mode):
             return os.open(OOSupport.from_rstr(path), flags, mode)
 
-        return extdef([traits.str, int, int], int, traits.ll_os_name('open'),
+        return extdef([traits.str0, int, int], int, traits.ll_os_name('open'),
                       llimpl=os_open_llimpl, oofakeimpl=os_open_oofakeimpl)
 
     @registering_if(os, 'getloadavg')
@@ -1050,7 +1060,7 @@
         def os_access_oofakeimpl(path, mode):
             return os.access(OOSupport.from_rstr(path), mode)
 
-        return extdef([traits.str, int], s_Bool, llimpl=access_llimpl,
+        return extdef([traits.str0, int], s_Bool, llimpl=access_llimpl,
                       export_name=traits.ll_os_name("access"),
                       oofakeimpl=os_access_oofakeimpl)
 
@@ -1062,8 +1072,8 @@
         from pypy.rpython.module.ll_win32file import make_getfullpathname_impl
         getfullpathname_llimpl = make_getfullpathname_impl(traits)
 
-        return extdef([traits.str],  # a single argument which is a str
-                      traits.str,    # returns a string
+        return extdef([traits.str0],  # a single argument which is a str
+                      traits.str0,    # returns a string
                       traits.ll_os_name('_getfullpathname'),
                       llimpl=getfullpathname_llimpl)
 
@@ -1174,8 +1184,8 @@
                     raise OSError(error, "os_readdir failed")
                 return result
 
-        return extdef([traits.str],  # a single argument which is a str
-                      [traits.str],  # returns a list of strings
+        return extdef([traits.str0],  # a single argument which is a str
+                      [traits.str0],  # returns a list of strings
                       traits.ll_os_name('listdir'),
                       llimpl=os_listdir_llimpl)
 
@@ -1241,7 +1251,7 @@
             if res == -1:
                 raise OSError(rposix.get_errno(), "os_chown failed")
 
-        return extdef([str, int, int], None, "ll_os.ll_os_chown",
+        return extdef([str0, int, int], None, "ll_os.ll_os_chown",
                       llimpl=os_chown_llimpl)
 
     @registering_if(os, 'lchown')
@@ -1254,7 +1264,7 @@
             if res == -1:
                 raise OSError(rposix.get_errno(), "os_lchown failed")
 
-        return extdef([str, int, int], None, "ll_os.ll_os_lchown",
+        return extdef([str0, int, int], None, "ll_os.ll_os_lchown",
                       llimpl=os_lchown_llimpl)
 
     @registering_if(os, 'readlink')
@@ -1283,12 +1293,11 @@
                     lltype.free(buf, flavor='raw')
                     bufsize *= 4
             # convert the result to a string
-            l = [buf[i] for i in range(res)]
-            result = ''.join(l)
+            result = rffi.charp2strn(buf, res)
             lltype.free(buf, flavor='raw')
             return result
 
-        return extdef([str], str,
+        return extdef([str0], str0,
                       "ll_os.ll_os_readlink",
                       llimpl=os_readlink_llimpl)
 
@@ -1361,7 +1370,7 @@
             res = os_system(command)
             return rffi.cast(lltype.Signed, res)
 
-        return extdef([str], int, llimpl=system_llimpl,
+        return extdef([str0], int, llimpl=system_llimpl,
                       export_name="ll_os.ll_os_system")
 
     @registering_str_unicode(os.unlink)
@@ -1383,7 +1392,7 @@
                 if not win32traits.DeleteFile(path):
                     raise rwin32.lastWindowsError()
 
-        return extdef([traits.str], s_None, llimpl=unlink_llimpl,
+        return extdef([traits.str0], s_None, llimpl=unlink_llimpl,
                       export_name=traits.ll_os_name('unlink'))
 
     @registering_str_unicode(os.chdir)
@@ -1401,7 +1410,7 @@
             from pypy.rpython.module.ll_win32file import make_chdir_impl
             os_chdir_llimpl = make_chdir_impl(traits)
 
-        return extdef([traits.str], s_None, llimpl=os_chdir_llimpl,
+        return extdef([traits.str0], s_None, llimpl=os_chdir_llimpl,
                       export_name=traits.ll_os_name('chdir'))
 
     @registering_str_unicode(os.mkdir)
@@ -1424,7 +1433,7 @@
                 if res < 0:
                     raise OSError(rposix.get_errno(), "os_mkdir failed")
 
-        return extdef([traits.str, int], s_None, llimpl=os_mkdir_llimpl,
+        return extdef([traits.str0, int], s_None, llimpl=os_mkdir_llimpl,
                       export_name=traits.ll_os_name('mkdir'))
 
     @registering_str_unicode(os.rmdir)
@@ -1437,7 +1446,7 @@
             if res < 0:
                 raise OSError(rposix.get_errno(), "os_rmdir failed")
 
-        return extdef([traits.str], s_None, llimpl=rmdir_llimpl,
+        return extdef([traits.str0], s_None, llimpl=rmdir_llimpl,
                       export_name=traits.ll_os_name('rmdir'))
 
     @registering_str_unicode(os.chmod)
@@ -1454,7 +1463,7 @@
             from pypy.rpython.module.ll_win32file import make_chmod_impl
             chmod_llimpl = make_chmod_impl(traits)
 
-        return extdef([traits.str, int], s_None, llimpl=chmod_llimpl,
+        return extdef([traits.str0, int], s_None, llimpl=chmod_llimpl,
                       export_name=traits.ll_os_name('chmod'))
 
     @registering_str_unicode(os.rename)
@@ -1476,7 +1485,7 @@
                 if not win32traits.MoveFile(oldpath, newpath):
                     raise rwin32.lastWindowsError()
 
-        return extdef([traits.str, traits.str], s_None, llimpl=rename_llimpl,
+        return extdef([traits.str0, traits.str0], s_None, llimpl=rename_llimpl,
                       export_name=traits.ll_os_name('rename'))
 
     @registering_str_unicode(getattr(os, 'mkfifo', None))
@@ -1489,7 +1498,7 @@
             if res < 0:
                 raise OSError(rposix.get_errno(), "os_mkfifo failed")
 
-        return extdef([traits.str, int], s_None, llimpl=mkfifo_llimpl,
+        return extdef([traits.str0, int], s_None, llimpl=mkfifo_llimpl,
                       export_name=traits.ll_os_name('mkfifo'))
 
     @registering_str_unicode(getattr(os, 'mknod', None))
@@ -1503,7 +1512,7 @@
             if res < 0:
                 raise OSError(rposix.get_errno(), "os_mknod failed")
 
-        return extdef([traits.str, int, int], s_None, llimpl=mknod_llimpl,
+        return extdef([traits.str0, int, int], s_None, llimpl=mknod_llimpl,
                       export_name=traits.ll_os_name('mknod'))
 
     @registering(os.umask)
@@ -1555,7 +1564,7 @@
             if res < 0:
                 raise OSError(rposix.get_errno(), "os_link failed")
 
-        return extdef([str, str], s_None, llimpl=link_llimpl,
+        return extdef([str0, str0], s_None, llimpl=link_llimpl,
                       export_name="ll_os.ll_os_link")
 
     @registering_if(os, 'symlink')
@@ -1568,7 +1577,7 @@
             if res < 0:
                 raise OSError(rposix.get_errno(), "os_symlink failed")
 
-        return extdef([str, str], s_None, llimpl=symlink_llimpl,
+        return extdef([str0, str0], s_None, llimpl=symlink_llimpl,
                       export_name="ll_os.ll_os_symlink")
 
     @registering_if(os, 'fork')
diff --git a/pypy/rpython/module/ll_os_environ.py b/pypy/rpython/module/ll_os_environ.py
--- a/pypy/rpython/module/ll_os_environ.py
+++ b/pypy/rpython/module/ll_os_environ.py
@@ -3,8 +3,11 @@
 from pypy.rpython.controllerentry import Controller
 from pypy.rpython.extfunc import register_external
 from pypy.rpython.lltypesystem import rffi, lltype
+from pypy.rpython.module import ll_os
 from pypy.rlib import rposix
 
+str0 = ll_os.str0
+
 # ____________________________________________________________
 #
 # Annotation support to control access to 'os.environ' in the RPython program
@@ -64,7 +67,7 @@
     rffi.free_charp(l_name)
     return result
 
-register_external(r_getenv, [str], annmodel.SomeString(can_be_None=True),
+register_external(r_getenv, [str0], annmodel.SomeString(can_be_None=True),
                   export_name='ll_os.ll_os_getenv',
                   llimpl=getenv_llimpl)
 
@@ -93,7 +96,7 @@
     if l_oldstring:
         rffi.free_charp(l_oldstring)
 
-register_external(r_putenv, [str, str], annmodel.s_None,
+register_external(r_putenv, [str0, str0], annmodel.s_None,
                   export_name='ll_os.ll_os_putenv',
                   llimpl=putenv_llimpl)
 
@@ -128,7 +131,7 @@
             del envkeepalive.byname[name]
             rffi.free_charp(l_oldstring)
 
-    register_external(r_unsetenv, [str], annmodel.s_None,
+    register_external(r_unsetenv, [str0], annmodel.s_None,
                       export_name='ll_os.ll_os_unsetenv',
                       llimpl=unsetenv_llimpl)
 
@@ -172,7 +175,7 @@
         i += 1
     return result
 
-register_external(r_envkeys, [], [str],   # returns a list of strings
+register_external(r_envkeys, [], [str0],   # returns a list of strings
                   export_name='ll_os.ll_os_envkeys',
                   llimpl=envkeys_llimpl)
 
@@ -193,6 +196,6 @@
         i += 1
     return result
 
-register_external(r_envitems, [], [(str, str)],
+register_external(r_envitems, [], [(str0, str0)],
                   export_name='ll_os.ll_os_envitems',
                   llimpl=envitems_llimpl)
diff --git a/pypy/rpython/module/ll_os_stat.py b/pypy/rpython/module/ll_os_stat.py
--- a/pypy/rpython/module/ll_os_stat.py
+++ b/pypy/rpython/module/ll_os_stat.py
@@ -236,7 +236,7 @@
 def register_stat_variant(name, traits):
     if name != 'fstat':
         arg_is_path = True
-        s_arg = traits.str
+        s_arg = traits.str0
         ARG1 = traits.CCHARP
     else:
         arg_is_path = False
@@ -251,8 +251,6 @@
             [s_arg], s_StatResult, traits.ll_os_name(name),
             llimpl=posix_stat_llimpl)
 
-    assert traits.str is str
-
     if sys.platform.startswith('linux'):
         # because we always use _FILE_OFFSET_BITS 64 - this helps things work that are not a c compiler
         _functions = {'stat':  'stat64',
@@ -283,7 +281,7 @@
 
     @func_renamer('os_%s_fake' % (name,))
     def posix_fakeimpl(arg):
-        if s_arg == str:
+        if s_arg == traits.str0:
             arg = hlstr(arg)
         st = getattr(os, name)(arg)
         fields = [TYPE for fieldname, TYPE in STAT_FIELDS]
diff --git a/pypy/rpython/ootypesystem/test/test_ooann.py b/pypy/rpython/ootypesystem/test/test_ooann.py
--- a/pypy/rpython/ootypesystem/test/test_ooann.py
+++ b/pypy/rpython/ootypesystem/test/test_ooann.py
@@ -231,7 +231,7 @@
 
     a = RPythonAnnotator()
     s = a.build_types(oof, [bool])
-    assert s == annmodel.SomeString(can_be_None=True)
+    assert annmodel.SomeString(can_be_None=True).contains(s)
 
 def test_oostring():
     def oof():
diff --git a/pypy/rpython/test/test_extfunc.py b/pypy/rpython/test/test_extfunc.py
--- a/pypy/rpython/test/test_extfunc.py
+++ b/pypy/rpython/test/test_extfunc.py
@@ -167,3 +167,43 @@
         a = RPythonAnnotator(policy=policy)
         s = a.build_types(f, [])
         assert isinstance(s, annmodel.SomeString)
+
+    def test_str0(self):
+        str0 = annmodel.SomeString(no_nul=True)
+        def os_open(s):
+            pass
+        register_external(os_open, [str0], None)
+        def f(s):
+            return os_open(s)
+        policy = AnnotatorPolicy()
+        policy.allow_someobjects = False
+        a = RPythonAnnotator(policy=policy)
+        a.build_types(f, [str])  # Does not raise
+        assert a.translator.config.translation.check_str_without_nul == False
+        # Now enable the str0 check, and try again with a similar function
+        a.translator.config.translation.check_str_without_nul=True
+        def g(s):
+            return os_open(s)
+        raises(Exception, a.build_types, g, [str])
+        a.build_types(g, [str0])  # Does not raise
+
+    def test_list_of_str0(self):
+        str0 = annmodel.SomeString(no_nul=True)
+        def os_execve(l):
+            pass
+        register_external(os_execve, [[str0]], None)
+        def f(l):
+            return os_execve(l)
+        policy = AnnotatorPolicy()
+        policy.allow_someobjects = False
+        a = RPythonAnnotator(policy=policy)
+        a.build_types(f, [[str]])  # Does not raise
+        assert a.translator.config.translation.check_str_without_nul == False
+        # Now enable the str0 check, and try again with a similar function
+        a.translator.config.translation.check_str_without_nul=True
+        def g(l):
+            return os_execve(l)
+        raises(Exception, a.build_types, g, [[str]])
+        a.build_types(g, [[str0]])  # Does not raise
+        
+
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
@@ -60,7 +60,8 @@
     if sys.platform == 'win32':
         # Can't rename a DLL: it is always called 'libpypy-c.dll'
         for extra in ['libpypy-c.dll',
-                      'libexpat.dll', 'sqlite3.dll', 'msvcr90.dll']:
+                      'libexpat.dll', 'sqlite3.dll', 'msvcr90.dll',
+                      'libeay32.dll', 'ssleay32.dll']:
             p = pypy_c.dirpath().join(extra)
             if not p.check():
                 p = py.path.local.sysfind(extra)
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
@@ -11,7 +11,6 @@
 from pypy.translator.tool.cbuild import ExternalCompilationInfo
 
 class BasicGcPolicy(object):
-    stores_hash_at_the_end = False
 
     def __init__(self, db, thread_enabled=False):
         self.db = db
@@ -47,8 +46,7 @@
         return ExternalCompilationInfo(
             pre_include_bits=['/* using %s */' % (gct.__class__.__name__,),
                               '#define MALLOC_ZERO_FILLED %d' % (gct.malloc_zero_filled,),
-                              ],
-            post_include_bits=['typedef void *GC_hidden_pointer;']
+                              ]
             )
 
     def get_prebuilt_hash(self, obj):
@@ -308,7 +306,6 @@
 
 class FrameworkGcPolicy(BasicGcPolicy):
     transformerclass = framework.FrameworkGCTransformer
-    stores_hash_at_the_end = True
 
     def struct_setup(self, structdefnode, rtti):
         if rtti is not None and hasattr(rtti._obj, 'destructor_funcptr'):
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
@@ -3,6 +3,7 @@
 import os, time, sys
 from pypy.tool.udir import udir
 from pypy.rlib.rarithmetic import r_longlong
+from pypy.annotation import model as annmodel
 from pypy.translator.c.test.test_genc import compile
 from pypy.translator.c.test.test_standalone import StandaloneTests
 posix = __import__(os.name)
@@ -145,7 +146,7 @@
     filename = str(py.path.local(__file__))
     def call_access(path, mode):
         return os.access(path, mode)
-    f = compile(call_access, [str, int])
+    f = compile(call_access, [annmodel.s_Str0, int])
     for mode in os.R_OK, os.W_OK, os.X_OK, (os.R_OK | os.W_OK | os.X_OK):
         assert f(filename, mode) == os.access(filename, mode)
 
@@ -225,7 +226,7 @@
 def test_system():
     def does_stuff(cmd):
         return os.system(cmd)
-    f1 = compile(does_stuff, [str])
+    f1 = compile(does_stuff, [annmodel.s_Str0])
     res = f1("echo hello")
     assert res == 0
 
@@ -311,7 +312,7 @@
 def test_chdir():
     def does_stuff(path):
         os.chdir(path)
-    f1 = compile(does_stuff, [str])
+    f1 = compile(does_stuff, [annmodel.s_Str0])
     curdir = os.getcwd()
     try:
         os.chdir('..')
@@ -325,7 +326,7 @@
             os.rmdir(path)
         else:
             os.mkdir(path, 0777)
-    f1 = compile(does_stuff, [str, bool])
+    f1 = compile(does_stuff, [annmodel.s_Str0, bool])
     dirname = str(udir.join('test_mkdir_rmdir'))
     f1(dirname, False)
     assert os.path.exists(dirname) and os.path.isdir(dirname)
@@ -628,7 +629,7 @@
             return os.environ[s]
         except KeyError:
             return '--missing--'
-    func = compile(fn, [str])
+    func = compile(fn, [annmodel.s_Str0])
     os.environ.setdefault('USER', 'UNNAMED_USER')
     result = func('USER')
     assert result == os.environ['USER']
@@ -640,7 +641,7 @@
         res = os.environ.get(s)
         if res is None: res = '--missing--'
         return res
-    func = compile(fn, [str])
+    func = compile(fn, [annmodel.s_Str0])
     os.environ.setdefault('USER', 'UNNAMED_USER')
     result = func('USER')
     assert result == os.environ['USER']
@@ -654,7 +655,7 @@
         os.environ[s] = t3
         os.environ[s] = t4
         os.environ[s] = t5
-    func = compile(fn, [str, str, str, str, str, str])
+    func = compile(fn, [annmodel.s_Str0] * 6)
     func('PYPY_TEST_DICTLIKE_ENVIRON', 'a', 'b', 'c', 'FOOBAR', '42',
          expected_extra_mallocs = (2, 3, 4))   # at least two, less than 5
     assert _real_getenv('PYPY_TEST_DICTLIKE_ENVIRON') == '42'
@@ -678,7 +679,7 @@
             else:
                 raise Exception("should have raised!")
             # os.environ[s5] stays
-    func = compile(fn, [str, str, str, str, str])
+    func = compile(fn, [annmodel.s_Str0] * 5)
     if hasattr(__import__(os.name), 'unsetenv'):
         expected_extra_mallocs = range(2, 10)
         # at least 2, less than 10: memory for s1, s2, s3, s4 should be freed
@@ -743,7 +744,7 @@
             raise AssertionError("should have failed!")
         result = os.listdir(s)
         return '/'.join(result)
-    func = compile(mylistdir, [str])
+    func = compile(mylistdir, [annmodel.s_Str0])
     for testdir in [str(udir), os.curdir]:
         result = func(testdir)
         result = result.split('/')
diff --git a/pypy/translator/cli/test/runtest.py b/pypy/translator/cli/test/runtest.py
--- a/pypy/translator/cli/test/runtest.py
+++ b/pypy/translator/cli/test/runtest.py
@@ -276,7 +276,7 @@
 
 def get_annotation(x):
     if isinstance(x, basestring) and len(x) > 1:
-        return SomeString()
+        return SomeString(no_nul='\x00' not in x)
     else:
         return lltype_to_annotation(typeOf(x))
 
diff --git a/pypy/translator/driver.py b/pypy/translator/driver.py
--- a/pypy/translator/driver.py
+++ b/pypy/translator/driver.py
@@ -184,6 +184,7 @@
         self.standalone = standalone
 
         if standalone:
+            # the 'argv' parameter
             inputtypes = [s_list_of_strings]
         self.inputtypes = inputtypes
 
diff --git a/pypy/translator/goal/nanos.py b/pypy/translator/goal/nanos.py
--- a/pypy/translator/goal/nanos.py
+++ b/pypy/translator/goal/nanos.py
@@ -266,7 +266,7 @@
     raise NotImplementedError("os.name == %r" % (os.name,))
 
 def getenv(space, w_name):
-    name = space.str_w(w_name)
+    name = space.str0_w(w_name)
     return space.wrap(os.environ.get(name))
 getenv_w = interp2app(getenv)
 
diff --git a/pypy/translator/goal/targetpypystandalone.py b/pypy/translator/goal/targetpypystandalone.py
--- a/pypy/translator/goal/targetpypystandalone.py
+++ b/pypy/translator/goal/targetpypystandalone.py
@@ -159,6 +159,8 @@
         ## if config.translation.type_system == 'ootype':
         ##     config.objspace.usemodules.suggest(rbench=True)
 
+        config.translation.suggest(check_str_without_nul=True)
+
         if config.translation.thread:
             config.objspace.usemodules.thread = True
         elif config.objspace.usemodules.thread:


More information about the pypy-commit mailing list