[pypy-commit] pypy numpy-dtype-refactor: merged default in

alex_gaynor noreply at buildbot.pypy.org
Wed Nov 30 16:50:48 CET 2011


Author: Alex Gaynor <alex.gaynor at gmail.com>
Branch: numpy-dtype-refactor
Changeset: r50016:26a0320190db
Date: 2011-11-30 10:48 -0500
http://bitbucket.org/pypy/pypy/changeset/26a0320190db/

Log:	merged default in

diff --git a/pypy/annotation/specialize.py b/pypy/annotation/specialize.py
--- a/pypy/annotation/specialize.py
+++ b/pypy/annotation/specialize.py
@@ -36,9 +36,7 @@
             newtup = SpaceOperation('newtuple', starargs, argscopy[-1])
             newstartblock.operations.append(newtup)
             newstartblock.closeblock(Link(argscopy, graph.startblock))
-            graph.startblock.isstartblock = False
             graph.startblock = newstartblock
-            newstartblock.isstartblock = True
             argnames = argnames + ['.star%d' % i for i in range(nb_extra_args)]
             graph.signature = Signature(argnames)
             # note that we can mostly ignore defaults: if nb_extra_args > 0, 
diff --git a/pypy/jit/codewriter/effectinfo.py b/pypy/jit/codewriter/effectinfo.py
--- a/pypy/jit/codewriter/effectinfo.py
+++ b/pypy/jit/codewriter/effectinfo.py
@@ -241,12 +241,15 @@
         return op.opname == 'jit_force_quasi_immutable'
 
 class RandomEffectsAnalyzer(BoolGraphAnalyzer):
-    def analyze_direct_call(self, graph, seen=None):
-        if hasattr(graph, "func") and hasattr(graph.func, "_ptr"):
-            if graph.func._ptr._obj.random_effects_on_gcobjs:
+    def analyze_external_call(self, op, seen=None):
+        try:
+            funcobj = op.args[0].value._obj
+            if funcobj.random_effects_on_gcobjs:
                 return True
-        return super(RandomEffectsAnalyzer, self).analyze_direct_call(graph,
-                                                                      seen)
+        except (AttributeError, lltype.DelayedPointer):
+            pass
+        return super(RandomEffectsAnalyzer, self).analyze_external_call(
+            op, seen)
 
     def analyze_simple_operation(self, op, graphinfo):
         return False
diff --git a/pypy/jit/codewriter/test/test_call.py b/pypy/jit/codewriter/test/test_call.py
--- a/pypy/jit/codewriter/test/test_call.py
+++ b/pypy/jit/codewriter/test/test_call.py
@@ -192,3 +192,21 @@
     [op] = block.operations
     call_descr = cc.getcalldescr(op)
     assert call_descr.extrainfo.has_random_effects()
+
+def test_random_effects_on_stacklet_switch():
+    from pypy.jit.backend.llgraph.runner import LLtypeCPU
+    from pypy.rlib._rffi_stacklet import switch, thread_handle, handle
+    @jit.dont_look_inside
+    def f():
+        switch(rffi.cast(thread_handle, 0), rffi.cast(handle, 0))
+
+    rtyper = support.annotate(f, [])
+    jitdriver_sd = FakeJitDriverSD(rtyper.annotator.translator.graphs[0])
+    cc = CallControl(LLtypeCPU(rtyper), jitdrivers_sd=[jitdriver_sd])
+    res = cc.find_all_graphs(FakePolicy())
+
+    [f_graph] = [x for x in res if x.func is f]
+    [block, _] = list(f_graph.iterblocks())
+    op = block.operations[-1]
+    call_descr = cc.getcalldescr(op)
+    assert call_descr.extrainfo.has_random_effects()
diff --git a/pypy/jit/codewriter/test/test_longlong.py b/pypy/jit/codewriter/test/test_longlong.py
--- a/pypy/jit/codewriter/test/test_longlong.py
+++ b/pypy/jit/codewriter/test/test_longlong.py
@@ -78,7 +78,7 @@
             oplist = tr.rewrite_operation(op)
             assert len(oplist) == 2
             assert oplist[0].opname == 'residual_call_irf_f'
-            assert oplist[0].args[0].value == 'llong_from_int'
+            assert oplist[0].args[0].value == opname.split('_')[0]+'_from_int'
             assert oplist[0].args[1] == 'calldescr-84'
             assert list(oplist[0].args[2]) == [const(0)]
             assert list(oplist[0].args[3]) == []
diff --git a/pypy/jit/metainterp/gc.py b/pypy/jit/metainterp/gc.py
--- a/pypy/jit/metainterp/gc.py
+++ b/pypy/jit/metainterp/gc.py
@@ -7,6 +7,9 @@
         self.config = config
 
 
+class GC_none(GcDescription):
+    malloc_zero_filled = True
+
 class GC_boehm(GcDescription):
     malloc_zero_filled = True
 
diff --git a/pypy/jit/metainterp/warmspot.py b/pypy/jit/metainterp/warmspot.py
--- a/pypy/jit/metainterp/warmspot.py
+++ b/pypy/jit/metainterp/warmspot.py
@@ -255,10 +255,8 @@
         s_binding = self.translator.annotator.binding
         jd._portal_args_s = [s_binding(v) for v in args]
         graph = copygraph(graph)
-        graph.startblock.isstartblock = False
         [jmpp] = find_jit_merge_points([graph])
         graph.startblock = support.split_before_jit_merge_point(*jmpp)
-        graph.startblock.isstartblock = True
         # a crash in the following checkgraph() means that you forgot
         # to list some variable in greens=[] or reds=[] in JitDriver,
         # or that a jit_merge_point() takes a constant as an argument.
