Author: Carl Friedrich Bolz <cfb...@gmx.de>
Branch: space-newtext
Changeset: r89058:66c3c930e1f2
Date: 2016-12-13 16:54 +0100
http://bitbucket.org/pypy/pypy/changeset/66c3c930e1f2/

Log:    merge default

diff --git a/lib_pypy/_pypy_wait.py b/lib_pypy/_pypy_wait.py
--- a/lib_pypy/_pypy_wait.py
+++ b/lib_pypy/_pypy_wait.py
@@ -1,3 +1,4 @@
+import os
 from resource import ffi, lib, _make_struct_rusage
 
 __all__ = ["wait3", "wait4"]
@@ -7,6 +8,9 @@
     status = ffi.new("int *")
     ru = ffi.new("struct rusage *")
     pid = lib.wait3(status, options, ru)
+    if pid == -1:
+        errno = ffi.errno
+        raise OSError(errno, os.strerror(errno))
 
     rusage = _make_struct_rusage(ru)
 
@@ -16,6 +20,9 @@
     status = ffi.new("int *")
     ru = ffi.new("struct rusage *")
     pid = lib.wait4(pid, status, options, ru)
+    if pid == -1:
+        errno = ffi.errno
+        raise OSError(errno, os.strerror(errno))
 
     rusage = _make_struct_rusage(ru)
 
diff --git a/lib_pypy/greenlet.egg-info b/lib_pypy/greenlet.egg-info
--- a/lib_pypy/greenlet.egg-info
+++ b/lib_pypy/greenlet.egg-info
@@ -1,6 +1,6 @@
 Metadata-Version: 1.0
 Name: greenlet
-Version: 0.4.10
+Version: 0.4.11
 Summary: Lightweight in-process concurrent programming
 Home-page: https://github.com/python-greenlet/greenlet
 Author: Ralf Schmitt (for CPython), PyPy team
diff --git a/lib_pypy/greenlet.py b/lib_pypy/greenlet.py
--- a/lib_pypy/greenlet.py
+++ b/lib_pypy/greenlet.py
@@ -1,7 +1,7 @@
 import sys
 import _continuation
 
-__version__ = "0.4.10"
+__version__ = "0.4.11"
 
 # ____________________________________________________________
 # Exceptions
diff --git a/pypy/doc/project-ideas.rst b/pypy/doc/project-ideas.rst
--- a/pypy/doc/project-ideas.rst
+++ b/pypy/doc/project-ideas.rst
@@ -71,8 +71,11 @@
 Analyzing performance of applications is always tricky. We have various
 tools, for example a `jitviewer`_ that help us analyze performance.
 
-The jitviewer shows the code generated by the PyPy JIT in a hierarchical way,
-as shown by the screenshot below:
+The old tool was partly rewritten and combined with vmprof. The service is
+hosted at `vmprof.com`_.
+
+The following shows an old image of the jitviewer.
+The code generated by the PyPy JIT in a hierarchical way:
 
   - at the bottom level, it shows the Python source code of the compiled loops
 
@@ -84,13 +87,17 @@
 
 .. image:: image/jitviewer.png
 
-The jitviewer is a web application based on flask and jinja2 (and jQuery on
-the client): if you have great web developing skills and want to help PyPy,
+The jitviewer is a web application based on django and angularjs:
+if you have great web developing skills and want to help PyPy,
 this is an ideal task to get started, because it does not require any deep
-knowledge of the internals.
+knowledge of the internals. Head over to `vmprof-python`_, `vmprof-server`_ and
+`vmprof-integration`_ to find open issues and documentation.
 
-.. _jitviewer: http://bitbucket.org/pypy/jitviewer
-
+.. _jitviewer: http://vmprof.com
+.. _vmprof.com: http://vmprof.com
+.. _vmprof-python: https://github.com/vmprof/vmprof-python
+.. _vmprof-server: https://github.com/vmprof/vmprof-server
+.. _vmprof-integration: https://github.com/vmprof/vmprof-integration
 
 Optimized Unicode Representation
 --------------------------------
diff --git a/pypy/doc/whatsnew-head.rst b/pypy/doc/whatsnew-head.rst
--- a/pypy/doc/whatsnew-head.rst
+++ b/pypy/doc/whatsnew-head.rst
@@ -5,6 +5,15 @@
 .. this is a revision shortly after release-pypy2.7-v5.6
 .. startrev: 7e9787939641
 
+
+Since a while now, PyPy preserves the order of dictionaries and sets.
+However, the set literal syntax ``{x, y, z}`` would by mistake build a
+set with the opposite order: ``set([z, y, x])``.  This has been fixed.
+Note that CPython is inconsistent too: in 2.7.12, ``{5, 5.0}`` would be
+``set([5.0])``, but in 2.7.trunk it is ``set([5])``.  PyPy's behavior
+changed in exactly the same way because of this fix.
+
+
 .. branch: rpython-error-to-systemerror
 
 Any uncaught RPython exception (from a PyPy bug) is turned into an
@@ -29,3 +38,10 @@
 .. branch: desc-specialize
 
 Refactor FunctionDesc.specialize() and related code (RPython annotator).
+
+.. branch: raw-calloc
+
+.. branch: issue2446
+
+Assign ``tp_doc`` to the new TypeObject's type dictionary ``__doc__`` key
+so it will be picked up by app-level objects of that type
diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py
--- a/pypy/interpreter/baseobjspace.py
+++ b/pypy/interpreter/baseobjspace.py
@@ -433,6 +433,8 @@
         make_finalizer_queue(W_Root, self)
         self._code_of_sys_exc_info = None
 
+        self._builtin_functions_by_identifier = {'': None}
+
         # can be overridden to a subclass
         self.initialize()
 
diff --git a/pypy/interpreter/executioncontext.py 
b/pypy/interpreter/executioncontext.py
--- a/pypy/interpreter/executioncontext.py
+++ b/pypy/interpreter/executioncontext.py
@@ -547,6 +547,8 @@
 
     @jit.dont_look_inside
     def _run_finalizers(self):
+        # called by perform() when we have to "perform" this action,
+        # and also directly at the end of gc.collect).
         while True:
             w_obj = self.space.finalizer_queue.next_dead()
             if w_obj is None:
diff --git a/pypy/interpreter/function.py b/pypy/interpreter/function.py
--- a/pypy/interpreter/function.py
+++ b/pypy/interpreter/function.py
@@ -247,16 +247,15 @@
     def descr_function_repr(self):
         return self.getrepr(self.space, 'function %s' % (self.name,))
 
-    # delicate
-    _all = {'': None}
 
     def _cleanup_(self):
+        # delicate
         from pypy.interpreter.gateway import BuiltinCode
         if isinstance(self.code, BuiltinCode):
             # we have been seen by other means so rtyping should not choke
             # on us
             identifier = self.code.identifier
-            previous = Function._all.get(identifier, self)
+            previous = 
self.space._builtin_functions_by_identifier.get(identifier, self)
             assert previous is self, (
                 "duplicate function ids with identifier=%r: %r and %r" % (
                 identifier, previous, self))
@@ -264,10 +263,10 @@
         return False
 
     def add_to_table(self):
-        Function._all[self.code.identifier] = self
+        self.space._builtin_functions_by_identifier[self.code.identifier] = 
self
 
-    def find(identifier):
-        return Function._all[identifier]
+    def find(space, identifier):
+        return space._builtin_functions_by_identifier[identifier]
     find = staticmethod(find)
 
     def descr_function__reduce__(self, space):
diff --git a/pypy/interpreter/gateway.py b/pypy/interpreter/gateway.py
--- a/pypy/interpreter/gateway.py
+++ b/pypy/interpreter/gateway.py
@@ -689,9 +689,9 @@
         return space.newtuple([builtin_code,
                                
space.newtuple([space.newtext(self.identifier)])])
 
-    def find(indentifier):
+    def find(space, indentifier):
         from pypy.interpreter.function import Function
-        return Function._all[indentifier].code
+        return Function.find(space, identifier).code
     find = staticmethod(find)
 
     def signature(self):
diff --git a/pypy/interpreter/pyopcode.py b/pypy/interpreter/pyopcode.py
--- a/pypy/interpreter/pyopcode.py
+++ b/pypy/interpreter/pyopcode.py
@@ -1292,9 +1292,10 @@
     @jit.unroll_safe
     def BUILD_SET(self, itemcount, next_instr):
         w_set = self.space.newset()
-        for i in range(itemcount):
-            w_item = self.popvalue()
+        for i in range(itemcount-1, -1, -1):
+            w_item = self.peekvalue(i)
             self.space.call_method(w_set, 'add', w_item)
+        self.popvalues(itemcount)
         self.pushvalue(w_set)
 
     def STORE_MAP(self, oparg, next_instr):
diff --git a/pypy/interpreter/test/test_compiler.py 
b/pypy/interpreter/test/test_compiler.py
--- a/pypy/interpreter/test/test_compiler.py
+++ b/pypy/interpreter/test/test_compiler.py
@@ -729,6 +729,10 @@
 
 
 class AppTestCompiler:
+    def setup_class(cls):
+        cls.w_host_is_pypy = cls.space.wrap(
+            '__pypy__' in sys.builtin_module_names)
+
     def test_bom_with_future(self):
         s = '\xef\xbb\xbffrom __future__ import division\nx = 1/2'
         ns = {}
@@ -771,6 +775,18 @@
         assert math.copysign(1., c[0]) == -1.0
         assert math.copysign(1., c[1]) == -1.0
 
+    def test_dict_and_set_literal_order(self):
+        x = 1
+        l1 = list({1:'a', 3:'b', 2:'c', 4:'d'})
+        l2 = list({1, 3, 2, 4})
+        l3 = list({x:'a', 3:'b', 2:'c', 4:'d'})
+        l4 = list({x, 3, 2, 4})
+        if not self.host_is_pypy:
+            # the full test relies on the host Python providing ordered dicts
+            assert set(l1) == set(l2) == set(l3) == set(l4) == {1, 3, 2, 4}
+        else:
+            assert l1 == l2 == l3 == l4 == [1, 3, 2, 4]
+
 
 ##class TestPythonAstCompiler(BaseTestCompiler):
 ##    def setup_method(self, method):
diff --git a/pypy/interpreter/test/test_pyframe.py 
b/pypy/interpreter/test/test_pyframe.py
--- a/pypy/interpreter/test/test_pyframe.py
+++ b/pypy/interpreter/test/test_pyframe.py
@@ -580,3 +580,25 @@
             pass
         sys.settrace(None)
         assert seen == ['call', 'exception', 'return']
