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