diff --git a/pypy/module/micronumpy/interp_numarray.py b/pypy/module/micronumpy/interp_numarray.py
--- a/pypy/module/micronumpy/interp_numarray.py
+++ b/pypy/module/micronumpy/interp_numarray.py
@@ -1109,6 +1109,14 @@
     def debug_repr(self):
         return 'Slice(%s)' % self.parent.debug_repr()
 
+    def copy(self):
+        array = NDimArray(self.size, self.shape[:], self.find_dtype())
+        iter = self.start_iter()
+        while not iter.done():
+            array.setitem(iter.offset, self.getitem(iter.offset))
+            iter = iter.next(len(self.shape))
+        return array
+
 class NDimArray(BaseArray):
     """ A class representing contiguous array. We know that each iteration
     by say ufunc will increase the data index by one
diff --git a/pypy/module/micronumpy/test/test_numarray.py b/pypy/module/micronumpy/test/test_numarray.py
--- a/pypy/module/micronumpy/test/test_numarray.py
+++ b/pypy/module/micronumpy/test/test_numarray.py
@@ -764,6 +764,19 @@
         a[::-1] = a + a
         assert (a == [8, 6, 4, 2, 0]).all()
 
+    def test_debug_repr(self):
+        from numpypy import zeros, sin
+        a = zeros(1)
+        assert a.__debug_repr__() == 'Array'
+        assert (a + a).__debug_repr__() == 'Call2(add, Array, Array)'
+        assert (a[::2]).__debug_repr__() == 'Slice(Array)'
+        assert (a + 2).__debug_repr__() == 'Call2(add, Array, Scalar)'
+        assert (a + a.flat).__debug_repr__() == 'Call2(add, Array, FlatIter(Array))'
+        assert sin(a).__debug_repr__() == 'Call1(sin, Array)'
+        b = a + a
+        b[0] = 3
+        assert b.__debug_repr__() == 'Call2(add, forced=Array)'
+
 class AppTestMultiDim(BaseNumpyAppTest):
     def test_init(self):
         import numpypy
@@ -993,18 +1006,11 @@
         a = array([1, 2, 3])
         assert dot(a.flat, a.flat) == 14
 
-    def test_debug_repr(self):
-        from numpypy import zeros, sin
-        a = zeros(1)
-        assert a.__debug_repr__() == 'Array'
-        assert (a + a).__debug_repr__() == 'Call2(add, Array, Array)'
-        assert (a[::2]).__debug_repr__() == 'Slice(Array)'
-        assert (a + 2).__debug_repr__() == 'Call2(add, Array, Scalar)'
-        assert (a + a.flat).__debug_repr__() == 'Call2(add, Array, FlatIter(Array))'
-        assert sin(a).__debug_repr__() == 'Call1(sin, Array)'
-        b = a + a
-        b[0] = 3
-        assert b.__debug_repr__() == 'Call2(add, forced=Array)'
+    def test_slice_copy(self):
+        from numpypy import zeros
+        a = zeros((10, 10))
+        b = a[0].copy()
+        assert (b == zeros(10)).all()
 
 class AppTestSupport(BaseNumpyAppTest):
     def setup_class(cls):
diff --git a/pypy/objspace/flow/model.py b/pypy/objspace/flow/model.py
--- a/pypy/objspace/flow/model.py
+++ b/pypy/objspace/flow/model.py
@@ -38,7 +38,6 @@
     def __init__(self, name, startblock, return_var=None):
         self.name        = name    # function name (possibly mangled already)
         self.startblock  = startblock
-        self.startblock.isstartblock = True
         # build default returnblock
         self.returnblock = Block([return_var or Variable()])
         self.returnblock.operations = ()
@@ -171,11 +170,10 @@
 
 
 class Block(object):
-    __slots__ = """isstartblock inputargs operations exitswitch
+    __slots__ = """inputargs operations exitswitch
                 exits blockcolor""".split()
     
     def __init__(self, inputargs):
-        self.isstartblock = False
         self.inputargs = list(inputargs)  # mixed list of variable/const XXX 
         self.operations = []              # list of SpaceOperation(s)
         self.exitswitch = None            # a variable or
@@ -452,7 +450,6 @@
         newblock.closeblock(*newlinks)
 
     newstartblock = blockmap[graph.startblock]
-    newstartblock.isstartblock = True
     newgraph = FunctionGraph(graph.name, newstartblock)
     newgraph.returnblock = blockmap[graph.returnblock]
     newgraph.exceptblock = blockmap[graph.exceptblock]
@@ -490,7 +487,6 @@
 
 
         for block in graph.iterblocks():
-            assert bool(block.isstartblock) == (block is graph.startblock)
             assert type(block.exits) is tuple, (
                 "block.exits is a %s (closeblock() or recloseblock() missing?)"
                 % (type(block.exits).__name__,))
diff --git a/pypy/objspace/flow/test/test_checkgraph.py b/pypy/objspace/flow/test/test_checkgraph.py
--- a/pypy/objspace/flow/test/test_checkgraph.py
+++ b/pypy/objspace/flow/test/test_checkgraph.py
@@ -13,20 +13,6 @@
     py.test.raises(AssertionError, checkgraph, g)
 
 
-def test_nostartblock():
-    g = FunctionGraph("g", Block([]))
-    g.startblock.closeblock(Link([Constant(1)], g.returnblock))
-    g.startblock.isstartblock = False
-    py.test.raises(AssertionError, checkgraph, g)
-
-def test_twostartblocks():
-    g = FunctionGraph("g", Block([]))
-    b = Block([])
-    b.isstartblock = True
-    g.startblock.closeblock(Link([], b))
-    b.closeblock(Link([Constant(1)], g.returnblock))
-    py.test.raises(AssertionError, checkgraph, g)
-
 def test_exitlessblocknotexitblock():
     g = FunctionGraph("g", Block([]))
     py.test.raises(AssertionError, checkgraph, g)
