예제 #1
0
def memo(funcdesc, arglist_s):
    from rpython.annotator.model import SomePBC, SomeImpossibleValue, SomeBool
    from rpython.annotator.model import unionof
    # call the function now, and collect possible results
    argvalues = []
    for s in arglist_s:
        if s.is_constant():
            values = [s.const]
        elif isinstance(s, SomePBC):
            values = []
            assert not s.can_be_None, "memo call: cannot mix None and PBCs"
            for desc in s.descriptions:
                if desc.pyobj is None:
                    raise annmodel.AnnotatorError(
                        "memo call with a class or PBC that has no "
                        "corresponding Python object (%r)" % (desc,))
                values.append(desc.pyobj)
        elif isinstance(s, SomeImpossibleValue):
            return s    # we will probably get more possible args later
        elif isinstance(s, SomeBool):
            values = [False, True]
        else:
            raise annmodel.AnnotatorError("memo call: argument must be a class "
                                          "or a frozen PBC, got %r" % (s,))
        argvalues.append(values)
    # the list of all possible tuples of arguments to give to the memo function
    possiblevalues = cartesian_product(argvalues)

    # a MemoTable factory -- one MemoTable per family of arguments that can
    # be called together, merged via a UnionFind.
    bookkeeper = funcdesc.bookkeeper
    try:
        memotables = bookkeeper.all_specializations[funcdesc]
    except KeyError:
        func = funcdesc.pyobj
        if func is None:
            raise annmodel.AnnotatorError("memo call: no Python function object"
                                          "to call (%r)" % (funcdesc,))

        def compute_one_result(args):
            value = func(*args)
            memotable = MemoTable(funcdesc, args, value)
            memotable.register_finish()
            return memotable

        memotables = UnionFind(compute_one_result)
        bookkeeper.all_specializations[funcdesc] = memotables

    # merge the MemoTables for the individual argument combinations
    firstvalues = possiblevalues.next()
    _, _, memotable = memotables.find(firstvalues)
    for values in possiblevalues:
        _, _, memotable = memotables.union(firstvalues, values)

    if memotable.graph is not None:
        return memotable.graph   # if already computed
    else:
        # otherwise, for now, return the union of each possible result
        return unionof(*[bookkeeper.immutablevalue(v)
                         for v in memotable.table.values()])
예제 #2
0
def test_cleanup():
    state = []
    class ReferencedByExternalState(object):
        def __init__(self, obj):
            state.append(self)
            self.obj = obj

        def absorb(self, other):
            state.remove(other)

    uf = UnionFind(ReferencedByExternalState)
    uf.find(1)
    for i in xrange(1, 10, 2):
        uf.union(i, 1)
    uf.find(2)
    for i in xrange(2, 20, 2):
        uf.union(i, 2)
    assert len(state) == 2  # we have exactly 2 partitions
예제 #3
0
def test_cleanup():
    state = []
    class ReferencedByExternalState(object):
        def __init__(self, obj):
            state.append(self)
            self.obj = obj

        def absorb(self, other):
            state.remove(other)

    uf = UnionFind(ReferencedByExternalState)
    uf.find(1)
    for i in xrange(1, 10, 2):
        uf.union(i, 1)
    uf.find(2)
    for i in xrange(2, 20, 2):
        uf.union(i, 2)
    assert len(state) == 2 # we have exactly 2 partitions
예제 #4
0
def memo(funcdesc, args_s):
    # call the function now, and collect possible results

    # the list of all possible tuples of arguments to give to the memo function
    possiblevalues = cartesian_product([all_values(s_arg) for s_arg in args_s])

    # a MemoTable factory -- one MemoTable per family of arguments that can
    # be called together, merged via a UnionFind.
    bookkeeper = funcdesc.bookkeeper
    try:
        memotables = bookkeeper.all_specializations[funcdesc]
    except KeyError:
        func = funcdesc.pyobj
        if func is None:
            raise annmodel.AnnotatorError(
                "memo call: no Python function object"
                "to call (%r)" % (funcdesc, ))

        def compute_one_result(args):
            value = func(*args)
            memotable = MemoTable(funcdesc, args, value)
            memotable.register_finish()
            return memotable

        memotables = UnionFind(compute_one_result)
        bookkeeper.all_specializations[funcdesc] = memotables

    # merge the MemoTables for the individual argument combinations
    firstvalues = possiblevalues.next()
    _, _, memotable = memotables.find(firstvalues)
    for values in possiblevalues:
        _, _, memotable = memotables.union(firstvalues, values)

    if memotable.graph is not None:
        return memotable.graph  # if already computed
    else:
        # otherwise, for now, return the union of each possible result
        return unionof(
            *[bookkeeper.immutablevalue(v) for v in memotable.table.values()])
예제 #5
0
def memo(funcdesc, args_s):
    # call the function now, and collect possible results

    # the list of all possible tuples of arguments to give to the memo function
    possiblevalues = cartesian_product([all_values(s_arg) for s_arg in args_s])

    # a MemoTable factory -- one MemoTable per family of arguments that can
    # be called together, merged via a UnionFind.
    bookkeeper = funcdesc.bookkeeper
    try:
        memotables = bookkeeper.all_specializations[funcdesc]
    except KeyError:
        func = funcdesc.pyobj
        if func is None:
            raise annmodel.AnnotatorError("memo call: no Python function object"
                                          "to call (%r)" % (funcdesc,))

        def compute_one_result(args):
            value = func(*args)
            memotable = MemoTable(funcdesc, args, value)
            memotable.register_finish()
            return memotable

        memotables = UnionFind(compute_one_result)
        bookkeeper.all_specializations[funcdesc] = memotables

    # merge the MemoTables for the individual argument combinations
    firstvalues = possiblevalues.next()
    _, _, memotable = memotables.find(firstvalues)
    for values in possiblevalues:
        _, _, memotable = memotables.union(firstvalues, values)

    if memotable.graph is not None:
        return memotable.graph   # if already computed
    else:
        # otherwise, for now, return the union of each possible result
        return unionof(*[bookkeeper.immutablevalue(v)
                         for v in memotable.table.values()])
