Commits

Armin Rigo committed 7cfdee1 Merge

merge heads

Comments (0)

Files changed (21)

pypy/jit/codewriter/test/test_regalloc.py

 from pypy.objspace.flow.model import c_last_exception
 from pypy.rpython.lltypesystem import lltype, llmemory, rclass
 from pypy.rlib.rarithmetic import ovfcheck
-from pypy.rlib.objectmodel import keepalive_until_here
 
 
 class TestRegAlloc:

pypy/rpython/lltypesystem/rlist.py

 from pypy.rlib.debug import ll_assert
 from pypy.rlib.rarithmetic import ovfcheck
 from pypy.rpython.lltypesystem import rffi
-from pypy.rlib.objectmodel import keepalive_until_here
 from pypy.rpython.lltypesystem.lloperation import llop
 from pypy.rlib import rgc
 

pypy/rpython/memory/test/test_gc.py

 from pypy.rpython.lltypesystem.rstr import STR
 from pypy.rpython.lltypesystem.lloperation import llop
 from pypy.rlib.objectmodel import we_are_translated
-from pypy.rlib.objectmodel import compute_unique_id, keepalive_until_here
+from pypy.rlib.objectmodel import compute_unique_id
 from pypy.rlib import rgc
 from pypy.rlib.rstring import StringBuilder
 from pypy.rlib.rarithmetic import LONG_BIT

pypy/rpython/memory/test/test_transformed_gc.py

 from pypy.rlib import rgc
 from pypy import conftest
 from pypy.rlib.rstring import StringBuilder
-from pypy.rlib.objectmodel import keepalive_until_here
 from pypy.rlib.rarithmetic import LONG_BIT
 
 WORD = LONG_BIT // 8

pypy/rpython/module/ll_os.py

 from pypy.rpython.lltypesystem.rstr import STR
 from pypy.rpython.annlowlevel import llstr
 from pypy.rlib import rgc
-from pypy.rlib.objectmodel import keepalive_until_here, specialize
+from pypy.rlib.objectmodel import specialize
 
 def monkeypatch_rposix(posixfunc, unicodefunc, signature):
     func_name = posixfunc.__name__

pypy/translator/backendopt/constfold.py

 from pypy.objspace.flow.model import Constant, Variable, SpaceOperation
 from pypy.objspace.flow.model import c_last_exception
 from pypy.objspace.flow.model import mkentrymap
-from pypy.translator.backendopt.support import split_block_with_keepalive
 from pypy.translator.backendopt.support import log
 from pypy.translator.simplify import eliminate_empty_blocks
-from pypy.translator.unsimplify import insert_empty_block
+from pypy.translator.unsimplify import insert_empty_block, split_block
 from pypy.rpython.lltypesystem.lloperation import llop
 from pypy.rpython.lltypesystem import lltype
 
 
 def fold_op_list(operations, constants, exit_early=False, exc_catch=False):
     newops = []
-    keepalives = []
     folded_count = 0
-    first_sideeffect_index = None
     for spaceop in operations:
         vargsmodif = False
         vargs = []
         try:
             op = getattr(llop, spaceop.opname)
         except AttributeError:
-            sideeffects = True
+            pass
         else:
-            sideeffects = op.sideeffects
-            if not sideeffects and len(args) == len(vargs):
+            if not op.sideeffects and len(args) == len(vargs):
                 RESTYPE = spaceop.result.concretetype
                 try:
                     result = op(RESTYPE, *args)
         # failed to fold an operation, exit early if requested
         if exit_early:
             return folded_count