diff --git a/pypy/objspace/std/listobject.py b/pypy/objspace/std/listobject.py
--- a/pypy/objspace/std/listobject.py
+++ b/pypy/objspace/std/listobject.py
@@ -50,6 +50,13 @@
     else:
         return space.fromcache(StringListStrategy)
 
+    # check for floats
+    for w_obj in list_w:
+        if not is_W_FloatObject(w_obj):
+            break
+    else:
+        return space.fromcache(FloatListStrategy)
+
     return space.fromcache(ObjectListStrategy)
 
 def is_W_IntObject(w_object):
@@ -60,7 +67,9 @@
     from pypy.objspace.std.stringobject import W_StringObject
     return type(w_object) is W_StringObject
 
-
+def is_W_FloatObject(w_object):
+    from pypy.objspace.std.floatobject import W_FloatObject
+    return type(w_object) is W_FloatObject
 
 class W_ListObject(W_AbstractListObject):
     from pypy.objspace.std.listtype import list_typedef as typedef
@@ -364,6 +373,8 @@
             strategy = self.space.fromcache(IntegerListStrategy)
         elif is_W_StringObject(w_item):
             strategy = self.space.fromcache(StringListStrategy)
+        elif is_W_FloatObject(w_item):
+            strategy = self.space.fromcache(FloatListStrategy)
         else:
             strategy = self.space.fromcache(ObjectListStrategy)
 
@@ -905,6 +916,32 @@
         if reverse:
             l.reverse()
 
+class FloatListStrategy(AbstractUnwrappedStrategy, ListStrategy):
+    _none_value = 0.0
+
+    def wrap(self, floatval):
+        return self.space.wrap(floatval)
+
+    def unwrap(self, w_float):
+        return self.space.float_w(w_float)
+
+    erase, unerase = rerased.new_erasing_pair("float")
+    erase = staticmethod(erase)
+    unerase = staticmethod(unerase)
+
+    def is_correct_type(self, w_obj):
+        return is_W_FloatObject(w_obj)
+
+    def list_is_correct_type(self, w_list):
+        return w_list.strategy is self.space.fromcache(FloatListStrategy)
+
+    def sort(self, w_list, reverse):
+        l = self.unerase(w_list.lstorage)
+        sorter = FloatSort(l, len(l))
+        sorter.sort()
+        if reverse:
+            l.reverse()
+
 class StringListStrategy(AbstractUnwrappedStrategy, ListStrategy):
     _none_value = None
 
@@ -934,6 +971,7 @@
     def getitems_str(self, w_list):
         return self.unerase(w_list.lstorage)
 
+
 # _______________________________________________________
 
 init_signature = Signature(['sequence'], None, None)
@@ -1282,6 +1320,7 @@
 
 TimSort = make_timsort_class()
 IntBaseTimSort = make_timsort_class()
+FloatBaseTimSort = make_timsort_class()
 StringBaseTimSort = make_timsort_class()
 
 class KeyContainer(baseobjspace.W_Root):
@@ -1302,6 +1341,10 @@
     def lt(self, a, b):
         return a < b
 
+class FloatSort(FloatBaseTimSort):
+    def lt(self, a, b):
+        return a < b
+
 class StringSort(StringBaseTimSort):
     def lt(self, a, b):
         return a < b
diff --git a/pypy/objspace/std/test/test_listobject.py b/pypy/objspace/std/test/test_listobject.py
--- a/pypy/objspace/std/test/test_listobject.py
+++ b/pypy/objspace/std/test/test_listobject.py
@@ -470,11 +470,17 @@
         l.extend(iter([1, 2, 3, 4]))
         assert l is l0
         assert l == [1, 1, 2, 3, 4]
+
         l = l0 = ['a']
         l.extend(iter(['b', 'c', 'd']))
         assert l == ['a', 'b', 'c', 'd']
         assert l is l0
 
+        l = l0 = [1.2]
+        l.extend(iter([2.3, 3.4, 4.5]))
+        assert l == [1.2, 2.3, 3.4, 4.5]
+        assert l is l0
+
     def test_sort(self):
         l = l0 = [1, 5, 3, 0]
         l.sort()
@@ -493,6 +499,10 @@
         l.sort(reverse=True)
         assert l == ["d", "c", "b", "a"]
 
+        l = [3.3, 2.2, 4.4, 1.1, 3.1, 5.5]
+        l.sort()
+        assert l == [1.1, 2.2, 3.1, 3.3, 4.4, 5.5]
+
     def test_sort_cmp(self):
         def lencmp(a,b): return cmp(len(a), len(b))
         l = [ 'a', 'fiver', 'tre', '' ]
@@ -546,11 +556,19 @@
         assert l[-2] == 6
         raises(IndexError, "l[len(l)]")
         raises(IndexError, "l[-len(l)-1]")
+
         l = ['a', 'b', 'c']
         assert l[0] == 'a'
         assert l[-1] == 'c'
         assert l[-2] == 'b'
         raises(IndexError, "l[len(l)]")
+
+        l = [1.1, 2.2, 3.3]
+        assert l[0] == 1.1
+        assert l[-1] == 3.3
+        assert l[-2] == 2.2
+        raises(IndexError, "l[len(l)]")
+
         l = []
         raises(IndexError, "l[1]")
 
@@ -588,6 +606,16 @@
         assert l is l0
         raises(IndexError, "del l[0]")
 
