Exemple #1
0
 def update_rdict_annotations(self, s_eqfn, s_hashfn, other=None):
     assert self.custom_eq_hash
     s_eqfn = unionof(s_eqfn, self.s_rdict_eqfn)
     s_hashfn = unionof(s_hashfn, self.s_rdict_hashfn)
     self.s_rdict_eqfn = s_eqfn
     self.s_rdict_hashfn = s_hashfn
     self.emulate_rdict_calls(other=other)
Exemple #2
0
 def update_rdict_annotations(self, s_eqfn, s_hashfn, other=None):
     assert self.custom_eq_hash
     s_eqfn = unionof(s_eqfn, self.s_rdict_eqfn)
     s_hashfn = unionof(s_hashfn, self.s_rdict_hashfn)
     self.s_rdict_eqfn = s_eqfn
     self.s_rdict_hashfn = s_hashfn
     self.emulate_rdict_calls(other=other)
Exemple #3
0
def normalize_calltable_row_annotation(annotator, graphs):
    if len(graphs) <= 1:
        return False  # nothing to do
    graph_bindings = {}
    for graph in graphs:
        graph_bindings[graph] = [annotator.binding(v) for v in graph.getargs()]
    iterbindings = graph_bindings.itervalues()
    nbargs = len(iterbindings.next())
    for binding in iterbindings:
        assert len(binding) == nbargs

    generalizedargs = []
    for i in range(nbargs):
        args_s = []
        for graph, bindings in graph_bindings.items():
            args_s.append(bindings[i])
        s_value = annmodel.unionof(*args_s)
        generalizedargs.append(s_value)
    result_s = [
        annotator.binding(graph.getreturnvar()) for graph in graph_bindings
    ]
    generalizedresult = annmodel.unionof(*result_s)

    conversion = False
    for graph in graphs:
        bindings = graph_bindings[graph]
        need_conversion = (generalizedargs != bindings)
        if need_conversion:
            conversion = True
            oldblock = graph.startblock
            inlist = []
            for j, s_value in enumerate(generalizedargs):
                v = Variable(graph.getargs()[j])
                annotator.setbinding(v, s_value)
                inlist.append(v)
            newblock = Block(inlist)
            # prepare the output args of newblock and link
            outlist = inlist[:]
            newblock.closeblock(Link(outlist, oldblock))
            graph.startblock = newblock
            # finished
            checkgraph(graph)
            annotator.annotated[newblock] = annotator.annotated[oldblock]
        # convert the return value too
        if annotator.binding(graph.getreturnvar()) != generalizedresult:
            conversion = True
            annotator.setbinding(graph.getreturnvar(), generalizedresult)

    return conversion
Exemple #4
0
def normalize_calltable_row_annotation(annotator, graphs):
    if len(graphs) <= 1:
        return False   # nothing to do
    graph_bindings = {}
    for graph in graphs:
        graph_bindings[graph] = [annotator.binding(v)
                                 for v in graph.getargs()]
    iterbindings = graph_bindings.itervalues()
    nbargs = len(iterbindings.next())
    for binding in iterbindings:
        assert len(binding) == nbargs

    generalizedargs = []
    for i in range(nbargs):
        args_s = []
        for graph, bindings in graph_bindings.items():
            args_s.append(bindings[i])
        s_value = annmodel.unionof(*args_s)
        generalizedargs.append(s_value)
    result_s = [annotator.binding(graph.getreturnvar())
                for graph in graph_bindings]
    generalizedresult = annmodel.unionof(*result_s)

    conversion = False
    for graph in graphs:
        bindings = graph_bindings[graph]
        need_conversion = (generalizedargs != bindings)
        if need_conversion:
            conversion = True
            oldblock = graph.startblock
            inlist = []
            for j, s_value in enumerate(generalizedargs):
                v = Variable(graph.getargs()[j])
                annotator.setbinding(v, s_value)
                inlist.append(v)
            newblock = Block(inlist)
            # prepare the output args of newblock and link
            outlist = inlist[:]
            newblock.closeblock(Link(outlist, oldblock))
            graph.startblock = newblock
            # finished
            checkgraph(graph)
            annotator.annotated[newblock] = annotator.annotated[oldblock]
        # convert the return value too
        if annotator.binding(graph.getreturnvar()) != generalizedresult:
            conversion = True
            annotator.setbinding(graph.getreturnvar(), generalizedresult)

    return conversion
Exemple #5
0
 def pycall(self, whence, args, s_previous_result, op=None):
     inputcells = self.parse_arguments(args)
     result = self.specialize(inputcells, op)
     if isinstance(result, FunctionGraph):
         graph = result         # common case
         annotator = self.bookkeeper.annotator
         # if that graph has a different signature, we need to re-parse
         # the arguments.
         # recreate the args object because inputcells may have been changed
         new_args = args.unmatch_signature(self.signature, inputcells)
         inputcells = self.parse_arguments(new_args, graph)
         result = annotator.recursivecall(graph, whence, inputcells)
         signature = getattr(self.pyobj, '_signature_', None)
         if signature:
             sigresult = enforce_signature_return(self, signature[1], result)
             if sigresult is not None:
                 annotator.addpendingblock(
                     graph, graph.returnblock, [sigresult])
                 result = sigresult
     # Some specializations may break the invariant of returning
     # annotations that are always more general than the previous time.
     # We restore it here:
     from rpython.annotator.model import unionof
     result = unionof(result, s_previous_result)
     return result
