Author: Christian Tismer <tis...@stackless.com>
Branch: win64-stage1
Changeset: r50041:78ed73b0b1af
Date: 2011-12-01 18:16 +0100
http://bitbucket.org/pypy/pypy/changeset/78ed73b0b1af/

Log:    merge default

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/jtransform.py 
b/pypy/jit/codewriter/jtransform.py
--- a/pypy/jit/codewriter/jtransform.py
+++ b/pypy/jit/codewriter/jtransform.py
@@ -15,6 +15,8 @@
 from pypy.translator.simplify import get_funcobj
 from pypy.translator.unsimplify import varoftype
 
+class UnsupportedMallocFlags(Exception):
+    pass
 
 def transform_graph(graph, cpu=None, callcontrol=None, portal_jd=None):
     """Transform a control flow graph to make it suitable for
@@ -205,7 +207,19 @@
         if op.args[0] in self.vable_array_vars:
             self.vable_array_vars[op.result]= self.vable_array_vars[op.args[0]]
 
-    rewrite_op_cast_pointer = rewrite_op_same_as
+    def rewrite_op_cast_pointer(self, op):
+        newop = self.rewrite_op_same_as(op)
+        assert newop is None
+        if (self._is_rclass_instance(op.args[0]) and
+                self._is_rclass_instance(op.result)):
+            FROM = op.args[0].concretetype.TO
+            TO = op.result.concretetype.TO
+            if lltype._castdepth(TO, FROM) > 0:
+                vtable = heaptracker.get_vtable_for_gcstruct(self.cpu, TO)
+                const_vtable = Constant(vtable, lltype.typeOf(vtable))
+                return [None, # hack, do the right renaming from op.args[0] to 
op.result
+                        SpaceOperation("record_known_class", [op.args[0], 
const_vtable], None)]
+
     def rewrite_op_cast_bool_to_int(self, op): pass
     def rewrite_op_cast_bool_to_uint(self, op): pass
     def rewrite_op_cast_char_to_int(self, op): pass
@@ -481,8 +495,22 @@
 
     def rewrite_op_malloc_varsize(self, op):
         if op.args[1].value['flavor'] == 'raw':
+            d = op.args[1].value.copy()
+            d.pop('flavor')
+            add_memory_pressure = d.pop('add_memory_pressure', False)
+            zero = d.pop('zero', False)
+            track_allocation = d.pop('track_allocation', True)
+            if d:
+                raise UnsupportedMallocFlags(d)
             ARRAY = op.args[0].value
-            return self._do_builtin_call(op, 'raw_malloc',
+            name = 'raw_malloc'
+            if zero:
+                name += '_zero'
+            if add_memory_pressure:
+                name += '_add_memory_pressure'
+            if not track_allocation:
+                name += '_no_track_allocation'
+            return self._do_builtin_call(op, name,
                                          [op.args[2]],
                                          extra = (ARRAY,),
                                          extrakey = ARRAY)
diff --git a/pypy/jit/codewriter/support.py b/pypy/jit/codewriter/support.py
--- a/pypy/jit/codewriter/support.py
+++ b/pypy/jit/codewriter/support.py
@@ -599,10 +599,21 @@
             return p
         return _ll_0_alloc_with_del
 
-    def build_ll_1_raw_malloc(ARRAY):
-        def _ll_1_raw_malloc(n):
-            return lltype.malloc(ARRAY, n, flavor='raw')
-        return _ll_1_raw_malloc
+    def build_raw_malloc_builder(zero=False, add_memory_pressure=False, 
track_allocation=True):
+        def build_ll_1_raw_malloc(ARRAY):
+            def _ll_1_raw_malloc(n):
+                return lltype.malloc(ARRAY, n, flavor='raw', zero=zero, 
add_memory_pressure=add_memory_pressure)
+            return _ll_1_raw_malloc
+        return build_ll_1_raw_malloc
+
+    build_ll_1_raw_malloc = build_raw_malloc_builder()
+    build_ll_1_raw_malloc_zero = build_raw_malloc_builder(zero=True)
+    build_ll_1_raw_malloc_zero_add_memory_pressure = 
build_raw_malloc_builder(zero=True, add_memory_pressure=True)
+    build_ll_1_raw_malloc_add_memory_pressure = 
build_raw_malloc_builder(add_memory_pressure=True)
+    build_ll_1_raw_malloc_no_track_allocation = 
build_raw_malloc_builder(track_allocation=False)
+    build_ll_1_raw_malloc_zero_no_track_allocation = 
build_raw_malloc_builder(zero=True, track_allocation=False)
+    build_ll_1_raw_malloc_zero_add_memory_pressure_no_track_allocation = 
build_raw_malloc_builder(zero=True, add_memory_pressure=True, 
track_allocation=False)
+    build_ll_1_raw_malloc_add_memory_pressure_no_track_allocation = 
build_raw_malloc_builder(add_memory_pressure=True, track_allocation=False)
 
     def build_ll_1_raw_free(ARRAY):
         def _ll_1_raw_free(p):
diff --git a/pypy/jit/codewriter/test/test_jtransform.py 
b/pypy/jit/codewriter/test/test_jtransform.py
--- a/pypy/jit/codewriter/test/test_jtransform.py
+++ b/pypy/jit/codewriter/test/test_jtransform.py
@@ -1,3 +1,5 @@
+
+import py
 import random
 try:
     from itertools import product
@@ -15,12 +17,12 @@
 
 from pypy.objspace.flow.model import FunctionGraph, Block, Link
 from pypy.objspace.flow.model import SpaceOperation, Variable, Constant
-from pypy.rpython.lltypesystem import lltype, llmemory, rclass, rstr
+from pypy.rpython.lltypesystem import lltype, llmemory, rclass, rstr, rffi
 from pypy.rpython.lltypesystem.module import ll_math
 from pypy.translator.unsimplify import varoftype
 from pypy.jit.codewriter import heaptracker, effectinfo
 from pypy.jit.codewriter.flatten import ListOfKind
-from pypy.jit.codewriter.jtransform import Transformer
+from pypy.jit.codewriter.jtransform import Transformer, UnsupportedMallocFlags
 from pypy.jit.metainterp.history import getkind
 
 def const(x):
@@ -538,6 +540,44 @@
     assert op1.opname == '-live-'
     assert op1.args == []
 
+def test_raw_malloc():
+    S = rffi.CArray(lltype.Signed)
+    v1 = varoftype(lltype.Signed)
+    v = varoftype(lltype.Ptr(S))
+    flags = Constant({'flavor': 'raw'}, lltype.Void)
+    op = SpaceOperation('malloc_varsize', [Constant(S, lltype.Void), flags,
+                                           v1], v)
+    tr = Transformer(FakeCPU(), FakeResidualCallControl())
+    op0, op1 = tr.rewrite_operation(op)
+    assert op0.opname == 'residual_call_ir_i'
+    assert op0.args[0].value == 'raw_malloc'    # pseudo-function as a str
+    assert op1.opname == '-live-'
+    assert op1.args == []
+
+def test_raw_malloc_zero():
+    S = rffi.CArray(lltype.Signed)
+    v1 = varoftype(lltype.Signed)
+    v = varoftype(lltype.Ptr(S))
+    flags = Constant({'flavor': 'raw', 'zero': True}, lltype.Void)
+    op = SpaceOperation('malloc_varsize', [Constant(S, lltype.Void), flags,
+                                           v1], v)
+    tr = Transformer(FakeCPU(), FakeResidualCallControl())
+    op0, op1 = tr.rewrite_operation(op)
+    assert op0.opname == 'residual_call_ir_i'
+    assert op0.args[0].value == 'raw_malloc_zero'    # pseudo-function as a str
+    assert op1.opname == '-live-'
+    assert op1.args == []
+
+def test_raw_malloc_unsupported_flag():
+    S = rffi.CArray(lltype.Signed)
+    v1 = varoftype(lltype.Signed)
+    v = varoftype(lltype.Ptr(S))
+    flags = Constant({'flavor': 'raw', 'unsupported_flag': True}, lltype.Void)
+    op = SpaceOperation('malloc_varsize', [Constant(S, lltype.Void), flags,
+                                           v1], v)
+    tr = Transformer(FakeCPU(), FakeResidualCallControl())
+    py.test.raises(UnsupportedMallocFlags, tr.rewrite_operation, op)
+
 def test_rename_on_links():
     v1 = Variable()
     v2 = Variable(); v2.concretetype = llmemory.Address
@@ -1140,4 +1180,4 @@
     assert op1.opname == 'mark_opaque_ptr'
     assert op1.args == [v1]
     assert op1.result is None
-    assert op2 is None
\ No newline at end of file
+    assert op2 is None
diff --git a/pypy/jit/metainterp/blackhole.py b/pypy/jit/metainterp/blackhole.py
--- a/pypy/jit/metainterp/blackhole.py
+++ b/pypy/jit/metainterp/blackhole.py
@@ -518,6 +518,9 @@
     @arguments("r")
     def bhimpl_mark_opaque_ptr(a):
         pass
+    @arguments("r", "i")
+    def bhimpl_record_known_class(a, b):
+        pass
 
     @arguments("i", returns="i")
     def bhimpl_int_copy(a):
diff --git a/pypy/jit/metainterp/optimizeopt/rewrite.py 
b/pypy/jit/metainterp/optimizeopt/rewrite.py
--- a/pypy/jit/metainterp/optimizeopt/rewrite.py
+++ b/pypy/jit/metainterp/optimizeopt/rewrite.py
@@ -260,6 +260,16 @@
     def optimize_GUARD_FALSE(self, op):
         self.optimize_guard(op, CONST_0)
 
+    def optimize_RECORD_KNOWN_CLASS(self, op):
+        value = self.getvalue(op.getarg(0))
+        expectedclassbox = op.getarg(1)
+        assert isinstance(expectedclassbox, Const)
+        realclassbox = value.get_constant_class(self.optimizer.cpu)
+        if realclassbox is not None:
+            assert realclassbox.same_constant(expectedclassbox)
+            return
+        value.make_constant_class(expectedclassbox, None)
+
     def optimize_GUARD_CLASS(self, op):
         value = self.getvalue(op.getarg(0))
         expectedclassbox = op.getarg(1)
@@ -481,6 +491,9 @@
         self.pure(rop.CAST_PTR_TO_INT, [op.result], op.getarg(0))
         self.emit_operation(op)
 
+    def optimize_SAME_AS(self, op):
+        self.make_equal_to(op.result, self.getvalue(op.getarg(0)))
+
 dispatch_opt = make_dispatcher_method(OptRewrite, 'optimize_',
         default=OptRewrite.emit_operation)
 optimize_guards = _findall(OptRewrite, 'optimize_', 'GUARD')
diff --git a/pypy/jit/metainterp/optimizeopt/simplify.py 
b/pypy/jit/metainterp/optimizeopt/simplify.py
--- a/pypy/jit/metainterp/optimizeopt/simplify.py
+++ b/pypy/jit/metainterp/optimizeopt/simplify.py
@@ -28,6 +28,9 @@
     def optimize_MARK_OPAQUE_PTR(self, op):
         pass
 
+    def optimize_RECORD_KNOWN_CLASS(self, op):
+        pass
+
 
 dispatch_opt = make_dispatcher_method(OptSimplify, 'optimize_',
         default=OptSimplify.emit_operation)
diff --git a/pypy/jit/metainterp/optimizeopt/test/test_optimizeopt.py 
b/pypy/jit/metainterp/optimizeopt/test/test_optimizeopt.py
--- a/pypy/jit/metainterp/optimizeopt/test/test_optimizeopt.py
+++ b/pypy/jit/metainterp/optimizeopt/test/test_optimizeopt.py
@@ -6482,6 +6482,21 @@
         # not obvious, because of the exception UnicodeDecodeError that
         # can be raised by ll_str2unicode()
 
+    def test_record_known_class(self):
+        ops = """
+        [p0]
+        p1 = getfield_gc(p0, descr=nextdescr)
+        record_known_class(p1, ConstClass(node_vtable))
+        guard_class(p1, ConstClass(node_vtable)) []
+        jump(p1)
+        """
+        expected = """
+        [p0]
+        p1 = getfield_gc(p0, descr=nextdescr)
+        jump(p1)
+        """
+        self.optimize_loop(ops, expected)
+
     def test_quasi_immut(self):
         ops = """
         [p0, p1, i0]