+        l = l0 = [1.1, 2.2, 3.3]
+        del l[0]
+        assert l == [2.2, 3.3]
+        del l[-1]
+        assert l == [2.2]
+        del l[-1]
+        assert l == []
+        assert l is l0
+        raises(IndexError, "del l[0]")
+
         l = range(10)
         del l[5]
         assert l == [0, 1, 2, 3, 4, 6, 7, 8, 9]
@@ -627,9 +655,15 @@
         del l[:]
         assert l is l0
         assert l == []
+
         l = ['a', 'b']
         del l[:]
         assert l == []
+
+        l = [1.1, 2.2]
+        del l[:]
+        assert l == []
+
         l = range(5)
         del l[:]
         assert l == []
@@ -640,6 +674,11 @@
         assert l is l0
         assert l == [1,2,3,4,5]
 
+        l = l0 = [1.1,2.2,3.3]
+        l += [4.4,5.5]
+        assert l is l0
+        assert l == [1.1,2.2,3.3,4.4,5.5]
+
         l = l0 = ['a', 'b', 'c']
         l1 = l[:]
         l += ['d']
@@ -697,6 +736,11 @@
         l *= -5
         assert l == []
 
+        l = l0 = [1.1, 2.2]
+        l *= 2
+        assert l is l0
+        assert l == [1.1, 2.2, 1.1, 2.2]
+
         l = range(2)
         l *= 2
         assert l == [0, 1, 0, 1]
@@ -731,6 +775,10 @@
         assert c.index(0) == 0
         raises(ValueError, c.index, 3)
 
+        c = [0.0, 2.2, 4.4]
+        assert c.index(0) == 0.0
+        raises(ValueError, c.index, 3)
+
     def test_index_cpython_bug(self):
         if self.on_cpython:
             skip("cpython has a bug here")
@@ -779,6 +827,10 @@
         l[::3] = ('a', 'b')
         assert l == ['a', 1, 2, 'b', 4, 5]
 
+        l = [0.0, 1.1, 2.2, 3.3, 4.4, 5.5]
+        l[::3] = ('a', 'b')
+        assert l == ['a', 1.1, 2.2, 'b', 4.4, 5.5]
+
     def test_setslice_with_self(self):
         l = [1,2,3,4]
         l[:] = l
@@ -835,6 +887,10 @@
         l.append("a")
         assert l == [1,2,3,"a"]
 
+        l = [1.1, 2.2, 3.3]
+        l.append(4.4)
+        assert l == [1.1, 2.2, 3.3, 4.4]
+
     def test_count(self):
         c = list('hello')
         assert c.count('l') == 2
@@ -875,6 +931,10 @@
         l.pop()
         assert l == range(9)
 
+        l = [1.1, 2.2, 3.3]
+        l.pop()
+        assert l == [1.1, 2.2]
+
         l = []
         raises(IndexError, l.pop, 0)
 
@@ -897,16 +957,19 @@
         l2 = ["1", "2", "3", "4"]
         l3 = range(5)
         l4 = [1, 2, 3, "4"]
+        l5 = [1.1, 2.2, 3.3, 4.4]
 
         raises(IndexError, l1.pop, -5)
         raises(IndexError, l2.pop, -5)
         raises(IndexError, l3.pop, -6)
         raises(IndexError, l4.pop, -5)
+        raises(IndexError, l5.pop, -5)
 
         assert l1.pop(-2) == 3
         assert l2.pop(-2) == "3"
         assert l3.pop(-2) == 3
         assert l4.pop(-2) == 3
+        assert l5.pop(-2) == 3.3
 
     def test_remove(self):
         c = list('hello world')
@@ -925,6 +988,13 @@
         l = [0, 3, 5]
         raises(ValueError, c.remove, 2)
 
+        l = [0.0, 1.1, 2.2, 3.3, 4.4]
+        l.remove(2.2)
+        assert l == [0.0, 1.1, 3.3, 4.4]
+        l = [0.0, 3.3, 5.5]
+        raises(ValueError, c.remove, 2)
+        raises(ValueError, c.remove, 2.2)
+
     def test_reverse(self):
         c = list('hello world')
         c.reverse()
diff --git a/pypy/objspace/std/test/test_liststrategies.py b/pypy/objspace/std/test/test_liststrategies.py
--- a/pypy/objspace/std/test/test_liststrategies.py
+++ b/pypy/objspace/std/test/test_liststrategies.py
@@ -1,4 +1,4 @@
-from pypy.objspace.std.listobject import W_ListObject, EmptyListStrategy, ObjectListStrategy, IntegerListStrategy, StringListStrategy, RangeListStrategy, make_range_list
+from pypy.objspace.std.listobject import W_ListObject, EmptyListStrategy, ObjectListStrategy, IntegerListStrategy, FloatListStrategy, StringListStrategy, RangeListStrategy, make_range_list
 from pypy.objspace.std import listobject
 from pypy.objspace.std.test.test_listobject import TestW_ListObject
 
@@ -15,7 +15,7 @@
     def test_empty_to_any(self):
         l = W_ListObject(self.space, [])
         assert isinstance(l.strategy, EmptyListStrategy)
-        l.append(self.space.wrap(1.))
+        l.append(self.space.wrap((1,3)))
         assert isinstance(l.strategy, ObjectListStrategy)
 
         l = W_ListObject(self.space, [])
@@ -28,6 +28,11 @@
         l.append(self.space.wrap('a'))
         assert isinstance(l.strategy, StringListStrategy)
 
