Exemple #1
0
 def union((d1, d2)):
     assert (d1.eq_func is d2.eq_func is None) or (d1.eq_func.const is d2.eq_func.const)
     assert (d1.hash_func is d2.hash_func is None) or (d1.hash_func.const is d2.hash_func.const)
     s_new = SomeOrderedDict(d1.bookkeeper, d1.eq_func, d1.hash_func)
     s_new.key_type = d1.key_type = model.unionof(d1.key_type, d2.key_type)
     s_new.value_type = d1.value_type = model.unionof(d1.value_type, d2.value_type)
     return s_new
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 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 #4
0
 def update_rdict_annotations(self, s_eqfn, s_hashfn, other=None):
     if not self.custom_eq_hash:
         self.custom_eq_hash = True
     else:
         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)
 def update_rdict_annotations(self, s_eqfn, s_hashfn, other=None):
     if not self.custom_eq_hash:
         self.custom_eq_hash = True
     else:
         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 #6
0
 def union((d1, d2)):
     assert (d1.eq_func is d2.eq_func is None) or (d1.eq_func.const is
                                                   d2.eq_func.const)
     assert (d1.hash_func is d2.hash_func is None) or (d1.hash_func.const is
                                                       d2.hash_func.const)
     s_new = SomeOrderedDict(d1.bookkeeper, d1.eq_func, d1.hash_func)
     s_new.key_type = d1.key_type = model.unionof(d1.key_type, d2.key_type)
     s_new.value_type = d1.value_type = model.unionof(
         d1.value_type, d2.value_type)
     return s_new
Exemple #7
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))
            oldblock.isstartblock = False
            newblock.isstartblock = True
            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 #8
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))
            oldblock.isstartblock = False
            newblock.isstartblock = True
            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 #9
0
    def __init__(self, hrtyper):
        self.hrtyper = hrtyper
        RGenOp = hrtyper.RGenOp
        rtyper = hrtyper.rtyper
        bk = rtyper.annotator.bookkeeper
        s_w_bool = annmodel.unionof(bk.immutablevalue(W_BoolObject.w_False),
                                    bk.immutablevalue(W_BoolObject.w_True))
        r_w_bool = rtyper.getrepr(s_w_bool)
        self.ll_False = r_w_bool.convert_const(W_BoolObject.w_False)
        self.ll_True = r_w_bool.convert_const(W_BoolObject.w_True)

        A = lltype.Array(lltype.typeOf(self.ll_False))
        self.ll_bools = lltype.malloc(A, 2, immortal=True)
        self.ll_bools[0] = self.ll_False
        self.ll_bools[1] = self.ll_True
        self.gv_bools = RGenOp.constPrebuiltGlobal(self.ll_bools)
        self.boolsToken = RGenOp.arrayToken(A)

        self.bools_gv = [
            RGenOp.constPrebuiltGlobal(self.ll_False),
            RGenOp.constPrebuiltGlobal(self.ll_True)
        ]

        self.ptrkind = RGenOp.kindToken(r_w_bool.lowleveltype)
        self.boolkind = RGenOp.kindToken(lltype.Bool)

        ll_BoolObject = r_w_bool.rclass.getvtable()
        self.BoolObjectBox = rvalue.redbox_from_prebuilt_value(
            RGenOp, ll_BoolObject)

        self.Falsebox = rvalue.redbox_from_prebuilt_value(RGenOp, False)
        self.Truebox = rvalue.redbox_from_prebuilt_value(RGenOp, True)
        self.boolboxes = [self.Falsebox, self.Truebox]
Exemple #10
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()])
Exemple #11
0
 def __call__(self, funcdesc, inputcells):
     from pypy.rpython.lltypesystem import lltype
     args_s = []
     from pypy.annotation 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 Exception("%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 Exception("%r argument %d:\n"
                             "expected %s,\n"
                             "     got %s" %
                             (funcdesc, i + 1, s_arg, s_input))
     inputcells[:] = args_s