+
+    def test_generator_trace_stopiteration(self):
+        import sys
+        def f():
+            yield 5
+        gen = f()
+        assert next(gen) == 5
+        seen = []
+        def trace_func(frame, event, *args):
+            print('TRACE:', frame, event, args)
+            seen.append(event)
+            return trace_func
+        def g():
+            for x in gen:
+                never_entered
+        sys.settrace(trace_func)
+        g()
+        sys.settrace(None)
+        print 'seen:', seen
+        # on Python 3 we get an extra 'exception' when 'for' catches
+        # StopIteration
+        assert seen == ['call', 'line', 'call', 'return', 'return']
diff --git a/pypy/interpreter/test/test_special.py 
b/pypy/interpreter/test/test_special.py
--- a/pypy/interpreter/test/test_special.py
+++ b/pypy/interpreter/test/test_special.py
@@ -4,9 +4,11 @@
     def test_Ellipsis(self):
         assert Ellipsis == Ellipsis
         assert repr(Ellipsis) == 'Ellipsis'
+        assert Ellipsis.__class__.__name__ == 'ellipsis'
     
     def test_NotImplemented(self):
         def f():
             return NotImplemented
         assert f() == NotImplemented 
         assert repr(NotImplemented) == 'NotImplemented'
+        assert NotImplemented.__class__.__name__ == 'NotImplementedType'
diff --git a/pypy/interpreter/test/test_unicodehelper.py 
b/pypy/interpreter/test/test_unicodehelper.py
new file mode 100644
--- /dev/null
+++ b/pypy/interpreter/test/test_unicodehelper.py
@@ -0,0 +1,26 @@
+from pypy.interpreter.unicodehelper import encode_utf8, decode_utf8
+
+class FakeSpace:
+    pass
+
+def test_encode_utf8():
+    space = FakeSpace()
+    assert encode_utf8(space, u"abc") == "abc"
+    assert encode_utf8(space, u"\u1234") == "\xe1\x88\xb4"
+    assert encode_utf8(space, u"\ud800") == "\xed\xa0\x80"
+    assert encode_utf8(space, u"\udc00") == "\xed\xb0\x80"
+    # for the following test, go to lengths to avoid CPython's optimizer
+    # and .pyc file storage, which collapse the two surrogates into one
+    c = u"\udc00"
+    assert encode_utf8(space, u"\ud800" + c) == "\xf0\x90\x80\x80"
+
+def test_decode_utf8():
+    space = FakeSpace()
+    assert decode_utf8(space, "abc") == u"abc"
+    assert decode_utf8(space, "\xe1\x88\xb4") == u"\u1234"
+    assert decode_utf8(space, "\xed\xa0\x80") == u"\ud800"
+    assert decode_utf8(space, "\xed\xb0\x80") == u"\udc00"
+    got = decode_utf8(space, "\xed\xa0\x80\xed\xb0\x80")
+    assert map(ord, got) == [0xd800, 0xdc00]
+    got = decode_utf8(space, "\xf0\x90\x80\x80")
+    assert map(ord, got) == [0x10000]
diff --git a/pypy/interpreter/typedef.py b/pypy/interpreter/typedef.py
--- a/pypy/interpreter/typedef.py
+++ b/pypy/interpreter/typedef.py
@@ -771,12 +771,12 @@
 )
 assert not Cell.typedef.acceptable_as_base_class  # no __new__
 
