def create_exception_handling(self, graph):
        """After an exception in a direct_call (or indirect_call), that is not caught
        by an explicit
        except statement, we need to reraise the exception. So after this
        direct_call we need to test if an exception had occurred. If so, we return
        from the current graph with a special value (False/-1/-1.0/null).
        Because of the added exitswitch we need an additional block.
        """
        if hasattr(graph, "exceptiontransformed"):
            assert self.same_obj(self.exc_data_ptr, graph.exceptiontransformed)
            return
        else:
            self.raise_analyzer.analyze_direct_call(graph)
            graph.exceptiontransformed = self.exc_data_ptr

        join_blocks(graph)
        # collect the blocks before changing them
        n_need_exc_matching_blocks = 0
        n_gen_exc_checks = 0
        #
        entrymap = mkentrymap(graph)
        if graph.exceptblock in entrymap:
            for link in entrymap[graph.exceptblock]:
                self.transform_jump_to_except_block(graph, entrymap, link)
        #
        for block in list(graph.iterblocks()):
            self.replace_fetch_restore_operations(block)
            need_exc_matching, gen_exc_checks = self.transform_block(graph, block)
            n_need_exc_matching_blocks += need_exc_matching
            n_gen_exc_checks += gen_exc_checks
        cleanup_graph(graph)
        return n_need_exc_matching_blocks, n_gen_exc_checks
Beispiel #2
0
    def create_exception_handling(self, graph, always_exc_clear=False):
        """After an exception in a direct_call (or indirect_call), that is not caught
        by an explicit
        except statement, we need to reraise the exception. So after this
        direct_call we need to test if an exception had occurred. If so, we return
        from the current graph with a special value (False/-1/-1.0/null).
        Because of the added exitswitch we need an additional block.
        """
        if hasattr(graph, 'exceptiontransformed'):
            assert self.same_obj(self.exc_data_ptr, graph.exceptiontransformed)
            return
        else:
            self.raise_analyzer.analyze_direct_call(graph)
            graph.exceptiontransformed = self.exc_data_ptr

        self.always_exc_clear = always_exc_clear
        join_blocks(graph)
        # collect the blocks before changing them
        n_need_exc_matching_blocks = 0
        n_gen_exc_checks = 0
        for block in list(graph.iterblocks()):
            self.replace_stack_unwind(block)
            self.replace_fetch_restore_operations(block)
            need_exc_matching, gen_exc_checks = self.transform_block(
                graph, block)
            n_need_exc_matching_blocks += need_exc_matching
            n_gen_exc_checks += gen_exc_checks
        self.transform_except_block(graph, graph.exceptblock)
        cleanup_graph(graph)
        removenoops.remove_superfluous_keep_alive(graph)
        return n_need_exc_matching_blocks, n_gen_exc_checks
Beispiel #3
0
def test_replace_exitswitch_by_constant_bug():
    class X:
        pass
    def constant9():
        x = X()
        x.n = 3
        x.n = 9
        return x.n
    def fn():
        n = constant9()
        if n == 1: return 5
        elif n == 2: return 6
        elif n == 3: return 8
        elif n == 4: return -123
        elif n == 5: return 12973
        else: return n
    
    t = TranslationContext()
    a = t.buildannotator()
    a.build_types(fn, [])
    rtyper = t.buildrtyper()
    rtyper.specialize()
    graph = t.graphs[0]
    remove_same_as(graph)
    merge_if_blocks_once(graph)
    from pypy.translator.backendopt import malloc, inline
    inline.auto_inlining(t, 20)
    malloc.remove_mallocs(t, t.graphs)
    from pypy.translator import simplify
    simplify.join_blocks(graph)
Beispiel #4
0
    def create_exception_handling(self, graph):
        """After an exception in a direct_call (or indirect_call), that is not caught
        by an explicit
        except statement, we need to reraise the exception. So after this
        direct_call we need to test if an exception had occurred. If so, we return
        from the current graph with a special value (False/-1/-1.0/null).
        Because of the added exitswitch we need an additional block.
        """
        if hasattr(graph, 'exceptiontransformed'):
            assert self.same_obj(self.exc_data_ptr, graph.exceptiontransformed)
            return
        else:
            self.raise_analyzer.analyze_direct_call(graph)
            graph.exceptiontransformed = self.exc_data_ptr

        join_blocks(graph)
        # collect the blocks before changing them
        n_need_exc_matching_blocks = 0
        n_gen_exc_checks = 0
        #
        entrymap = mkentrymap(graph)
        if graph.exceptblock in entrymap:
            for link in entrymap[graph.exceptblock]:
                self.transform_jump_to_except_block(graph, entrymap, link)
        #
        for block in list(graph.iterblocks()):
            self.replace_fetch_restore_operations(block)
            need_exc_matching, gen_exc_checks = self.transform_block(
                graph, block)
            n_need_exc_matching_blocks += need_exc_matching
            n_gen_exc_checks += gen_exc_checks
        cleanup_graph(graph)
        return n_need_exc_matching_blocks, n_gen_exc_checks