diff --git a/pypy/jit/metainterp/pyjitpl.py b/pypy/jit/metainterp/pyjitpl.py
--- a/pypy/jit/metainterp/pyjitpl.py
+++ b/pypy/jit/metainterp/pyjitpl.py
@@ -243,6 +243,18 @@
     def opimpl_mark_opaque_ptr(self, box):
         return self.execute(rop.MARK_OPAQUE_PTR, box)
 
+    @arguments("box", "box")
+    def opimpl_record_known_class(self, box, clsbox):
+        from pypy.rpython.lltypesystem import llmemory
+        if self.metainterp.heapcache.is_class_known(box):
+            return
+        adr = clsbox.getaddr()
+        bounding_class = llmemory.cast_adr_to_ptr(adr, rclass.CLASSTYPE)
+        if bounding_class.subclassrange_max - bounding_class.subclassrange_min 
== 1:
+            # precise class knowledge, this can be used
+            self.execute(rop.RECORD_KNOWN_CLASS, box, clsbox)
+            self.metainterp.heapcache.class_now_known(box)
+
     @arguments("box")
     def _opimpl_any_return(self, box):
         self.metainterp.finishframe(box)
diff --git a/pypy/jit/metainterp/resoperation.py 
b/pypy/jit/metainterp/resoperation.py
--- a/pypy/jit/metainterp/resoperation.py
+++ b/pypy/jit/metainterp/resoperation.py
@@ -494,6 +494,7 @@
     'COPYSTRCONTENT/5',       # src, dst, srcstart, dststart, length
     'COPYUNICODECONTENT/5',
     'QUASIIMMUT_FIELD/1d',    # [objptr], descr=SlowMutateDescr