Exemple #6
0
    def pbc_call(self, pbc, args, emulated=None):
        """Analyse a call to a SomePBC() with the given args (list of
        annotations).
        """
        if emulated is None:
            whence = self.position_key
            # fish the existing annotation for the result variable,
            # needed by some kinds of specialization.
            fn, block, i = self.position_key
            op = block.operations[i]
            s_previous_result = self.annotator.annotation(op.result)
            if s_previous_result is None:
                s_previous_result = s_ImpossibleValue
        else:
            if emulated is True:
                whence = None
            else:
                whence = emulated  # callback case
            op = None
            s_previous_result = s_ImpossibleValue

        results = []
        for desc in pbc.descriptions:
            results.append(desc.pycall(whence, args, s_previous_result, op))
        s_result = unionof(*results)
        return s_result
Exemple #7
0
 def union((bltn1, bltn2)):
     if (bltn1.analyser != bltn2.analyser or
         bltn1.methodname != bltn2.methodname or
         bltn1.s_self is None or bltn2.s_self is None):
         raise UnionError(bltn1, bltn2)
     s_self = unionof(bltn1.s_self, bltn2.s_self)
     return SomeBuiltin(bltn1.analyser, s_self, methodname=bltn1.methodname)
Exemple #8
0
 def pycall(self, schedule, args, s_previous_result, op=None):
     inputcells = self.parse_arguments(args)
     result = self.specialize(inputcells, op)
     if isinstance(result, FunctionGraph):
         graph = result  # common case
         # if that graph has a different signature, we need to re-parse
         # the arguments.
         # recreate the args object because inputcells may have been changed
         new_args = args.unmatch_signature(self.signature, inputcells)
         inputcells = self.parse_arguments(new_args, graph)
         result = schedule(graph, inputcells)
         signature = getattr(self.pyobj, '_signature_', None)
         if signature:
             sigresult = enforce_signature_return(self, signature[1],
                                                  result)
             if sigresult is not None:
                 self.bookkeeper.annotator.addpendingblock(
                     graph, graph.returnblock, [sigresult])
                 result = sigresult
     # Some specializations may break the invariant of returning
     # annotations that are always more general than the previous time.
     # We restore it here:
     from rpython.annotator.model import unionof
     result = unionof(result, s_previous_result)
     return result
Exemple #9
0
    def addpendingblock(self, graph, block, cells):
        """Register an entry point into block with the given input cells."""
        if graph in self.fixed_graphs:
            # special case for annotating/rtyping in several phases: calling
            # a graph that has already been rtyped.  Safety-check the new
            # annotations that are passed in, and don't annotate the old
            # graph -- it's already low-level operations!
            for a, s_newarg in zip(block.inputargs, cells):
                s_oldarg = a.annotation
                # XXX: Should use s_oldarg.contains(s_newarg) but that breaks
                # PyPy translation
                if annmodel.unionof(s_oldarg, s_newarg) != s_oldarg:
                    raise annmodel.AnnotatorError(
                        "Late-stage annotation is not allowed to modify the "
                        "existing annotation for variable %s: %s" %
                            (a, s_oldarg))

        else:
            assert not self.frozen
            if block not in self.annotated:
                self.bindinputargs(graph, block, cells)
            else:
                self.mergeinputargs(graph, block, cells)
            if not self.annotated[block]:
                self.pendingblocks[block] = graph
Exemple #10
0
    def pbc_call(self, pbc, args, emulated=None):
        """Analyse a call to a SomePBC() with the given args (list of
        annotations).
        """
        if emulated is None:
            whence = self.position_key
            # fish the existing annotation for the result variable,
            # needed by some kinds of specialization.
            fn, block, i = self.position_key
            op = block.operations[i]
            s_previous_result = self.annotator.annotation(op.result)
            if s_previous_result is None:
                s_previous_result = s_ImpossibleValue
        else:
            if emulated is True:
                whence = None
            else:
                whence = emulated # callback case
            op = None
            s_previous_result = s_ImpossibleValue

        results = []
        for desc in pbc.descriptions:
            results.append(desc.pycall(whence, args, s_previous_result, op))
        s_result = unionof(*results)
        return s_result
Exemple #11
0
 def add_constant_source(self, classdef, source):
     s_value = source.s_get_value(classdef, self.name)
     if source.instance_level:
         # a prebuilt instance source forces readonly=False, see above
         self.modified(classdef)
     s_new_value = unionof(self.s_value, s_value)
     self.s_value = s_new_value