Exemple #12
0
    def compute_result_annotation(self, **kwds_s):
        from pypy.annotation import model as annmodel
        driver = self.instance.im_self
        keys = kwds_s.keys()
        keys.sort()
        expected = ['s_' + name for name in driver.greens + driver.reds]
        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)
            if annmodel.isdegenerated(s_value):
                raise JitHintError("mixing incompatible types in argument %s"
                                   " of jit_merge_point/can_enter_jit" %
                                   key[2:])
            cache[key] = s_value

        if self.instance.__name__ == 'jit_merge_point':
            self.annotate_hooks(**kwds_s)
            
        return annmodel.s_None
Exemple #13
0
    def __init__(self, hrtyper):
        self.hrtyper = hrtyper
        RGenOp = hrtyper.RGenOp
        rtyper = hrtyper.rtyper
        bk = rtyper.annotator.bookkeeper
        s_w_bool = annmodel.unionof(bk.immutablevalue(W_BoolObject.w_False),
                                    bk.immutablevalue(W_BoolObject.w_True))
        r_w_bool = rtyper.getrepr(s_w_bool)
        self.ll_False = r_w_bool.convert_const(W_BoolObject.w_False)
        self.ll_True  = r_w_bool.convert_const(W_BoolObject.w_True)

        A = lltype.Array(lltype.typeOf(self.ll_False))
        self.ll_bools = lltype.malloc(A, 2, immortal=True)
        self.ll_bools[0] = self.ll_False
        self.ll_bools[1] = self.ll_True
        self.gv_bools = RGenOp.constPrebuiltGlobal(self.ll_bools)
        self.boolsToken = RGenOp.arrayToken(A)

        self.bools_gv = [RGenOp.constPrebuiltGlobal(self.ll_False),
                         RGenOp.constPrebuiltGlobal(self.ll_True)]

        self.ptrkind = RGenOp.kindToken(r_w_bool.lowleveltype)
        self.boolkind = RGenOp.kindToken(lltype.Bool)

        ll_BoolObject = r_w_bool.rclass.getvtable()
        self.BoolObjectBox = rvalue.redbox_from_prebuilt_value(RGenOp,
                                                               ll_BoolObject)

        self.Falsebox = rvalue.redbox_from_prebuilt_value(RGenOp, False)
        self.Truebox = rvalue.redbox_from_prebuilt_value(RGenOp, True)
        self.boolboxes = [self.Falsebox, self.Truebox]
Exemple #14
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)
        if not descs:
            return s_ImpossibleValue
        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.binding(op.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 #15
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)
        if not descs:
            return s_ImpossibleValue
        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.binding(op.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 #16
0
    def indirect_call(hs_v1, *args_hs):
        hs_graph_list = args_hs[-1]
        args_hs = args_hs[:-1]
        assert hs_graph_list.is_constant()
        graph_list = hs_graph_list.const
        if graph_list is None:
            # cannot follow indirect calls to unknown targets
            return variableoftype(hs_v1.concretetype.TO.RESULT)

        bookkeeper = getbookkeeper()
        myorigin = bookkeeper.myorigin()
        myorigin.__class__ = CallOpOriginFlags     # thud
        fixed = myorigin.read_fixed()
        tsgraphs_accum = []
        hs_res = bookkeeper.graph_family_call(graph_list, fixed, args_hs,
                                              tsgraphs_accum, hs_v1)
        myorigin.any_called_graph = tsgraphs_accum[0]

        if isinstance(hs_res, SomeLLAbstractConstant):
            hs_res.myorigin = myorigin

        # we need to make sure that hs_res does not become temporarily less
        # general as a result of calling another specialized version of the
        # function
        return annmodel.unionof(hs_res, bookkeeper.current_op_binding())
Exemple #17
0
    def compute_result_annotation(self, **kwds_s):
        from pypy.annotation 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)
            if annmodel.isdegenerated(s_value):
                raise JitHintError("mixing incompatible types in argument %s"
                                   " of jit_merge_point/can_enter_jit" %
                                   key[2:])
            cache[key] = s_value

        return annmodel.s_None