+    'RECORD_KNOWN_CLASS/2',   # [objptr, clsptr]
 
     '_CANRAISE_FIRST', # ----- start of can_raise operations -----
     '_CALL_FIRST',
diff --git a/pypy/jit/metainterp/test/test_ajit.py 
b/pypy/jit/metainterp/test/test_ajit.py
--- a/pypy/jit/metainterp/test/test_ajit.py
+++ b/pypy/jit/metainterp/test/test_ajit.py
@@ -3585,6 +3585,67 @@
         self.interp_operations(f, [5], translationoptions=translationoptions)
 
 
+    def test_annotation_gives_knowledge_to_tracer(self):
+        class Base(object):
+            pass
+        class A(Base):
+            def f(self):
+                return self.a
+            def g(self):
+                return self.a + 1
+        class B(Base):
+            def f(self):
+                return self.b
+            def g(self):
+                return self.b + 1
+        class C(B):
+            def f(self):
+                self.c += 1
+                return self.c
+            def g(self):
+                return self.c + 1
+        @dont_look_inside
+        def make(x):
+            if x > 0:
+                a = A()
+                a.a = x + 1
+            elif x < 0:
+                a = B()
+                a.b = -x
+            else:
+                a = C()
+                a.c = 10
+            return a
+        def f(x):
+            a = make(x)
+            if x > 0:
+                assert isinstance(a, A)
+                z = a.f()
+            elif x < 0:
+                assert isinstance(a, B)
+                z = a.f()
+            else:
+                assert isinstance(a, C)
+                z = a.f()
+            return z + a.g()
+        res1 = f(6)
+        res2 = self.interp_operations(f, [6])
+        assert res1 == res2
+        self.check_operations_history(guard_class=0, record_known_class=1)
+
+        res1 = f(-6)
+        res2 = self.interp_operations(f, [-6])
+        assert res1 == res2
+        # cannot use record_known_class here, because B has a subclass
+        self.check_operations_history(guard_class=1)
+
+        res1 = f(0)
+        res2 = self.interp_operations(f, [0])
+        assert res1 == res2
+        # here it works again
+        self.check_operations_history(guard_class=0, record_known_class=1)
+
+
 class TestLLtype(BaseLLtypeTests, LLJitMixin):
     def test_tagged(self):
         from pypy.rlib.objectmodel import UnboxedValue