Exemple #12
0
 def union((bltn1, bltn2)):
     if (bltn1.analyser != bltn2.analyser or
             bltn1.methodname != bltn2.methodname):
         raise UnionError(bltn1, bltn2)
     s_self = unionof(bltn1.s_self, bltn2.s_self)
     return SomeBuiltinMethod(bltn1.analyser, s_self,
             methodname=bltn1.methodname)
Exemple #13
0
 def union((iter1, iter2)):
     s_cont = unionof(iter1.s_container, iter2.s_container)
     if iter1.variant != iter2.variant:
         raise UnionError(
             iter1, iter2,
             "RPython cannot unify incompatible iterator variants")
     return SomeIterator(s_cont, *iter1.variant)
Exemple #14
0
 def __call__(self, funcdesc, inputcells):
     from rpython.rtyper.lltypesystem import lltype
     args_s = []
     from rpython.annotator import model as annmodel
     for i, argtype in enumerate(self.argtypes):
         if isinstance(argtype, (types.FunctionType, types.MethodType)):
             argtype = argtype(*inputcells)
         if isinstance(argtype, lltype.LowLevelType) and\
             argtype is lltype.Void:
             # XXX the mapping between Void and annotation
             # is not quite well defined
             s_input = inputcells[i]
             assert isinstance(s_input, annmodel.SomePBC)
             assert s_input.is_constant()
             args_s.append(s_input)
         elif argtype is None:
             args_s.append(inputcells[i])     # no change
         else:
             args_s.append(annotation(argtype, bookkeeper=funcdesc.bookkeeper))
     if len(inputcells) != len(args_s):
         raise SignatureError("%r: expected %d args, got %d" % (funcdesc,
                                                           len(args_s),
                                                           len(inputcells)))
     for i, (s_arg, s_input) in enumerate(zip(args_s, inputcells)):
         s_input = unionof(s_input, s_arg)
         if not s_arg.contains(s_input):
             raise SignatureError("%r argument %d:\n"
                             "expected %s,\n"
                             "     got %s" % (funcdesc, i+1,
                                          s_arg,
                                          s_input))
     inputcells[:] = args_s
Exemple #15
0
 def merge(self, other, classdef):
     assert self.name == other.name
     s_new_value = unionof(self.s_value, other.s_value)
     self.s_value = s_new_value
     if not other.readonly:
         self.modified(classdef)
     self.read_locations.update(other.read_locations)
Exemple #16
0
    def pbc_call(self, pbc, args, emulated=None):
        """Analyse a call to a SomePBC() with the given args (list of
        annotations).
        """
        descs = list(pbc.descriptions)
        first = descs[0]
        first.mergecallfamilies(*descs[1:])

        if emulated is None:
            whence = self.position_key
            # fish the existing annotation for the result variable,
            # needed by some kinds of specialization.
            fn, block, i = self.position_key
            op = block.operations[i]
            s_previous_result = self.annotator.annotation(op.result)
            if s_previous_result is None:
                s_previous_result = s_ImpossibleValue
        else:
            if emulated is True:
                whence = None
            else:
                whence = emulated  # callback case
            op = None
            s_previous_result = s_ImpossibleValue

        def schedule(graph, inputcells):
            return self.annotator.recursivecall(graph, whence, inputcells)

        results = []
        for desc in descs:
            results.append(desc.pycall(schedule, args, s_previous_result, op))
        s_result = unionof(*results)
        return s_result
Exemple #17
0
 def merge(self, other, classdef):
     assert self.name == other.name
     s_new_value = unionof(self.s_value, other.s_value)
     self.s_value = s_new_value
     if not other.readonly:
         self.modified(classdef)
     self.read_locations.update(other.read_locations)
Exemple #18
0
 def pycall(self, whence, args, s_previous_result, op=None):
     inputcells = self.parse_arguments(args)
     s_result = self.specialize(inputcells, op)
     if isinstance(s_result, FunctionGraph):
         s_result = s_result.getreturnvar().annotation
     s_result = unionof(s_result, s_previous_result)
     return s_result
Exemple #19
0
    def pbc_call(self, pbc, args, emulated=None):
        """Analyse a call to a SomePBC() with the given args (list of
        annotations).
        """
        descs = list(pbc.descriptions)
        first = descs[0]
        first.mergecallfamilies(*descs[1:])

        if emulated is None:
            whence = self.position_key
            # fish the existing annotation for the result variable,
            # needed by some kinds of specialization.
            fn, block, i = self.position_key
            op = block.operations[i]
            s_previous_result = self.annotator.annotation(op.result)
            if s_previous_result is None:
                s_previous_result = s_ImpossibleValue
        else:
            if emulated is True:
                whence = None
            else:
                whence = emulated # callback case
            op = None
            s_previous_result = s_ImpossibleValue

        def schedule(graph, inputcells):
            return self.annotator.recursivecall(graph, whence, inputcells)

        results = []
        for desc in descs:
            results.append(desc.pycall(schedule, args, s_previous_result, op))
        s_result = unionof(*results)
        return s_result
