Author: Ronan Lamy <ronan.l...@gmail.com>
Branch: py3k
Changeset: r84911:b56f881df46b
Date: 2016-06-03 19:55 +0100
http://bitbucket.org/pypy/pypy/changeset/b56f881df46b/

Log:    hg merge default (f731f9ef48f8)

diff --git a/pypy/doc/release-pypy2.7-v5.3.0.rst 
b/pypy/doc/release-pypy2.7-v5.3.0.rst
new file mode 100644
--- /dev/null
+++ b/pypy/doc/release-pypy2.7-v5.3.0.rst
@@ -0,0 +1,139 @@
+============
+PyPy2.7 v5.3
+============
+
+We have released PyPy2.7 v5.3, about six weeks after PyPy 5.1. 
+This release includes further improvements for the CAPI compatibility layer
+which we call cpyext. In addtion to complete support for lxml, we now pass
+most (more than 90%) of the upstream numpy test suite, and much of SciPy is
+supported as well.
+
+We also improved the speed of ... and ...
+
+We updated cffi_ to ...
+
+You can download the PyPy2.7 v5.3 release here:
+
+    http://pypy.org/download.html
+
+We would like to thank our donors for the continued support of the PyPy
+project.
+
+We would also like to thank our contributors and
+encourage new people to join the project. PyPy has many
+layers and we need help with all of them: `PyPy`_ and `RPython`_ documentation
+improvements, tweaking popular `modules`_ to run on pypy, or general `help`_
+with making RPython's JIT even better.
+
+.. _`PyPy`: http://doc.pypy.org
+.. _`RPython`: https://rpython.readthedocs.org
+.. _`modules`: 
http://doc.pypy.org/en/latest/project-ideas.html#make-more-python-modules-pypy-friendly
+.. _`help`: http://doc.pypy.org/en/latest/project-ideas.html
+.. _`numpy`: https://bitbucket.org/pypy/numpy
+.. _cffi: https://cffi.readthedocs.org
+.. _`fully support for the IBM s390x`: 
http://morepypy.blogspot.com/2016/04/pypy-enterprise-edition.html
+.. _`blog post`: 
http://morepypy.blogspot.com/2016/04/warmup-improvements-more-efficient.html
+
+What is PyPy?
+=============
+
+PyPy is a very compliant Python interpreter, almost a drop-in replacement for
+CPython 2.7. It's fast (`PyPy and CPython 2.7.x`_ performance comparison)
+due to its integrated tracing JIT compiler.
+
+We also welcome developers of other
+`dynamic languages`_ to see what RPython can do for them.
+
+This release supports: 
+
+  * **x86** machines on most common operating systems
+    (Linux 32/64, Mac OS X 64, Windows 32, OpenBSD, FreeBSD),
+  
+  * newer **ARM** hardware (ARMv6 or ARMv7, with VFPv3) running Linux,
+  
+  * big- and little-endian variants of **PPC64** running Linux,
+
+  * **s390x** running Linux
+
+.. _`PyPy and CPython 2.7.x`: http://speed.pypy.org
+.. _`dynamic languages`: http://pypyjs.org
+
+Other Highlights (since 5.1 released in April 2016)
+=========================================================
+
+* New features:
+
+  * Merge a major expansion of the C-API support in cpyext, here are some of
+    the highlights:
+      - allow c-snippet tests to be run with -A so we can verify we are 
compatible
+      - fix many edge cases exposed by fixing tests to run with -A
+      - issequence() logic matches cpython
+      - make PyStringObject and PyUnicodeObject field names compatible with 
cpython
+      - add prelminary support for PyDateTime_*
+      - support PyComplexObject, PyFloatObject, PyDict_Merge, PyDictProxy,
+        PyMemoryView_*, _Py_HashDouble, PyFile_AsFile, PyFile_FromFile,
+      - PyAnySet_CheckExact, PyUnicode_Concat
+      - improve support for PyGILState_Ensure, PyGILState_Release, and thread
+        primitives, also find a case where CPython will allow thread creation
+        before PyEval_InitThreads is run, dissallow on PyPy 
+      - create a PyObject-specific list strategy
+      - rewrite slot assignment for typeobjects
+      - improve tracking of PyObject to rpython object mapping
+      - support tp_as_{number, sequence, mapping, buffer} slots
+
+  * CPyExt tweak: instead of "GIL not held when a CPython C extension module
+    calls PyXxx", we now silently acquire/release the GIL.  Helps with
+    CPython C extension modules that call some PyXxx() functions without
+    holding the GIL (arguably, they are theorically buggy).
+
+  * Add rgc.FinalizerQueue, documented in 
pypy/doc/discussion/finalizer-order.rst.
+    It is a more flexible way to make RPython finalizers. Use this mechanism to
+    clean up handling of ``__del__`` methods, fixing issue #2287
+
+  * Generalize cpyext old-style buffers to more than just str/buffer, add
+    support for mmap
+
+* Bug Fixes
+
+  * Issues reported with our previous release were resolved_ after reports 
from users on
+    our issue tracker at https://bitbucket.org/pypy/pypy/issues or on IRC at
+    #pypy
+
+* Numpy_:
+
+  * Implement ufunc.outer on numpypy
+
+* Performance improvements:
+
+  * Use bitstrings to compress lists of descriptors that are attached to an
+    EffectInfo
+
+  * Remove most of the _ovf, _zer and _val operations from RPython.  Kills
+    quite some code internally, and allows the JIT to do better
+    optimizations: for example, app-level code like ``x / 2`` or ``x % 2``
+    can now be turned into ``x >> 1`` or ``x & 1``, even if x is possibly
+    negative.
+
+
+* Internal refactorings:
+
+  * Reduce the size of generated C sources during translation by 
+    refactoring function declarations
+
+  * Remove a number of translation-time options that were not tested and
+    never used. Also fix a performance bug in the method cache
+
+  * Reduce the size of generated code by using the same function objects in
+    all generated subclasses
+
+  * Compile c snippets with -Werror, and fix warnings it exposed
+
+.. _resolved: http://doc.pypy.org/en/latest/whatsnew-5.3.0.html
+.. _Numpy: https://bitbucket.org/pypy/numpy
+
+Please update, and continue to help us make PyPy better.
+
+Cheers
+
+The PyPy Team
+
diff --git a/pypy/interpreter/astcompiler/codegen.py 
b/pypy/interpreter/astcompiler/codegen.py
--- a/pypy/interpreter/astcompiler/codegen.py
+++ b/pypy/interpreter/astcompiler/codegen.py
@@ -669,7 +669,6 @@
             self.emit_jump(ops.JUMP_FORWARD, end)
             self.use_next_block(next_except)
         self.emit_op(ops.END_FINALLY)   # this END_FINALLY will always re-raise