diff --git a/pypy/jit/metainterp/test/test_virtual.py 
b/pypy/jit/metainterp/test/test_virtual.py
--- a/pypy/jit/metainterp/test/test_virtual.py
+++ b/pypy/jit/metainterp/test/test_virtual.py
@@ -612,7 +612,7 @@
             return node.value
         res = self.meta_interp(f, [48, 3], policy=StopAtXPolicy(externfn))
         assert res == f(48, 3)
-        self.check_loop_count(3)
+        self.check_loop_count(5)
         res = self.meta_interp(f, [40, 3], policy=StopAtXPolicy(externfn))
         assert res == f(40, 3)
         self.check_loop_count(3)
@@ -761,6 +761,27 @@
         res = self.meta_interp(f, [0x1F, 0x11])
         assert res == f(0x1F, 0x11)
 
+    def test_duplicated_virtual(self):
+        myjitdriver = JitDriver(greens = [], reds = ['n', 'node1', 'node2'])
+        def f(n):
+            node1 = self._new()
+            node1.value = 0
+            node2 = self._new()
+            node2.value = 1
+            while n > 0:
+                myjitdriver.jit_merge_point(n=n, node1=node1, node2=node2)
+                next = self._new()
+                next.value = node1.value + node2.value + n
+                node1 = next
+                node2 = next
+                n -= 1
+            return node1.value 
+        res = self.meta_interp(f, [10])
+        assert res == f(10)
+        self.check_resops(new_with_vtable=0, new=0)
+
+        
+
 class VirtualMiscTests:
 
     def test_multiple_equal_virtuals(self):
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/__pypy__/__init__.py b/pypy/module/__pypy__/__init__.py
--- a/pypy/module/__pypy__/__init__.py
+++ b/pypy/module/__pypy__/__init__.py
@@ -27,6 +27,7 @@
         'builtinify'                : 'interp_magic.builtinify',
         'lookup_special'            : 'interp_magic.lookup_special',
         'do_what_I_mean'            : 'interp_magic.do_what_I_mean',