Beispiel #5
0
 def test_tweak_generator_graph(self):
     def f(n, x, y, z):
         z *= 10
         yield n + 1
         z -= 10
     #
     space = FlowObjSpace()
     graph = space.build_flow(f, tweak_for_generator=False)
     GeneratorIterator = make_generatoriterator_class(graph)
     replace_graph_with_bootstrap(GeneratorIterator, graph)
     func1 = attach_next_method(GeneratorIterator, graph)
     if option.view:
         graph.show()
     #
     assert func1._generator_next_method_of_ is GeneratorIterator
     assert hasattr(GeneratorIterator, 'next')
     #
     graph_next = space.build_flow(GeneratorIterator.next.im_func)
     join_blocks(graph_next)
     if option.view:
         graph_next.show()
     #
     graph1 = space.build_flow(func1, tweak_for_generator=False)
     tweak_generator_body_graph(GeneratorIterator.Entry, graph1)
     if option.view:
         graph1.show()
Beispiel #6
0
def remove_asserts(translator, graphs):
    rtyper = translator.rtyper
    clsdef = translator.annotator.bookkeeper.getuniqueclassdef(AssertionError)
    r_AssertionError = rclass.getclassrepr(rtyper, clsdef)
    ll_AssertionError = r_AssertionError.convert_const(AssertionError)
    total_count = [0, 0]

    for graph in graphs:
        count = 0
        morework = True
        while morework:
            morework = False
            eliminate_empty_blocks(graph)
            join_blocks(graph)
            for link in graph.iterlinks():
                if (link.target is graph.exceptblock
                    and isinstance(link.args[0], Constant)
                    and link.args[0].value == ll_AssertionError):
                    if kill_assertion_link(graph, link):
                        count += 1
                        morework = True
                        break
                    else:
                        total_count[0] += 1
                        if translator.config.translation.verbose:
                            log.removeassert("cannot remove an assert from %s" % (graph.name,))
        if count:
            # now melt away the (hopefully) dead operation that compute
            # the condition
            total_count[1] += count
            if translator.config.translation.verbose:
                log.removeassert("removed %d asserts in %s" % (count, graph.name))
            checkgraph(graph)
            #transform_dead_op_vars(graph, translator)
    log.removeassert("Could not remove %d asserts, but removed %d asserts." % tuple(total_count))
    def create_exception_handling(self, graph, always_exc_clear=False):
        """After an exception in a direct_call (or indirect_call), that is not caught
        by an explicit
        except statement, we need to reraise the exception. So after this
        direct_call we need to test if an exception had occurred. If so, we return
        from the current graph with a special value (False/-1/-1.0/null).
        Because of the added exitswitch we need an additional block.
        """
        if hasattr(graph, 'exceptiontransformed'):
            assert self.same_obj(self.exc_data_ptr, graph.exceptiontransformed)
            return
        else:
            self.raise_analyzer.analyze_direct_call(graph)
            graph.exceptiontransformed = self.exc_data_ptr

        self.always_exc_clear = always_exc_clear
        join_blocks(graph)
        # collect the blocks before changing them
        n_need_exc_matching_blocks = 0
        n_gen_exc_checks           = 0
        for block in list(graph.iterblocks()):
            self.replace_stack_unwind(block)
            self.replace_fetch_restore_operations(block)
            need_exc_matching, gen_exc_checks = self.transform_block(graph, block)
            n_need_exc_matching_blocks += need_exc_matching
            n_gen_exc_checks           += gen_exc_checks
        self.transform_except_block(graph, graph.exceptblock)
        cleanup_graph(graph)
        removenoops.remove_superfluous_keep_alive(graph)
        return n_need_exc_matching_blocks, n_gen_exc_checks