+        l = W_ListObject(self.space, [])
+        assert isinstance(l.strategy, EmptyListStrategy)
+        l.append(self.space.wrap(1.2))
+        assert isinstance(l.strategy, FloatListStrategy)
+
     def test_int_to_any(self):
         l = W_ListObject(self.space, [self.space.wrap(1),self.space.wrap(2),self.space.wrap(3)])
         assert isinstance(l.strategy, IntegerListStrategy)
@@ -44,6 +49,14 @@
         l.append(self.space.wrap(3))
         assert isinstance(l.strategy, ObjectListStrategy)
 
+    def test_float_to_any(self):
+        l = W_ListObject(self.space, [self.space.wrap(1.1),self.space.wrap(2.2),self.space.wrap(3.3)])
+        assert isinstance(l.strategy, FloatListStrategy)
+        l.append(self.space.wrap(4.4))
+        assert isinstance(l.strategy, FloatListStrategy)
+        l.append(self.space.wrap("a"))
+        assert isinstance(l.strategy, ObjectListStrategy)
+
     def test_setitem(self):
         # This should work if test_listobject.py passes
         l = W_ListObject(self.space, [self.space.wrap('a'),self.space.wrap('b'),self.space.wrap('c')])
@@ -65,6 +78,12 @@
         l.setitem(0, self.space.wrap(2))
         assert isinstance(l.strategy, ObjectListStrategy)
 
+        # FloatStrategy to ObjectStrategy
+        l = W_ListObject(self.space, [self.space.wrap(1.2),self.space.wrap(2.3),self.space.wrap(3.4)])
+        assert isinstance(l.strategy, FloatListStrategy)
+        l.setitem(0, self.space.wrap("a"))
+        assert isinstance(l.strategy, ObjectListStrategy)
+
     def test_insert(self):
         # no change
         l = W_ListObject(self.space, [self.space.wrap(1),self.space.wrap(2),self.space.wrap(3)])
@@ -84,6 +103,12 @@
         l.insert(3, self.space.wrap('d'))
         assert isinstance(l.strategy, ObjectListStrategy)
 
+        # FloatStrategy
+        l = W_ListObject(self.space, [self.space.wrap(1.1),self.space.wrap(2.2),self.space.wrap(3.3)])
+        assert isinstance(l.strategy, FloatListStrategy)
+        l.insert(3, self.space.wrap('d'))
+        assert isinstance(l.strategy, ObjectListStrategy)
+
         # EmptyStrategy
         l = W_ListObject(self.space, [])
         assert isinstance(l.strategy, EmptyListStrategy)
@@ -95,7 +120,9 @@
         l.insert(0, self.space.wrap(2))
         assert isinstance(l.strategy, IntegerListStrategy)
 
-    def notest_list_empty_after_delete(self):
+    def test_list_empty_after_delete(self):
+        import py
+        py.test.skip("return to emptyliststrategy is not supported anymore")
         l = W_ListObject(self.space, [self.space.wrap(3)])
         assert isinstance(l.strategy, IntegerListStrategy)
         l.deleteitem(0)
@@ -117,21 +144,36 @@
         l.setslice(0, 1, 2, W_ListObject(self.space, [self.space.wrap(1), self.space.wrap(2), self.space.wrap(3)]))
         assert isinstance(l.strategy, IntegerListStrategy)
 
+        # IntegerStrategy to IntegerStrategy
         l = W_ListObject(self.space, [self.space.wrap(1), self.space.wrap(2), self.space.wrap(3)])
         assert isinstance(l.strategy, IntegerListStrategy)
         l.setslice(0, 1, 2, W_ListObject(self.space, [self.space.wrap(4), self.space.wrap(5), self.space.wrap(6)]))
         assert isinstance(l.strategy, IntegerListStrategy)
 
+        # ObjectStrategy to ObjectStrategy
         l = W_ListObject(self.space, [self.space.wrap(1), self.space.wrap('b'), self.space.wrap(3)])
         assert isinstance(l.strategy, ObjectListStrategy)
         l.setslice(0, 1, 2, W_ListObject(self.space, [self.space.wrap(1), self.space.wrap(2), self.space.wrap(3)]))
         assert isinstance(l.strategy, ObjectListStrategy)
 
+        # IntegerStrategy to ObjectStrategy
         l = W_ListObject(self.space, [self.space.wrap(1), self.space.wrap(2), self.space.wrap(3)])
         assert isinstance(l.strategy, IntegerListStrategy)
         l.setslice(0, 1, 2, W_ListObject(self.space, [self.space.wrap('a'), self.space.wrap('b'), self.space.wrap('c')]))
         assert isinstance(l.strategy, ObjectListStrategy)
 
+        # StringStrategy to ObjectStrategy
+        l = W_ListObject(self.space, [self.space.wrap('a'), self.space.wrap('b'), self.space.wrap('c')])
+        assert isinstance(l.strategy, StringListStrategy)
+        l.setslice(0, 1, 2, W_ListObject(self.space, [self.space.wrap(1), self.space.wrap(2), self.space.wrap(3)]))
+        assert isinstance(l.strategy, ObjectListStrategy)
+
+        # FloatStrategy to ObjectStrategy
+        l = W_ListObject(self.space, [self.space.wrap(1.1), self.space.wrap(2.2), self.space.wrap(3.3)])
+        assert isinstance(l.strategy, FloatListStrategy)
+        l.setslice(0, 1, 2, W_ListObject(self.space, [self.space.wrap('a'), self.space.wrap(2), self.space.wrap(3)]))
+        assert isinstance(l.strategy, ObjectListStrategy)
+
     def test_setslice_List(self):
 
         def wrapitems(items):
@@ -160,6 +202,11 @@
         keep_other_strategy(l, 0, 2, other.length(), other)
         assert l.strategy is self.space.fromcache(StringListStrategy)
 