+        'list_strategy'             : 'interp_magic.list_strategy',
     }
 
     submodules = {
diff --git a/pypy/module/__pypy__/interp_magic.py 
b/pypy/module/__pypy__/interp_magic.py
--- a/pypy/module/__pypy__/interp_magic.py
+++ b/pypy/module/__pypy__/interp_magic.py
@@ -5,7 +5,6 @@
 from pypy.objspace.std.typeobject import MethodCache
 from pypy.objspace.std.mapdict import IndexCache
 
-
 def internal_repr(space, w_object):
     return space.wrap('%r' % (w_object,))
 
@@ -73,3 +72,11 @@
 
 def do_what_I_mean(space):
     return space.wrap(42)
+
+def list_strategy(space, w_list):
+    from pypy.objspace.std.listobject import W_ListObject
+    if isinstance(w_list, W_ListObject):
+        return space.wrap(w_list.strategy._applevel_repr)
+    else:
+        w_msg = space.wrap("Can only get the list strategy of a list")
+        raise OperationError(space.w_TypeError, w_msg)
diff --git a/pypy/module/__pypy__/test/test_special.py 
b/pypy/module/__pypy__/test/test_special.py
--- a/pypy/module/__pypy__/test/test_special.py
+++ b/pypy/module/__pypy__/test/test_special.py
@@ -5,7 +5,7 @@
     def setup_class(cls):
         if option.runappdirect:
             py.test.skip("does not make sense on pypy-c")
-        cls.space = gettestobjspace(**{"objspace.usemodules.select": False})
+        cls.space = gettestobjspace(**{"objspace.usemodules.select": False, 
"objspace.std.withrangelist": True})
 
     def test__isfake(self):
         from __pypy__ import isfake
@@ -54,3 +54,21 @@
         from __pypy__ import do_what_I_mean
         x = do_what_I_mean()
         assert x == 42
+
+    def test_list_strategy(self):
+        from __pypy__ import list_strategy
+
+        l = [1, 2, 3]
+        assert list_strategy(l) == "int"
+        l = ["a", "b", "c"]
+        assert list_strategy(l) == "str"
+        l = [1.1, 2.2, 3.3]
+        assert list_strategy(l) == "float"
+        l = range(3)
+        assert list_strategy(l) == "range"
+        l = [1, "b", 3]
+        assert list_strategy(l) == "object"
+        l = []
+        assert list_strategy(l) == "empty"
+        o = 5
+        raises(TypeError, list_strategy, 5)
diff --git a/pypy/module/micronumpy/interp_dtype.py 
b/pypy/module/micronumpy/interp_dtype.py
--- a/pypy/module/micronumpy/interp_dtype.py
+++ b/pypy/module/micronumpy/interp_dtype.py
@@ -131,7 +131,7 @@
 
 
 def binop(func):
-    func._annspecialcase_ = "specialize:call_location"
+    specialize.argtype(1, 2)(func)
     @functools.wraps(func)
     def impl(self, v1, v2):
         return self.adapt_val(func(self,
@@ -141,6 +141,7 @@
     return impl
 
 def raw_binop(func):
+    specialize.argtype(1, 2)(func)
     # Returns the result unwrapped.
     @functools.wraps(func)
     def impl(self, v1, v2):
@@ -151,6 +152,7 @@
     return impl
 
 def unaryop(func):
+    specialize.argtype(1)(func)
     @functools.wraps(func)
     def impl(self, v):
         return self.adapt_val(func(self, self.for_computation(self.unbox(v))))
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
@@ -1110,6 +1110,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
@@ -760,6 +760,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
@@ -989,18 +1002,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(object):
     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
@@ -40,7 +40,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 = ()
@@ -173,11 +172,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
@@ -454,7 +452,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]
@@ -492,7 +489,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
@@ -317,6 +326,8 @@
     to the added item.
     W_Lists do not switch back to EmptyListStrategy when becoming empty 
again."""
 
+    _applevel_repr = "empty"
+
     def __init__(self, space):
         ListStrategy.__init__(self, space)
         # cache an empty list that is used whenever getitems is called (i.e. 
sorting)
@@ -364,6 +375,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)
 
@@ -415,6 +428,8 @@
     On any operation destroying the range (inserting, appending non-ints)
     the strategy is switched to IntegerListStrategy."""
 
+    _applevel_repr = "range"
+
     def switch_to_integer_strategy(self, w_list):
         items = self._getitems_range(w_list, False)
         strategy = w_list.strategy = self.space.fromcache(IntegerListStrategy)
@@ -853,6 +868,7 @@
 
 class ObjectListStrategy(AbstractUnwrappedStrategy, ListStrategy):
     _none_value = None
+    _applevel_repr = "object"
 
     def unwrap(self, w_obj):
         return w_obj
@@ -881,6 +897,7 @@
 
 class IntegerListStrategy(AbstractUnwrappedStrategy, ListStrategy):
     _none_value = 0
+    _applevel_repr = "int"
 
     def wrap(self, intval):
         return self.space.wrap(intval)
@@ -905,8 +922,36 @@
         if reverse:
             l.reverse()
 
+class FloatListStrategy(AbstractUnwrappedStrategy, ListStrategy):
+    _none_value = 0.0
+    _applevel_repr = "float"
+
+    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
+    _applevel_repr = "str"
 
     def wrap(self, stringval):
         return self.space.wrap(stringval)
@@ -934,6 +979,7 @@
     def getitems_str(self, w_list):
         return self.unerase(w_list.lstorage)
 
+
 # _______________________________________________________
 
 init_signature = Signature(['sequence'], None, None)
@@ -1282,6 +1328,7 @@
 
 TimSort = make_timsort_class()
 IntBaseTimSort = make_timsort_class()
+FloatBaseTimSort = make_timsort_class()
 StringBaseTimSort = make_timsort_class()
 
 class KeyContainer(baseobjspace.W_Root):
@@ -1302,6 +1349,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
@@ -471,11 +471,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()
@@ -494,6 +500,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', '' ]
@@ -547,11 +557,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]")
 
@@ -589,6 +607,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]
@@ -628,9 +656,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 == []
@@ -641,6 +675,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']
@@ -698,6 +737,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]
@@ -732,6 +776,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")
@@ -780,6 +828,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
@@ -836,6 +888,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
@@ -876,6 +932,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)
 
@@ -898,16 +958,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')
@@ -926,6 +989,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/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)")
-@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)")
-@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/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):
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
http://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to