예제 #6
0
def memo(funcdesc, arglist_s):
    from rpython.annotator.model import SomePBC, SomeImpossibleValue, SomeBool
    from rpython.annotator.model import unionof
    # call the function now, and collect possible results
    argvalues = []
    for s in arglist_s:
        if s.is_constant():
            values = [s.const]
        elif isinstance(s, SomePBC):
            values = []
            assert not s.can_be_None, "memo call: cannot mix None and PBCs"
            for desc in s.descriptions:
                if desc.pyobj is None:
                    raise annmodel.AnnotatorError(
                        "memo call with a class or PBC that has no "
                        "corresponding Python object (%r)" % (desc, ))
                values.append(desc.pyobj)
        elif isinstance(s, SomeImpossibleValue):
            return s  # we will probably get more possible args later
        elif isinstance(s, SomeBool):
            values = [False, True]
        else:
            raise annmodel.AnnotatorError(
                "memo call: argument must be a class "
                "or a frozen PBC, got %r" % (s, ))
        argvalues.append(values)
    # the list of all possible tuples of arguments to give to the memo function
    possiblevalues = cartesian_product(argvalues)

    # a MemoTable factory -- one MemoTable per family of arguments that can
    # be called together, merged via a UnionFind.
    bookkeeper = funcdesc.bookkeeper
    try:
        memotables = bookkeeper.all_specializations[funcdesc]
    except KeyError:
        func = funcdesc.pyobj
        if func is None:
            raise annmodel.AnnotatorError(
                "memo call: no Python function object"
                "to call (%r)" % (funcdesc, ))

        def compute_one_result(args):
            value = func(*args)
            memotable = MemoTable(funcdesc, args, value)
            memotable.register_finish()
            return memotable

        memotables = UnionFind(compute_one_result)
        bookkeeper.all_specializations[funcdesc] = memotables

    # merge the MemoTables for the individual argument combinations
    firstvalues = possiblevalues.next()
    _, _, memotable = memotables.find(firstvalues)
    for values in possiblevalues:
        _, _, memotable = memotables.union(firstvalues, values)

    if memotable.graph is not None:
        return memotable.graph  # if already computed
    else:
        # otherwise, for now, return the union of each possible result
        return unionof(
            *[bookkeeper.immutablevalue(v) for v in memotable.table.values()])
예제 #7
0
    def compute_lifetimes(self, graph):
        """Compute the static data flow of the graph: returns a list of LifeTime
        instances, each of which corresponds to a set of Variables from the graph.
        The variables are grouped in the same LifeTime if a value can pass from
        one to the other by following the links.  Each LifeTime also records all
        places where a Variable in the set is used (read) or build (created).
        """
        lifetimes = UnionFind(LifeTime)

        def set_creation_point(block, var, *cp):
            _, _, info = lifetimes.find((block, var))
            info.creationpoints.add(cp)

        def set_use_point(block, var, *usepoint):
            _, _, info = lifetimes.find((block, var))
            info.usepoints.add(usepoint)

        def union(block1, var1, block2, var2):
            if isinstance(var1, Variable):
                lifetimes.union((block1, var1), (block2, var2))
            elif isinstance(var1, Constant):
                set_creation_point(block2, var2, "constant", var1)
            else:
                raise TypeError(var1)

        for var in graph.startblock.inputargs:
            set_creation_point(graph.startblock, var, "inputargs")
        set_use_point(graph.returnblock, graph.returnblock.inputargs[0],
                      "return")
        set_use_point(graph.exceptblock, graph.exceptblock.inputargs[0],
                      "except")
        set_use_point(graph.exceptblock, graph.exceptblock.inputargs[1],
                      "except")

        for node in graph.iterblocks():
            for op in node.operations:
                if op.opname in self.IDENTITY_OPS:
                    # special-case these operations to identify their input
                    # and output variables
                    union(node, op.args[0], node, op.result)
                    continue
                if op.opname in self.SUBSTRUCT_OPS:
                    if self.visit_substruct_op(node, union, op):
                        continue
                for i in range(len(op.args)):
                    if isinstance(op.args[i], Variable):
                        set_use_point(node, op.args[i], "op", node, op, i)
                set_creation_point(node, op.result, "op", node, op)
            if isinstance(node.exitswitch, Variable):
                set_use_point(node, node.exitswitch, "exitswitch", node)

        for node in graph.iterlinks():
            if isinstance(node.last_exception, Variable):
                set_creation_point(node.prevblock, node.last_exception,
                                   "last_exception")
            if isinstance(node.last_exc_value, Variable):
                set_creation_point(node.prevblock, node.last_exc_value,
                                   "last_exc_value")
            duplicate_info = set()
            for i, arg in enumerate(node.args):
                union(node.prevblock, arg, node.target,
                      node.target.inputargs[i])
                if isinstance(arg, Variable):

                    _, _, info = lifetimes.find((node.prevblock, arg))
                    if info in duplicate_info and len(info.creationpoints) > 1:
                        # same variable (up to renaming via same_as or
                        # cast_pointer) present several times in link.args, and
                        # the variable is created in two different places:
                        # consider it as a 'use' of the variable, which will
                        # disable malloc optimization (aliasing problems)
                        set_use_point(node.prevblock, arg, "dup", node, i)
                    else:
                        duplicate_info.add(info)

        return lifetimes.infos()