Exemple #18
0
 def __call__(self, funcdesc, inputcells):
     from pypy.rpython.lltypesystem import lltype
     args_s = []
     from pypy.annotation 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 Exception("%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 Exception("%r argument %d:\n"
                             "expected %s,\n"
                             "     got %s" % (funcdesc, i+1,
                                          s_arg,
                                          s_input))
     inputcells[:] = args_s
Exemple #19
0
    def _call_single_graph(hs_f1, graph, RESULT, *args_hs):
        bookkeeper = getbookkeeper()
        if not bookkeeper.annotator.policy.look_inside_graph(graph):
            return cannot_follow_call(bookkeeper, graph, args_hs, RESULT)

        # recursive call from the entry point to itself: ignore them and
        # just hope the annotations are correct
        if (bookkeeper.getdesc(graph)._cache.get(None, None) is
            bookkeeper.annotator.translator.graphs[0]):
            return variableoftype(RESULT)

        myorigin = bookkeeper.myorigin()
        myorigin.__class__ = CallOpOriginFlags     # thud
        fixed = myorigin.read_fixed()
        tsgraphs_accum = []
        hs_res = bookkeeper.graph_call(graph, fixed, args_hs,
                                       tsgraphs_accum)
        myorigin.any_called_graph = tsgraphs_accum[0]

        if isinstance(hs_res, SomeLLAbstractConstant):
            hs_res.myorigin = myorigin        

        # we need to make sure that hs_res does not become temporarily less
        # general as a result of calling another specialized version of the
        # function
        return annmodel.unionof(hs_res, bookkeeper.current_op_binding())
Exemple #20
0
    def _call_single_graph(hs_f1, graph, RESULT, *args_hs):
        bookkeeper = getbookkeeper()
        if not bookkeeper.annotator.policy.look_inside_graph(graph):
            return cannot_follow_call(bookkeeper, graph, args_hs, RESULT)

        # recursive call from the entry point to itself: ignore them and
        # just hope the annotations are correct
        if (bookkeeper.getdesc(graph)._cache.get(None, None) is
                bookkeeper.annotator.translator.graphs[0]):
            return variableoftype(RESULT)

        myorigin = bookkeeper.myorigin()
        myorigin.__class__ = CallOpOriginFlags  # thud
        fixed = myorigin.read_fixed()
        tsgraphs_accum = []
        hs_res = bookkeeper.graph_call(graph, fixed, args_hs, tsgraphs_accum)
        myorigin.any_called_graph = tsgraphs_accum[0]

        if isinstance(hs_res, SomeLLAbstractConstant):
            hs_res.myorigin = myorigin

        # we need to make sure that hs_res does not become temporarily less
        # general as a result of calling another specialized version of the
        # function
        return annmodel.unionof(hs_res, bookkeeper.current_op_binding())
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()])
Exemple #22
0
 def mergeinputargs(self, graph, block, inputcells, called_from_graph=None):
     # Merge the new 'cells' with each of the block's existing input
     # variables.
     oldcells = [self.binding(a) for a in block.inputargs]
     unions = [annmodel.unionof(c1,c2) for c1, c2 in zip(oldcells,inputcells)]
     # if the merged cells changed, we must redo the analysis
     if unions != oldcells:
         self.bindinputargs(graph, block, unions, called_from_graph)
Exemple #23
0
def unioncheck(*somevalues):
    s_value = unionof(*somevalues)
    if isdegenerated(s_value):
        if not getattr(TLS, 'no_side_effects_in_union', 0):
            bookkeeper = getbookkeeper()
            if bookkeeper is not None:
                bookkeeper.ondegenerated('union', s_value)
    return s_value