Exemple #20
0
 def __call__(self, funcdesc, inputcells):
     from rpython.rtyper.lltypesystem import lltype
     args_s = []
     from rpython.annotator import model as annmodel
     for i, argtype in enumerate(self.argtypes):
         if isinstance(argtype, (types.FunctionType, types.MethodType)):
             argtype = argtype(*inputcells)
         if argtype is lltype.Void:
             # XXX the mapping between Void and annotation
             # is not quite well defined
             s_input = inputcells[i]
             assert isinstance(s_input,
                               (annmodel.SomePBC, annmodel.SomeNone))
             assert s_input.is_constant()
             args_s.append(s_input)
         elif argtype is None:
             args_s.append(inputcells[i])  # no change
         else:
             args_s.append(
                 annotation(argtype, bookkeeper=funcdesc.bookkeeper))
     if len(inputcells) != len(args_s):
         raise SignatureError("%r: expected %d args, got %d" %
                              (funcdesc, len(args_s), len(inputcells)))
     for i, (s_arg, s_input) in enumerate(zip(args_s, inputcells)):
         s_input = unionof(s_input, s_arg)
         if not s_arg.contains(s_input):
             raise SignatureError("%r argument %d:\n"
                                  "expected %s,\n"
                                  "     got %s" %
                                  (funcdesc, i + 1, s_arg, s_input))
     inputcells[:] = args_s
Exemple #21
0
 def add_constant_source(self, classdef, source):
     s_value = source.s_get_value(classdef, self.name)
     if source.instance_level:
         # a prebuilt instance source forces readonly=False, see above
         self.modified(classdef)
     s_new_value = unionof(self.s_value, s_value)
     self.s_value = s_new_value
Exemple #22
0
    def addpendingblock(self, graph, block, cells):
        """Register an entry point into block with the given input cells."""
        if graph in self.fixed_graphs:
            # special case for annotating/rtyping in several phases: calling
            # a graph that has already been rtyped.  Safety-check the new
            # annotations that are passed in, and don't annotate the old
            # graph -- it's already low-level operations!
            for a, s_newarg in zip(block.inputargs, cells):
                s_oldarg = a.annotation
                # XXX: Should use s_oldarg.contains(s_newarg) but that breaks
                # PyPy translation
                if annmodel.unionof(s_oldarg, s_newarg) != s_oldarg:
                    raise annmodel.AnnotatorError(
                        "Late-stage annotation is not allowed to modify the "
                        "existing annotation for variable %s: %s" %
                        (a, s_oldarg))

        else:
            assert not self.frozen
            if block not in self.annotated:
                self.bindinputargs(graph, block, cells)
            else:
                self.mergeinputargs(graph, block, cells)
            if not self.annotated[block]:
                self.pendingblocks[block] = graph
Exemple #23
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()])
Exemple #24
0
 def union((tup1, tup2)):
     if len(tup1.items) != len(tup2.items):
         raise UnionError(tup1, tup2, "RPython cannot unify tuples of "
                 "different length: %d versus %d" % \
                 (len(tup1.items), len(tup2.items)))
     else:
         unions = [unionof(x, y) for x, y in zip(tup1.items, tup2.items)]
         return SomeTuple(items=unions)
Exemple #25
0
 def getitem((tup1, int2)):
     if int2.is_immutable_constant():
         try:
             return tup1.items[int2.const]
         except IndexError:
             return s_ImpossibleValue
     else:
         return unionof(*tup1.items)
Exemple #26
0
 def union((tup1, tup2)):
     if len(tup1.items) != len(tup2.items):
         raise UnionError(tup1, tup2, "RPython cannot unify tuples of "
                 "different length: %d versus %d" % \
                 (len(tup1.items), len(tup2.items)))
     else:
         unions = [unionof(x,y) for x,y in zip(tup1.items, tup2.items)]
         return SomeTuple(items = unions)
Exemple #27
0
 def getitem((tup1, int2)):
     if int2.is_immutable_constant():
         try:
             return tup1.items[int2.const]
         except IndexError:
             return s_ImpossibleValue
     else:
         return unionof(*tup1.items)
Exemple #28
0
 def union((tup1, tup2)):
     if len(tup1.items) != len(tup2.items):
         raise UnionError("cannot take the union of a tuple of length %d "
                          "and a tuple of length %d" % (len(tup1.items),
                                                        len(tup2.items)))
     else:
         unions = [unionof(x,y) for x,y in zip(tup1.items, tup2.items)]
         return SomeTuple(items = unions)
Exemple #29
0
 def union((bltn1, bltn2)):
     if (bltn1.analyser != bltn2.analyser or
         bltn1.methodname != bltn2.methodname or
         bltn1.s_self is None or bltn2.s_self is None):
         raise UnionError("cannot merge two different builtin functions "
                          "or methods:\n  %r\n  %r" % (bltn1, bltn2))
     s_self = unionof(bltn1.s_self, bltn2.s_self)
     return SomeBuiltin(bltn1.analyser, s_self, methodname=bltn1.methodname)
Exemple #30
0
 def generalize(self, s_other_value):
     s_new_value = unionof(self.s_value, s_other_value)
     updated = s_new_value != self.s_value
     if updated:
         if self.dont_change_any_more:
             raise TooLateForChange
         self.s_value = s_new_value
         self.notify_update()
     return updated