+        l = W_ListObject(self.space, wrapitems([1.1, 2.2, 3.3, 4.4, 5.5]))
+        other = W_ListObject(self.space, [])
+        keep_other_strategy(l, 0, 1, l.length(), other)
+        assert l.strategy is self.space.fromcache(FloatListStrategy)
+
         l = W_ListObject(self.space, wrapitems(["a",3,"c",4,"e"]))
         other = W_ListObject(self.space, wrapitems(["a", "b", "c"]))
         keep_other_strategy(l, 0, 2, other.length(), other)
@@ -194,6 +241,11 @@
         l.extend(W_ListObject(self.space, [self.space.wrap(4), self.space.wrap(5), self.space.wrap(6)]))
         assert isinstance(l.strategy, IntegerListStrategy)
 
+        l = W_ListObject(self.space, [self.space.wrap(1.1), self.space.wrap(2.2), self.space.wrap(3.3)])
+        assert isinstance(l.strategy, FloatListStrategy)
+        l.extend(W_ListObject(self.space, [self.space.wrap(4), self.space.wrap(5), self.space.wrap(6)]))
+        assert isinstance(l.strategy, ObjectListStrategy)
+
     def test_empty_extend_with_any(self):
         empty = W_ListObject(self.space, [])
         assert isinstance(empty.strategy, EmptyListStrategy)
@@ -220,6 +272,11 @@
 
         empty = W_ListObject(self.space, [])
         assert isinstance(empty.strategy, EmptyListStrategy)
+        empty.extend(W_ListObject(self.space, [self.space.wrap(1.1), self.space.wrap(2.2), self.space.wrap(3.3)]))
+        assert isinstance(empty.strategy, FloatListStrategy)
+
+        empty = W_ListObject(self.space, [])
+        assert isinstance(empty.strategy, EmptyListStrategy)
         empty.extend(W_ListObject(self.space, []))
         assert isinstance(empty.strategy, EmptyListStrategy)
 
@@ -293,12 +350,13 @@
         l.setslice(0, 1, 3, W_ListObject(self.space, [self.space.wrap(1), self.space.wrap(2), self.space.wrap(3)]))
         assert isinstance(l.strategy, IntegerListStrategy)
 
-    def test_get_items_copy(self):
+    def test_copy_list(self):
         l1 = W_ListObject(self.space, [self.space.wrap(1), self.space.wrap(2), self.space.wrap(3)])
-        l2 = l1.getitems()
+        l2 = l1.clone()
         l2.append(self.space.wrap(4))
         assert not l2 == l1.getitems()
 
+    def test_getitems_does_not_copy_object_list(self):
         l1 = W_ListObject(self.space, [self.space.wrap(1), self.space.wrap("two"), self.space.wrap(3)])
         l2 = l1.getitems()
         l2.append(self.space.wrap("four"))
@@ -345,7 +403,6 @@
         # should not raise
         assert getslice__List_ANY_ANY(self.space, l, self.space.wrap(15), self.space.wrap(2222)).strategy == self.space.fromcache(EmptyListStrategy)
 
-
     def test_add_to_rangelist(self):
         l1 = make_range_list(self.space, 1, 1, 3)
         l2 = W_ListObject(self.space, [self.space.wrap(4), self.space.wrap(5)])
diff --git a/pypy/rlib/_stacklet_n_a.py b/pypy/rlib/_stacklet_n_a.py
--- a/pypy/rlib/_stacklet_n_a.py
+++ b/pypy/rlib/_stacklet_n_a.py
@@ -1,4 +1,5 @@
 from pypy.rlib import _rffi_stacklet as _c
+from pypy.rlib import objectmodel, debug
 from pypy.rpython.annlowlevel import llhelper
 from pypy.tool.staticmethods import StaticMethods
 
@@ -21,6 +22,9 @@
 
     def destroy(thrd, h):
         _c.destroy(thrd._thrd, h)
+        if objectmodel.we_are_translated():
+            debug.debug_print("not using a framework GC: "
+                              "stacklet_destroy() may leak")
 
     is_empty_handle = _c.is_empty_handle
 
diff --git a/pypy/rlib/jit.py b/pypy/rlib/jit.py
--- a/pypy/rlib/jit.py
+++ b/pypy/rlib/jit.py
@@ -176,7 +176,6 @@
     return decorator
 
 @oopspec("jit.isconstant(value)")
- at specialize.ll()
 def isconstant(value):
     """
     While tracing, returns whether or not the value is currently known to be
@@ -186,9 +185,9 @@
     This is for advanced usage only.
     """
     return NonConstant(False)
+isconstant._annspecialcase_ = "specialize:call_location"
 
 @oopspec("jit.isvirtual(value)")
- at specialize.ll()
 def isvirtual(value):
     """
     Returns if this value is virtual, while tracing, it's relatively
@@ -197,6 +196,7 @@
     This is for advanced usage only.
     """
     return NonConstant(False)
+isvirtual._annspecialcase_ = "specialize:call_location"
 
 class Entry(ExtRegistryEntry):
     _about_ = hint
diff --git a/pypy/rpython/memory/gctransform/asmgcroot.py b/pypy/rpython/memory/gctransform/asmgcroot.py
--- a/pypy/rpython/memory/gctransform/asmgcroot.py
+++ b/pypy/rpython/memory/gctransform/asmgcroot.py
@@ -92,7 +92,6 @@
         # make a copy of the graph that will reload the values
         graph2 = copygraph(fnptr._obj.graph)
         block2 = graph2.startblock
-        block2.isstartblock = False
         block1 = Block([])
         reloadedvars = []
         for v, c_p in zip(block2.inputargs, sra):