-        self.is_dead_code()
         self.use_next_block(otherwise)
         self.visit_sequence(tr.orelse)
         self.use_next_block(end)
diff --git a/pypy/module/cpyext/include/patchlevel.h 
b/pypy/module/cpyext/include/patchlevel.h
--- a/pypy/module/cpyext/include/patchlevel.h
+++ b/pypy/module/cpyext/include/patchlevel.h
@@ -29,8 +29,8 @@
 #define PY_VERSION             "3.3.5"
 
 /* PyPy version as a string */
-#define PYPY_VERSION "5.2.0-alpha0"
-#define PYPY_VERSION_NUM  0x05020000
+#define PYPY_VERSION "5.3.0-alpha0"
+#define PYPY_VERSION_NUM  0x05030000
 
 /* Defined to mean a PyPy where cpyext holds more regular references
    to PyObjects, e.g. staying alive as long as the internal PyPy object
diff --git a/pypy/module/sys/version.py b/pypy/module/sys/version.py
--- a/pypy/module/sys/version.py
+++ b/pypy/module/sys/version.py
@@ -10,7 +10,7 @@
 #XXX # sync CPYTHON_VERSION with patchlevel.h, package.py
 CPYTHON_API_VERSION        = 1013   #XXX # sync with include/modsupport.h
 
-PYPY_VERSION               = (5, 2, 0, "alpha", 0)    #XXX # sync patchlevel.h
+PYPY_VERSION               = (5, 3, 0, "alpha", 0)    #XXX # sync patchlevel.h
 
 
 import pypy
diff --git a/pypy/objspace/std/bytearrayobject.py 
b/pypy/objspace/std/bytearrayobject.py
--- a/pypy/objspace/std/bytearrayobject.py
+++ b/pypy/objspace/std/bytearrayobject.py
@@ -460,9 +460,8 @@
 def _hexstring_to_array(space, s):
     data = []
     length = len(s)
-    i = -2
+    i = 0
     while True:
-        i += 2
         while i < length and s[i] == ' ':
             i += 1
         if i >= length:
@@ -483,6 +482,7 @@
                         "non-hexadecimal number found in fromhex() arg at "
                         "position %d", i + 1)
         data.append(chr(top*16 + bot))
+        i += 2
     return data
 
 
diff --git a/rpython/memory/gc/base.py b/rpython/memory/gc/base.py
--- a/rpython/memory/gc/base.py
+++ b/rpython/memory/gc/base.py
@@ -184,7 +184,7 @@
     def can_move(self, addr):
         return False
 
-    def malloc_fixedsize_nonmovable(self, typeid):
+    def malloc_fixed_or_varsize_nonmovable(self, typeid, length):
         raise MemoryError
 
     def pin(self, addr):
diff --git a/rpython/memory/gc/incminimark.py b/rpython/memory/gc/incminimark.py
--- a/rpython/memory/gc/incminimark.py
+++ b/rpython/memory/gc/incminimark.py
@@ -718,8 +718,9 @@
         return llmemory.cast_adr_to_ptr(obj, llmemory.GCREF)
 
 
-    def malloc_fixedsize_nonmovable(self, typeid):
-        obj = self.external_malloc(typeid, 0, alloc_young=True)
+    def malloc_fixed_or_varsize_nonmovable(self, typeid, length):
+        # length==0 for fixedsize
+        obj = self.external_malloc(typeid, length, alloc_young=True)
         return llmemory.cast_adr_to_ptr(obj, llmemory.GCREF)
 
 
diff --git a/rpython/memory/gc/minimark.py b/rpython/memory/gc/minimark.py
--- a/rpython/memory/gc/minimark.py
+++ b/rpython/memory/gc/minimark.py
@@ -628,8 +628,9 @@
         return llmemory.cast_adr_to_ptr(obj, llmemory.GCREF)
 
 
-    def malloc_fixedsize_nonmovable(self, typeid):
-        obj = self.external_malloc(typeid, 0, alloc_young=True)
+    def malloc_fixed_or_varsize_nonmovable(self, typeid, length):
+        # length==0 for fixedsize
+        obj = self.external_malloc(typeid, length, alloc_young=True)
         return llmemory.cast_adr_to_ptr(obj, llmemory.GCREF)
 
 
diff --git a/rpython/memory/gctransform/framework.py 
b/rpython/memory/gctransform/framework.py
--- a/rpython/memory/gctransform/framework.py
+++ b/rpython/memory/gctransform/framework.py
@@ -530,9 +530,10 @@
                                              getfn(func,
                                                    [SomeAddress()],
                                                    annmodel.s_None)
-        self.malloc_nonmovable_ptr = getfn(GCClass.malloc_fixedsize_nonmovable,
-                                           [s_gc, s_typeid16],
-                                           s_gcref)
+        self.malloc_nonmovable_ptr = getfn(
+            GCClass.malloc_fixed_or_varsize_nonmovable,
+            [s_gc, s_typeid16, annmodel.SomeInteger()],
+            s_gcref)
 
         self.register_finalizer_ptr = getfn(GCClass.register_finalizer,
                                             [s_gc,
@@ -773,12 +774,16 @@
         c_has_light_finalizer = rmodel.inputconst(lltype.Bool,
                                                   has_light_finalizer)
 
+        is_varsize = op.opname.endswith('_varsize') or flags.get('varsize')
+
         if flags.get('nonmovable'):
-            assert op.opname == 'malloc'
-            assert not flags.get('varsize')
+            if not is_varsize:
+                v_length = rmodel.inputconst(lltype.Signed, 0)
+            else:
+                v_length = op.args[-1]
             malloc_ptr = self.malloc_nonmovable_ptr
-            args = [self.c_const_gc, c_type_id]
-        elif not op.opname.endswith('_varsize') and not flags.get('varsize'):
+            args = [self.c_const_gc, c_type_id, v_length]
+        elif not is_varsize:
             zero = flags.get('zero', False)
             if (self.malloc_fast_ptr is not None and
                 not c_has_finalizer.value and
diff --git a/rpython/rlib/rgc.py b/rpython/rlib/rgc.py
--- a/rpython/rlib/rgc.py
+++ b/rpython/rlib/rgc.py
@@ -1001,3 +1001,259 @@
     def specialize_call(self, hop):
         hop.exception_cannot_occur()
         return hop.genop('gc_gettypeid', hop.args_v, resulttype=lltype.Signed)
+
+# ____________________________________________________________
+
+
+class _rawptr_missing_item(object):
+    pass
+_rawptr_missing_item = _rawptr_missing_item()
+
+
+class _ResizableListSupportingRawPtr(list):
+    """Calling this class is a no-op after translation.
+
+    Before translation, it returns a new instance of
+    _ResizableListSupportingRawPtr, on which
+    rgc.nonmoving_raw_ptr_for_resizable_list() might be
+    used if needed.  For now, only supports lists of chars.
+    """
+    __slots__ = ('_raw_items',)   # either None or a rffi.CCHARP
+
+    def __init__(self, lst):
+        self._raw_items = None
+        self.__from_list(lst)
+
+    def __resize(self):
+        """Called before an operation changes the size of the list"""
+        if self._raw_items is not None:
+            list.__init__(self, self.__as_list())
+            self._raw_items = None
+
+    def __from_list(self, lst):
+        """Initialize the list from a copy of the list 'lst'."""
+        assert isinstance(lst, list)
+        for x in lst:
+            assert isinstance(x, str) and len(x) == 1
+        if self is lst:
+            return
+        if len(self) != len(lst):
+            self.__resize()
+        if self._raw_items is None:
+            list.__init__(self, lst)
+        else:
+            assert len(self) == self._raw_items._obj.getlength() == len(lst)
+            for i in range(len(self)):
+                self._raw_items[i] = lst[i]
+
+    def __as_list(self):
+        """Return a list (the same or a different one) which contains the
+        items in the regular way."""
+        if self._raw_items is None:
+            return self
+        length = self._raw_items._obj.getlength()
+        assert length == len(self)
+        return [self._raw_items[i] for i in range(length)]
+
+    def __getitem__(self, index):
+        if self._raw_items is None:
+            return list.__getitem__(self, index)
+        if index < 0:
+            index += len(self)
+        if not (0 <= index < len(self)):
+            raise IndexError
+        return self._raw_items[index]
+
+    def __setitem__(self, index, new):
+        if self._raw_items is None:
+            return list.__setitem__(self, index, new)
+        if index < 0:
+            index += len(self)
+        if not (0 <= index < len(self)):
+            raise IndexError
+        self._raw_items[index] = new
+
+    def __delitem__(self, index):
+        self.__resize()
+        list.__delitem__(self, index)
+
+    def __getslice__(self, i, j):
+        return list.__getslice__(self.__as_list(), i, j)
+
+    def __setslice__(self, i, j, new):
+        lst = self.__as_list()
+        list.__setslice__(lst, i, j, new)
+        self.__from_list(lst)
+
+    def __delslice__(self, i, j):
+        lst = self.__as_list()
+        list.__delslice__(lst, i, j)
+        self.__from_list(lst)
+
+    def __iter__(self):
+        try:
+            i = 0
+            while True:
+                yield self[i]
+                i += 1
+        except IndexError:
+            pass
+
+    def __reversed__(self):
+        i = len(self)
+        while i > 0:
+            i -= 1
+            yield self[i]
+
+    def __contains__(self, item):
+        return list.__contains__(self.__as_list(), item)
+
+    def __add__(self, other):
+        if isinstance(other, _ResizableListSupportingRawPtr):
+            other = other.__as_list()
+        return list.__add__(self.__as_list(), other)
+
+    def __radd__(self, other):
+        if isinstance(other, _ResizableListSupportingRawPtr):
+            other = other.__as_list()
+        return list.__add__(other, self.__as_list())
+
+    def __iadd__(self, other):
+        self.__resize()
+        return list.__iadd__(self, other)
+
+    def __eq__(self, other):
+        return list.__eq__(self.__as_list(), other)
+    def __ne__(self, other):
+        return list.__ne__(self.__as_list(), other)
+    def __ge__(self, other):
+        return list.__ge__(self.__as_list(), other)
+    def __gt__(self, other):
+        return list.__gt__(self.__as_list(), other)
+    def __le__(self, other):
+        return list.__le__(self.__as_list(), other)
+    def __lt__(self, other):
+        return list.__lt__(self.__as_list(), other)
+
+    def __mul__(self, other):
+        return list.__mul__(self.__as_list(), other)
+
+    def __rmul__(self, other):
+        return list.__mul__(self.__as_list(), other)
+
+    def __imul__(self, other):
+        self.__resize()
+        return list.__imul__(self, other)
+
+    def __repr__(self):
+        return '_ResizableListSupportingRawPtr(%s)' % (
+            list.__repr__(self.__as_list()),)
+
+    def append(self, object):
+        self.__resize()
+        return list.append(self, object)
+
+    def count(self, value):
+        return list.count(self.__as_list(), value)
+
+    def extend(self, iterable):
+        self.__resize()
+        return list.extend(self, iterable)
+
+    def index(self, value, *start_stop):
+        return list.index(self.__as_list(), value, *start_stop)
+
+    def insert(self, index, object):
+        self.__resize()
+        return list.insert(self, index, object)
+
+    def pop(self, *opt_index):
+        self.__resize()
+        return list.pop(self, *opt_index)
+
+    def remove(self, value):
+        self.__resize()
+        return list.remove(self, value)
+
+    def reverse(self):
+        lst = self.__as_list()
+        list.reverse(lst)
+        self.__from_list(lst)
+
+    def sort(self, *args, **kwds):
+        lst = self.__as_list()
+        list.sort(lst, *args, **kwds)
+        self.__from_list(lst)
+
+    def _nonmoving_raw_ptr_for_resizable_list(self):
+        if self._raw_items is None:
+            existing_items = list(self)
+            from rpython.rtyper.lltypesystem import lltype, rffi
+            self._raw_items = lltype.malloc(rffi.CCHARP.TO, len(self),
+                                           flavor='raw', immortal=True)
+            self.__from_list(existing_items)
+            assert self._raw_items is not None
+        return self._raw_items
+
+def resizable_list_supporting_raw_ptr(lst):
+    return _ResizableListSupportingRawPtr(lst)
+
+def nonmoving_raw_ptr_for_resizable_list(lst):
+    assert isinstance(lst, _ResizableListSupportingRawPtr)
+    return lst._nonmoving_raw_ptr_for_resizable_list()
+
+
+def _check_resizable_list_of_chars(s_list):
+    from rpython.annotator import model as annmodel
+    from rpython.rlib import debug
+    if annmodel.s_None.contains(s_list):
+        return    # "None", will likely be generalized later
+    if not isinstance(s_list, annmodel.SomeList):
+        raise Exception("not a list, got %r" % (s_list,))
+    if not isinstance(s_list.listdef.listitem.s_value,
+                      (annmodel.SomeChar, annmodel.SomeImpossibleValue)):
+        raise debug.NotAListOfChars
+    s_list.listdef.resize()    # must be resizable
+
+class Entry(ExtRegistryEntry):
+    _about_ = resizable_list_supporting_raw_ptr
+
+    def compute_result_annotation(self, s_list):
+        _check_resizable_list_of_chars(s_list)
+        return s_list
+
+    def specialize_call(self, hop):
+        hop.exception_cannot_occur()
+        return hop.inputarg(hop.args_r[0], 0)
+
+class Entry(ExtRegistryEntry):
+    _about_ = nonmoving_raw_ptr_for_resizable_list
+
+    def compute_result_annotation(self, s_list):
+        from rpython.rtyper.lltypesystem import lltype, rffi
+        from rpython.rtyper.llannotation import SomePtr
+        _check_resizable_list_of_chars(s_list)
+        return SomePtr(rffi.CCHARP)
+
+    def specialize_call(self, hop):
+        v_list = hop.inputarg(hop.args_r[0], 0)
+        hop.exception_cannot_occur()   # ignoring MemoryError
+        return hop.gendirectcall(ll_nonmovable_raw_ptr_for_resizable_list,
+                                 v_list)
+
+def ll_nonmovable_raw_ptr_for_resizable_list(ll_list):
+    from rpython.rtyper.lltypesystem import lltype, rffi
+    array = ll_list.items
+    if can_move(array):
+        length = ll_list.length
+        new_array = lltype.malloc(lltype.typeOf(ll_list).TO.items.TO, length,
+                                  nonmovable=True)
+        i = 0
+        while i < length:
+            new_array[i] = array[i]
+            i += 1
+        ll_list.items = new_array
+        array = new_array
+    ptr = lltype.direct_arrayitems(array)
+    # ptr is a Ptr(FixedSizeArray(Char, 1)).  Cast it to a rffi.CCHARP
+    return rffi.cast(rffi.CCHARP, ptr)
diff --git a/rpython/rlib/test/test_rgc.py b/rpython/rlib/test/test_rgc.py
--- a/rpython/rlib/test/test_rgc.py
+++ b/rpython/rlib/test/test_rgc.py
@@ -1,6 +1,6 @@
 from rpython.rtyper.test.test_llinterp import gengraph, interpret
 from rpython.rtyper.error import TyperError
-from rpython.rtyper.lltypesystem import lltype, llmemory
+from rpython.rtyper.lltypesystem import lltype, llmemory, rffi
 from rpython.rlib import rgc # Force registration of gc.collect
 import gc
 import py, sys
@@ -254,6 +254,153 @@
 
     assert typer.custom_trace_funcs == [(TP, trace_func)]
 
+def test_nonmoving_raw_ptr_for_resizable_list():
+    def f(n):
+        lst = ['a', 'b', 'c']
+        lst = rgc.resizable_list_supporting_raw_ptr(lst)
+        lst.append(chr(n))
+        assert lst[3] == chr(n)
+        assert lst[-1] == chr(n)
+        #
+        ptr = rgc.nonmoving_raw_ptr_for_resizable_list(lst)
+        assert lst[:] == ['a', 'b', 'c', chr(n)]
+        assert lltype.typeOf(ptr) == rffi.CCHARP
+        assert [ptr[i] for i in range(4)] == ['a', 'b', 'c', chr(n)]
+        #
+        lst[-3] = 'X'
+        assert ptr[1] == 'X'
+        ptr[2] = 'Y'
+        assert lst[-2] == 'Y'
+        #
+        addr = rffi.cast(lltype.Signed, ptr)
+        ptr = rffi.cast(rffi.CCHARP, addr)
+        rgc.collect()    # should not move lst.items
+        lst[-4] = 'g'
+        assert ptr[0] == 'g'
+        ptr[3] = 'H'
+        assert lst[-1] == 'H'
+        return lst
+    #
+    # direct untranslated run
+    lst = f(35)
+    assert isinstance(lst, rgc._ResizableListSupportingRawPtr)
+    #
+    # llinterp run
+    interpret(f, [35])
+    #
+    # compilation with the GC transformer
+    import subprocess
+    from rpython.translator.interactive import Translation
+    #
+    def main(argv):
+        f(len(argv))
+        print "OK!"
+        return 0
+    #
+    t = Translation(main, gc="incminimark")
+    t.disable(['backendopt'])
+    t.set_backend_extra_options(c_debug_defines=True)
+    exename = t.compile()
+    data = subprocess.check_output([str(exename), '.', '.', '.'])
+    assert data.strip().endswith('OK!')
+
+def test_ListSupportingRawPtr_direct():
+    lst = ['a', 'b', 'c']
+    lst = rgc.resizable_list_supporting_raw_ptr(lst)
+
+    def check_nonresizing():
+        assert lst[1] == lst[-2] == 'b'
+        lst[1] = 'X'
+        assert lst[1] == 'X'
+        lst[-1] = 'Y'
+        assert lst[1:3] == ['X', 'Y']
+        assert lst[-2:9] == ['X', 'Y']
+        lst[1:2] = 'B'
+        assert lst[:] == ['a', 'B', 'Y']
+        assert list(iter(lst)) == ['a', 'B', 'Y']
+        assert list(reversed(lst)) == ['Y', 'B', 'a']
+        assert 'B' in lst
+        assert 'b' not in lst
+        assert p[0] == 'a'
+        assert p[1] == 'B'
+        assert p[2] == 'Y'
+        assert lst + ['*'] == ['a', 'B', 'Y', '*']
+        assert ['*'] + lst == ['*', 'a', 'B', 'Y']
+        assert lst + lst == ['a', 'B', 'Y', 'a', 'B', 'Y']
+        base = ['8']
+        base += lst
+        assert base == ['8', 'a', 'B', 'Y']
+        assert lst == ['a', 'B', 'Y']
+        assert ['a', 'B', 'Y'] == lst
+        assert ['a', 'B', 'Z'] != lst
+        assert ['a', 'B', 'Z'] >  lst
+        assert ['a', 'B', 'Z'] >= lst
+        assert lst * 2 == ['a', 'B', 'Y', 'a', 'B', 'Y']
+        assert 2 * lst == ['a', 'B', 'Y', 'a', 'B', 'Y']
+        assert lst.count('B') == 1
+        assert lst.index('Y') == 2
+        lst.reverse()
+        assert lst == ['Y', 'B', 'a']
+        lst.sort()
+        assert lst == ['B', 'Y', 'a']
+        lst.sort(reverse=True)
+        assert lst == ['a', 'Y', 'B']
+        lst[1] = 'b'
+        lst[2] = 'c'
+        assert list(lst) == ['a', 'b', 'c']
+
+    p = lst
+    check_nonresizing()
+    assert lst._raw_items is None
+    lst._nonmoving_raw_ptr_for_resizable_list()
+    p = lst._raw_items
+    check_nonresizing()
+    assert lst._raw_items == p
+    assert p[0] == 'a'
+    assert p[1] == 'b'
+    assert p[2] == 'c'
+
+    def do_resizing_operation():
+        del lst[1]
+        yield ['a', 'c']
+
+        lst[:2] = ['X']
+        yield ['X', 'c']
+
+        del lst[:2]
+        yield ['c']
+
+        x = lst
+        x += ['t']
+        yield ['a', 'b', 'c', 't']
+
+        x = lst
+        x *= 3
+        yield ['a', 'b', 'c'] * 3
+
+        lst.append('f')
+        yield ['a', 'b', 'c', 'f']
+
+        lst.extend('fg')
+        yield ['a', 'b', 'c', 'f', 'g']
+
+        lst.insert(1, 'k')
+        yield ['a', 'k', 'b', 'c']
+
+        n = lst.pop(1)
+        assert n == 'b'
+        yield ['a', 'c']
+
+        lst.remove('c')
+        yield ['a', 'b']
+
+    assert lst == ['a', 'b', 'c']
+    for expect in do_resizing_operation():
+        assert lst == expect
+        assert lst._raw_items is None
+        lst = ['a', 'b', 'c']
+        lst = rgc.resizable_list_supporting_raw_ptr(lst)
+        lst._nonmoving_raw_ptr_for_resizable_list()
 
 # ____________________________________________________________
 
@@ -368,7 +515,6 @@
         assert fq._triggered == 1
 
     def test_finalizer_trigger_calls_too_much(self):
-        from rpython.rtyper.lltypesystem import lltype, rffi
         external_func = rffi.llexternal("foo", [], lltype.Void)
         # ^^^ with release_gil=True
         class X(object):
diff --git a/rpython/rtyper/lltypesystem/lltype.py 
b/rpython/rtyper/lltypesystem/lltype.py
--- a/rpython/rtyper/lltypesystem/lltype.py
+++ b/rpython/rtyper/lltypesystem/lltype.py
@@ -2174,7 +2174,8 @@
 
 
 def malloc(T, n=None, flavor='gc', immortal=False, zero=False,
-           track_allocation=True, add_memory_pressure=False):
+           track_allocation=True, add_memory_pressure=False,
+           nonmovable=False):
     assert flavor in ('gc', 'raw')
     if zero or immortal:
         initialization = 'example'
@@ -2200,7 +2201,8 @@
 
 @analyzer_for(malloc)
 def ann_malloc(s_T, s_n=None, s_flavor=None, s_zero=None,
-               s_track_allocation=None, s_add_memory_pressure=None):
+               s_track_allocation=None, s_add_memory_pressure=None,
+               s_nonmovable=None):
     assert (s_n is None or s_n.knowntype == int
             or issubclass(s_n.knowntype, base_int))
     assert s_T.is_constant()
@@ -2218,6 +2220,7 @@
         assert s_track_allocation is None or s_track_allocation.is_constant()
         assert (s_add_memory_pressure is None or
                 s_add_memory_pressure.is_constant())
+        assert s_nonmovable is None or s_nonmovable.is_constant()
         # not sure how to call malloc() for the example 'p' in the
         # presence of s_extraargs
         r = SomePtr(Ptr(s_T.const))
diff --git a/rpython/rtyper/lltypesystem/test/test_lltype.py 
b/rpython/rtyper/lltypesystem/test/test_lltype.py
--- a/rpython/rtyper/lltypesystem/test/test_lltype.py
+++ b/rpython/rtyper/lltypesystem/test/test_lltype.py
@@ -659,6 +659,7 @@
         a[3] = 30
         a[4] = 40
         b0 = direct_arrayitems(a)
+        assert typeOf(b0) == Ptr(FixedSizeArray(Signed, 1))
         b1 = direct_ptradd(b0, 1)
         b2 = direct_ptradd(b1, 1)
         b3 = direct_ptradd(b0, 3)
diff --git a/rpython/rtyper/rbuiltin.py b/rpython/rtyper/rbuiltin.py
--- a/rpython/rtyper/rbuiltin.py
+++ b/rpython/rtyper/rbuiltin.py
@@ -348,7 +348,7 @@
 
 @typer_for(lltype.malloc)
 def rtype_malloc(hop, i_flavor=None, i_zero=None, i_track_allocation=None,
-                 i_add_memory_pressure=None):
+                 i_add_memory_pressure=None, i_nonmovable=None):
     assert hop.args_s[0].is_constant()
     vlist = [hop.inputarg(lltype.Void, arg=0)]
     opname = 'malloc'
@@ -357,8 +357,10 @@
         (i_flavor, lltype.Void),
         (i_zero, None),
         (i_track_allocation, None),
-        (i_add_memory_pressure, None))
-    (v_flavor, v_zero, v_track_allocation, v_add_memory_pressure) = kwds_v
+        (i_add_memory_pressure, None),
+        (i_nonmovable, None))
+    (v_flavor, v_zero, v_track_allocation,
+     v_add_memory_pressure, v_nonmovable) = kwds_v
     flags = {'flavor': 'gc'}
     if v_flavor is not None:
         flags['flavor'] = v_flavor.value
@@ -368,6 +370,8 @@
         flags['track_allocation'] = v_track_allocation.value
     if i_add_memory_pressure is not None:
         flags['add_memory_pressure'] = v_add_memory_pressure.value
+    if i_nonmovable is not None:
+        flags['nonmovable'] = v_nonmovable
     vlist.append(hop.inputconst(lltype.Void, flags))
 
     assert 1 <= hop.nb_args <= 2
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to