Exemple #31
0
 def pycall(self, whence, args, s_previous_result, op=None):
     inputcells = self.parse_arguments(args)
     s_result = self.specialize(inputcells, op)
     if isinstance(s_result, FunctionGraph):
         s_result = s_result.getreturnvar().annotation
         if s_result is None:
             s_result = s_ImpossibleValue
     s_result = unionof(s_result, s_previous_result)
     return s_result
Exemple #32
0
 def enter_tunnel(self, bookkeeper, s_obj):
     dict = self._getdict(bookkeeper)
     s_previousobj, reflowpositions = dict.setdefault(
         self, (annmodel.s_ImpossibleValue, {}))
     s_obj = annmodel.unionof(s_previousobj, s_obj)
     if s_obj != s_previousobj:
         dict[self] = (s_obj, reflowpositions)
         for position in reflowpositions:
             bookkeeper.annotator.reflowfromposition(position)
Exemple #33
0
 def enter_tunnel(self, bookkeeper, s_obj):
     dict = self._getdict(bookkeeper)
     s_previousobj, reflowpositions = dict.setdefault(
         self, (annmodel.s_ImpossibleValue, {}))
     s_obj = annmodel.unionof(s_previousobj, s_obj)
     if s_obj != s_previousobj:
         dict[self] = (s_obj, reflowpositions)
         for position in reflowpositions:
             bookkeeper.annotator.reflowfromposition(position)
Exemple #34
0
 def getitem((tup1, int2)):
     if int2.is_immutable_constant():
         try:
             return tup1.items[int2.const]
         except IndexError:
             return s_ImpossibleValue
     else:
         getbookkeeper().count("tuple_random_getitem", tup1)
         return unionof(*tup1.items)
Exemple #35
0
 def generalize(self, s_other_value):
     s_new_value = unionof(self.s_value, s_other_value)
     updated = s_new_value != self.s_value
     if updated:
         if self.dont_change_any_more:
             raise TooLateForChange
         self.s_value = s_new_value
         self.notify_update()
     return updated
Exemple #36
0
 def mergeinputargs(self, graph, block, inputcells):
     # Merge the new 'cells' with each of the block's existing input
     # variables.
     oldcells = [self.binding(a) for a in block.inputargs]
     try:
         unions = [annmodel.unionof(c1,c2) for c1, c2 in zip(oldcells,inputcells)]
     except annmodel.UnionError, e:
         # Add source code to the UnionError
         e.source = '\n'.join(source_lines(graph, block, None, long=True))
         raise
Exemple #37
0
 def mergeinputargs(self, graph, block, inputcells):
     # Merge the new 'cells' with each of the block's existing input
     # variables.
     oldcells = [self.binding(a) for a in block.inputargs]
     try:
         unions = [annmodel.unionof(c1,c2) for c1, c2 in zip(oldcells,inputcells)]
     except annmodel.UnionError, e:
         # Add source code to the UnionError
         e.source = '\n'.join(source_lines(graph, block, None, long=True))
         raise
Exemple #38
0
def _rtype_compare_template(hop, func):
    s_int1, s_int2 = hop.args_s
    if s_int1.unsigned or s_int2.unsigned:
        if not s_int1.nonneg or not s_int2.nonneg:
            raise TyperError("comparing a signed and an unsigned number")

    repr = hop.rtyper.getrepr(annmodel.unionof(s_int1, s_int2)).as_int
    vlist = hop.inputargs(repr, repr)
    hop.exception_is_here()
    return hop.genop(repr.opprefix + func, vlist, resulttype=Bool)
Exemple #39
0
def _rtype_compare_template(hop, func):
    s_int1, s_int2 = hop.args_s
    if s_int1.unsigned or s_int2.unsigned:
        if not s_int1.nonneg or not s_int2.nonneg:
            raise TyperError("comparing a signed and an unsigned number")

    repr = hop.rtyper.getrepr(annmodel.unionof(s_int1, s_int2)).as_int
    vlist = hop.inputargs(repr, repr)
    hop.exception_is_here()
    return hop.genop(repr.opprefix+func, vlist, resulttype=Bool)
Exemple #40
0
    def pbc_getattr(self, pbc, s_attr):
        assert s_attr.is_constant()
        attr = s_attr.const

        descs = list(pbc.descriptions)
        if not descs:
            return s_ImpossibleValue

        first = descs[0]
        if len(descs) == 1:
            return first.s_read_attribute(attr)

        change = first.mergeattrfamilies(descs[1:], attr)
        attrfamily = first.getattrfamily(attr)

        position = self.position_key
        attrfamily.read_locations[position] = True

        actuals = []
        for desc in descs:
            actuals.append(desc.s_read_attribute(attr))
        s_result = unionof(*actuals)

        s_oldvalue = attrfamily.get_s_value(attr)
        attrfamily.set_s_value(attr, unionof(s_result, s_oldvalue))

        if change:
            for position in attrfamily.read_locations:
                self.annotator.reflowfromposition(position)

        if isinstance(s_result, SomeImpossibleValue):
            for desc in descs:
                try:
                    attrs = desc.read_attribute('_attrs_')
                except AttributeError:
                    continue
                if isinstance(attrs, Constant):
                    attrs = attrs.value
                if attr in attrs:
                    raise HarmlesslyBlocked("getattr on enforced attr")

        return s_result