@@ -109,7 +108,6 @@
                                                         [w], v))
             reloadedvars.append(v)
         block1.closeblock(Link(reloadedvars, block2))
-        block1.isstartblock = True
         graph2.startblock = block1
         FUNC2 = lltype.FuncType([], FUNC1.RESULT)
         fnptr2 = lltype.functionptr(FUNC2,
diff --git a/pypy/rpython/memory/gctransform/test/test_transform.py b/pypy/rpython/memory/gctransform/test/test_transform.py
--- a/pypy/rpython/memory/gctransform/test/test_transform.py
+++ b/pypy/rpython/memory/gctransform/test/test_transform.py
@@ -102,12 +102,12 @@
         llops.genop("gc_pop_alive", [var])
 
 
-def checkblock(block, is_borrowed):
+def checkblock(block, is_borrowed, is_start_block):
     if block.operations == ():
         # a return/exception block -- don't want to think about them
         # (even though the test passes for somewhat accidental reasons)
         return
-    if block.isstartblock:
+    if is_start_block:
         refs_in = 0
     else:
         refs_in = len([v for v in block.inputargs if isinstance(v, Variable)
@@ -167,7 +167,7 @@
     if check:
         for graph, is_borrowed in graphs_borrowed.iteritems():
             for block in graph.iterblocks():
-                checkblock(block, is_borrowed)
+                checkblock(block, is_borrowed, block is graph.startblock)
     return t, transformer
 
 def getops(graph):
diff --git a/pypy/rpython/memory/gctransform/transform.py b/pypy/rpython/memory/gctransform/transform.py
--- a/pypy/rpython/memory/gctransform/transform.py
+++ b/pypy/rpython/memory/gctransform/transform.py
@@ -263,9 +263,7 @@
         # still be empty (but let's check)
         if starts_with_empty_block(graph) and inserted_empty_startblock:
             old_startblock = graph.startblock
-            graph.startblock.isstartblock = False
             graph.startblock = graph.startblock.exits[0].target
-            graph.startblock.isstartblock = True
 
         checkgraph(graph)
 
diff --git a/pypy/rpython/normalizecalls.py b/pypy/rpython/normalizecalls.py
--- a/pypy/rpython/normalizecalls.py
+++ b/pypy/rpython/normalizecalls.py
@@ -116,8 +116,6 @@
                     v = Constant(default)
                 outlist.append(v)
             newblock.closeblock(Link(outlist, oldblock))
-            oldblock.isstartblock = False
-            newblock.isstartblock = True
             graph.startblock = newblock
             for i in range(len(newdefaults)-1,-1,-1):
                 if newdefaults[i] is NODEFAULT:
@@ -171,8 +169,6 @@
             # prepare the output args of newblock and link
             outlist = inlist[:]
             newblock.closeblock(Link(outlist, oldblock))
-            oldblock.isstartblock = False
-            newblock.isstartblock = True
             graph.startblock = newblock
             # finished
             checkgraph(graph)
diff --git a/pypy/tool/nullpath.py b/pypy/tool/nullpath.py
--- a/pypy/tool/nullpath.py
+++ b/pypy/tool/nullpath.py
@@ -1,4 +1,4 @@
-import py
+import py, os
 
 class NullPyPathLocal(py.path.local):
 
@@ -6,7 +6,7 @@
         return self.__class__(py.path.local.join(self, *args))
 
     def open(self, mode):
-        return open('/dev/null', mode)
+        return open(os.devnull, mode)
 
     def __repr__(self):
         return py.path.local.__repr__(self) + ' [fake]'
diff --git a/pypy/tool/test/test_nullpath.py b/pypy/tool/test/test_nullpath.py
--- a/pypy/tool/test/test_nullpath.py
+++ b/pypy/tool/test/test_nullpath.py
@@ -1,11 +1,7 @@
-import sys
+import sys, os
 import py
 from pypy.tool.nullpath import NullPyPathLocal
 
-def setup_module():
-    if 'posix' not in sys.builtin_module_names:
-        py.test.skip('posix only')
-
 def test_nullpath(tmpdir):
     path = NullPyPathLocal(tmpdir)
     assert repr(path).endswith('[fake]')
@@ -13,4 +9,4 @@
     assert isinstance(foo_txt, NullPyPathLocal)
     #
     f = foo_txt.open('w')
-    assert f.name == '/dev/null'
+    assert f.name == os.devnull
diff --git a/pypy/translator/backendopt/constfold.py b/pypy/translator/backendopt/constfold.py
--- a/pypy/translator/backendopt/constfold.py
+++ b/pypy/translator/backendopt/constfold.py
@@ -37,8 +37,9 @@
                 except (KeyboardInterrupt, SystemExit):
                     raise
                 except Exception, e:
-                    log.WARNING('constant-folding %r:' % (spaceop,))
-                    log.WARNING('  %s: %s' % (e.__class__.__name__, e))
+                    pass   # turn off reporting these as warnings: useless
+                    #log.WARNING('constant-folding %r:' % (spaceop,))
+                    #log.WARNING('  %s: %s' % (e.__class__.__name__, e))
                 else:
                     # success in folding this space operation
                     if spaceop.opname in fixup_op_result:
diff --git a/pypy/translator/backendopt/inline.py b/pypy/translator/backendopt/inline.py
--- a/pypy/translator/backendopt/inline.py
+++ b/pypy/translator/backendopt/inline.py
@@ -453,7 +453,6 @@
         #vars that need to be passed through the blocks of the inlined function
         linktoinlined = splitlink
         copiedstartblock = self.copy_block(self.graph_to_inline.startblock)
-        copiedstartblock.isstartblock = False
         #find args passed to startblock of inlined function
         passon_args = []
         for arg in self.op.args[1:]:
diff --git a/pypy/translator/backendopt/mallocv.py b/pypy/translator/backendopt/mallocv.py
--- a/pypy/translator/backendopt/mallocv.py
+++ b/pypy/translator/backendopt/mallocv.py
@@ -391,7 +391,6 @@
         virtualframe = VirtualFrame(graph2.startblock, 0, nodelist)
         graphbuilder = GraphBuilder(self, graph2)
         specblock = graphbuilder.start_from_virtualframe(virtualframe)
-        specblock.isstartblock = True
         specgraph = graph2
         specgraph.name += '_mallocv'
         specgraph.startblock = specblock
diff --git a/pypy/translator/backendopt/test/test_malloc.py b/pypy/translator/backendopt/test/test_malloc.py
--- a/pypy/translator/backendopt/test/test_malloc.py
+++ b/pypy/translator/backendopt/test/test_malloc.py
@@ -50,7 +50,8 @@
         # we do the loop ourselves instead of calling remove_simple_mallocs()
         while True:
             progress = remover.remove_mallocs_once(graph)
-            simplify.transform_dead_op_vars_in_blocks(list(graph.iterblocks()))
+            simplify.transform_dead_op_vars_in_blocks(list(graph.iterblocks()),
+                                                      [graph])
             if progress and option.view:
                 t.view()
             if expected_result is not Ellipsis:
diff --git a/pypy/translator/c/test/test_refcount.py b/pypy/translator/c/test/test_refcount.py
--- a/pypy/translator/c/test/test_refcount.py
+++ b/pypy/translator/c/test/test_refcount.py
@@ -229,7 +229,6 @@
     graph = t.buildflowgraph(g)
     assert graph.startblock.operations == []
     graph.startblock = graph.startblock.exits[0].target
-    graph.startblock.isstartblock = True
     from pypy.objspace.flow.model import checkgraph
     checkgraph(graph)
     t._prebuilt_graphs[g] = graph
diff --git a/pypy/translator/simplify.py b/pypy/translator/simplify.py
--- a/pypy/translator/simplify.py
+++ b/pypy/translator/simplify.py
@@ -397,7 +397,8 @@
 def transform_dead_op_vars(graph, translator=None):
     """Remove dead operations and variables that are passed over a link
     but not used in the target block. Input is a graph."""
-    return transform_dead_op_vars_in_blocks(list(graph.iterblocks()), translator)
+    return transform_dead_op_vars_in_blocks(list(graph.iterblocks()),
+                                            [graph], translator)
 
 # the set of operations that can safely be removed
 # (they have no side effects, at least in R-Python)
@@ -419,11 +420,19 @@
     hasattr: True,
     }
 
-def transform_dead_op_vars_in_blocks(blocks, translator=None):
+def find_start_blocks(graphs):
+    start_blocks = set()
+    for graph in graphs:
+        start_blocks.add(graph.startblock)
+    return start_blocks
+
+def transform_dead_op_vars_in_blocks(blocks, graphs, translator=None):
     """Remove dead operations and variables that are passed over a link
     but not used in the target block. Input is a set of blocks"""
     read_vars = {}  # set of variables really used
     variable_flow = {}  # map {Var: list-of-Vars-it-depends-on}
+    set_of_blocks = set(blocks)
+    start_blocks = find_start_blocks(graphs)
 
     def canremove(op, block):
         if op.opname not in CanRemove:
@@ -451,7 +460,7 @@
 
         if block.exits:
             for link in block.exits:
-                if link.target not in blocks:
+                if link.target not in set_of_blocks:
                     for arg, targetarg in zip(link.args, link.target.inputargs):
                         read_vars[arg] = True
                         read_vars[targetarg] = True
@@ -465,7 +474,7 @@
                 read_vars[arg] = True
         # an input block's inputargs should not be modified, even if some
         # of the function's input arguments are not actually used
-        if block.isstartblock:
+        if block in start_blocks:
             for arg in block.inputargs:
                 read_vars[arg] = True
 
diff --git a/pypy/translator/transform.py b/pypy/translator/transform.py
--- a/pypy/translator/transform.py
+++ b/pypy/translator/transform.py
@@ -115,7 +115,7 @@
     # to kill dead (never-followed) links,
     # which can possibly remove more variables.
     from pypy.translator.simplify import transform_dead_op_vars_in_blocks
-    transform_dead_op_vars_in_blocks(block_subset)
+    transform_dead_op_vars_in_blocks(block_subset, self.translator.graphs)
 
 def transform_dead_code(self, block_subset):
     """Remove dead code: these are the blocks that are not annotated at all
diff --git a/pypy/translator/unsimplify.py b/pypy/translator/unsimplify.py
--- a/pypy/translator/unsimplify.py
+++ b/pypy/translator/unsimplify.py
@@ -42,9 +42,7 @@
     vars = [copyvar(annotator, v) for v in graph.startblock.inputargs]
     newblock = Block(vars)
     newblock.closeblock(Link(vars, graph.startblock))
-    graph.startblock.isstartblock = False
     graph.startblock = newblock
-    graph.startblock.isstartblock = True
 
 def starts_with_empty_block(graph):
     return (not graph.startblock.operations
@@ -151,9 +149,7 @@
     newop = SpaceOperation('direct_call', [c_initial_func], v_none)
     extrablock.operations = [newop]
     extrablock.closeblock(Link(args, entry_point.startblock))
-    entry_point.startblock.isstartblock = False
     entry_point.startblock = extrablock
-    entry_point.startblock.isstartblock = True
     checkgraph(entry_point)
 
 def call_final_function(translator, final_func, annhelper=None):


More information about the pypy-commit mailing list