Beispiel #8
0
def test_replace_exitswitch_by_constant_bug():
    class X:
        pass
    def constant9():
        x = X()
        x.n = 3
        x.n = 9
        return x.n
    def fn():
        n = constant9()
        if n == 1: return 5
        elif n == 2: return 6
        elif n == 3: return 8
        elif n == 4: return -123
        elif n == 5: return 12973
        else: return n
    
    t = TranslationContext()
    a = t.buildannotator()
    a.build_types(fn, [])
    rtyper = t.buildrtyper()
    rtyper.specialize()
    graph = t.graphs[0]
    remove_same_as(graph)
    merge_if_blocks_once(graph)
    from pypy.translator.backendopt import malloc, inline
    inline.auto_inlining(t, 20)
    malloc.remove_mallocs(t, t.graphs)
    from pypy.translator import simplify
    simplify.join_blocks(graph)
Beispiel #9
0
 def test_wearetranslated(self):
     x = self.codetest(self.wearetranslated)
     from pypy.translator.simplify import join_blocks
     join_blocks(x)
     # check that 'x' is an empty graph
     assert len(x.startblock.operations) == 0
     assert len(x.startblock.exits) == 1
     assert x.startblock.exits[0].target is x.returnblock
Beispiel #10
0
 def test_wearetranslated(self):
     x = self.codetest(self.wearetranslated)
     from pypy.translator.simplify import join_blocks
     join_blocks(x)
     # check that 'x' is an empty graph
     assert len(x.startblock.operations) == 0
     assert len(x.startblock.exits) == 1
     assert x.startblock.exits[0].target is x.returnblock
Beispiel #11
0
 def test_specialcases(self):
     x = self.codetest(self.specialcases)
     from pypy.translator.simplify import join_blocks
     join_blocks(x)
     assert len(x.startblock.operations) == 14
     for op in x.startblock.operations:
         assert op.opname in ['lt', 'le', 'eq', 'ne',
                                    'gt', 'ge', 'is_', 'xor']
         assert len(op.args) == 2
         assert op.args[1].value == 3
Beispiel #12
0
 def test_specialcases(self):
     x = self.codetest(self.specialcases)
     from pypy.translator.simplify import join_blocks
     join_blocks(x)
     assert len(x.startblock.operations) == 14
     for op in x.startblock.operations:
         assert op.opname in ['lt', 'le', 'eq', 'ne',
                                    'gt', 'ge', 'is_', 'xor']
         assert len(op.args) == 2
         assert op.args[1].value == 3
Beispiel #13
0
    def test_specialcases(self):
        x = self.codetest(self.specialcases)
        from pypy.translator.simplify import join_blocks

        join_blocks(x)
        assert len(x.startblock.operations) == 14
        for op in x.startblock.operations:
            assert op.opname in ["lt", "le", "eq", "ne", "gt", "ge", "is_", "xor"]
            assert len(op.args) == 2
            assert op.args[1].value == 3
Beispiel #14
0
def virtualize_mallocs(translator, graphs, verbose=False):
    newgraphs = graphs[:]
    mallocv = MallocVirtualizer(newgraphs, translator.rtyper, verbose)
    while mallocv.remove_mallocs_once():
        pass
    for graph in newgraphs:
        checkgraph(graph)
        join_blocks(graph)
    assert newgraphs[:len(graphs)] == graphs
    del newgraphs[:len(graphs)]
    translator.graphs.extend(newgraphs)
Beispiel #15
0
def remove_duplicate_casts(graph, translator):
    simplify.join_blocks(graph)
    num_removed = 0
    # remove chains of casts
    for block in graph.iterblocks():
        comes_from = {}
        for op in block.operations:
            if op.opname == "cast_pointer":
                if op.args[0] in comes_from:
                    from_var = comes_from[op.args[0]]
                    comes_from[op.result] = from_var
                    if from_var.concretetype == op.result.concretetype:
                        op.opname = "same_as"
                        op.args = [from_var]
                        num_removed += 1
                    else:
                        op.args = [from_var]
                else:
                    comes_from[op.result] = op.args[0]
    if num_removed:
        remove_same_as(graph)
    # remove duplicate casts
    for block in graph.iterblocks():
        available = {}
        for op in block.operations:
            if op.opname == "cast_pointer":
                key = (op.args[0], op.result.concretetype)
                if key in available:
                    op.opname = "same_as"
                    op.args = [available[key]]
                    num_removed += 1
                else:
                    available[key] = op.result
            elif op.opname == 'resume_point':
                available.clear()
    if num_removed:
        remove_same_as(graph)
        # remove casts with unused results
        for block in graph.iterblocks():
            used = {}
            for link in block.exits:
                for arg in link.args:
                    used[arg] = True
            for i, op in list(enumerate(block.operations))[::-1]:
                if op.opname == "cast_pointer" and op.result not in used:
                    del block.operations[i]
                    num_removed += 1
                else:
                    for arg in op.args:
                        used[arg] = True
        if translator.config.translation.verbose:
            log.removecasts(
                "removed %s cast_pointers in %s" % (num_removed, graph.name))
    return num_removed