-        if spaceop.opname == 'keepalive' and first_sideeffect_index is None:
-            if vargsmodif:
-                continue    # keepalive(constant) is not useful
-            keepalives.append(spaceop)
         else:
             if vargsmodif:
                 if (spaceop.opname == 'indirect_call'
                 else:
                     spaceop = SpaceOperation(spaceop.opname, vargs,
                                              spaceop.result)
-            if sideeffects and first_sideeffect_index is None:
-                first_sideeffect_index = len(newops)
             newops.append(spaceop)
     # end
     if exit_early:
         return folded_count
     else:
-        # move the keepalives to the end of the block, which makes the life
-        # of prepare_constant_fold_link() easier.  Don't put them past the
-        # exception-raising operation, though.  There is also no point in
-        # moving them past the first sideeffect-ing operation.
-        if first_sideeffect_index is None:
-            first_sideeffect_index = len(newops) - exc_catch
-        newops[first_sideeffect_index:first_sideeffect_index] = keepalives
         return newops
 
 def constant_fold_block(block):
     if block.exitswitch == c_last_exception:
         n -= 1
     # is the next, non-folded operation an indirect_call?
-    m = folded_count
-    while m < n and block.operations[m].opname == 'keepalive':
-        m += 1
-    if m < n:
-        nextop = block.operations[m]
+    if folded_count < n:
+        nextop = block.operations[folded_count]
         if nextop.opname == 'indirect_call' and nextop.args[0] in constants:
             # indirect_call -> direct_call
             callargs = [constants[nextop.args[0]]]
             constants1 = constants.copy()
             complete_constants(link, constants1)
-            newkeepalives = []
-            for i in range(folded_count, m):
-                [v] = block.operations[i].args
-                v = constants1.get(v, v)
-                v_void = Variable()
-                v_void.concretetype = lltype.Void
-                newkeepalives.append(SpaceOperation('keepalive', [v], v_void))
             for v in nextop.args[1:-1]:
                 callargs.append(constants1.get(v, v))
             v_result = Variable(nextop.result)
             v_result.concretetype = nextop.result.concretetype
             constants[nextop.result] = v_result
             callop = SpaceOperation('direct_call', callargs, v_result)
-            newblock = insert_empty_block(None, link, newkeepalives + [callop])
+            newblock = insert_empty_block(None, link, [callop])
             [link] = newblock.exits
             assert link.target is block
-            folded_count = m+1
+            folded_count += 1
 
     if folded_count > 0:
         splits = splitblocks.setdefault(block, [])
                 splitlink = block.exits[0]
             else:
                 # split the block at the given position
-                splitlink = split_block_with_keepalive(block, position)
+                splitlink = split_block(None, block, position)
                 assert list(block.exits) == [splitlink]
             assert link.target is block
             assert splitlink.prevblock is block

pypy/translator/backendopt/inline.py

 from pypy.rpython import rmodel
 from pypy.tool.algo import sparsemat
 from pypy.translator.backendopt import removenoops
-from pypy.translator.backendopt.support import log, split_block_with_keepalive
+from pypy.translator.backendopt.support import log
 from pypy.translator.unsimplify import split_block
 from pypy.translator.backendopt.support import find_backedges, find_loop_blocks
 from pypy.translator.backendopt.canraise import RaiseAnalyzer
             self.varmap[var] = copyvar(None, var)
         return self.varmap[var]
 
-    def generate_keepalive(self, *args):
-        from pypy.translator.backendopt.support import generate_keepalive
-        if self.translator.rtyper.type_system.name == 'lltypesystem':
-            return generate_keepalive(*args)
-        else:
-            return []
-
     def passon_vars(self, cache_key):
         if cache_key in self._passon_vars:
             return self._passon_vars[cache_key]
             for exceptionlink in afterblock.exits[1:]:
                 if exc_match(vtable, exceptionlink.llexitcase):
                     passon_vars = self.passon_vars(link.prevblock)
-                    copiedblock.operations += self.generate_keepalive(passon_vars)
                     copiedlink.target = exceptionlink.target
                     linkargs = self.find_args_in_exceptional_case(
                         exceptionlink, link.prevblock, var_etype, var_evalue, afterblock, passon_vars)
         del blocks[-1].exits[0].llexitcase
         linkargs = copiedexceptblock.inputargs
         copiedexceptblock.recloseblock(Link(linkargs, blocks[0]))
-        copiedexceptblock.operations += self.generate_keepalive(linkargs)
 
     def do_inline(self, block, index_operation):
         splitlink = split_block(None, block, index_operation)
         # this copy is created with the method passon_vars
         self.original_passon_vars = [arg for arg in block.exits[0].args
                                          if isinstance(arg, Variable)]
-        n = 0
-        while afterblock.operations[n].opname == 'keepalive':
-            n += 1
-        assert afterblock.operations[n].opname == self.op.opname
-        self.op = afterblock.operations.pop(n)
+        assert afterblock.operations[0].opname == self.op.opname
+        self.op = afterblock.operations.pop(0)
         #vars that need to be passed through the blocks of the inlined function
         linktoinlined = splitlink
         copiedstartblock = self.copy_block(self.graph_to_inline.startblock)
 
 OP_WEIGHTS = {'same_as': 0,
               'cast_pointer': 0,
-              'keepalive': 0,
               'malloc': 2,
               'yield_current_frame_to_caller': sys.maxint, # XXX bit extreme
               'resume_point': sys.maxint, # XXX bit extreme
                               call_count_pred=call_count_pred)
         log.inlining('inlined %d callsites.'% (count,))
         for graph in graphs:
-            removenoops.remove_superfluous_keep_alive(graph)
             removenoops.remove_duplicate_casts(graph, translator)

pypy/translator/backendopt/malloc.py

         # in this 'block', follow where the 'var' goes to and replace
         # it by a flattened-out family of variables.  This family is given
         # by newvarsmap, whose keys are the 'flatnames'.
-        self.last_removed_access = None
 
         def list_newvars():
             return [newvarsmap[key] for key in self.flatnames]
                     newargs.append(arg)
             link.args[:] = newargs
 
-        self.insert_keepalives(list_newvars())
         block.operations[:] = self.newops
 
     def compute_lifetimes(self, graph):
         STRUCT = self.get_STRUCT(lltypes.keys()[0])
 
         # must be only ever accessed via getfield/setfield/getsubstruct/
-        # direct_fieldptr, or touched by keepalive or ptr_iszero/ptr_nonzero.
+        # direct_fieldptr, or touched by ptr_iszero/ptr_nonzero.
         # Note that same_as and cast_pointer are not recorded in usepoints.
         self.accessed_substructs = {}
 
     MALLOC_OP = "malloc"
     FIELD_ACCESS =     dict.fromkeys(["getfield",
                                       "setfield",
-                                      "keepalive",
                                       "ptr_iszero",
                                       "ptr_nonzero",
                                       "getarrayitem",
                                        [newvarsmap[key]],
                                        op.result)
             self.newops.append(newop)
-            self.last_removed_access = len(self.newops)
         elif op.opname in ("setfield", "setarrayitem"):
             S = op.args[0].concretetype.TO
             fldname = op.args[1].value
                 self.newops.append(newop)
             else:
                 newvarsmap[key] = op.args[2]
-                self.last_removed_access = len(self.newops)
         elif op.opname in ("same_as", "cast_pointer"):
             vars[op.result] = True
             # Consider the two pointers (input and result) as
             # equivalent.  We can, and indeed must, use the same
             # flattened list of variables for both, as a "setfield"
             # via one pointer must be reflected in the other.
-        elif op.opname == 'keepalive':
-            self.last_removed_access = len(self.newops)
         elif op.opname in ("getsubstruct", "getarraysubstruct",
                            "direct_fieldptr"):
             S = op.args[0].concretetype.TO
         else:
             raise AssertionError, op.opname
 
-        
-    def insert_keepalives(self, newvars):
-        if self.last_removed_access is not None:
-            keepalives = []
-            for v in newvars:
-                T = v.concretetype
-                if isinstance(T, lltype.Ptr) and T._needsgc():
-                    v0 = Variable()
-                    v0.concretetype = lltype.Void
-                    newop = SpaceOperation('keepalive', [v], v0)
-                    keepalives.append(newop)
-            self.newops[self.last_removed_access:self.last_removed_access] = keepalives
 
 class OOTypeMallocRemover(BaseMallocRemover):
 
                                    [newvarsmap[key]],
                                    op.result)
             self.newops.append(newop)
-            last_removed_access = len(self.newops)
         elif op.opname == "oosetfield":
             S = op.args[0].concretetype
             fldname = op.args[1].value
             key = self.key_for_field_access(S, fldname)
             assert key in newvarsmap
             newvarsmap[key] = op.args[2]
-            last_removed_access = len(self.newops)
         elif op.opname in ("same_as", "oodowncast", "ooupcast"):
             vars[op.result] = True
             # Consider the two pointers (input and result) as
         else:
             raise AssertionError, op.opname
 
-    def insert_keepalives(self, newvars):
-        pass
 
 def remove_simple_mallocs(graph, type_system='lltypesystem', verbose=True):
     if type_system == 'lltypesystem':

pypy/translator/backendopt/mallocprediction.py

             break
         count += newcount
     for graph in graphs:
-        removenoops.remove_superfluous_keep_alive(graph)
         removenoops.remove_duplicate_casts(graph, translator)
     return count
 

pypy/translator/backendopt/mallocv.py

         else:
             return self.handle_default(op)
 
-    def handle_op_keepalive(self, op):
-        node = self.getnode(op.args[0])
-        if isinstance(node, VirtualSpecNode):
-            rtnodes, vtnodes = find_all_nodes([node])
-            newops = []
-            for rtnode in rtnodes:
-                v = self.renamings[rtnode]
-                if isinstance(v, Variable):
-                    T = v.concretetype
-                    if isinstance(T, lltype.Ptr) and T._needsgc():
-                        v0 = varoftype(lltype.Void)
-                        newops.append(SpaceOperation('keepalive', [v], v0))
-            return newops
-        else:
-            return self.handle_default(op)
-
     def handle_op_ptr_nonzero(self, op):
         node = self.getnode(op.args[0])
         if isinstance(node, VirtualSpecNode):

pypy/translator/backendopt/removenoops.py

         for i, op in list(enumerate(block.operations))[::-1]:
             if op.opname == "debug_assert":
                 del block.operations[i]
-
-def remove_superfluous_keep_alive(graph):
-    for block in graph.iterblocks():
-        used = {}
-        for i, op in list(enumerate(block.operations))[::-1]:
-            if op.opname == "keepalive":
-                if op.args[0] in used:
-                    del block.operations[i]
-                else:
-                    used[op.args[0]] = True
- 
-

pypy/translator/backendopt/support.py

         # assume PyObjPtr
         return True
 
-def needs_conservative_livevar_calculation(block):
-    from pypy.rpython.lltypesystem import rclass
-    vars = block.getvariables()
-    assert len(block.exits) == 1
-    exitingvars = block.exits[0].args
-    for var in vars:
-        TYPE = getattr(var, "concretetype", lltype.Ptr(lltype.PyObject))
-        if isinstance(TYPE, lltype.Ptr) and not var_needsgc(var):
-            if isinstance(TYPE.TO, lltype.FuncType):
-                continue
-            try:
-                lltype.castable(TYPE, rclass.CLASSTYPE)
-            except lltype.InvalidCast:
-                if var in exitingvars:
-                    return True
-    else:
-        return False
-
-def generate_keepalive(vars, annotator=None):
-    keepalive_ops = []
-    for v in vars:
-        if isinstance(v, Constant):
-            continue
-        if v.concretetype._is_atomic():
-            continue
-        v_keepalive = Variable()
-        v_keepalive.concretetype = lltype.Void
-        if annotator is not None:
-            annotator.setbinding(v_keepalive, s_ImpossibleValue)
-        keepalive_ops.append(SpaceOperation('keepalive', [v], v_keepalive))
-    return keepalive_ops
-
-def split_block_with_keepalive(block, index_operation,
-                               keep_alive_op_args=True,
-                               annotator=None):
-    splitlink = split_block(annotator, block, index_operation)
-    afterblock = splitlink.target
-    conservative_keepalives = needs_conservative_livevar_calculation(block)
-    if conservative_keepalives:
-        keep_alive_vars = [var for var in block.getvariables()
-                               if var_needsgc(var)]
-        # XXX you could maybe remove more, if the variables are kept
-        # alive by something else. but this is sometimes hard to know
-        for i, var in enumerate(keep_alive_vars):
-            try:
-                index = splitlink.args.index(var)
-                newvar = afterblock.inputargs[index]
-            except ValueError:
-                splitlink.args.append(var)
-                newvar = copyvar(annotator, var)
-                afterblock.inputargs.append(newvar)
-            keep_alive_vars[i] = newvar
-    elif keep_alive_op_args and afterblock.operations: 
-        keep_alive_vars = [var for var in afterblock.operations[0].args
-                               if isinstance(var, Variable) and var_needsgc(var)]
-        if len(afterblock.operations) > 1 or afterblock.exitswitch != c_last_exception:
-            afterblock.operations[1:1] = generate_keepalive(keep_alive_vars,
-                                                            annotator=annotator)
-            keep_alive_vars = []
-    else:
-        keep_alive_vars = []
-    pos = len(afterblock.operations)
-    if afterblock.exitswitch == c_last_exception:
-        pos -= 1    # insert the keepalives just before the last operation
-                    # in case of exception-catching
-    afterblock.operations[pos:pos] = generate_keepalive(keep_alive_vars)
-    return splitlink
-
 def find_calls_from(translator, graph, memo=None):
     if memo and graph in memo:
         return memo[graph]

pypy/translator/backendopt/test/test_constfold.py

     check_graph(graph, [0], 61, t)
 
 
-def test_keepalive_const_substruct():
-    py.test.skip("do we want partial folding of getinteriorfield?")
-    S2 = lltype.Struct('S2', ('x', lltype.Signed))
-    S1 = lltype.GcStruct('S1', ('sub', S2))
-    s1 = lltype.malloc(S1)
-    s1.sub.x = 1234
-    def fn():
-        return s1.sub.x
-    graph, t = get_graph(fn, [])
-    assert summary(graph) == {'getinteriorfield': 1}
-    constant_fold_graph(graph)
-
-    # kill all references to 's1'
-    s1 = fn = None
-    del graph.func
-    import gc; gc.collect()
-
-    assert summary(graph) == {'getfield': 1}
-    check_graph(graph, [], 1234, t)
-
-
 def test_keepalive_const_fieldptr():
     S1 = lltype.GcStruct('S1', ('x', lltype.Signed))
     s1 = lltype.malloc(S1)

pypy/translator/backendopt/test/test_malloc.py

             auto_inline_graphs(t, t.graphs, inline)
         if option.view:
             t.view()
-        # to detect missing keepalives and broken intermediate graphs,
+        # to detect broken intermediate graphs,
         # we do the loop ourselves instead of calling remove_simple_mallocs()
         while True:
             progress = remover.remove_mallocs_once(graph)
     type_system = 'lltype'
     MallocRemover = LLTypeMallocRemover
 
-    def test_with_keepalive(self):
-        from pypy.rlib.objectmodel import keepalive_until_here
-        def fn1(x, y):
-            if x > 0:
-                t = x+y, x-y
-            else:
-                t = x-y, x+y
-            s, d = t
-            keepalive_until_here(t)
-            return s*d
-        self.check(fn1, [int, int], [15, 10], 125)
-
     def test_dont_remove_with__del__(self):
         import os
         delcalls = [0]
         op = graph.startblock.exits[0].target.exits[1].target.operations[0]
         assert op.opname == "malloc"
 
-    def test_add_keepalives(self):
-        class A:
-            pass
-        SMALL = lltype.Struct('SMALL', ('x', lltype.Signed))
-        BIG = lltype.GcStruct('BIG', ('z', lltype.Signed), ('s', SMALL))
-        def fn7(i):
-            big = lltype.malloc(BIG)
-            a = A()
-            a.big = big
-            a.small = big.s
-            a.small.x = 0
-            while i > 0:
-                a.small.x += i
-                i -= 1
-            return a.small.x
-        self.check(fn7, [int], [10], 55, must_be_removed=False)
-
-    def test_getsubstruct(self):
-        py.test.skip("fails because of the interior structure changes")
-        SMALL = lltype.Struct('SMALL', ('x', lltype.Signed))
-        BIG = lltype.GcStruct('BIG', ('z', lltype.Signed), ('s', SMALL))
-
-        def fn(n1, n2):
-            b = lltype.malloc(BIG)
-            b.z = n1
-            b.s.x = n2
-            return b.z - b.s.x
-
-        self.check(fn, [int, int], [100, 58], 42)
-
-    def test_fixedsizearray(self):
-        py.test.skip("fails because of the interior structure changes")
-        A = lltype.FixedSizeArray(lltype.Signed, 3)
-        S = lltype.GcStruct('S', ('a', A))
-
-        def fn(n1, n2):
-            s = lltype.malloc(S)
-            a = s.a
-            a[0] = n1
-            a[2] = n2
-            return a[0]-a[2]
-
-        self.check(fn, [int, int], [100, 42], 58)
-
     def test_wrapper_cannot_be_removed(self):
         SMALL = lltype.OpaqueType('SMALL')
         BIG = lltype.GcStruct('BIG', ('z', lltype.Signed), ('s', SMALL))

pypy/translator/backendopt/test/test_mallocv.py

         if option.view:
             t.view()
         self.original_graph_count = len(t.graphs)
-        # to detect missing keepalives and broken intermediate graphs,
+        # to detect broken intermediate graphs,
         # we do the loop ourselves instead of calling remove_simple_mallocs()
         maxiter = 100
         mallocv = MallocVirtualizer(t.graphs, t.rtyper, verbose=True)
     type_system = 'lltype'
     #MallocRemover = LLTypeMallocRemover
 
-    def test_with_keepalive(self):
-        from pypy.rlib.objectmodel import keepalive_until_here
-        def fn1(x, y):
-            if x > 0:
-                t = x+y, x-y
-            else:
-                t = x-y, x+y
-            s, d = t
-            keepalive_until_here(t)
-            return s*d
-        self.check(fn1, [int, int], [15, 10], 125)
-
-    def test_add_keepalives(self):
-        class A:
-            pass
-        SMALL = lltype.Struct('SMALL', ('x', lltype.Signed))
-        BIG = lltype.GcStruct('BIG', ('z', lltype.Signed), ('s', SMALL))
-        def fn7(i):
-            big = lltype.malloc(BIG)
-            a = A()
-            a.big = big
-            a.small = big.s
-            a.small.x = 0
-            while i > 0:
-                a.small.x += i
-                i -= 1
-            return a.small.x
-        self.check(fn7, [int], [10], 55,
-                   expected_mallocs=1)   # no support for interior structs
-
     def test_getsubstruct(self):
         SMALL = lltype.Struct('SMALL', ('x', lltype.Signed))
         BIG = lltype.GcStruct('BIG', ('z', lltype.Signed), ('s', SMALL))
             return x.u1.b * x.u2.a
         self.check(fn, [], [], DONT_CHECK_RESULT)
 
-    def test_keep_all_keepalives(self):
-        SIZE = llmemory.sizeof(lltype.Signed)
-        PARRAY = lltype.Ptr(lltype.FixedSizeArray(lltype.Signed, 1))
-        class A:
-            def __init__(self):
-                self.addr = llmemory.raw_malloc(SIZE)
-            def __del__(self):
-                llmemory.raw_free(self.addr)
-        class B:
-            pass
-        def myfunc():
-            b = B()
-            b.keep = A()
-            b.data = llmemory.cast_adr_to_ptr(b.keep.addr, PARRAY)
-            b.data[0] = 42
-            ptr = b.data
-            # normally 'b' could go away as early as here, which would free
-            # the memory held by the instance of A in b.keep...
-            res = ptr[0]
-            # ...so we explicitly keep 'b' alive until here
-            objectmodel.keepalive_until_here(b)
-            return res
-        graph = self.check(myfunc, [], [], 42,
-                           expected_mallocs=1,    # 'A' instance left
-                           expected_calls=1)      # to A.__init__()
-
-        # there is a getarrayitem near the end of the graph of myfunc.
-        # However, the memory it accesses must still be protected by the
-        # following keepalive, even after malloc removal
-        entrymap = mkentrymap(graph)
-        [link] = entrymap[graph.returnblock]
-        assert link.prevblock.operations[-1].opname == 'keepalive'
-
     def test_nested_struct(self):
         S = lltype.GcStruct("S", ('x', lltype.Signed))
         T = lltype.GcStruct("T", ('s', S))

pypy/translator/backendopt/test/test_removenoops.py

 from pypy.translator.backendopt.removenoops import remove_same_as, \
-        remove_unaryops, remove_duplicate_casts, remove_superfluous_keep_alive
+        remove_unaryops, remove_duplicate_casts
 from pypy.translator.backendopt.inline import simple_inline_function
 from pypy.translator.translator import TranslationContext, graphof
 from pypy.rpython.memory.gctransform.test.test_transform import getops
     result = interp.eval_graph(f_graph, [-2])
     assert result == -1
 
-def test_remove_keepalive():
-    S = lltype.GcStruct("s", ("f", lltype.Signed))
-    def f():
-        s1 = lltype.malloc(S)
-        llop.keepalive(lltype.Void, s1)
-        s2 = lltype.malloc(S)
-        llop.keepalive(lltype.Void, s1)
-        llop.keepalive(lltype.Void, s2)
-        return lltype.cast_ptr_to_int(s1) + lltype.cast_ptr_to_int(s2)
-    graph, t = get_graph(f, [])
-    remove_superfluous_keep_alive(graph)
-    ops = getops(graph)
-    assert len(ops['keepalive']) == 2
-
 def test_remove_duplicate_casts():
     class A(object):
         def __init__(self, x, y):

pypy/translator/backendopt/test/test_support.py

-from pypy.translator.unsimplify import varoftype
 from pypy.translator.translator import TranslationContext, graphof
 from pypy.translator.backendopt.support import \
-     needs_conservative_livevar_calculation, split_block_with_keepalive, \
      find_loop_blocks, find_backedges, compute_reachability
 
-from pypy.rpython.rtyper import LowLevelOpList
-from pypy.rpython.lltypesystem import lltype
-from pypy.objspace.flow import model
-
-NonGcB = lltype.Struct("B", ('x', lltype.Signed))
-GcA = lltype.GcStruct("A", ('b', NonGcB), ('c', lltype.Ptr(lltype.FuncType([], lltype.Void))))
-
-def test_nclc_should_be_true():
-    # this is testing a block like:
-    # +--- inputargs: pointer_to_gc
-    # | v0 <- op_getsubstruct pointer_to_gc 'b'
-    # +--- exitargs: v0 (i.e. pointer to non-gc)
-    llops = LowLevelOpList()
-    ptr_a = varoftype(lltype.Ptr(GcA))
-    v_res = llops.genop("getsubstruct", [ptr_a, model.Constant('b', lltype.Void)],
-                        resulttype=lltype.Ptr(NonGcB))
-    block = model.Block([ptr_a])
-    block.operations.extend(llops)
-    block.closeblock(model.Link([v_res], None))
-    assert needs_conservative_livevar_calculation(block)
-
-def test_nclc_nongc_not_passed_on():
-    # +--- inputargs: pointer_to_gc
-    # | v0 <- op_getsubstruct pointer_to_gc 'b'
-    # +--- exitargs: pointer_to_gc (i.e. the pointer to non-gc doesn't leave the block)
-    llops = LowLevelOpList()
-    ptr_a = varoftype(lltype.Ptr(GcA))
-    v_res = llops.genop("getsubstruct", [ptr_a, model.Constant('b', lltype.Void)],
-                        resulttype=lltype.Ptr(NonGcB))
-    block = model.Block([ptr_a])
-    block.operations.extend(llops)
-    block.closeblock(model.Link([ptr_a], None))
-    assert not needs_conservative_livevar_calculation(block)
-
-def test_nclc_ignore_functype():
-    # +--- inputargs: pointer_to_gc
-    # | v0 <- op_getfield pointer_to_gc 'c'
-    # +--- exitargs: v0 (i.e. a pointer to function)
-    # pointers to functions are 'not gc' but functions are also
-    # immortal so you don't need to muck around inserting keepalives
-    # so *they* don't die!
-    llops = LowLevelOpList()
-    ptr_a = varoftype(lltype.Ptr(GcA))
-    v_res = llops.genop("getfield", [ptr_a, model.Constant('c', lltype.Void)],
-                        resulttype=GcA.c)
-    block = model.Block([ptr_a])
-    block.operations.extend(llops)
-    block.closeblock(model.Link([v_res], None))
-    assert not needs_conservative_livevar_calculation(block)
-
-def test_sbwk_should_insert_keepalives():
-    # this is testing something like:
-    # v0 <- op_producing_non_gc
-    # v1 <- op_using_v0        <- split here
-    llops = LowLevelOpList()
-    ptr_a = varoftype(lltype.Ptr(GcA))
-    v_res = llops.genop("getfield", [ptr_a, model.Constant('b', lltype.Void)],
-                        resulttype=lltype.Ptr(NonGcB))
-    llops.genop("direct_call", [model.Constant(None, lltype.Void), v_res],
-                resulttype=lltype.Void)
-    block = model.Block([ptr_a])
-    block.operations.extend(llops)
-    block.closeblock(model.Link([], None))
-    link = split_block_with_keepalive(block, 1)
-    assert 'keepalive' in [op.opname for op in link.target.operations]
-
-def test_sbwk_should_insert_keepalives_2():
-    # this is testing something like:
-    # v0 <- op_producing_non_gc
-    # v1 <- op_not_using_v0        <- split here
-    # v2 <- op_using_v0
-    llops = LowLevelOpList()
-    ptr_a = varoftype(lltype.Ptr(GcA))
-    v_res = llops.genop("getfield", [ptr_a, model.Constant('b', lltype.Void)],
-                        resulttype=lltype.Ptr(NonGcB))
-    llops.genop("direct_call", [model.Constant(None, lltype.Void)],
-                resulttype=lltype.Void)
-    llops.genop("direct_call", [model.Constant(None, lltype.Void), v_res],
-                resulttype=lltype.Void)
-    block = model.Block([ptr_a])
-    block.operations.extend(llops)
-    block.closeblock(model.Link([], None))
-    link = split_block_with_keepalive(block, 1)
-    assert 'keepalive' in [op.opname for op in link.target.operations]
-
 #__________________________________________________________
 # test compute_reachability
 

pypy/translator/exceptiontransform.py

             n_need_exc_matching_blocks += need_exc_matching
             n_gen_exc_checks           += gen_exc_checks
         cleanup_graph(graph)
-        removenoops.remove_superfluous_keep_alive(graph)
         return n_need_exc_matching_blocks, n_gen_exc_checks
 
     def replace_stack_unwind(self, block):

pypy/translator/stackless/transform.py

 from pypy.rpython.lltypesystem.lloperation import LL_OPERATIONS
 from pypy.rlib import rarithmetic
 from pypy.rpython import rclass, rmodel
-from pypy.translator.backendopt import support
+from pypy.translator.unsimplify import split_block
 from pypy.objspace.flow import model
 from pypy.translator import unsimplify, simplify
 from pypy.translator.unsimplify import varoftype
             link = block.exits[0]
             nextblock = None
         else:
-            link = support.split_block_with_keepalive(block, i+1)
+            link = split_block(None, block, i+1)
             i = 0
             nextblock = link.target
 
             exitcases = dict.fromkeys([l.exitcase for l in block.exits])
             nextblock = None
         else:
-            link = support.split_block_with_keepalive(block, i+1)
+            link = split_block(None, block, i+1)
             nextblock = link.target
             block.exitswitch = model.c_last_exception
             link.llexitcase = None

pypy/translator/test/test_simplify.py

     assert graph.startblock.operations[-1].opname == 'direct_call'
 
 
-def test_remove_pointless_keepalive():
-    from pypy.rlib import objectmodel
-    class C:
-        y = None
-        z1 = None
-        z2 = None
-
-    def g():
-        return C()
-
-    def f(i):
-        c = g()
-        c.y
-        if i:
-            n = c.z1
-        else:
-            n = c.z2
-        objectmodel.keepalive_until_here(c, n)
-
-    graph, t = translate(f, [bool])
-
-    #t.view()
-
-    for block in graph.iterblocks():
-        for op in block.operations:
-            assert op.opname != 'getfield'
-            if op.opname == 'keepalive':
-                assert op.args[0] in graph.getargs()
-
-
 def test_remove_identical_variables():
     def g(code):
         pc = 0

pypy/translator/unsimplify.py

 def split_block(annotator, block, index, _forcelink=None):
     """return a link where prevblock is the block leading up but excluding the
     index'th operation and target is a new block with the neccessary variables 
-    passed on.  NOTE: if you call this after rtyping, you WILL need to worry
-    about keepalives, you may use backendopt.support.split_block_with_keepalive.
+    passed on.
     """
     assert 0 <= index <= len(block.operations)
     if block.exitswitch == c_last_exception: