示例#1
0
    def __init__(self, annotator):
        self.annotator = annotator
        self.policy = annotator.policy
        self.descs = {}  # map Python objects to their XxxDesc wrappers
        self.methoddescs = {}  # map (funcdesc, classdef) to the MethodDesc
        self.classdefs = []  # list of all ClassDefs
        self.pbctypes = {}
        self.seen_mutable = {}
        self.listdefs = {}  # map position_keys to ListDefs
        self.dictdefs = {}  # map position_keys to DictDefs
        self.immutable_cache = {}

        self.classpbc_attr_families = {
        }  # {'attr': UnionFind(ClassAttrFamily)}
        self.frozenpbc_attr_families = UnionFind(description.FrozenAttrFamily)
        self.pbc_maximal_call_families = UnionFind(description.CallFamily)

        self.emulated_pbc_calls = {}
        self.all_specializations = {}  # {FuncDesc: specialization-info}
        self.pending_specializations = []  # list of callbacks
        self.external_class_cache = {}  # cache of ExternalType classes

        self.needs_generic_instantiate = {}

        self.stats = Stats(self)

        # used in SomeObject.__new__ for keeping debugging info
        self._isomeobject_coming_from = identity_dict()

        delayed_imports()
示例#2
0
def memo(funcdesc, arglist_s):
    from pypy.annotation.model import SomePBC, SomeImpossibleValue, SomeBool
    from pypy.annotation.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 Exception(
                        "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 Exception("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 Exception("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()])
示例#3
0
文件: bookkeeper.py 项目: njues/Sypy
 def get_classpbc_attr_families(self, attrname):
     """Return the UnionFind for the ClassAttrFamilies corresponding to
     attributes of the given name.
     """
     map = self.classpbc_attr_families
     try:
         access_sets = map[attrname]
     except KeyError:
         access_sets = map[attrname] = UnionFind(description.ClassAttrFamily)
     return access_sets
示例#4
0
 def __init__(self, hannotator):
     self.pending_specializations = []
     self.originflags = {}
     self.virtual_containers = {}
     self.descs = {}
     self.tsgraph_maximal_call_families = UnionFind(TsGraphCallFamily)
     self.annotator = hannotator
     self.tsgraphsigs = {}
     self.nonstuboriggraphcount = 0
     self.stuboriggraphcount = 0
     if hannotator is not None:     # for tests
         t = hannotator.base_translator
         self.impurity_analyzer = ImpurityAnalyzer(t)
     # circular imports hack
     global hintmodel
     from pypy.jit.hintannotator import model as hintmodel
示例#5
0
 def coalesce_variables(self):
     self._unionfind = UnionFind()
     pendingblocks = list(self.graph.iterblocks())
     while pendingblocks:
         block = pendingblocks.pop()
         # Aggressively try to coalesce each source variable with its
         # target.  We start from the end of the graph instead of
         # from the beginning.  This is a bit arbitrary, but the idea
         # is that the end of the graph runs typically more often
         # than the start, given that we resume execution from the
         # middle during blackholing.
         for link in block.exits:
             if link.last_exception is not None:
                 self._depgraph.add_node(link.last_exception)
             if link.last_exc_value is not None:
                 self._depgraph.add_node(link.last_exc_value)
             for i, v in enumerate(link.args):
                 self._try_coalesce(v, link.target.inputargs[i])
示例#6
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
示例#7
0
 def __init__(self, graph):
     # Build a list of "unification opportunities": for each block and each
     # 'n', an "opportunity" groups the block's nth input variable with
     # the nth output variable from each of the incoming links, in a list:
     # [Block, blockvar, linkvar, linkvar, linkvar...]
     opportunities = []
     opportunities_with_const = []
     for block, links in mkinsideentrymap(graph).items():
         assert links
         for n, inputvar in enumerate(block.inputargs):
             vars = [block, inputvar]
             put_in = opportunities
             for link in links:
                 var = link.args[n]
                 if not isinstance(var, Variable):
                     put_in = opportunities_with_const
                 vars.append(var)
             # if any link provides a Constant, record this in
             # the opportunities_with_const list instead
             put_in.append(vars)
     self.opportunities = opportunities
     self.opportunities_with_const = opportunities_with_const
     self.variable_families = UnionFind()
示例#8
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[cp] = True

        def set_use_point(block, var, *up):
            _, _, info = lifetimes.find((block, var))
            info.usepoints[up] = True

        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")

        def visit(node):
            if isinstance(node, Block):
                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)

            if isinstance(node, Link):
                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")
                d = {}
                for i, arg in enumerate(node.args):
                    union(node.prevblock, arg, node.target,
                          node.target.inputargs[i])
                    if isinstance(arg, Variable):
                        if arg in d:
                            # same variable present several times in link.args
                            # 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:
                            d[arg] = True

        traverse(visit, graph)
        return lifetimes.infos()