Beispiel #16
0
def virtualize_mallocs(translator, graphs, verbose=False):
    newgraphs = graphs[:]
    mallocv = MallocVirtualizer(newgraphs, translator.rtyper, verbose)
    while mallocv.remove_mallocs_once():
        pass
    for graph in newgraphs:
        checkgraph(graph)
        join_blocks(graph)
    assert newgraphs[:len(graphs)] == graphs
    del newgraphs[:len(graphs)]
    translator.graphs.extend(newgraphs)
Beispiel #17
0
def remove_duplicate_casts(graph, translator):
    simplify.join_blocks(graph)
    num_removed = 0
    # remove chains of casts
    for block in graph.iterblocks():
        comes_from = {}
        for op in block.operations:
            if op.opname == "cast_pointer":
                if op.args[0] in comes_from:
                    from_var = comes_from[op.args[0]]
                    comes_from[op.result] = from_var
                    if from_var.concretetype == op.result.concretetype:
                        op.opname = "same_as"
                        op.args = [from_var]
                        num_removed += 1
                    else:
                        op.args = [from_var]
                else:
                    comes_from[op.result] = op.args[0]
    if num_removed:
        remove_same_as(graph)
    # remove duplicate casts
    for block in graph.iterblocks():
        available = {}
        for op in block.operations:
            if op.opname == "cast_pointer":
                key = (op.args[0], op.result.concretetype)
                if key in available:
                    op.opname = "same_as"
                    op.args = [available[key]]
                    num_removed += 1
                else:
                    available[key] = op.result
            elif op.opname == 'resume_point':
                available.clear()
    if num_removed:
        remove_same_as(graph)
        # remove casts with unused results
        for block in graph.iterblocks():
            used = {}
            for link in block.exits:
                for arg in link.args:
                    used[arg] = True
            for i, op in list(enumerate(block.operations))[::-1]:
                if op.opname == "cast_pointer" and op.result not in used:
                    del block.operations[i]
                    num_removed += 1
                else:
                    for arg in op.args:
                        used[arg] = True
        if translator.config.translation.verbose:
            log.removecasts("removed %s cast_pointers in %s" %
                            (num_removed, graph.name))
    return num_removed
def transform_func(fn, inputtypes):
    t = TranslationContext()
    t.buildannotator().build_types(fn, inputtypes)
    t.buildrtyper().specialize()
    if conftest.option.view:
        t.view()
    g = graphof(t, fn)
    etrafo = exceptiontransform.ExceptionTransformer(t)
    etrafo.create_exception_handling(g)
    join_blocks(g)
    if conftest.option.view:
        t.view()
    return t, g
Beispiel #19
0
 def transform_func(self, fn, inputtypes, backendopt=False):
     t = TranslationContext()
     t.buildannotator().build_types(fn, inputtypes)
     t.buildrtyper(type_system=self.type_system).specialize()
     if conftest.option.view:
         t.view()
     if backendopt:
         backend_optimizations(t)
     g = graphof(t, fn)
     etrafo = exceptiontransform.ExceptionTransformer(t)
     etrafo.create_exception_handling(g)
     join_blocks(g)
     if conftest.option.view:
         t.view()
     return t, g
Beispiel #20
0
 def transform_func(self, fn, inputtypes, backendopt=False):
     t = TranslationContext()
     t.buildannotator().build_types(fn, inputtypes)
     t.buildrtyper(type_system=self.type_system).specialize()
     if conftest.option.view:
         t.view()
     if backendopt:
         backend_optimizations(t)
     g = graphof(t, fn)
     etrafo = exceptiontransform.ExceptionTransformer(t)
     etrafo.create_exception_handling(g)
     join_blocks(g)
     if conftest.option.view:
         t.view()
     return t, g
