Author: Armin Rigo <ar...@tunes.org>
Branch: py3.5
Changeset: r88993:28385e50deee
Date: 2016-12-10 15:10 +0100
http://bitbucket.org/pypy/pypy/changeset/28385e50deee/

Log:    hg merge default

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
@@ -47,3 +47,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/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/unicodehelper.py 
b/pypy/interpreter/unicodehelper.py
--- a/pypy/interpreter/unicodehelper.py
+++ b/pypy/interpreter/unicodehelper.py
@@ -142,6 +142,8 @@
 
 def encode_utf8(space, uni, allow_surrogates=False):
     # Note that Python3 tends to forbid lone surrogates
+    # Also, note that the two characters \d800\dc00 are considered as
+    # a paired surrogate, and turn into a single 4-byte utf8 char.
     return runicode.unicode_encode_utf_8(
         uni, len(uni), "strict",
         errorhandler=encode_error_handler(space),
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/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
@@ -145,7 +145,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()
@@ -397,7 +397,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
@@ -1132,3 +1132,38 @@
 
         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
@@ -326,6 +326,8 @@
         w_obj = W_PyCWrapperObject(space, pto, method_name, wrapper_func,
                 wrapper_func_kwds, doc, func_voidp, offset=offset)
         dict_w[method_name] = space.wrap(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)
 
@@ -461,13 +463,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)
         self.flag_cpytype = True
-        self.flag_heaptype = pto.c_tp_flags & Py_TPFLAGS_HEAPTYPE
+        self.flag_heaptype = flag_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'
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/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/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,22 +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, macro=True)
-c_major = external('major', [rffi.INT], rffi.INT, macro=True)
-c_minor = external('minor', [rffi.INT], rffi.INT, macro=True)
+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')
-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')
-def major(dev):
-    return c_major(dev)
+    @replace_os_function('major')
+    def major(dev):
+        return c_major(dev)
 
-@replace_os_function('minor')
-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/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,7 @@
     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
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