-Ellipsis.typedef = TypeDef("Ellipsis",
+Ellipsis.typedef = TypeDef("ellipsis",
     __repr__ = interp2app(Ellipsis.descr__repr__),
 )
 assert not Ellipsis.typedef.acceptable_as_base_class  # no __new__
 
-NotImplemented.typedef = TypeDef("NotImplemented",
+NotImplemented.typedef = TypeDef("NotImplementedType",
     __repr__ = interp2app(NotImplemented.descr__repr__),
 )
 assert not NotImplemented.typedef.acceptable_as_base_class  # no __new__
diff --git a/pypy/interpreter/unicodehelper.py 
b/pypy/interpreter/unicodehelper.py
--- a/pypy/interpreter/unicodehelper.py
+++ b/pypy/interpreter/unicodehelper.py
@@ -51,6 +51,10 @@
     return result
 
 def decode_utf8(space, string):
+    # Surrogates are accepted and not treated specially at all.
+    # If there happen to be two 3-bytes encoding a pair of surrogates,
+    # you still get two surrogate unicode characters in the result.
+    # These are the Python2 rules; Python3 differs.
     result, consumed = runicode.str_decode_utf_8(
         string, len(string), "strict",
         final=True, errorhandler=decode_error_handler(space),
@@ -59,8 +63,9 @@
 
 def encode_utf8(space, uni):
     # Note that this function never raises UnicodeEncodeError,
-    # since surrogate pairs are allowed.
-    # This is not the case with Python3.
+    # since surrogates are allowed, either paired or lone.
+    # A paired surrogate is considered like the non-BMP character
+    # it stands for.  These are the Python2 rules; Python3 differs.
     return runicode.unicode_encode_utf_8(
         uni, len(uni), "strict",
         errorhandler=raise_unicode_exception_encode,
diff --git a/pypy/module/_cffi_backend/test/test_ffi_obj.py 
b/pypy/module/_cffi_backend/test/test_ffi_obj.py
--- a/pypy/module/_cffi_backend/test/test_ffi_obj.py
+++ b/pypy/module/_cffi_backend/test/test_ffi_obj.py
@@ -401,7 +401,8 @@
             retries += 1
             assert retries <= 5
             import gc; gc.collect()
-        assert seen == [40, 40, raw1, raw2]
+        assert (seen == [40, 40, raw1, raw2] or
+                seen == [40, 40, raw2, raw1])
         assert repr(seen[2]) == "<cdata 'char[]' owning 41 bytes>"
         assert repr(seen[3]) == "<cdata 'char[]' owning 41 bytes>"
 
diff --git a/pypy/module/_pickle_support/maker.py 
b/pypy/module/_pickle_support/maker.py
--- a/pypy/module/_pickle_support/maker.py
+++ b/pypy/module/_pickle_support/maker.py
@@ -77,7 +77,7 @@
 def builtin_code(space, identifier):
     from pypy.interpreter import gateway
     try:
-        return gateway.BuiltinCode.find(identifier)
+        return gateway.BuiltinCode.find(space, identifier)
     except KeyError:
         raise oefmt(space.w_RuntimeError,
                     "cannot unpickle builtin code: %s", identifier)
@@ -86,7 +86,7 @@
 def builtin_function(space, identifier):
     from pypy.interpreter import function
     try:
-        return function.Function.find(identifier)
+        return function.Function.find(space, identifier)
     except KeyError:
         raise oefmt(space.w_RuntimeError,
                     "cannot unpickle builtin function: %s", identifier)
diff --git a/pypy/module/cpyext/pyobject.py b/pypy/module/cpyext/pyobject.py
--- a/pypy/module/cpyext/pyobject.py
+++ b/pypy/module/cpyext/pyobject.py
@@ -25,11 +25,9 @@
     basestruct = PyObject.TO
     W_BaseObject = W_ObjectObject
 
-    def get_dealloc(self, space):
+    def get_dealloc(self):
         from pypy.module.cpyext.typeobject import subtype_dealloc
-        return llhelper(
-            subtype_dealloc.api_func.functype,
-            subtype_dealloc.api_func.get_wrapper(space))
+        return subtype_dealloc.api_func
 
     def allocate(self, space, w_type, itemcount=0):
         # similar to PyType_GenericAlloc?
@@ -109,10 +107,8 @@
                 return tp_alloc(space, w_type, itemcount)
 
         if tp_dealloc:
-            def get_dealloc(self, space):
-                return llhelper(
-                    tp_dealloc.api_func.functype,
-                    tp_dealloc.api_func.get_wrapper(space))
+            def get_dealloc(self):
+                return tp_dealloc.api_func
 
         if tp_attach:
             def attach(self, space, pyobj, w_obj):
diff --git a/pypy/module/cpyext/slotdefs.py b/pypy/module/cpyext/slotdefs.py
--- a/pypy/module/cpyext/slotdefs.py
+++ b/pypy/module/cpyext/slotdefs.py
@@ -8,12 +8,12 @@
     cpython_api, generic_cpy_call, PyObject, Py_ssize_t, Py_TPFLAGS_CHECKTYPES,
     mangle_name, pypy_decl, Py_buffer, Py_bufferP)
 from pypy.module.cpyext.typeobjectdefs import (
-    unaryfunc, wrapperfunc, ternaryfunc, PyTypeObjectPtr, binaryfunc, 
ternaryfunc,
+    unaryfunc, ternaryfunc, PyTypeObjectPtr, binaryfunc,
     getattrfunc, getattrofunc, setattrofunc, lenfunc, ssizeargfunc, inquiry,
     ssizessizeargfunc, ssizeobjargproc, iternextfunc, initproc, richcmpfunc,
     cmpfunc, hashfunc, descrgetfunc, descrsetfunc, objobjproc, objobjargproc,
     readbufferproc, getbufferproc, ssizessizeobjargproc)
-from pypy.module.cpyext.pyobject import from_ref, make_ref, Py_DecRef
+from pypy.module.cpyext.pyobject import make_ref, Py_DecRef
 from pypy.module.cpyext.pyerrors import PyErr_Occurred
 from pypy.module.cpyext.memoryobject import fill_Py_buffer
 from pypy.module.cpyext.state import State
@@ -21,8 +21,10 @@
 from pypy.interpreter.argument import Arguments
 from rpython.rlib.buffer import Buffer
 from rpython.rlib.unroll import unrolling_iterable
-from rpython.rlib.objectmodel import specialize
+from rpython.rlib.objectmodel import specialize, not_rpython
 from rpython.tool.sourcetools import func_renamer
+from rpython.flowspace.model import Constant
+from rpython.flowspace.specialcase import register_flow_sc
 from rpython.rtyper.annlowlevel import llhelper
 from pypy.module.sys.version import CPYTHON_VERSION
 
@@ -59,6 +61,17 @@
                 "expected %d-%d arguments, got %d",
                 low, high, space.len_w(w_ob))
 
+@not_rpython
+def llslot(space, func):
+    return llhelper(func.api_func.functype, func.api_func.get_wrapper(space))
+
+@register_flow_sc(llslot)
+def sc_llslot(ctx, v_space, v_func):
+    assert isinstance(v_func, Constant)
+    get_llhelper = v_func.value.api_func.get_llhelper
+    return ctx.appcall(get_llhelper, v_space)
+
+
 def wrap_init(space, w_self, w_args, func, w_kwargs):
     func_init = rffi.cast(initproc, func)
     res = generic_cpy_call(space, func_init, w_self, w_args, w_kwargs)
@@ -106,7 +119,7 @@
     args_w = space.fixedview(w_args)
     arg3 = space.w_None
     if len(args_w) > 1:
-        arg3 = args_w[1] 
+        arg3 = args_w[1]
     return generic_cpy_call(space, func_ternary, w_self, args_w[0], arg3)
 
 def wrap_ternaryfunc_r(space, w_self, w_args, func):
@@ -121,7 +134,7 @@
     Py_DecRef(space, ref)
     arg3 = space.w_None
     if len(args_w) > 1:
-        arg3 = args_w[1] 
+        arg3 = args_w[1]
     return generic_cpy_call(space, func_ternary, args_w[0], w_self, arg3)
 
 
@@ -322,7 +335,7 @@
             self.strides = [1]
         else:
             self.strides = strides
-        self.ndim = ndim 
+        self.ndim = ndim
         self.itemsize = itemsize
         self.readonly = readonly
 
@@ -437,9 +450,10 @@
     try:
         return SLOTS[key]
     except KeyError:
-        ret = build_slot_tp_function(space, typedef, name)
-        SLOTS[key] = ret
-        return ret
+        slot_func = build_slot_tp_function(space, typedef, name)
+        api_func = slot_func.api_func if slot_func else None
+        SLOTS[key] = api_func
+        return api_func
 
 def build_slot_tp_function(space, typedef, name):
     w_type = space.gettypeobject(typedef)
@@ -472,7 +486,6 @@
             @func_renamer("cpyext_%s_%s" % (name.replace('.', '_'), 
typedef.name))
             def slot_func(space, w_self):
                 return space.call_function(slot_fn, w_self)
-            api_func = slot_func.api_func
             handled = True
 
     # binary functions
@@ -499,7 +512,6 @@
             @func_renamer("cpyext_%s_%s" % (name.replace('.', '_'), 
typedef.name))
             def slot_func(space, w_self, w_arg):
                 return space.call_function(slot_fn, w_self, w_arg)
-            api_func = slot_func.api_func
             handled = True
 
     # binary-with-Py_ssize_t-type
@@ -517,7 +529,6 @@
             @func_renamer("cpyext_%s_%s" % (name.replace('.', '_'), 
typedef.name))
             def slot_func(space, w_self, arg):
                 return space.call_function(slot_fn, w_self, space.newint(arg))
-            api_func = slot_func.api_func
             handled = True
 
     # ternary functions
@@ -532,7 +543,6 @@
             @func_renamer("cpyext_%s_%s" % (name.replace('.', '_'), 
typedef.name))
             def slot_func(space, w_self, w_arg1, w_arg2):
                 return space.call_function(slot_fn, w_self, w_arg1, w_arg2)
-            api_func = slot_func.api_func
             handled = True
 
     if handled:
@@ -552,7 +562,7 @@
             else:
                 space.call_function(delattr_fn, w_self, w_name)
             return 0
-        api_func = slot_tp_setattro.api_func
+        slot_func = slot_tp_setattro
     elif name == 'tp_getattro':
         getattr_fn = w_type.getdictvalue(space, '__getattribute__')
         if getattr_fn is None:
@@ -562,7 +572,7 @@
         @func_renamer("cpyext_tp_getattro_%s" % (typedef.name,))
         def slot_tp_getattro(space, w_self, w_name):
             return space.call_function(getattr_fn, w_self, w_name)
-        api_func = slot_tp_getattro.api_func
+        slot_func = slot_tp_getattro
     elif name == 'tp_call':
         call_fn = w_type.getdictvalue(space, '__call__')
         if call_fn is None:
@@ -574,7 +584,7 @@
             args = Arguments(space, [w_self],
                              w_stararg=w_args, w_starstararg=w_kwds)
             return space.call_args(call_fn, args)
-        api_func = slot_tp_call.api_func
+        slot_func = slot_tp_call
 
     elif name == 'tp_iternext':
         iternext_fn = w_type.getdictvalue(space, 'next')
@@ -590,7 +600,7 @@
                 if not e.match(space, space.w_StopIteration):
                     raise
                 return None
-        api_func = slot_tp_iternext.api_func
+        slot_func = slot_tp_iternext
 
     elif name == 'tp_init':
         init_fn = w_type.getdictvalue(space, '__init__')
@@ -605,7 +615,7 @@
                              w_stararg=w_args, w_starstararg=w_kwds)
             space.call_args(init_fn, args)
             return 0
-        api_func = slot_tp_init.api_func
+        slot_func = slot_tp_init
     elif name == 'tp_new':
         new_fn = w_type.getdictvalue(space, '__new__')
         if new_fn is None:
@@ -617,12 +627,12 @@
             args = Arguments(space, [w_self],
                              w_stararg=w_args, w_starstararg=w_kwds)
             return space.call_args(space.get(new_fn, w_self), args)
-        api_func = slot_tp_new.api_func
+        slot_func = slot_tp_new
     elif name == 'tp_as_buffer.c_bf_getbuffer':
         buff_fn = w_type.getdictvalue(space, '__buffer__')
         if buff_fn is None:
             return
-        @cpython_api([PyObject, Py_bufferP, rffi.INT_real], 
+        @cpython_api([PyObject, Py_bufferP, rffi.INT_real],
                 rffi.INT_real, header=None, error=-1)
         @func_renamer("cpyext_%s_%s" % (name.replace('.', '_'), typedef.name))
         def buff_w(space, w_self, view, flags):
@@ -647,14 +657,14 @@
             return 0
         # XXX remove this when it no longer crashes a translated PyPy
         return
-        api_func = buff_w.api_func
+        slot_func = buff_w
     else:
         # missing: tp_as_number.nb_nonzero, tp_as_number.nb_coerce
         # tp_as_sequence.c_sq_contains, tp_as_sequence.c_sq_length
         # richcmpfunc(s)
         return
 
-    return lambda: llhelper(api_func.functype, api_func.get_wrapper(space))
+    return slot_func
 
 PyWrapperFlag_KEYWORDS = 1
 
@@ -985,8 +995,8 @@
 slotdefs = sorted(slotdefs, key=slotdef_sort_key)
 
 slotdefs_for_tp_slots = unrolling_iterable(
-    [(x.method_name, x.slot_name, x.slot_names, x.slot_func)
-     for x in slotdefs])
+    [(x.method_name, x.slot_name, x.slot_names,
+      x.slot_func.api_func if x.slot_func else None) for x in slotdefs])
 
 slotdefs_for_wrappers = unrolling_iterable(
     [(x.method_name, x.slot_names, x.wrapper_func, x.wrapper_func_kwds, x.doc)
diff --git a/pypy/module/cpyext/test/test_typeobject.py 
b/pypy/module/cpyext/test/test_typeobject.py
--- a/pypy/module/cpyext/test/test_typeobject.py
+++ b/pypy/module/cpyext/test/test_typeobject.py
@@ -142,7 +142,7 @@
         assert fuu2(u"abc").baz().escape()
         raises(TypeError, module.fooType.object_member.__get__, 1)
 
-    def test_multiple_inheritance(self):
+    def test_multiple_inheritance1(self):
         module = self.import_module(name='foo')
         obj = module.UnicodeSubtype(u'xyz')
         obj2 = module.UnicodeSubtype2()
@@ -422,7 +422,7 @@
         assert space.int_w(space.getattr(w_class, w_name)) == 1
         space.delitem(w_dict, w_name)
 
-    def test_multiple_inheritance(self, space, api):
+    def test_multiple_inheritance2(self, space, api):
         w_class = space.appexec([], """():
             class A(object):
                 pass
@@ -1167,3 +1167,38 @@
             __metaclass__ = FooType
         print repr(X)
         X()
+
+    def test_multiple_inheritance3(self):
+        module = self.import_extension('foo', [
+           ("new_obj", "METH_NOARGS",
+            '''
+                PyObject *obj;
+                PyTypeObject *Base1, *Base2, *Base12;
+                Base1 =  (PyTypeObject*)PyType_Type.tp_alloc(&PyType_Type, 0);
+                Base2 =  (PyTypeObject*)PyType_Type.tp_alloc(&PyType_Type, 0);
+                Base12 =  (PyTypeObject*)PyType_Type.tp_alloc(&PyType_Type, 0);
+                Base1->tp_name = "Base1";
+                Base2->tp_name = "Base2";
+                Base12->tp_name = "Base12";
+                Base1->tp_basicsize = sizeof(PyHeapTypeObject);
+                Base2->tp_basicsize = sizeof(PyHeapTypeObject);
+                Base12->tp_basicsize = sizeof(PyHeapTypeObject);
+                Base1->tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | 
Py_TPFLAGS_HEAPTYPE;
+                Base2->tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | 
Py_TPFLAGS_HEAPTYPE;
+                Base12->tp_flags = Py_TPFLAGS_DEFAULT;
+                Base12->tp_base = Base1;
+                Base12->tp_bases = PyTuple_Pack(2, Base1, Base2); 
+                Base12->tp_doc = "The Base12 type or object";
+                if (PyType_Ready(Base1) < 0) return NULL;
+                if (PyType_Ready(Base2) < 0) return NULL;
+                if (PyType_Ready(Base12) < 0) return NULL;
+                obj = PyObject_New(PyObject, Base12);
+                return obj;
+            '''
+            )])
+        obj = module.new_obj()
+        assert 'Base12' in str(obj)
+        assert type(obj).__doc__ == "The Base12 type or object"
+        assert obj.__doc__ == "The Base12 type or object"
+
+
diff --git a/pypy/module/cpyext/typeobject.py b/pypy/module/cpyext/typeobject.py
--- a/pypy/module/cpyext/typeobject.py
+++ b/pypy/module/cpyext/typeobject.py
@@ -3,7 +3,6 @@
 from rpython.rlib import jit
 from rpython.rlib.objectmodel import specialize
 from rpython.rlib.rstring import rsplit
-from rpython.rtyper.annlowlevel import llhelper
 from rpython.rtyper.lltypesystem import rffi, lltype
 
 from pypy.interpreter.baseobjspace import W_Root, DescrMismatch
@@ -28,7 +27,8 @@
     PyObject, make_ref, create_ref, from_ref, get_typedescr, make_typedescr,
     track_reference, Py_DecRef, as_pyobj)
 from pypy.module.cpyext.slotdefs import (
-    slotdefs_for_tp_slots, slotdefs_for_wrappers, get_slot_tp_function)
+    slotdefs_for_tp_slots, slotdefs_for_wrappers, get_slot_tp_function,
+    llslot)
 from pypy.module.cpyext.state import State
 from pypy.module.cpyext.structmember import PyMember_GetOne, PyMember_SetOne
 from pypy.module.cpyext.typeobjectdefs import (
@@ -249,27 +249,21 @@
     # coming from a parent C type.
 
     typedef = w_type.layout.typedef
-    for method_name, slot_name, slot_names, slot_func in slotdefs_for_tp_slots:
+    for method_name, slot_name, slot_names, slot_apifunc in 
slotdefs_for_tp_slots:
         w_descr = w_type.lookup(method_name)
         if w_descr is None:
             # XXX special case iternext
             continue
 
-        slot_func_helper = None
-
-        if slot_func is None and typedef is not None:
-            get_slot = get_slot_tp_function(space, typedef, slot_name)
-            if get_slot:
-                slot_func_helper = get_slot()
-        elif slot_func:
-            slot_func_helper = llhelper(slot_func.api_func.functype,
-                                        slot_func.api_func.get_wrapper(space))
-
-        if slot_func_helper is None:
+        if slot_apifunc is None and typedef is not None:
+            slot_apifunc = get_slot_tp_function(space, typedef, slot_name)
+        if not slot_apifunc:
             if WARN_ABOUT_MISSING_SLOT_FUNCTIONS:
-                os.write(2, "%s defined by %s but no slot function defined!\n" 
% (
+                os.write(2,
+                    "%s defined by %s but no slot function defined!\n" % (
                         method_name, w_type.getname(space)))
             continue
+        slot_func_helper = slot_apifunc.get_llhelper(space)
 
         # XXX special case wrapper-functions and use a "specific" slot func
 
@@ -329,6 +323,8 @@
         w_obj = W_PyCWrapperObject(space, pto, method_name, wrapper_func,
                 wrapper_func_kwds, doc, func_voidp, offset=offset)
         dict_w[method_name] = w_obj
+    if pto.c_tp_doc:
+        dict_w['__doc__'] = space.newbytes(rffi.charp2str(pto.c_tp_doc))
     if pto.c_tp_new:
         add_tp_new_wrapper(space, dict_w, pto)
 
@@ -373,9 +369,8 @@
 
 def setup_new_method_def(space):
     ptr = get_new_method_def(space)
-    ptr.c_ml_meth = rffi.cast(PyCFunction_typedef,
-        llhelper(tp_new_wrapper.api_func.functype,
-                 tp_new_wrapper.api_func.get_wrapper(space)))
+    ptr.c_ml_meth = rffi.cast(
+        PyCFunction_typedef, llslot(space, tp_new_wrapper))
 
 def add_tp_new_wrapper(space, dict_w, pto):
     if "__new__" in dict_w:
@@ -465,13 +460,17 @@
         convert_member_defs(space, dict_w, pto.c_tp_members, self)
 
         name = rffi.charp2str(pto.c_tp_name)
-        new_layout = (pto.c_tp_basicsize > rffi.sizeof(PyObject.TO) or
-                      pto.c_tp_itemsize > 0)
+        flag_heaptype = pto.c_tp_flags & Py_TPFLAGS_HEAPTYPE
+        if flag_heaptype:
+            minsize = rffi.sizeof(PyHeapTypeObject.TO)
+        else:
+            minsize = rffi.sizeof(PyObject.TO)
+        new_layout = (pto.c_tp_basicsize > minsize or pto.c_tp_itemsize > 0)
 
         W_TypeObject.__init__(self, space, name,
-            bases_w or [space.w_object], dict_w, force_new_layout=new_layout)
+            bases_w or [space.w_object], dict_w, force_new_layout=new_layout,
+            is_heaptype=flag_heaptype)
         self.flag_cpytype = True
-        self.flag_heaptype = pto.c_tp_flags & Py_TPFLAGS_HEAPTYPE
         # if a sequence or a mapping, then set the flag to force it
         if pto.c_tp_as_sequence and pto.c_tp_as_sequence.c_sq_item:
             self.flag_map_or_seq = 'S'
@@ -494,8 +493,7 @@
 def subtype_dealloc(space, obj):
     pto = obj.c_ob_type
     base = pto
-    this_func_ptr = llhelper(subtype_dealloc.api_func.functype,
-            subtype_dealloc.api_func.get_wrapper(space))
+    this_func_ptr = llslot(space, subtype_dealloc)
     while base.c_tp_dealloc == this_func_ptr:
         base = base.c_tp_base
         assert base
@@ -597,46 +595,31 @@
         return
     c_buf = lltype.malloc(PyBufferProcs, flavor='raw', zero=True)
     lltype.render_immortal(c_buf)
-    c_buf.c_bf_getsegcount = llhelper(bf_segcount.api_func.functype,
-                                      bf_segcount.api_func.get_wrapper(space))
+    c_buf.c_bf_getsegcount = llslot(space, bf_segcount)
     if space.is_w(w_type, space.w_bytes):
         # Special case: str doesn't support get_raw_address(), so we have a
         # custom get*buffer that instead gives the address of the char* in the
         # PyBytesObject*!
-        c_buf.c_bf_getreadbuffer = llhelper(
-            str_getreadbuffer.api_func.functype,
-            str_getreadbuffer.api_func.get_wrapper(space))
-        c_buf.c_bf_getcharbuffer = llhelper(
-            str_getcharbuffer.api_func.functype,
-            str_getcharbuffer.api_func.get_wrapper(space))
+        c_buf.c_bf_getreadbuffer = llslot(space, str_getreadbuffer)
+        c_buf.c_bf_getcharbuffer = llslot(space, str_getcharbuffer)
     elif space.is_w(w_type, space.w_unicode):
         # Special case: unicode doesn't support get_raw_address(), so we have a
         # custom get*buffer that instead gives the address of the char* in the
         # PyUnicodeObject*!
-        c_buf.c_bf_getreadbuffer = llhelper(
-            unicode_getreadbuffer.api_func.functype,
-            unicode_getreadbuffer.api_func.get_wrapper(space))
+        c_buf.c_bf_getreadbuffer = llslot(space, unicode_getreadbuffer)
     elif space.is_w(w_type, space.w_buffer):
         # Special case: we store a permanent address on the cpyext wrapper,
         # so we'll reuse that.
         # Note: we could instead store a permanent address on the buffer 
object,
         # and use get_raw_address()
-        c_buf.c_bf_getreadbuffer = llhelper(
-            buf_getreadbuffer.api_func.functype,
-            buf_getreadbuffer.api_func.get_wrapper(space))
-        c_buf.c_bf_getcharbuffer = llhelper(
-            buf_getcharbuffer.api_func.functype,
-            buf_getcharbuffer.api_func.get_wrapper(space))
+        c_buf.c_bf_getreadbuffer = llslot(space, buf_getreadbuffer)
+        c_buf.c_bf_getcharbuffer = llslot(space, buf_getcharbuffer)
     else:
         # use get_raw_address()
-        c_buf.c_bf_getreadbuffer = llhelper(bf_getreadbuffer.api_func.functype,
-                                    
bf_getreadbuffer.api_func.get_wrapper(space))
-        c_buf.c_bf_getcharbuffer = llhelper(bf_getcharbuffer.api_func.functype,
-                                    
bf_getcharbuffer.api_func.get_wrapper(space))
+        c_buf.c_bf_getreadbuffer = llslot(space, bf_getreadbuffer)
+        c_buf.c_bf_getcharbuffer = llslot(space, bf_getcharbuffer)
         if bufspec == 'read-write':
-            c_buf.c_bf_getwritebuffer = llhelper(
-                bf_getwritebuffer.api_func.functype,
-                bf_getwritebuffer.api_func.get_wrapper(space))
+            c_buf.c_bf_getwritebuffer = llslot(space, bf_getwritebuffer)
     pto.c_tp_as_buffer = c_buf
     pto.c_tp_flags |= Py_TPFLAGS_HAVE_GETCHARBUFFER
     pto.c_tp_flags |= Py_TPFLAGS_HAVE_NEWBUFFER
@@ -697,12 +680,10 @@
     # dealloc
     if space.gettypeobject(w_type.layout.typedef) is w_type:
         # only for the exact type, like 'space.w_tuple' or 'space.w_list'
-        pto.c_tp_dealloc = typedescr.get_dealloc(space)
+        pto.c_tp_dealloc = typedescr.get_dealloc().get_llhelper(space)
     else:
         # for all subtypes, use subtype_dealloc()
-        pto.c_tp_dealloc = llhelper(
-            subtype_dealloc.api_func.functype,
-            subtype_dealloc.api_func.get_wrapper(space))
+        pto.c_tp_dealloc = llslot(space, subtype_dealloc)
     if space.is_w(w_type, space.w_bytes):
         pto.c_tp_itemsize = 1
     elif space.is_w(w_type, space.w_tuple):
@@ -710,10 +691,8 @@
     # buffer protocol
     setup_buffer_procs(space, w_type, pto)
 
-    pto.c_tp_free = llhelper(PyObject_Free.api_func.functype,
-            PyObject_Free.api_func.get_wrapper(space))
-    pto.c_tp_alloc = llhelper(PyType_GenericAlloc.api_func.functype,
-            PyType_GenericAlloc.api_func.get_wrapper(space))
+    pto.c_tp_free = llslot(space, PyObject_Free)
+    pto.c_tp_alloc = llslot(space, PyType_GenericAlloc)
     builder = space.fromcache(StaticObjectBuilder)
     if ((pto.c_tp_flags & Py_TPFLAGS_HEAPTYPE) != 0
             and builder.cpyext_type_init is None):
@@ -904,15 +883,11 @@
 
     if not pto.c_tp_setattro:
         from pypy.module.cpyext.object import PyObject_GenericSetAttr
-        pto.c_tp_setattro = llhelper(
-            PyObject_GenericSetAttr.api_func.functype,
-            PyObject_GenericSetAttr.api_func.get_wrapper(space))
+        pto.c_tp_setattro = llslot(space, PyObject_GenericSetAttr)
 
     if not pto.c_tp_getattro:
         from pypy.module.cpyext.object import PyObject_GenericGetAttr
-        pto.c_tp_getattro = llhelper(
-            PyObject_GenericGetAttr.api_func.functype,
-            PyObject_GenericGetAttr.api_func.get_wrapper(space))
+        pto.c_tp_getattro = llslot(space, PyObject_GenericGetAttr)
 
     if w_obj.is_cpytype():
         Py_DecRef(space, pto.c_tp_dict)
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
@@ -14,7 +14,28 @@
     cache.clear()
     cache = space.fromcache(MapAttrCache)
     cache.clear()
+
     rgc.collect()
+
+    # if we are running in gc.disable() mode but gc.collect() is called,
+    # we should still call the finalizers now.  We do this as an attempt
+    # to get closer to CPython's behavior: in Py3.5 some tests
+    # specifically rely on that.  This is similar to how, in CPython, an
+    # explicit gc.collect() will invoke finalizers from cycles and fully
+    # ignore the gc.disable() mode.
+    temp_reenable = not space.user_del_action.enabled_at_app_level
+    if temp_reenable:
+        enable_finalizers(space)
+    try:
+        # fetch the pending finalizers from the queue, where they are
+        # likely to have been added by rgc.collect() above, and actually
+        # run them now.  This forces them to run before this function
+        # returns, and also always in the enable_finalizers() mode.
+        space.user_del_action._run_finalizers()
+    finally:
+        if temp_reenable:
+            disable_finalizers(space)
+
     return space.newint(0)
 
 def enable(space):
diff --git a/pypy/module/gc/test/test_gc.py b/pypy/module/gc/test/test_gc.py
--- a/pypy/module/gc/test/test_gc.py
+++ b/pypy/module/gc/test/test_gc.py
@@ -70,6 +70,19 @@
         gc.enable()
         assert gc.isenabled()
 
+    def test_gc_collect_overrides_gc_disable(self):
+        import gc
+        deleted = []
+        class X(object):
+            def __del__(self):
+                deleted.append(1)
+        assert gc.isenabled()
+        gc.disable()
+        X()
+        gc.collect()
+        assert deleted == [1]
+        gc.enable()
+
 
 class AppTestGcDumpHeap(object):
     pytestmark = py.test.mark.xfail(run=False)
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
@@ -374,17 +374,7 @@
     def test_sum(self):
         result = self.run("sum")
         assert result == sum(range(30))
-        self.check_vectorized(1, 1)
-
-    def define_sum():
-        return """
-        a = |30|
-        sum(a)
-        """
-    def test_sum(self):
-        result = self.run("sum")
-        assert result == sum(range(30))
-        self.check_vectorized(1, 1)
+        self.check_vectorized(1, 0)
 
     def define_sum_int():
         return """
@@ -408,7 +398,7 @@
     def test_sum_multi(self):
         result = self.run("sum_multi")
         assert result == sum(range(30)) + sum(range(60))
-        self.check_vectorized(1, 1)
+        self.check_vectorized(1, 0)
 
     def define_sum_float_to_int16():
         return """
@@ -490,7 +480,7 @@
         assert retval == sum(range(1,11))
         # check that we got only one loop
         assert len(get_stats().loops) == 1
-        self.check_vectorized(2, 1)
+        self.check_vectorized(2, 0)
 
     def test_reduce_axis_compile_only_once(self):
         self.compile_graph()
@@ -501,7 +491,7 @@
         retval = self.interp.eval_graph(self.graph, [i])
         # check that we got only one loop
         assert len(get_stats().loops) == 1
-        self.check_vectorized(3, 1)
+        self.check_vectorized(3, 0)
 
     def define_prod():
         return """
@@ -518,12 +508,10 @@
     def test_prod(self):
         result = self.run("prod")
         assert int(result) == 576
-        self.check_vectorized(1, 1)
 
     def test_prod_zero(self):
         result = self.run("prod_zero")
         assert int(result) == 0
-        self.check_vectorized(1, 1)
 
 
     def define_max():
diff --git a/pypy/module/pypyjit/test_pypy_c/test_micronumpy.py 
b/pypy/module/pypyjit/test_pypy_c/test_micronumpy.py
--- a/pypy/module/pypyjit/test_pypy_c/test_micronumpy.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_micronumpy.py
@@ -75,8 +75,6 @@
 
     arith_comb = [
         ('sum','int', 1742, 1742, 1),
-        ('sum','float', 2581, 2581, 1),
-        ('prod','float', 1, 3178, 1),
         ('prod','int', 1, 3178, 1),
         ('any','int', 1, 2239, 1),
         ('any','int', 0, 4912, 0),
diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi0/test_ffi_backend.py 
b/pypy/module/test_lib_pypy/cffi_tests/cffi0/test_ffi_backend.py
--- a/pypy/module/test_lib_pypy/cffi_tests/cffi0/test_ffi_backend.py
+++ b/pypy/module/test_lib_pypy/cffi_tests/cffi0/test_ffi_backend.py
@@ -494,3 +494,15 @@
     def test_negative_array_size(self):
         ffi = FFI()
         py.test.raises(ValueError, ffi.cast, "int[-5]", 0)
+
+    def test_cannot_instantiate_manually(self):
+        ffi = FFI()
+        ct = type(ffi.typeof("void *"))
+        py.test.raises(TypeError, ct)
+        py.test.raises(TypeError, ct, ffi.NULL)
+        for cd in [type(ffi.cast("void *", 0)),
+                   type(ffi.new("char[]", 3)),
+                   type(ffi.gc(ffi.NULL, lambda x: None))]:
+            py.test.raises(TypeError, cd)
+            py.test.raises(TypeError, cd, ffi.NULL)
+            py.test.raises(TypeError, cd, ffi.typeof("void *"))
diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_ffi_obj.py 
b/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_ffi_obj.py
--- a/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_ffi_obj.py
+++ b/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_ffi_obj.py
@@ -361,7 +361,8 @@
         retries += 1
         assert retries <= 5
         import gc; gc.collect()
-    assert seen == [40, 40, raw1, raw2]
+    assert (seen == [40, 40, raw1, raw2] or
+            seen == [40, 40, raw2, raw1])
     assert repr(seen[2]) == "<cdata 'char[]' owning 41 bytes>"
     assert repr(seen[3]) == "<cdata 'char[]' owning 41 bytes>"
 
diff --git a/pypy/module/test_lib_pypy/test_os_wait.py 
b/pypy/module/test_lib_pypy/test_os_wait.py
--- a/pypy/module/test_lib_pypy/test_os_wait.py
+++ b/pypy/module/test_lib_pypy/test_os_wait.py
@@ -34,3 +34,7 @@
         assert os.WEXITSTATUS(status) == exit_status
         assert isinstance(rusage.ru_utime, float)
         assert isinstance(rusage.ru_maxrss, int)
+
+def test_errors():
+    py.test.raises(OSError, _pypy_wait.wait3, -999)
+    py.test.raises(OSError, _pypy_wait.wait4, -999, -999)
diff --git a/pypy/objspace/std/typeobject.py b/pypy/objspace/std/typeobject.py
--- a/pypy/objspace/std/typeobject.py
+++ b/pypy/objspace/std/typeobject.py
@@ -162,7 +162,8 @@
 
     @dont_look_inside
     def __init__(self, space, name, bases_w, dict_w,
-                 overridetypedef=None, force_new_layout=False):
+                 overridetypedef=None, force_new_layout=False,
+                 is_heaptype=True):
         self.space = space
         self.name = name
         self.bases_w = bases_w
@@ -172,7 +173,7 @@
         self.weakrefable = False
         self.w_doc = space.w_None
         self.weak_subclasses = []
-        self.flag_heaptype = False
+        self.flag_heaptype = is_heaptype
         self.flag_cpytype = False
         self.flag_abstract = False
         self.flag_sequence_bug_compat = False
@@ -740,7 +741,7 @@
         dict_w[key] = space.getitem(w_dict, w_key)
     w_type = space.allocate_instance(W_TypeObject, w_typetype)
     W_TypeObject.__init__(w_type, space, name, bases_w or [space.w_object],
-                          dict_w)
+                          dict_w, is_heaptype=True)
     w_type.ready()
     return w_type
 
@@ -1136,7 +1137,6 @@
     if len(w_self.bases_w) == 0:
         w_self.bases_w = [w_self.space.w_object]
     w_bestbase = check_and_find_best_base(w_self.space, w_self.bases_w)
-    w_self.flag_heaptype = True
     for w_base in w_self.bases_w:
         if not isinstance(w_base, W_TypeObject):
             continue
@@ -1161,7 +1161,6 @@
         w_doc = w_self.space.newtext_or_none(instancetypedef.doc)
     w_self.w_doc = w_doc
     ensure_common_attributes(w_self)
-    w_self.flag_heaptype = instancetypedef.heaptype
     #
     # usually 'instancetypedef' is new, i.e. not seen in any base,
     # but not always (see Exception class)
@@ -1335,7 +1334,8 @@
         else:
             overridetypedef = typedef
         w_type = W_TypeObject(space, typedef.name, bases_w, dict_w,
-                              overridetypedef=overridetypedef)
+                              overridetypedef=overridetypedef,
+                              is_heaptype=overridetypedef.heaptype)
         if typedef is not overridetypedef:
             w_type.w_doc = space.newtext_or_none(typedef.doc)
         if hasattr(typedef, 'flag_sequence_bug_compat'):
diff --git a/rpython/jit/backend/llgraph/runner.py 
b/rpython/jit/backend/llgraph/runner.py
--- a/rpython/jit/backend/llgraph/runner.py
+++ b/rpython/jit/backend/llgraph/runner.py
@@ -1128,7 +1128,7 @@
                 value = sum(value)
             elif info.accum_operation == '*':
                 def prod(acc, x): return acc * x
-                value = reduce(prod, value, 1)
+                value = reduce(prod, value, 1.0)
             else:
                 raise NotImplementedError("accum operator in fail guard")
             values[i] = value
diff --git a/rpython/jit/backend/ppc/regalloc.py 
b/rpython/jit/backend/ppc/regalloc.py
--- a/rpython/jit/backend/ppc/regalloc.py
+++ b/rpython/jit/backend/ppc/regalloc.py
@@ -1066,7 +1066,6 @@
 
     prepare_cond_call_value_r = prepare_cond_call_value_i
 
-
 def notimplemented(self, op):
     msg = '[PPC/regalloc] %s not implemented\n' % op.getopname()
     if we_are_translated():
diff --git a/rpython/jit/backend/zarch/assembler.py 
b/rpython/jit/backend/zarch/assembler.py
--- a/rpython/jit/backend/zarch/assembler.py
+++ b/rpython/jit/backend/zarch/assembler.py
@@ -396,6 +396,7 @@
         #   * gcmap is pushed
         #   * the old value of these regs must already be stored in the 
jitframe
         #   * on exit, all registers are restored from the jitframe
+        #   * the result of the call is moved to register r1
 
         mc = InstrBuilder()
         self.mc = mc
@@ -427,6 +428,9 @@
         self._reload_frame_if_necessary(mc)
 
         self.pop_gcmap(mc) # cancel the push_gcmap(store=True) in the caller
+
+        mc.LGR(r.SCRATCH2, r.RES)
+
         self._pop_core_regs_from_jitframe(mc, saved_regs)
         if supports_floats:
             self._pop_fp_regs_from_jitframe(mc)
diff --git a/rpython/jit/backend/zarch/opassembler.py 
b/rpython/jit/backend/zarch/opassembler.py
--- a/rpython/jit/backend/zarch/opassembler.py
+++ b/rpython/jit/backend/zarch/opassembler.py
@@ -374,10 +374,12 @@
     _COND_CALL_SAVE_REGS = [r.r11, r.r2, r.r3, r.r4, r.r5]
 
     def emit_cond_call(self, op, arglocs, regalloc):
+        resloc = arglocs[0]
+        arglocs = arglocs[1:]
+
         fcond = self.guard_success_cc
         self.guard_success_cc = c.cond_none
         assert fcond.value != c.cond_none.value
-        fcond = c.negate(fcond)
 
         jmp_adr = self.mc.get_relative_pos()
         self.mc.reserve_cond_jump() # patched later to a relative branch
@@ -411,6 +413,8 @@
         self.mc.BASR(r.r14, r.r14)
         # restoring the registers saved above, and doing pop_gcmap(), is left
         # to the cond_call_slowpath helper.  We never have any result value.
+        if resloc is not None:
+            self.mc.LGR(resloc, r.SCRATCH2)
         relative_target = self.mc.currpos() - jmp_adr
         pmc = OverwritingBuilder(self.mc, jmp_adr, 1)
         pmc.BRCL(fcond, l.imm(relative_target))
@@ -419,6 +423,9 @@
         # guard_no_exception too
         self.previous_cond_call_jcond = jmp_adr, fcond
 
+    emit_cond_call_value_i = emit_cond_call
+    emit_cond_call_value_r = emit_cond_call
+
 class AllocOpAssembler(object):
     _mixin_ = True
 
diff --git a/rpython/jit/backend/zarch/regalloc.py 
b/rpython/jit/backend/zarch/regalloc.py
--- a/rpython/jit/backend/zarch/regalloc.py
+++ b/rpython/jit/backend/zarch/regalloc.py
@@ -1107,14 +1107,32 @@
 
     def prepare_cond_call(self, op):
         self.load_condition_into_cc(op.getarg(0))
-        locs = []
+        locs = [None]
+        self.assembler.guard_success_cc = c.negate(
+                self.assembler.guard_success_cc)
         # support between 0 and 4 integer arguments
         assert 2 <= op.numargs() <= 2 + 4
         for i in range(1, op.numargs()):
             loc = self.loc(op.getarg(i))
             assert loc.type != FLOAT
             locs.append(loc)
-        return locs
+        return locs # [None, function, arg0, ..., argn]
+
+    def prepare_cond_call_value_i(self, op):
+        x = self.ensure_reg(op.getarg(0))
+        self.load_condition_into_cc(op.getarg(0))
+        self.rm.force_allocate_reg(op, selected_reg=x)   # spilled if survives
+        # ^^^ if arg0!=0, we jump over the next block of code (the call)
+        locs = [x]
+        # support between 0 and 4 integer arguments
+        assert 2 <= op.numargs() <= 2 + 4
+        for i in range(1, op.numargs()):
+            loc = self.loc(op.getarg(i))
+            assert loc.type != FLOAT
+            locs.append(loc)
+        return locs     # [res, function, args...]
+
+    prepare_cond_call_value_r = prepare_cond_call_value_i
 
     def prepare_cond_call_gc_wb(self, op):
         arglocs = [self.ensure_reg(op.getarg(0))]
diff --git a/rpython/jit/codewriter/jtransform.py 
b/rpython/jit/codewriter/jtransform.py
--- a/rpython/jit/codewriter/jtransform.py
+++ b/rpython/jit/codewriter/jtransform.py
@@ -593,6 +593,8 @@
         log.WARNING('ignoring hint %r at %r' % (hints, self.graph))
 
     def _rewrite_raw_malloc(self, op, name, args):
+        # NB. the operation 'raw_malloc' is not supported; this is for
+        # the operation 'malloc'/'malloc_varsize' with {flavor: 'gc'}
         d = op.args[1].value.copy()
         d.pop('flavor')
         add_memory_pressure = d.pop('add_memory_pressure', False)
diff --git a/rpython/jit/codewriter/support.py 
b/rpython/jit/codewriter/support.py
--- a/rpython/jit/codewriter/support.py
+++ b/rpython/jit/codewriter/support.py
@@ -142,10 +142,14 @@
             assert len(lst) == len(args_v), (
                 "not supported so far: 'greens' variables contain Void")
         # a crash here means that you have to reorder the variable named in
-        # the JitDriver.  Indeed, greens and reds must both be sorted: first
-        # all INTs, followed by all REFs, followed by all FLOATs.
+        # the JitDriver.  
         lst2 = sort_vars(lst)
-        assert lst == lst2
+        assert lst == lst2, ("You have to reorder the variables named in "
+            "the JitDriver (both the 'greens' and 'reds' independently). "
+            "They must be sorted like this: first all the integer-like, "
+            "then all the pointer-like, and finally the floats.\n"
+            "Got: %r\n"
+            "Expected: %r" % (lst, lst2))
         return lst
     #
     return (_sort(greens_v, True), _sort(reds_v, False))
diff --git a/rpython/jit/metainterp/optimizeopt/schedule.py 
b/rpython/jit/metainterp/optimizeopt/schedule.py
--- a/rpython/jit/metainterp/optimizeopt/schedule.py
+++ b/rpython/jit/metainterp/optimizeopt/schedule.py
@@ -978,10 +978,7 @@
                    self.right is other.right
 
 class AccumPack(Pack):
-    SUPPORTED = { rop.FLOAT_ADD: '+',
-                  rop.INT_ADD:   '+',
-                  rop.FLOAT_MUL: '*',
-                }
+    SUPPORTED = { rop.INT_ADD: '+', }
 
     def __init__(self, nodes, operator, position):
         Pack.__init__(self, nodes)
diff --git a/rpython/jit/metainterp/optimizeopt/test/test_costmodel.py 
b/rpython/jit/metainterp/optimizeopt/test/test_costmodel.py
--- a/rpython/jit/metainterp/optimizeopt/test/test_costmodel.py
+++ b/rpython/jit/metainterp/optimizeopt/test/test_costmodel.py
@@ -197,7 +197,7 @@
         f13 = float_add(f12, f11)
         """)
         savings = self.savings(loop1)
-        assert savings == 2
+        assert savings == -2
 
     @py.test.mark.parametrize("bytes,s", [(4,0),(8,0)])
     def test_sum_float_to_int(self, bytes, s):
diff --git a/rpython/jit/metainterp/optimizeopt/test/test_vecopt.py 
b/rpython/jit/metainterp/optimizeopt/test/test_vecopt.py
--- a/rpython/jit/metainterp/optimizeopt/test/test_vecopt.py
+++ b/rpython/jit/metainterp/optimizeopt/test/test_vecopt.py
@@ -1162,32 +1162,32 @@
         vopt = self.vectorize(loop,1)
         self.assert_equal(loop, self.parse_loop(opt))
 
-    def test_accumulate_basic(self):
-        trace = """
-        [p0, i0, f0]
-        f1 = raw_load_f(p0, i0, descr=floatarraydescr)
-        f2 = float_add(f0, f1)
-        i1 = int_add(i0, 8)
-        i2 = int_lt(i1, 100)
-        guard_true(i2) [p0, i0, f2]
-        jump(p0, i1, f2)
-        """
-        trace_opt = """
-        [p0, i0, f0]
-        v6[0xf64] = vec_f()
-        v7[2xf64] = vec_float_xor(v6[0xf64], v6[0xf64])
-        v2[2xf64] = vec_pack_f(v7[2xf64], f0, 0, 1)
-        label(p0, i0, v2[2xf64])
-        i1 = int_add(i0, 16)
-        i2 = int_lt(i1, 100)
-        guard_true(i2) [p0, i0, v2[2xf64]]
-        v1[2xf64] = vec_load_f(p0, i0, 1, 0, descr=floatarraydescr)
-        v3[2xf64] = vec_float_add(v2[2xf64], v1[2xf64])
-        jump(p0, i1, v3[2xf64])
-        """
-        loop = self.parse_loop(trace)
-        opt = self.vectorize(loop)
-        self.assert_equal(loop, self.parse_loop(trace_opt))
+    #def test_accumulate_basic(self):
+    #    trace = """
+    #    [p0, i0, f0]
+    #    f1 = raw_load_f(p0, i0, descr=floatarraydescr)
+    #    f2 = float_add(f0, f1)
+    #    i1 = int_add(i0, 8)
+    #    i2 = int_lt(i1, 100)
+    #    guard_true(i2) [p0, i0, f2]
+    #    jump(p0, i1, f2)
+    #    """
+    #    trace_opt = """
+    #    [p0, i0, f0]
+    #    v6[0xf64] = vec_f()
+    #    v7[2xf64] = vec_float_xor(v6[0xf64], v6[0xf64])
+    #    v2[2xf64] = vec_pack_f(v7[2xf64], f0, 0, 1)
+    #    label(p0, i0, v2[2xf64])
+    #    i1 = int_add(i0, 16)
+    #    i2 = int_lt(i1, 100)
+    #    guard_true(i2) [p0, i0, v2[2xf64]]
+    #    v1[2xf64] = vec_load_f(p0, i0, 1, 0, descr=floatarraydescr)
+    #    v3[2xf64] = vec_float_add(v2[2xf64], v1[2xf64])
+    #    jump(p0, i1, v3[2xf64])
+    #    """
+    #    loop = self.parse_loop(trace)
+    #    opt = self.vectorize(loop)
+    #    self.assert_equal(loop, self.parse_loop(trace_opt))
 
     def test_element_f45_in_guard_failargs(self):
         trace = self.parse_loop("""
diff --git a/rpython/jit/metainterp/optimizeopt/vector.py 
b/rpython/jit/metainterp/optimizeopt/vector.py
--- a/rpython/jit/metainterp/optimizeopt/vector.py
+++ b/rpython/jit/metainterp/optimizeopt/vector.py
@@ -842,11 +842,16 @@
                 oplist.append(vecop)
                 opnum = rop.VEC_INT_XOR
                 if datatype == FLOAT:
-                    opnum = rop.VEC_FLOAT_XOR
+                    # see PRECISION loss below
+                    raise NotImplementedError
                 vecop = VecOperation(opnum, [vecop, vecop],
                                      vecop, count)
                 oplist.append(vecop)
             elif pack.reduce_init() == 1:
+                # PRECISION loss, because the numbers are accumulated 
(associative, commutative properties must hold)
+                # you can end up a small number and a huge number that is 
finally multiplied. giving an
+                # inprecision result, thus this is disabled now
+                raise NotImplementedError
                 # multiply is only supported by floats
                 vecop = OpHelpers.create_vec_expand(ConstFloat(1.0), bytesize,
                                                     signed, count)
diff --git a/rpython/jit/metainterp/test/test_vector.py 
b/rpython/jit/metainterp/test/test_vector.py
--- a/rpython/jit/metainterp/test/test_vector.py
+++ b/rpython/jit/metainterp/test/test_vector.py
@@ -414,7 +414,9 @@
                              lambda a,b: 
lltype.intmask(lltype.intmask(a)+lltype.intmask(b)), lltype.Signed)
     small_floats = st.floats(min_value=-100, max_value=100, allow_nan=False, 
allow_infinity=False)
     test_vec_float_sum = vec_reduce(small_floats, lambda a,b: a+b, rffi.DOUBLE)
-    test_vec_float_prod = vec_reduce(small_floats, lambda a,b: a*b, 
rffi.DOUBLE)
+    # PRECISION loss, because the numbers are accumulated (associative, 
commutative properties must hold)
+    # you can end up a small number and a huge number that is finally 
multiplied losing precision
+    # test_vec_float_prod = vec_reduce(small_floats, lambda a,b: a*b, 
rffi.DOUBLE)
 
 
     def test_constant_expand(self):
diff --git a/rpython/memory/gctransform/transform.py 
b/rpython/memory/gctransform/transform.py
--- a/rpython/memory/gctransform/transform.py
+++ b/rpython/memory/gctransform/transform.py
@@ -427,6 +427,13 @@
         return result
     mh._ll_malloc_fixedsize = _ll_malloc_fixedsize
 
+    def _ll_malloc_fixedsize_zero(size):
+        result = mh.allocate(size, zero=True)
+        if not result:
+            raise MemoryError()
+        return result
+    mh._ll_malloc_fixedsize_zero = _ll_malloc_fixedsize_zero
+
     def _ll_compute_size(length, size, itemsize):
         try:
             varsize = ovfcheck(itemsize * length)
@@ -453,10 +460,9 @@
 
     def _ll_malloc_varsize_no_length_zero(length, size, itemsize):
         tot_size = _ll_compute_size(length, size, itemsize)
-        result = mh.allocate(tot_size)
+        result = mh.allocate(tot_size, zero=True)
         if not result:
             raise MemoryError()
-        llmemory.raw_memclear(result, tot_size)
         return result
     mh.ll_malloc_varsize_no_length_zero = _ll_malloc_varsize_no_length_zero
 
@@ -470,17 +476,16 @@
         mh = mallocHelpers()
         mh.allocate = llmemory.raw_malloc
         ll_raw_malloc_fixedsize = mh._ll_malloc_fixedsize
+        ll_raw_malloc_fixedsize_zero = mh._ll_malloc_fixedsize_zero
         ll_raw_malloc_varsize_no_length = mh.ll_malloc_varsize_no_length
         ll_raw_malloc_varsize = mh.ll_malloc_varsize
         ll_raw_malloc_varsize_no_length_zero  = 
mh.ll_malloc_varsize_no_length_zero
 
-        stack_mh = mallocHelpers()
-        stack_mh.allocate = lambda size: llop.stack_malloc(llmemory.Address, 
size)
-        ll_stack_malloc_fixedsize = stack_mh._ll_malloc_fixedsize
-
         if self.translator:
             self.raw_malloc_fixedsize_ptr = self.inittime_helper(
                 ll_raw_malloc_fixedsize, [lltype.Signed], llmemory.Address)
+            self.raw_malloc_fixedsize_zero_ptr = self.inittime_helper(
+                ll_raw_malloc_fixedsize_zero, [lltype.Signed], 
llmemory.Address)
             self.raw_malloc_varsize_no_length_ptr = self.inittime_helper(
                 ll_raw_malloc_varsize_no_length, [lltype.Signed]*3, 
llmemory.Address, inline=False)
             self.raw_malloc_varsize_ptr = self.inittime_helper(
@@ -488,9 +493,6 @@
             self.raw_malloc_varsize_no_length_zero_ptr = self.inittime_helper(
                 ll_raw_malloc_varsize_no_length_zero, [lltype.Signed]*3, 
llmemory.Address, inline=False)
 
-            self.stack_malloc_fixedsize_ptr = self.inittime_helper(
-                ll_stack_malloc_fixedsize, [lltype.Signed], llmemory.Address)
-
     def gct_malloc(self, hop, add_flags=None):
         TYPE = hop.spaceop.result.concretetype.TO
         assert not TYPE._is_varsize()
@@ -503,21 +505,16 @@
         hop.cast_result(v_raw)
 
     def gct_fv_raw_malloc(self, hop, flags, TYPE, c_size):
-        v_raw = hop.genop("direct_call", [self.raw_malloc_fixedsize_ptr, 
c_size],
+        if flags.get('zero'):
+            ll_func = self.raw_malloc_fixedsize_zero_ptr
+        else:
+            ll_func = self.raw_malloc_fixedsize_ptr
+        v_raw = hop.genop("direct_call", [ll_func, c_size],
                           resulttype=llmemory.Address)
-        if flags.get('zero'):
-            hop.genop("raw_memclear", [v_raw, c_size])
         if flags.get('track_allocation', True):
             hop.genop("track_alloc_start", [v_raw])
         return v_raw
 
-    def gct_fv_stack_malloc(self, hop, flags, TYPE, c_size):
-        v_raw = hop.genop("direct_call", [self.stack_malloc_fixedsize_ptr, 
c_size],
-                          resulttype=llmemory.Address)
-        if flags.get('zero'):
-            hop.genop("raw_memclear", [v_raw, c_size])
-        return v_raw
-
     def gct_malloc_varsize(self, hop, add_flags=None):
         flags = hop.spaceop.args[1].value
         if add_flags:
diff --git a/rpython/rlib/rposix.py b/rpython/rlib/rposix.py
--- a/rpython/rlib/rposix.py
+++ b/rpython/rlib/rposix.py
@@ -1778,25 +1778,23 @@
     finally:
         lltype.free(l_utsbuf, flavor='raw')
 
-# These are actually macros on some/most systems
-c_makedev = external('makedev', [rffi.INT, rffi.INT], rffi.INT)
-c_major = external('major', [rffi.INT], rffi.INT)
-c_minor = external('minor', [rffi.INT], rffi.INT)
+if sys.platform != 'win32':
+    # These are actually macros on some/most systems
+    c_makedev = external('makedev', [rffi.INT, rffi.INT], rffi.INT, macro=True)
+    c_major = external('major', [rffi.INT], rffi.INT, macro=True)
+    c_minor = external('minor', [rffi.INT], rffi.INT, macro=True)
 
-@replace_os_function('makedev')
-@jit.dont_look_inside
-def makedev(maj, min):
-    return c_makedev(maj, min)
+    @replace_os_function('makedev')
+    def makedev(maj, min):
+        return c_makedev(maj, min)
 
-@replace_os_function('major')
-@jit.dont_look_inside
-def major(dev):
-    return c_major(dev)
+    @replace_os_function('major')
+    def major(dev):
+        return c_major(dev)
 
-@replace_os_function('minor')
-@jit.dont_look_inside
-def minor(dev):
-    return c_minor(dev)
+    @replace_os_function('minor')
+    def minor(dev):
+        return c_minor(dev)
 
 #___________________________________________________________________
 
diff --git a/rpython/rlib/rsocket.py b/rpython/rlib/rsocket.py
--- a/rpython/rlib/rsocket.py
+++ b/rpython/rlib/rsocket.py
@@ -398,7 +398,7 @@
             baseofs = offsetof(_c.sockaddr_un, 'c_sun_path')
             self.setdata(sun, baseofs + len(path))
             rffi.setintfield(sun, 'c_sun_family', AF_UNIX)
-            if _c.linux and path.startswith('\x00'):
+            if _c.linux and path[0] == '\x00':
                 # Linux abstract namespace extension
                 if len(path) > sizeof(_c.sockaddr_un.c_sun_path):
                     raise RSocketError("AF_UNIX path too long")
diff --git a/rpython/rlib/runicode.py b/rpython/rlib/runicode.py
--- a/rpython/rlib/runicode.py
+++ b/rpython/rlib/runicode.py
@@ -327,6 +327,16 @@
 
 def unicode_encode_utf_8(s, size, errors, errorhandler=None,
                          allow_surrogates=allow_surrogate_by_default):
+    # In this function, allow_surrogates can be:
+    #
+    #  * True:  surrogates are always allowed.  A valid surrogate pair
+    #           is replaced with the non-BMP unicode char it stands for,
+    #           which is then encoded as 4 bytes.
+    #
+    #  * False: surrogates are always forbidden.
+    #
+    # See also unicode_encode_utf8sp().
+    #
     if errorhandler is None:
         errorhandler = default_unicode_error_encode
     return unicode_encode_utf_8_impl(s, size, errors, errorhandler,
@@ -391,6 +401,33 @@
                 _encodeUCS4(result, ch)
     return result.build()
 
+def unicode_encode_utf8sp(s, size):
+    # Surrogate-preserving utf-8 encoding.  Any surrogate character
+    # turns into its 3-bytes encoding, whether it is paired or not.
+    # This should always be reversible, and the reverse is the regular
+    # str_decode_utf_8() with allow_surrogates=True.
+    assert(size >= 0)
+    result = StringBuilder(size)
+    pos = 0
+    while pos < size:
+        ch = ord(s[pos])
+        pos += 1
+        if ch < 0x80:
+            # Encode ASCII
+            result.append(chr(ch))
+        elif ch < 0x0800:
+            # Encode Latin-1
+            result.append(chr((0xc0 | (ch >> 6))))
+            result.append(chr((0x80 | (ch & 0x3f))))
+        elif ch < 0x10000:
+            # Encode UCS2 Unicode ordinals, and surrogates
+            result.append((chr((0xe0 | (ch >> 12)))))
+            result.append((chr((0x80 | ((ch >> 6) & 0x3f)))))
+            result.append((chr((0x80 | (ch & 0x3f)))))
+        else:
+            _encodeUCS4(result, ch)
+    return result.build()
+
 # ____________________________________________________________
 # utf-16
 
diff --git a/rpython/rlib/test/test_rposix.py b/rpython/rlib/test/test_rposix.py
--- a/rpython/rlib/test/test_rposix.py
+++ b/rpython/rlib/test/test_rposix.py
@@ -281,6 +281,12 @@
     def test_isatty(self):
         assert rposix.isatty(-1) is False
 
+    @py.test.mark.skipif("not hasattr(rposix, 'makedev')")
+    def test_makedev(self):
+        dev = rposix.makedev(24, 7)
+        assert rposix.major(dev) == 24
+        assert rposix.minor(dev) == 7
+
 
 @py.test.mark.skipif("not hasattr(os, 'ttyname')")
 class TestOsExpect(ExpectTest):
diff --git a/rpython/rlib/test/test_runicode.py 
b/rpython/rlib/test/test_runicode.py
--- a/rpython/rlib/test/test_runicode.py
+++ b/rpython/rlib/test/test_runicode.py
@@ -812,6 +812,21 @@
         py.test.raises(UnicodeEncodeError, encoder, u' 12, \u1234 ', 7, None)
         assert encoder(u'u\u1234', 2, 'replace') == 'u?'
 
+    def test_encode_utf8sp(self):
+        # for the following test, go to lengths to avoid CPython's optimizer
+        # and .pyc file storage, which collapse the two surrogates into one
+        c = u"\udc00"
+        for input, expected in [
+                (u"", ""),
+                (u"abc", "abc"),
+                (u"\u1234", "\xe1\x88\xb4"),
+                (u"\ud800", "\xed\xa0\x80"),
+                (u"\udc00", "\xed\xb0\x80"),
+                (u"\ud800" + c, "\xed\xa0\x80\xed\xb0\x80"),
+            ]:
+            got = runicode.unicode_encode_utf8sp(input, len(input))
+            assert got == expected
+
 
 class TestTranslation(object):
     def setup_class(cls):
diff --git a/rpython/rtyper/llinterp.py b/rpython/rtyper/llinterp.py
--- a/rpython/rtyper/llinterp.py
+++ b/rpython/rtyper/llinterp.py
@@ -997,11 +997,14 @@
     # __________________________________________________________
     # operations on addresses
 
-    def op_raw_malloc(self, size):
+    def op_raw_malloc(self, size, zero):
+        assert lltype.typeOf(size) == lltype.Signed
+        return llmemory.raw_malloc(size, zero=zero)
+
+    def op_boehm_malloc(self, size):
         assert lltype.typeOf(size) == lltype.Signed
         return llmemory.raw_malloc(size)
-
-    op_boehm_malloc = op_boehm_malloc_atomic = op_raw_malloc
+    op_boehm_malloc_atomic = op_boehm_malloc
 
     def op_boehm_register_finalizer(self, p, finalizer):
         pass
@@ -1069,9 +1072,6 @@
             assert offset.TYPE == ARGTYPE
             getattr(addr, str(ARGTYPE).lower())[offset.repeat] = value
 
-    def op_stack_malloc(self, size): # mmh
-        raise NotImplementedError("backend only")
-
     def op_track_alloc_start(self, addr):
         # we don't do tracking at this level
         checkadr(addr)
diff --git a/rpython/rtyper/lltypesystem/llarena.py 
b/rpython/rtyper/lltypesystem/llarena.py
--- a/rpython/rtyper/lltypesystem/llarena.py
+++ b/rpython/rtyper/lltypesystem/llarena.py
@@ -506,13 +506,17 @@
 
 llimpl_malloc = rffi.llexternal('malloc', [lltype.Signed], llmemory.Address,
                                 sandboxsafe=True, _nowrapper=True)
+llimpl_calloc = rffi.llexternal('calloc', [lltype.Signed, lltype.Signed],
+                                llmemory.Address,
+                                sandboxsafe=True, _nowrapper=True)
 llimpl_free = rffi.llexternal('free', [llmemory.Address], lltype.Void,
                               sandboxsafe=True, _nowrapper=True)
 
 def llimpl_arena_malloc(nbytes, zero):
-    addr = llimpl_malloc(nbytes)
-    if bool(addr):
-        llimpl_arena_reset(addr, nbytes, zero)
+    if zero:
+        addr = llimpl_calloc(nbytes, 1)
+    else:
+        addr = llimpl_malloc(nbytes)
     return addr
 llimpl_arena_malloc._always_inline_ = True
 register_external(arena_malloc, [int, int], llmemory.Address,
diff --git a/rpython/rtyper/lltypesystem/llmemory.py 
b/rpython/rtyper/lltypesystem/llmemory.py
--- a/rpython/rtyper/lltypesystem/llmemory.py
+++ b/rpython/rtyper/lltypesystem/llmemory.py
@@ -7,6 +7,7 @@
 import weakref
 from rpython.annotator.bookkeeper import analyzer_for
 from rpython.annotator.model import SomeInteger, SomeObject, SomeString, s_Bool
+from rpython.annotator.model import SomeBool
 from rpython.rlib.objectmodel import Symbolic, specialize
 from rpython.rtyper.lltypesystem import lltype
 from rpython.rtyper.lltypesystem.lltype import SomePtr
@@ -936,14 +937,15 @@
 
 # ____________________________________________________________
 
-def raw_malloc(size):
+def raw_malloc(size, zero=False):
     if not isinstance(size, AddressOffset):
         raise NotImplementedError(size)
-    return size._raw_malloc([], zero=False)
+    return size._raw_malloc([], zero=zero)
 
 @analyzer_for(raw_malloc)
-def ann_raw_malloc(s_size):
+def ann_raw_malloc(s_size, s_zero=None):
     assert isinstance(s_size, SomeInteger)  # XXX add noneg...?
+    assert s_zero is None or isinstance(s_zero, SomeBool)
     return SomeAddress()
 
 
diff --git a/rpython/rtyper/lltypesystem/lloperation.py 
b/rpython/rtyper/lltypesystem/lloperation.py
--- a/rpython/rtyper/lltypesystem/lloperation.py
+++ b/rpython/rtyper/lltypesystem/lloperation.py
@@ -396,7 +396,6 @@
     'raw_store':            LLOp(canrun=True),
     'bare_raw_store':       LLOp(),
     'gc_load_indexed':      LLOp(sideeffects=False, canrun=True),
-    'stack_malloc':         LLOp(), # mmh
     'track_alloc_start':    LLOp(),
     'track_alloc_stop':     LLOp(),
     'adr_add':              LLOp(canfold=True),
diff --git a/rpython/rtyper/rbuiltin.py b/rpython/rtyper/rbuiltin.py
--- a/rpython/rtyper/rbuiltin.py
+++ b/rpython/rtyper/rbuiltin.py
@@ -574,10 +574,14 @@
 # memory addresses
 
 @typer_for(llmemory.raw_malloc)
-def rtype_raw_malloc(hop):
-    v_size, = hop.inputargs(lltype.Signed)
+def rtype_raw_malloc(hop, i_zero=None):
+    v_size = hop.inputarg(lltype.Signed, arg=0)
+    v_zero, = parse_kwds(hop, (i_zero, None))
+    if v_zero is None:
+        v_zero = hop.inputconst(lltype.Bool, False)
     hop.exception_cannot_occur()
-    return hop.genop('raw_malloc', [v_size], resulttype=llmemory.Address)
+    return hop.genop('raw_malloc', [v_size, v_zero],
+                     resulttype=llmemory.Address)
 
 @typer_for(llmemory.raw_malloc_usage)
 def rtype_raw_malloc_usage(hop):
diff --git a/rpython/rtyper/test/test_llinterp.py 
b/rpython/rtyper/test/test_llinterp.py
--- a/rpython/rtyper/test/test_llinterp.py
+++ b/rpython/rtyper/test/test_llinterp.py
@@ -372,19 +372,6 @@
             result = interpret(getids, [i, j])
             assert result
 
-def test_stack_malloc():
-    py.test.skip("stack-flavored mallocs no longer supported")
-    class A(object):
-        pass
-    def f():
-        a = A()
-        a.i = 1
-        return a.i
-    interp, graph = get_interpreter(f, [])
-    graph.startblock.operations[0].args[1] = inputconst(Void, {'flavor': 
"stack"})
-    result = interp.eval_graph(graph, [])
-    assert result == 1
-
 def test_invalid_stack_access():
     py.test.skip("stack-flavored mallocs no longer supported")
     class A(object):
diff --git a/rpython/translator/c/funcgen.py b/rpython/translator/c/funcgen.py
--- a/rpython/translator/c/funcgen.py
+++ b/rpython/translator/c/funcgen.py
@@ -608,16 +608,6 @@
         return 'GC_REGISTER_FINALIZER(%s, (GC_finalization_proc)%s, NULL, 
NULL, NULL);' \
                % (self.expr(op.args[0]), self.expr(op.args[1]))
 
-    def OP_RAW_MALLOC(self, op):
-        eresult = self.expr(op.result)
-        esize = self.expr(op.args[0])
-        return "OP_RAW_MALLOC(%s, %s, void *);" % (esize, eresult)
-
-    def OP_STACK_MALLOC(self, op):
-        eresult = self.expr(op.result)
-        esize = self.expr(op.args[0])
-        return "OP_STACK_MALLOC(%s, %s, void *);" % (esize, eresult)
-
     def OP_DIRECT_FIELDPTR(self, op):
         return self.OP_GETFIELD(op, ampersand='&')
 
diff --git a/rpython/translator/c/src/mem.h b/rpython/translator/c/src/mem.h
--- a/rpython/translator/c/src/mem.h
+++ b/rpython/translator/c/src/mem.h
@@ -8,11 +8,14 @@
 #define OP_STACK_CURRENT(r)  r = (Signed)&r
 
 
-#define OP_RAW_MALLOC(size, r, restype)  {                             \
-       r = (restype) malloc(size);                             \
-       if (r != NULL) {                                                \
-           COUNT_MALLOC;                                               \
-       }                                                               \
+#define OP_RAW_MALLOC(size, zero, result)  {    \
+        if (zero)                               \
+            result = calloc(size, 1);           \
+        else                                    \
+            result = malloc(size);              \
+        if (result != NULL) {                   \
+            COUNT_MALLOC;                       \
+        }                                       \
     }
 
 #define OP_RAW_FREE(p, r) free(p); COUNT_FREE;
@@ -26,10 +29,6 @@
 #define alloca  _alloca
 #endif
 
-#define OP_STACK_MALLOC(size,r,restype)                                 \
-    r = (restype) alloca(size);                                         \
-    if (r != NULL) memset((void*) r, 0, size);
-    
 #define OP_RAW_MEMCOPY(x,y,size,r) memcpy(y,x,size);
 #define OP_RAW_MEMMOVE(x,y,size,r) memmove(y,x,size);
 
diff --git a/rpython/translator/c/test/test_lladdresses.py 
b/rpython/translator/c/test/test_lladdresses.py
--- a/rpython/translator/c/test/test_lladdresses.py
+++ b/rpython/translator/c/test/test_lladdresses.py
@@ -32,7 +32,29 @@
     assert res == 42
     res = fc(1)
     assert res == 1
-    
+
+def test_memory_access_zero():
+    def f():
+        blocks = []
+        for i in range(1000):
+            addr = raw_malloc(16, zero=False)
+            addr.signed[1] = 10000 + i
+            blocks.append(addr)
+        for addr in blocks:
+            raw_free(addr)
+        result = 0
+        blocks = []
+        for i in range(1000):
+            addr = raw_malloc(16, zero=True)
+            result |= addr.signed[1]
+            blocks.append(addr)
+        for addr in blocks:
+            raw_free(addr)
+        return result
+    fc = compile(f, [])
+    res = fc()
+    assert res == 0
+
 def test_memory_float():
     S = lltype.GcStruct("S", ("x", lltype.Float), ("y", lltype.Float))
     offset = FieldOffset(S, 'x')
@@ -155,18 +177,6 @@
     fn = compile(f, [int])
     assert fn(1) == 2
 
-def test_flavored_malloc_stack():
-    class A(object):
-        _alloc_flavor_ = "stack"
-        def __init__(self, val):
-            self.val = val
-    def f(x):
-        a = A(x + 1)
-        result = a.val
-        return result
-    fn = compile(f, [int])
-    assert fn(1) == 2
-
 def test_gcref():
     if sys.platform == 'darwin':
         py.test.skip("'boehm' may crash")
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to