Beispiel #21
0
 def __init__(self, translator, graph, inline_func, lltype_to_classdef,
              inline_guarded_calls=False,
              inline_guarded_calls_no_matter_what=False,
              raise_analyzer=None,
              call_count_pred=None):
     BaseInliner.__init__(self, translator, graph, lltype_to_classdef,
                          inline_guarded_calls,
                          inline_guarded_calls_no_matter_what,
                          raise_analyzer,
                          call_count_pred)
     self.inline_func = inline_func
     # to simplify exception matching
     join_blocks(graph)
     # find callsites *after* joining blocks...
     callsites = find_callsites(graph, inline_func)
     self.block_to_index = {}
     for g, block, i in callsites:
         self.block_to_index.setdefault(block, {})[i] = g
Beispiel #22
0
def remove_tail_calls_to_self(translator, graph):
    entrymap = mkentrymap(graph)
    changed = False
    for link in entrymap[graph.returnblock]:
        block = link.prevblock
        if (len(block.exits) == 1 and len(block.operations) > 0
                and block.operations[-1].opname == 'direct_call'
                and block.operations[-1].result == link.args[0]):
            call = get_graph(block.operations[-1].args[0], translator)
            print "getgraph", graph
            if graph is graph:
                _remove_tail_call(translator, graph, block)
                changed = True
    if changed:
        from pypy.translator import simplify
        checkgraph(graph)
        simplify.remove_identical_vars(graph)
        simplify.eliminate_empty_blocks(graph)
        simplify.join_blocks(graph)
Beispiel #23
0
 def __init__(self, translator, graph, inline_func, lltype_to_classdef,
              inline_guarded_calls=False,
              inline_guarded_calls_no_matter_what=False,
              raise_analyzer=None,
              call_count_pred=None,
              cleanup=True):
     BaseInliner.__init__(self, translator, graph, lltype_to_classdef,
                          inline_guarded_calls,
                          inline_guarded_calls_no_matter_what,
                          raise_analyzer,
                          call_count_pred,
                          cleanup)
     self.inline_func = inline_func
     # to simplify exception matching
     join_blocks(graph)
     # find callsites *after* joining blocks...
     callsites = find_callsites(graph, inline_func)
     self.block_to_index = {}
     for g, block, i in callsites:
         self.block_to_index.setdefault(block, {})[i] = g
Beispiel #24
0
def remove_tail_calls_to_self(translator, graph):
    entrymap = mkentrymap(graph)
    changed = False
    for link in entrymap[graph.returnblock]:
        block = link.prevblock
        if (len(block.exits) == 1 and
            len(block.operations) > 0 and
            block.operations[-1].opname == 'direct_call' and
            block.operations[-1].result == link.args[0]):
            call = get_graph(block.operations[-1].args[0], translator)
            print "getgraph", graph
            if graph is graph:
                _remove_tail_call(translator, graph, block)
                changed = True
    if changed:
        from pypy.translator import simplify
        checkgraph(graph)
        simplify.remove_identical_vars(graph)
        simplify.eliminate_empty_blocks(graph)
        simplify.join_blocks(graph)
Beispiel #25
0
def remove_asserts(translator, graphs):
    rtyper = translator.rtyper
    clsdef = translator.annotator.bookkeeper.getuniqueclassdef(AssertionError)
    r_AssertionError = rclass.getclassrepr(rtyper, clsdef)
    ll_AssertionError = r_AssertionError.convert_const(AssertionError)
    total_count = [0, 0]

    for graph in graphs:
        count = 0
        morework = True
        while morework:
            morework = False
            eliminate_empty_blocks(graph)
            join_blocks(graph)
            for link in graph.iterlinks():
                if (link.target is graph.exceptblock
                        and isinstance(link.args[0], Constant)
                        and link.args[0].value == ll_AssertionError):
                    if kill_assertion_link(graph, link):
                        count += 1
                        morework = True
                        break
                    else:
                        total_count[0] += 1
                        if translator.config.translation.verbose:
                            log.removeassert(
                                "cannot remove an assert from %s" %
                                (graph.name, ))
        if count:
            # now melt away the (hopefully) dead operation that compute
            # the condition
            total_count[1] += count
            if translator.config.translation.verbose:
                log.removeassert("removed %d asserts in %s" %
                                 (count, graph.name))
            checkgraph(graph)
            #transform_dead_op_vars(graph, translator)
    log.removeassert("Could not remove %d asserts, but removed %d asserts." %
                     tuple(total_count))