Exemple #24
0
 def generalize_key(self, s_key):
     new_key_type = model.unionof(self.key_type, s_key)
     updated = new_key_type != self.key_type
     if updated:
         self.key_type = new_key_type
         for position_key in self.key_read_locations:
             self.bookkeeper.annotator.reflowfromposition(position_key)
         self.emulate_rdict_calls()
Exemple #25
0
 def generalize_key(self, s_key):
     new_key_type = model.unionof(self.key_type, s_key)
     updated = new_key_type != self.key_type
     if updated:
         self.key_type = new_key_type
         for position_key in self.key_read_locations:
             self.bookkeeper.annotator.reflowfromposition(position_key)
         self.emulate_rdict_calls()
Exemple #26
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 #27
0
def unioncheck(*somevalues):
    s_value = unionof(*somevalues)
    if isdegenerated(s_value):
        if not getattr(TLS, 'no_side_effects_in_union', 0):
            bookkeeper = getbookkeeper()
            if bookkeeper is not None:
                bookkeeper.ondegenerated('union', s_value)
    return s_value
Exemple #28
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 #29
0
 def mergeinputargs(self, graph, block, inputcells, called_from_graph=None):
     # Merge the new 'cells' with each of the block's existing input
     # variables.
     oldcells = [self.binding(a) for a in block.inputargs]
     unions = [annmodel.unionof(c1,c2) for c1, c2 in zip(oldcells,inputcells)]
     # if the merged cells changed, we must redo the analysis
     if unions != oldcells:
         self.bindinputargs(graph, block, unions, called_from_graph)
Exemple #30
0
 def __call__(self, *args):
     args = args[1:]
     assert len(self.s_args) == len(args),\
         "Function %s expects %d arguments, got %d instead" % (self.name,
                                           len(self.s_args), len(args))
     for num, (arg, expected) in enumerate(zip(args, self.s_args)):
         res = unionof(arg, expected)
         assert expected.contains(res)
     return self.s_retval
Exemple #31
0
 def union((gencall, pbc)):
     for desc in pbc.descriptions:
         unique_key = desc
         bk = desc.bookkeeper
         s_result = bk.emulate_pbc_call(unique_key, pbc, gencall.args_s)
         s_result = unionof(s_result, gencall.s_result)
         assert gencall.s_result.contains(s_result)
     gencall.descriptions.update(pbc.descriptions)
     return gencall
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 __call__(self, *args):
     args = args[1:]
     assert len(self.s_args) == len(args),\
         "Function %s expects %d arguments, got %d instead" % (self.name,
                                           len(self.s_args), len(args))
     for num, (arg, expected) in enumerate(zip(args, self.s_args)):
         res = unionof(arg, expected)
         assert expected.contains(res)
     return self.s_retval
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 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 #36
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.makerepr(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 #37
0
 def compute_result_annotation(self, *args_s):
     if hasattr(self, 'ann_hook'):
         self.ann_hook()
     if self.signature_args is not None:
         assert len(args_s) == len(self.signature_args),\
                "Argument number mismatch"
         for arg, expected in zip(args_s, self.signature_args):
             arg = unionof(arg, expected)
             assert expected.contains(arg)
     return self.signature_result
Exemple #38
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)
        if isdegenerated(s_new_value):
            self.bookkeeper.ondegenerated("source %r attr %s" % (source, self.name), s_new_value)

        self.s_value = s_new_value
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.makerepr(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 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 #42
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)       
     if isdegenerated(s_new_value):            
         self.bookkeeper.ondegenerated("source %r attr %s" % (source, self.name),
                                       s_new_value)
             
     self.s_value = s_new_value