Exemple #41
0
 def generalize(self, s_other_value):
     s_new_value = unionof(self.s_value, s_other_value)
     updated = s_new_value != self.s_value
     if updated:
         if self.dont_change_any_more:
             raise TooLateForChange
         self.s_value = s_new_value
         # reflow from all reading points
         for position_key in self.read_locations:
             self.bookkeeper.annotator.reflowfromposition(position_key)
     return updated
Exemple #42
0
def weakly_contains(s_bigger, s_smaller):
    # a special version of s_bigger.contains(s_smaller).  Warning, to
    # support ListDefs properly, this works by trying to produce a side-effect
    # on s_bigger.  It relies on the fact that s_bigger was created with
    # an expression like 'annotation([s_item])' which returns a ListDef with
    # no bookkeeper, on which side-effects are not allowed.
    try:
        s_union = annmodel.unionof(s_bigger, s_smaller)
        return s_bigger.contains(s_union)
    except (annmodel.UnionError, TooLateForChange):
        return False
Exemple #43
0
 def generalize(self, s_other_value):
     s_new_value = unionof(self.s_value, s_other_value)
     updated = s_new_value != self.s_value
     if updated:
         if self.dont_change_any_more:
             raise TooLateForChange
         self.s_value = s_new_value
         # reflow from all reading points
         for position_key in self.read_locations:
             self.bookkeeper.annotator.reflowfromposition(position_key)
     return updated
Exemple #44
0
def weakly_contains(s_bigger, s_smaller):
    # a special version of s_bigger.contains(s_smaller).  Warning, to
    # support ListDefs properly, this works by trying to produce a side-effect
    # on s_bigger.  It relies on the fact that s_bigger was created with
    # an expression like 'annotation([s_item])' which returns a ListDef with
    # no bookkeeper, on which side-effects are not allowed.
    try:
        s_union = annmodel.unionof(s_bigger, s_smaller)
        return s_bigger.contains(s_union)
    except (annmodel.UnionError, TooLateForChange):
        return False
Exemple #45
0
    def pbc_getattr(self, pbc, s_attr):
        assert s_attr.is_constant()
        attr = s_attr.const

        descs = list(pbc.descriptions)
        first = descs[0]
        if len(descs) == 1:
            return first.s_read_attribute(attr)

        change = first.mergeattrfamilies(descs[1:], attr)
        attrfamily = first.getattrfamily(attr)

        position = self.position_key
        attrfamily.read_locations[position] = True

        actuals = []
        for desc in descs:
            actuals.append(desc.s_read_attribute(attr))
        s_result = unionof(*actuals)

        s_oldvalue = attrfamily.get_s_value(attr)
        attrfamily.set_s_value(attr, unionof(s_result, s_oldvalue))

        if change:
            for position in attrfamily.read_locations:
                self.annotator.reflowfromposition(position)

        if isinstance(s_result, SomeImpossibleValue):
            for desc in descs:
                try:
                    attrs = desc.read_attribute('_attrs_')
                except AttributeError:
                    continue
                if isinstance(attrs, Constant):
                    attrs = attrs.value
                if attr in attrs:
                    raise HarmlesslyBlocked("getattr on enforced attr")

        return s_result
Exemple #46
0
def builtin_max(*s_values):
    if len(s_values) == 1:  # xxx do we support this?
        s_iter = s_values[0].iter()
        return s_iter.next()
    else:
        s = unionof(*s_values)
        if type(s) is SomeInteger and not s.nonneg:
            nonneg = False
            for s1 in s_values:
                nonneg |= s1.nonneg
            if nonneg:
                s = SomeInteger(nonneg=True, knowntype=s.knowntype)
        return s
Exemple #47
0
def builtin_max(*s_values):
    if len(s_values) == 1: # xxx do we support this?
        s_iter = s_values[0].iter()
        return s_iter.next()
    else:
        s = unionof(*s_values)
        if type(s) is SomeInteger and not s.nonneg:
            nonneg = False
            for s1 in s_values:
                nonneg |= s1.nonneg
            if nonneg:
                s = SomeInteger(nonneg=True, knowntype=s.knowntype)
        return s
Exemple #48
0
class __extend__(pairtype(FunctionReprBase, FunctionReprBase)):
    def rtype_is_((robj1, robj2), hop):
        if hop.s_result.is_constant():
            return inputconst(Bool, hop.s_result.const)
        s_pbc = annmodel.unionof(robj1.s_pbc, robj2.s_pbc)
        r_pbc = hop.rtyper.getrepr(s_pbc)
        v1, v2 = hop.inputargs(r_pbc, r_pbc)
        assert v1.concretetype == v2.concretetype
        if v1.concretetype == Char:
            return hop.genop('char_eq', [v1, v2], resulttype=Bool)
        elif isinstance(v1.concretetype, Ptr):
            return hop.genop('ptr_eq', [v1, v2], resulttype=Bool)
        else:
            raise TyperError("unknown type %r" % (v1.concretetype, ))
Exemple #49
0
 def check_args(self, callspec):
     params_s = self.args_s
     args_s, kwargs = callspec.unpack()
     if kwargs:
         raise SignatureError(
             "External functions cannot be called with keyword arguments")
     if len(args_s) != len(params_s):
         raise SignatureError("Argument number mismatch")
     for i, s_param in enumerate(params_s):
         arg = unionof(args_s[i], s_param)
         if not s_param.contains(arg):
             raise SignatureError(
                 "In call to external function %r:\n"
                 "arg %d must be %s,\n"
                 "          got %s" % (
                     self.name, i + 1, s_param, args_s[i]))
Exemple #50
0
    def merge(self, other):
        if self is not other:
            if getattr(TLS, 'no_side_effects_in_union', 0):
                raise UnionError(self, other)

            if other.dont_change_any_more:
                if self.dont_change_any_more:
                    raise TooLateForChange
                else:
                    # lists using 'other' don't expect it to change any more,
                    # so we try merging into 'other', which will give
                    # TooLateForChange if it actually tries to make
                    # things more general
                    self, other = other, self

            self.immutable &= other.immutable
            if other.must_not_resize:
                if self.resized:
                    raise ListChangeUnallowed("list merge with a resized")
                self.must_not_resize = True
            if other.mutated:
                self.mutate()
            if other.resized:
                self.resize()
            if other.range_step != self.range_step:
                self.setrangestep(self._step_map[type(self.range_step),
                                                 type(other.range_step)])
            self.itemof.update(other.itemof)
            read_locations = self.read_locations.copy()
            other_read_locations = other.read_locations.copy()
            self.read_locations.update(other.read_locations)
            s_value = self.s_value
            s_other_value = other.s_value
            s_new_value = unionof(s_value, s_other_value)
            if s_new_value != s_value:
                if self.dont_change_any_more:
                    raise TooLateForChange
            self.patch()    # which should patch all refs to 'other'
            if s_new_value != s_value:
                self.s_value = s_new_value
                # reflow from reading points
                for position_key in read_locations:
                    self.bookkeeper.annotator.reflowfromposition(position_key) 
            if s_new_value != s_other_value:
                # reflow from reading points
                for position_key in other_read_locations:
                    other.bookkeeper.annotator.reflowfromposition(position_key)
Exemple #51
0
    def merge(self, other):
        if self is not other:
            if getattr(TLS, 'no_side_effects_in_union', 0):
                raise UnionError(self, other)

            if other.dont_change_any_more:
                if self.dont_change_any_more:
                    raise TooLateForChange
                else:
                    # lists using 'other' don't expect it to change any more,
                    # so we try merging into 'other', which will give
                    # TooLateForChange if it actually tries to make
                    # things more general
                    self, other = other, self

            self.immutable &= other.immutable
            if other.must_not_resize:
                if self.resized:
                    raise ListChangeUnallowed("list merge with a resized")
                self.must_not_resize = True
            if other.mutated:
                self.mutate()
            if other.resized:
                self.resize()
            if other.range_step != self.range_step:
                self.setrangestep(self._step_map[type(self.range_step),
                                                 type(other.range_step)])
            self.itemof.update(other.itemof)
            read_locations = self.read_locations.copy()
            other_read_locations = other.read_locations.copy()
            self.read_locations.update(other.read_locations)
            s_value = self.s_value
            s_other_value = other.s_value
            s_new_value = unionof(s_value, s_other_value)
            if s_new_value != s_value:
                if self.dont_change_any_more:
                    raise TooLateForChange
            self.patch()    # which should patch all refs to 'other'
            if s_new_value != s_value:
                self.s_value = s_new_value
                # reflow from reading points
                for position_key in read_locations:
                    self.bookkeeper.annotator.reflowfromposition(position_key) 
            if s_new_value != s_other_value:
                # reflow from reading points
                for position_key in other_read_locations:
                    other.bookkeeper.annotator.reflowfromposition(position_key)
Exemple #52
0
 def mergeinputargs(self, graph, block, inputcells):
     # Merge the new 'cells' with each of the block's existing input
     # variables.
     oldcells = [self.binding(a) for a in block.inputargs]
     try:
         unions = [annmodel.unionof(c1,c2) for c1, c2 in zip(oldcells,inputcells)]
     except annmodel.UnionError as e:
         # Add source code to the UnionError
         e.source = '\n'.join(source_lines(graph, block, None, long=True))
         if self.keepgoing:
             self.errors.append(e)
             self.failed_blocks.add(block)
             return
         raise
     # if the merged cells changed, we must redo the analysis
     if unions != oldcells:
         self.bindinputargs(graph, block, unions)