Exemple #43
0
    def merge(self, other, classdef='?'):
        assert self.name == other.name
        s_new_value = unionof(self.s_value, other.s_value)
        if isdegenerated(s_new_value):
            what = "%s attr %s" % (classdef, self.name)
            self.bookkeeper.ondegenerated(what, s_new_value)

        self.s_value = s_new_value
        if not other.readonly:
            self.modified(classdef)
        self.read_locations.update(other.read_locations)
Exemple #44
0
    def merge(self, other, classdef='?'):
        assert self.name == other.name
        s_new_value = unionof(self.s_value, other.s_value)
        if isdegenerated(s_new_value):
            what = "%s attr %s" % (classdef, self.name)
            self.bookkeeper.ondegenerated(what, s_new_value)

        self.s_value = s_new_value
        if not other.readonly:
            self.modified(classdef)
        self.read_locations.update(other.read_locations)
Exemple #45
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 #46
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 #47
0
    def merge(self, other):
        if self is not other:
            if getattr(TLS, 'no_side_effects_in_union', 0):
                raise UnionError("merging list/dict items")

            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
            if isdegenerated(s_new_value):
                if self.bookkeeper:
                    self.bookkeeper.ondegenerated(self, s_new_value)
                elif other.bookkeeper:
                    other.bookkeeper.ondegenerated(other, s_new_value)
            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 #48
0
    def merge(self, other):
        if self is not other:
            if getattr(TLS, 'no_side_effects_in_union', 0):
                raise UnionError("merging list/dict items")

            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
            if isdegenerated(s_new_value):
                if self.bookkeeper:
                    self.bookkeeper.ondegenerated(self, s_new_value)
                elif other.bookkeeper:
                    other.bookkeeper.ondegenerated(other, s_new_value)
            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 #49
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 #50
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 #51
0
 def generalize(self, s_other_value):
     s_new_value = unionof(self.s_value, s_other_value)
     if isdegenerated(s_new_value) and self.bookkeeper:
         self.bookkeeper.ondegenerated(self, s_new_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 #52
0
    def direct_call(hs_f1, *args_hs):
        bookkeeper = getbookkeeper()
        fnobj = hs_f1.const._obj
        if (bookkeeper.annotator.policy.oopspec and
            hasattr(fnobj._callable, 'oopspec')):
            # try to handle the call as a high-level operation
            try:
                return handle_highlevel_operation(bookkeeper, fnobj._callable,
                                                  *args_hs)
            except NotImplementedError:
                pass
        # don't try to annotate suggested_primitive graphs
        if getattr(getattr(fnobj, '_callable', None), 'suggested_primitive', False):
            return variableoftype(lltype.typeOf(fnobj).RESULT)

        # normal call
        if not hasattr(fnobj, 'graph'):
            raise NotImplementedError("XXX call to externals or primitives")
        if not bookkeeper.annotator.policy.look_inside_graph(fnobj.graph):
            return cannot_follow_call(bookkeeper, fnobj.graph, args_hs,
                                      lltype.typeOf(fnobj).RESULT)

        # recursive call from the entry point to itself: ignore them and
        # just hope the annotations are correct
        if (bookkeeper.getdesc(fnobj.graph)._cache.get(None, None) is
            bookkeeper.annotator.translator.graphs[0]):
            return variableoftype(lltype.typeOf(fnobj).RESULT)

        myorigin = bookkeeper.myorigin()
        myorigin.__class__ = CallOpOriginFlags     # thud
        fixed = myorigin.read_fixed()
        tsgraphs_accum = []
        hs_res = bookkeeper.graph_call(fnobj.graph, fixed, args_hs,
                                       tsgraphs_accum)
        myorigin.any_called_graph = tsgraphs_accum[0]

        if isinstance(hs_res, SomeLLAbstractConstant):
            hs_res.myorigin = myorigin

##        elif fnobj.graph.name.startswith('ll_stritem'):
##            if isinstance(hs_res, SomeLLAbstractVariable):
##                print hs_res
##                import pdb; pdb.set_trace()
        
            
        # we need to make sure that hs_res does not become temporarily less
        # general as a result of calling another specialized version of the
        # function
        return annmodel.unionof(hs_res, bookkeeper.current_op_binding())
Exemple #53
0
 def graph_family_call(self, graph_list, fixed, args_hs,
                       tsgraphs_accum=None, hs_callable=None):
     if tsgraphs_accum is None:
         tsgraphs = []
     else:
         tsgraphs = tsgraphs_accum
     results_hs = []
     for graph in graph_list:
         results_hs.append(self.graph_call(graph, fixed, args_hs,
                                           tsgraphs, hs_callable))
     # put the tsgraphs in the same call family
     call_families = self.tsgraph_maximal_call_families
     _, rep, callfamily = call_families.find(tsgraphs[0])
     for tsgraph in tsgraphs[1:]:
         _, rep, callfamily = call_families.union(rep, tsgraph)
     return annmodel.unionof(*results_hs)
Exemple #54
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)
     # Some specializations may break the invariant of returning
     # annotations that are always more general than the previous time.
     # We restore it here:
     from pypy.annotation.model import unionof
     result = unionof(result, s_previous_result)
     return result
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 = 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 addpendingblock(self, graph, block, cells, called_from_graph=None):
     """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(graph.getargs(), cells):
             s_oldarg = self.binding(a)
             assert annmodel.unionof(s_oldarg, s_newarg) == s_oldarg
     else:
         assert not self.frozen
         for a in cells:
             assert isinstance(a, annmodel.SomeObject)
         if block not in self.annotated:
             self.bindinputargs(graph, block, cells, called_from_graph)
         else:
             self.mergeinputargs(graph, block, cells, called_from_graph)
         if not self.annotated[block]:
             self.pendingblocks[block] = graph
Exemple #57
0
    def _call_multiple_graphs(hs_v1, graph_list, RESULT, *args_hs):
        if graph_list is None:
            # cannot follow indirect calls to unknown targets
            return variableoftype(RESULT)

        bookkeeper = getbookkeeper()
        myorigin = bookkeeper.myorigin()
        myorigin.__class__ = CallOpOriginFlags  # thud
        fixed = myorigin.read_fixed()
        tsgraphs_accum = []
        hs_res = bookkeeper.graph_family_call(graph_list, fixed, args_hs,
                                              tsgraphs_accum, hs_v1)
        myorigin.any_called_graph = tsgraphs_accum[0]

        if isinstance(hs_res, SomeLLAbstractConstant):
            hs_res.myorigin = myorigin

        # we need to make sure that hs_res does not become temporarily less
        # general as a result of calling another specialized version of the
        # function
        return annmodel.unionof(hs_res, bookkeeper.current_op_binding())
Exemple #58
0
def create_class_constructors(annotator):
    bk = annotator.bookkeeper
    call_families = bk.pbc_maximal_call_families

    for family in call_families.infos():
        if len(family.descs) <= 1:
            continue
        descs = family.descs.keys()
        if not isinstance(descs[0], description.ClassDesc):
            continue
        # Note that if classes are in the same callfamily, their __init__
        # attribute must be in the same attrfamily as well.
        change = descs[0].mergeattrfamilies(descs[1:], '__init__')
        if hasattr(descs[0].getuniqueclassdef(), 'my_instantiate_graph'):
            assert not change, "after the fact change to a family of classes" # minimal sanity check
            continue
        # Put __init__ into the attr family, for ClassesPBCRepr.call()
        attrfamily = descs[0].getattrfamily('__init__')
        inits_s = [desc.s_read_attribute('__init__') for desc in descs]
        s_value = annmodel.unionof(attrfamily.s_value, *inits_s)
        attrfamily.s_value = s_value
        # ClassesPBCRepr.call() will also need instantiate() support
        for desc in descs:
            bk.needs_generic_instantiate[desc.getuniqueclassdef()] = True