Exemple #53
0
 def addpendingblock(self, graph, block, cells):
     """Register an entry point into block with the given input cells."""
     if graph in self.fixed_graphs:
         # special case for annotating/rtyping in several phases: calling
         # a graph that has already been rtyped.  Safety-check the new
         # annotations that are passed in, and don't annotate the old
         # graph -- it's already low-level operations!
         for a, s_newarg in zip(block.inputargs, cells):
             s_oldarg = self.binding(a)
             assert annmodel.unionof(s_oldarg, s_newarg) == s_oldarg
     else:
         assert not self.frozen
         if block not in self.annotated:
             self.bindinputargs(graph, block, cells)
         else:
             self.mergeinputargs(graph, block, cells)
         if not self.annotated[block]:
             self.pendingblocks[block] = graph
Exemple #54
0
 def addpendingblock(self, graph, block, cells):
     """Register an entry point into block with the given input cells."""
     if graph in self.fixed_graphs:
         # special case for annotating/rtyping in several phases: calling
         # a graph that has already been rtyped.  Safety-check the new
         # annotations that are passed in, and don't annotate the old
         # graph -- it's already low-level operations!
         for a, s_newarg in zip(block.inputargs, cells):
             s_oldarg = self.binding(a)
             assert annmodel.unionof(s_oldarg, s_newarg) == s_oldarg
     else:
         assert not self.frozen
         if block not in self.annotated:
             self.bindinputargs(graph, block, cells)
         else:
             self.mergeinputargs(graph, block, cells)
         if not self.annotated[block]:
             self.pendingblocks[block] = graph
Exemple #55
0
    def normalize_args(self, *args_s):
        args = self.signature_args
        signature_args = [annotation(arg, None) for arg in args]
        assert len(args_s) == len(signature_args),\
               "Argument number mismatch"

        for i, expected in enumerate(signature_args):
            arg = annmodel.unionof(args_s[i], expected)
            if not expected.contains(arg):
                name = getattr(self, 'name', None)
                if not name:
                    try:
                        name = self.instance.__name__
                    except AttributeError:
                        name = '?'
                raise Exception("In call to external function %r:\n"
                                "arg %d must be %s,\n"
                                "          got %s" % (
                    name, i+1, expected, args_s[i]))
        return signature_args
Exemple #56
0
    def normalize_args(self, *args_s):
        args = self.signature_args
        signature_args = [annotation(arg, None) for arg in args]
        assert len(args_s) == len(signature_args),\
               "Argument number mismatch"

        for i, expected in enumerate(signature_args):
            arg = annmodel.unionof(args_s[i], expected)
            if not expected.contains(arg):
                name = getattr(self, 'name', None)
                if not name:
                    try:
                        name = self.instance.__name__
                    except AttributeError:
                        name = '?'
                raise Exception("In call to external function %r:\n"
                                "arg %d must be %s,\n"
                                "          got %s" %
                                (name, i + 1, expected, args_s[i]))
        return signature_args
Exemple #57
0
 def mergeinputargs(self, graph, block, inputcells):
     # Merge the new 'cells' with each of the block's existing input
     # variables.
     oldcells = [self.binding(a) for a in block.inputargs]
     try:
         unions = [
             annmodel.unionof(c1, c2)
             for c1, c2 in zip(oldcells, inputcells)
         ]
     except annmodel.UnionError as e:
         # Add source code to the UnionError
         e.source = '\n'.join(source_lines(graph, block, None, long=True))
         if self.keepgoing:
             self.errors.append(e)
             self.failed_blocks.add(block)
             return
         raise
     # if the merged cells changed, we must redo the analysis
     if unions != oldcells:
         self.bindinputargs(graph, block, unions)
Exemple #58
0
    def compute_result_annotation(self, **kwds_s):
        from rpython.annotator import model as annmodel

        if self.instance.__name__ == 'jit_merge_point':
            self.annotate_hooks(**kwds_s)

        driver = self.instance.im_self
        keys = kwds_s.keys()
        keys.sort()
        expected = [
            's_' + name for name in driver.greens + driver.reds
            if '.' not in name
        ]
        expected.sort()
        if keys != expected:
            raise JitHintError("%s expects the following keyword "
                               "arguments: %s" % (self.instance, expected))

        try:
            cache = self.bookkeeper._jit_annotation_cache[driver]
        except AttributeError:
            cache = {}
            self.bookkeeper._jit_annotation_cache = {driver: cache}
        except KeyError:
            cache = {}
            self.bookkeeper._jit_annotation_cache[driver] = cache
        for key, s_value in kwds_s.items():
            s_previous = cache.get(key, annmodel.s_ImpossibleValue)
            s_value = annmodel.unionof(
                s_previous, s_value
            )  # where="mixing incompatible types in argument %s of jit_merge_point/can_enter_jit" % key[2:]
            cache[key] = s_value

        # add the attribute _dont_reach_me_in_del_ (see rpython.rtyper.rclass)
        try:
            graph = self.bookkeeper.position_key[0]
            graph.func._dont_reach_me_in_del_ = True
        except (TypeError, AttributeError):
            pass

        return annmodel.s_None
Exemple #59
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()])